[patch] Tariff support & configure (libxml2)

Marko Saaresto <[email protected]>
Newsgroups gmane.comp.mobile.kannel.devel
Organization Matchem Oy
Message-ID <[email protected]>
Well, here is a patch adding some elementary tariff support to current 
cvs-version of Kannel. This is mainly based on and includes the 
modifications in the diff posted by Tarmo Fimberg.

What this patch modifies:

doc/userguide/userguide.xml: some documentation about tariff-parameters
gw/msg-decl.h: adding an integer field (tariff) to message structure
gw/smsbox.c: added handling of tariff information throughout the box
gw/smsc_cimd2.c: tariff and timestamp support
gw/smsc_http.c: tariff-parameter to outbound messages

The patch has seen preliminary testing and compiles against Kannel 
cvs-20020805.

I do not know what plans for tariff support there generally are but this 
is in my opinion one good approach to get it started.



The other patch is a minor fix for configure and configure.in that still 
check for libxml2-2.2.5 although Kannel now seems to require at least 
libxml2-2.3.0, I think.


-- 
Marko Saaresto, Software Developer     MatchEm Ltd
[email protected]             <www.matchem.com>
Mob. +358-44-380 0013                  fax: +358-9-644 091
tariff_patch.diff (text/plain, 16.6 KB)
Index: doc/userguide/userguide.xml
===================================================================
RCS file: /home/cvs/gateway/doc/userguide/userguide.xml,v
retrieving revision 1.185
diff -u -r1.185 userguide.xml
--- doc/userguide/userguide.xml	5 Aug 2002 15:04:13 -0000	1.185
+++ doc/userguide/userguide.xml	5 Aug 2002 21:32:39 -0000
@@ -2022,6 +2022,9 @@
 send stored messages as soon as Kannel logs in (this is the normal
 configuration).</para>
 
+<para> The CIMD2 driver supports tariff classes. This support should be
+documented.</para>
+
 <programlisting>
 group = smsc
 smsc = cimd2
@@ -2966,6 +2969,10 @@
    <para>This special "SMSC" is used for HTTP based connections with
    other gateways and various other relay services, when direct SMSC
    is not available.</para>
+
+   <para>Relay gateway acknowledges incoming messages and sends
+   replies through sendsms push. Relay gateway uses "tariff"
+   request parameter to deliver billing data.</para>
   
 <programlisting>
 group = smsc
@@ -3294,6 +3301,25 @@
     <entry>?</entry>
    </row>
 
+   <row>
+    <entry spanname="feature">Supports Tariff information</entry>
+   </row>
+   <row>
+    <entry></entry>
+    <entry>?</entry>
+    <entry>y?</entry>
+    <entry>?</entry>
+    <entry>?</entry>
+    <entry>?</entry>
+    <entry>?</entry>
+    <entry>?</entry>
+    <entry>?</entry>
+    <entry>?</entry>
+    <entry>?</entry>
+    <entry>y</entry>
+    <entry>?</entry>
+   </row>
+
   </tbody>
  </tgroup>
 </table>
@@ -4477,6 +4503,9 @@
    <row><entry><literal>alt-dcs</literal></entry>
    <entry><literal>X-Kannel-Alt-DCS</literal></entry></row>
 
+   <row><entry><literal>tariff</literal></entry>
+   <entry><literal>X-Kannel-Tariff</literal></entry></row>
+
   </tbody>
   </tgroup>
  </table>
@@ -5496,6 +5525,15 @@
 	but wants to distinguish them in the log. In the case of a HTTP SMSC
 	type the account name is prepended with the servicename (username) and a colon (:)
 	and forwarded to the next insta ce of kannel. This allows hierarchical accounting.
+     </entry></row>
+
+    <row><entry><literal>tariff</literal></entry>
+     <entry>number</entry>
+     <entry valign=bottom>
+        Tariff class for the message. Some SMSC drivers support tariff classes and
+        this parameter carries the price information. NOTE: currently there is no
+        unified way to handle tariff classes. Valid values for this parameter are
+        currently SMSC (driver) specific.
      </entry></row>
 
   </tbody>
Index: gw/msg-decl.h
===================================================================
RCS file: /home/cvs/gateway/gw/msg-decl.h,v
retrieving revision 1.19
diff -u -r1.19 msg-decl.h
--- gw/msg-decl.h	5 Aug 2002 15:04:45 -0000	1.19
+++ gw/msg-decl.h	5 Aug 2002 21:32:39 -0000
@@ -44,6 +44,7 @@
 		INTEGER(alt_dcs);
         INTEGER(rpi);
 		OCTSTR(charset);
+		INTEGER(tariff);
 	})
 
 MSG(ack,
Index: gw/smsbox.c
===================================================================
RCS file: /home/cvs/gateway/gw/smsbox.c,v
retrieving revision 1.208
diff -u -r1.208 smsbox.c
--- gw/smsbox.c	5 Aug 2002 17:03:47 -0000	1.208
+++ gw/smsbox.c	5 Aug 2002 21:32:40 -0000
@@ -317,7 +317,7 @@
 				      int *coding, int *compress, 
 				      int *validity, int *deferred, 
 				      int *dlr_mask, Octstr **dlr_url, 
-				      Octstr **account, int *pid, int *alt_dcs, int *rpi)
+				      Octstr **account, int *pid, int *alt_dcs, int *rpi, int *tariff)
 {
     Octstr *name, *val;
     long l;
@@ -325,7 +325,7 @@
     *dlr_mask = 0;
     *dlr_url = NULL;
     *mclass = *mwi = *coding = *compress = *validity = 
-	*deferred = *pid = *alt_dcs = *rpi = 0;
+        *deferred = *pid = *alt_dcs = *rpi = *tariff = 0;
     for(l=0; l<list_len(headers); l++) {
 	http_header_get(headers, l, &name, &val);
 
@@ -388,7 +388,10 @@
     	    sscanf(octstr_get_cstr(val),"%d", mclass);
         }
 	else if (octstr_case_compare(name, octstr_imm("X-Kannel-Alt-DCS")) == 0) {
-    	    sscanf(octstr_get_cstr(val),"%d", alt_dcs);
+	    sscanf(octstr_get_cstr(val),"%d", alt_dcs);
+        }
+	else if (octstr_case_compare(name, octstr_imm("X-Kannel-Tariff")) == 0) {
+    	    sscanf(octstr_get_cstr(val),"%d", tariff);
         }
 	else if (octstr_case_compare(name, octstr_imm("X-Kannel-Compress")) == 0) {
     	    sscanf(octstr_get_cstr(val),"%d", compress);
@@ -460,7 +463,7 @@
                                   int *validity, int *deferred,
                                   int *dlr_mask, Octstr **dlr_url,
                                   Octstr **account, int *pid, int *alt_dcs,
-                                  int *rpi, List **tolist)
+                                  int *rpi, List **tolist, int *tariff)
 {                                    
 
 /*
@@ -503,7 +506,7 @@
     *dlr_mask = 0;
     *dlr_url = NULL;
     *mclass = *mwi = *coding = *compress = *validity = 
-	*deferred = *pid = *alt_dcs = *rpi = 0;
+	*deferred = *pid = *alt_dcs = *rpi = *tariff = 0;
 
     debug("sms", 0, "XMLParsing: XML: <%s>", octstr_get_cstr(*body));
 
@@ -574,6 +577,14 @@
 	O_DESTROY(tmp);
     }
 
+    /*Tariff class (tariff) */
+    get_tag(tmp, octstr_imm("tariff"), &tmp, 0, 0);
+    if(tmp) {
+        if(octstr_parse_long(&tmplong, tmp, 0, 10) != -1)
+	    *tariff = tmplong;
+        O_DESTROY(tmp);
+    }
+
     /* rpi */
     get_tag(*body, octstr_imm("rpi"), &tmp, 0, 0);
     if(tmp) {
@@ -683,7 +694,7 @@
 			 int mclass, int mwi, int coding, int compress,
 			 int validity, int deferred,
 			 Octstr *dlr_url, int dlr_mask, int pid, int alt_dcs,
-             int rpi, Octstr *smsc)
+			 int rpi, Octstr *smsc, int tariff)
 {    
     msg->sms.msgdata = replytext;
     msg->sms.time = time(NULL);
@@ -745,6 +756,12 @@
 	else 
 	    warning(0, "Tried to set MClass field, denied.");
     }
+    if (tariff) {
+        if (urltrans_accept_x_kannel_headers(trans))
+	    msg->sms.tariff = tariff;	  
+	else 
+	    warning(0, "Tried to set Tariff field, denied.");
+    }
     if (pid) {
         if (urltrans_accept_x_kannel_headers(trans))
 	    msg->sms.pid = pid;	  
@@ -881,7 +898,7 @@
     Octstr *smsc;
     int dlr_mask;
     int octets;
-    int mclass, mwi, coding, compress, pid, alt_dcs, rpi;
+    int mclass, mwi, coding, compress, pid, alt_dcs, rpi, tariff;
     int validity, deferred;
     unsigned long retries;
     unsigned int queued; /* indicate if processes reply is requeued */
@@ -920,7 +937,7 @@
 					  NULL, NULL, &smsc, &mclass, &mwi, 
 					  &coding, &compress, &validity, 
 					  &deferred, &dlr_mask, &dlr_url, 
-					  &account, &pid, &alt_dcs, &rpi);
+					  &account, &pid, &alt_dcs, &rpi, &tariff);
             } else if (octstr_case_compare(type, text_plain) == 0) {
                 replytext = octstr_duplicate(reply_body);
                 octstr_destroy(reply_body);
@@ -930,7 +947,7 @@
 					  NULL, NULL, &smsc, &mclass, &mwi, 
 					  &coding, &compress, &validity, 
 					  &deferred, &dlr_mask, &dlr_url, 
-					  &account, &pid, &alt_dcs, &rpi);
+					  &account, &pid, &alt_dcs, &rpi, &tariff);
             } else if (octstr_case_compare(type, text_xml) == 0) {
                 replytext = octstr_duplicate(reply_body);
                 octstr_destroy(reply_body); 
@@ -938,7 +955,7 @@
                 get_x_kannel_from_xml(mt_reply, &type, &replytext, reply_headers, 
                         &from, &to, &udh, NULL, NULL, &smsc, &mclass, &mwi, 
                         &coding, &compress, &validity, &deferred, &dlr_mask, 
-                        &dlr_url, &account, &pid, &alt_dcs, &rpi, NULL);
+                        &dlr_url, &account, &pid, &alt_dcs, &rpi, NULL, &tariff);
             } else if (octstr_case_compare(type, octet_stream) == 0) {
                 replytext = octstr_duplicate(reply_body);
                 octstr_destroy(reply_body);
@@ -948,7 +965,7 @@
 					  NULL, NULL, &smsc, &mclass, &mwi, 
 					  &coding, &compress, &validity, 
 					  &deferred, &dlr_mask, &dlr_url, 
-					  &account, &pid, &alt_dcs, &rpi);
+					  &account, &pid, &alt_dcs, &rpi, &tariff);
             } else {
                 replytext = octstr_duplicate(reply_couldnotrepresent); 
             }
@@ -968,7 +985,7 @@
 
         fill_message(msg, trans, replytext, octets, from, to, udh, mclass,
             mwi, coding, compress, validity, deferred, dlr_url, 
-           dlr_mask, pid, alt_dcs, rpi, smsc);
+           dlr_mask, pid, alt_dcs, rpi, smsc, tariff);
 
         if (final_url == NULL)
             final_url = octstr_imm("");
@@ -1158,6 +1175,13 @@
 	    	octstr_get_cstr(os));
 	    octstr_destroy(os);
 	}
+	if(msg->sms.tariff) {
+	    Octstr *os;
+	    os = octstr_format("%d",msg->sms.tariff);
+	    http_header_add(request_headers, "X-Kannel-Tariff", 
+	    	octstr_get_cstr(os));
+	    octstr_destroy(os);
+	}
 	if(msg->sms.mwi) {
 	    Octstr *os;
 	    os = octstr_format("%d",msg->sms.mwi);
@@ -1651,7 +1675,7 @@
 				 int validity, int deferred, 
 				 int *status, int dlr_mask, Octstr *dlr_url, 
 				 Octstr *account, int pid, int alt_dcs, int rpi,
-				 List *receiver)
+				 List *receiver, int tariff)
 {				     
     Msg *msg = NULL;
     Octstr *newfrom, *returnerror, *receiv;
@@ -1809,7 +1833,13 @@
 	goto fielderror;
     }
     msg->sms.alt_dcs = alt_dcs;
-    
+
+    if ( tariff < 0 || alt_dcs > 99 ) {
+	returnerror = octstr_create("Tariff field misformed, rejected");
+	goto fielderror;
+    }
+    msg->sms.tariff = tariff;
+
     if ( mwi < 0 || mwi > 8 ) {
 	returnerror = octstr_create("MWI field misformed, rejected");
 	goto fielderror;
@@ -2058,7 +2088,7 @@
     Octstr *account = NULL;
     int	dlr_mask = 0;
     Octstr *dlr_mask_string;
-    int mclass, mwi, coding, compress, validity, deferred, pid, alt_dcs, rpi;
+    int mclass, mwi, coding, compress, validity, deferred, pid, alt_dcs, rpi, tariff;
    
     /* check the username and password */
     t = authorise_user(args, client_ip);
@@ -2083,7 +2113,7 @@
     	dlr_mask = 0;
 
     mclass = mwi = coding = compress = validity = 
-	deferred = pid = alt_dcs = rpi = 0;
+        deferred = pid = alt_dcs = rpi = tariff = 0;
 
     tmp_string = NULL;
     tmp_string = http_cgi_variable(args, "flash");
@@ -2113,6 +2143,11 @@
         sscanf(octstr_get_cstr(tmp_string),"%d", &alt_dcs);
 
     tmp_string = NULL;
+    tmp_string = http_cgi_variable(args, "tariff");
+    if(tmp_string != NULL)
+        sscanf(octstr_get_cstr(tmp_string),"%d", &tariff);
+
+    tmp_string = NULL;
     tmp_string = http_cgi_variable(args, "mwi");
     if(tmp_string != NULL)
         sscanf(octstr_get_cstr(tmp_string),"%d", &mwi);
@@ -2157,7 +2192,7 @@
     return smsbox_req_handle(t, client_ip, from, to, text, charset, udh, 
 			     smsc, mclass, mwi, coding, compress, validity, 
 			     deferred, status, dlr_mask, dlr_url, account,
-			     pid, alt_dcs, rpi, NULL);
+			     pid, alt_dcs, rpi, NULL, tariff);
     
 }
 
@@ -2177,7 +2212,7 @@
     Octstr *account;
     List *tolist;
     int dlr_mask = 0;
-    int mclass, mwi, coding, compress, validity, deferred, pid, alt_dcs, rpi;
+    int mclass, mwi, coding, compress, validity, deferred, pid, alt_dcs, rpi, tariff;
  
     from = to = user = pass = udh = smsc = dlr_url = account = NULL;
     tolist = NULL;
@@ -2191,12 +2226,12 @@
 	get_x_kannel_from_xml(mt_push, &type, &body, headers, &from, &to, &udh,
 		       	&user, &pass, &smsc, &mclass, &mwi, &coding,
 		       	&compress, &validity, &deferred, &dlr_mask, &dlr_url, 
-			&account, &pid, &alt_dcs, &rpi, &tolist);
+			&account, &pid, &alt_dcs, &rpi, &tolist, &tariff);
     } else {
 	get_x_kannel_from_headers(headers, &from, &to, &udh,
 			      &user, &pass, &smsc, &mclass, &mwi, &coding,
 			      &compress, &validity, &deferred, 
-			      &dlr_mask, &dlr_url, &account, &pid, &alt_dcs, &rpi);
+			      &dlr_mask, &dlr_url, &account, &pid, &alt_dcs, &rpi, &tariff);
     }
 
     /* check the username and password */
@@ -2236,7 +2271,7 @@
 	    ret = smsbox_req_handle(t, client_ip, from, to, body, charset,
 				    udh, smsc, mclass, mwi, coding, compress, 
 				    validity, deferred, status, dlr_mask, 
-				    dlr_url, account, pid, alt_dcs, rpi, tolist);
+				    dlr_url, account, pid, alt_dcs, rpi, tolist, tariff);
 
 	octstr_destroy(type);
 	octstr_destroy(charset);
Index: gw/smsc_cimd2.c
===================================================================
RCS file: /home/cvs/gateway/gw/smsc_cimd2.c,v
retrieving revision 1.30
diff -u -r1.30 smsc_cimd2.c
--- gw/smsc_cimd2.c	26 Apr 2002 10:29:57 -0000	1.30
+++ gw/smsc_cimd2.c	5 Aug 2002 21:32:40 -0000
@@ -164,6 +164,10 @@
     { NULL }
 };
 
+static const int chval2(char one, char two) {
+	return (one & 0x0f) * 10 + (two & 0x0f); 
+}
+
 /* Return the index in the parameters array for this parameter id.
  * Return -1 if it is not found. */
 static const int parm_index(int parmno)
@@ -581,6 +585,14 @@
  * format is useless.  It's in the local time of the MC, with
  * a 2-digit year and no DST information.  We can do without.
  */
+// It is essential reference - <T.F>
+// We use local timezone and century!
+
+static Octstr *packet_get_time_parm(struct packet *packet, int parmno) {
+	/* Our code should never even try a bad parameter access. */
+	gw_assert(parm_type(parmno) == P_TIME);
+	return packet_get_parm(packet, parmno);
+}
 
 /* Look for a Hex parameter with id 'parmno' in the packet and return
  * its value.  Return NULL if the parameter was not found.  The value
@@ -801,6 +813,8 @@
                 octstr_get_cstr(name));
         octstr_destroy(name);
     }
+    info(0, "CIMD2 received: <%s>", octstr_get_cstr(packet->data));
+
 }
 
 /* Table of known error codes */
@@ -1234,6 +1248,11 @@
 
     packet_add_address_parm(packet, P_DESTINATION_ADDRESS, msg->sms.receiver);
 
+	if ( octstr_len(msg->sms.sender) > 0 )
+		packet_add_address_parm(packet,
+			P_ORIGINATING_ADDRESS, msg->sms.sender);
+	//T.F if we give orig. addr, let SMSC prepend service nr
+
     /* CIMD2 interprets the originating address as a sub-address to
      * our connection number (so if the connection is "400" and we
      * fill in "600" as the sender number, the user sees "400600").
@@ -1270,6 +1289,9 @@
     else
 	packet_add_int_parm(packet, P_STATUS_REPORT_REQUEST, 0);
 
+    if ( msg->sms.tariff > 0 )
+        packet_add_int_parm(packet, P_TARIFF_CLASS, msg->sms.tariff);
+
     truncated = 0;
 
     spaceleft = 140;
@@ -1401,6 +1423,8 @@
     Octstr *origin = NULL;
     Octstr *UDH = NULL;
     Octstr *text = NULL;
+    Octstr *cimdt = NULL;
+    struct tm tm;
     int DCS;
 
     /* See GSM 03.38.  The bit patterns we can handle are:
@@ -1420,6 +1444,22 @@
     UDH = packet_get_hex_parm(request, P_USER_DATA_HEADER);
     /* Text is either in User Data or User Data Binary field. */
     text = packet_get_sms_parm(request, P_USER_DATA);
+	
+	cimdt = packet_get_time_parm(request, P_MC_TIMESTAMP);
+
+	// Initialize tm with current time
+	tm = gw_gmtime(time(NULL));
+	// extract century
+	tm.tm_year = (tm.tm_year / 100) * 100;
+	tm.tm_year+= chval2(octstr_get_char(cimdt, 0), octstr_get_char(cimdt, 1));
+	tm.tm_mon  = chval2(octstr_get_char(cimdt, 2), octstr_get_char(cimdt, 3)) - 1;
+	tm.tm_mday = chval2(octstr_get_char(cimdt, 4), octstr_get_char(cimdt, 5));
+	tm.tm_hour = chval2(octstr_get_char(cimdt, 6), octstr_get_char(cimdt, 7));
+	tm.tm_min  = chval2(octstr_get_char(cimdt, 8), octstr_get_char(cimdt, 9));
+	tm.tm_sec  = chval2(octstr_get_char(cimdt,10), octstr_get_char(cimdt,11));
+	// some problems if timedrift
+	//T.F>
+
     if (text != NULL) {
 #if CIMD2_TRACE
         debug("bb.sms.cimd2", 0, "CIMD2 received message.  Text:");
@@ -1469,6 +1509,8 @@
         message->sms.udhdata = UDH;
     }
     message->sms.msgdata = text;
+	message->sms.time = (int)mktime(&tm);
+
     return message;
 
 error:
@@ -1535,6 +1577,7 @@
 retransmit:
     packet_set_send_sequence(request, smsc);
     packet_set_checksum(request);
+    info(0, "CIMD2 sending: <%s>", octstr_get_cstr(request->data));
 
     ret = octstr_write_to_socket(smsc->socket, request->data);
     if (ret < 0)
Index: gw/smsc_http.c
===================================================================
RCS file: /home/cvs/gateway/gw/smsc_http.c,v
retrieving revision 1.20
diff -u -r1.20 smsc_http.c
--- gw/smsc_http.c	26 Apr 2002 10:31:57 -0000	1.20
+++ gw/smsc_http.c	5 Aug 2002 21:32:40 -0000
@@ -258,6 +258,19 @@
 	octstr_format_append(url, "&account=%E:%E", sms->sms.service, sms->sms.account);
 
     headers = list_create();
+
+    // if there is tariff information, append it here
+    if(sms->sms.tariff!=0) {
+        Octstr *os;
+        os = octstr_format("%d",sms->sms.tariff);
+	http_header_add(headers, "X-Kannel-Tariff", 
+			octstr_get_cstr(os));
+	octstr_destroy(os);
+
+	octstr_format_append(url, "&tariff=%d", sms->sms.tariff);
+
+	debug("smsc.http.kannel", 0, "Adding tariff information");
+    }
     debug("smsc.http.kannel", 0, "start request");
     http_start_request(conndata->http_ref, url, headers, NULL, 0, sms, NULL);
configure_patch.diff (text/plain, 1.3 KB)
Index: configure
===================================================================
RCS file: /home/cvs/gateway/configure,v
retrieving revision 1.101
diff -u -r1.101 configure
--- configure	2 Aug 2002 13:19:41 -0000	1.101
+++ configure	5 Aug 2002 21:32:38 -0000
@@ -2140,7 +2140,7 @@
 '
   echo "${nl}${T_MD}Checking for libxml2 support ...${T_ME}"
 
-xml_ver_required="2.2.5"
+xml_ver_required="2.3.0"
 for ac_prog in xml2-config xml-config
 do
 # Extract the first word of "$ac_prog", so it can be a program name with args.
Index: configure.in
===================================================================
RCS file: /home/cvs/gateway/configure.in,v
retrieving revision 1.103
diff -u -r1.103 configure.in
--- configure.in	2 Aug 2002 13:19:41 -0000	1.103
+++ configure.in	5 Aug 2002 21:32:38 -0000
@@ -178,10 +178,10 @@
 
 
 dnl Check if we have libxml2 installed and which version it is.
-dnl Kannel requires currently at least version 2.2.5 of libxml2.
+dnl Kannel requires currently at least version 2.3.0 of libxml2.
 
 AC_CONFIG_SECTION([Checking for libxml2 support])
-xml_ver_required="2.2.5"
+xml_ver_required="2.3.0"
 AC_PATH_PROGS(XML_CONFIG, xml2-config xml-config, no)
 if test "$XML_CONFIG" = "no"; then
   AC_MSG_ERROR([You MUST have the libxml2 (aka gnome-xml) library installed])
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.