chan_vpb: Fix a gcc 7 out-of-bounds complaint
[asterisk/asterisk.git] / addons / chan_mobile.c
index 197974a..8f04af7 100644 (file)
@@ -42,8 +42,6 @@
 
 #include "asterisk.h"
 
-ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
-
 #include <pthread.h>
 #include <signal.h>
 
@@ -73,16 +71,16 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/app.h"
 #include "asterisk/manager.h"
 #include "asterisk/io.h"
+#include "asterisk/smoother.h"
+#include "asterisk/format_cache.h"
 
 #define MBL_CONFIG "chan_mobile.conf"
 #define MBL_CONFIG_OLD "mobile.conf"
 
 #define DEVICE_FRAME_SIZE 48
-#define DEVICE_FRAME_FORMAT AST_FORMAT_SLINEAR
+#define DEVICE_FRAME_FORMAT ast_format_slin
 #define CHANNEL_FRAME_SIZE 320
 
-static struct ast_format prefformat;
-
 static int discovery_interval = 60;                    /* The device discovery interval, default 60 seconds. */
 static pthread_t discovery_thread = AST_PTHREADT_NULL; /* The discovery thread */
 static sdp_session_t *sdp_session;
@@ -209,9 +207,9 @@ static char *mblsendsms_desc =
 "  Message - text of the message\n";
 
 static struct ast_channel *mbl_new(int state, struct mbl_pvt *pvt, char *cid_num,
-               const struct ast_channel *requestor);
+               const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor);
 static struct ast_channel *mbl_request(const char *type, struct ast_format_cap *cap,
-               const struct ast_channel *requestor, const char *data, int *cause);
+               const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, const char *data, int *cause);
 static int mbl_call(struct ast_channel *ast, const char *dest, int timeout);
 static int mbl_hangup(struct ast_channel *ast);
 static int mbl_answer(struct ast_channel *ast);
@@ -838,9 +836,8 @@ e_return:
 */
 
 static struct ast_channel *mbl_new(int state, struct mbl_pvt *pvt, char *cid_num,
-               const struct ast_channel *requestor)
+               const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor)
 {
-
        struct ast_channel *chn;
 
        pvt->answered = 0;
@@ -855,18 +852,18 @@ static struct ast_channel *mbl_new(int state, struct mbl_pvt *pvt, char *cid_num
        ast_dsp_digitreset(pvt->dsp);
 
        chn = ast_channel_alloc(1, state, cid_num, pvt->id, 0, 0, pvt->context,
-                       requestor ? ast_channel_linkedid(requestor) : "", 0,
+                       assignedids, requestor, 0,
                        "Mobile/%s-%04lx", pvt->id, ast_random() & 0xffff);
        if (!chn) {
                goto e_return;
        }
 
        ast_channel_tech_set(chn, &mbl_tech);
-       ast_format_cap_add(ast_channel_nativeformats(chn), &prefformat);
-       ast_format_copy(ast_channel_rawreadformat(chn), &prefformat);
-       ast_format_copy(ast_channel_rawwriteformat(chn), &prefformat);
-       ast_format_copy(ast_channel_writeformat(chn), &prefformat);
-       ast_format_copy(ast_channel_readformat(chn), &prefformat);
+       ast_channel_nativeformats_set(chn, mbl_tech.capabilities);
+       ast_channel_set_rawreadformat(chn, DEVICE_FRAME_FORMAT);
+       ast_channel_set_rawwriteformat(chn, DEVICE_FRAME_FORMAT);
+       ast_channel_set_writeformat(chn, DEVICE_FRAME_FORMAT);
+       ast_channel_set_readformat(chn, DEVICE_FRAME_FORMAT);
        ast_channel_tech_pvt_set(chn, pvt);
 
        if (state == AST_STATE_RING)
@@ -887,7 +884,7 @@ e_return:
 }
 
 static struct ast_channel *mbl_request(const char *type, struct ast_format_cap *cap,
-               const struct ast_channel *requestor, const char *data, int *cause)
+               const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, const char *data, int *cause)
 {
 
        struct ast_channel *chn = NULL;
@@ -902,9 +899,9 @@ static struct ast_channel *mbl_request(const char *type, struct ast_format_cap *
                return NULL;
        }
 
-       if (!(ast_format_cap_iscompatible(cap, &prefformat))) {
-               char tmp[256];
-               ast_log(LOG_WARNING, "Asked to get a channel of unsupported format '%s'\n", ast_getformatname_multiple(tmp, sizeof(tmp), cap));
+       if (ast_format_cap_iscompatible_format(cap, DEVICE_FRAME_FORMAT) == AST_FORMAT_CMP_NOT_EQUAL) {
+               struct ast_str *codec_buf = ast_str_alloca(AST_FORMAT_CAP_NAMES_LEN);
+               ast_log(LOG_WARNING, "Asked to get a channel of unsupported format '%s'\n", ast_format_cap_get_names(cap, &codec_buf));
                *cause = AST_CAUSE_FACILITY_NOT_IMPLEMENTED;
                return NULL;
        }
@@ -946,7 +943,7 @@ static struct ast_channel *mbl_request(const char *type, struct ast_format_cap *
        }
 
        ast_mutex_lock(&pvt->lock);
-       chn = mbl_new(AST_STATE_DOWN, pvt, NULL, requestor);
+       chn = mbl_new(AST_STATE_DOWN, pvt, NULL, assignedids, requestor);
        ast_mutex_unlock(&pvt->lock);
        if (!chn) {
                ast_log(LOG_WARNING, "Unable to allocate channel structure.\n");
@@ -1116,7 +1113,7 @@ static struct ast_frame *mbl_read(struct ast_channel *ast)
 
        memset(&pvt->fr, 0x00, sizeof(struct ast_frame));
        pvt->fr.frametype = AST_FRAME_VOICE;
-       ast_format_set(&pvt->fr.subclass.format, DEVICE_FRAME_FORMAT, 0);
+       pvt->fr.subclass.format = DEVICE_FRAME_FORMAT;
        pvt->fr.src = "Mobile";
        pvt->fr.offset = AST_FRIENDLY_OFFSET;
        pvt->fr.mallocd = 0;
@@ -3591,7 +3588,7 @@ static int handle_response_clip(struct mbl_pvt *pvt, char *buf)
                        ast_debug(1, "[%s] error parsing CLIP: %s\n", pvt->id, buf);
                }
 
-               if (!(chan = mbl_new(AST_STATE_RING, pvt, clip, NULL))) {
+               if (!(chan = mbl_new(AST_STATE_RING, pvt, clip, NULL, NULL))) {
                        ast_log(LOG_ERROR, "[%s] unable to allocate channel for incoming call\n", pvt->id);
                        hfp_send_chup(pvt->hfp);
                        msg_queue_push(pvt, AT_OK, AT_CHUP);
@@ -3681,7 +3678,7 @@ static int handle_response_cmgr(struct mbl_pvt *pvt, char *buf)
                pvt->incoming_sms = 0;
 
                /* XXX this channel probably does not need to be associated with this pvt */
-               if (!(chan = mbl_new(AST_STATE_DOWN, pvt, NULL, NULL))) {
+               if (!(chan = mbl_new(AST_STATE_DOWN, pvt, NULL, NULL, NULL))) {
                        ast_debug(1, "[%s] error creating sms message channel, disconnecting\n", pvt->id);
                        return -1;
                }
@@ -3802,7 +3799,7 @@ static void *do_monitor_phone(void *data)
 {
        struct mbl_pvt *pvt = (struct mbl_pvt *)data;
        struct hfp_pvt *hfp = pvt->hfp;
-       char buf[256];
+       char buf[350];
        int t;
        at_message_t at_msg;
        struct msg_queue_entry *entry;
@@ -3856,10 +3853,7 @@ static void *do_monitor_phone(void *data)
                }
 
                if ((at_msg = at_read_full(hfp->rsock, buf, sizeof(buf))) < 0) {
-                       /* XXX gnu specific strerror_r is assummed here, this
-                        * is not really safe.  See the strerror(3) man page
-                        * for more info. */
-                       ast_debug(1, "[%s] error reading from device: %s (%d)\n", pvt->id, strerror_r(errno, buf, sizeof(buf)), errno);
+                       ast_debug(1, "[%s] error reading from device: %s (%d)\n", pvt->id, strerror(errno), errno);
                        break;
                }
 
@@ -3996,7 +3990,7 @@ static void *do_monitor_phone(void *data)
                        ast_debug(1, "[%s] error parsing message\n", pvt->id);
                        goto e_cleanup;
                case AT_READ_ERROR:
-                       ast_debug(1, "[%s] error reading from device: %s (%d)\n", pvt->id, strerror_r(errno, buf, sizeof(buf)), errno);
+                       ast_debug(1, "[%s] error reading from device: %s (%d)\n", pvt->id, strerror(errno), errno);
                        goto e_cleanup;
                default:
                        break;
@@ -4074,11 +4068,7 @@ static void *do_monitor_headset(void *data)
                        continue;
 
                if ((at_msg = at_read_full(pvt->rfcomm_socket, buf, sizeof(buf))) < 0) {
-                       if (strerror_r(errno, buf, sizeof(buf)))
-                               ast_debug(1, "[%s] error reading from device\n", pvt->id);
-                       else
-                               ast_debug(1, "[%s] error reading from device: %s (%d)\n", pvt->id, buf, errno);
-
+                       ast_debug(1, "[%s] error reading from device: %s (%d)\n", pvt->id, strerror(errno), errno);
                        goto e_cleanup;
                }
                ast_debug(1, "[%s] %s\n", pvt->id, buf);
@@ -4140,7 +4130,7 @@ static void *do_monitor_headset(void *data)
 
                                pvt->incoming = 1;
 
-                               if (!(chan = mbl_new(AST_STATE_UP, pvt, NULL, NULL))) {
+                               if (!(chan = mbl_new(AST_STATE_UP, pvt, NULL, NULL, NULL))) {
                                        ast_log(LOG_ERROR, "[%s] unable to allocate channel for incoming call\n", pvt->id);
                                        ast_mutex_unlock(&pvt->lock);
                                        goto e_cleanup;
@@ -4697,7 +4687,8 @@ static int unload_module(void)
        if (sdp_session)
                sdp_close(sdp_session);
 
-       mbl_tech.capabilities = ast_format_cap_destroy(mbl_tech.capabilities);
+       ao2_ref(mbl_tech.capabilities, -1);
+       mbl_tech.capabilities = NULL;
        return 0;
 }
 
@@ -4706,16 +4697,20 @@ static int load_module(void)
 
        int dev_id, s;
 
-       if (!(mbl_tech.capabilities = ast_format_cap_alloc(0))) {
+       if (!(mbl_tech.capabilities = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
                return AST_MODULE_LOAD_DECLINE;
        }
-       ast_format_set(&prefformat, DEVICE_FRAME_FORMAT, 0);
-       ast_format_cap_add(mbl_tech.capabilities, &prefformat);
+
+       ast_format_cap_append(mbl_tech.capabilities, DEVICE_FRAME_FORMAT, 0);
        /* Check if we have Bluetooth, no point loading otherwise... */
        dev_id = hci_get_route(NULL);
+
        s = hci_open_dev(dev_id);
        if (dev_id < 0 || s < 0) {
                ast_log(LOG_ERROR, "No Bluetooth devices found. Not loading module.\n");
+               ao2_ref(mbl_tech.capabilities, -1);
+               mbl_tech.capabilities = NULL;
+               hci_close_dev(s);
                return AST_MODULE_LOAD_DECLINE;
        }
 
@@ -4723,6 +4718,8 @@ static int load_module(void)
 
        if (mbl_load_config()) {
                ast_log(LOG_ERROR, "Errors reading config file %s. Not loading module.\n", MBL_CONFIG);
+               ao2_ref(mbl_tech.capabilities, -1);
+               mbl_tech.capabilities = NULL;
                return AST_MODULE_LOAD_DECLINE;
        }
 
@@ -4747,14 +4744,14 @@ static int load_module(void)
        return AST_MODULE_LOAD_SUCCESS;
 
 e_cleanup:
-       if (sdp_session)
-               sdp_close(sdp_session);
+       unload_module();
 
-       return AST_MODULE_LOAD_FAILURE;
+       return AST_MODULE_LOAD_DECLINE;
 }
 
 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "Bluetooth Mobile Device Channel Driver",
-               .load = load_module,
-               .unload = unload_module,
-               .load_pri = AST_MODPRI_CHANNEL_DRIVER,
+       .support_level = AST_MODULE_SUPPORT_EXTENDED,
+       .load = load_module,
+       .unload = unload_module,
+       .load_pri = AST_MODPRI_CHANNEL_DRIVER,
 );