]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
FS-9276 new feature proxy in-dialog calls sip notify and info similar to proxy hold
authorMuhammad Zaka <muhammad.zaka@synety.com>
Fri, 17 Jun 2016 09:45:28 +0000 (10:45 +0100)
committerMuhammad Zaka <muhammad.zaka@synety.com>
Mon, 1 Aug 2016 10:44:12 +0000 (11:44 +0100)
src/mod/endpoints/mod_sofia/conf/sofia.conf.xml
src/mod/endpoints/mod_sofia/mod_sofia.h
src/mod/endpoints/mod_sofia/sofia.c
src/mod/endpoints/mod_sofia/sofia_glue.c

index a03f52ac005350b661ae76f6b7c7e6e5deda9dd7..36502849d4bd0c54ad8397747756f1ea3b6c0a92 100644 (file)
              really need to change this.
         -->
         <!-- <param name="renegotiate-codec-on-hold" value="true"/> -->
-
         <!-- Turn on proxy hold when proxy media and proxy mode are disabled 
              By default it is not set
         --> 
         <!-- <param name="proxy-hold" value="true"/> -->
+        <!-- Choose the proxy notify events. Default is not set
+
+             all - every in-dialogs call sip notify will be proxy to the core pbx or b2bua
+             <param name="proxy-notify-events" value="all"/>
+
+             <eventlist> - only event list sip notify will be proxy to the core pbx or b2bua
+                           this option provide users to specific events to be proxy through
+                           e.g talk,conference
+             <param name="proxy-notify-events" value="talk,conference"/>
+        -->
+        <!-- Choose the proxy info content type. Default is not set.
+
+             all - every in-dialogs call sip infos will be proxy to the core pbx or b2bua
+             <param name="proxy-info-content-types" value="all"/>
+
+             <info_content_type_list> - only content type list of sip info will be proxy to the core pbx
+                                   or b2bua this option provide users to specific infos to be proxy through
+                                   e.g application/pause-recording,application/resume-recording
+             <param name="proxy-info-content-types" value="application/pause-recording,application/resume-recording"/>
+        -->
       </settings>
     </profile>
   </profiles>
index 70ef0dd241505ae7073cfbaa21bd9b5de812de4f..6d97c55f813ef03bd7b6d5d86e9de0a584b938c8 100644 (file)
@@ -764,6 +764,8 @@ struct sofia_profile {
        ka_type_t keepalive;
        int bind_attempts;
        int bind_attempt_interval;
+       char *proxy_notify_events;
+       char *proxy_info_content_types;
 };
 
 
@@ -1066,6 +1068,8 @@ void sofia_reg_release_gateway__(const char *file, const char *func, int line, s
 
 #define sofia_use_soa(_t) sofia_test_flag(_t, TFLAG_ENABLE_SOA)
 
+#define sofia_test_extra_headers(val) (((!strncasecmp(val, "X-", 2) && strncasecmp(val, "X-FS-", 5)) || !strncasecmp(val, "P-", 2) || !strncasecmp(val, "On", 2)) ? 1 : 0)
+
 #define check_decode(_var, _session) do {                                                              \
                assert(_session);                                                                                               \
                if (!zstr(_var)) {                                                              \
@@ -1162,6 +1166,7 @@ switch_status_t sofia_glue_send_notify(sofia_profile_t *profile, const char *use
 char *sofia_glue_get_extra_headers(switch_channel_t *channel, const char *prefix);
 void sofia_glue_set_extra_headers(switch_core_session_t *session, sip_t const *sip, const char *prefix);
 char *sofia_glue_get_extra_headers_from_event(switch_event_t *event, const char *prefix);
+char *sofia_glue_get_non_extra_unknown_headers(sip_t const *sip);
 void sofia_update_callee_id(switch_core_session_t *session, sofia_profile_t *profile, sip_t const *sip, switch_bool_t send);
 void sofia_send_callee_id(switch_core_session_t *session, const char *name, const char *number);
 int sofia_sla_supported(sip_t const *sip);
index 233c121105a90865644f4aff6f1170c23f20b184..dad12ed7b4da990a83fb1196c8130b08ce409a42 100644 (file)
@@ -679,6 +679,29 @@ void sofia_handle_sip_i_notify(switch_core_session_t *session, int status,
 
        /* if no session, assume it could be an incoming notify from a gateway subscription */
        if (session) {
+               if (!zstr(profile->proxy_notify_events) && (!strcasecmp(profile->proxy_notify_events, "all") || strstr(profile->proxy_notify_events, sip->sip_event->o_type))) {
+                       switch_core_session_t *other_session;
+                       if (switch_core_session_get_partner(session, &other_session) == SWITCH_STATUS_SUCCESS) {
+                               private_object_t *other_tech_pvt = switch_core_session_get_private(other_session);
+                               const char *full_to = NULL;
+                               char *pl = NULL;
+                               char *unknown = NULL;
+
+                               full_to = switch_str_nil(switch_channel_get_variable(switch_core_session_get_channel(other_session), "sip_full_to"));
+                               if (sip->sip_payload && sip->sip_payload->pl_data) {
+                                       pl = switch_core_session_strdup(other_session, (char*)sip->sip_payload->pl_data);
+                               }
+                               unknown = sofia_glue_get_non_extra_unknown_headers(sip);
+                               nua_notify(other_tech_pvt->nh, NUTAG_NEWSUB(1), NUTAG_SUBSTATE(nua_substate_active),
+                                                       TAG_IF((full_to), SIPTAG_TO_STR(full_to)), SIPTAG_SUBSCRIPTION_STATE_STR("active"),
+                                                       SIPTAG_EVENT_STR(sip->sip_event->o_type), TAG_IF(!zstr(unknown), SIPTAG_HEADER_STR(unknown)),
+                                                       TAG_IF(!zstr(pl), SIPTAG_PAYLOAD_STR(pl)), TAG_END());
+                               switch_safe_free(unknown);
+                               switch_core_session_rwunlock(other_session);
+                       }
+                       nua_respond(nh, SIP_200_OK, NUTAG_WITH_THIS_MSG(de->data->e_msg), TAG_END());
+                       goto end;
+               }
                /* make sure we have a proper "talk" event */
                if (strcasecmp(sip->sip_event->o_type, "talk")) {
                        goto error;
@@ -5621,6 +5644,10 @@ switch_status_t config_sofia(sofia_config_t reload, char *profile_name)
                                                }  else {
                                                        sofia_clear_pflag(profile, PFLAG_PROXY_HOLD);
                                                }
+                                       } else if (!strcasecmp(var, "proxy-notify-events")) {
+                                               profile->proxy_notify_events = switch_core_strdup(profile->pool, val);
+                                       } else if (!strcasecmp(var, "proxy-info-content-types")) {
+                                               profile->proxy_info_content_types = switch_core_strdup(profile->pool, val);
                                        }
                                }
 
@@ -9114,8 +9141,37 @@ void sofia_handle_sip_i_info(nua_t *nua, sofia_profile_t *profile, nua_handle_t
                assert(switch_core_session_get_private(session));
 
                sofia_glue_set_extra_headers(session, sip, SOFIA_SIP_INFO_HEADER_PREFIX);
+               if (!zstr(profile->proxy_info_content_types) && sip && sip->sip_content_type && sip->sip_content_type->c_type && sip->sip_content_type->c_subtype &&
+                       (!strcasecmp(profile->proxy_info_content_types,"all") || strstr(profile->proxy_info_content_types,sip->sip_content_type->c_type))) {
+                       switch_core_session_t *other_session;
 
+                       if (switch_core_session_get_partner(session, &other_session) == SWITCH_STATUS_SUCCESS) {
+                               char *pl = NULL;
+                               char *ct = NULL;
+                               char *extra_headers = NULL;
+                               char *unknown = NULL;
+                               private_object_t *other_tech_pvt = switch_core_session_get_private(other_session);
+
+                               ct = switch_core_session_strdup(other_session, (char*)sip->sip_content_type->c_type);
+                               if (sip->sip_payload && sip->sip_payload->pl_data) {
+                                       pl = switch_core_session_strdup(other_session,(char*)sip->sip_payload->pl_data);
+                               }
+                               unknown = sofia_glue_get_non_extra_unknown_headers(sip);
+
+                                extra_headers = sofia_glue_get_extra_headers(channel, SOFIA_SIP_INFO_HEADER_PREFIX);
 
+                               nua_info(other_tech_pvt->nh,
+                                               SIPTAG_CONTENT_TYPE_STR(ct),
+                                               TAG_IF(!zstr(extra_headers), SIPTAG_HEADER_STR(extra_headers)),
+                                               TAG_IF(!zstr(unknown), SIPTAG_HEADER_STR(unknown)),
+                                               TAG_IF(!zstr(other_tech_pvt->user_via), SIPTAG_VIA_STR(other_tech_pvt->user_via)),
+                                               TAG_IF(!zstr(pl), SIPTAG_PAYLOAD_STR(pl)),
+                                               TAG_END());
+                               switch_safe_free(extra_headers);
+                               switch_safe_free(unknown);
+                               switch_core_session_rwunlock(other_session);
+                       }
+               }
 
                if (sip && sip->sip_content_type && sip->sip_content_type->c_type && !strcasecmp(sip->sip_content_type->c_type, "freeswitch/data")) {
                        char *data = NULL;
index cef4c6142989c32b3aa2f51e73d66f080eb198ab..acbddcaf736deb8a38f37d7ad419d8b46edf30f4 100644 (file)
@@ -644,7 +644,7 @@ void sofia_glue_set_extra_headers(switch_core_session_t *session, sip_t const *s
        }
 
        for (un = sip->sip_unknown; un; un = un->un_next) {
-               if ((!strncasecmp(un->un_name, "X-", 2) && strncasecmp(un->un_name, "X-FS-", 5)) || !strncasecmp(un->un_name, "P-", 2) || !strncasecmp(un->un_name, "On", 2)) {
+               if (sofia_test_extra_headers(un->un_name)) {
                        if (!zstr(un->un_value)) {
                                switch_snprintf(name, sizeof(name), "%s%s", prefix, un->un_name);
                                switch_channel_set_variable(channel, name, un->un_value);
@@ -685,6 +685,33 @@ char *sofia_glue_get_extra_headers_from_event(switch_event_t *event, const char
        return extra_headers;
 }
 
+char *sofia_glue_get_non_extra_unknown_headers(sip_t const *sip)
+{
+       char *unknown = NULL;
+       switch_stream_handle_t stream = { 0 };
+       sip_unknown_t *un;
+
+       if (!sip) {
+               return NULL;
+       }
+
+       SWITCH_STANDARD_STREAM(stream);
+       for (un = sip->sip_unknown; un; un = un->un_next) {
+               if (!sofia_test_extra_headers(un->un_name)) {
+                       if (!zstr(un->un_value)) {
+                               stream.write_function(&stream, "%s: %s\r\n",un->un_name,un->un_value);
+                       }
+               }
+       }
+       if (!zstr((char *) stream.data)) {
+               unknown = stream.data;
+       } else {
+               switch_safe_free(stream.data);
+       }
+
+       return unknown;
+}
+
 switch_status_t sofia_glue_do_invite(switch_core_session_t *session)
 {
        char *alert_info = NULL;