diff --git a/channels/chan_brcm.c b/channels/chan_brcm.c index 663a59d1f90ebe3e21d48cde2b7bb030fbd8d945..b86714b4fdb46b6995a87f0d23f5baa8a414d919 100644 --- a/channels/chan_brcm.c +++ b/channels/chan_brcm.c @@ -552,7 +552,6 @@ static int brcm_indicate(struct ast_channel *ast, int condition, const void *dat //ast_mutex_lock(&sub->parent->lock); switch(condition) { case AST_CONTROL_UNHOLD: - res = 0; //We still want asterisk core to play tone brcm_stop_dialtone(sub->parent); // Play a beep when unholding. @@ -577,7 +576,6 @@ static int brcm_indicate(struct ast_channel *ast, int condition, const void *dat sub->codec = -1; if (sub->channel_state == RINGBACK) endpt_signal(sub->parent->line_id, "ringback", "off", NULL); - res = 0; break; case AST_CONTROL_RINGING: ast_debug(4, "Got AST_CONTROL_RINGING on %s, sub->codec = %d\n", ast_channel_name(ast), sub->codec); @@ -589,10 +587,8 @@ static int brcm_indicate(struct ast_channel *ast, int condition, const void *dat sub->call_id = ast_channel_callid(sub->owner); endpt_connection(sub->parent->line_id, sub->call_id, "update"); } - res = 0; break; case AST_CONTROL_UNHOLD_FOR_TRANSFER: - res = -1; if (sub->channel_state == TRANSFERING) { struct ast_channel *bridged_chan = ast_channel_bridge_peer(sub->owner); if (bridged_chan) { @@ -661,11 +657,9 @@ static int brcm_indicate(struct ast_channel *ast, int condition, const void *dat } } } - res = 0; } else if (sub->owner && (sub->call_id == 0)) { sub->call_id = ast_channel_callid(sub->owner); endpt_connection(sub->parent->line_id, sub->call_id, "update"); - res = 0; } else { res = -1; } diff --git a/channels/chan_pjsip.c b/channels/chan_pjsip.c index 5383c93cc53474d8224cda86bba642046f9b5071..9f19af12d16082378235dbc61b38a01635abfef9 100644 --- a/channels/chan_pjsip.c +++ b/channels/chan_pjsip.c @@ -1807,10 +1807,12 @@ static int chan_pjsip_indicate(struct ast_channel *ast, int condition, const voi } } struct ast_channel *bridged_chan; + ast_channel_unlock(ast); bridged_chan = ast_channel_bridge_peer(ast); - + ast_channel_lock(ast); if (bridged_chan) { ast_indicate(bridged_chan, AST_CONTROL_UNHOLD_FOR_TRANSFER); + ast_channel_unref(bridged_chan); } break; case AST_CONTROL_SRCUPDATE: @@ -2072,7 +2074,7 @@ static void xfer_client_on_evsub_state(pjsip_evsub *sub, pjsip_event *event) struct ast_channel *bridged_chan = ast_channel_bridge_peer(chan); if (bridged_chan) { while (2 < ao2_ref(bridged_chan, 0)) - ao2_ref(bridged_chan, -1); + ast_channel_unref(bridged_chan); } if (res) { @@ -2174,16 +2176,28 @@ static void transfer_refer(struct ast_sip_session *session, const char *target) chan_name, target, replaces); } - if (PJSIP_URI_SCHEME_IS_SIP(session->request_uri)) - snprintf(referto, sizeof(referto), "<sip:%s@%s%s>", target, session->endpoint->fromdomain, replaces); - else if (PJSIP_URI_SCHEME_IS_SIPS(session->request_uri)) - snprintf(referto, sizeof(referto), "<sips:%s@%s%s>", target, session->endpoint->fromdomain, replaces); - else if (PJSIP_URI_SCHEME_IS_TEL(session->request_uri)) - snprintf(referto, sizeof(referto), "<tel:%s@%s%s>", target, session->endpoint->fromdomain, replaces); - else { + char method[5] = {0}; + if (session->request_uri) { + if (PJSIP_URI_SCHEME_IS_SIP(session->request_uri)) + strncpy(method, "sip", sizeof(method) - 1); + else if (PJSIP_URI_SCHEME_IS_SIPS(session->request_uri)) + strncpy(method, "sips", sizeof(method) - 1); + else if (PJSIP_URI_SCHEME_IS_TEL(session->request_uri)) + strncpy(method, "tel", sizeof(method) - 1); + else { + ast_log(LOG_ERROR, "Unsupported URI for Refer-To header. Refer will not be sent!\n"); + goto failure; + } + + } else if (session->contact) { + char *contact_uri = ast_strdupa(session->contact->uri); + strncpy(method, strtok(contact_uri, ":"), sizeof(method) - 1); + } else { ast_log(LOG_ERROR, "Unsupported URI for Refer-To header. Refer will not be sent!\n"); goto failure; } + + snprintf(referto, sizeof(referto), "<%s:%s@%s%s>", method, target, session->endpoint->fromdomain, replaces); ast_debug(1, "Refer-To: %s\n", referto); if (pjsip_xfer_initiate(sub, pj_cstr(&tmp, referto), &packet) != PJ_SUCCESS) { @@ -2193,9 +2207,6 @@ static void transfer_refer(struct ast_sip_session *session, const char *target) // unattended call transfer if (!chan_name) { const char *callid = chan_pjsip_get_uniqueid(session->channel); - const char *totag; - const char *fromtag; - char local_tag[pj_strlen(&session->inv_session->dlg->local.info->tag) + 1]; char remote_tag[pj_strlen(&session->inv_session->dlg->remote.info->tag) + 1]; @@ -2211,16 +2222,7 @@ static void transfer_refer(struct ast_sip_session *session, const char *target) if (!ast_strlen_zero(ref_by_val)) { ast_sip_add_header(packet, "Referred-By", ref_by_val); } else { - if (PJSIP_URI_SCHEME_IS_SIP(session->request_uri)) - snprintf(local_info, sizeof(local_info), "<sip:%s@%s>", session->endpoint->contact_user, session->endpoint->fromdomain); - else if (PJSIP_URI_SCHEME_IS_SIPS(session->request_uri)) - snprintf(local_info, sizeof(local_info), "<sips:%s@%s>", session->endpoint->contact_user, session->endpoint->fromdomain); - else if (PJSIP_URI_SCHEME_IS_TEL(session->request_uri)) - snprintf(local_info, sizeof(local_info), "<tel:%s@%s>", session->endpoint->contact_user, session->endpoint->fromdomain); - else { - ast_log(LOG_ERROR, "Unsupported URI for Referred-By header. Refer will not be sent!\n"); - goto failure; - } + snprintf(local_info, sizeof(local_info), "<%s:%s@%s>", method, session->endpoint->contact_user, session->endpoint->fromdomain); ast_sip_add_header(packet, "Referred-By", local_info); } @@ -2257,12 +2259,7 @@ static int transfer(void *data) target = contact->uri; } } - - if (ast_channel_state(trnf_data->session->channel) == AST_STATE_RING) { - transfer_redirect(trnf_data->session, target); - } else { - transfer_refer(trnf_data->session, target); - } + transfer_refer(trnf_data->session, target); } ao2_ref(trnf_data, -1); diff --git a/res/res_pjsip_refer.c b/res/res_pjsip_refer.c index 5af0af6229861ed2a0acc29643528fe12d71ba33..2c442426a9978d58b34c3112c6eac723db76d293 100644 --- a/res/res_pjsip_refer.c +++ b/res/res_pjsip_refer.c @@ -64,6 +64,8 @@ struct refer_progress { int sent_100; /*! \brief Whether to notifies all the progress details on blind transfer */ unsigned int refer_blind_progress; + /*! \brief Pointer to Invite session state. */ + unsigned int *invite_state; }; /*! \brief REFER Progress notification structure */ @@ -153,6 +155,15 @@ static int refer_progress_notify(void *data) return 0; } + if (*notification->progress->invite_state != PJSIP_INV_STATE_CONFIRMED) { + ast_debug(3, "Not sending NOTIFY of response '%d' and state '%u' on progress monitor '%p' as invite session has been terminated\n", + notification->response, notification->state, notification->progress); + pjsip_evsub_set_mod_data(sub, refer_progress_module.id, NULL); + sub = NULL; + pjsip_dlg_dec_lock(notification->progress->dlg); + return 0; + } + /* Send a deferred initial 100 Trying SIP frag NOTIFY if we haven't already. */ if (!notification->progress->sent_100) { notification->progress->sent_100 = 1; @@ -421,6 +432,7 @@ static int refer_progress_alloc(struct ast_sip_session *session, pjsip_rx_data * /* To prevent a potential deadlock we need the dialog so we can lock/unlock */ (*progress)->dlg = session->inv_session->dlg; + (*progress)->invite_state = &session->inv_session->state; /* We also need to make sure it stays around until we're done with it */ pjsip_dlg_inc_session((*progress)->dlg, &refer_progress_module);