Hi ,

This is a proposed implementation for sending data_sm PDUs that also enforces SMPP requirement for having sm_length=0 when using message_payload TLV. To send a data_sm PDU the sendsms request should be like meta-data?smsc-type=smpp_data_sm?. *msg_to_pdu() was replaced by two functions *msg_to_sm_pdu() and *msg_to_datasm_pdu() for submit_sm and data_sm() PDUs respectively and handle_pdu() got a new case for incoming data_sm_resp PDU.


BR,

Michael Zervakis



-----Original Message-----
From: Alexander Malysh [mailto:malys...@googlemail.com] On Behalf Of Alexander Malysh
Sent: Friday, November 27, 2009 5:04 PM
To: Michael Zervakis
Cc: Kannel Devel; Alejandro Guerrieri
Subject: Re: SMPP data_sm implementation for MT messages



where do you have message_payload extracted to user?



that is simple:



MT(data_sm) -> sendsms?text=ABC&metadata=?smpp?pdu_type=data_sm... -> data_sm.message_payload=ABC

MT(submit_sm) -> sendsms?text=ABC... -> submit_sm.short_message=ABC



MO(data_sm) -> data_sm.message_payload=ABC -> receivesms?text=ABC&metadata=?smpp?pdu_type=data_sm

MO(submit_sm) -> submit_sm.short_message=ABC -> receivesms?text=ABC



If user set for MT text=ABC&metadata=?smpp?pdu_type=data_sm&message_payload=XXX then it's undefined and

we are free to choose which one to use and I would prefer to use text as message_payload...



Hope that's clear.



Thanks,

Alexander Malysh



Am 27.11.2009 um 15:21 schrieb Michael Zervakis:



>

> Let's assume that we follow Alex's recommendation "meta-data=?smpp?operation=data_sm&..." and if operation is omitted we use submit_sm as default.

>

>

> We should clarify what should happen to "text=xxxx" if set and this should affect both submit_sm and data_sm operations as SMPP specs state that short_message and message_payload cannot coexist in a PDU (sm_length should be zero if message_payload is used). I can think of three cases here:

>

> 1) When "text" has a value and "message_payload" is not set. For submit_sm no need to change anything. For data_sm we append meta-data with message_payload and set the value of "text" to it (example: "text=XXXX&meta-data=?smpp?operation=data_sm").

> 2) When both "text" and "message_payload" have values. For submit_sm operation "text" value is set to null (so "sm_length" is set to 0 and we don't break specs) and we use the provided "message_payload" value. For data_sm operation we simply ignore "text" value.

>

> 3) When "message_payload" has a value and "text" is not set. Normal case doesn't break specs.

>

>

>

>

>

>> -----Original Message-----

>> From: Alexander Malysh [mailto:malys...@googlemail.com] On Behalf Of

> Alexander Malysh

>> Sent: Friday, November 27, 2009 3:32 PM

>> To: Michael Zervakis

>> Cc: devel@kannel.org; aguerri...@kannel.org

>> Subject: Re: SMPP data_sm implementation for MT messages

>

>

>> Hi,

>

>

>> why not just use metadata=?smpp?operation=data_sm&... ?

>

>> then you can check in smsc_smpp whether submit_sm or data_sm should be used.

>

>

>> Whether you have to use message_payload or short_message is

> implementation details that

>

>> should not be exported to user interface.

>

>

>> Thanks,

>

>> Alexander Malysh

>

>

>> Am 27.11.2009 um 13:00 schrieb Michael Zervakis:

>

>

>> > Data_sm PDU cannot contain a short_message field. Actually data_sm

> contains only TLVs and instead of "short_message" field we should use TLV "message_payload" to send text. As a result text=xxxx is obsolete when sending data_sm PDU. If we use data=xxxx what would be the value of data since all necessary data will be included in "meta-data=?smpp?" ?

>

>> >

>

>> >

>

>> >> -----Original Message-----

>

>> >> From: Alejandro Guerrieri [mailto:aguerri...@kannel.org]

>

>> >> Sent: Friday, November 27, 2009 12:04 PM

>

>> >> To: Michael Zervakis

>

>> >> Cc: devel@kannel.org

>

>> >> Subject: Re: SMPP data_sm implementation for MT messages

>

>> >

>

>> >

>

>> > >What about using "data=xxxx" instead of "text=xxxx" ?

>

>> >

>

>> > >--

>

>> >

>

>> > >Alejandro Guerrieri

>

>> >

>

>> > >aguerri...@kannel.org

>

>> >

>

>> > >

>

>> > >

>

>> > >

>

>> > >On 27/11/2009, at 10:00, Michael Zervakis wrote:

>

>> >

>

>> > >

>

>> > >> Data_sm can be used as an alternate of submit_sm when transmitting

>

>> > >> optional parameters (meta-data) and some carriers require the use of

>

>> > >> data_sm for MT charging applications.

>

>> >

>

>> > >> Since Kannel is not implementing this feature it's a good idea to

>

>> > >> start a discussion on how this could be implemented.

>

>> >

>

>> > >>

>

>> > >> First of all it's obvious that "static int send_messages()" at gw

>

>> >

>

>> > >> \smsc\smsc_smpp.c must be able to differentiate msgs that need to be

>

>> > >> sent as data_sm.

>

>> >

>

>> > >> I can think of two ways to achieve this:

>

>> >

>

>> > >> 1) Alter MSG definition to inlcude a new parameter that defines type

>

>> > >> of message Data or normal SMS

>

>> >

>

>> > >> Possible ways to use the new parameter could be the following

>

>> >

>

>> > >> /cgi-bin/sendsms?from=1111&to=2222&<new parameter>=data&meta-data=?

>

>> >

>

>> > >> smpp?key=value

>

>> >

>

>> > >> /cgi-bin/senddata?from=1111&to=2222&meta-data=?smpp?key=value

>

>> >

>

>> > >> 2) Leave MSG definition untouched and use meta-data to mark msg as

>

>> > >> data

>

>> >

>

>> > >> /cgi-bin/sendsms?from=1111&to=2222&meta-data=?smpp?<new

>

>> > >> parameter>=data&key=value

>

>> >

>

>> > >>

>

>> > >> Finally a new function has to be defined at gw\smsc\smsc_smpp.c to

>

>> > >> build data_sm pdu from msg for example "static SMPP_PDU

>

>> > >> *dmsg_to_pdu(SMPP *smpp, Msg *msg)"

>

>> >

>

>> > >> and function "static int handle_pdu()" at gw\smsc\smsc_smpp.c has to

>

>> > >> be modified to include a case for data_sm_resp PDU.

>

>> >

>

>> > >>

>

>> > >> Any comments?

>

>> >

>

>> > >>

>

>> > >>

>

>> >

>

>



Index: doc/userguide/userguide.xml
===================================================================
--- doc/userguide/userguide.xml (revision 4833)
+++ doc/userguide/userguide.xml (working copy)
@@ -9781,12 +9781,14 @@
         </sect3>
       </sect2>
       <sect2>
-        <title>MT Messages</title>
+        <title>MT Messages SUBMIT_SM or DATA_SM</title>
         <para>To send into an MT messages the <literal>meta-data</literal> 
parameter should be used.</para>
         
         <para>The format used to pass the data has 2 parts: The 
<literal>?smsc-type?</literal> (surrounded by question marks),
-        which specify the kind of smsc receiving the data (at the moment only 
<literal>smpp</literal> is implemented) and then a set of key/value
-        pairs with the data to be transmitted. Extra smsc-types can be added 
surrounded by question marks and followed by the key/value pairs.</para>
+        which specify the kind of smsc receiving the data and then a set of 
key/value pairs with the data to be transmitted. 
+        Currently only SMPP is implemented with two possible values for 
<literal>?smsc-type?</literal>: <literal>smpp</literal> 
+        for SUBMIT_SM PDUs and <literal>smpp_data_sm</literal>) for DATA_SM 
PDUs.
+        Extra smsc-types can be added surrounded by question marks and 
followed by the key/value pairs.</para>
         
         <para>In other words,  the data should be coded using the following 
format, where URLENCODE() implies that the data between parentheses should
         be urlencoded:</para>
@@ -9800,14 +9802,26 @@
 
              <sect3>
                <title>Examples</title>
-               <para>If we want to send the parameter "my-data" with value 
"Hello World" to an SMSC over SMPP, we'd use:</para>
+               <para>If we want to send the parameter "my-data" with value 
"Hello World" to an SMSC over SMPP using SUBMIT_SM PDU, we'd use:</para>
                <para>sendsms get-url:</para>
                
<para><literal>http://localhost:13013/cgi-bin/sendsms?...&amp;meta-data=%3Fsmpp%3Fmy-data%3DHello%2BWorld</literal></para>
+            <para>Similarly if we want to send the above using DATA_SM PDU, 
we'd use:</para>
+               <para>sendsms get-url:</para>
+               
<para><literal>http://localhost:13013/cgi-bin/sendsms?...&amp;meta-data=%3Fsmpp_data_sm%3Fmy-data%3DHello%2BWorld</literal></para>
           <para>sendsms post:</para>
           <para>Send <literal>?smpp?my-data=Hello+World</literal> on the 
<literal>X-Kannel-Meta-Data</literal> header</para>
-          <para>XML:</para>
+          <para>XML: SUBMIT_SM</para>
           
<para><literal>&lt;meta-data&gt;?smpp?my-data=Hello+World&lt;/meta-data&gt;</literal></para>
+          <para>XML: DATA_SM</para>
+          
<para><literal>&lt;meta-data&gt;?smpp_data_sm?my-data=Hello+World&lt;/meta-data&gt;</literal></para>
              </sect3>
+
+          </sect3>
+            <title>SMPP TLV message_payload (0x0424)</title>
+            <para>SMPP message_payload TLV is an alternative to submit_sm 
short_message when sending messages longer than 255 octets.
+                  When sending submit_sm PDU with message_payload then 
short_message should be null. Kannel enforces this restriction 
+                  by ignoring supplied values for <literal>text</literal> if 
<literal>message_payload</literal> TLV is present.</para>
+          </sect3>
       </sect2>
     </sect1>
 </appendix>
Index: gw/smsc/smsc_smpp.c
===================================================================
--- gw/smsc/smsc_smpp.c (revision 4833)
+++ gw/smsc/smsc_smpp.c (working copy)
@@ -747,14 +747,12 @@
 }
 
 
-static SMPP_PDU *msg_to_pdu(SMPP *smpp, Msg *msg)
+static SMPP_PDU *msg_to_sm_pdu(SMPP_PDU *pdu, Msg *msg, SMPP *smpp)
 {
-    SMPP_PDU *pdu;
+
     int validity;
-
-    pdu = smpp_pdu_create(submit_sm,
-                         counter_increase(smpp->message_id_counter));
-
+
+
     pdu->u.submit_sm.source_addr = octstr_duplicate(msg->sms.sender);
     pdu->u.submit_sm.destination_addr = octstr_duplicate(msg->sms.receiver);
 
@@ -876,9 +874,41 @@
     /*
      * set data segments and length
      */
-
-    pdu->u.submit_sm.short_message = octstr_duplicate(msg->sms.msgdata);
-
+    
+    /* 
+     If a message contains both msg_data and meta_data and within meta_data is 
contained the tlv message_payload
+     then ignore smg_data field forward message's meta_data and print a 
warning message
+     */ 
+    
+    
+    if((octstr_len(msg->sms.msgdata)) && (octstr_len(msg->sms.meta_data)))
+    {   
+        debug("bb.sms.smpp", 0, "msg->sms.msgdata = [%s] and 
msg->sms.meta_data !=[%s]", 
octstr_get_cstr(msg->sms.msgdata),octstr_get_cstr(msg->sms.meta_data));
+        
+        if(octstr_search(msg->sms.meta_data, 
octstr_imm("message_payload"),0)!=-1) 
+        {
+            pdu->u.submit_sm.short_message == NULL; 
+            pdu->u.submit_sm.sm_length = 0;
+            warning(0, "SMPP[%s]: Ignoring msg->sms.msgdata = [%s] because 
msg->sms.meta_data(message_payload)= [%s] TLV message_payload was found ",
+                    
octstr_get_cstr(smpp->conn->id),octstr_get_cstr(msg->sms.msgdata),octstr_get_cstr(msg->sms.meta_data));
+            
+        }
+        else
+        {
+            pdu->u.submit_sm.short_message = 
octstr_duplicate(msg->sms.msgdata);
+            pdu->u.submit_sm.sm_length = 
octstr_len(pdu->u.submit_sm.short_message);
+            
+        }
+    }
+    else
+    {
+        pdu->u.submit_sm.short_message = octstr_duplicate(msg->sms.msgdata);
+        pdu->u.submit_sm.sm_length = 
octstr_len(pdu->u.submit_sm.short_message);
+        
+    } 
+    
+    /*pdu->u.submit_sm.short_message = octstr_duplicate(msg->sms.msgdata);*/
+    
     /*
      * only re-encoding if using default smsc charset that is defined via
      * alt-charset in smsc group and if MT is not binary
@@ -908,9 +938,9 @@
     if (octstr_len(msg->sms.udhdata)) {
         octstr_insert(pdu->u.submit_sm.short_message, msg->sms.udhdata, 0);
     }
-
-    pdu->u.submit_sm.sm_length = octstr_len(pdu->u.submit_sm.short_message);
-
+
     /*
      * check for validity and defered settings
      * were message value has higher priiority then smsc config group value
@@ -958,6 +988,228 @@
 }
 
 
+/* Function to create a data_sm pdu
+ 
+ Pdu fields:
+ 
+ (common to both sumbit_sm and data_sm)
+ 1. command length
+ 2. command id
+ 3. command status
+ 4. sequence number
+ 5. service type
+ 6. source_addr_ton
+ 7. source_addr_npi
+ 8. source_addr
+ 9. dest_addr_ton
+ 10. dest_addr_npi
+ 11.destnation_addr
+ 12. esm_class
+ 13. registered_delivery
+ 14. data_coding
+ 15. Optional TLVs
+ 
+ */
+
+static SMPP_PDU *msg_to_datasm_pdu(SMPP_PDU *pdu, Msg *msg, SMPP *smpp)
+{
+
+
+    pdu->u.data_sm.source_addr = octstr_duplicate(msg->sms.sender);
+
+    pdu->u.data_sm.destination_addr = octstr_duplicate(msg->sms.receiver);
+
+
+    /* Set the service type of the outgoing message. We'll use the config
+     * directive as default and 'binfo' as specific parameter. */
+    pdu->u.data_sm.service_type = octstr_len(msg->sms.binfo) ?
+    octstr_duplicate(msg->sms.binfo) : octstr_duplicate(smpp->service_type);
+
+
+
+    /* Check for manual override of source ton and npi values */
+    if(smpp->source_addr_ton > -1 && smpp->source_addr_npi > -1) {
+        pdu->u.data_sm.source_addr_ton = smpp->source_addr_ton;
+        pdu->u.data_sm.source_addr_npi = smpp->source_addr_npi;
+        debug("bb.sms.smpp", 0, "SMPP[%s]: Manually forced source addr ton = 
%d, source add npi = %d",
+              octstr_get_cstr(smpp->conn->id), smpp->source_addr_ton,
+              smpp->source_addr_npi);
+    } else {
+        /* setup default values */
+        pdu->u.data_sm.source_addr_ton = GSM_ADDR_TON_NATIONAL; /* national */
+        pdu->u.data_sm.source_addr_npi = GSM_ADDR_NPI_E164; /* ISDN number 
plan */
+    }
+
+    if (pdu->u.data_sm.source_addr && smpp->autodetect_addr) {
+        /* lets see if its international or alphanumeric sender */
+        if (octstr_get_char(pdu->u.data_sm.source_addr, 0) == '+') {
+            if (!octstr_check_range(pdu->u.data_sm.source_addr, 1, 256, 
gw_isdigit)) {
+                pdu->u.data_sm.source_addr_ton = GSM_ADDR_TON_ALPHANUMERIC; /* 
alphanum */
+                pdu->u.data_sm.source_addr_npi = GSM_ADDR_NPI_UNKNOWN;    /* 
short code */
+                if (smpp->alt_addr_charset) {
+                    if (octstr_str_case_compare(smpp->alt_addr_charset, "gsm") 
== 0) {
+                        /* @ would break PDU if converted into GSM*/
+                        octstr_replace(pdu->u.data_sm.source_addr, 
octstr_imm("@"), octstr_imm("?"));
+                        charset_utf8_to_gsm(pdu->u.data_sm.source_addr);
+                    } else if (charset_convert(pdu->u.data_sm.source_addr, 
SMPP_DEFAULT_CHARSET, octstr_get_cstr(smpp->alt_addr_charset)) != 0)
+                        error(0, "Failed to convert source_addr from charset 
<%s> to <%s>, will send as is.",
+                              SMPP_DEFAULT_CHARSET, 
octstr_get_cstr(smpp->alt_addr_charset));
+                }
+            } else {
+                /* numeric sender address with + in front -> international 
(remove the +) */
+                octstr_delete(pdu->u.data_sm.source_addr, 0, 1);
+                pdu->u.data_sm.source_addr_ton = GSM_ADDR_TON_INTERNATIONAL;
+            }
+        } else {
+            if (!octstr_check_range(pdu->u.submit_sm.source_addr,0, 256, 
gw_isdigit)) {
+                pdu->u.data_sm.source_addr_ton = GSM_ADDR_TON_ALPHANUMERIC;
+                pdu->u.data_sm.source_addr_npi = GSM_ADDR_NPI_UNKNOWN;
+                if (smpp->alt_addr_charset) {
+                    if (octstr_str_case_compare(smpp->alt_addr_charset, "gsm") 
== 0) {
+                        /* @ would break PDU if converted into GSM */
+                        octstr_replace(pdu->u.data_sm.source_addr, 
octstr_imm("@"), octstr_imm("?"));
+                        charset_utf8_to_gsm(pdu->u.data_sm.source_addr);
+                    } else if (charset_convert(pdu->u.data_sm.source_addr, 
SMPP_DEFAULT_CHARSET, octstr_get_cstr(smpp->alt_addr_charset)) != 0)
+                        error(0, "Failed to convert source_addr from charset 
<%s> to <%s>, will send as is.",
+                              SMPP_DEFAULT_CHARSET, 
octstr_get_cstr(smpp->alt_addr_charset));
+                }
+            }
+        }
+    }
+
+
+    /* Check for manual override of destination ton and npi values */
+    if (smpp->dest_addr_ton > -1 && smpp->dest_addr_npi > -1) {
+        pdu->u.data_sm.dest_addr_ton = smpp->dest_addr_ton;
+        pdu->u.data_sm.dest_addr_npi = smpp->dest_addr_npi;
+        debug("bb.sms.smpp", 0, "SMPP[%s]: Manually forced dest addr ton = %d, 
dest add npi = %d",
+              octstr_get_cstr(smpp->conn->id), smpp->dest_addr_ton,
+              smpp->dest_addr_npi);
+    } else {
+        pdu->u.data_sm.dest_addr_ton = GSM_ADDR_TON_NATIONAL; /* national */
+        pdu->u.data_sm.dest_addr_npi = GSM_ADDR_NPI_E164; /* ISDN number plan 
*/
+    }
+
+    /*
+     * if its a international number starting with +, lets remove the
+     * '+' and set number type to international instead
+     */
+    if (octstr_get_char(pdu->u.data_sm.destination_addr,0) == '+') {
+        octstr_delete(pdu->u.data_sm.destination_addr, 0,1);
+        pdu->u.data_sm.dest_addr_ton = GSM_ADDR_TON_INTERNATIONAL;
+    }
+    
+    /* check length of src/dst address */
+    if (octstr_len(pdu->u.data_sm.destination_addr) > 20 ||
+        octstr_len(pdu->u.data_sm.source_addr) > 20) {
+        smpp_pdu_destroy(pdu);
+        return NULL;
+    }
+
+    /*
+     * set the data coding scheme (DCS) field
+     * check if we have a forced value for this from the smsc-group.
+     * Note: if message class is set, then we _must_ force alt_dcs otherwise
+     * dcs has reserved values (e.g. mclass=2, dcs=0x11). We check MWI flag
+     * first here, because MWI and MCLASS can not be set at the same time and
+     * function fields_to_dcs check MWI first, so we have no need to force 
alt_dcs
+     * if MWI is set.
+     */
+    if (msg->sms.mwi == MWI_UNDEF && msg->sms.mclass != MC_UNDEF)
+        pdu->u.data_sm.data_coding = fields_to_dcs(msg, 1); /* force alt_dcs */
+    else
+        pdu->u.data_sm.data_coding = fields_to_dcs(msg,
+                                                   (msg->sms.alt_dcs != 
SMS_PARAM_UNDEFINED ?
+                                                    msg->sms.alt_dcs : 
smpp->conn->alt_dcs));
+
+
+    /*
+     * set the esm_class field
+     * default is store and forward, plus udh and rpi if requested
+     */
+    pdu->u.data_sm.esm_class = ESM_CLASS_SUBMIT_STORE_AND_FORWARD_MODE;
+    if (octstr_len(msg->sms.udhdata))
+        pdu->u.data_sm.esm_class = pdu->u.submit_sm.esm_class |
+        ESM_CLASS_SUBMIT_UDH_INDICATOR;
+    if (msg->sms.rpi > 0)
+        pdu->u.data_sm.esm_class = pdu->u.submit_sm.esm_class |
+        ESM_CLASS_SUBMIT_RPI;
+
+
+    /* ask for the delivery reports if needed */
+    if (DLR_IS_SUCCESS_OR_FAIL(msg->sms.dlr_mask))
+        pdu->u.data_sm.registered_delivery = 1;
+    else if (DLR_IS_FAIL(msg->sms.dlr_mask) && 
!DLR_IS_SUCCESS(msg->sms.dlr_mask))
+        pdu->u.data_sm.registered_delivery = 2;
+
+    if (DLR_IS_INTERMEDIATE(msg->sms.dlr_mask))
+        pdu->u.data_sm.registered_delivery += 16;
+
+
+
+    /* set more messages to send */
+    if (smpp->version > 0x33 && msg->sms.msg_left > 0)
+        pdu->u.data_sm.more_messages_to_send = 1;
+
+    dict_destroy(pdu->u.data_sm.tlv);
+
+    /* search within meta_data group for smpp_data_sm */
+    pdu->u.data_sm.tlv = meta_data_get_values(msg->sms.meta_data, 
"smpp_data_sm");
+
+    /*pdu->u.data_sm.data_coding = 1;*/
+
+
+    return pdu; 
+}
+
+
+
+/* Procedure for deternining the type of pdu to build :
+ 1. Submit_sm message will be build by the msg_to_pdu when the field meta_data 
is empty 
+ or when within the meta_data mesage field there is not a string of the form 
"pdu_type=data_sm". 
+ 2. Else when the meta_data is not empty and contains a string of the form 
"pdu_type=data_sm" the 
+ pdu that is going to be build will be a data_sm pdu.
+ */
+
+static SMPP_PDU *msg_to_pdu(SMPP *smpp, Msg *msg)
+{
+    SMPP_PDU *pdu;
+    unsigned long pdu_type =0;
+    
+    /* make sure we are not searching within a null string */
+    if(octstr_len(msg->sms.meta_data) == 0)
+    {    
+        pdu_type = submit_sm;
+        debug("bb.sms.smpp", 0, "msg_to_pdu : pdu_type = submit_sm");
+    }    
+    else if(octstr_search(msg->sms.meta_data, 
octstr_imm("?smpp_data_sm?"),0)==-1)
+    {
+        pdu_type = submit_sm;      
+        debug("bb.sms.smpp", 0, "msg_to_pdu : pdu_type = submit_sm");
+    }
+    else 
+    {        
+        pdu_type = data_sm;    
+        debug("bb.sms.smpp", 0, "msg_to_pdu : pdu_type = data_sm");
+    }
+
+
+    /* kltsa : 07/07/2010 : submit_sm will now passed as parameter pdu_type */
+    pdu = smpp_pdu_create(pdu_type,counter_increase(smpp->message_id_counter));
+
+    switch (pdu_type) 
+    {
+        case data_sm  : pdu = msg_to_datasm_pdu(pdu,msg,smpp);
+            break;/*add other cases here*/
+        default: pdu = msg_to_sm_pdu(pdu,msg,smpp);
+            break;
+    }
+
+    return pdu;
+}    
+
+
+
 static int send_enquire_link(SMPP *smpp, Connection *conn, long *last_sent)
 {
     SMPP_PDU *pdu;
@@ -1073,7 +1325,21 @@
         /* check for write errors */
         if (send_pdu(conn, smpp->conn->id, pdu) == 0) {
             struct smpp_msg *smpp_msg = smpp_msg_create(msg);
-            os = octstr_format("%ld", pdu->u.submit_sm.sequence_number);
+
+            /* Check for sequence number errors depending on pdu type */
+            if(pdu->type == submit_sm)
+            {
+                os = octstr_format("%ld", pdu->u.submit_sm.sequence_number);
+                debug("bb.sms.smpp", 0, "send_messages : pdu->type = 
submit_sm");
+            }
+            else if(pdu->type == data_sm)
+            {
+                os = octstr_format("%ld", pdu->u.data_sm.sequence_number);
+                debug("bb.sms.smpp", 0, "send_messages : pdu->type = data_sm");
+            }
+            else
+                error(0, "send_messages : :unknown pdu type = 
[%lu]!\n",pdu->type);
+
             dict_put(smpp->sent_msgs, os, smpp_msg);
             smpp_pdu_destroy(pdu);
             octstr_destroy(os);
@@ -1504,9 +1770,72 @@
                 msg->sms.smsc_id = octstr_duplicate(smpp->conn->id);
                 reason =  bb_smscconn_receive(smpp->conn, msg);
                 resp->u.data_sm_resp.command_status = 
smscconn_failure_reason_to_smpp_status(reason);
-           }
-           break;
-
+            }
+            break;
+        case data_sm_resp:
+            os = octstr_format("%ld", pdu->u.data_sm_resp.sequence_number);
+            smpp_msg = dict_remove(smpp->sent_msgs, os);
+            octstr_destroy(os);
+            if (smpp_msg == NULL) {
+                warning(0, "SMPP[%s]: SMSC sent data_sm_resp "
+                        "with wrong sequence number 0x%08lx",
+                        octstr_get_cstr(smpp->conn->id),
+                        pdu->u.data_sm_resp.sequence_number);
+                break;
+            }
+            msg = smpp_msg->msg;
+            smpp_msg_destroy(smpp_msg, 0);
+            if (pdu->u.data_sm_resp.command_status != 0) {
+                error(0, "SMPP[%s]: SMSC returned error code 0x%08lx (%s) "
+                      "in response to data_sm.",
+                      octstr_get_cstr(smpp->conn->id),
+                      pdu->u.data_sm_resp.command_status,
+                      
smpp_error_to_string(pdu->u.data_sm_resp.command_status));
+                reason = smpp_status_to_smscconn_failure_reason(
+                                                                
pdu->u.data_sm_resp.command_status);
+
+                /*
+                 * check to see if we got a "throttling error", in which case 
we'll just
+                 * sleep for a while
+                 */
+                if (pdu->u.data_sm_resp.command_status == SMPP_ESME_RTHROTTLED)
+                    time(&(smpp->throttling_err_time));
+                else
+                    smpp->throttling_err_time = 0;
+
+                bb_smscconn_send_failed(smpp->conn, msg, reason, 
octstr_format("0x%08lx/%s", pdu->u.data_sm_resp.command_status,
+                                                                               
smpp_error_to_string(pdu->u.data_sm_resp.command_status)));
+                --(*pending_submits);
+            } else {
+                Octstr *tmp;
+
+                /* check if msg_id is C string, decimal or hex for this SMSC */
+                if (smpp->smpp_msg_id_type == -1) {
+                    /* the default, C string */
+                    tmp = octstr_duplicate(pdu->u.data_sm_resp.message_id);
+                } else {
+                    if ((smpp->smpp_msg_id_type & 0x01) ||
+                        (!octstr_check_range(pdu->u.data_sm_resp.message_id, 0,
+                                             
octstr_len(pdu->u.data_sm_resp.message_id), gw_isdigit))) {
+                        tmp = octstr_format("%llu", strtoll(  /* hex */
+                                                            
octstr_get_cstr(pdu->u.data_sm_resp.message_id), NULL, 16));
+                    } else {
+                        tmp = octstr_format("%llu", strtoll(  /* decimal */
+                                                            
octstr_get_cstr(pdu->u.data_sm_resp.message_id), NULL, 10));
+                    }
+                }
+
+                /* SMSC ACK.. now we have the message id. */
+                if (DLR_IS_ENABLED_DEVICE(msg->sms.dlr_mask))
+                    dlr_add(smpp->conn->id, tmp, msg);
+
+                octstr_destroy(tmp);
+                bb_smscconn_sent(smpp->conn, msg, NULL);
+                --(*pending_submits);
+            } /* end if for SMSC ACK */
+            break;
+
         case deliver_sm:
               /*
             * If SMSCConn stopped then send temp. error code

Reply via email to