diff options
-rw-r--r-- | apps/app_queue.c | 20 | ||||
-rw-r--r-- | configs/samples/iax.conf.sample | 12 | ||||
-rw-r--r-- | res/res_clialiases.c | 8 | ||||
-rw-r--r-- | res/res_hep.c | 2 | ||||
-rw-r--r-- | res/res_musiconhold.c | 4 | ||||
-rw-r--r-- | res/res_pjsip_sdp_rtp.c | 3 | ||||
-rw-r--r-- | res/res_pjsip_session.c | 9 | ||||
-rw-r--r-- | res/res_smdi.c | 44 | ||||
-rw-r--r-- | third-party/pjproject/patches/0050-dont_terminate_session_early.patch | 71 |
9 files changed, 144 insertions, 29 deletions
diff --git a/apps/app_queue.c b/apps/app_queue.c index e3a4e22a9..6aea58ccb 100644 --- a/apps/app_queue.c +++ b/apps/app_queue.c @@ -1572,6 +1572,7 @@ struct member { char state_exten[AST_MAX_EXTENSION]; /*!< Extension to get state from (if using hint) */ char state_context[AST_MAX_CONTEXT]; /*!< Context to use when getting state (if using hint) */ char state_interface[AST_CHANNEL_NAME]; /*!< Technology/Location from which to read devicestate changes */ + int state_id; /*!< Extension state callback id (if using hint) */ char membername[80]; /*!< Member name to use in queue logs */ int penalty; /*!< Are we a last resort? */ int calls; /*!< Number of calls serviced by this member */ @@ -2629,12 +2630,21 @@ static int get_queue_member_status(struct member *cur) return ast_strlen_zero(cur->state_exten) ? ast_device_state(cur->state_interface) : extensionstate2devicestate(ast_extension_state(NULL, cur->state_context, cur->state_exten)); } +static void destroy_queue_member_cb(void *obj) +{ + struct member *mem = obj; + + if (mem->state_id != -1) { + ast_extension_state_del(mem->state_id, extension_state_cb); + } +} + /*! \brief allocate space for new queue member and set fields based on parameters passed */ static struct member *create_queue_member(const char *interface, const char *membername, int penalty, int paused, const char *state_interface, int ringinuse) { struct member *cur; - if ((cur = ao2_alloc(sizeof(*cur), NULL))) { + if ((cur = ao2_alloc(sizeof(*cur), destroy_queue_member_cb))) { cur->ringinuse = ringinuse; cur->penalty = penalty; cur->paused = paused; @@ -2661,6 +2671,10 @@ static struct member *create_queue_member(const char *interface, const char *mem ast_copy_string(cur->state_exten, exten, sizeof(cur->state_exten)); ast_copy_string(cur->state_context, S_OR(context, "default"), sizeof(cur->state_context)); + + cur->state_id = ast_extension_state_add(cur->state_context, cur->state_exten, extension_state_cb, NULL); + } else { + cur->state_id = -1; } cur->status = get_queue_member_status(cur); } @@ -11081,8 +11095,6 @@ static int unload_module(void) device_state_sub = stasis_unsubscribe_and_join(device_state_sub); - ast_extension_state_del(0, extension_state_cb); - ast_unload_realtime("queue_members"); ao2_cleanup(queues); ao2_cleanup(pending_members); @@ -11240,8 +11252,6 @@ static int load_module(void) err |= STASIS_MESSAGE_TYPE_INIT(queue_agent_dump_type); err |= STASIS_MESSAGE_TYPE_INIT(queue_agent_ringnoanswer_type); - ast_extension_state_add(NULL, NULL, extension_state_cb, NULL); - if (err) { unload_module(); return AST_MODULE_LOAD_DECLINE; diff --git a/configs/samples/iax.conf.sample b/configs/samples/iax.conf.sample index ebe4d7fdc..c6da46179 100644 --- a/configs/samples/iax.conf.sample +++ b/configs/samples/iax.conf.sample @@ -576,12 +576,12 @@ inkeys=freeworlddialup ; ; Peers may also be specified, with a secret and a remote hostname. ; -[demo] -type=peer -username=asterisk -secret=supersecret -host=216.207.245.47 -description=Demo System At Digium ; Description of this peer, as listed by +;[demo] +;type=peer +;username=asterisk +;secret=supersecret +;host=192.168.10.10 +;description=My IAX2 Peer ; Description of this peer, as listed by ; 'iax2 show peers' ;sendani=no ;host=asterisk.linux-support.net diff --git a/res/res_clialiases.c b/res/res_clialiases.c index 1a2fc6939..337c31c97 100644 --- a/res/res_clialiases.c +++ b/res/res_clialiases.c @@ -103,7 +103,7 @@ static char *cli_alias_passthrough(struct ast_cli_entry *e, int cmd, struct ast_ struct cli_alias tmp = { .cli_entry.command = e->command, }; - char *generator; + char *generator = NULL; const char *line; /* Try to find the alias based on the CLI entry */ @@ -118,14 +118,10 @@ static char *cli_alias_passthrough(struct ast_cli_entry *e, int cmd, struct ast_ case CLI_GENERATE: line = a->line; line += (strlen(alias->alias)); - if (!strncasecmp(alias->alias, alias->real_cmd, strlen(alias->alias))) { - generator = NULL; - } else if (!ast_strlen_zero(a->word)) { + if (strncasecmp(alias->alias, alias->real_cmd, strlen(alias->alias))) { struct ast_str *real_cmd = ast_str_alloca(strlen(alias->real_cmd) + strlen(line) + 1); ast_str_append(&real_cmd, 0, "%s%s", alias->real_cmd, line); generator = ast_cli_generator(ast_str_buffer(real_cmd), a->word, a->n); - } else { - generator = ast_cli_generator(alias->real_cmd, a->word, a->n); } ao2_ref(alias, -1); return generator; diff --git a/res/res_hep.c b/res/res_hep.c index 25b4d13b1..ba036d70f 100644 --- a/res/res_hep.c +++ b/res/res_hep.c @@ -421,7 +421,7 @@ int hepv3_is_loaded(void) { RAII_VAR(struct module_config *, config, ao2_global_obj_ref(global_config), ao2_cleanup); - return (config != NULL) ? 1 : 0; + return config && config->general->enabled; } struct hepv3_capture_info *hepv3_create_capture_info(const void *payload, size_t len) diff --git a/res/res_musiconhold.c b/res/res_musiconhold.c index ef1b81c2a..17e91b70c 100644 --- a/res/res_musiconhold.c +++ b/res/res_musiconhold.c @@ -333,6 +333,7 @@ static int ast_moh_files_next(struct ast_channel *chan) } } else { state->announcement = 0; + state->samples = 0; } if (!state->class->total_files) { @@ -1934,6 +1935,9 @@ static char *handle_cli_moh_show_classes(struct ast_cli_entry *e, int cmd, struc ast_cli(a->fd, "Class: %s\n", class->name); ast_cli(a->fd, "\tMode: %s\n", S_OR(class->mode, "<none>")); ast_cli(a->fd, "\tDirectory: %s\n", S_OR(class->dir, "<none>")); + if (ast_test_flag(class, MOH_ANNOUNCEMENT)) { + ast_cli(a->fd, "\tAnnouncement: %s\n", S_OR(class->announcement, "<none>")); + } if (ast_test_flag(class, MOH_CUSTOM)) { ast_cli(a->fd, "\tApplication: %s\n", S_OR(class->args, "<none>")); ast_cli(a->fd, "\tKill Escalation Delay: %zu ms\n", class->kill_delay / 1000); diff --git a/res/res_pjsip_sdp_rtp.c b/res/res_pjsip_sdp_rtp.c index a87758267..854ed1459 100644 --- a/res/res_pjsip_sdp_rtp.c +++ b/res/res_pjsip_sdp_rtp.c @@ -1253,7 +1253,8 @@ static int add_crypto_to_stream(struct ast_sip_session *session, /* If this is an answer we need to use our current state, if it's an offer we need to use * the configured value. */ - if (pjmedia_sdp_neg_get_state(session->inv_session->neg) != PJMEDIA_SDP_NEG_STATE_DONE) { + if (session->inv_session->neg + && pjmedia_sdp_neg_get_state(session->inv_session->neg) != PJMEDIA_SDP_NEG_STATE_DONE) { setup = dtls->get_setup(session_media->rtp); } else { setup = session->endpoint->media.rtp.dtls_cfg.default_setup; diff --git a/res/res_pjsip_session.c b/res/res_pjsip_session.c index 55b91208a..958f2254b 100644 --- a/res/res_pjsip_session.c +++ b/res/res_pjsip_session.c @@ -3878,10 +3878,15 @@ static struct pjmedia_sdp_session *create_local_sdp(pjsip_inv_session *inv, stru if (!session->pending_media_state->topology || !ast_stream_topology_get_count(session->pending_media_state->topology)) { /* We've encountered a situation where we have been told to create a local SDP but noone has given us any indication - * of what kind of stream topology they would like. As a fallback we use the topology from the configured endpoint. + * of what kind of stream topology they would like. We try to not alter the current state of the SDP negotiation + * by using what is currently negotiated. If this is unavailable we fall back to what is configured on the endpoint. */ ast_stream_topology_free(session->pending_media_state->topology); - session->pending_media_state->topology = ast_stream_topology_clone(session->endpoint->media.topology); + if (session->active_media_state->topology) { + session->pending_media_state->topology = ast_stream_topology_clone(session->active_media_state->topology); + } else { + session->pending_media_state->topology = ast_stream_topology_clone(session->endpoint->media.topology); + } if (!session->pending_media_state->topology) { return NULL; } diff --git a/res/res_smdi.c b/res/res_smdi.c index 0edabb83c..054e6aab6 100644 --- a/res/res_smdi.c +++ b/res/res_smdi.c @@ -586,9 +586,8 @@ static void *smdi_read(void *iface_p) struct ast_smdi_interface *iface = iface_p; struct ast_smdi_md_message *md_msg; struct ast_smdi_mwi_message *mwi_msg; - char c = '\0'; char *cp = NULL; - int i; + int i, c; int start = 0; /* read an smdi message */ @@ -616,7 +615,14 @@ static void *smdi_read(void *iface_p) /* read the message desk number */ for (i = 0; i < sizeof(md_msg->mesg_desk_num) - 1; i++) { - md_msg->mesg_desk_num[i] = fgetc(iface->file); + c = fgetc(iface->file); + if (c == EOF) { + ast_log(LOG_ERROR, "Unexpected EOF while reading MD message\n"); + ao2_ref(md_msg, -1); + ao2_ref(iface, -1); + return NULL; + } + md_msg->mesg_desk_num[i] = (char) c; ast_debug(1, "Read a '%c'\n", md_msg->mesg_desk_num[i]); } @@ -626,7 +632,14 @@ static void *smdi_read(void *iface_p) /* read the message desk terminal number */ for (i = 0; i < sizeof(md_msg->mesg_desk_term) - 1; i++) { - md_msg->mesg_desk_term[i] = fgetc(iface->file); + c = fgetc(iface->file); + if (c == EOF) { + ast_log(LOG_ERROR, "Unexpected EOF while reading SMDI message\n"); + ao2_ref(md_msg, -1); + ao2_ref(iface, -1); + return NULL; + } + md_msg->mesg_desk_term[i] = (char) c; ast_debug(1, "Read a '%c'\n", md_msg->mesg_desk_term[i]); } @@ -635,7 +648,14 @@ static void *smdi_read(void *iface_p) ast_debug(1, "The message desk terminal is '%s'\n", md_msg->mesg_desk_term); /* read the message type */ - md_msg->type = fgetc(iface->file); + c = fgetc(iface->file); + if (c == EOF) { + ast_log(LOG_ERROR, "Unexpected EOF while reading SMDI message\n"); + ao2_ref(md_msg, -1); + ao2_ref(iface, -1); + return NULL; + } + md_msg->type = (char) c; ast_debug(1, "Message type is '%c'\n", md_msg->type); @@ -717,7 +737,7 @@ static void *smdi_read(void *iface_p) /* discard the 'I' (from 'MWI') */ fgetc(iface->file); - + /* read the forwarding station number (may be blank) */ cp = &mwi_msg->fwd_st[0]; for (i = 0; i < sizeof(mwi_msg->fwd_st) - 1; i++) { @@ -740,8 +760,16 @@ static void *smdi_read(void *iface_p) ast_copy_string(mwi_msg->name, mwi_msg->fwd_st, sizeof(mwi_msg->name)); /* read the mwi failure cause */ - for (i = 0; i < sizeof(mwi_msg->cause) - 1; i++) - mwi_msg->cause[i] = fgetc(iface->file); + for (i = 0; i < sizeof(mwi_msg->cause) - 1; i++) { + c = fgetc(iface->file); + if (c == EOF) { + ast_log(LOG_ERROR, "Unexpected EOF while reading MWI message\n"); + ao2_ref(mwi_msg, -1); + ao2_ref(iface, -1); + return NULL; + } + mwi_msg->cause[i] = (char) c; + } mwi_msg->cause[sizeof(mwi_msg->cause) - 1] = '\0'; diff --git a/third-party/pjproject/patches/0050-dont_terminate_session_early.patch b/third-party/pjproject/patches/0050-dont_terminate_session_early.patch new file mode 100644 index 000000000..718968c79 --- /dev/null +++ b/third-party/pjproject/patches/0050-dont_terminate_session_early.patch @@ -0,0 +1,71 @@ +commit ca0b723e92bd76bbda1bbd14477a829eaeeb675e +Author: Joshua Colp <jcolp@digium.com> +Date: Wed Dec 13 10:58:57 2017 +0000 + + Ignore transport error on completed transaction. + Don't disconnect call if transport error happens on transaction that is not initial INVITE transaction. + + Scenario: + + DNS lookup returning two servers. + Sending INVITE to first server over TCP. + Response received with code 503 (Service Unavailable). + Failover to second server, sending second INVITE after restarting the session. + TCP connection for the first INVITE getting disconnected and causing call disconnection (while second INVITE is still outstanding). + + This is a backport of 5714 from upstream PJSIP. + +diff --git a/pjsip/src/pjsip-ua/sip_inv.c b/pjsip/src/pjsip-ua/sip_inv.c +index ac4d1949..0173cb4c 100644 +--- a/pjsip/src/pjsip-ua/sip_inv.c ++++ b/pjsip/src/pjsip-ua/sip_inv.c +@@ -4254,8 +4254,7 @@ static void inv_on_state_calling( pjsip_inv_session *inv, pjsip_event *e) + if ((tsx->status_code == PJSIP_SC_CALL_TSX_DOES_NOT_EXIST && + tsx->method.id != PJSIP_CANCEL_METHOD) || + tsx->status_code == PJSIP_SC_REQUEST_TIMEOUT || +- tsx->status_code == PJSIP_SC_TSX_TIMEOUT || +- tsx->status_code == PJSIP_SC_TSX_TRANSPORT_ERROR) ++ tsx->status_code == PJSIP_SC_TSX_TIMEOUT) + { + inv_set_cause(inv, tsx->status_code, &tsx->status_text); + inv_set_state(inv, PJSIP_INV_STATE_DISCONNECTED, e); +diff --git a/pjsip/src/pjsip/sip_transaction.c b/pjsip/src/pjsip/sip_transaction.c +index 7ac3d1b7..d52b12a7 100644 +--- a/pjsip/src/pjsip/sip_transaction.c ++++ b/pjsip/src/pjsip/sip_transaction.c +@@ -2044,9 +2044,14 @@ static void transport_callback(void *token, pjsip_tx_data *tdata, + */ + lock_timer(tsx); + tsx->transport_err = (pj_status_t)-sent; +- tsx_cancel_timer(tsx, &tsx->timeout_timer); +- tsx_schedule_timer(tsx, &tsx->timeout_timer, &delay, +- TRANSPORT_ERR_TIMER); ++ /* Don't cancel timeout timer if tsx state is already ++ * PJSIP_TSX_STATE_COMPLETED (see #2076). ++ */ ++ if (tsx->state < PJSIP_TSX_STATE_COMPLETED) { ++ tsx_cancel_timer(tsx, &tsx->timeout_timer); ++ tsx_schedule_timer(tsx, &tsx->timeout_timer, &delay, ++ TRANSPORT_ERR_TIMER); ++ } + unlock_timer(tsx); + } + +@@ -2077,9 +2082,14 @@ static void tsx_tp_state_callback( pjsip_transport *tp, + */ + lock_timer(tsx); + tsx->transport_err = info->status; +- tsx_cancel_timer(tsx, &tsx->timeout_timer); +- tsx_schedule_timer(tsx, &tsx->timeout_timer, &delay, +- TRANSPORT_ERR_TIMER); ++ /* Don't cancel timeout timer if tsx state is already ++ * PJSIP_TSX_STATE_COMPLETED (see #2076). ++ */ ++ if (tsx->state < PJSIP_TSX_STATE_COMPLETED) { ++ tsx_cancel_timer(tsx, &tsx->timeout_timer); ++ tsx_schedule_timer(tsx, &tsx->timeout_timer, &delay, ++ TRANSPORT_ERR_TIMER); ++ } + unlock_timer(tsx); + } + } |