Merge "pbx: Update device and presence state when changing a hint extension."
authorJoshua Colp <jcolp@digium.com>
Tue, 22 Sep 2015 10:29:52 +0000 (05:29 -0500)
committerGerrit Code Review <gerrit2@gerrit.digium.api>
Tue, 22 Sep 2015 10:29:52 +0000 (05:29 -0500)
apps/app_queue.c
cdr/cdr_adaptive_odbc.c
cel/cel_odbc.c
cel/cel_pgsql.c
channels/chan_pjsip.c
channels/chan_sip.c
main/astfd.c
main/config_options.c
res/res_config_sqlite.c
res/res_pjsip_diversion.c

index bb3ec17..23f6985 100644 (file)
@@ -5582,6 +5582,10 @@ struct queue_stasis_data {
        struct local_optimization caller_optimize;
        /*! Local channel optimization details for the member */
        struct local_optimization member_optimize;
+       /*! Member channel */
+       struct ast_channel *member_channel;
+       /*! Caller channel */
+       struct ast_channel *caller_channel;
 };
 
 /*!
@@ -5599,6 +5603,9 @@ static void queue_stasis_data_destructor(void *obj)
        ao2_cleanup(queue_data->member);
        queue_unref(queue_data->queue);
        ast_string_field_free_memory(queue_data);
+
+       ao2_ref(queue_data->member_channel, -1);
+       ao2_ref(queue_data->caller_channel, -1);
 }
 
 /*!
@@ -5645,6 +5652,16 @@ static struct queue_stasis_data *queue_stasis_data_alloc(struct queue_ent *qe,
        queue_data->caller_pos = qe->opos;
        ao2_ref(mem, +1);
        queue_data->member = mem;
+
+       /*
+        * During transfers it's possible for both the member and/or caller
+        * channel(s) to not be available. Adding a reference here ensures
+        * that the channels remain until app_queue is completely done with
+        * them.
+        */
+       queue_data->member_channel = ao2_bump(peer);
+       queue_data->caller_channel = ao2_bump(qe->chan);
+
        return queue_data;
 }
 
@@ -6016,7 +6033,9 @@ static void handle_hangup(void *userdata, struct stasis_subscription *sub,
        }
 
        chan = ast_channel_get_by_name(channel_blob->snapshot->name);
-       if (chan && ast_channel_has_role(chan, AST_TRANSFERER_ROLE_NAME)) {
+       if (chan && (ast_channel_has_role(chan, AST_TRANSFERER_ROLE_NAME) ||
+                    !ast_strlen_zero(pbx_builtin_getvar_helper(chan, "ATTENDEDTRANSFER")) ||
+                    !ast_strlen_zero(pbx_builtin_getvar_helper(chan, "BLINDTRANSFER")))) {
                /* Channel that is hanging up is doing it as part of a transfer.
                 * We'll get a transfer event later
                 */
index 8bd9d0d..0da8c01 100644 (file)
@@ -358,11 +358,11 @@ static SQLHSTMT generic_prepare(struct odbc_obj *obj, void *data)
        return stmt;
 }
 
-#define LENGTHEN_BUF1(size)                                                                                                            \
+#define LENGTHEN_BUF(size, var_sql)                                                                                                            \
                        do {                                                                                                                            \
                                /* Lengthen buffer, if necessary */                                                             \
-                               if (ast_str_strlen(sql) + size + 1 > ast_str_size(sql)) {               \
-                                       if (ast_str_make_space(&sql, ((ast_str_size(sql) + size + 1) / 512 + 1) * 512) != 0) { \
+                               if (ast_str_strlen(var_sql) + size + 1 > ast_str_size(var_sql)) {               \
+                                       if (ast_str_make_space(&var_sql, ((ast_str_size(var_sql) + size + 1) / 512 + 1) * 512) != 0) { \
                                                ast_log(LOG_ERROR, "Unable to allocate sufficient memory.  Insert CDR '%s:%s' failed.\n", tableptr->connection, tableptr->table); \
                                                ast_free(sql);                                                                                  \
                                                ast_free(sql2);                                                                                 \
@@ -372,18 +372,10 @@ static SQLHSTMT generic_prepare(struct odbc_obj *obj, void *data)
                                }                                                                                                                               \
                        } while (0)
 
-#define LENGTHEN_BUF2(size)                                                                                                            \
-                       do {                                                                                                                            \
-                               if (ast_str_strlen(sql2) + size + 1 > ast_str_size(sql2)) {             \
-                                       if (ast_str_make_space(&sql2, ((ast_str_size(sql2) + size + 3) / 512 + 1) * 512) != 0) { \
-                                               ast_log(LOG_ERROR, "Unable to allocate sufficient memory.  Insert CDR '%s:%s' failed.\n", tableptr->connection, tableptr->table); \
-                                               ast_free(sql);                                                                                  \
-                                               ast_free(sql2);                                                                                 \
-                                               AST_RWLIST_UNLOCK(&odbc_tables);                                                \
-                                               return -1;                                                                                              \
-                                       }                                                                                                                       \
-                               }                                                                                                                               \
-                       } while (0)
+#define LENGTHEN_BUF1(size)    \
+       LENGTHEN_BUF(size, sql);
+#define LENGTHEN_BUF2(size)    \
+       LENGTHEN_BUF(size, sql2);
 
 static int odbc_log(struct ast_cdr *cdr)
 {
index 2d8408b..3c0be04 100644 (file)
@@ -341,11 +341,11 @@ static SQLHSTMT generic_prepare(struct odbc_obj *obj, void *data)
        return stmt;
 }
 
-#define LENGTHEN_BUF1(size)                                                                                                            \
+#define LENGTHEN_BUF(size, var_sql)                                                                                                            \
                        do {                                                                                                                            \
                                /* Lengthen buffer, if necessary */                                                             \
-                               if (ast_str_strlen(sql) + size + 1 > ast_str_size(sql)) {               \
-                                       if (ast_str_make_space(&sql, ((ast_str_size(sql) + size + 1) / 512 + 1) * 512) != 0) { \
+                               if (ast_str_strlen(var_sql) + size + 1 > ast_str_size(var_sql)) {               \
+                                       if (ast_str_make_space(&var_sql, ((ast_str_size(var_sql) + size + 1) / 512 + 1) * 512) != 0) { \
                                                ast_log(LOG_ERROR, "Unable to allocate sufficient memory.  Insert CEL '%s:%s' failed.\n", tableptr->connection, tableptr->table); \
                                                ast_free(sql);                                                                                  \
                                                ast_free(sql2);                                                                                 \
@@ -355,18 +355,11 @@ static SQLHSTMT generic_prepare(struct odbc_obj *obj, void *data)
                                }                                                                                                                               \
                        } while (0)
 
-#define LENGTHEN_BUF2(size)                                                                                                            \
-                       do {                                                                                                                            \
-                               if (ast_str_strlen(sql2) + size + 1 > ast_str_size(sql2)) {             \
-                                       if (ast_str_make_space(&sql2, ((ast_str_size(sql2) + size + 3) / 512 + 1) * 512) != 0) { \
-                                               ast_log(LOG_ERROR, "Unable to allocate sufficient memory.  Insert CEL '%s:%s' failed.\n", tableptr->connection, tableptr->table); \
-                                               ast_free(sql);                                                                                  \
-                                               ast_free(sql2);                                                                                 \
-                                               AST_RWLIST_UNLOCK(&odbc_tables);                                                \
-                                               return;                                                                                                 \
-                                       }                                                                                                                       \
-                               }                                                                                                                               \
-                       } while (0)
+#define LENGTHEN_BUF1(size) \
+       LENGTHEN_BUF(size, sql);
+
+#define LENGTHEN_BUF2(size) \
+       LENGTHEN_BUF(size, sql2);
 
 static void odbc_log(struct ast_event *event)
 {
index f495947..e4e280e 100644 (file)
@@ -100,11 +100,11 @@ struct columns {
 
 static AST_RWLIST_HEAD_STATIC(psql_columns, columns);
 
-#define LENGTHEN_BUF1(size) \
+#define LENGTHEN_BUF(size, var_sql) \
        do { \
                /* Lengthen buffer, if necessary */ \
-               if (ast_str_strlen(sql) + size + 1 > ast_str_size(sql)) { \
-                       if (ast_str_make_space(&sql, ((ast_str_size(sql) + size + 3) / 512 + 1) * 512) != 0) { \
+               if (ast_str_strlen(var_sql) + size + 1 > ast_str_size(var_sql)) { \
+                       if (ast_str_make_space(&var_sql, ((ast_str_size(var_sql) + size + 3) / 512 + 1) * 512) != 0) { \
                                ast_log(LOG_ERROR, "Unable to allocate sufficient memory.  Insert CEL '%s:%s' failed.\n", pghostname, table); \
                                ast_free(sql); \
                                ast_free(sql2); \
@@ -114,18 +114,10 @@ static AST_RWLIST_HEAD_STATIC(psql_columns, columns);
                } \
        } while (0)
 
+#define LENGTHEN_BUF1(size) \
+       LENGTHEN_BUF(size, sql);
 #define LENGTHEN_BUF2(size) \
-       do { \
-               if (ast_str_strlen(sql2) + size + 1 > ast_str_size(sql2)) { \
-                       if (ast_str_make_space(&sql2, ((ast_str_size(sql2) + size + 3) / 512 + 1) * 512) != 0) { \
-                               ast_log(LOG_ERROR, "Unable to allocate sufficient memory.  Insert CEL '%s:%s' failed.\n", pghostname, table); \
-                               ast_free(sql); \
-                               ast_free(sql2); \
-                               AST_RWLIST_UNLOCK(&psql_columns); \
-                               return; \
-                       } \
-               } \
-       } while (0)
+       LENGTHEN_BUF(size, sql2);
 
 static void pgsql_reconnect(void)
 {
index 9603f05..153b2a3 100644 (file)
@@ -160,10 +160,10 @@ static struct ast_sip_session_supplement chan_pjsip_ack_supplement = {
 static enum ast_rtp_glue_result chan_pjsip_get_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance **instance)
 {
        struct ast_sip_channel_pvt *channel = ast_channel_tech_pvt(chan);
-       struct chan_pjsip_pvt *pvt = channel->pvt;
+       struct chan_pjsip_pvt *pvt;
        struct ast_sip_endpoint *endpoint;
 
-       if (!pvt || !channel->session || !pvt->media[SIP_MEDIA_AUDIO]->rtp) {
+       if (!channel || !channel->session || !(pvt = channel->pvt) || !pvt->media[SIP_MEDIA_AUDIO]->rtp) {
                return AST_RTP_GLUE_RESULT_FORBID;
        }
 
index f96a80f..8d5af2f 100644 (file)
@@ -13940,6 +13940,7 @@ static void initreqprep(struct sip_request *req, struct sip_pvt *p, int sipmetho
        int cid_has_name = 1;
        int cid_has_num = 1;
        struct ast_party_id connected_id;
+       int ret;
 
        if (ast_test_flag(&p->flags[0], SIP_USEREQPHONE)) {
                const char *s = p->username;    /* being a string field, cannot be NULL */
@@ -14024,26 +14025,41 @@ static void initreqprep(struct sip_request *req, struct sip_pvt *p, int sipmetho
 
        ast_copy_string(tmp_l, l, sizeof(tmp_l));
        if (sip_cfg.pedanticsipchecking) {
-               ast_escape_quoted(n, tmp_n, sizeof(tmp_n));
-               n = tmp_n;
                ast_uri_encode(l, tmp_l, sizeof(tmp_l), ast_uri_sip_user);
        }
 
        ourport = (p->fromdomainport && (p->fromdomainport != STANDARD_SIP_PORT)) ? p->fromdomainport : ast_sockaddr_port(&p->ourip);
 
-       /* If a caller id name was specified, add a display name. */
-       if (cid_has_name || !cid_has_num) {
-               snprintf(from, sizeof(from), "\"%s\" ", n);
+       if (!sip_standard_port(p->socket.type, ourport)) {
+               ret = snprintf(from, sizeof(from), "<sip:%s@%s:%d>;tag=%s", tmp_l, d, ourport, p->tag);
        } else {
-               from[0] = '\0';
+               ret = snprintf(from, sizeof(from), "<sip:%s@%s>;tag=%s", tmp_l, d, p->tag);
+       }
+       if (ret < 0 || ret >= sizeof(from)) { /* a return value of size or more means that the output was truncated */
+               /* We don't have an escape path from here... */
+               ast_log(LOG_ERROR, "The From header was truncated in call '%s'. This call setup will fail.\n", p->callid);
        }
 
-       if (!sip_standard_port(p->socket.type, ourport)) {
-               size_t offset = strlen(from);
-               snprintf(&from[offset], sizeof(from) - offset, "<sip:%s@%s:%d>;tag=%s", tmp_l, d, ourport, p->tag);
-       } else {
-               size_t offset = strlen(from);
-               snprintf(&from[offset], sizeof(from) - offset, "<sip:%s@%s>;tag=%s", tmp_l, d, p->tag);
+       /* If a caller id name was specified, prefix a display name, if there is enough room. */
+       if (cid_has_name || !cid_has_num) {
+               size_t written = strlen(from);
+               ssize_t left = sizeof(from) - written - 4; /* '"" \0' */
+               if (left > 0) {
+                       size_t name_len;
+                       if (sip_cfg.pedanticsipchecking) {
+                               ast_escape_quoted(n, tmp_n, MIN(left + 1, sizeof(tmp_n)));
+                               n = tmp_n;
+                       }
+                       name_len = strlen(n);
+                       if (left < name_len) {
+                               name_len = left;
+                       }
+                       memmove(from + name_len + 3, from, written + 1);
+                       from[0] = '"';
+                       memcpy(from + 1, n, name_len);
+                       from[name_len + 1] = '"';
+                       from[name_len + 2] = ' ';
+               }
        }
 
        if (!ast_strlen_zero(explicit_uri)) {
@@ -14085,21 +14101,25 @@ static void initreqprep(struct sip_request *req, struct sip_pvt *p, int sipmetho
                /*! \todo Need to add back the VXML URL here at some point, possibly use build_string for all this junk */
                if (!strchr(p->todnid, '@')) {
                        /* We have no domain in the dnid */
-                       snprintf(to, sizeof(to), "<sip:%s@%s>%s%s", p->todnid, p->tohost, ast_strlen_zero(p->theirtag) ? "" : ";tag=", p->theirtag);
+                       ret = snprintf(to, sizeof(to), "<sip:%s@%s>%s%s", p->todnid, p->tohost, ast_strlen_zero(p->theirtag) ? "" : ";tag=", p->theirtag);
                } else {
-                       snprintf(to, sizeof(to), "<sip:%s>%s%s", p->todnid, ast_strlen_zero(p->theirtag) ? "" : ";tag=", p->theirtag);
+                       ret = snprintf(to, sizeof(to), "<sip:%s>%s%s", p->todnid, ast_strlen_zero(p->theirtag) ? "" : ";tag=", p->theirtag);
                }
        } else {
                if (sipmethod == SIP_NOTIFY && !ast_strlen_zero(p->theirtag)) {
                        /* If this is a NOTIFY, use the From: tag in the subscribe (RFC 3265) */
-                       snprintf(to, sizeof(to), "<%s%s>;tag=%s", (strncasecmp(p->uri, "sip:", 4) ? "sip:" : ""), p->uri, p->theirtag);
+                       ret = snprintf(to, sizeof(to), "<%s%s>;tag=%s", (strncasecmp(p->uri, "sip:", 4) ? "sip:" : ""), p->uri, p->theirtag);
                } else if (p->options && p->options->vxml_url) {
                        /* If there is a VXML URL append it to the SIP URL */
-                       snprintf(to, sizeof(to), "<%s>;%s", p->uri, p->options->vxml_url);
+                       ret = snprintf(to, sizeof(to), "<%s>;%s", p->uri, p->options->vxml_url);
                } else {
-                       snprintf(to, sizeof(to), "<%s>", p->uri);
+                       ret = snprintf(to, sizeof(to), "<%s>", p->uri);
                }
        }
+       if (ret < 0 || ret >= sizeof(to)) { /* a return value of size or more means that the output was truncated */
+               /* We don't have an escape path from here... */
+               ast_log(LOG_ERROR, "The To header was truncated in call '%s'. This call setup will fail.\n", p->callid);
+       }
 
        init_req(req, sipmethod, p->uri);
        /* now tmp_n is available so reuse it to build the CSeq */
index 7467376..d1879f0 100644 (file)
@@ -46,6 +46,8 @@ ASTERISK_REGISTER_FILE()
 #include "asterisk/lock.h"
 #include "asterisk/strings.h"
 #include "asterisk/unaligned.h"
+#include "asterisk/localtime.h"
+#include "asterisk/time.h"
 
 static struct fdleaks {
        const char *callname;
@@ -54,6 +56,7 @@ static struct fdleaks {
        char file[40];
        char function[25];
        char callargs[60];
+       struct timeval now;
 } fdleaks[1024] = { { "", }, };
 
 /* COPY does ast_copy_string(dst, src, sizeof(dst)), except:
@@ -79,6 +82,7 @@ static struct fdleaks {
 #define STORE_COMMON(offset, name, ...)     \
        do { \
                struct fdleaks *tmp = &fdleaks[offset]; \
+               tmp->now = ast_tvnow(); \
                COPY(tmp->file, file);      \
                tmp->line = line;           \
                COPY(tmp->function, func);  \
@@ -271,7 +275,7 @@ static char *handle_show_fd(struct ast_cli_entry *e, int cmd, struct ast_cli_arg
        case CLI_GENERATE:
                return NULL;
        }
-       getrlimit(RLIMIT_FSIZE, &rl);
+       getrlimit(RLIMIT_NOFILE, &rl);
        if (rl.rlim_cur == RLIM_INFINITY || rl.rlim_max == RLIM_INFINITY) {
                ast_copy_string(line, "unlimited", sizeof(line));
        } else {
@@ -280,8 +284,13 @@ static char *handle_show_fd(struct ast_cli_entry *e, int cmd, struct ast_cli_arg
        ast_cli(a->fd, "Current maxfiles: %s\n", line);
        for (i = 0; i < ARRAY_LEN(fdleaks); i++) {
                if (fdleaks[i].isopen) {
+                       struct ast_tm tm = {0};
+                       char datestring[256];
+
+                       ast_localtime(&fdleaks[i].now, &tm, NULL);
+                       ast_strftime(datestring, sizeof(datestring), "%F %T", &tm);
                        snprintf(line, sizeof(line), "%d", fdleaks[i].line);
-                       ast_cli(a->fd, "%5d %15s:%-7.7s (%-25s): %s(%s)\n", i, fdleaks[i].file, line, fdleaks[i].function, fdleaks[i].callname, fdleaks[i].callargs);
+                       ast_cli(a->fd, "%5d [%s] %22s:%-7.7s (%-25s): %s(%s)\n", i, datestring, fdleaks[i].file, line, fdleaks[i].function, fdleaks[i].callname, fdleaks[i].callargs);
                }
        }
        return CLI_SUCCESS;
index a1ba5d2..4ab7a5b 100644 (file)
@@ -837,6 +837,10 @@ int aco_set_defaults(struct aco_type *type, const char *category, void *obj)
        struct aco_option *opt;
        struct ao2_iterator iter;
 
+       if (!type->internal) {
+               return -1;
+       }
+
        iter = ao2_iterator_init(type->internal->opts, 0);
 
        while ((opt = ao2_iterator_next(&iter))) {
index 5659b4e..4375c39 100644 (file)
@@ -781,8 +781,16 @@ static int cdr_handler(struct ast_cdr *cdr)
        struct ast_str *sql1 = ast_str_create(160), *sql2 = ast_str_create(16);
        int first = 1;
 
+       if (!sql1 || !sql2) {
+               ast_free(sql1);
+               ast_free(sql2);
+               return -1;
+       }
+
        if (!tbl) {
                ast_log(LOG_WARNING, "No such table: %s\n", cdr_table);
+               ast_free(sql1);
+               ast_free(sql2);
                return -1;
        }
 
index 3dfae45..ea2c7cd 100644 (file)
@@ -117,7 +117,9 @@ static void set_redirecting_value(char **dst, const pj_str_t *src)
 {
        ast_free(*dst);
        *dst = ast_malloc(pj_strlen(src) + 1);
-       ast_copy_pj_str(*dst, src, pj_strlen(src) + 1);
+       if (*dst) {
+               ast_copy_pj_str(*dst, src, pj_strlen(src) + 1);
+       }
 }
 
 static void set_redirecting_id(pjsip_name_addr *name_addr, struct ast_party_id *data,