diff options
-rw-r--r-- | apps/app_queue.c | 20 | ||||
-rw-r--r-- | configs/samples/iax.conf.sample | 12 | ||||
-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-- | third-party/pjproject/patches/0050-dont_terminate_session_early.patch | 71 |
6 files changed, 105 insertions, 14 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_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/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); + } + } |