Hi, I'm ++1 for this patch :)
attched you can find rediffed patch agains current cvs. On Thursday 16 October 2003 19:58, Steve Kennedy wrote: > Hi, > > I'd still like to get this included in Kannel, it alters the behaviour > of the (old) at2 module to handle inbound SMS's better. > > It probably needs rejigging to make it work with the new smsc_at stuff, > but I think it's very worthwhile and has been working here successfully > for about 6 months !!! > > Maybe it could be turned into a configurable option. > > > Steve -- Best regards / Mit besten Gr��en aus D�sseldorf Dipl.-Ing. Alexander Malysh ___________________________________________ Centrium GmbH Vogelsanger Weg 80 40470 D�sseldorf Fon: +49 (0211) 74 84 51 80 Fax: +49 (0211) 277 49 109 email: a.malysh at centrium.de web: www.centrium.de msn: olek2002 at hotmail.com icq: 98063111 ___________________________________________ Please avoid sending me Word or PowerPoint attachments. See http://www.fsf.org/philosophy/no-word-attachments.html
Index: gw/smsc/smsc_at.c
===================================================================
RCS file: /home/cvs/gateway/gw/smsc/smsc_at.c,v
retrieving revision 1.7
diff -a -u -r1.7 smsc_at.c
--- gw/smsc/smsc_at.c 15 Oct 2003 21:28:27 -0000 1.7
+++ gw/smsc/smsc_at.c 16 Oct 2003 20:43:40 -0000
@@ -458,14 +458,7 @@
if (privdata->sms_memory_poll_interval && privdata->modem->message_storage) {
/* set message storage location for "SIM buffering" using the CPMS command */
- Octstr *temp;
- temp = octstr_create("AT+CPMS=");
- octstr_append_char(temp, 34);
- octstr_append(temp, privdata->modem->message_storage);
- octstr_append_char(temp, 34);
- ret = at2_send_modem_command(privdata, octstr_get_cstr(temp), 0, 0);
- octstr_destroy(temp);
- if (ret != 0)
+ if (at2_set_message_storage(privdata, privdata->modem->message_storage) != 0)
return -1;
}
@@ -535,6 +528,17 @@
ret = 1;
goto end;
}
+ if (octstr_search(line, octstr_imm("+CMTI:"), 0) != -1 ||
+ octstr_search(line, octstr_imm("+CDSI:"), 0) != -1) {
+ /*
+ we received an incoming message indication
+ put it in the pending_incoming_messages queue for later retrieval
+ */
+ debug("bb.smsc.at2", 0, "AT2[%s]: +CMTI incoming SMS indication: %s", octstr_get_cstr(privdata->name), octstr_get_cstr(line));
+ list_append(privdata->pending_incoming_messages, line);
+ line = NULL;
+ continue;
+ }
if (octstr_search(line, octstr_imm("+CMT:"), 0) != -1 ||
octstr_search(line, octstr_imm("+CDS:"), 0) != -1 ||
((octstr_search(line, octstr_imm("+CMGR:"), 0) != -1) && (cmgr_flag = 1)) ) {
@@ -612,11 +616,132 @@
return ret;
}
-
-void at2_read_sms_memory(PrivAT2data* privdata)
+int at2_read_delete_message(PrivAT2data* privdata, int message_number)
{
char cmd[20];
+ int message_count = 0;
+
+ sprintf(cmd, "AT+CMGR=%d", message_number);
+ /* read one message from memory */
+ at2_write_line(privdata, cmd);
+ if (at2_wait_modem_command(privdata, 0, 0, &message_count) != 0) {
+ debug("bb.smsc.at2", 0, "AT2[%s]: failed to get message %d.",
+ octstr_get_cstr(privdata->name), message_number);
+ return 0; /* failed to read the message - skip to next message */
+ }
+
+ /* no need to delete if no message collected */
+ if (!message_count) {
+ debug("bb.smsc.at2", 0, "AT2[%s]: not deleted.",
+ octstr_get_cstr(privdata->name));
+ return 0;
+ }
+
+ sprintf(cmd, "AT+CMGD=%d", message_number); /* delete the message we just read */
+ /*
+ * 3 seconds (default timeout of send_modem_command()) is not enough with some
+ * modems if the message is large, so we'll give it 7 seconds
+ */
+ if (at2_send_modem_command(privdata, cmd, 7, 0) != 0) {
+ /*
+ * failed to delete the message, we'll just ignore it for now,
+ * this is bad, since if the message really didn't get deleted
+ * we'll see it next time around.
+ */
+ error(2, "AT2[%s]: failed to delete message %d.",
+ octstr_get_cstr(privdata->name), message_number);
+ }
+
+ return 1;
+}
+
+/*
+ * This function loops through the pending_incoming_messages queue for CMTI
+ * notifications.
+ * Every notification is parsed and the messages are read (and deleted)
+ * accordingly.
+*/
+void at2_read_pending_incoming_messages(PrivAT2data* privdata)
+{
+ Octstr *current_storage = NULL;
+
+ if (privdata->modem->message_storage) {
+ current_storage = octstr_duplicate(privdata->modem->message_storage);
+ }
+ while (list_len(privdata->pending_incoming_messages) > 0) {
+ int pos;
+ long location;
+ Octstr *cmti_storage = NULL, *line = NULL;
+
+ line = list_extract_first(privdata->pending_incoming_messages);
+ /* message memory starts after the first quote in the string */
+ if ((pos = octstr_search_char(line, '"', 0)) != -1) {
+ /* grab memory storage name */
+ int next_quote = octstr_search_char(line, '"', ++pos);
+ if (next_quote == -1) { /* no second qoute - this line must be broken somehow */
+ O_DESTROY(line);
+ continue;
+ }
+
+ /* store notification storage location for reference */
+ cmti_storage = octstr_copy(line, pos, next_quote - pos);
+ } else
+ /* reset pos for the next lookup which would start from the beginning if no memory
+ * location was found */
+ pos = 0;
+
+ /* if no message storage is set in configuration - set now */
+ if (!privdata->modem->message_storage && cmti_storage) {
+ info(2, "AT2[%s]: CMTI received, but no message-storage is set in confiuration."
+ "setting now to <%s>", octstr_get_cstr(privdata->name), octstr_get_cstr(cmti_storage));
+ privdata->modem->message_storage = octstr_duplicate(cmti_storage);
+ current_storage = octstr_duplicate(cmti_storage);
+ at2_set_message_storage(privdata, cmti_storage);
+ }
+
+ /* find the message id from the line, which should appear after the first comma */
+ if ((pos = octstr_search_char(line, ',', pos)) == -1) { /* this CMTI notification is probably broken */
+ error(2, "AT2[%s]: failed to find memory location in CMTI notification",
+ octstr_get_cstr(privdata->name));
+ O_DESTROY(line);
+ octstr_destroy(cmti_storage);
+ continue;
+ }
+
+ if ((pos = octstr_parse_long(&location, line, ++pos, 10)) == -1) {
+ /* there was an error parsing the message id. next! */
+ error(2, "AT2[%s]: error parsing memory location in CMTI notification",
+ octstr_get_cstr(privdata->name));
+ O_DESTROY(line);
+ octstr_destroy(cmti_storage);
+ continue;
+ }
+ /* check if we need to change storage location before issuing the read command */
+ if (!current_storage || (octstr_compare(current_storage, cmti_storage) != 0)) {
+ octstr_destroy(current_storage);
+ current_storage = octstr_duplicate(cmti_storage);
+ at2_set_message_storage(privdata, cmti_storage);
+ }
+
+ if (!at2_read_delete_message(privdata, location)) {
+ error(1,"AT2[%s]: CMTI notification received, but no message found in memory!",
+ octstr_get_cstr(privdata->name));
+ }
+
+
+ octstr_destroy(line);
+ octstr_destroy(cmti_storage);
+ }
+ /* set prefered message storage back to what configured */
+ if (current_storage && privdata->modem->message_storage && (octstr_compare(privdata->modem->message_storage, current_storage) != 0))
+ at2_set_message_storage(privdata, privdata->modem->message_storage);
+
+ octstr_destroy(current_storage);
+}
+
+void at2_read_sms_memory(PrivAT2data* privdata)
+{
/* get memory status */
if (at2_check_sms_memory(privdata) == -1) {
debug("bb.smsc.at2", 0, "AT2[%s]: memory check error", octstr_get_cstr(privdata->name));
@@ -659,40 +784,15 @@
* loop till end of memory or collected enouch messages
*/
for (i = 1; i <= privdata->sms_memory_capacity &&
- message_count < privdata->sms_memory_usage; ++i) {
- int old_message_count = message_count;
- sprintf(cmd, "AT+CMGR=%d", i);
- /* read one message from memory */
- at2_write_line(privdata, cmd);
- if (at2_wait_modem_command(privdata, 0, 0, &message_count) != 0) {
- debug("bb.smsc.at2", 0, "AT2[%s]: failed to get message %d.",
- octstr_get_cstr(privdata->name), i);
- continue; /* failed to read the message - skip to next message */
- }
+ message_count < privdata->sms_memory_usage; ++i) {
- /* no need to delete if no message collected */
- if (old_message_count == message_count) {
- debug("bb.smsc.at2", 0, "AT2[%s]: not deleted.",
- octstr_get_cstr(privdata->name));
- continue;
- }
-
- sprintf(cmd, "AT+CMGD=%d", i); /* delete the message we just read */
- /*
- * 3 seconds is not enough with some modems if the message is large,
- * so we'll give it 7 seconds
- */
- if (at2_send_modem_command(privdata, cmd, 7, 0) != 0) {
- /*
- * failed to delete the message, we'll just ignore it for now,
- * this is bad, since if the message really didn't get deleted
- * we'll see it next time around.
- */
- debug("bb.smsc.at2", 0, "AT2[%s]: failed to delete message %d.",
- octstr_get_cstr(privdata->name), i);
- continue;
-
- }
+ /* if (meanwhile) there are pending CMTI notifications, process these first
+ * to not let CMTI and sim buffering sit in each others way */
+ while (list_len(privdata->pending_incoming_messages) > 0) {
+ at2_read_pending_incoming_messages(privdata);
+ }
+ /* read the message and delete it */
+ message_count += at2_read_delete_message(privdata, i);
}
}
/*
@@ -902,6 +1002,10 @@
} else
at2_wait_modem_command(privdata, 1, 0, NULL);
+ while (list_len(privdata->pending_incoming_messages) > 0) {
+ at2_read_pending_incoming_messages(privdata);
+ }
+
if (privdata->keepalive &&
idle_timeout + privdata->keepalive < time(NULL)) {
if (at2_send_modem_command(privdata,
@@ -934,6 +1038,7 @@
octstr_destroy(privdata->name);
octstr_destroy(privdata->configfile);
list_destroy(privdata->outgoing_queue, NULL);
+ list_destroy(privdata->pending_incoming_messages, octstr_destroy_item);
gw_free(conn->data);
conn->data = NULL;
conn->why_killed = SMSCCONN_KILLED_SHUTDOWN;
@@ -1020,6 +1125,7 @@
privdata = gw_malloc(sizeof(PrivAT2data));
privdata->outgoing_queue = list_create();
+ privdata->pending_incoming_messages = list_create();
privdata->configfile = cfg_get_configfile(cfg);
@@ -2218,4 +2324,20 @@
O_DESTROY(temp);
return out;
+}
+
+int at2_set_message_storage(PrivAT2data* privdata, Octstr* memory_name)
+{
+ Octstr *temp;
+ int ret;
+
+ if (!memory_name || !privdata)
+ return -1;
+
+ temp = octstr_format("AT+CPMS=\"%S\"", memory_name);
+ ret = at2_send_modem_command(privdata, octstr_get_cstr(temp), 0, 0);
+ octstr_destroy(temp);
+ if (ret != 0)
+ return -1;
+ return 0;
}
Index: gw/smsc/smsc_at.h
===================================================================
RCS file: /home/cvs/gateway/gw/smsc/smsc_at.h,v
retrieving revision 1.2
diff -a -u -r1.2 smsc_at.h
--- gw/smsc/smsc_at.h 15 Oct 2003 21:28:27 -0000 1.2
+++ gw/smsc/smsc_at.h 16 Oct 2003 20:43:41 -0000
@@ -81,6 +81,7 @@
int sms_memory_poll_interval;
int sms_memory_capacity;
int sms_memory_usage;
+ List *pending_incoming_messages;
} PrivAT2data;
@@ -304,6 +305,24 @@
* from an MSISDN number
*/
static Octstr* at2_format_address_field(Octstr* msisdn);
+
+/*
+ * Check the pending_incoming_messages queue for CMTI notifications.
+ * Every notification is parsed and the messages are read (and deleted)
+ * accordingly.
+ */
+static void at2_read_pending_incoming_messages(PrivAT2data* privdata);
+
+/*
+ * Set the memory storage location of the modem by sending a +CPMS command
+ */
+static int at2_set_message_storage(PrivAT2data* privdata, Octstr* memory_name);
+
+/*
+ * Reads a message from selected memory location and deletes it afterwards.
+ * returns 0 on failure and 1 on success
+ */
+static int at2_read_delete_message(PrivAT2data* privdata, int message_number);
#endif /* SMSC_AT2_H */
pgp00000.pgp
Description: signature
