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?...&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?...&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><meta-data>?smpp?my-data=Hello+World</meta-data></literal></para>
+ <para>XML: DATA_SM</para>
+
<para><literal><meta-data>?smpp_data_sm?my-data=Hello+World</meta-data></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