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