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;
 }
 

Attachment: signature.asc
Description: This is a digitally signed message part

Reply via email to