]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
first pass on some new stuff
authorAnthony Minessale <anthm@freeswitch.org>
Wed, 11 Jul 2012 20:15:43 +0000 (15:15 -0500)
committerAnthony Minessale <anthm@freeswitch.org>
Wed, 11 Jul 2012 20:15:50 +0000 (15:15 -0500)
12 files changed:
libs/esl/src/esl_event.c
libs/esl/src/include/esl_event.h
libs/sofia-sip/libsofia-sip-ua/nua/nua_notifier.c
src/include/switch_types.h
src/mod/applications/mod_conference/mod_conference.c
src/mod/applications/mod_dptools/mod_dptools.c
src/mod/endpoints/mod_sofia/mod_sofia.c
src/mod/endpoints/mod_sofia/mod_sofia.h
src/mod/endpoints/mod_sofia/sofia.c
src/mod/endpoints/mod_sofia/sofia_presence.c
src/switch_event.c
src/switch_rtp.c

index 6ebd6669b6ee4db11ae4f47eaed81acf9acd5ec8..7a0da29db3603febe25f017c912e012f701b66e1 100644 (file)
@@ -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"
 };
 
index b7dea736c907d84d58732ba43b2ae11bd6a8f650..1b6e6e29b46565347165c522db275432198736b4 100644 (file)
@@ -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;
 
index e7d3d7470f0b32097303ad792881761e6960bb6b..8ef6747aff9d393052a83e5efbe6419969f59c61 100644 (file)
@@ -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;
 }
index 08b6c6195459aa28d44660fdc3958a9eaa1716b5..6dc6118fe959c5d7f4201edb5c9540133cc2038a 100644 (file)
@@ -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;
 
index 68acd3ad7040d90679854d91a7dbb1da7859cf57..151084e44ac46f2e1668309d1a05b11d04325899 100644 (file)
@@ -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("<conference-info xmlns=\"urn:ietf:params:xml:ns:conference-info\" "
+                                                         "entity=\"sip:%s@%s\" state=\"full\"/>\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 */
index 0937b37c3c91121b6d2daf99ddb901ebdbd88be5..80543033e0989ebd426777530420c1eb6eb8cad8 100755 (executable)
@@ -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);
 }
 
index d5faa8e3c93996e755bf5aae2c9cec6cca2a0f20..b2c47d97d3211263a8978b0ce708a8bf6956a100 100644 (file)
@@ -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();
index 98975bdfdb80204b2eccedc68d4fc61b7be087f8..219b7c7b2f9822394e6c134898334e76a1549c5f 100644 (file)
@@ -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;
index b04cb89e37021d7476fab71dba20398308e2a444..423757d655defcda553394e01765bd19c102f562 100644 (file)
@@ -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;
 
index 16539aeef4dcbe76db5fa86e05f0d5c1ff88a1fb..a6024037b1e79cbc532a161a3652c4b652e7506e 100644 (file)
@@ -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;
index 0f08b496c077baa9365ff91969da96b463ebf6b3..4bfbbb1ff72381eb0fd506ee4ba464ec59e037b9 100644 (file)
@@ -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"
 };
 
index 7d6ad297a2fe0dc50763b4f977328cbfbb21563d..ba55d693f65f1b2ff30276d8752cec075f6f01c2 100644 (file)
@@ -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)