Re: [Fwd: error after receiving messages (modem is wavecom)]

Andrija Petrovic <[email protected]>
Newsgroups gmane.comp.mobile.kannel.devel
Message-ID <[email protected]>
Hi Stipe,

mi u Beogradu se jos odlicno secamo hrvatskog, srdacan pozdrav iz Srbije!

Stipe Tolj wrote:
> Hi Andrija,
>
> (prvo, ako znas hrvatski sto pripostavljam, dobar dan i pozdrav ;)
>
> Andrija Petrovic wrote:
>
>> Hi, Stipe,
>> well, I did a lot of tinkering on smsc_at.c (as you may have guessed 
>> by now), but I'm trying to send my (more or less) useful patches one 
>> by one.
>> At the moment, I'm still waiting for any reply (be it an approval or 
>> rejection) for my proposal for much quicker reading from SIM memory 
>> (May 28th 2006), and then I'll move on.
>> For the case you described, the simple cure is to re-queue the SMS to 
>> be sent, and try sending later.
>> That was the patch I intended to propose next.
>>
>> I can send the patch right away, it helped me a lot with a slightly 
>> different (but equally irritating) problem with Siemens family of 
>> modems, but, again, please consider my proposal on using the AT+CMGL 
>> command, it may help a lot of AT modem users...
>
> Can you isolate this patch to fix this specific thing, in order to 
> re-queue the messages and hence do a retry.
>
> Since this is a "failure"-fix patch it should go first, before the 
> "performance"-fix patch you did already propose.
>
> Stipe
here's a patch that solves several problems in communication with an AT 
modem.
There are several changes here:

1. The original logic of the device's main thread is changed so that 
sending SMSes is done at the end of the loop pass.
2. Moreover, only one SMS is sent per loop pass - due to the change in 
at2_send_messages.
3. Sending of the SMS message is tried only once.
4. If the sending of the SMS fails, TEMPORARY failure is reported 
instead of MALFORMED failure, so that the message is not destroyed, but 
re-queued instead.

So, if the sending of the SMS should fail, loop immediately goes to a 
wait state, waiting for "what modem has to say". Such behavior helped us 
with the Siemens family: when one wants to send an SMS at the moment 
when the modem is being notified from the GSM network about an incoming 
SMS, the sending fails and needs to be retried. But, this retry needs to 
be done after letting the modem report an incoming SMS. We believe that 
such behavior is proper for other families of AT modems. Failing to 
comply to such a behavior (sending fails => immediately try again, for 
example, just like the program does in the current version), leads to a 
situation when the modem does not receive any incoming messages from the 
mobile network. Senders get an error message "Message not sent" on their 
mobile phones when they try to send an SMS to the stalled modem. The 
only cure for Siemens modems is to turn them off (plug out the power), 
and turn them on again. On boot, all the SMS messages that were not 
received "pour" like an avalanche from the GSM network to the modem.
In our case, under heavy SMS loads (5-6 per minute, lasting for several 
hours), we usually could not stand for more than several minutes 
(several dozens of incoming SMS messages). This patch allowed us to 
receive thousands of SMS messages (it works, in fact, for 3 months now 
under varying load) with no major problems. (Minor problems will be 
addressed in a later patch proposal).
Note: number of sending retries and the retry period are set in the core 
section of the conf file (sms-resend-retry and sms-resend-freq, 
respectively).

Additionally, we needed to fix one more thing here:

5. When waiting for a response from the AT modem in 
at2_wait_modem_command, timeout limit is readjusted when a line arrives 
that is/should be followed by another line.
Currently, without this readjustment, the wait loop exits due to time 
out, and the program soon misaligns with the information flow from the 
modem, which leads to fatal misinterpretation of modem response. Again, 
this problem is easily encountered under heavy incoming SMS load.

Best regards,
Andrija
smsc_at.c.diff.32 (text/plain, 5.5 KB)
Index: gateway/gw/smsc/smsc_at.c
===================================================================
RCS file: /home/cvs/gateway/gw/smsc/smsc_at.c,v
retrieving revision 1.31
diff -u -b -B -a -u -r1.31 smsc_at.c
--- gateway/gw/smsc/smsc_at.c	23 May 2006 13:27:31 -0000	1.31
+++ gateway/gw/smsc/smsc_at.c	14 Jun 2006 13:55:03 -0000
@@ -653,6 +653,8 @@
             }
             if (octstr_search(line, octstr_imm("RING"), 0) != -1) {
                 at2_write_line(privdata, "ATH0");
+                time(&end_time);
+                end_time += timeout;
                 continue;
             }
             if (octstr_search(line, octstr_imm("+CPIN: READY"), 0) != -1) {
@@ -679,6 +681,8 @@
                       octstr_get_cstr(privdata->name), octstr_get_cstr(line));
                 gwlist_append(privdata->pending_incoming_messages, line);
                 line = NULL;
+                time(&end_time);
+                end_time += timeout;
                 continue;
             }
             if (octstr_search(line, octstr_imm("+CMT:"), 0) != -1 ||
@@ -719,6 +723,8 @@
                         O_DESTROY(pdu);
                     }
                 }
+                time(&end_time);
+                end_time += timeout;
                 continue;
             }
             if ((octstr_search(line, octstr_imm("+CMGS:"),0) != -1) && (output)) {
@@ -732,6 +738,9 @@
                           octstr_get_cstr(privdata->name));
                 else
                     *output = temp;
+                time(&end_time);
+                end_time += timeout;
+                continue;
             }
             /* finally check if we received a generic error */
             if (octstr_search(line, octstr_imm("ERROR"), 0) != -1) {
@@ -1177,11 +1186,6 @@
 
     idle_timeout = 0;
     while (!privdata->shutdown) {
-        l = gw_prioqueue_len(privdata->outgoing_queue);
-        if (l > 0) {
-            at2_send_messages(privdata);
-            idle_timeout = time(NULL);
-        } else
             at2_wait_modem_command(privdata, 1, 0, NULL);
 
         while (gwlist_len(privdata->pending_incoming_messages) > 0) {
@@ -1208,6 +1212,11 @@
             }
             memory_poll_timeout = time(NULL);
         }
+        l = gw_prioqueue_len(privdata->outgoing_queue);
+        if (l > 0) {
+            at2_send_messages(privdata);
+            idle_timeout = time(NULL);
+        }
     }
     at2_close_device(privdata);
     mutex_lock(conn->flow_mutex);
@@ -1973,15 +1982,12 @@
 static void at2_send_messages(PrivAT2data *privdata)
 {
     Msg *msg;
-
-    do {
         if (privdata->modem->enable_mms && 
             gw_prioqueue_len(privdata->outgoing_queue) > 1)
             at2_send_modem_command(privdata, "AT+CMMS=2", 0, 0);
 
         if ((msg = gw_prioqueue_remove(privdata->outgoing_queue)))
             at2_send_one_message(privdata, msg);
-    } while (msg);
 }
 
 
@@ -1990,7 +1996,6 @@
     unsigned char command[500];
     int ret = -1;
     char sc[3];
-    int retries = RETRY_SEND;
 
     if (octstr_len(privdata->my_number)) {
         octstr_destroy(msg->sms.sender);
@@ -2010,16 +2015,13 @@
 
     if (msg_type(msg) == sms) {
         Octstr *pdu;
+        int msg_id = -1;
 
         if ((pdu = at2_pdu_encode(msg, privdata)) == NULL) {
             error(2, "AT2[%s]: Error encoding PDU!",octstr_get_cstr(privdata->name));
             return;
         }	
 
-        ret = -99;
-        retries = RETRY_SEND;
-        while ((ret != 0) && (retries-- > 0)) {
-            int msg_id = -1;
             /* 
              * send the initial command and then wait for > 
              */
@@ -2029,13 +2031,15 @@
             debug("bb.smsc.at2", 0, "AT2[%s]: send command status: %d",
                   octstr_get_cstr(privdata->name), ret);
 
-            if (ret != 1) /* > only! */
-                continue;
+        if (ret == 1) {/* > only! */
                 
             /* 
              * Ok the > has been see now so we can send the PDU now and a 
              * control Z but no CR or LF 
              * 
+             * ret is currently 1, but on successful sending of the PDU
+             * it will be 0
+             * 
              * We will handle the 'nokiaphone' types a bit differently, since
              * they have a generic error in accepting PDUs that are "too big".
              * Which means, PDU that are longer then 18 bytes get truncated by
@@ -2080,10 +2084,11 @@
             ret = at2_wait_modem_command(privdata, 20, 0, &msg_id);
             debug("bb.smsc.at2", 0, "AT2[%s]: send command status: %d",
                   octstr_get_cstr(privdata->name), ret);
-
-            if (ret != 0) /* OK only */
-                continue;
-
+        }
+        if (ret != 0) {
+            bb_smscconn_send_failed(privdata->conn, msg,
+                    SMSCCONN_FAILED_TEMPORARILY, octstr_create("Requeueing SMS to be sent"));
+        }else{
             /* store DLR message if needed for SMSC generated delivery reports */
             if (DLR_IS_ENABLED_DEVICE(msg->sms.dlr_mask)) {
                 if (msg_id == -1)
@@ -2101,15 +2106,6 @@
             bb_smscconn_sent(privdata->conn, msg, NULL);
         }
 
-        if (ret != 0) {
-            /*
-             * no need to do counter_increase(privdata->conn->failed) here,
-             * since bb_smscconn_send_failed() will inc the counter on
-             * SMSCCONN_FAILED_MALFORMED
-             */
-            bb_smscconn_send_failed(privdata->conn, msg,
-	        SMSCCONN_FAILED_MALFORMED, octstr_create("MALFORMED"));
-        }
 
         O_DESTROY(pdu);
     }
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.