Hi all,

I'm trying to modify the bearerbox so the bb would make a HTTP GET request to a specific url every time a SMPP SMSC client loses the connection or comes back online.

All this to ensure that our routing app reacts as quickly as possible when the connection fails and routes the traffic away to another SMSC. Currently we are polling the Kannel's status page once a minute, which is not adaptive enough.

We considered designing our routing app to state several smsc-ids (like smsc-id=primary;secondary) when submitting the message to Kannel, so Kannel would choose the secondary smsc in case the primary is not available, but we saw an overhead of updating an actual price, user's balance and smsc-id of the message after it has been submitted to the upstream SMSC.

The patch is made against rev 5043 with `svn diff --patch-compatible` command. Not being much confident with C++ myself, I'm asking for your advice - are there any critical flaws I'm not aware of?

This is a basic version, and there is a room for improvement, like adding templates to the url for passing smsc host, port, username, service-type etc., and adding this notifications to other smsc types.

And as allways, if anyone finds it usefull, I would be honored if you add it to the Kannel codebase.

Thanks a lot in advance,
--
Regards,
Semion Spivak,
SmsCoin.com
Index: doc/userguide/userguide.xml
===================================================================
--- doc/userguide/userguide.xml (revision 5043)
+++ doc/userguide/userguide.xml (working copy)
@@ -3618,6 +3618,16 @@
        Accepted values are 0 (Default SMSC Mode) and 3 (Store and Forward). 
        Defaults to 3.
      </entry></row>
+   
+   <row><entry><literal>connection-status-url</literal></entry>
+     <entry><literal>string</literal></entry>
+     <entry valign="bottom">
+       Optional. Kannel will make a non-blocking HTTP GET request to this URL 
when
+       the SMSC comes online or loses the connection.
+       The parameters of the request will be as following:
+       smsc-id - the urlencoded smsc-admin-id (if set in the smsc group) or 
smsc-id;
+       status - "active", "connecting" or "disconnected"  
+     </entry></row>
 
    </tbody></tgroup></informaltable>
 
Index: gw/smsc/smsc_smpp.c
===================================================================
--- gw/smsc/smsc_smpp.c (revision 5043)
+++ gw/smsc/smsc_smpp.c (working copy)
@@ -125,6 +125,8 @@
 #define SMPP_WAITACK_REQUEUE        0x01
 #define SMPP_WAITACK_NEVER_EXPIRE   0x02
 
+static HTTPCaller *caller;
+
 /***********************************************************************
  * Implementation of the actual SMPP protocol: reading and writing
  * PDUs in the correct order.
@@ -1559,7 +1561,55 @@
     return dlrmsg;
 }
 
+/*
+ * Make a non-blocking request to conn->callback_url on conn->status change
+ */
+static void status_url_notify(SMSCConn *conn){
+       if (conn->connection_status_url == NULL || conn->prev_status == 
conn->status){
+               return;
+       }
 
+       Octstr *url;
+       Octstr *smsc_id;
+       List *request_headers;
+
+       conn->prev_status = conn->status;
+
+       /* construct the request url with parameters */
+       url = octstr_duplicate(conn->connection_status_url);
+       octstr_append(url, octstr_imm("?smsc-id="));
+       smsc_id = octstr_duplicate(conn->admin_id);
+       octstr_url_encode(smsc_id);
+       octstr_append(url, smsc_id);
+
+       switch(conn->status){
+               case SMSCCONN_CONNECTING:
+               case SMSCCONN_RECONNECTING:
+                       octstr_append(url, octstr_imm("&status=connecting"));
+                       break;
+               case SMSCCONN_ACTIVE:
+               case SMSCCONN_ACTIVE_RECV:
+                       octstr_append(url, octstr_imm("&status=active"));
+                       break;
+               case SMSCCONN_DISCONNECTED:
+               case SMSCCONN_DEAD:
+                       octstr_append(url, octstr_imm("&status=disconnected"));
+       }
+
+       /* create the caller and make a request */
+       caller = http_caller_create();
+       request_headers = http_create_empty_headers();
+       http_header_add(request_headers, "User-Agent", GW_NAME "/" GW_VERSION);
+       http_start_request(caller, HTTP_METHOD_GET, url, request_headers,
+                                          NULL, 1, NULL, NULL);
+
+       /* cleanup */
+       http_destroy_headers(request_headers);
+       octstr_destroy(smsc_id);
+       octstr_destroy(url);
+}
+
+
 static long smscconn_failure_reason_to_smpp_status(long reason)
 {
     switch (reason) {
@@ -1800,6 +1850,7 @@
                 mutex_unlock(smpp->conn->flow_mutex);
                 bb_smscconn_connected(smpp->conn);
             }
+            status_url_notify(smpp->conn);
             break;
 
         case bind_transceiver_resp:
@@ -1825,6 +1876,7 @@
                 mutex_unlock(smpp->conn->flow_mutex);
                 bb_smscconn_connected(smpp->conn);
             }
+            status_url_notify(smpp->conn);
             break;
 
         case bind_receiver_resp:
@@ -1851,6 +1903,7 @@
                 }
                 mutex_unlock(smpp->conn->flow_mutex);
             }
+            status_url_notify(smpp->conn);
             break;
 
         case unbind:
@@ -1859,6 +1912,7 @@
             smpp->conn->status = SMSCCONN_DISCONNECTED;
             mutex_unlock(smpp->conn->flow_mutex);
             *pending_submits = -1;
+            status_url_notify(smpp->conn);
             break;
 
         case unbind_resp:
@@ -1865,6 +1919,7 @@
             mutex_lock(smpp->conn->flow_mutex);
             smpp->conn->status = SMSCCONN_DISCONNECTED;
             mutex_unlock(smpp->conn->flow_mutex);
+            status_url_notify(smpp->conn);
             break;
 
         case generic_nack:
@@ -2174,6 +2229,7 @@
             mutex_lock(smpp->conn->flow_mutex);
             smpp->conn->status = SMSCCONN_RECONNECTING;
             mutex_unlock(smpp->conn->flow_mutex);
+            status_url_notify(smpp->conn);
             gwthread_sleep(smpp->conn->reconnect_delay);
         }
         /*
@@ -2219,11 +2275,12 @@
     if (transmitter || smpp->transmitter == -1) {
         debug("bb.smpp", 0, "SMSCConn %s shut down.",
               octstr_get_cstr(smpp->conn->name));
-        
+
         mutex_lock(smpp->conn->flow_mutex);
         smpp->conn->status = SMSCCONN_DEAD;
         smpp->conn->data = NULL;
         mutex_unlock(smpp->conn->flow_mutex);
+        status_url_notify(smpp->conn);
         
         smpp_destroy(smpp);
         bb_smscconn_killed();
Index: gw/smscconn.c
===================================================================
--- gw/smscconn.c       (revision 5043)
+++ gw/smscconn.c       (working copy)
@@ -270,6 +270,10 @@
     if (conn->log_file)
         conn->log_idx = log_open(octstr_get_cstr(conn->log_file), 
                                  conn->log_level, GW_EXCL); 
+
+    /* setting an external connection status url */
+    GET_OPTIONAL_VAL(conn->connection_status_url, "connection-status-url");
+
 #undef GET_OPTIONAL_VAL
 #undef SPLIT_OPTIONAL_VAL
 
Index: gw/smscconn_p.h
===================================================================
--- gw/smscconn_p.h     (revision 5043)
+++ gw/smscconn_p.h     (working copy)
@@ -245,6 +245,9 @@
 
 
     void *data;                        /* SMSC specific stuff */
+
+    smscconn_status_t prev_status; /* previous status, to determine the status 
changes */
+    Octstr *connection_status_url; /* external callback url for notifying 
about connection status changes */
 };
 
 /*
Index: gwlib/cfg.def
===================================================================
--- gwlib/cfg.def       (revision 5043)
+++ gwlib/cfg.def       (working copy)
@@ -424,6 +424,7 @@
     OCTSTR(generic-status-sent)
     OCTSTR(generic-status-error)
     OCTSTR(generic-foreign-id-regex)
+    OCTSTR(connection-status-url)
 )
 
 

Reply via email to