[patch] preliminary tariff support (update)

Marko Saaresto <[email protected]>
Newsgroups gmane.comp.mobile.kannel.devel
Organization Matchem Oy
Message-ID <[email protected]>
This is a repost of the tariff patch I posted earlier this summer. It 
has been adapted to reflect the new location of SMSC drivers.

We at Matchem could _really_ use tariff support and I personally would 
like to see this one accepted to the main CVS branch instead of 
maintaining a proprietary in-house patch . How about? Do you think this 
approach is good enough? Does it need more developement first? Should a 
new sub-project be established?


-- 
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.7 KB)
Index: doc/userguide/userguide.xml
===================================================================
RCS file: /home/cvs/gateway/doc/userguide/userguide.xml,v
retrieving revision 1.189
diff -u -r1.189 userguide.xml
--- doc/userguide/userguide.xml	22 Aug 2002 17:29:39 -0000	1.189
+++ doc/userguide/userguide.xml	28 Aug 2002 15:40:42 -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
@@ -3076,6 +3079,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
@@ -3404,6 +3411,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>
@@ -4587,6 +4613,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>
@@ -5756,6 +5785,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	28 Aug 2002 15:40:42 -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.209
diff -u -r1.209 smsbox.c
--- gw/smsbox.c	20 Aug 2002 21:13:22 -0000	1.209
+++ gw/smsbox.c	28 Aug 2002 15:40:42 -0000
@@ -322,7 +322,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;
@@ -330,7 +330,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);
 
@@ -393,7 +393,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);
@@ -465,7 +468,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)
 {                                    
 
 /*
@@ -508,7 +511,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));
 
@@ -579,6 +582,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) {
@@ -688,7 +699,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);
@@ -750,6 +761,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;	  
@@ -888,7 +905,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 */
@@ -927,7 +944,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);
@@ -937,7 +954,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); 
@@ -945,7 +962,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);
@@ -955,7 +972,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); 
             }
@@ -975,7 +992,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("");
@@ -1165,6 +1182,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);
@@ -1658,7 +1682,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;
@@ -1816,7 +1840,13 @@
 	goto fielderror;
     }
     msg->sms.alt_dcs = alt_dcs;
-    
+
+    if ( tariff < 0 || tariff > 999 ) {
+	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;
@@ -2065,7 +2095,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);
@@ -2090,7 +2120,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");
@@ -2120,6 +2150,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);
@@ -2164,7 +2199,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);
     
 }
 
@@ -2184,7 +2219,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;
@@ -2198,12 +2233,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 */
@@ -2243,7 +2278,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/smsc_cimd2.c
===================================================================
RCS file: /home/cvs/gateway/gw/smsc/smsc_cimd2.c,v
retrieving revision 1.1
diff -u -r1.1 smsc_cimd2.c
--- gw/smsc/smsc_cimd2.c	8 Aug 2002 17:44:38 -0000	1.1
+++ gw/smsc/smsc_cimd2.c	28 Aug 2002 15:40:43 -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)
@@ -582,6 +586,16 @@
  * 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
  * is de-hexed. */
@@ -801,6 +815,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 +1250,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 +1291,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 +1425,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 +1446,21 @@
     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 +1510,8 @@
         message->sms.udhdata = UDH;
     }
     message->sms.msgdata = text;
+	message->sms.time = (int)mktime(&tm);
+
     return message;
 
 error:
@@ -1535,6 +1578,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/smsc_http.c
===================================================================
RCS file: /home/cvs/gateway/gw/smsc/smsc_http.c,v
retrieving revision 1.3
diff -u -r1.3 smsc_http.c
--- gw/smsc/smsc_http.c	20 Aug 2002 21:13:56 -0000	1.3
+++ gw/smsc/smsc_http.c	28 Aug 2002 15:40:43 -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, HTTP_METHOD_GET, url, headers, 
                        NULL, 0, sms, NULL);
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.