Re: [patch] bearerbox acknowledged sendsms (fixed)

Kalle Marjola <[email protected]>
Newsgroups gmane.comp.mobile.kannel.devel
Organization Enpocket
Message-ID <[email protected]>
(patch attached)

Why am I using this FC2 when all it causes is problems..


-- 
 &Kalle Marjola ::: Development ::: Helsinki ::: Enpocket
confirmed_sendsms.patch (text/x-patch, 15.8 KB)
? access.log
? check.log.new
? check_bb.log
? check_bb.tmp
? check_fake.log
? check_headers.log
? check_http.log
? check_http_list.log
? check_http_server.log
? check_https_server.log
? check_ppg.tmp
? check_sendsms.log
? check_sendsms_bb.log
? check_sendsms_sms.log
? check_sendsms_smsc.log
? check_smpp_bb.log
? check_smpp_drive.log
? check_wap.log
? check_wap.tmp
? confirmed_sendsms.patch
? kannel.log
? kannel.store
? store-spool
? gwlib/gw_uuid_types.h
? test/test_boxc
? test/test_mime_multipart
? test/test_pcre
? test/test_prioqueue
? test/test_regex
? test/test_uuid
Index: gw/smsbox.c
===================================================================
RCS file: /home/cvs/gateway/gw/smsbox.c,v
retrieving revision 1.252
diff -u -r1.252 smsbox.c
--- gw/smsbox.c	3 Sep 2004 12:42:33 -0000	1.252
+++ gw/smsbox.c	15 Dec 2004 08:52:25 -0000
@@ -130,6 +130,15 @@
 int charset_processing (Octstr *charset, Octstr *text, int coding);
 static long get_tag(Octstr *body, Octstr *tag, Octstr **value, long pos, int nostrip);
 
+/* for delayed HTTP answers.
+ * Dict key is uuid, value is HTTPClient pointer
+ * of open transaction
+ */
+
+static int immediate_sendsms_reply = 0;
+static Dict *client_dict = NULL;
+static List *sendsms_reply_hdrs = NULL;
+
 /***********************************************************************
  * Communication with the bearerbox.
  */
@@ -150,6 +159,60 @@
     write_to_bearerbox(msg);
 }
 
+/*
+ * Handle delayed reply to HTTP sendsms client, if any
+ */
+static void delayed_http_reply(Msg *msg)
+{
+    HTTPClient *client;
+    Octstr *os, *answer;
+    char id[UUID_STR_LEN + 1];
+    int status;
+	  
+    uuid_unparse(msg->ack.id, id);
+    os = octstr_create(id);
+    debug("sms.http", 0, "Got ACK (%d) of %s", msg->ack.nack, octstr_get_cstr(os));
+    client = dict_remove(client_dict, os);
+    if (client == NULL) {
+        debug("sms.http", 0, "No client - multi-send or ACK to pull-reply");
+        octstr_destroy(os);
+        return;
+    }
+    /* XXX  this should be fixed so that we really wait for DLR
+     *      SMSC accept/deny before doing this - but that is far
+     *      more slower, a bit more complex, and is done later on
+     */
+
+    switch (msg->ack.nack) {
+      case ack_success:
+        status = HTTP_ACCEPTED;
+        answer = octstr_create("0: Accepted for delivery");
+        break;
+      case ack_buffered:
+        status = HTTP_ACCEPTED;
+        answer = octstr_create("3: Queued for later delivery");
+        break;
+      case ack_failed:
+        status = HTTP_FORBIDDEN;
+        answer = octstr_create("Not routable. Do not try again.");
+        break;
+      case ack_failed_tmp:
+        status = HTTP_SERVICE_UNAVAILABLE;
+        answer = octstr_create("Temporal failure, try again later.");
+        break;
+      default:
+	error(0, "Strange reply from bearerbox!");
+        status = HTTP_SERVICE_UNAVAILABLE;
+        answer = octstr_create("Temporal failure, try again later.");
+        break;
+    }
+
+    http_send_reply(client, status, sendsms_reply_hdrs, answer);
+
+    octstr_destroy(answer);
+    octstr_destroy(os);
+}
+
 
 /*
  * Read an Msg from the bearerbox and send it to the proper receiver
@@ -189,10 +252,9 @@
 	    total++;
 	    list_produce(smsbox_requests, msg);
 	} else if (msg_type(msg) == ack) {
-	    /*
-	     * do nothing for now. Later we will handle this
-	     * gracefully...
-	     */
+
+	    if (!immediate_sendsms_reply)
+		delayed_http_reply(msg);
 	    msg_destroy(msg);
 	} else {
 	    warning(0, "Received other message than sms/admin, ignoring!");
@@ -1874,9 +1936,27 @@
 
 
 
+static void store_uuid(Msg *msg, Octstr **stored_uuid)
+{
+    char id[UUID_STR_LEN + 1];
+
+    gw_assert(msg != NULL);
+    gw_assert(*stored_uuid == NULL);
+    gw_assert(!immediate_sendsms_reply);
+    
+    uuid_unparse(msg->sms.id, id);
+    *stored_uuid = octstr_create(id);
+
+    debug("sms.http", 0, "Stored UUID %s", octstr_get_cstr(*stored_uuid));
+
+    /* this octstr is then used to store the HTTP client into 
+     * client_dict, if need to, in sendsms_thread */
+}
+
 
 
 static Octstr *smsbox_req_handle(URLTranslation *t, Octstr *client_ip,
+				 Octstr **stored_uuid,
 				 Octstr *from, Octstr *to, Octstr *text, 
 				 Octstr *charset, Octstr *udh, Octstr *smsc,
 				 int mclass, int mwi, int coding, int compress, 
@@ -2231,6 +2311,14 @@
 	             udh == NULL ? ( text == NULL ? "" : octstr_get_cstr(text) ) : "<< UDH >>");
         }
     }
+    /* Store id if needed for a delayed HTTP reply */
+
+    if (!immediate_sendsms_reply) {
+	store_uuid(msg, stored_uuid);
+    }
+    
+
+
     msg_destroy(msg);
     list_destroy(receiver, octstr_destroy_item);
     list_destroy(allowed, octstr_destroy_item);
@@ -2379,7 +2467,8 @@
  * Create and send an SMS message from an HTTP request.
  * Args: args contains the CGI parameters
  */
-static Octstr *smsbox_req_sendsms(List *args, Octstr *client_ip, int *status)
+static Octstr *smsbox_req_sendsms(List *args, Octstr *client_ip, int *status,
+				  Octstr **stored_uuid)
 {
     URLTranslation *t = NULL;
     Octstr *tmp_string;
@@ -2477,7 +2566,7 @@
 	return octstr_create("Empty receiver number not allowed, rejected");
     }
 
-    return smsbox_req_handle(t, client_ip, from, to, text, charset, udh,
+    return smsbox_req_handle(t, client_ip, stored_uuid, from, to, text, charset, udh,
 			     smsc, mclass, mwi, coding, compress, validity, 
 			     deferred, status, dlr_mask, dlr_url, account,
 			     pid, alt_dcs, rpi, NULL, binfo, priority);
@@ -2490,7 +2579,8 @@
  * Args: args contains the CGI parameters
  */
 static Octstr *smsbox_sendsms_post(List *headers, Octstr *body,
-				   Octstr *client_ip, int *status)
+				   Octstr *client_ip, int *status,
+				   Octstr **stored_uuid)
 {
     URLTranslation *t = NULL;
     Octstr *user, *pass, *ret, *type;
@@ -2586,7 +2676,7 @@
 	}
 
 	if (ret == NULL)
-	    ret = smsbox_req_handle(t, client_ip, from, to, body, charset,
+	    ret = smsbox_req_handle(t, client_ip, stored_uuid, from, to, body, charset,
 				    udh, smsc, mclass, mwi, coding, compress, 
 				    validity, deferred, status, dlr_mask, 
 				    dlr_url, account, pid, alt_dcs, rpi, tolist,
@@ -2696,7 +2786,8 @@
  * otherwise read the configuration from the configuration file.
  * Args: list contains the CGI parameters
  */
-static Octstr *smsbox_req_sendota(List *list, Octstr *client_ip, int *status)
+static Octstr *smsbox_req_sendota(List *list, Octstr *client_ip, int *status,
+				  Octstr **stored_uuid)
 {
     Octstr *id, *from, *phonenumber, *smsc, *ota_doc, *doc_type, *account;
     CfgGroup *grp;
@@ -2851,7 +2942,11 @@
         *status = HTTP_INTERNAL_SERVER_ERROR;
         return octstr_create("Sending failed.");
     }
+    else if (!immediate_sendsms_reply) {
+	store_uuid(msg, stored_uuid);
+    }
 
+    
     *status = HTTP_ACCEPTED;
     return octstr_create("Sent.");
 }
@@ -2866,7 +2961,8 @@
  * parameters are not used but the POST contains the XML body itself.
  */
 static Octstr *smsbox_sendota_post(List *headers, Octstr *body,
-                                   Octstr *client_ip, int *status)
+                                   Octstr *client_ip, int *status,
+				   Octstr **stored_uuid)
 {
     Octstr *name, *val, *ret;
     Octstr *from, *to, *id, *user, *pass, *smsc;
@@ -2958,54 +3054,57 @@
 	    ret = octstr_create("Unsupported content-type, rejected");
 	} else {
 
-        /* 
-         * ok, this is want we expect
-         * now lets compile the whole thing 
-         */
-        ota_doc = octstr_duplicate(body);
+	    /* 
+	     * ok, this is want we expect
+	     * now lets compile the whole thing 
+	     */
+	    ota_doc = octstr_duplicate(body);
 
-        if ((r = ota_pack_message(&msg, ota_doc, doc_type, from, to)) < 0) {
-            *status = HTTP_BAD_REQUEST;
-            msg_destroy(msg);
-            if (r == -2) {
-                ret = octstr_create("Erroneous document type, cannot"
-                                     " compile\n");
-                goto error;
-            }
-            else if (r == -1) {
-	           ret = octstr_create("Erroneous ota source, cannot compile\n");
-               goto error;
-            }
-        }
+	    if ((r = ota_pack_message(&msg, ota_doc, doc_type, from, to)) < 0) {
+		*status = HTTP_BAD_REQUEST;
+		msg_destroy(msg);
+		if (r == -2) {
+		    ret = octstr_create("Erroneous document type, cannot"
+					" compile\n");
+		    goto error;
+		}
+		else if (r == -1) {
+		    ret = octstr_create("Erroneous ota source, cannot compile\n");
+		    goto error;
+		}
+	    }
 
-        /* we still need to check if smsc is forced for this */
-        if (urltrans_forced_smsc(t)) {
-            msg->sms.smsc_id = octstr_duplicate(urltrans_forced_smsc(t));
-            if (smsc)
-                info(0, "send-sms request smsc id ignored, as smsc id forced to %s",
-                     octstr_get_cstr(urltrans_forced_smsc(t)));
-        } else if (smsc) {
-            msg->sms.smsc_id = octstr_duplicate(smsc);
-        } else if (urltrans_default_smsc(t)) {
-            msg->sms.smsc_id = octstr_duplicate(urltrans_default_smsc(t));
-        } else
-            msg->sms.smsc_id = NULL;
+	    /* we still need to check if smsc is forced for this */
+	    if (urltrans_forced_smsc(t)) {
+		msg->sms.smsc_id = octstr_duplicate(urltrans_forced_smsc(t));
+		if (smsc)
+		    info(0, "send-sms request smsc id ignored, as smsc id forced to %s",
+			 octstr_get_cstr(urltrans_forced_smsc(t)));
+	    } else if (smsc) {
+		msg->sms.smsc_id = octstr_duplicate(smsc);
+	    } else if (urltrans_default_smsc(t)) {
+		msg->sms.smsc_id = octstr_duplicate(urltrans_default_smsc(t));
+	    } else
+		msg->sms.smsc_id = NULL;
 
-        info(0, "%s <%s> <%s>", octstr_get_cstr(sendota_url), 
-             id ? octstr_get_cstr(id) : "XML", octstr_get_cstr(to));
+	    info(0, "%s <%s> <%s>", octstr_get_cstr(sendota_url), 
+		 id ? octstr_get_cstr(id) : "XML", octstr_get_cstr(to));
     
-        r = send_message(t, msg); 
-        msg_destroy(msg);
+	    r = send_message(t, msg); 
+	    msg_destroy(msg);
 
-        if (r == -1) {
-            error(0, "sendota_request: failed");
-            *status = HTTP_INTERNAL_SERVER_ERROR;
-            ret = octstr_create("Sending failed.");
-        }
+	    if (r == -1) {
+		error(0, "sendota_request: failed");
+		*status = HTTP_INTERNAL_SERVER_ERROR;
+		ret = octstr_create("Sending failed.");
+	    }
+	    else if (!immediate_sendsms_reply) {
+		store_uuid(msg, stored_uuid);
+	    }
 
-        *status = HTTP_ACCEPTED;
-        ret = octstr_create("Sent.");
-    }
+	    *status = HTTP_ACCEPTED;
+	    ret = octstr_create("Sent.");
+	}
     }    
     
 error:
@@ -3018,17 +3117,15 @@
 
 
 static void sendsms_thread(void *arg)
-{
+ {
     HTTPClient *client;
     Octstr *ip, *url, *body, *answer;
-    List *hdrs, *args, *reply_hdrs;
+    List *hdrs, *args;
     int status;
+    Octstr *stored_uuid;
 
-    reply_hdrs = http_create_empty_headers();
-    http_header_add(reply_hdrs, "Content-type", "text/html");
-    http_header_add(reply_hdrs, "Pragma", "no-cache");
-    http_header_add(reply_hdrs, "Cache-Control", "no-cache");
-
+    stored_uuid = NULL;
+    
     for (;;) {
     	client = http_accept_request(sendsms_port, &ip, &url, &hdrs, &body, 
 	    	    	    	     &args);
@@ -3051,9 +3148,9 @@
 	 * related routine handle the checking
 	 */
 	if (body == NULL)
-	    answer = smsbox_req_sendsms(args, ip, &status);
+	    answer = smsbox_req_sendsms(args, ip, &status, &stored_uuid);
 	else
-	    answer = smsbox_sendsms_post(hdrs, body, ip, &status);
+	    answer = smsbox_sendsms_post(hdrs, body, ip, &status, &stored_uuid);
     }
     /* XML-RPC */
     else if (octstr_compare(url, xmlrpc_url) == 0)
@@ -3071,9 +3168,9 @@
     else if (octstr_compare(url, sendota_url) == 0)
     {
 	if (body == NULL)
-            answer = smsbox_req_sendota(args, ip, &status);
+            answer = smsbox_req_sendota(args, ip, &status, &stored_uuid);
         else
-            answer = smsbox_sendota_post(hdrs, body, ip, &status);
+            answer = smsbox_sendota_post(hdrs, body, ip, &status, &stored_uuid);
     }
     /* add aditional URI compares here */
     else {
@@ -3084,18 +3181,22 @@
 	debug("sms.http", 0, "Status: %d Answer: <%s>", status,
           octstr_get_cstr(answer));
 
-    octstr_destroy(ip);
-    octstr_destroy(url);
-    http_destroy_headers(hdrs);
-    octstr_destroy(body);
-    http_destroy_cgiargs(args);
-	
-    http_send_reply(client, status, reply_hdrs, answer);
+	octstr_destroy(ip);
+	octstr_destroy(url);
+	http_destroy_headers(hdrs);
+	octstr_destroy(body);
+	http_destroy_cgiargs(args);
 
-    octstr_destroy(answer);
+	if (immediate_sendsms_reply || status != HTTP_ACCEPTED || stored_uuid == NULL)
+	  http_send_reply(client, status, sendsms_reply_hdrs, answer);
+	else {
+	  debug("sms.http", 0, "Delayed reply - wait for bearerbox");
+	  dict_put(client_dict, stored_uuid, client);
+	  octstr_destroy(stored_uuid);
+	}
+	octstr_destroy(answer);
     }
 
-    http_destroy_headers(reply_hdrs);
 }
 
 
@@ -3306,6 +3407,9 @@
 	     octstr_get_cstr(global_sender));
     }
     
+    /* should smsbox reply to sendsms immediate or wait for bearerbox ack */
+    cfg_get_bool(&immediate_sendsms_reply, grp, octstr_imm("immediate-sendsms-reply"));
+
     /* determine which timezone we use for access logging */
     if ((p = cfg_get(grp, octstr_imm("access-log-time"))) != NULL) {
         lf = (octstr_case_compare(p, octstr_imm("gmt")) == 0) ? 0 : 1;
@@ -3411,6 +3515,13 @@
     if (urltrans_add_cfg(translations, cfg) == -1)
 	panic(0, "urltrans_add_cfg failed");
 
+    client_dict = dict_create(32, NULL);
+    sendsms_reply_hdrs = http_create_empty_headers();
+    http_header_add(sendsms_reply_hdrs, "Content-type", "text/html");
+    http_header_add(sendsms_reply_hdrs, "Pragma", "no-cache");
+    http_header_add(sendsms_reply_hdrs, "Cache-Control", "no-cache");
+
+
     caller = http_caller_create();
     smsbox_requests = list_create();
     smsbox_http_requests = list_create();
@@ -3474,6 +3585,9 @@
     if (black_list_regex != NULL) gw_regex_destroy(black_list_regex);
     cfg_destroy(cfg);
 
+    dict_destroy(client_dict); /* XXX is this right location? */
+    http_destroy_headers(sendsms_reply_hdrs); /* ditto */
+
     /* 
      * Just sleep for a while to get bearerbox chance to restart.
      * Otherwise we will fail while trying to connect to bearerbox!
Index: gw/smskannel.conf
===================================================================
RCS file: /home/cvs/gateway/gw/smskannel.conf,v
retrieving revision 1.16
diff -u -r1.16 smskannel.conf
--- gw/smskannel.conf	13 Dec 2004 08:24:56 -0000	1.16
+++ gw/smskannel.conf	15 Dec 2004 08:52:25 -0000
@@ -78,7 +78,9 @@
 group = smsbox
 bearerbox-host = localhost
 sendsms-port = 13013
-#global-sender = 13013
+# uncomment following for the old sendsms behaviour
+#immediate-sendsms-reply = true   
+global-sender = 13013
 #sendsms-chars = "0123456789 +-"
 #log-file = "/tmp/smsbox.log"
 #log-level = 0
Index: gwlib/cfg.def
===================================================================
RCS file: /home/cvs/gateway/gwlib/cfg.def,v
retrieving revision 1.108
diff -u -r1.108 cfg.def
--- gwlib/cfg.def	13 Dec 2004 08:24:56 -0000	1.108
+++ gwlib/cfg.def	15 Dec 2004 08:52:26 -0000
@@ -266,6 +266,7 @@
     OCTSTR(http-queue-delay)
     OCTSTR(white-list-regex)
     OCTSTR(black-list-regex)
+    OCTSTR(immediate-sendsms-reply)
 )
 
 
Index: gwlib/http.h
===================================================================
RCS file: /home/cvs/gateway/gwlib/http.h,v
retrieving revision 1.63
diff -u -r1.63 http.h
--- gwlib/http.h	22 Jan 2004 14:08:25 -0000	1.63
+++ gwlib/http.h	15 Dec 2004 08:52:26 -0000
@@ -158,7 +158,8 @@
     HTTP_UNSUPPORTED_MEDIA_TYPE    = 415,
     HTTP_INTERNAL_SERVER_ERROR     = 500,
     HTTP_NOT_IMPLEMENTED           = 501,
-    HTTP_BAD_GATEWAY               = 502
+    HTTP_BAD_GATEWAY               = 502,
+    HTTP_SERVICE_UNAVAILABLE       = 503
 };
 
 /*
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.