Re: Feature request/wish for Kannel
Andrija Petrovic <[email protected]>
| Newsgroups | gmane.comp.mobile.kannel.devel |
|---|---|
| Message-ID | <[email protected]> |
Sorry for the delay in responding, but, apart from other problems, I had
to struggle with too many features I have built into my version of
smsc_at until I got it working. Of course, once I made it work, I never
cleared out all the unneeded stuff...
Anyhow, here's the patch that should keep the modem in a regular state
under any exploitation circumstances.
The main goal of the patch is to follow a simple rule:
"If the modem reports an error during SMS sending, don't retry the
sending, but ask it what it's got to say"
So, any loops related to SMS sending are removed:
1. loop in at2_send_messages has been removed. Messages will be sent one
by one from the at2_device_thread main loop - while(!privdata->shutdown)
2. loop in at2_send_one_message has been removed, so the single SMS
sending either succeeds or fails
Consequences of the patch:
1. the define RETRY_SEND has been renamed to RETRY_WRITE (because it is
also used in writing a line to the modem), there is no RETRY_SEND any more
2. the user needs to rely upon the sms-resend-retry mechanism - this
works fine AFAIK. E.g. put sms-resend-retry = 5 in the conf file.
Without such a line, kannel will not try to resend the SMS
Best regards,
Andrija
Alexander Malysh wrote:
> Hi,
>
> please post your patches and I will look how to integrate and which part of
> it into mainline. I'm also interested in smsc_at working...
>
> Andrija Petrovic wrote:
>
>
>> This mail will be slightly off topic, but I need to comment on the issue
>> the author has already recognized :)
>>
>> Yes, that issue when everything looks "fine" - but you need to restart
>> Kannel to get SMSes in masses - is something that I've been struggling
>> for few months in the spring of 2006.
>>
>> I solved the problem (tested on the Siemens family of GSM modems), and
>> happily use my version of Kannel since. I presented the first part of
>> the solution somewhere at the end of May 2006, but got no response - so
>> I gave up committing to devel-kannel (since my sole concern is smsc_at).
>>
>> Long story short, the problem is in forcing the modem to send an SMS -
>> even if it reports an error.
>>
>> In the official Kannel version, there is a RETRY_SEND (equal to 3, in
>> smsc_at.h) define that defines how many times an SMS sending process
>> needs to be retried. It's purpose is illogical - having a complete and
>> logical sms-resend-retry mechanism built in the Kannel logic.
>>
>> In the official Kannel version, if the software receives an error
>> response while trying to send the SMS, it simply tries again in a loop
>> (3 times, due to the value of RETRY_SEND). Such a behavior confuses the
>> GSM modem - on the first forcible SMS sending retry.
>>
>> If the software should report unsuccessful SMS sending through
>> bb_smscconn_send_failed(privdata->conn, msg,
>> SMSCCONN_FAILED_TEMPORARILY, octstr_create("ERROR"));
>>
>> and let the modem "relax" (by asking it if there are new incoming SMS
>> messages pending) when it receives an error response from the modem, I
>> have seen that Siemens modems (TC 45, MC 39i) would never expose the
>> notorious issue.
>>
>> I have never encountered the issue in the last 15 months - since I
>> altered the logic within smsc_at.c. With the RETRY_SEND mechanism, I
>> have had the issue more than once daily (I operate the GSM modems in a
>> rather intense SMS traffic).
>>
>> Hope this comment will lead to a usable official version of smsc_at.c in
>> the future.
>>
>> Best regards,
>> Andrija Petrovic
>>
>> Andreas Fink wrote:
>>
>>> this is kinda dangerous as the at command and response are in a tight
>>> loop.
>>> you could very easily screw up kannel.
>>>
>>> For example you set echo off/on and kannel would get confused.
>>> The problem you are seeing is usually not related to information the
>>> operator sends which get reflected into AT commands.
>>>
>>> But I have seen similar issues where everything looks "fine" but SMS
>>> just dont hit the phone. After restarting kannel, the queued SMS come
>>> in in masses.
>>>
>>> My approach to this problem would be to use the kannel keepalive
>>> mechanism not only to send a AT and wait for Ok but to go through the
>>> initialization sequence again.
>>>
>>>
>>> On 05.09.2007, at 11:39, Nis - Kannel wrote:
>>>
>>>
>>>> This seems the only maillist for contacting the developers behind
>>>> Kannel. If not, please tell me how or where.
>>>>
>>>> I have been using Kannel for some time now and not had any problemes
>>>> since i got it running.
>>>> The troubles that i get, is releated to the modem/mobile devices.
>>>>
>>>> So my request/wish is a Kannel utility for sending AT commands to the
>>>> modem/mobile devices.
>>>> Some of the mobile companies, likes to send new settings or clock
>>>> adjustments without warning.
>>>> And after one of those, the mobile no longer working without
>>>> restarting Kannel.
>>>> Some mobiles just cant clear the stored sms and runs out of space.
>>>> If a SIM card i failing, it can take days before it's noticed.
>>>> Or any othter things that can be monitored by using AT commands and
>>>> thereby prevented.
>>>>
>>>> Since Kannel locks the connection, other programs can't access the
>>>> device.
>>>> Could it not be possible to make somekind of pipe through Kannel, so
>>>> someone can inject AT commands and get the reply from the device?
>>>> Then someone can make there own scripts for sending and reading AT
>>>> commands.
>>>>
>>>> Any reply related is much appreciated.
>>>>
>>>> /Nis
>>>>
>>>
>>>
>>>
>>> Andreas Fink
>>>
>>> Fink Consulting GmbH
>>> Global Networks Schweiz AG
>>> BebbiCell AG
>>>
>>> ---------------------------------------------------------------
>>> Tel: +41-61-6666330 Fax: +41-61-6666331 Mobile: +41-79-2457333
>>> Address: Clarastrasse 3, 4058 Basel, Switzerland
>>> E-Mail: [email protected] <mailto:[email protected]>
>>> www.finkconsulting.com www.global-networks.ch www.bebbicell
>>> <http://www.bebbicell>.ch
>>> ---------------------------------------------------------------
>>> ICQ: 8239353 MSN: [email protected] <mailto:[email protected]> AIM: smsrelay
>>> Skype: andreasfink
>>> Yahoo: finkconsulting SMS: +41792457333
>>>
>>>
>>>
>>>
>>>
>>>
>
>
smsc_at.diff
(text/plain, 10.2 KB)
Index: gw/smsc/smsc_at.c
===================================================================
RCS file: /home/cvs/gateway/gw/smsc/smsc_at.c,v
retrieving revision 1.37
diff -u -r1.37 smsc_at.c
--- gw/smsc/smsc_at.c 22 Jul 2007 13:15:25 -0000 1.37
+++ gw/smsc/smsc_at.c 11 Sep 2007 10:34:18 -0000
@@ -339,7 +339,7 @@
errno = 0;
s = write(privdata->fd, octstr_get_cstr(linestr) + data_written,
count - data_written);
- if (s < 0 && errno == EAGAIN && write_count < RETRY_SEND) {
+ if (s < 0 && errno == EAGAIN && write_count < RETRY_WRITE) {
gwthread_sleep(1);
++write_count;
} else if (s > 0) {
@@ -372,7 +372,7 @@
while (1) {
errno = 0;
s = write(privdata->fd, ctrlz, 1);
- if (s < 0 && errno == EAGAIN && write_count < RETRY_SEND) {
+ if (s < 0 && errno == EAGAIN && write_count < RETRY_WRITE) {
gwthread_sleep(1);
++write_count;
} else
@@ -401,7 +401,7 @@
count = strlen(line);
while(count > data_written) {
s = write(privdata->fd, line + data_written, count - data_written);
- if (s < 0 && errno == EAGAIN && write_count < RETRY_SEND) {
+ if (s < 0 && errno == EAGAIN && write_count < RETRY_WRITE) {
gwthread_sleep(1);
++write_count;
} else if (s > 0) {
@@ -1188,12 +1188,7 @@
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);
+ at2_wait_modem_command(privdata, 1, 0, NULL);
/* read error, so re-connect */
if (privdata->fd == -1) {
@@ -1225,6 +1220,11 @@
}
memory_poll_timeout = time(NULL);
}
+
+ if (gw_prioqueue_len(privdata->outgoing_queue) > 0) {
+ at2_send_messages(privdata);
+ idle_timeout = time(NULL);
+ }
}
at2_close_device(privdata);
mutex_lock(conn->flow_mutex);
@@ -1991,14 +1991,12 @@
{
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);
+ 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);
}
@@ -2007,7 +2005,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);
@@ -2033,103 +2030,90 @@
return;
}
- ret = -99;
- retries = RETRY_SEND;
- while ((ret != 0) && (retries-- > 0)) {
- int msg_id = -1;
- /*
- * send the initial command and then wait for >
- */
- sprintf(command, "AT+CMGS=%ld", octstr_len(pdu) / 2);
-
- ret = at2_send_modem_command(privdata, command, 5, 1);
- debug("bb.smsc.at2", 0, "AT2[%s]: send command status: %d",
- octstr_get_cstr(privdata->name), ret);
-
- if (ret != 1) /* > only! */
- continue;
-
- /*
- * Ok the > has been see now so we can send the PDU now and a
- * control Z but no CR or LF
- *
- * 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
- * the phone modems. We'll buffer the PDU output in a loop.
- * All other types will get handled as used to be.
- */
-
- if (octstr_compare(privdata->modem->id, octstr_imm("nokiaphone")) != 0) {
-
- sprintf(command, "%s%s", sc, octstr_get_cstr(pdu));
- at2_write(privdata, command);
- at2_write_ctrlz(privdata);
-
- } else {
-
- /* include the CTRL-Z in the PDU string */
- sprintf(command, "%s%s%c", sc, octstr_get_cstr(pdu), 0x1A);
-
- /* chop PDU into 18-byte-at-a-time pieces to prevent choking
- * of certain GSM Phones (e.g. Nokia 6310, 6230 etc.) */
- if (strlen(command) > 18) {
- unsigned char chop[20];
- int len = strlen(command);
- int pos = 0;
- int ret = 18;
-
- while (pos < len) {
- if (pos + ret > len)
- ret = len - pos;
- memcpy(chop, command + pos, ret);
- pos += ret;
- chop[ret] = '\0';
- at2_write(privdata, chop);
- gwthread_sleep((double) 10/1000);
- }
- } else {
- at2_write(privdata, command);
- }
- }
-
- /* wait 20 secs for modem command */
- 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;
-
- /* store DLR message if needed for SMSC generated delivery reports */
- if (DLR_IS_ENABLED_DEVICE(msg->sms.dlr_mask)) {
- if (msg_id == -1)
- error(0,"AT2[%s]: delivery notification requested, but I have no message ID!",
- octstr_get_cstr(privdata->name));
- else {
- Octstr *dlrmsgid = octstr_format("%d", msg_id);
-
- dlr_add(privdata->conn->id, dlrmsgid, msg);
-
- O_DESTROY(dlrmsgid);
- }
- }
-
- 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);
- }
+ int msg_id = -1;
+ /*
+ * send the initial command and then wait for >
+ */
+ sprintf(command, "AT+CMGS=%ld", octstr_len(pdu) / 2);
+
+ ret = at2_send_modem_command(privdata, command, 5, 1);
+ debug("bb.smsc.at2", 0, "AT2[%s]: send command status: %d",
+ octstr_get_cstr(privdata->name), ret);
+
+ 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
+ *
+ * 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
+ * the phone modems. We'll buffer the PDU output in a loop.
+ * All other types will get handled as used to be.
+ */
+
+ if (octstr_compare(privdata->modem->id, octstr_imm("nokiaphone")) != 0) {
+
+ sprintf(command, "%s%s", sc, octstr_get_cstr(pdu));
+ at2_write(privdata, command);
+ at2_write_ctrlz(privdata);
+
+ } else {
+
+ /* include the CTRL-Z in the PDU string */
+ sprintf(command, "%s%s%c", sc, octstr_get_cstr(pdu), 0x1A);
+
+ /* chop PDU into 18-byte-at-a-time pieces to prevent choking
+ * of certain GSM Phones (e.g. Nokia 6310, 6230 etc.) */
+ if (strlen(command) > 18) {
+ unsigned char chop[20];
+ int len = strlen(command);
+ int pos = 0;
+ int ret = 18;
+
+ while (pos < len) {
+ if (pos + ret > len)
+ ret = len - pos;
+ memcpy(chop, command + pos, ret);
+ pos += ret;
+ chop[ret] = '\0';
+ at2_write(privdata, chop);
+ gwthread_sleep((double) 10/1000);
+ }
+ } else {
+ at2_write(privdata, command);
+ }
+ }
+
+ /* wait 20 secs for modem command */
+ 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) {
+ bb_smscconn_send_failed(privdata->conn, msg,
+ SMSCCONN_FAILED_TEMPORARILY, octstr_create("ERROR"));
+ }else{
+ /* store DLR message if needed for SMSC generated delivery reports */
+ if (DLR_IS_ENABLED_DEVICE(msg->sms.dlr_mask)) {
+ if (msg_id == -1)
+ error(0,"AT2[%s]: delivery notification requested, but I have no message ID!",
+ octstr_get_cstr(privdata->name));
+ else {
+ Octstr *dlrmsgid = octstr_format("%d", msg_id);
+
+ dlr_add(privdata->conn->id, dlrmsgid, msg);
+
+ O_DESTROY(dlrmsgid);
+ }
+ }
+
+ bb_smscconn_sent(privdata->conn, msg, NULL);
+ }
+ }
+ O_DESTROY(pdu);
+ }
}
Index: gw/smsc/smsc_at.h
===================================================================
RCS file: /home/cvs/gateway/gw/smsc/smsc_at.h,v
retrieving revision 1.12
diff -u -r1.12 smsc_at.h
--- gw/smsc/smsc_at.h 7 Jan 2007 23:52:53 -0000 1.12
+++ gw/smsc/smsc_at.h 11 Sep 2007 10:34:18 -0000
@@ -82,8 +82,8 @@
#define PNT_INTER 1
#define PNT_NATIONAL 2
-/* The number of times to attempt to send a message should sending fail */
-#define RETRY_SEND 3
+/* The number of times to attempt to write a line should writing fail */
+#define RETRY_WRITE 3
/*
* defines for use with the so-called "SIM buffering techinique":