Hi Alex,

Thanks a lot for the followup.

1) Changed to http_get_real(), with blocking==1. Seems to work fine in blocking mode for now. Hopefully will not leak memory (or will it? I'm a bit confused here).

2) Moved the status_url_notify() to bb_smscconn.c, added it to bb_smscconn_ready() and bb_smscconn_connected(); also introduced bb_smsc_disconnected().

I will continue to work on it, I'm planning to add templating and notifications to other smsc types soon.

On 2013-08-16 2:44 PM, Alexander Malysh wrote:
Hi,

idea is OK but implementation is wrong.

1) +    http_start_request(caller, HTTP_METHOD_GET, url, request_headers,
+                                          NULL, 1, NULL, NULL);

I'm missing consumer who reads completed requests otherwise you will leak 
memory.

2) why do you add it to smpp module instead of to add it to bb_smscconn? Here 
it will work for all
smsc types.

Alex

Am 13.08.2013 um 11:32 schrieb Semion Spivak <[email protected]>:

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
<smsc_status_url.patch>


--
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 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/bb_smscconn.c
===================================================================
--- gw/bb_smscconn.c    (revision 5043)
+++ gw/bb_smscconn.c    (working copy)
@@ -167,7 +167,9 @@
 static void shutdown_concat_handler(void);
 static int check_concatenation(Msg **msg, Octstr *smscid);
 static void clear_old_concat_parts(void);
+static void status_url_notify(SMSCConn *conn);
 
+
 /*---------------------------------------------------------------------------
  * CALLBACK FUNCTIONS
  *
@@ -178,16 +180,25 @@
 {
     gwlist_add_producer(flow_threads);
     gwlist_add_producer(incoming_sms);
+    status_url_notify(conn);
 }
 
 
 void bb_smscconn_connected(SMSCConn *conn)
 {
-    if (router_thread >= 0)
-       gwthread_wakeup(router_thread);
+       if (router_thread >= 0)
+               gwthread_wakeup(router_thread);
+
+       status_url_notify(conn);
 }
 
 
+void bb_smscconn_disconnected(SMSCConn *conn)
+{
+       status_url_notify(conn);
+}
+
+
 void bb_smscconn_killed(void)
 {
     /* NOTE: after status has been set to SMSCCONN_DEAD, bearerbox
@@ -653,8 +664,61 @@
 }
 
 
+/*
+ * Make a blocking request to conn->connection_status_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, *smsc_id, *final_url, *reply_body;
+       List *request_headers, *reply_headers;
+       int status, method;
+       void *id;
 
+       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:
+                       octstr_append(url, octstr_imm("&status=active"));
+                       break;
+               case SMSCCONN_ACTIVE_RECV:
+                       octstr_append(url, octstr_imm("&status=active_recv"));
+                       break;
+               case SMSCCONN_DISCONNECTED:
+                       octstr_append(url, octstr_imm("&status=disconnected"));
+                       break;
+               case SMSCCONN_DEAD:
+                       octstr_append(url, octstr_imm("&status=dead"));
+       }
+
+       /* create the User-Agent headers and make a request */
+       request_headers = http_create_empty_headers();
+       http_header_add(request_headers, "User-Agent", GW_NAME "/" GW_VERSION);
+       status = http_get_real(HTTP_METHOD_GET, url, request_headers,
+                                                  &final_url, &reply_headers, 
&reply_body);
+
+       /* cleanup */
+       http_destroy_headers(request_headers);
+       http_destroy_headers(reply_headers);
+       octstr_destroy(smsc_id);
+       octstr_destroy(final_url);
+       octstr_destroy(reply_body);
+}
+
+
 /*-------------------------------------------------------------
  * public functions
  *
Index: gw/smsc/smsc_smpp.c
===================================================================
--- gw/smsc/smsc_smpp.c (revision 5043)
+++ gw/smsc/smsc_smpp.c (working copy)
@@ -1787,6 +1787,7 @@
                 mutex_lock(smpp->conn->flow_mutex);
                 smpp->conn->status = SMSCCONN_DISCONNECTED;
                 mutex_unlock(smpp->conn->flow_mutex);
+                bb_smscconn_disconnected(smpp->conn);
                 if (pdu->u.bind_transmitter_resp.command_status == 
SMPP_ESME_RINVSYSID ||
                     pdu->u.bind_transmitter_resp.command_status == 
SMPP_ESME_RINVPASWD ||
                     pdu->u.bind_transmitter_resp.command_status == 
SMPP_ESME_RINVSYSTYP) {
@@ -1812,6 +1813,7 @@
                  mutex_lock(smpp->conn->flow_mutex);
                  smpp->conn->status = SMSCCONN_DISCONNECTED;
                  mutex_unlock(smpp->conn->flow_mutex);
+                 bb_smscconn_disconnected(smpp->conn);
                  if (pdu->u.bind_transceiver_resp.command_status == 
SMPP_ESME_RINVSYSID ||
                      pdu->u.bind_transceiver_resp.command_status == 
SMPP_ESME_RINVPASWD ||
                      pdu->u.bind_transceiver_resp.command_status == 
SMPP_ESME_RINVSYSTYP) {
@@ -1837,6 +1839,7 @@
                  mutex_lock(smpp->conn->flow_mutex);
                  smpp->conn->status = SMSCCONN_DISCONNECTED;
                  mutex_unlock(smpp->conn->flow_mutex);
+                 bb_smscconn_disconnected(smpp->conn);
                  if (pdu->u.bind_receiver_resp.command_status == 
SMPP_ESME_RINVSYSID ||
                      pdu->u.bind_receiver_resp.command_status == 
SMPP_ESME_RINVPASWD ||
                      pdu->u.bind_receiver_resp.command_status == 
SMPP_ESME_RINVSYSTYP) {
@@ -1858,6 +1861,7 @@
             mutex_lock(smpp->conn->flow_mutex);
             smpp->conn->status = SMSCCONN_DISCONNECTED;
             mutex_unlock(smpp->conn->flow_mutex);
+            bb_smscconn_disconnected(smpp->conn);
             *pending_submits = -1;
             break;
 
@@ -1865,6 +1869,7 @@
             mutex_lock(smpp->conn->flow_mutex);
             smpp->conn->status = SMSCCONN_DISCONNECTED;
             mutex_unlock(smpp->conn->flow_mutex);
+            bb_smscconn_disconnected(smpp->conn);
             break;
 
         case generic_nack:
@@ -2174,6 +2179,7 @@
             mutex_lock(smpp->conn->flow_mutex);
             smpp->conn->status = SMSCCONN_RECONNECTING;
             mutex_unlock(smpp->conn->flow_mutex);
+            bb_smscconn_disconnected(smpp->conn);
             gwthread_sleep(smpp->conn->reconnect_delay);
         }
         /*
@@ -2219,11 +2225,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);
+        bb_smscconn_disconnected(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