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