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)
)