Hi, I found a problem when I use iTegno WM1080A with Kannel. Finally I got the bug and solve it.. So these are the description of bug, and attached the diff to current HEAD version of gw/smsc/smsc_at.c
- What: - write(fd, buf, len) function did not write all data in buf. Return value of this function, show how much data in buf has been written. - This bug will result that only 19 chars of SMS, can be sent. Because write only eat 64 char at one time (in my system, others my vary), which is equivalent with 19 chars of SMS in my system. - How to produce the bug: - I am using RH8, Linux kernel 2.4.22, glibc 2.3.2, libxml2 2.5.11, Kannel 1.3.1 (and cvs version as well), iTegno WM1080A/3000. -- cogito ergo sum GPG fingerprint: E2BC 9029 F3FB 90C7 2FAB 9E42 421E F015 119E 0D5D
Index: gw/smsc/smsc_at.c =================================================================== RCS file: /home/cvs/gateway/gw/smsc/smsc_at.c,v retrieving revision 1.8 diff -u -r1.8 smsc_at.c --- gw/smsc/smsc_at.c 17 Oct 2003 14:11:47 -0000 1.8 +++ gw/smsc/smsc_at.c 12 Nov 2003 13:10:42 -0000 @@ -236,19 +236,29 @@ int count; int s = 0; int write_count = 0; + char *data; + int data_written = 0; Octstr *linestr = NULL; linestr = octstr_format("%s\r", line); debug("bb.smsc.at2", 0, "AT2[%s]: --> %s^M", octstr_get_cstr(privdata->name), line); + /* + * yulianto: Not all data eaten by 'write' function, it might eat data + * partially. This why we need loop. + * */ + data = octstr_get_cstr(linestr); count = octstr_len(linestr); while (1) { errno = 0; - s = write(privdata->fd, octstr_get_cstr(linestr), count); + s = write(privdata->fd, data + data_written, count - data_written); if (s < 0 && errno == EAGAIN && write_count < RETRY_SEND) { gwthread_sleep(1); ++write_count; + } else if (data_written < count) { + data_written += s; + write_count = 0; } else break; }; @@ -256,6 +266,7 @@ if (s < 0) { debug("bb.smsc.at2", 0, "AT2[%s]: write failed with errno %d", octstr_get_cstr(privdata->name), errno); + tcflush(privdata->fd, TCOFLUSH); return s; } tcdrain(privdata->fd); @@ -284,6 +295,7 @@ if (s < 0) { debug("bb.smsc.at2", 0, "AT2[%s]: write failed with errno %d", octstr_get_cstr(privdata->name), errno); + tcflush(privdata->fd, TCOFLUSH); return s; } tcdrain(privdata->fd); @@ -296,11 +308,38 @@ { int count; int s; + int write_count = 0; + char *data = line; + int data_written = 0; count = strlen(line); debug("bb.smsc.at2", 0, "AT2[%s]: --> %s", octstr_get_cstr(privdata->name), line); - s = write(privdata->fd, line, count); + debug("bb.smsc.at2", 0, "AT2[%s]: --> %s", octstr_get_cstr(privdata->name), line); + /* + * yulianto: Not all data eaten by 'write' function, it might eat data + * partially. This why we need loop. + * */ + while (1) { + errno = 0; + s = write(privdata->fd, data + data_written, count - data_written); + if (s < 0 && errno == EAGAIN && write_count < RETRY_SEND) { + gwthread_sleep(1); + ++write_count; + } else if (data_written < count) { + data_written += s; + write_count = 0; + } else + break; + }; + if (s < 0) { + debug("bb.smsc.at2", 0, "AT2[%s]: write failed with errno %d", + octstr_get_cstr(privdata->name), errno); + tcflush(privdata->fd, TCOFLUSH); + return s; + } tcdrain(privdata->fd); + gwthread_sleep((double) (privdata->modem == NULL ? + 100 : privdata->modem->sendline_sleep) / 1000); return s; }
signature.asc
Description: This is a digitally signed message part