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