提交 968f4fcc authored 作者: Anthony Minessale's avatar Anthony Minessale

fix sofia (part 2) you'd better 'make sure'

git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@3860 d0543943-73ff-0310-b7d9-9358b9ac24b2
上级 905a48c8
......@@ -599,7 +599,8 @@ static int nua_notify_usage_shutdown(nua_handle_t *nh,
if (!cr->cr_usage) {
/* Unnotify */
nua_stack_notify2(nh->nh_nua, nh, nua_r_destroy, du, NULL);
/* Commenting this line out to supress an attended transfer bug (awaiting fix from pessi) */
//nua_stack_notify2(nh->nh_nua, nh, nua_r_destroy, du, NULL);
return cr->cr_usage != du;
}
......
......@@ -49,7 +49,7 @@ typedef struct sofia_profile sofia_profile_t;
#define NUA_MAGIC_T sofia_profile_t
struct sofia_private {
switch_core_session_t *session;
char uuid[SWITCH_UUID_FORMATTED_LENGTH + 1];
outbound_reg_t *oreg;
};
......@@ -167,8 +167,7 @@ typedef enum {
TFLAG_XFER = (1 << 19),
TFLAG_NOMEDIA = (1 << 20),
TFLAG_BUGGY_2833 = (1 << 21),
TFLAG_SIP_HOLD = (1 << 22),
TFLAG_RWLOCK = (1 << 23)
TFLAG_SIP_HOLD = (1 << 22)
} TFLAGS;
static struct {
......@@ -256,7 +255,6 @@ struct sofia_profile {
struct private_object {
sofia_private_t *sofia_private;
sofia_private_t *sofia_private2;
uint32_t flags;
switch_payload_t agreed_pt;
switch_core_session_t *session;
......@@ -374,7 +372,7 @@ static void sip_i_state(int status,
static void sip_i_refer(nua_t *nua,
sofia_profile_t *profile,
nua_handle_t *nh,
sofia_private_t *sofia_private,
switch_core_session_t *session,
sip_t const *sip,
tagi_t tags[]);
......@@ -983,7 +981,7 @@ static void do_invite(switch_core_session_t *session)
abort();
}
memset(tech_pvt->sofia_private, 0, sizeof(*tech_pvt->sofia_private));
tech_pvt->sofia_private->session = session;
switch_copy_string(tech_pvt->sofia_private->uuid, switch_core_session_get_uuid(session), sizeof(tech_pvt->sofia_private->uuid));
nua_handle_bind(tech_pvt->nh, tech_pvt->sofia_private);
}
......@@ -1057,14 +1055,7 @@ static void do_xfer_invite(switch_core_session_t *session)
TAG_END());
if (!(tech_pvt->sofia_private2 = malloc(sizeof(*tech_pvt->sofia_private2)))) {
abort();
}
memset(tech_pvt->sofia_private2, 0, sizeof(*tech_pvt->sofia_private2));
tech_pvt->sofia_private2->session = tech_pvt->sofia_private->session;
nua_handle_bind(tech_pvt->nh2, tech_pvt->sofia_private2);
nua_handle_bind(tech_pvt->nh2, tech_pvt->sofia_private);
nua_invite(tech_pvt->nh2,
TAG_IF(rpid, SIPTAG_HEADER_STR(rpid)),
......@@ -1237,7 +1228,7 @@ static int hangup_cause_to_sip(switch_call_cause_t cause) {
static switch_status_t sofia_on_hangup(switch_core_session_t *session)
{
switch_core_session_t *asession;
switch_core_session_t *a_session;
private_object_t *tech_pvt;
switch_channel_t *channel = NULL;
switch_call_cause_t cause;
......@@ -1261,10 +1252,10 @@ static switch_status_t sofia_on_hangup(switch_core_session_t *session)
switch_core_hash_delete(tech_pvt->profile->chat_hash, tech_pvt->hash_key);
}
if (tech_pvt->kick && (asession = switch_core_session_locate(tech_pvt->kick))) {
switch_channel_t *a_channel = switch_core_session_get_channel(asession);
if (tech_pvt->kick && (a_session = switch_core_session_locate(tech_pvt->kick))) {
switch_channel_t *a_channel = switch_core_session_get_channel(a_session);
switch_channel_hangup(a_channel, switch_channel_get_cause(channel));
switch_core_session_rwunlock(asession);
switch_core_session_rwunlock(a_session);
}
if (tech_pvt->nh) {
......@@ -1297,7 +1288,7 @@ static switch_status_t sofia_on_hangup(switch_core_session_t *session)
}
if (tech_pvt->sofia_private) {
tech_pvt->sofia_private->session = NULL;
*tech_pvt->sofia_private->uuid = '\0';
}
return SWITCH_STATUS_SUCCESS;
......@@ -1862,23 +1853,21 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
if (switch_test_flag(tech_pvt, TFLAG_XFER)) {
switch_clear_flag_locked(tech_pvt, TFLAG_XFER);
if (msg->pointer_arg) {
switch_core_session_t *asession, *bsession = msg->pointer_arg;
switch_core_session_t *a_session, *b_session = msg->pointer_arg;
if ((asession = switch_core_session_locate(tech_pvt->xferto))) {
private_object_t *a_tech_pvt = switch_core_session_get_private(asession);
private_object_t *b_tech_pvt = switch_core_session_get_private(bsession);
if ((a_session = switch_core_session_locate(tech_pvt->xferto))) {
private_object_t *a_tech_pvt = switch_core_session_get_private(a_session);
private_object_t *b_tech_pvt = switch_core_session_get_private(b_session);
switch_set_flag_locked(a_tech_pvt, TFLAG_REINVITE);
a_tech_pvt->remote_sdp_audio_ip = switch_core_session_strdup(asession, b_tech_pvt->remote_sdp_audio_ip);
a_tech_pvt->remote_sdp_audio_ip = switch_core_session_strdup(a_session, b_tech_pvt->remote_sdp_audio_ip);
a_tech_pvt->remote_sdp_audio_port = b_tech_pvt->remote_sdp_audio_port;
a_tech_pvt->local_sdp_audio_ip = switch_core_session_strdup(asession, b_tech_pvt->local_sdp_audio_ip);
a_tech_pvt->local_sdp_audio_ip = switch_core_session_strdup(a_session, b_tech_pvt->local_sdp_audio_ip);
a_tech_pvt->local_sdp_audio_port = b_tech_pvt->local_sdp_audio_port;
activate_rtp(a_tech_pvt);
b_tech_pvt->kick = switch_core_session_strdup(bsession, tech_pvt->xferto);
switch_core_session_rwunlock(asession);
b_tech_pvt->kick = switch_core_session_strdup(b_session, tech_pvt->xferto);
switch_core_session_rwunlock(a_session);
}
......@@ -2505,7 +2494,7 @@ static void sip_i_state(int status,
int ss_state = nua_callstate_init;
switch_channel_t *channel = NULL;
private_object_t *tech_pvt = NULL;
switch_core_session_t *session = sofia_private ? sofia_private->session : NULL;
switch_core_session_t *session = NULL;
const char *replaces_str = NULL;
char *uuid;
switch_core_session_t *other_session = NULL;
......@@ -2513,6 +2502,16 @@ static void sip_i_state(int status,
char st[80] = "";
if (sofia_private) {
if (!switch_strlen_zero(sofia_private->uuid)) {
if (!(session = switch_core_session_locate(sofia_private->uuid))) {
/* too late */
return;
}
}
}
tl_gets(tags,
NUTAG_CALLSTATE_REF(ss_state),
NUTAG_OFFER_RECV_REF(offer_recv),
......@@ -2549,7 +2548,7 @@ static void sip_i_state(int status,
}
if (status == 988) {
return;
goto done;
}
switch ((enum nua_callstate)ss_state) {
......@@ -2591,7 +2590,7 @@ static void sip_i_state(int status,
switch_channel_pre_answer(other_channel);
switch_core_session_rwunlock(other_session);
}
return;
goto done;
} else {
sdp_parser_t *parser = sdp_parse(tech_pvt->home, r_sdp, (int)strlen(r_sdp), 0);
sdp_session_t *sdp;
......@@ -2628,7 +2627,7 @@ static void sip_i_state(int status,
case nua_callstate_received:
if (session && switch_core_session_running(session)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Re-Entering Call State Received!\n");
return;
goto done;
}
if (channel) {
......@@ -2638,7 +2637,7 @@ static void sip_i_state(int status,
switch_channel_set_state(channel, CS_INIT);
switch_set_flag_locked(tech_pvt, TFLAG_READY);
switch_core_session_thread_launch(session);
return;
goto done;
} else {
sdp_parser_t *parser = sdp_parse(tech_pvt->home, r_sdp, (int)strlen(r_sdp), 0);
sdp_session_t *sdp;
......@@ -2673,7 +2672,7 @@ static void sip_i_state(int status,
if ((b_private = nua_handle_magic(bnh))) {
char *br_b = switch_channel_get_variable(channel, SWITCH_BRIDGE_VARIABLE);
char *br_a = switch_core_session_get_uuid(b_private->session);
char *br_a = b_private->uuid;
if (br_b) {
switch_ivr_uuid_bridge(br_a, br_b);
......@@ -2689,7 +2688,7 @@ static void sip_i_state(int status,
}
nua_handle_unref(bnh);
}
return;
goto done;
}
switch_channel_set_variable(channel, "endpoint_disposition", "NO CODECS");
......@@ -2706,7 +2705,7 @@ static void sip_i_state(int status,
if (tech_pvt && r_sdp) {
if (r_sdp) {
if (switch_test_flag(tech_pvt, TFLAG_NOMEDIA)) {
return;
goto done;
} else {
sdp_parser_t *parser = sdp_parse(tech_pvt->home, r_sdp, (int)strlen(r_sdp), 0);
sdp_session_t *sdp;
......@@ -2739,7 +2738,7 @@ static void sip_i_state(int status,
tech_pvt->nh2 = NULL;
tech_choose_port(tech_pvt);
activate_rtp(tech_pvt);
return;
goto done;
}
if (channel) {
......@@ -2752,7 +2751,7 @@ static void sip_i_state(int status,
switch_channel_answer(other_channel);
switch_core_session_rwunlock(other_session);
}
return;
goto done;
} else {
sdp_parser_t *parser = sdp_parse(tech_pvt->home, r_sdp, (int)strlen(r_sdp), 0);
sdp_session_t *sdp;
......@@ -2775,7 +2774,7 @@ static void sip_i_state(int status,
tech_choose_port(tech_pvt);
activate_rtp(tech_pvt);
switch_channel_mark_answered(channel);
return;
goto done;
}
switch_channel_set_variable(channel, "endpoint_disposition", "NO CODECS");
......@@ -2785,7 +2784,7 @@ static void sip_i_state(int status,
switch_set_flag_locked(tech_pvt, TFLAG_ANS);
switch_channel_set_variable(channel, "endpoint_disposition", "ANSWER");
switch_channel_mark_answered(channel);
return;
goto done;
} //else probably an ack
}
......@@ -2794,10 +2793,6 @@ static void sip_i_state(int status,
break;
case nua_callstate_terminated:
if (session) {
if (switch_test_flag(tech_pvt, TFLAG_RWLOCK)) {
switch_core_session_rwunlock(session);
switch_clear_flag_locked(tech_pvt, TFLAG_RWLOCK);
}
if (!switch_test_flag(tech_pvt, TFLAG_BYE)) {
switch_set_flag_locked(tech_pvt, TFLAG_BYE);
......@@ -2812,18 +2807,25 @@ static void sip_i_state(int status,
if (tech_pvt->sofia_private) {
free(tech_pvt->sofia_private);
nua_handle_bind(tech_pvt->nh, NULL);
tech_pvt->sofia_private = NULL;
}
tech_pvt->nh = NULL;
} else if (sofia_private) {
free(sofia_private);
}
if (nh) {
nua_handle_bind(nh, NULL);
nua_handle_destroy(nh);
}
break;
}
done:
if (session) {
switch_core_session_rwunlock(session);
}
}
......@@ -3532,7 +3534,7 @@ static void sip_r_subscribe(int status,
static void sip_i_refer(nua_t *nua,
sofia_profile_t *profile,
nua_handle_t *nh,
sofia_private_t *sofia_private,
switch_core_session_t *session,
sip_t const *sip,
tagi_t tags[])
{
......@@ -3540,9 +3542,6 @@ static void sip_i_refer(nua_t *nua,
sip_from_t const *from;
sip_to_t const *to;
sip_refer_to_t const *refer_to;
switch_core_session_t *session = sofia_private ? sofia_private->session : NULL;
if (session) {
private_object_t *tech_pvt = NULL;
char *etmp = NULL, *exten = NULL;
switch_channel_t *channel_a = NULL, *channel_b = NULL;
......@@ -3550,7 +3549,6 @@ static void sip_i_refer(nua_t *nua,
tech_pvt = switch_core_session_get_private(session);
channel_a = switch_core_session_get_channel(session);
if (!sip->sip_cseq || !(etmp = switch_mprintf("refer;id=%u", sip->sip_cseq->cs_seq))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Memory Error!\n");
goto done;
......@@ -3598,31 +3596,27 @@ static void sip_i_refer(nua_t *nua,
}
if ((replaces = sip_replaces_make(tech_pvt->home, rep)) && (bnh = nua_handle_by_replaces(nua, replaces))) {
sofia_private_t *b_private = NULL;
private_object_t *tech_pvt_b = NULL;
private_object_t *b_tech_pvt = NULL;
switch_core_session_t *b_session = NULL;
switch_channel_set_variable(channel_a, SOFIA_REPLACES_HEADER, rep);
if ((b_private = nua_handle_magic(bnh))) {
tech_pvt_b = (private_object_t *) switch_core_session_get_private(b_private->session);
channel_b = switch_core_session_get_channel(b_private->session);
if (!(b_session = switch_core_session_locate(b_private->uuid))) {
goto done;
}
b_tech_pvt = (private_object_t *) switch_core_session_get_private(b_session);
channel_b = switch_core_session_get_channel(b_session);
br_a = switch_channel_get_variable(channel_a, SWITCH_BRIDGE_VARIABLE);
br_b = switch_channel_get_variable(channel_b, SWITCH_BRIDGE_VARIABLE);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Attended Transfer [%s][%s]\n", br_a, br_b);
if (switch_test_flag(tech_pvt, TFLAG_RWLOCK)) {
switch_core_session_rwunlock(tech_pvt->session);
switch_clear_flag_locked(tech_pvt, TFLAG_RWLOCK);
}
if (switch_test_flag(tech_pvt_b, TFLAG_RWLOCK)) {
switch_core_session_rwunlock(tech_pvt_b->session);
switch_clear_flag_locked(tech_pvt_b, TFLAG_RWLOCK);
}
if (br_a && br_b) {
switch_ivr_uuid_bridge(br_a, br_b);
switch_channel_set_variable(channel_b, "endpoint_disposition", "ATTENDED_TRANSFER");
switch_set_flag_locked(tech_pvt, TFLAG_BYE);
switch_set_flag_locked(b_tech_pvt, TFLAG_BYE);
nua_notify(tech_pvt->nh, SIPTAG_CONTENT_TYPE_STR("message/sipfrag"),
SIPTAG_PAYLOAD_STR("SIP/2.0 200 OK"),
SIPTAG_EVENT_STR(etmp),
......@@ -3631,35 +3625,33 @@ static void sip_i_refer(nua_t *nua,
} else {
if (!br_a && !br_b) {
switch_set_flag_locked(tech_pvt, TFLAG_NOHUP);
switch_set_flag_locked(tech_pvt_b, TFLAG_XFER);
tech_pvt_b->xferto = switch_core_session_strdup(b_private->session, switch_core_session_get_uuid(session));
switch_set_flag_locked(b_tech_pvt, TFLAG_XFER);
b_tech_pvt->xferto = switch_core_session_strdup(b_session, switch_core_session_get_uuid(session));
} else if (!br_a && br_b) {
switch_core_session_t *bsession;
switch_core_session_t *br_b_session;
if ((bsession = switch_core_session_locate(br_b))) {
private_object_t *b_tech_pvt = switch_core_session_get_private(bsession);
switch_channel_t *b_channel = switch_core_session_get_channel(bsession);
private_object_t *bp_tech_pvt = switch_core_session_get_private(b_private->session);
if ((br_b_session = switch_core_session_locate(br_b))) {
private_object_t *br_b_tech_pvt = switch_core_session_get_private(br_b_session);
switch_channel_t *br_b_channel = switch_core_session_get_channel(br_b_session);
switch_core_session_get_uuid(b_private->session);
switch_set_flag_locked(tech_pvt, TFLAG_NOHUP);
switch_channel_clear_state_handler(b_channel, NULL);
switch_channel_set_state_flag(b_channel, CF_TRANSFER);
switch_channel_set_state(b_channel, CS_TRANSMIT);
switch_channel_clear_state_handler(br_b_channel, NULL);
switch_channel_set_state_flag(br_b_channel, CF_TRANSFER);
switch_channel_set_state(br_b_channel, CS_TRANSMIT);
switch_set_flag_locked(tech_pvt, TFLAG_REINVITE);
tech_pvt->local_sdp_audio_ip = switch_core_session_strdup(session, bp_tech_pvt->local_sdp_audio_ip);
tech_pvt->local_sdp_audio_port = bp_tech_pvt->local_sdp_audio_port;
tech_pvt->local_sdp_audio_ip = switch_core_session_strdup(session, b_tech_pvt->local_sdp_audio_ip);
tech_pvt->local_sdp_audio_port = b_tech_pvt->local_sdp_audio_port;
tech_pvt->remote_sdp_audio_ip = switch_core_session_strdup(session, b_tech_pvt->remote_sdp_audio_ip);
tech_pvt->remote_sdp_audio_port = b_tech_pvt->remote_sdp_audio_port;
tech_pvt->remote_sdp_audio_ip = switch_core_session_strdup(session, br_b_tech_pvt->remote_sdp_audio_ip);
tech_pvt->remote_sdp_audio_port = br_b_tech_pvt->remote_sdp_audio_port;
activate_rtp(tech_pvt);
b_tech_pvt->kick = switch_core_session_strdup(bsession, switch_core_session_get_uuid(session));
br_b_tech_pvt->kick = switch_core_session_strdup(br_b_session, switch_core_session_get_uuid(session));
switch_core_session_rwunlock(bsession);
switch_core_session_rwunlock(br_b_session);
}
switch_channel_hangup(channel_b, SWITCH_CAUSE_ATTENDED_TRANSFER);
......@@ -3671,20 +3663,23 @@ static void sip_i_refer(nua_t *nua,
TAG_END());
}
if (b_session) {
switch_core_session_rwunlock(b_session);
}
}
nua_handle_unref(bnh);
} else { /* the other channel is on a different box, we have to go find them */
if (exten && (br_a = switch_channel_get_variable(channel_a, SWITCH_BRIDGE_VARIABLE))) {
switch_core_session_t *asession;
switch_core_session_t *a_session;
switch_channel_t *channel = switch_core_session_get_channel(session);
if ((asession = switch_core_session_locate(br_a))) {
if ((a_session = switch_core_session_locate(br_a))) {
switch_core_session_t *tsession;
switch_call_cause_t cause = SWITCH_CAUSE_NORMAL_CLEARING;
uint32_t timeout = 60;
char *tuuid_str;
channel = switch_core_session_get_channel(asession);
channel = switch_core_session_get_channel(a_session);
exten = switch_mprintf("sofia/%s/%s@%s:%s",
profile->name,
......@@ -3695,7 +3690,7 @@ static void sip_i_refer(nua_t *nua,
switch_channel_set_variable(channel, SOFIA_REPLACES_HEADER, rep);
if (switch_ivr_originate(asession,
if (switch_ivr_originate(a_session,
&tsession,
&cause,
exten,
......@@ -3712,15 +3707,11 @@ static void sip_i_refer(nua_t *nua,
goto done;
}
switch_core_session_rwunlock(asession);
switch_core_session_rwunlock(a_session);
tuuid_str = switch_core_session_get_uuid(tsession);
switch_ivr_uuid_bridge(br_a, tuuid_str);
switch_channel_set_variable(channel_a, "endpoint_disposition", "ATTENDED_TRANSFER");
switch_set_flag_locked(tech_pvt, TFLAG_BYE);
if (switch_test_flag(tech_pvt, TFLAG_RWLOCK)) {
switch_core_session_rwunlock(tech_pvt->session);
switch_clear_flag_locked(tech_pvt, TFLAG_RWLOCK);
}
nua_notify(tech_pvt->nh, SIPTAG_CONTENT_TYPE_STR("message/sipfrag"),
SIPTAG_PAYLOAD_STR("SIP/2.0 200 OK"),
SIPTAG_EVENT_STR(etmp),
......@@ -3754,12 +3745,12 @@ static void sip_i_refer(nua_t *nua,
char *br;
if ((br = switch_channel_get_variable(channel, SWITCH_BRIDGE_VARIABLE))) {
switch_core_session_t *bsession;
switch_core_session_t *b_session;
if ((bsession = switch_core_session_locate(br))) {
if ((b_session = switch_core_session_locate(br))) {
switch_channel_set_variable(channel, "TRANSFER_FALLBACK", (char *) from->a_user);
switch_ivr_session_transfer(bsession, exten, profile->dialplan, profile->context);
switch_core_session_rwunlock(bsession);
switch_ivr_session_transfer(b_session, exten, profile->dialplan, profile->context);
switch_core_session_rwunlock(b_session);
}
switch_channel_set_variable(channel, "endpoint_disposition", "BLIND_TRANSFER");
......@@ -3770,10 +3761,6 @@ static void sip_i_refer(nua_t *nua,
SIPTAG_EVENT_STR(etmp),
TAG_END());
*/
if (switch_test_flag(tech_pvt, TFLAG_RWLOCK)) {
switch_core_session_rwunlock(tech_pvt->session);
switch_clear_flag_locked(tech_pvt, TFLAG_RWLOCK);
}
} else {
exten = switch_mprintf("sip:%s@%s:%s",
(char *) refer_to->r_url->url_user,
......@@ -3790,10 +3777,6 @@ static void sip_i_refer(nua_t *nua,
SIPTAG_EVENT_STR(etmp),
TAG_END());
*/
if (switch_test_flag(tech_pvt, TFLAG_RWLOCK)) {
switch_core_session_rwunlock(tech_pvt->session);
switch_clear_flag_locked(tech_pvt, TFLAG_RWLOCK);
}
do_xfer_invite(session);
}
......@@ -3806,7 +3789,7 @@ static void sip_i_refer(nua_t *nua,
if (etmp) {
switch_safe_free(etmp);
}
}
}
......@@ -3977,20 +3960,9 @@ static void sip_i_invite(nua_t *nua,
sip_t const *sip,
tagi_t tags[])
{
switch_core_session_t *session = sofia_private ? sofia_private->session : NULL;
switch_core_session_t *session = NULL;
char key[128] = "";
sip_unknown_t *un;
if (!session) {
if ((profile->pflags & PFLAG_AUTH_CALLS)) {
if (handle_register(nua, profile, nh, sip, REG_INVITE, key, sizeof(key))) {
return;
}
}
if ((session = switch_core_session_request(&sofia_endpoint_interface, NULL))) {
private_object_t *tech_pvt = NULL;
switch_channel_t *channel = NULL;
sip_from_t const *from = sip->sip_from;
......@@ -4005,6 +3977,18 @@ static void sip_i_invite(nua_t *nua,
char *from_port;
char uri[1024];
if ((profile->pflags & PFLAG_AUTH_CALLS)) {
if (handle_register(nua, profile, nh, sip, REG_INVITE, key, sizeof(key))) {
return;
}
}
if (!(session = switch_core_session_request(&sofia_endpoint_interface, NULL))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Session Alloc Failed!\n");
return;
}
if (!(tech_pvt = (private_object_t *) switch_core_session_alloc(session, sizeof(private_object_t)))) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Hey where is my memory pool?\n");
terminate_session(&session, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER, __LINE__);
......@@ -4069,8 +4053,6 @@ static void sip_i_invite(nua_t *nua,
}
attach_private(session, profile, tech_pvt, username);
switch_core_session_read_lock(session);
switch_set_flag(tech_pvt, TFLAG_RWLOCK);
channel = switch_core_session_get_channel(session);
switch_channel_set_variable(channel, "endpoint_disposition", "INBOUND CALL");
set_chat_hash(tech_pvt, sip);
......@@ -4218,10 +4200,9 @@ static void sip_i_invite(nua_t *nua,
abort();
}
memset(tech_pvt->sofia_private, 0, sizeof(*tech_pvt->sofia_private));
tech_pvt->sofia_private->session = session;
switch_copy_string(tech_pvt->sofia_private->uuid, switch_core_session_get_uuid(session), sizeof(tech_pvt->sofia_private->uuid));
nua_handle_bind(nh, tech_pvt->sofia_private);
}
}
}
static void sip_i_register(nua_t *nua,
......@@ -4277,13 +4258,12 @@ static void sip_r_challenge(int status,
nua_t *nua,
sofia_profile_t *profile,
nua_handle_t *nh,
sofia_private_t *sofia_private,
switch_core_session_t *session,
sip_t const *sip,
tagi_t tags[])
{
outbound_reg_t *oreg = NULL;
sip_www_authenticate_t const *authenticate = NULL;
switch_core_session_t *session = sofia_private ? sofia_private->session : NULL;
char const *realm = NULL;
char *p = NULL, *duprealm = NULL, *qrealm = NULL;
char const *scheme = NULL;
......@@ -4386,15 +4366,18 @@ static void event_callback(nua_event_t event,
{
struct private_object *tech_pvt = NULL;
auth_res_t auth_res = AUTH_FORBIDDEN;
switch_core_session_t *session = sofia_private ? sofia_private->session : NULL;
switch_core_session_t *session = NULL;
if (sofia_private) {
if (!switch_strlen_zero(sofia_private->uuid)) {
if (session) {
if (switch_core_session_read_lock(session) != SWITCH_STATUS_SUCCESS) {
if ((session = switch_core_session_locate(sofia_private->uuid))) {
tech_pvt = switch_core_session_get_private(session);
} else {
/* too late */
return;
}
tech_pvt = switch_core_session_get_private(session);
}
}
if (status != 100 && status != 200) {
......@@ -4432,122 +4415,73 @@ static void event_callback(nua_event_t event,
}
if (sip && (status == 401 || status == 407)) {
sip_r_challenge(status, phrase, nua, profile, nh, sofia_private, sip, tags);
sip_r_challenge(status, phrase, nua, profile, nh, session, sip, tags);
goto done;
}
switch (event) {
case nua_r_shutdown:
//sip_r_shutdown(status, phrase, nua, profile, nh, sofia_private, sip, tags);
break;
case nua_r_get_params:
//sip_r_get_params(status, phrase, nua, profile, nh, sofia_private, sip, tags);
break;
case nua_r_invite:
break;
case nua_r_register:
sip_r_register(status, phrase, nua, profile, nh, sofia_private, sip, tags);
break;
case nua_r_unregister:
//sip_r_unregister(status, phrase, nua, profile, nh, sofia_private, sip, tags);
break;
case nua_r_options:
//sip_r_options(status, phrase, nua, profile, nh, sofia_private, sip, tags);
break;
case nua_i_options:
sip_i_options(status, phrase, nua, profile, nh, sofia_private, sip, tags);
break;
case nua_i_fork:
//sip_i_fork(status, phrase, nua, profile, nh, sofia_private, sip, tags);
break;
case nua_i_invite:
if (!session) {
sip_i_invite(nua, profile, nh, sofia_private, sip, tags);
}
break;
case nua_i_publish:
sip_i_publish(nua, profile, nh, sofia_private, sip, tags);
break;
case nua_i_register:
sip_i_register (nua, profile, nh, sofia_private, sip, tags);
break;
case nua_i_prack:
//sip_i_prack(nua, profile, nh, sofia_private, sip, tags);
break;
case nua_i_state:
sip_i_state(status, phrase, nua, profile, nh, sofia_private, sip, tags);
break;
case nua_r_bye:
//sip_r_bye(status, phrase, nua, profile, nh, sofia_private, sip, tags);
break;
case nua_i_bye:
//sip_i_bye(nua, profile, nh, sofia_private, sip, tags);
break;
case nua_i_message:
sip_i_message(status, phrase, nua, profile, nh, sofia_private, sip, tags);
break;
case nua_r_info:
//sip_r_info(status, phrase, nua, profile, nh, sofia_private, sip, tags);
break;
case nua_i_info:
sip_i_info(nua, profile, nh, session, sip, tags);
break;
case nua_r_refer:
//sip_r_refer(status, phrase, nua, profile, nh, sofia_private, sip, tags);
break;
case nua_i_refer:
sip_i_refer(nua, profile, nh, sofia_private, sip, tags);
if (session) {
sip_i_refer(nua, profile, nh, session, sip, tags);
}
break;
case nua_r_subscribe:
sip_r_subscribe(status, phrase, nua, profile, nh, sofia_private, sip, tags);
break;
case nua_i_subscribe:
sip_i_subscribe(status, phrase, nua, profile, nh, sofia_private, sip, tags);
break;
case nua_r_unsubscribe:
//sip_r_unsubscribe(status, phrase, nua, profile, nh, sofia_private, sip, tags);
break;
case nua_r_publish:
//sip_r_publish(status, phrase, nua, profile, nh, sofia_private, sip, tags);
break;
case nua_r_message:
case nua_r_notify:
break;
case nua_i_notify:
//sip_i_notify(nua, profile, nh, sofia_private, sip, tags);
break;
case nua_i_cancel:
//sip_i_cancel(nua, profile, nh, sofia_private, sip, tags);
break;
case nua_i_error:
//sip_i_error(nua, profile, nh, sofia_private, status, phrase, tags);
break;
case nua_i_active:
case nua_i_ack:
case nua_i_terminated:
......
......@@ -68,9 +68,15 @@ struct switch_media_bug {
struct switch_media_bug *next;
};
typedef enum {
SSF_NONE = 0,
SSF_DESTROYED = (1 << 0)
} switch_session_flag_t;
struct switch_core_session {
uint32_t id;
char name[80];
switch_session_flag_t flags;
int thread_running;
switch_memory_pool_t *pool;
switch_channel_t *channel;
......@@ -567,24 +573,22 @@ SWITCH_DECLARE(char *) switch_core_get_variable(char *varname)
SWITCH_DECLARE(switch_core_session_t *) switch_core_session_locate(char *uuid_str)
{
switch_core_session_t *session;
switch_core_session_t *session = NULL;
if (uuid_str) {
switch_mutex_lock(runtime.session_table_mutex);
if ((session = switch_core_hash_find(runtime.session_table, uuid_str))) {
/* Acquire a read lock on the session */
if (switch_thread_rwlock_tryrdlock(session->rwlock) != SWITCH_STATUS_SUCCESS) {
if (switch_test_flag(session, SSF_DESTROYED) || switch_thread_rwlock_tryrdlock(session->rwlock) != SWITCH_STATUS_SUCCESS) {
/* not available, forget it */
session = NULL;
}
}
switch_mutex_unlock(runtime.session_table_mutex);
}
/* if its not NULL, now it's up to you to rwunlock this */
return session;
} else {
return NULL;
}
}
SWITCH_DECLARE(void) switch_core_session_hupall(switch_call_cause_t cause)
......@@ -3232,6 +3236,14 @@ SWITCH_DECLARE(void) switch_core_session_destroy(switch_core_session_t **session
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Close Channel %s\n", switch_channel_get_name((*session)->channel));
switch_mutex_lock(runtime.session_table_mutex);
switch_core_hash_delete(runtime.session_table, (*session)->uuid_str);
if (runtime.session_count) {
runtime.session_count--;
}
switch_set_flag((*session), SSF_DESTROYED);
switch_mutex_unlock(runtime.session_table_mutex);
if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_DESTROY) == SWITCH_STATUS_SUCCESS) {
switch_channel_event_set_data((*session)->channel, event);
switch_event_fire(&event);
......@@ -3247,11 +3259,6 @@ SWITCH_DECLARE(void) switch_core_session_destroy(switch_core_session_t **session
apr_pool_destroy(pool);
pool = NULL;
switch_mutex_lock(runtime.session_table_mutex);
if (runtime.session_count) {
runtime.session_count--;
}
switch_mutex_unlock(runtime.session_table_mutex);
}
SWITCH_DECLARE(switch_status_t) switch_core_hash_init(switch_hash_t **hash, switch_memory_pool_t *pool)
......@@ -3342,11 +3349,8 @@ static void *SWITCH_THREAD_FUNC switch_core_session_thread(switch_thread_t *thre
{
switch_core_session_t *session = obj;
session->thread = thread;
snprintf(session->name, sizeof(session->name), "%u", session->id);
switch_mutex_lock(runtime.session_table_mutex);
session->id = runtime.session_id++;
switch_core_hash_insert(runtime.session_table, session->uuid_str, session);
switch_mutex_unlock(runtime.session_table_mutex);
switch_core_session_run(session);
switch_core_media_bug_remove_all(session);
......@@ -3354,9 +3358,6 @@ static void *SWITCH_THREAD_FUNC switch_core_session_thread(switch_thread_t *thre
switch_core_session_write_lock(session);
switch_core_session_rwunlock(session);
switch_mutex_lock(runtime.session_table_mutex);
switch_core_hash_delete(runtime.session_table, session->uuid_str);
switch_mutex_unlock(runtime.session_table_mutex);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Session %u (%s) Ended\n", session->id, switch_channel_get_name(session->channel));
switch_core_session_destroy(&session);
return NULL;
......@@ -3479,9 +3480,13 @@ SWITCH_DECLARE(switch_core_session_t *) switch_core_session_request(const switch
switch_thread_cond_create(&session->cond, session->pool);
switch_thread_rwlock_create(&session->rwlock, session->pool);
snprintf(session->name, sizeof(session->name), "%u", session->id);
switch_mutex_lock(runtime.session_table_mutex);
session->id = runtime.session_id++;
switch_core_hash_insert(runtime.session_table, session->uuid_str, session);
runtime.session_count++;
switch_mutex_unlock(runtime.session_table_mutex);
return session;
}
......
......@@ -3308,12 +3308,12 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_multi_threaded_bridge(switch_core_ses
if (switch_channel_test_flag(caller_channel, CF_TRANSFER) && !switch_channel_test_flag(peer_channel, CF_TRANSFER)) {
//switch_channel_hangup(peer_channel, SWITCH_CAUSE_NORMAL_CLEARING);
switch_yield(2000000);
//switch_yield(2000000);
}
if (!switch_channel_test_flag(caller_channel, CF_TRANSFER) && switch_channel_test_flag(peer_channel, CF_TRANSFER)) {
//switch_channel_hangup(caller_channel, SWITCH_CAUSE_NORMAL_CLEARING);
switch_yield(2000000);
//switch_yield(2000000);
}
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论