This is with respect to the CVS version of Kannel. The SMPP driver's
calculation of the validity and deferred fields for messages to the SMSC
is incorrect. (I noticed this because it worked with my simulator at
2340 hrs but not at 0100 hrs. Sure enough in the first case it correctly
said I was +6 UTC, but in the second it said I was -18 UTC. Of course
the simulator then returned a NAK).

Fixing this for my system was easy. I'm working on GNU/Linux with kernel
2.4.9 and Glibc 2.1. I'll need some advice in order to come up with a
more acceptable/portable solution. Calculating time differences is not
a straightforward task and it made sense to use the library functions
available. This is what I learned in the process of looking for a more
widely applicable solution. It might be obvious, but I'll state it here
just in case.

localtime() originated from SysV. Upon return it sets a global called
timezone, which stores the offset from UTC. This isn't nice for
multithreaded programs. (Though in this particular case it's probably
alright since one's UTC offset won't change from one call to the next). A
POSIX.1c variant is localtime_r(). This gives you the offset required in
a local variable (in addition to setting the global timezone). While a
solution with localtime() would be fine, the only drawback is it doesn't
take into account daylight savings which localtime_r() does.

My changes are attached. I updated my copy of the CVS tree at
approximately 17:30 GMT on 21 Aug and this is a diff to it.

Vibhu
diff -Naurw gateway.orig/gw/smsc/smsc_smpp.c gateway.new/gw/smsc/smsc_smpp.c
--- gateway.orig/gw/smsc/smsc_smpp.c    Thu Aug 22 01:11:29 2002
+++ gateway.new/gw/smsc/smsc_smpp.c     Thu Aug 22 04:18:17 2002
@@ -258,7 +258,7 @@
     SMPP_PDU *pdu; 
     Octstr *buffer;
     Octstr *relation_UTC_time = NULL;
-    struct tm gmtime, localtime, tm;
+    struct tm tm;
     int gwqdiff;
 
     pdu = smpp_pdu_create(submit_sm,  
@@ -359,11 +359,7 @@
     if (msg->sms.validity || msg->sms.deferred) {
 
         /* work out 1/4 hour difference between local time and UTC/GMT */
-        gmtime = gw_gmtime(time(NULL));
-        localtime = gw_localtime(time(NULL));
-        gwqdiff = ((localtime.tm_hour - gmtime.tm_hour) * 4)
-                  + ((localtime.tm_min - gmtime.tm_min) / 15);
-        
+       gwqdiff = (int) (gw_localtime_r(time(NULL)).tm_gmtoff/900);
         if (gwqdiff >= 0) {
             relation_UTC_time = octstr_create("+");
         } else {
diff -Naurw gateway.orig/gwlib/protected.c gateway.new/gwlib/protected.c
--- gateway.orig/gwlib/protected.c      Thu Aug 22 03:33:21 2002
+++ gateway.new/gwlib/protected.c       Thu Aug 22 04:11:56 2002
@@ -13,6 +13,7 @@
  * Undefine the accident protectors.
  */
 #undef localtime
+#undef localtime_r
 #undef gmtime
 #undef rand
 #undef gethostbyname
@@ -20,6 +21,7 @@
 
 enum {
     LOCALTIME,
+    LOCALTIME_R,
     GMTIME,
     RAND,
     GETHOSTBYNAME,
@@ -67,6 +69,17 @@
     lock(LOCALTIME);
     tm = *localtime(&t);
     unlock(LOCALTIME);
+    return tm;
+}
+
+
+struct tm gw_localtime_r(time_t t)
+{
+    struct tm tm;
+
+    lock(LOCALTIME_R);
+    localtime_r(&t, &tm);
+    unlock(LOCALTIME_R);
     return tm;
 }
 
diff -Naurw gateway.orig/gwlib/protected.h gateway.new/gwlib/protected.h
--- gateway.orig/gwlib/protected.h      Thu Aug 22 03:33:34 2002
+++ gateway.new/gwlib/protected.h       Thu Aug 22 04:09:24 2002
@@ -18,6 +18,7 @@
 void gwlib_protected_init(void);
 void gwlib_protected_shutdown(void);
 struct tm gw_localtime(time_t t);
+struct tm gw_localtime_r(time_t t);
 struct tm gw_gmtime(time_t t);
 int gw_rand(void);
 int gw_gethostbyname(struct hostent *ret, const char *name);
@@ -28,6 +29,9 @@
 
 #undef localtime
 #define localtime(t) do_not_use_localtime_directly
+
+#undef localtime_r
+#define localtime_r(t,s) do_not_use_localtime_r_directly
 
 #undef gmtime
 #define gmtime(t) do_not_use_gmtime_directly

Attachment: msg04700/pgp00000.pgp
Description: PGP signature

Reply via email to