diff options
-rw-r--r-- | channels/chan_pjsip.c | 5 | ||||
-rw-r--r-- | channels/chan_sip.c | 17 | ||||
-rw-r--r-- | channels/pjsip/dialplan_functions.c | 50 | ||||
-rw-r--r-- | include/asterisk/res_pjsip_session.h | 2 | ||||
-rw-r--r-- | main/asterisk.c | 38 | ||||
-rw-r--r-- | res/res_pjsip/config_transport.c | 10 | ||||
-rw-r--r-- | res/res_pjsip/pjsip_options.c | 53 | ||||
-rw-r--r-- | res/res_pjsip_session.c | 6 | ||||
-rw-r--r-- | res/res_rtp_asterisk.c | 8 |
9 files changed, 127 insertions, 62 deletions
diff --git a/channels/chan_pjsip.c b/channels/chan_pjsip.c index e4e8fa586..69bcc187f 100644 --- a/channels/chan_pjsip.c +++ b/channels/chan_pjsip.c @@ -605,6 +605,11 @@ static struct ast_channel *chan_pjsip_new(struct ast_sip_session *session, int s ast_party_id_copy(&ast_channel_caller(chan)->id, &session->id); ast_party_id_copy(&ast_channel_caller(chan)->ani, &session->id); + if (!ast_strlen_zero(exten)) { + /* Set provided DNID on the new channel. */ + ast_channel_dialed(chan)->number.str = ast_strdup(exten); + } + ast_channel_priority_set(chan, 1); ast_channel_callgroup_set(chan, session->endpoint->pickup.callgroup); diff --git a/channels/chan_sip.c b/channels/chan_sip.c index a6e5493c2..4bae39da0 100644 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -30125,6 +30125,7 @@ static int sip_send_keepalive(const void *data) struct sip_peer *peer = (struct sip_peer*) data; int res = 0; const char keepalive[] = "\r\n"; + size_t count = sizeof(keepalive) - 1; peer->keepalivesend = -1; @@ -30135,12 +30136,12 @@ static int sip_send_keepalive(const void *data) /* Send the packet out using the proper method for this peer */ if ((peer->socket.fd != -1) && (peer->socket.type == AST_TRANSPORT_UDP)) { - res = ast_sendto(peer->socket.fd, keepalive, sizeof(keepalive), 0, &peer->addr); + res = ast_sendto(peer->socket.fd, keepalive, count, 0, &peer->addr); } else if ((peer->socket.type & (AST_TRANSPORT_TCP | AST_TRANSPORT_TLS)) && peer->socket.tcptls_session) { - res = sip_tcptls_write(peer->socket.tcptls_session, keepalive, sizeof(keepalive)); + res = sip_tcptls_write(peer->socket.tcptls_session, keepalive, count); } else if (peer->socket.type == AST_TRANSPORT_UDP) { - res = ast_sendto(sipsock, keepalive, sizeof(keepalive), 0, &peer->addr); + res = ast_sendto(sipsock, keepalive, count, 0, &peer->addr); } if (res == -1) { @@ -30154,7 +30155,7 @@ static int sip_send_keepalive(const void *data) } } - if (res != sizeof(keepalive)) { + if (res != count) { ast_log(LOG_WARNING, "sip_send_keepalive to %s returned %d: %s\n", ast_sockaddr_stringify(&peer->addr), res, strerror(errno)); } @@ -30554,6 +30555,14 @@ static struct ast_channel *sip_request_call(const char *type, struct ast_format_ } } + /* If stripping the DNID left us with nothing, bail out */ + if (ast_strlen_zero(tmp)) { + dialog_unlink_all(p); + dialog_unref(p, "unref dialog p from bad destination"); + *cause = AST_CAUSE_DESTINATION_OUT_OF_ORDER; + return NULL; + } + /* Divvy up the items separated by slashes */ AST_NONSTANDARD_APP_ARGS(args, tmp, '/'); diff --git a/channels/pjsip/dialplan_functions.c b/channels/pjsip/dialplan_functions.c index 861edf72d..aa376f892 100644 --- a/channels/pjsip/dialplan_functions.c +++ b/channels/pjsip/dialplan_functions.c @@ -388,7 +388,7 @@ </enumlist> </enum> <enum name="target_uri"> - <para>The request URI of the <literal>INVITE</literal> request associated with the creation of this channel.</para> + <para>The contact URI where requests are sent.</para> </enum> <enum name="local_uri"> <para>The local URI.</para> @@ -402,6 +402,10 @@ <enum name="remote_tag"> <para>Tag in To header</para> </enum> + <enum name="request_uri"> + <para>The request URI of the incoming <literal>INVITE</literal> + associated with the creation of this channel.</para> + </enum> <enum name="t38state"> <para>The current state of any T.38 fax on this channel.</para> <enumlist> @@ -656,6 +660,27 @@ static int channel_read_rtcp(struct ast_channel *chan, const char *type, const c return 0; } +static int print_escaped_uri(struct ast_channel *chan, const char *type, + pjsip_uri_context_e context, const void *uri, char *buf, size_t size) +{ + int res; + char *buf_copy; + + res = pjsip_uri_print(context, uri, buf, size); + if (res < 0) { + ast_log(LOG_ERROR, "Channel %s: Unescaped %s too long for %d byte buffer\n", + ast_channel_name(chan), type, (int) size); + + /* Empty buffer that likely is not terminated. */ + buf[0] = '\0'; + return -1; + } + + buf_copy = ast_strdupa(buf); + ast_escape_quoted(buf_copy, buf, size); + return 0; +} + /*! * \internal \brief Handle reading signalling information */ @@ -664,6 +689,7 @@ static int channel_read_pjsip(struct ast_channel *chan, const char *type, const struct ast_sip_channel_pvt *channel = ast_channel_tech_pvt(chan); char *buf_copy; pjsip_dialog *dlg; + int res = 0; if (!channel) { ast_log(AST_LOG_WARNING, "Channel %s has no pvt!\n", ast_channel_name(chan)); @@ -689,25 +715,27 @@ static int channel_read_pjsip(struct ast_channel *chan, const char *type, const return -1; #endif } else if (!strcmp(type, "target_uri")) { - pjsip_uri_print(PJSIP_URI_IN_REQ_URI, dlg->target, buf, buflen); - buf_copy = ast_strdupa(buf); - ast_escape_quoted(buf_copy, buf, buflen); + res = print_escaped_uri(chan, type, PJSIP_URI_IN_REQ_URI, dlg->target, buf, + buflen); } else if (!strcmp(type, "local_uri")) { - pjsip_uri_print(PJSIP_URI_IN_FROMTO_HDR, dlg->local.info->uri, buf, buflen); - buf_copy = ast_strdupa(buf); - ast_escape_quoted(buf_copy, buf, buflen); + res = print_escaped_uri(chan, type, PJSIP_URI_IN_FROMTO_HDR, dlg->local.info->uri, + buf, buflen); } else if (!strcmp(type, "local_tag")) { ast_copy_pj_str(buf, &dlg->local.info->tag, buflen); buf_copy = ast_strdupa(buf); ast_escape_quoted(buf_copy, buf, buflen); } else if (!strcmp(type, "remote_uri")) { - pjsip_uri_print(PJSIP_URI_IN_FROMTO_HDR, dlg->remote.info->uri, buf, buflen); - buf_copy = ast_strdupa(buf); - ast_escape_quoted(buf_copy, buf, buflen); + res = print_escaped_uri(chan, type, PJSIP_URI_IN_FROMTO_HDR, + dlg->remote.info->uri, buf, buflen); } else if (!strcmp(type, "remote_tag")) { ast_copy_pj_str(buf, &dlg->remote.info->tag, buflen); buf_copy = ast_strdupa(buf); ast_escape_quoted(buf_copy, buf, buflen); + } else if (!strcmp(type, "request_uri")) { + if (channel->session->request_uri) { + res = print_escaped_uri(chan, type, PJSIP_URI_IN_REQ_URI, + channel->session->request_uri, buf, buflen); + } } else if (!strcmp(type, "t38state")) { ast_copy_string(buf, t38state_to_string[channel->session->t38state], buflen); } else if (!strcmp(type, "local_addr")) { @@ -743,7 +771,7 @@ static int channel_read_pjsip(struct ast_channel *chan, const char *type, const return -1; } - return 0; + return res; } /*! \brief Struct used to push function arguments to task processor */ diff --git a/include/asterisk/res_pjsip_session.h b/include/asterisk/res_pjsip_session.h index de6589abd..6d506a35b 100644 --- a/include/asterisk/res_pjsip_session.h +++ b/include/asterisk/res_pjsip_session.h @@ -211,6 +211,8 @@ struct ast_sip_session { unsigned int ended_while_deferred:1; /*! DTMF mode to use with this session, from endpoint but can change */ enum ast_sip_dtmf_mode dtmf; + /*! Initial incoming INVITE Request-URI. NULL otherwise. */ + pjsip_uri *request_uri; }; typedef int (*ast_sip_session_request_creation_cb)(struct ast_sip_session *session, pjsip_tx_data *tdata); diff --git a/main/asterisk.c b/main/asterisk.c index 187a8ad6b..006a1b03a 100644 --- a/main/asterisk.c +++ b/main/asterisk.c @@ -733,6 +733,27 @@ static char *handle_show_sysinfo(struct ast_cli_entry *e, int cmd, struct ast_cl int totalswap = 0; #if defined(HAVE_SYSINFO) struct sysinfo sys_info; +#elif defined(HAVE_SYSCTL) + static int pageshift; + struct vmtotal vmtotal; + struct timeval boottime; + time_t now; + int mib[2], pagesize, usedswap = 0; + size_t len; +#endif + + switch (cmd) { + case CLI_INIT: + e->command = "core show sysinfo"; + e->usage = + "Usage: core show sysinfo\n" + " List current system information.\n"; + return NULL; + case CLI_GENERATE: + return NULL; + } + +#if defined(HAVE_SYSINFO) sysinfo(&sys_info); uptime = sys_info.uptime / 3600; physmem = sys_info.totalram * sys_info.mem_unit; @@ -741,12 +762,6 @@ static char *handle_show_sysinfo(struct ast_cli_entry *e, int cmd, struct ast_cl freeswap = (sys_info.freeswap * sys_info.mem_unit) / 1024; nprocs = sys_info.procs; #elif defined(HAVE_SYSCTL) - static int pageshift; - struct vmtotal vmtotal; - struct timeval boottime; - time_t now; - int mib[2], pagesize, usedswap = 0; - size_t len; /* calculate the uptime by looking at boottime */ time(&now); mib[0] = CTL_KERN; @@ -794,17 +809,6 @@ static char *handle_show_sysinfo(struct ast_cli_entry *e, int cmd, struct ast_cl #endif #endif - switch (cmd) { - case CLI_INIT: - e->command = "core show sysinfo"; - e->usage = - "Usage: core show sysinfo\n" - " List current system information.\n"; - return NULL; - case CLI_GENERATE: - return NULL; - } - ast_cli(a->fd, "\nSystem Statistics\n"); ast_cli(a->fd, "-----------------\n"); ast_cli(a->fd, " System Uptime: %ld hours\n", uptime); diff --git a/res/res_pjsip/config_transport.c b/res/res_pjsip/config_transport.c index 2f29456ab..a9a90ac92 100644 --- a/res/res_pjsip/config_transport.c +++ b/res/res_pjsip/config_transport.c @@ -917,6 +917,12 @@ static int transport_tls_method_handler(const struct aco_option *opt, struct ast state->tls.method = PJSIP_SSL_UNSPECIFIED_METHOD; } else if (!strcasecmp(var->value, "tlsv1")) { state->tls.method = PJSIP_TLSV1_METHOD; +#ifdef HAVE_PJSIP_TLS_TRANSPORT_PROTO + } else if (!strcasecmp(var->value, "tlsv1_1")) { + state->tls.method = PJSIP_TLSV1_1_METHOD; + } else if (!strcasecmp(var->value, "tlsv1_2")) { + state->tls.method = PJSIP_TLSV1_2_METHOD; +#endif } else if (!strcasecmp(var->value, "sslv2")) { state->tls.method = PJSIP_SSLV2_METHOD; } else if (!strcasecmp(var->value, "sslv3")) { @@ -933,6 +939,10 @@ static int transport_tls_method_handler(const struct aco_option *opt, struct ast static const char *tls_method_map[] = { [PJSIP_SSL_UNSPECIFIED_METHOD] = "unspecified", [PJSIP_TLSV1_METHOD] = "tlsv1", +#ifdef HAVE_PJSIP_TLS_TRANSPORT_PROTO + [PJSIP_TLSV1_1_METHOD] = "tlsv1_1", + [PJSIP_TLSV1_2_METHOD] = "tlsv1_2", +#endif [PJSIP_SSLV2_METHOD] = "sslv2", [PJSIP_SSLV3_METHOD] = "sslv3", [PJSIP_SSLV23_METHOD] = "sslv23", diff --git a/res/res_pjsip/pjsip_options.c b/res/res_pjsip/pjsip_options.c index 662166c89..fbe07d53d 100644 --- a/res/res_pjsip/pjsip_options.c +++ b/res/res_pjsip/pjsip_options.c @@ -1147,7 +1147,24 @@ static int qualify_and_schedule_cb_with_aor(void *obj, void *arg, int flags) static int qualify_and_schedule_cb_without_aor(void *obj, void *arg, int flags) { - qualify_and_schedule_contact((struct ast_sip_contact *) obj); + /* + * These are really dynamic contacts. We need to retrieve the aor associated + * with the contact since it's possible some of the aor's fields were updated + * since last load. + */ + struct ast_sip_contact *contact = obj; + struct ast_sip_aor *aor = ast_sip_location_retrieve_aor(contact->aor); + + if (aor) { + qualify_and_schedule_cb_with_aor(obj, aor, flags); + ao2_ref(aor, -1); + } else { + ast_log(LOG_WARNING, "Unable to locate AOR for contact '%s'. Keeping old " + "associated settings: frequency=%d, timeout=%f, authenticate=%s\n", + contact->uri, contact->qualify_frequency, contact->qualify_timeout, + contact->authenticate_qualify ? "yes" : "no"); + qualify_and_schedule_contact(contact); + } return 0; } @@ -1175,32 +1192,21 @@ static int qualify_and_schedule_all_cb(void *obj, void *arg, int flags) return 0; } -/*! - * \internal - * \brief Unschedule all existing contacts - */ -static int unschedule_all_cb(void *obj, void *arg, int flags) -{ - struct sched_data *data = obj; - - AST_SCHED_DEL_UNREF(sched, data->id, ao2_ref(data, -1)); - - return CMP_MATCH; -} - static void qualify_and_schedule_all(void) { - struct ast_variable *var = ast_variable_new("qualify_frequency >", "0", ""); struct ao2_container *aors; struct ao2_container *contacts; - if (!var) { - return; - } - aors = ast_sorcery_retrieve_by_fields(ast_sip_get_sorcery(), - "aor", AST_RETRIEVE_FLAG_MULTIPLE, var); + /* + * It's possible that the AOR had some of it's fields updated prior to a + * reload. For instance qualifying could have been turned on or off by + * setting the qualify_frequency. Due to this we have to iterate through + * all contacts (static and dynamic), and not just ones where the frequency + * is greater than zero, updating any contact fields with the AOR's values. + */ - ao2_callback(sched_qualifies, OBJ_NODATA | OBJ_MULTIPLE | OBJ_UNLINK, unschedule_all_cb, NULL); + aors = ast_sorcery_retrieve_by_fields(ast_sip_get_sorcery(), + "aor", AST_RETRIEVE_FLAG_MULTIPLE | AST_RETRIEVE_FLAG_ALL, NULL); if (aors) { ao2_callback(aors, OBJ_NODATA, qualify_and_schedule_all_cb, NULL); @@ -1208,14 +1214,11 @@ static void qualify_and_schedule_all(void) } contacts = ast_sorcery_retrieve_by_fields(ast_sip_get_sorcery(), - "contact", AST_RETRIEVE_FLAG_MULTIPLE, var); + "contact", AST_RETRIEVE_FLAG_MULTIPLE | AST_RETRIEVE_FLAG_ALL, NULL); if (contacts) { ao2_callback(contacts, OBJ_NODATA, qualify_and_schedule_cb_without_aor, NULL); ao2_ref(contacts, -1); } - - ast_variables_destroy(var); - } int ast_sip_format_contact_ami(void *obj, void *arg, int flags) diff --git a/res/res_pjsip_session.c b/res/res_pjsip_session.c index 781d3e4eb..55b91208a 100644 --- a/res/res_pjsip_session.c +++ b/res/res_pjsip_session.c @@ -2818,6 +2818,12 @@ static enum sip_get_destination_result get_destination(struct ast_sip_session *s ast_copy_pj_str(domain, &sip_ruri->host, size); pbx_builtin_setvar_helper(session->channel, "SIPDOMAIN", domain); + /* + * Save off the INVITE Request-URI in case it is + * needed: CHANNEL(pjsip,request_uri) + */ + session->request_uri = pjsip_uri_clone(session->inv_session->pool, ruri); + return SIP_GET_DEST_EXTEN_FOUND; } diff --git a/res/res_rtp_asterisk.c b/res/res_rtp_asterisk.c index 16eb7dddf..bdc83301e 100644 --- a/res/res_rtp_asterisk.c +++ b/res/res_rtp_asterisk.c @@ -5169,7 +5169,6 @@ static struct ast_frame *ast_rtcp_interpret(struct ast_rtp_instance *instance, c unsigned int first_word; /*! True if we have seen an acceptable SSRC to learn the remote RTCP address */ unsigned int ssrc_seen; - int report_counter = 0; struct ast_rtp_rtcp_report_block *report_block; struct ast_frame *f = &ast_null_frame; @@ -5413,7 +5412,7 @@ static struct ast_frame *ast_rtcp_interpret(struct ast_rtp_instance *instance, c } return &ast_null_frame; } - rtcp_report->report_block[report_counter] = report_block; + rtcp_report->report_block[0] = report_block; report_block->source_ssrc = ntohl(rtcpheader[i]); report_block->lost_count.packets = ntohl(rtcpheader[i + 1]) & 0x00ffffff; report_block->lost_count.fraction = ((ntohl(rtcpheader[i + 1]) & 0xff000000) >> 24); @@ -5450,7 +5449,6 @@ static struct ast_frame *ast_rtcp_interpret(struct ast_rtp_instance *instance, c ast_verbose(" DLSR: %4.4f (sec)\n",(double)report_block->dlsr / 65536.0); ast_verbose(" RTT: %4.4f(sec)\n", rtp->rtcp->rtt); } - report_counter++; } /* If and when we handle more than one report block, this should occur outside * this loop. @@ -5475,9 +5473,9 @@ static struct ast_frame *ast_rtcp_interpret(struct ast_rtp_instance *instance, c /* There's always a single report block stored, here */ struct ast_rtp_rtcp_report *rtcp_report2; report_block = transport_rtp->f.data.ptr + transport_rtp->f.datalen + sizeof(struct ast_rtp_rtcp_report_block *); - memcpy(report_block, rtcp_report->report_block[report_counter-1], sizeof(struct ast_rtp_rtcp_report_block)); + memcpy(report_block, rtcp_report->report_block[0], sizeof(struct ast_rtp_rtcp_report_block)); rtcp_report2 = (struct ast_rtp_rtcp_report *)transport_rtp->f.data.ptr; - rtcp_report2->report_block[report_counter-1] = report_block; + rtcp_report2->report_block[0] = report_block; transport_rtp->f.datalen += sizeof(struct ast_rtp_rtcp_report_block); } transport_rtp->f.offset = AST_FRIENDLY_OFFSET; |