]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
Add sip_watched_headers variable to launch events when a SIP message contains a given...
authorMoises Silva <moy@sangoma.com>
Tue, 15 Jan 2013 05:50:28 +0000 (00:50 -0500)
committerMoises Silva <moy@sangoma.com>
Tue, 2 Jun 2015 04:47:18 +0000 (00:47 -0400)
FS-6801 #resolve

src/mod/endpoints/mod_sofia/mod_sofia.c
src/mod/endpoints/mod_sofia/mod_sofia.h
src/mod/endpoints/mod_sofia/sofia.c

index 33f4e0f855a0b2934f07a4ad27e92f7de4a54726..0971e66088cac052de6d34d59034b502d0d48af1 100644 (file)
@@ -72,6 +72,7 @@ static switch_status_t sofia_kill_channel(switch_core_session_t *session, int si
 */
 static switch_status_t sofia_on_init(switch_core_session_t *session)
 {
+       const char *hval = NULL;
        switch_channel_t *channel = switch_core_session_get_channel(session);
        private_object_t *tech_pvt = (private_object_t *) switch_core_session_get_private(session);
        switch_status_t status = SWITCH_STATUS_SUCCESS;
@@ -89,6 +90,23 @@ static switch_status_t sofia_on_init(switch_core_session_t *session)
                switch_core_media_absorb_sdp(session);
        }
 
+       if ((hval = switch_channel_get_variable(channel, "sip_watch_headers"))) {
+               char *dupvar = NULL;
+               char *watch_headers[10];
+               unsigned int numhdrs = 0;
+               int i = 0;
+               dupvar = switch_core_session_strdup(session, hval);
+               numhdrs = switch_separate_string(dupvar, ',', watch_headers, switch_arraylen(watch_headers));
+               if (numhdrs) {
+                       char **wheaders = switch_core_session_alloc(session, ((numhdrs+1) * sizeof(wheaders[0])));
+                       for (i = 0; i < numhdrs; i++) {
+                               wheaders[i] = watch_headers[i];
+                       }
+                       wheaders[i] = NULL;
+                       tech_pvt->watch_headers = wheaders;
+               }
+       }
+
        if (switch_channel_test_flag(tech_pvt->channel, CF_RECOVERING) || switch_channel_test_flag(tech_pvt->channel, CF_RECOVERING_BRIDGE)) {
                sofia_set_flag(tech_pvt, TFLAG_RECOVERED);
        }
index 577ff07bbc8282f4f431412f3daef90a746b89b8..06a4c739bcf9e1741792bf5ac672b35dc6744bdd 100644 (file)
@@ -93,6 +93,7 @@ typedef struct private_object private_object_t;
 #define MY_EVENT_RECOVERY_RECOVERED "sofia::recovery_recovered"
 #define MY_EVENT_ERROR "sofia::error"
 #define MY_EVENT_PROFILE_START "sofia::profile_start"
+#define MY_EVENT_NOTIFY_WATCHED_HEADER "sofia::notify_watched_header"
 
 #define MULTICAST_EVENT "multicast::event"
 #define SOFIA_REPLACES_HEADER "_sofia_replaces_"
@@ -784,6 +785,7 @@ struct private_object {
        sofia_cid_type_t cid_type;
        uint32_t session_timeout;
        enum nua_session_refresher session_refresher;
+       char **watch_headers;
        char *respond_phrase;
        int respond_code;
        char *respond_dest;
index edc15cf69bef0f4b4affc49478bf9122433634b5..ef3d9381fa55be960c99327ba89e61926dd6a8d6 100644 (file)
@@ -1251,6 +1251,21 @@ static void tech_send_ack(nua_handle_t *nh, private_object_t *tech_pvt)
 
 }
 
+static void notify_watched_header(switch_core_session_t *session, const char *msgline, const char *hdrname, const char *hdrval)
+{
+       switch_event_t *event = NULL;
+       switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Found known watched header in message '%s', %s: %s\n", msgline, hdrname, hdrval);
+       if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, MY_EVENT_NOTIFY_WATCHED_HEADER) == SWITCH_STATUS_SUCCESS) {
+               switch_channel_t *channel = switch_core_session_get_channel(session);
+               switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "SIP-Message", msgline);
+               switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Header-Name", hdrname);
+               switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Header-Value", hdrval);
+               switch_channel_event_set_data(channel, event);
+               switch_event_fire(&event);
+       } else {
+               switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Failed creating event of type %s!\n", MY_EVENT_NOTIFY_WATCHED_HEADER);
+       }
+}
 
 //sofia_dispatch_event_t *de
 static void our_sofia_event_callback(nua_event_t event,
@@ -1326,6 +1341,56 @@ static void our_sofia_event_callback(nua_event_t event,
                }
        }
 
+       if (session && tech_pvt && tech_pvt->watch_headers && sip) {
+               char msgline[512];
+               int hi;
+               msg_header_t *h = NULL;
+               if (sip->sip_request) {
+                       h = (msg_header_t *)sip->sip_request;
+                       msg_header_field_e(msgline, sizeof(msgline), h, 0);
+               } else if (sip->sip_status) {
+                       h = (msg_header_t *)sip->sip_status;
+                       msg_header_field_e(msgline, sizeof(msgline), h, 0);
+               }
+               if (h) {
+                       sip_unknown_t *un = NULL;
+                       char buf[512];
+                       char *c = NULL;
+
+                       msgline[sizeof(msgline)-1] = '\0';
+                       c = strchr(msgline, '\r');
+                       if (c) {
+                               *c = '\0';
+                       }
+
+                       /* Faster (ie hash-based) search here would be nice? ie, make watch_headers a hash? */
+
+                       /* Search first in the valid headers */
+                       for (h = h->sh_succ; h; h = h->sh_succ) {
+                               sip_header_t *sh = (sip_header_t *)h;
+                               if (!sh->sh_class->hc_name) {
+                                       continue;
+                               }
+                               for (hi = 0; tech_pvt->watch_headers[hi]; hi++) {
+                                       if (!strcasecmp(tech_pvt->watch_headers[hi], sh->sh_class->hc_name)) {
+                                               msg_header_field_e(buf, sizeof(buf), h, 0);
+                                               buf[sizeof(buf)-1] = '\0';
+                                               notify_watched_header(session, msgline, sh->sh_class->hc_name, buf);
+                                       }
+                               }
+                       }
+
+                       /* Search now in the unknown headers */
+                       for (un = sip->sip_unknown; un; un = un->un_next) {
+                               for (hi = 0; tech_pvt->watch_headers[hi]; hi++) {
+                                       if (!strcasecmp(tech_pvt->watch_headers[hi], un->un_name)) {
+                                               notify_watched_header(session, msgline, un->un_name, un->un_value);
+                                       }
+                               }
+                       }
+               }
+       }
+
        if (sofia_test_pflag(profile, PFLAG_AUTH_ALL) && tech_pvt && tech_pvt->key && sip && (event < nua_r_set_params || event > nua_r_authenticate)) {
                sip_authorization_t const *authorization = NULL;