Hi all,
attached you can find patch that adds 2 new options for smsc_at:
max-error-count and reset-string. For description of those see userguide
changes inside of the patch.
This patch adds also properly device reconnections and some fixes here and
there.
P.S. This patch was generated based on smsc_at from centrium tree and is used
since at least 3 months w/o any problems.
Comments and votes please!
doc/userguide/userguide.xml | 16 16 + 0 - 0 !
gw/smsc/smsc_at.c | 105 79 + 26 - 0 !
gw/smsc/smsc_at.h | 4 3 + 1 - 0 !
gwlib/cfg.def | 2 2 + 0 - 0 !
4 files changed, 100 insertions(+), 27 deletions(-)
--
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: [EMAIL PROTECTED]
web: www.centrium.de
msn: [EMAIL PROTECTED]
icq: 98063111
___________________________________________
Please avoid sending me Word, Excel or PowerPoint attachments.
See http://www.fsf.org/philosophy/no-word-attachments.html
Index: gwlib/cfg.def
===================================================================
RCS file: /home/cvs/gateway/gwlib/cfg.def,v
retrieving revision 1.99
diff -a -u -r1.99 cfg.def
--- gwlib/cfg.def 8 Jan 2004 17:27:15 -0000 1.99
+++ gwlib/cfg.def 12 Jan 2004 14:05:06 -0000
@@ -343,6 +343,7 @@
OCTSTR(msg-id-type)
OCTSTR(no-dlr)
OCTSTR(connection-timeout)
+ OCTSTR(max-error-count)
)
@@ -450,6 +451,7 @@
OCTSTR(broken)
OCTSTR(message-storage)
OCTSTR(enable-mms)
+ OCTSTR(reset-string)
)
Index: gw/smsc/smsc_at.c
===================================================================
RCS file: /home/cvs/gateway/gw/smsc/smsc_at.c,v
retrieving revision 1.11
diff -a -u -r1.11 smsc_at.c
--- gw/smsc/smsc_at.c 15 Nov 2003 13:14:23 -0000 1.11
+++ gw/smsc/smsc_at.c 12 Jan 2004 14:05:06 -0000
@@ -95,6 +95,11 @@
static int at2_open_device1(PrivAT2data *privdata)
{
info(0, "AT2[%s]: opening device", octstr_get_cstr(privdata->name));
+ if (privdata->fd > 0) {
+ warning(0, "AT2[%s]: trying to open device with not closed device!!! Please report!!!",
+ octstr_get_cstr(privdata->name));
+ at2_close_device(privdata);
+ }
privdata->fd = open(octstr_get_cstr(privdata->device),
O_RDWR | O_NONBLOCK | O_NOCTTY);
if (privdata->fd == -1) {
@@ -160,6 +165,11 @@
info(0, "AT2[%s]: closing device", octstr_get_cstr(privdata->name));
close(privdata->fd);
privdata->fd = -1;
+ privdata->pin_ready = 0;
+ privdata->phase2plus = 0;
+ if (privdata->ilb != NULL)
+ octstr_destroy(privdata->ilb);
+ privdata->ilb = octstr_create("");
}
@@ -397,22 +407,21 @@
int at2_init_device(PrivAT2data *privdata)
{
- int res;
int ret;
Octstr *setpin;
info(0, "AT2[%s]: init device", octstr_get_cstr(privdata->name));
at2_set_speed(privdata, privdata->speed);
- res = at2_send_modem_command(privdata, "AT", 0, 0);
- if (res == -1) {
- /*
- * first try failed, maybe we need another one
- * after just having changed the speed
- */
- res = at2_send_modem_command(privdata, "AT", 0, 0);
- }
- if (res == -1) {
+ /* sleep 10 ms in order to get device some time to accept speed */
+ gwthread_sleep(0.10);
+
+ /* reset the modem */
+ if (at2_send_modem_command(privdata, "ATZ", 0, 0) == -1)
+ return -1;
+
+ /* check if the modem responded */
+ if (at2_send_modem_command(privdata, "AT", 0, 0) == -1) {
error(0, "AT2[%s]: no answer from modem", octstr_get_cstr(privdata->name));
return -1;
}
@@ -822,12 +831,12 @@
octstr_destroy(current_storage);
}
-void at2_read_sms_memory(PrivAT2data* privdata)
+static int 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));
- return ;
+ return -1;
}
if (privdata->sms_memory_usage) {
@@ -880,6 +889,7 @@
/*
at2_send_modem_command(privdata, ModemTypes[privdata->modemid].init1, 0, 0);
*/
+ return 0;
}
@@ -1011,7 +1021,7 @@
{
SMSCConn *conn = arg;
PrivAT2data *privdata = conn->data;
- int l, reconnecting = 0;
+ int l, reconnecting = 0, error_count = 0;
long idle_timeout, memory_poll_timeout = 0;
conn->status = SMSCCONN_CONNECTING;
@@ -1063,16 +1073,37 @@
continue;
}
+ if (privdata->max_error_count > 0 && error_count > privdata->max_error_count &&
+ privdata->modem != NULL && privdata->modem->reset_string != NULL) {
+ error_count = 0;
+ if (at2_send_modem_command(privdata,
+ octstr_get_cstr(privdata->modem->reset_string), 0, 0) != 0) {
+ error(0, "AT2[%s]: Reset of modem failed.", octstr_get_cstr(privdata->name));
+ at2_close_device(privdata);
+ continue;
+ }
+ else {
+ info(0, "AT2[%s]: Modem reseted.", octstr_get_cstr(privdata->name));
+ }
+ }
+
if (at2_init_device(privdata) != 0) {
error(0, "AT2[%s]: Opening failed. Terminating", octstr_get_cstr(privdata->name));
+ at2_close_device(privdata);
+ error_count++;
continue;
}
+ else
+ error_count = 0;
/* If we got here, then the device is opened */
break;
} while (!privdata->shutdown);
+ mutex_lock(conn->flow_mutex);
conn->status = SMSCCONN_ACTIVE;
+ conn->connect_time = time(NULL);
+ mutex_unlock(conn->flow_mutex);
bb_smscconn_connected(conn);
idle_timeout = 0;
@@ -1093,7 +1124,6 @@
if (at2_send_modem_command(privdata,
octstr_get_cstr(privdata->modem->keepalive_cmd), 5, 0) < 0) {
at2_close_device(privdata);
- conn->status = SMSCCONN_RECONNECTING;
reconnecting = 1;
goto reconnect;
}
@@ -1102,12 +1132,18 @@
if (privdata->sms_memory_poll_interval &&
memory_poll_timeout + privdata->sms_memory_poll_interval < time(NULL)) {
- at2_read_sms_memory(privdata);
+ if (at2_read_sms_memory(privdata) == -1) {
+ at2_close_device(privdata);
+ reconnecting = 1;
+ goto reconnect;
+ }
memory_poll_timeout = time(NULL);
}
}
at2_close_device(privdata);
+ mutex_lock(conn->flow_mutex);
conn->status = SMSCCONN_DISCONNECTED;
+ mutex_unlock(conn->flow_mutex);
/* maybe some cleanup here? */
at2_destroy_modem(privdata->modem);
octstr_destroy(privdata->device);
@@ -1123,8 +1159,10 @@
list_destroy(privdata->pending_incoming_messages, octstr_destroy_item);
gw_free(conn->data);
conn->data = NULL;
+ mutex_lock(conn->flow_mutex);
conn->why_killed = SMSCCONN_KILLED_SHUTDOWN;
conn->status = SMSCCONN_DEAD;
+ mutex_unlock(conn->flow_mutex);
bb_smscconn_killed();
}
@@ -1276,9 +1314,12 @@
privdata->conn = conn;
privdata->phase2plus = 0;
privdata->validityperiod = cfg_get(cfg, octstr_imm("validityperiod"));
+ if (cfg_get_integer((long*)&privdata->max_error_count, cfg, octstr_imm("max-error-count")) == -1)
+ privdata->max_error_count = -1;
conn->data = privdata;
conn->name = octstr_format("AT2[%s]", octstr_get_cstr(privdata->name));
+ conn->status = SMSCCONN_CONNECTING;
privdata->shutdown = 0;
@@ -1357,8 +1398,7 @@
+ at2_hexchar(octstr_get_char(buffer, pos + 1));
if (tmp < 0)
goto nomsg;
- tmp = 2 + tmp * 2;
- pos += tmp;
+ pos += 2 + tmp * 2;
}
/* check if the buffer is long enough to contain the full message */
@@ -1519,13 +1559,17 @@
stime = date_convert_universal(&mtime);
- /* get data length */
+ /* get data length
+ * XXX: Is it allowed to have length = 0 ??? (alex)
+ */
len = octstr_get_char(pdu, pos);
pos++;
+ debug("bb.smsc.at2", 0, "AT2[%s]: User data length read as (%d)", octstr_get_cstr(privdata->name), len);
+
/* if there is a UDH */
udhlen = 0;
- if (udhi) {
+ if (udhi && len > 0) {
udhlen = octstr_get_char(pdu, pos);
pos++;
if (udhlen + 1 > len)
@@ -1533,9 +1577,13 @@
udh = octstr_copy(pdu, pos, udhlen);
pos += udhlen;
len -= udhlen + 1;
- }
+ } else if (len <= 0) /* len < 0 is impossible, but sure is sure */
+ udhi = 0;
- if (pos > octstr_len(pdu))
+ debug("bb.smsc.at2", 0, "AT2[%s]: Udh decoding done len=%d udhi=%d udhlen=%d udh='%s'",
+ octstr_get_cstr(privdata->name), len, udhi, udhlen, (udh?octstr_get_cstr(udh):""));
+
+ if (pos > octstr_len(pdu) || len < 0)
goto msg_error;
/* build the message */
@@ -2077,11 +2125,14 @@
int at2_detect_speed(PrivAT2data *privdata)
{
int i;
+ int autospeeds[] = {
+#ifdef B115200
+ 115200,
+#endif
#ifdef B57600
- int autospeeds[] = { 57600, 38400, 19200, 9600 };
-#else
- int autospeeds[] = { 38400, 19200, 9600 };
+ 57600,
#endif
+ 38400, 19200, 9600 };
debug("bb.smsc.at2", 0, "AT2[%s]: detecting modem speed. ",
octstr_get_cstr(privdata->name));
@@ -2104,7 +2155,7 @@
int res;
- if (at2_open_device1(privdata) == -1)
+ if (at2_open_device(privdata) == -1)
return -1;
at2_set_speed(privdata, speed);
@@ -2130,7 +2181,7 @@
debug("bb.smsc.at2", 0, "AT2[%s]: detecting modem type", octstr_get_cstr(privdata->name));
- if (at2_open_device1(privdata) == -1)
+ if (at2_open_device(privdata) == -1)
return -1;
at2_set_speed(privdata, privdata->speed);
@@ -2301,6 +2352,8 @@
modem->init_string = cfg_get(grp, octstr_imm("init-string"));
if (modem->init_string == NULL)
modem->init_string = octstr_create("AT+CNMI=1,2,0,1,0");
+
+ modem->reset_string = cfg_get(grp, octstr_imm("reset-string"));
modem->speed = 9600;
cfg_get_integer(&modem->speed, grp, octstr_imm("speed"));
Index: gw/smsc/smsc_at.h
===================================================================
RCS file: /home/cvs/gateway/gw/smsc/smsc_at.h,v
retrieving revision 1.4
diff -a -u -r1.4 smsc_at.h
--- gw/smsc/smsc_at.h 15 Nov 2003 13:14:23 -0000 1.4
+++ gw/smsc/smsc_at.h 12 Jan 2004 14:05:06 -0000
@@ -101,6 +101,7 @@
Octstr *detect_string;
Octstr *detect_string2;
Octstr *init_string;
+ Octstr *reset_string;
long speed;
Octstr *enable_hwhs;
int need_sleep;
@@ -138,6 +139,7 @@
int sms_memory_capacity;
int sms_memory_usage;
List *pending_incoming_messages;
+ int max_error_count;
} PrivAT2data;
@@ -340,7 +342,7 @@
/*
* Checks whether any messages are buffered in message storage and extract them.
*/
-static void at2_read_sms_memory(PrivAT2data *privdata);
+static int at2_read_sms_memory(PrivAT2data *privdata);
/*
* Memory capacity and usage check
Index: doc/userguide/userguide.xml
===================================================================
RCS file: /home/cvs/gateway/doc/userguide/userguide.xml,v
retrieving revision 1.260
diff -a -u -r1.260 userguide.xml
--- doc/userguide/userguide.xml 10 Jan 2004 16:35:12 -0000 1.260
+++ doc/userguide/userguide.xml 12 Jan 2004 14:05:06 -0000
@@ -3321,6 +3321,14 @@
Modems known to work with this setting are Wavecom WM02/M1200 and the Siemens M20.
</entry></row>
+ <row><entry><literal>max-error-count</literal></entry>
+ <entry><literal>integer</literal></entry>
+ <entry valign="bottom">
+ Maximal error count for opening modem device or initializing of the modem before
+ <literal>reset-string</literal> will be executed. This is usefull when modem crashed and needs
+ hard reset. Default disabled.
+ </entry></row>
+
</tbody></tgroup></informaltable>
<para>Modem definitions are now multiple groups present in kannel.conf,
@@ -3455,6 +3463,14 @@
message on queue and hopefully will be quickier
sending the messages.
</entry></row>
+
+ <row><entry><literal>reset-string</literal></entry>
+ <entry><literal>string</literal></entry>
+ <entry valign="bottom">
+ Which reset string to execute when <literal>max-error-count</literal> reached.
+ Example for Falcom: AT+CFUN=1
+ </entry></row>
+
</tbody></tgroup></informaltable>