From 2aebe2456f8cc4a58e948cf6ac91df9f9f8af192 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Wed, 11 Jul 2012 15:15:43 -0500 Subject: [PATCH] first pass on some new stuff --- libs/esl/src/esl_event.c | 4 + libs/esl/src/include/esl_event.h | 4 + .../libsofia-sip-ua/nua/nua_notifier.c | 10 +- src/include/switch_types.h | 5 + .../mod_conference/mod_conference.c | 521 ++++++++++++++++-- .../applications/mod_dptools/mod_dptools.c | 12 + src/mod/endpoints/mod_sofia/mod_sofia.c | 48 +- src/mod/endpoints/mod_sofia/mod_sofia.h | 7 - src/mod/endpoints/mod_sofia/sofia.c | 86 ++- src/mod/endpoints/mod_sofia/sofia_presence.c | 134 ++++- src/switch_event.c | 4 + src/switch_rtp.c | 2 +- 12 files changed, 740 insertions(+), 97 deletions(-) diff --git a/libs/esl/src/esl_event.c b/libs/esl/src/esl_event.c index 6ebd6669b6..7a0da29db3 100644 --- a/libs/esl/src/esl_event.c +++ b/libs/esl/src/esl_event.c @@ -138,6 +138,10 @@ static const char *EVENT_NAMES[] = { "SOCKET_DATA", "MEDIA_BUG_START", "MEDIA_BUG_START", + "CONFERENCE_DATA_QUERY", + "CALL_SETUP_REQ", + "CALL_SETUP_RESULT", + "CONFERENCE_DATA", "ALL" }; diff --git a/libs/esl/src/include/esl_event.h b/libs/esl/src/include/esl_event.h index b7dea736c9..1b6e6e29b4 100644 --- a/libs/esl/src/include/esl_event.h +++ b/libs/esl/src/include/esl_event.h @@ -128,6 +128,10 @@ typedef enum { ESL_EVENT_SOCKET_DATA, ESL_EVENT_MEDIA_BUG_START, ESL_EVENT_MEDIA_BUG_STOP, + ESL_EVENT_CONFERENCE_DATA_QUERY, + ESL_EVENT_CONFERENCE_DATA, + ESL_EVENT_CALL_SETUP_REQ, + ESL_EVENT_CALL_SETUP_RESULT, ESL_EVENT_ALL } esl_event_types_t; diff --git a/libs/sofia-sip/libsofia-sip-ua/nua/nua_notifier.c b/libs/sofia-sip/libsofia-sip-ua/nua/nua_notifier.c index e7d3d7470f..8ef6747aff 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nua/nua_notifier.c +++ b/libs/sofia-sip/libsofia-sip-ua/nua/nua_notifier.c @@ -1000,13 +1000,14 @@ int nua_refer_server_respond(nua_server_request_t *sr, tagi_t const *tags) static int nua_refer_server_report(nua_server_request_t *sr, tagi_t const *tags) { - nua_handle_t *nh = sr->sr_owner; + //nua_handle_t *nh = sr->sr_owner; struct notifier_usage *nu = nua_dialog_usage_private(sr->sr_usage); sip_t const *sip = sr->sr_request.sip; sip_referred_by_t *by = sip->sip_referred_by, default_by[1]; sip_event_t const *o = sr->sr_usage->du_event; enum nua_substate substate = nua_substate_terminated; - int initial = sr->sr_initial, retval; + //int initial = sr->sr_initial, retval; + int retval; if (nu) { if (!sr->sr_terminating) @@ -1029,13 +1030,14 @@ int nua_refer_server_report(nua_server_request_t *sr, tagi_t const *tags) if (retval >= 2 || nu == NULL) return retval; +#if 0 if (initial) nua_stack_post_signal(nh, nua_r_notify, SIPTAG_EVENT(o), SIPTAG_CONTENT_TYPE_STR("message/sipfrag"), SIPTAG_PAYLOAD_STR("SIP/2.0 100 Trying\r\n"), - TAG_END()); - + TAG_END()); +#endif return retval; } diff --git a/src/include/switch_types.h b/src/include/switch_types.h index 08b6c61954..6dc6118fe9 100644 --- a/src/include/switch_types.h +++ b/src/include/switch_types.h @@ -1233,6 +1233,7 @@ typedef enum { CF_PICKUP, CF_CONFIRM_BLIND_TRANSFER, CF_NO_PRESENCE, + CF_CONFERENCE, /* WARNING: DO NOT ADD ANY FLAGS BELOW THIS LINE */ /* IF YOU ADD NEW ONES CHECK IF THEY SHOULD PERSIST OR ZERO THEM IN switch_core_session.c switch_core_session_request_xml() */ CF_FLAG_MAX @@ -1654,6 +1655,10 @@ typedef enum { SWITCH_EVENT_SOCKET_DATA, SWITCH_EVENT_MEDIA_BUG_START, SWITCH_EVENT_MEDIA_BUG_STOP, + SWITCH_EVENT_CONFERENCE_DATA_QUERY, + SWITCH_EVENT_CONFERENCE_DATA, + SWITCH_EVENT_CALL_SETUP_REQ, + SWITCH_EVENT_CALL_SETUP_RESULT, SWITCH_EVENT_ALL } switch_event_types_t; diff --git a/src/mod/applications/mod_conference/mod_conference.c b/src/mod/applications/mod_conference/mod_conference.c index 68acd3ad70..151084e44a 100644 --- a/src/mod/applications/mod_conference/mod_conference.c +++ b/src/mod/applications/mod_conference/mod_conference.c @@ -43,30 +43,6 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_conference_load); SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_conference_shutdown); SWITCH_MODULE_DEFINITION(mod_conference, mod_conference_load, mod_conference_shutdown, NULL); -typedef struct conference_cdr_node_s { - switch_caller_profile_t *cp; - char *record_path; - switch_time_t join_time; - switch_time_t leave_time; - uint32_t flags; - struct conference_cdr_node_s *next; -} conference_cdr_node_t; - -typedef enum { - CDRR_LOCKED = 1, - CDRR_PIN, - CDRR_MAXMEMBERS -} cdr_reject_reason_t; - -typedef struct conference_cdr_reject_s { - switch_caller_profile_t *cp; - switch_time_t reject_time; - cdr_reject_reason_t reason; - struct conference_cdr_reject_s *next; -} conference_cdr_reject_t; - - - typedef enum { CONF_SILENT_REQ = (1 << 0), CONF_SILENT_DONE = (1 << 1) @@ -121,13 +97,40 @@ static struct { uint32_t id_pool; int32_t running; uint32_t threads; - switch_event_node_t *node; } globals; /* forward declaration for conference_obj and caller_control */ struct conference_member; typedef struct conference_member conference_member_t; + +typedef struct conference_cdr_node_s { + switch_caller_profile_t *cp; + char *record_path; + switch_time_t join_time; + switch_time_t leave_time; + uint32_t flags; + uint32_t id; + conference_member_t *member; + struct conference_cdr_node_s *next; +} conference_cdr_node_t; + +typedef enum { + CDRR_LOCKED = 1, + CDRR_PIN, + CDRR_MAXMEMBERS +} cdr_reject_reason_t; + +typedef struct conference_cdr_reject_s { + switch_caller_profile_t *cp; + switch_time_t reject_time; + cdr_reject_reason_t reason; + struct conference_cdr_reject_s *next; +} conference_cdr_reject_t; + + + + struct call_list { char *string; int iteration; @@ -190,7 +193,8 @@ typedef enum { CFLAG_ENTER_SOUND = (1 << 13), CFLAG_VIDEO_BRIDGE = (1 << 14), CFLAG_AUDIO_ALWAYS = (1 << 15), - CFLAG_ENDCONF_FORCED = (1 << 16) + CFLAG_ENDCONF_FORCED = (1 << 16), + CFLAG_RFC4579 = (1 << 17) } conf_flag_t; typedef enum { @@ -263,6 +267,7 @@ struct vid_helper { /* Conference Object */ typedef struct conference_obj { char *name; + char *desc; char *timer_name; char *tts_engine; char *tts_voice; @@ -288,6 +293,7 @@ typedef struct conference_obj { char *record_filename; uint32_t terminate_on_silence; uint32_t max_members; + uint32_t doc_version; char *maxmember_sound; uint32_t announce_count; char *pin; @@ -476,11 +482,11 @@ static switch_status_t conference_outcall(conference_obj_t *conference, char *cid_num, char *profile, switch_call_cause_t *cause, - switch_call_cause_t *cancel_cause); + switch_call_cause_t *cancel_cause, switch_event_t *var_event); static switch_status_t conference_outcall_bg(conference_obj_t *conference, char *conference_name, switch_core_session_t *session, char *bridgeto, uint32_t timeout, const char *flags, const char *cid_name, - const char *cid_num, const char *call_uuid, const char *profile, switch_call_cause_t *cancel_cause); + const char *cid_num, const char *call_uuid, const char *profile, switch_call_cause_t *cancel_cause, switch_event_t **var_event); SWITCH_STANDARD_APP(conference_function); static void launch_conference_thread(conference_obj_t *conference); static void launch_conference_video_thread(conference_obj_t *conference); @@ -522,6 +528,7 @@ static void conference_cdr_del(conference_member_t *member) { member->cdr_node->leave_time = switch_epoch_time_now(NULL); member->cdr_node->flags = member->flags; + member->cdr_node->member = NULL; } static void conference_cdr_add(conference_member_t *member) @@ -535,6 +542,7 @@ static void conference_cdr_add(conference_member_t *member) np->next = member->conference->cdr_nodes; member->conference->cdr_nodes = member->cdr_node = np; member->cdr_node->join_time = switch_epoch_time_now(NULL); + member->cdr_node->member = member; if (!member->session) { member->cdr_node->record_path = switch_core_strdup(member->conference->pool, member->rec_path); @@ -548,6 +556,11 @@ static void conference_cdr_add(conference_member_t *member) } member->cdr_node->cp = switch_caller_profile_dup(member->conference->pool, cp); + + member->cdr_node->id = member->id; + + + } static void conference_cdr_rejected(conference_obj_t *conference, switch_channel_t *channel, cdr_reject_reason_t reason) @@ -569,6 +582,246 @@ static void conference_cdr_rejected(conference_obj_t *conference, switch_channel rp->cp = switch_caller_profile_dup(conference->pool, cp); } +static char *conference_rfc4579_render(conference_obj_t *conference, switch_event_t *event) +{ + switch_xml_t xml, x_tag, x_tag1, x_tag2, x_tag3, x_tag4; + char tmp[30]; + const char *domain; const char *name; + char *dup_domain = NULL; + char *uri; + int off = 0, off1 = 0, off2 = 0, off3 = 0, off4 = 0; + conference_cdr_node_t *np; + char *tmpp = tmp; + char *xml_text = NULL; + + if (!(xml = switch_xml_new("conference-info"))) { + abort(); + } + + switch_mutex_lock(conference->mutex); + switch_snprintf(tmp, sizeof(tmp), "%u", conference->doc_version); + conference->doc_version++; + switch_mutex_unlock(conference->mutex); + + if (!event || !(name = switch_event_get_header(event, "conference-name"))) { + if (!(name = conference->name)) { + name = "conference"; + } + } + + if (!event || !(domain = switch_event_get_header(event, "conference-domain"))) { + if (!(domain = conference->domain)) { + dup_domain = switch_core_get_variable_dup("domain"); + if (!(domain = dup_domain)) { + domain = "cluecon.com"; + } + } + } + + switch_xml_set_attr_d(xml, "version", tmpp); + + switch_xml_set_attr_d(xml, "state", "full"); + switch_xml_set_attr_d(xml, "xmlns", "urn:ietf:params:xml:ns:conference-info"); + + + uri = switch_mprintf("sip:%s@%s", name, domain); + switch_xml_set_attr_d(xml, "entity", uri); + + if (!(x_tag = switch_xml_add_child_d(xml, "conference-description", off++))) { + abort(); + } + + if (!(x_tag1 = switch_xml_add_child_d(x_tag, "display-text", off1++))) { + abort(); + } + switch_xml_set_txt_d(x_tag1, conference->desc ? conference->desc : "FreeSWITCH Conference"); + + + if (!(x_tag1 = switch_xml_add_child_d(x_tag, "conf-uris", off1++))) { + abort(); + } + + if (!(x_tag2 = switch_xml_add_child_d(x_tag1, "entry", off2++))) { + abort(); + } + + if (!(x_tag3 = switch_xml_add_child_d(x_tag2, "uri", off3++))) { + abort(); + } + switch_xml_set_txt_d(x_tag3, uri); + + + + if (!(x_tag = switch_xml_add_child_d(xml, "conference-state", off++))) { + abort(); + } + if (!(x_tag1 = switch_xml_add_child_d(x_tag, "user-count", off1++))) { + abort(); + } + switch_snprintf(tmp, sizeof(tmp), "%u", conference->count); + switch_xml_set_txt_d(x_tag1, tmpp); + + if (!(x_tag1 = switch_xml_add_child_d(x_tag, "active", off1++))) { + abort(); + } + switch_xml_set_txt_d(x_tag1, "true"); + + off1 = off2 = off3 = off4 = 0; + + if (!(x_tag = switch_xml_add_child_d(xml, "users", off++))) { + abort(); + } + + switch_mutex_lock(conference->member_mutex); + + for (np = conference->cdr_nodes; np; np = np->next) { + char *user_uri; + + if (!np->cp || (np->member && !np->member->session) || np->leave_time) { /* for now we'll remove participants when the leave */ + continue; + } + + if (!(x_tag1 = switch_xml_add_child_d(x_tag, "user", off1++))) { + abort(); + } + + user_uri = switch_mprintf("sip:%s@%s", np->cp->caller_id_number, domain); + + + switch_xml_set_attr_d(x_tag1, "state", "full"); + switch_xml_set_attr_d(x_tag1, "entity", user_uri); + + if (!(x_tag2 = switch_xml_add_child_d(x_tag1, "display-text", off2++))) { + abort(); + } + switch_xml_set_txt_d(x_tag2, np->cp->caller_id_name); + + + if (!(x_tag2 = switch_xml_add_child_d(x_tag1, "endpoint", off2++))) { + abort(); + } + switch_xml_set_attr_d(x_tag2, "entity", user_uri); + + + if (!(x_tag3 = switch_xml_add_child_d(x_tag2, "display-text", off3++))) { + abort(); + } + switch_xml_set_txt_d(x_tag3, np->cp->caller_id_name); + + + if (!(x_tag3 = switch_xml_add_child_d(x_tag2, "status", off3++))) { + abort(); + } + switch_xml_set_txt_d(x_tag3, np->leave_time ? "disconnected" : "connected"); + + + if (!(x_tag3 = switch_xml_add_child_d(x_tag2, "joining-info", off3++))) { + abort(); + } + if (!(x_tag4 = switch_xml_add_child_d(x_tag3, "when", off4++))) { + abort(); + } else { + switch_time_exp_t tm; + switch_size_t retsize; + const char *fmt = "%Y-%m-%dT%H:%M:%S%z"; + char *p; + + switch_time_exp_lt(&tm, (switch_time_t) conference->start_time * 1000000); + switch_strftime_nocheck(tmp, &retsize, sizeof(tmp), fmt, &tm); + p = end_of_p(tmpp) -1; + snprintf(p, 4, ":00"); + + + switch_xml_set_txt_d(x_tag4, tmpp); + } + + + + + /** ok so this is in the rfc but not the xsd + if (!(x_tag3 = switch_xml_add_child_d(x_tag2, "joining-method", off3++))) { + abort(); + } + switch_xml_set_txt_d(x_tag3, np->cp->direction == SWITCH_CALL_DIRECTION_INBOUND ? "dialed-in" : "dialed-out"); + */ + + if (np->member) { + switch_channel_t *channel = switch_core_session_get_channel(np->member->session); + const char *var; + + if (!(x_tag3 = switch_xml_add_child_d(x_tag2, "media", off3++))) { + abort(); + } + + snprintf(tmp, sizeof(tmp), "%ua", np->member->id); + switch_xml_set_attr_d(x_tag3, "id", tmpp); + + + if (!(x_tag4 = switch_xml_add_child_d(x_tag3, "type", off4++))) { + abort(); + } + switch_xml_set_txt_d(x_tag4, "audio"); + + if ((var = switch_channel_get_variable(channel, "rtp_use_ssrc"))) { + if (!(x_tag4 = switch_xml_add_child_d(x_tag3, "src-id", off4++))) { + abort(); + } + switch_xml_set_txt_d(x_tag4, var); + } + + if (!(x_tag4 = switch_xml_add_child_d(x_tag3, "status", off4++))) { + abort(); + } + switch_xml_set_txt_d(x_tag4, switch_channel_test_flag(channel, CF_HOLD) ? "sendonly" : "sendrecv"); + + + if (switch_channel_test_flag(channel, CF_VIDEO)) { + off4 = 0; + + if (!(x_tag3 = switch_xml_add_child_d(x_tag2, "media", off3++))) { + abort(); + } + + snprintf(tmp, sizeof(tmp), "%uv", np->member->id); + switch_xml_set_attr_d(x_tag3, "id", tmpp); + + + if (!(x_tag4 = switch_xml_add_child_d(x_tag3, "type", off4++))) { + abort(); + } + switch_xml_set_txt_d(x_tag4, "video"); + + if ((var = switch_channel_get_variable(channel, "rtp_use_video_ssrc"))) { + if (!(x_tag4 = switch_xml_add_child_d(x_tag3, "src-id", off4++))) { + abort(); + } + switch_xml_set_txt_d(x_tag4, var); + } + + if (!(x_tag4 = switch_xml_add_child_d(x_tag3, "status", off4++))) { + abort(); + } + switch_xml_set_txt_d(x_tag4, switch_channel_test_flag(channel, CF_HOLD) ? "sendonly" : "sendrecv"); + + } + } + + switch_safe_free(user_uri); + } + + switch_mutex_unlock(conference->member_mutex); + + off1 = off2 = off3 = off4 = 0; + + xml_text = switch_xml_toxml(xml, SWITCH_TRUE); + switch_xml_free(xml); + + switch_safe_free(dup_domain); + switch_safe_free(uri); + + return xml_text; +} + static void conference_cdr_render(conference_obj_t *conference) { switch_xml_t cdr, x_ptr, x_member, x_members, x_conference, x_cp, x_flags, x_tag, x_rejected, x_attempt; @@ -966,6 +1219,45 @@ static switch_status_t member_del_relationship(conference_member_t *member, uint return status; } +static void send_rfc_event(conference_obj_t *conference) +{ + switch_event_t *event; + char *body; + char *name = NULL, *domain = NULL, *dup_domain = NULL; + + if (!switch_test_flag(conference, CFLAG_RFC4579)) { + return; + } + + if (!(name = conference->name)) { + name = "conference"; + } + + if (!(domain = conference->domain)) { + dup_domain = switch_core_get_variable_dup("domain"); + if (!(domain = dup_domain)) { + domain = "cluecon.com"; + } + } + + + if (switch_event_create(&event, SWITCH_EVENT_CONFERENCE_DATA) == SWITCH_STATUS_SUCCESS) { + event->flags |= EF_UNIQ_HEADERS; + + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "conference-name", name); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "conference-domain", domain); + + body = conference_rfc4579_render(conference, NULL); + switch_event_add_body(event, body); + free(body); + switch_event_fire(&event); + } + + switch_safe_free(dup_domain); + +} + + /* Gain exclusive access and add the member to the list */ static switch_status_t conference_add_member(conference_obj_t *conference, conference_member_t *member) { @@ -1109,9 +1401,14 @@ static switch_status_t conference_add_member(conference_obj_t *conference, confe switch_mutex_unlock(member->audio_out_mutex); switch_mutex_unlock(member->audio_in_mutex); + send_rfc_event(conference); + switch_mutex_unlock(conference->mutex); status = SWITCH_STATUS_SUCCESS; + + + return status; } @@ -1248,6 +1545,11 @@ static switch_status_t conference_del_member(conference_obj_t *conference, confe unlock_member(member); switch_mutex_unlock(member->audio_out_mutex); switch_mutex_unlock(member->audio_in_mutex); + + + send_rfc_event(conference); + + switch_mutex_unlock(conference->mutex); status = SWITCH_STATUS_SUCCESS; @@ -3089,7 +3391,7 @@ static void conference_loop_output(conference_member_t *member) char *dial_str = switch_mprintf("%s%s", switch_str_nil(prefix), argv[x]); switch_assert(dial_str); conference_outcall_bg(member->conference, NULL, NULL, dial_str, to, switch_str_nil(flags), cid_name, cid_num, NULL, - profile, &member->conference->cancel_cause); + profile, &member->conference->cancel_cause, NULL); switch_safe_free(dial_str); } switch_safe_free(cpstr); @@ -5229,9 +5531,9 @@ static switch_status_t conf_api_sub_dial(conference_obj_t *conference, switch_st } if (conference) { - conference_outcall(conference, NULL, NULL, argv[2], 60, NULL, argv[4], argv[3], NULL, &cause, NULL); + conference_outcall(conference, NULL, NULL, argv[2], 60, NULL, argv[4], argv[3], NULL, &cause, NULL, NULL); } else { - conference_outcall(NULL, argv[0], NULL, argv[2], 60, NULL, argv[4], argv[3], NULL, &cause, NULL); + conference_outcall(NULL, argv[0], NULL, argv[2], 60, NULL, argv[4], argv[3], NULL, &cause, NULL, NULL); } stream->write_function(stream, "Call Requested: result: [%s]\n", switch_channel_cause2str(cause)); @@ -5254,9 +5556,9 @@ static switch_status_t conf_api_sub_bgdial(conference_obj_t *conference, switch_ switch_uuid_format(uuid_str, &uuid); if (conference) { - conference_outcall_bg(conference, NULL, NULL, argv[2], 60, NULL, argv[4], argv[3], uuid_str, NULL, NULL); + conference_outcall_bg(conference, NULL, NULL, argv[2], 60, NULL, argv[4], argv[3], uuid_str, NULL, NULL, NULL); } else { - conference_outcall_bg(NULL, argv[0], NULL, argv[2], 60, NULL, argv[4], argv[3], uuid_str, NULL, NULL); + conference_outcall_bg(NULL, argv[0], NULL, argv[2], 60, NULL, argv[4], argv[3], uuid_str, NULL, NULL, NULL); } stream->write_function(stream, "OK Job-UUID: %s\n", uuid_str); @@ -5777,7 +6079,7 @@ static switch_status_t conference_outcall(conference_obj_t *conference, char *cid_num, char *profile, switch_call_cause_t *cause, - switch_call_cause_t *cancel_cause) + switch_call_cause_t *cancel_cause, switch_event_t *var_event) { switch_core_session_t *peer_session = NULL; switch_channel_t *peer_channel; @@ -5792,7 +6094,7 @@ static switch_status_t conference_outcall(conference_obj_t *conference, if (conference == NULL) { char *dialstr = switch_mprintf("{ignore_early_media=true}%s", bridgeto); - status = switch_ivr_originate(NULL, &peer_session, cause, dialstr, 60, NULL, cid_name, cid_num, NULL, NULL, SOF_NO_LIMITS, NULL); + status = switch_ivr_originate(NULL, &peer_session, cause, dialstr, 60, NULL, cid_name, cid_num, NULL, var_event, SOF_NO_LIMITS, NULL); switch_safe_free(dialstr); if (status != SWITCH_STATUS_SUCCESS) { @@ -5828,7 +6130,7 @@ static switch_status_t conference_outcall(conference_obj_t *conference, switch_mutex_lock(conference->mutex); conference->originating++; switch_mutex_unlock(conference->mutex); - status = switch_ivr_originate(session, &peer_session, cause, bridgeto, timeout, NULL, cid_name, cid_num, NULL, NULL, SOF_NO_LIMITS, cancel_cause); + status = switch_ivr_originate(session, &peer_session, cause, bridgeto, timeout, NULL, cid_name, cid_num, NULL, var_event, SOF_NO_LIMITS, cancel_cause); switch_mutex_lock(conference->mutex); conference->originating--; switch_mutex_unlock(conference->mutex); @@ -5920,6 +6222,7 @@ struct bg_call { char *uuid; char *profile; switch_call_cause_t *cancel_cause; + switch_event_t *var_event; switch_memory_pool_t *pool; }; @@ -5931,8 +6234,10 @@ static void *SWITCH_THREAD_FUNC conference_outcall_run(switch_thread_t *thread, switch_call_cause_t cause; switch_event_t *event; + conference_outcall(call->conference, call->conference_name, - call->session, call->bridgeto, call->timeout, call->flags, call->cid_name, call->cid_num, call->profile, &cause, call->cancel_cause); + call->session, call->bridgeto, call->timeout, + call->flags, call->cid_name, call->cid_num, call->profile, &cause, call->cancel_cause, call->var_event); if (call->conference && test_eflag(call->conference, EFLAG_BGDIAL_RESULT) && switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CONF_EVENT_MAINT) == SWITCH_STATUS_SUCCESS) { @@ -5942,6 +6247,11 @@ static void *SWITCH_THREAD_FUNC conference_outcall_run(switch_thread_t *thread, switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Job-UUID", call->uuid); switch_event_fire(&event); } + + if (call->var_event) { + switch_event_destroy(&call->var_event); + } + switch_safe_free(call->bridgeto); switch_safe_free(call->flags); switch_safe_free(call->cid_name); @@ -5961,7 +6271,7 @@ static void *SWITCH_THREAD_FUNC conference_outcall_run(switch_thread_t *thread, static switch_status_t conference_outcall_bg(conference_obj_t *conference, char *conference_name, switch_core_session_t *session, char *bridgeto, uint32_t timeout, const char *flags, const char *cid_name, - const char *cid_num, const char *call_uuid, const char *profile, switch_call_cause_t *cancel_cause) + const char *cid_num, const char *call_uuid, const char *profile, switch_call_cause_t *cancel_cause, switch_event_t **var_event) { struct bg_call *call = NULL; switch_thread_t *thread; @@ -5977,6 +6287,11 @@ static switch_status_t conference_outcall_bg(conference_obj_t *conference, call->timeout = timeout; call->cancel_cause = cancel_cause; + if (var_event) { + call->var_event = *var_event; + var_event = NULL; + } + if (conference) { pool = conference->pool; } else { @@ -6152,7 +6467,11 @@ static void set_cflags(const char *flags, uint32_t *f) *f |= CFLAG_VIDEO_BRIDGE; } else if (!strcasecmp(argv[i], "audio-always")) { *f |= CFLAG_AUDIO_ALWAYS; + } else if (!strcasecmp(argv[i], "rfc-4579")) { + *f |= CFLAG_RFC4579; } + + } free(dup); @@ -6403,30 +6722,34 @@ SWITCH_STANDARD_APP(conference_function) switch_channel_set_app_flag_key("conf_silent", channel, CONF_SILENT_REQ); } + switch_channel_set_flag(channel, CF_CONFERENCE); + if (switch_channel_answer(channel) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Channel answer failed.\n"); - return; + goto end; } /* Save the original read codec. */ if (!(read_codec = switch_core_session_get_read_codec(session))) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Channel has no media!\n"); - return; + goto end; } if (zstr(data)) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Invalid arguments\n"); - return; + goto end; } mydata = switch_core_session_strdup(session, data); if (!mydata) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Pool Failure\n"); - return; + goto end; } + + if ((flags_str = strstr(mydata, flags_prefix))) { char *p; *((char *) flags_str) = '\0'; @@ -6764,7 +7087,7 @@ SWITCH_STANDARD_APP(conference_function) /* if we're using "bridge:" make an outbound call and bridge it in */ if (!zstr(bridgeto) && strcasecmp(bridgeto, "none")) { switch_call_cause_t cause; - if (conference_outcall(conference, NULL, session, bridgeto, 60, NULL, NULL, NULL, NULL, &cause, NULL) != SWITCH_STATUS_SUCCESS) { + if (conference_outcall(conference, NULL, session, bridgeto, 60, NULL, NULL, NULL, NULL, &cause, NULL, NULL) != SWITCH_STATUS_SUCCESS) { goto done; } } else { @@ -6913,6 +7236,11 @@ SWITCH_STANDARD_APP(conference_function) } switch_channel_set_variable(channel, "last_transfered_conference", NULL); + + end: + + switch_channel_clear_flag(channel, CF_CONFERENCE); + } /* Create a thread for the conference and launch it */ @@ -7123,6 +7451,7 @@ static conference_obj_t *conference_new(char *name, conf_xml_cfg_t cfg, switch_c switch_xml_t xml_kvp; char *timer_name = NULL; char *domain = NULL; + char *desc = NULL; char *name_domain = NULL; char *tts_engine = NULL; char *tts_voice = NULL; @@ -7246,6 +7575,8 @@ static conference_obj_t *conference_new(char *name, conf_xml_cfg_t cfg, switch_c } } else if (!strcasecmp(var, "domain") && !zstr(val)) { domain = val; + } else if (!strcasecmp(var, "description") && !zstr(val)) { + desc = val; } else if (!force_interval_i && !strcasecmp(var, "interval") && !zstr(val)) { uint32_t tmp = atoi(val); @@ -7606,6 +7937,11 @@ static conference_obj_t *conference_new(char *name, conf_xml_cfg_t cfg, switch_c if (!zstr(auto_record)) { conference->auto_record = switch_core_strdup(conference->pool, auto_record); } + + if (!zstr(desc)) { + conference->desc = switch_core_strdup(conference->pool, desc); + } + if (!zstr(terminate_on_silence)) { conference->terminate_on_silence = atoi(terminate_on_silence); } @@ -7681,6 +8017,89 @@ static void conference_send_presence(conference_obj_t *conference) } +static void call_setup_event_handler(switch_event_t *event) +{ + char *conf; + char *dial_str; + char *action; + conference_obj_t *conference = NULL; + + if (!switch_test_flag(conference, CFLAG_RFC4579)) { + return; + } + + conf = switch_event_get_header(event, "Target-Component"); + dial_str = switch_event_get_header(event, "Request-Target"); + action = switch_event_get_header(event, "Request-Action"); + + + if (!zstr(conf) && !zstr(dial_str) && !zstr(action) && (conference = conference_find(conf))) { + switch_event_t *var_event; + switch_event_header_t *hp; + + if (!strcasecmp(action, "call")) { + + if (switch_event_create_plain(&var_event, SWITCH_EVENT_CHANNEL_DATA) != SWITCH_STATUS_SUCCESS) { + abort(); + } + + for(hp = event->headers; hp; hp = hp->next) { + if (!strncasecmp(hp->name, "var_", 4)) { + switch_event_add_header(var_event, SWITCH_STACK_BOTTOM, hp->name + 4, hp->value); + } + } + + switch_event_add_header(var_event, SWITCH_STACK_BOTTOM, "conference_dial_str", dial_str); + + conference_outcall_bg(conference, NULL, NULL, dial_str, 60, NULL, NULL, NULL, NULL, NULL, NULL, &var_event); + + } else if (!strcasecmp(action, "end")) { + switch_core_session_hupall_matching_var("conference_dial_str", dial_str, SWITCH_CAUSE_NORMAL_CLEARING); + } + + switch_thread_rwlock_unlock(conference->rwlock); + } + +} + +static void conf_data_event_handler(switch_event_t *event) +{ + switch_event_t *revent; + char *name = switch_event_get_header(event, "conference-name"); + conference_obj_t *conference = NULL; + char *body = NULL; + + switch_event_dup(&revent, event); + revent->event_id = SWITCH_EVENT_CONFERENCE_DATA; + revent->flags |= EF_UNIQ_HEADERS; + switch_event_add_header(revent, SWITCH_STACK_TOP, "Event-Name", "CONFERENCE_DATA"); + + if (!zstr(name) && (conference = conference_find(name))) { + if (switch_test_flag(conference, CFLAG_RFC4579)) { + body = conference_rfc4579_render(conference, event); + } + switch_thread_rwlock_unlock(conference->rwlock); + + } + + if (!body) { + char *domain = switch_event_get_header(event, "conference-domain"); + + if (zstr(domain)) { + domain = "cluecon.com"; + } + + body = switch_mprintf("\n", name, domain); + switch_event_add_header(revent, SWITCH_STACK_BOTTOM, "notfound", "true"); + } + + switch_event_add_body(revent, body); + + switch_event_fire(&revent); + switch_safe_free(body); +} + static void pres_event_handler(switch_event_t *event) { @@ -7997,10 +8416,16 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_conference_load) switch_mutex_init(&globals.setup_mutex, SWITCH_MUTEX_NESTED, globals.conference_pool); /* Subscribe to presence request events */ - if (switch_event_bind_removable(modname, SWITCH_EVENT_PRESENCE_PROBE, SWITCH_EVENT_SUBCLASS_ANY, pres_event_handler, NULL, &globals.node) != - SWITCH_STATUS_SUCCESS) { + if (switch_event_bind(modname, SWITCH_EVENT_PRESENCE_PROBE, SWITCH_EVENT_SUBCLASS_ANY, pres_event_handler, NULL) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't subscribe to presence request events!\n"); - return SWITCH_STATUS_GENERR; + } + + if (switch_event_bind(modname, SWITCH_EVENT_CONFERENCE_DATA_QUERY, SWITCH_EVENT_SUBCLASS_ANY, conf_data_event_handler, NULL) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't subscribe to conference data query events!\n"); + } + + if (switch_event_bind(modname, SWITCH_EVENT_CALL_SETUP_REQ, SWITCH_EVENT_SUBCLASS_ANY, call_setup_event_handler, NULL) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't subscribe to conference data query events!\n"); } SWITCH_ADD_API(api_interface, "conference", "Conference module commands", conf_api_main, p); @@ -8031,7 +8456,9 @@ SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_conference_shutdown) switch_yield(100000); } - switch_event_unbind(&globals.node); + switch_event_unbind_callback(pres_event_handler); + switch_event_unbind_callback(conf_data_event_handler); + switch_event_unbind_callback(call_setup_event_handler); switch_event_free_subclass(CONF_EVENT_MAINT); /* free api interface help ".syntax" field string */ diff --git a/src/mod/applications/mod_dptools/mod_dptools.c b/src/mod/applications/mod_dptools/mod_dptools.c index 0937b37c3c..80543033e0 100755 --- a/src/mod/applications/mod_dptools/mod_dptools.c +++ b/src/mod/applications/mod_dptools/mod_dptools.c @@ -1145,6 +1145,18 @@ SWITCH_STANDARD_APP(set_name_function) SWITCH_STANDARD_APP(answer_function) { switch_channel_t *channel = switch_core_session_get_channel(session); + const char *arg = (char *) data; + + if (zstr(arg)) { + arg = switch_channel_get_variable(channel, "answer_flags"); + } + + if (!zstr(arg)) { + if (!switch_stristr("is_conference", arg)) { + switch_channel_set_flag(channel, CF_CONFERENCE); + } + } + switch_channel_answer(channel); } diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.c b/src/mod/endpoints/mod_sofia/mod_sofia.c index d5faa8e3c9..b2c47d97d3 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.c +++ b/src/mod/endpoints/mod_sofia/mod_sofia.c @@ -665,7 +665,10 @@ static switch_status_t sofia_answer_channel(switch_core_session_t *session) int is_3pcc = 0; char *sticky = NULL; const char *call_info = switch_channel_get_variable(channel, "presence_call_info_full"); - + + if (switch_channel_test_flag(channel, CF_CONFERENCE)) { + tech_pvt->reply_contact = switch_core_session_sprintf(session, "%s;isfocus", tech_pvt->reply_contact); + } if(sofia_test_flag(tech_pvt, TFLAG_3PCC_INVITE)) { // SNARK: complete hack to get final ack sent when a 3pcc invite has been passed from the other leg in bypass_media mode. @@ -5554,44 +5557,48 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_sofia_load) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Waiting for profiles to start\n"); switch_yield(1500000); - if (switch_event_bind_removable(modname, SWITCH_EVENT_CUSTOM, MULTICAST_EVENT, event_handler, NULL, - &mod_sofia_globals.custom_node) != SWITCH_STATUS_SUCCESS) { + if (switch_event_bind(modname, SWITCH_EVENT_CUSTOM, MULTICAST_EVENT, event_handler, NULL) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind!\n"); return SWITCH_STATUS_TERM; } - if (switch_event_bind_removable(modname, SWITCH_EVENT_PRESENCE_IN, SWITCH_EVENT_SUBCLASS_ANY, sofia_presence_event_handler, NULL, - &mod_sofia_globals.in_node) != SWITCH_STATUS_SUCCESS) { + if (switch_event_bind(modname, SWITCH_EVENT_CONFERENCE_DATA, SWITCH_EVENT_SUBCLASS_ANY, sofia_presence_event_handler, NULL) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind!\n"); return SWITCH_STATUS_GENERR; } - if (switch_event_bind_removable(modname, SWITCH_EVENT_PRESENCE_OUT, SWITCH_EVENT_SUBCLASS_ANY, sofia_presence_event_handler, NULL, - &mod_sofia_globals.out_node) != SWITCH_STATUS_SUCCESS) { + if (switch_event_bind(modname, SWITCH_EVENT_PRESENCE_IN, SWITCH_EVENT_SUBCLASS_ANY, sofia_presence_event_handler, NULL) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind!\n"); return SWITCH_STATUS_GENERR; } - if (switch_event_bind_removable(modname, SWITCH_EVENT_PRESENCE_PROBE, SWITCH_EVENT_SUBCLASS_ANY, sofia_presence_event_handler, NULL, - &mod_sofia_globals.probe_node) != SWITCH_STATUS_SUCCESS) { + if (switch_event_bind(modname, SWITCH_EVENT_PRESENCE_OUT, SWITCH_EVENT_SUBCLASS_ANY, sofia_presence_event_handler, NULL) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind!\n"); return SWITCH_STATUS_GENERR; } - if (switch_event_bind_removable(modname, SWITCH_EVENT_ROSTER, SWITCH_EVENT_SUBCLASS_ANY, sofia_presence_event_handler, NULL, - &mod_sofia_globals.roster_node) != SWITCH_STATUS_SUCCESS) { + if (switch_event_bind(modname, SWITCH_EVENT_PRESENCE_PROBE, SWITCH_EVENT_SUBCLASS_ANY, sofia_presence_event_handler, NULL) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind!\n"); return SWITCH_STATUS_GENERR; } - if (switch_event_bind_removable(modname, SWITCH_EVENT_MESSAGE_WAITING, SWITCH_EVENT_SUBCLASS_ANY, sofia_presence_mwi_event_handler, NULL, - &mod_sofia_globals.mwi_node) != SWITCH_STATUS_SUCCESS) { + if (switch_event_bind(modname, SWITCH_EVENT_ROSTER, SWITCH_EVENT_SUBCLASS_ANY, sofia_presence_event_handler, NULL) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind!\n"); return SWITCH_STATUS_GENERR; } - if (switch_event_bind_removable(modname, SWITCH_EVENT_CUSTOM, MY_EVENT_RECOVERY, sofia_glue_track_event_handler, NULL, - &mod_sofia_globals.recovery_node) != SWITCH_STATUS_SUCCESS) { + if (switch_event_bind(modname, SWITCH_EVENT_MESSAGE_WAITING, SWITCH_EVENT_SUBCLASS_ANY, sofia_presence_mwi_event_handler, NULL) != SWITCH_STATUS_SUCCESS) { + + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind!\n"); + return SWITCH_STATUS_GENERR; + } + + if (switch_event_bind(modname, SWITCH_EVENT_CUSTOM, MY_EVENT_RECOVERY, sofia_glue_track_event_handler, NULL) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind!\n"); return SWITCH_STATUS_GENERR; } @@ -5709,14 +5716,11 @@ SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_sofia_shutdown) } switch_mutex_unlock(mod_sofia_globals.mutex); - switch_event_unbind(&mod_sofia_globals.in_node); - switch_event_unbind(&mod_sofia_globals.probe_node); - switch_event_unbind(&mod_sofia_globals.out_node); - switch_event_unbind(&mod_sofia_globals.roster_node); - switch_event_unbind(&mod_sofia_globals.custom_node); - switch_event_unbind(&mod_sofia_globals.mwi_node); - switch_event_unbind(&mod_sofia_globals.recovery_node); + switch_event_unbind_callback(sofia_presence_event_handler); + switch_event_unbind_callback(sofia_presence_mwi_event_handler); + switch_event_unbind_callback(sofia_glue_track_event_handler); switch_event_unbind_callback(general_event_handler); + switch_event_unbind_callback(event_handler); while (mod_sofia_globals.threads) { switch_cond_next(); diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.h b/src/mod/endpoints/mod_sofia/mod_sofia.h index 98975bdfdb..219b7c7b2f 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.h +++ b/src/mod/endpoints/mod_sofia/mod_sofia.h @@ -368,13 +368,6 @@ struct mod_sofia_globals { int msg_queue_len; struct sofia_private destroy_private; struct sofia_private keep_private; - switch_event_node_t *in_node; - switch_event_node_t *probe_node; - switch_event_node_t *out_node; - switch_event_node_t *roster_node; - switch_event_node_t *custom_node; - switch_event_node_t *mwi_node; - switch_event_node_t *recovery_node; int guess_mask; char guess_mask_str[16]; int debug_presence; diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index b04cb89e37..423757d655 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -1189,8 +1189,59 @@ static void our_sofia_event_callback(nua_event_t event, case nua_r_refer: break; case nua_i_refer: - if (session) + if (session) { sofia_handle_sip_i_refer(nua, profile, nh, session, sip, de, tags); + } else { + const char *req_user = NULL, *req_host = NULL, *action = NULL, *ref_by_user = NULL; + char *refer_to = NULL, *referred_by = NULL, *method = NULL; + char *params = NULL; + switch_event_t *event; + + if (sip->sip_refer_to) { + refer_to = sip_header_as_string(nua_handle_home(nh), (void *) sip->sip_refer_to); + if ((params = strchr(refer_to, ';'))) { + *params++ = '\0'; + if ((method = switch_find_parameter(params, "method", NULL))) { + if (!strcasecmp(method, "INVITE")) { + action = "call"; + } else if (!strcasecmp(method, "BYE")) { + action = "end"; + } else { + action = method; + } + } + } + + refer_to = sofia_glue_get_url_from_contact(refer_to, 0); + + } + + if (sip->sip_referred_by) { + referred_by = sofia_glue_get_url_from_contact(sip_header_as_string(nua_handle_home(nh), (void *) sip->sip_referred_by), 0); + ref_by_user = sip->sip_referred_by->b_url->url_user; + } + + if (sip->sip_request && sip->sip_request->rq_url) { + req_user = sip->sip_request->rq_url->url_user; + req_host = sip->sip_request->rq_url->url_host; + } + + if (switch_event_create(&event, SWITCH_EVENT_CALL_SETUP_REQ) == SWITCH_STATUS_SUCCESS) { + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Requesting-Component", "mod_sofia"); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Target-Component", req_user); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Target-Domain", req_host); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Request-Action", action); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Request-Target", "sofia/%s/%s", profile->name, refer_to); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Request-Sender", "sofia/%s/%s", profile->name, referred_by); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "var_origination_caller_id_number", ref_by_user); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "var_origination_caller_id_name", ref_by_user); + switch_event_fire(&event); + } + + nua_respond(nh, SIP_202_ACCEPTED, NUTAG_WITH_THIS_MSG(de->data->e_msg), TAG_END()); + switch_safe_free(method); + + } break; case nua_r_subscribe: sofia_presence_handle_sip_r_subscribe(status, phrase, nua, profile, nh, sofia_private, sip, de, tags); @@ -2112,13 +2163,6 @@ void *SWITCH_THREAD_FUNC sofia_profile_thread_run(switch_thread_t *thread, void nua_set_params(profile->nua, SIPTAG_ALLOW_STR("INVITE, ACK, BYE, CANCEL, OPTIONS, MESSAGE, UPDATE, INFO"), - NUTAG_APPL_METHOD("OPTIONS"), - NUTAG_APPL_METHOD("REFER"), - NUTAG_APPL_METHOD("REGISTER"), - NUTAG_APPL_METHOD("NOTIFY"), NUTAG_APPL_METHOD("INFO"), NUTAG_APPL_METHOD("ACK"), NUTAG_APPL_METHOD("SUBSCRIBE"), -#ifdef MANUAL_BYE - NUTAG_APPL_METHOD("BYE"), -#endif NUTAG_AUTOANSWER(0), NUTAG_AUTOACK(0), NUTAG_AUTOALERT(0), @@ -2131,6 +2175,15 @@ void *SWITCH_THREAD_FUNC sofia_profile_thread_run(switch_thread_t *thread, void NUTAG_ALLOW("NOTIFY"), NUTAG_ALLOW_EVENTS("talk"), NUTAG_ALLOW_EVENTS("hold"), + NUTAG_ALLOW_EVENTS("conference"), + NUTAG_APPL_METHOD("OPTIONS"), + NUTAG_APPL_METHOD("REFER"), + NUTAG_APPL_METHOD("REGISTER"), + NUTAG_APPL_METHOD("NOTIFY"), NUTAG_APPL_METHOD("INFO"), NUTAG_APPL_METHOD("ACK"), NUTAG_APPL_METHOD("SUBSCRIBE"), +#ifdef MANUAL_BYE + NUTAG_APPL_METHOD("BYE"), +#endif + NUTAG_SESSION_TIMER(profile->session_timeout), NTATAG_MAX_PROCEEDING(profile->max_proceeding), TAG_IF(profile->pres_type, NUTAG_ALLOW("PUBLISH")), @@ -6829,11 +6882,13 @@ void sofia_handle_sip_i_refer(nua_t *nua, sofia_profile_t *profile, nua_handle_t goto done; } + printf("DICK %d\n", __LINE__); + if (!sip->sip_cseq || !(etmp = switch_mprintf("refer;id=%u", sip->sip_cseq->cs_seq))) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Memory Error!\n"); goto done; } - + printf("DICK %d\n", __LINE__); from = sip->sip_from; //to = sip->sip_to; @@ -6850,7 +6905,7 @@ void sofia_handle_sip_i_refer(nua_t *nua, sofia_profile_t *profile, nua_handle_t } if ((refer_to = sip->sip_refer_to)) { - char *rep; + char *rep = NULL; full_ref_to = sip_header_as_string(home, (void *) sip->sip_refer_to); if (sofia_test_pflag(profile, PFLAG_FULL_ID)) { @@ -6861,7 +6916,16 @@ void sofia_handle_sip_i_refer(nua_t *nua, sofia_profile_t *profile, nua_handle_t switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Process REFER to [%s@%s]\n", exten, (char *) refer_to->r_url->url_host); - if (refer_to->r_url->url_headers && (rep = (char *) switch_stristr("Replaces=", refer_to->r_url->url_headers))) { + + if (refer_to->r_url && refer_to->r_url->url_headers) { + rep = (char *) switch_stristr("Replaces=", refer_to->r_url->url_headers); + } + + printf("WTFX %s\n", rep); + + if (!rep) { + printf("WTF [%s]\n", refer_to->r_url->url_headers); + } else { sip_replaces_t *replaces; nua_handle_t *bnh = NULL; diff --git a/src/mod/endpoints/mod_sofia/sofia_presence.c b/src/mod/endpoints/mod_sofia/sofia_presence.c index 16539aeef4..a6024037b1 100644 --- a/src/mod/endpoints/mod_sofia/sofia_presence.c +++ b/src/mod/endpoints/mod_sofia/sofia_presence.c @@ -862,7 +862,102 @@ static void do_dialog_probe(switch_event_t *event) switch_safe_free(probe_user); } +static void send_conference_data(sofia_profile_t *profile, switch_event_t *event) +{ + char *sql; + struct pres_sql_cb cb = {profile, 0}; + const char *call_id = switch_event_get_header(event, "call_id"); + const char *from_user = switch_event_get_header(event, "conference-name"); + const char *from_host = switch_event_get_header(event, "conference-domain"); + const char *notfound = switch_event_get_header(event, "notfound"); + const char *body = switch_event_get_body(event); + if (!(from_user && from_host)) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Event information not given\n"); + return; + } + + if (switch_true(notfound)) { + sql = switch_mprintf("update sip_subscriptions set expires=%ld where " + "hostname='%q' and profile_name='%q' and sub_to_user='%q' and sub_to_host='%q' and event='conference'", + (long)switch_epoch_time_now(NULL), + mod_sofia_globals.hostname, profile->name, + from_user, from_host); + + sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE); + } + + + if (call_id) { + sql = switch_mprintf("select full_to, full_from, contact %q ';_;isfocus', expires, call_id, event, network_ip, network_port, " + "'application/conference-info+xml' as ct,'%q' as pt " + " from sip_subscriptions where " + "hostname='%q' and profile_name='%q' and sub_to_user='%q' and sub_to_host='%q' and event='conference'" + "and call_id = '%q' ", + switch_sql_concat(), + switch_str_nil(body), + mod_sofia_globals.hostname, profile->name, + from_user, from_host, call_id); + } else { + sql = switch_mprintf("select full_to, full_from, contact %q ';_;isfocus', expires, call_id, event, network_ip, network_port, " + "'application/conference-info+xml' as ct,'%q' as pt " + " from sip_subscriptions where " + "hostname='%q' and profile_name='%q' and sub_to_user='%q' and sub_to_host='%q' and event='conference'", + switch_sql_concat(), + switch_str_nil(body), + mod_sofia_globals.hostname, profile->name, + from_user, from_host); + } + + sofia_glue_execute_sql_callback(profile, profile->ireg_mutex, sql, sofia_presence_send_sql, &cb); + switch_safe_free(sql); + +} + +static void conference_data_event_handler(switch_event_t *event) +{ + const char *pname; + //const char *from_user = switch_event_get_header(event, "conference-name"); + //const char *from_host = switch_event_get_header(event, "conference-domain"); + const char *host = switch_event_get_header(event, "conference-domain"); + char *dup_domain = NULL; + sofia_profile_t *profile = NULL; + + if (zstr(host)) { + dup_domain = switch_core_get_variable_dup("domain"); + host = dup_domain; + } + + if ((pname = switch_event_get_header(event, "sofia-profile"))) { + profile = sofia_glue_find_profile(pname); + } + + if (host && !profile) { + profile = sofia_glue_find_profile(host); + } + + if (profile) { + send_conference_data(profile, event); + sofia_glue_release_profile(profile); + } else { + switch_console_callback_match_t *matches; + + if (list_profiles_full(NULL, NULL, &matches, SWITCH_FALSE) == SWITCH_STATUS_SUCCESS) { + switch_console_callback_match_node_t *m; + + for (m = matches->head; m; m = m->next) { + if ((profile = sofia_glue_find_profile(m->val))) { + send_conference_data(profile, event); + sofia_glue_release_profile(profile); + } + } + + switch_console_free_matches(&matches); + } + } + + switch_safe_free(dup_domain); +} static void actual_sofia_presence_event_handler(switch_event_t *event) { @@ -1374,7 +1469,13 @@ void *SWITCH_THREAD_FUNC sofia_presence_event_thread_run(switch_thread_t *thread if (!pop) { break; } - actual_sofia_presence_event_handler(event); + + if (event->event_id == SWITCH_EVENT_CONFERENCE_DATA) { + conference_data_event_handler(event); + } else { + actual_sofia_presence_event_handler(event); + } + switch_event_destroy(&event); count++; } @@ -1871,14 +1972,22 @@ static void _send_presence_notify(sofia_profile_t *profile, char *our_contact = profile->url, *our_contact_dup = NULL; sofia_destination_t *dst = NULL; - char *contact_str, *contact, *user_via = NULL; + char *contact_str, *contact, *user_via = NULL, *send_contact = NULL; char *route_uri = NULL, *o_contact_dup = NULL, *tmp, *to_uri, *dcs = NULL; const char *tp; + char *cparams = NULL; if (zstr(full_to) || zstr(full_from) || zstr(o_contact)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "MISSING DATA TO SEND NOTIFY.\n"); return; } + + if ((cparams = strstr(o_contact, ";_;"))) { + cparams += 3; + } + + + tmp = (char *)o_contact; o_contact_dup = sofia_glue_get_url_from_contact(tmp, 1); @@ -2012,6 +2121,12 @@ static void _send_presence_notify(sofia_profile_t *profile, callsequence = ++profile->cseq_base; switch_mutex_unlock(profile->ireg_mutex); + if (cparams) { + send_contact = switch_mprintf("%s;%s", contact_str, cparams); + contact_str = send_contact; + } + + nh = nua_handle(profile->nua, NULL, NUTAG_URL(contact), SIPTAG_CONTACT_STR(contact_str), TAG_END()); cseq = sip_cseq_create(nh->nh_home, callsequence, SIP_METHOD_NOTIFY); @@ -2047,6 +2162,7 @@ static void _send_presence_notify(sofia_profile_t *profile, sofia_glue_free_destination(dst); switch_safe_free(user_via); switch_safe_free(o_contact_dup); + switch_safe_free(send_contact); switch_safe_free(our_contact_dup); @@ -3649,9 +3765,17 @@ void sofia_presence_handle_sip_i_subscribe(int status, switch_safe_free(sql); } - } - - if ( sip->sip_event && sip->sip_event->o_type && !strcasecmp(sip->sip_event->o_type, "ua-profile") && contact_host ) { + } else if (!strcasecmp(event, "conference")) { + switch_event_t *event; + switch_event_create(&event, SWITCH_EVENT_CONFERENCE_DATA_QUERY); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Conference-Name", to_user); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Conference-Domain", to_host); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Query-From", from_user); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Query-From-Domain", from_host); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Call-Id", call_id); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Sofia-Profile", profile->name); + switch_event_fire(&event); + } else if ( sip->sip_event && sip->sip_event->o_type && !strcasecmp(sip->sip_event->o_type, "ua-profile") && contact_host ) { switch_event_t *params; char *uri = NULL; char *extra_headers = NULL; diff --git a/src/switch_event.c b/src/switch_event.c index 0f08b496c0..4bfbbb1ff7 100644 --- a/src/switch_event.c +++ b/src/switch_event.c @@ -193,6 +193,10 @@ static char *EVENT_NAMES[] = { "SOCKET_DATA", "MEDIA_BUG_START", "MEDIA_BUG_STOP", + "CONFERENCE_DATA_QUERY", + "CONFERENCE_DATA", + "CALL_SETUP_REQ", + "CALL_SETUP_RESULT", "ALL" }; diff --git a/src/switch_rtp.c b/src/switch_rtp.c index 7d6ad297a2..ba55d693f6 100644 --- a/src/switch_rtp.c +++ b/src/switch_rtp.c @@ -4676,7 +4676,7 @@ SWITCH_DECLARE(int) switch_rtp_write_manual(switch_rtp_t *rtp_session, SWITCH_DECLARE(uint32_t) switch_rtp_get_ssrc(switch_rtp_t *rtp_session) { - return rtp_session->send_msg.header.ssrc; + return rtp_session->ssrc; } SWITCH_DECLARE(void) switch_rtp_set_private(switch_rtp_t *rtp_session, void *private_data)