Main Page | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals

smsc_smpp.c File Reference

#include "gwlib/gwlib.h"
#include "msg.h"
#include "smsc_p.h"
#include "smpp_pdu.h"
#include "smscconn_p.h"
#include "bb_smscconn_cb.h"
#include "sms.h"
#include "dlr.h"
#include "bearerbox.h"

Include dependency graph for smsc_smpp.c:

Include dependency graph

Go to the source code of this file.

Data Structures

struct  SMPP
struct  smpp_msg
struct  io_arg

Defines

#define SMPP_DEFAULT_CHARSET   "UTF-8"
#define DEBUG   1
#define dump_pdu(msg, id, pdu)
#define SMPP_ENQUIRE_LINK_INTERVAL   30.0
#define SMPP_MAX_PENDING_SUBMITS   10
#define SMPP_DEFAULT_VERSION   0x34
#define SMPP_DEFAULT_PRIORITY   0
#define SMPP_THROTTLING_SLEEP_TIME   15
#define SMPP_DEFAULT_CONNECTION_TIMEOUT   10 * SMPP_ENQUIRE_LINK_INTERVAL
#define SMPP_DEFAULT_WAITACK   60
#define SMPP_DEFAULT_SHUTDOWN_TIMEOUT   30
#define SMPP_WAITACK_RECONNECT   0x00
#define SMPP_WAITACK_REQUEUE   0x01
#define SMPP_WAITACK_NEVER_EXPIRE   0x02

Functions

smpp_msgsmpp_msg_create (Msg *msg)
void smpp_msg_destroy (struct smpp_msg *msg, int destroy_msg)
SMPPsmpp_create (SMSCConn *conn, Octstr *host, int transmit_port, int receive_port, Octstr *system_type, Octstr *username, Octstr *password, Octstr *address_range, int source_addr_ton, int source_addr_npi, int dest_addr_ton, int dest_addr_npi, int enquire_link_interval, int max_pending_submits, int version, int priority, int validity, Octstr *my_number, int smpp_msg_id_type, int autodetect_addr, Octstr *alt_charset, Octstr *alt_addr_charset, Octstr *service_type, long connection_timeout, long wait_ack, int wait_ack_action)
void smpp_destroy (SMPP *smpp)
int read_pdu (SMPP *smpp, Connection *conn, long *len, SMPP_PDU **pdu)
long convert_addr_from_pdu (Octstr *id, Octstr *addr, long ton, long npi, Octstr *alt_addr_charset)
Msgpdu_to_msg (SMPP *smpp, SMPP_PDU *pdu, long *reason)
Msgdata_sm_to_msg (SMPP *smpp, SMPP_PDU *pdu, long *reason)
long smpp_status_to_smscconn_failure_reason (long status)
SMPP_PDUmsg_to_pdu (SMPP *smpp, Msg *msg)
void send_enquire_link (SMPP *smpp, Connection *conn, long *last_sent)
void send_unbind (SMPP *smpp, Connection *conn)
int send_pdu (Connection *conn, Octstr *id, SMPP_PDU *pdu)
void send_messages (SMPP *smpp, Connection *conn, long *pending_submits)
Connectionopen_transmitter (SMPP *smpp)
Connectionopen_transceiver (SMPP *smpp)
Connectionopen_receiver (SMPP *smpp)
Msghandle_dlr (SMPP *smpp, Octstr *destination_addr, Octstr *short_message, Octstr *message_payload, Octstr *receipted_message_id, long message_state)
long smscconn_failure_reason_to_smpp_status (long reason)
void handle_pdu (SMPP *smpp, Connection *conn, SMPP_PDU *pdu, long *pending_submits)
io_argio_arg_create (SMPP *smpp, int transmitter)
int do_queue_cleanup (SMPP *smpp, long *pending_submits, int action)
void io_thread (void *arg)
long queued_cb (SMSCConn *conn)
int send_msg_cb (SMSCConn *conn, Msg *msg)
int shutdown_cb (SMSCConn *conn, int finish_sending)
int smsc_smpp_create (SMSCConn *conn, CfgGroup *grp)


Define Documentation

#define DEBUG   1
 

Definition at line 90 of file smsc_smpp.c.

#define dump_pdu msg,
id,
pdu   ) 
 

Value:

do {                                        \
        debug("bb.sms.smpp", 0, "SMPP[%s]: %s", \
            octstr_get_cstr(id), msg);          \
        smpp_pdu_dump(pdu);                     \
    } while(0)
This version does dump.

Definition at line 96 of file smsc_smpp.c.

Referenced by io_thread(), send_enquire_link(), send_logoff(), send_pdu(), send_unbind(), and smasi_thread().

#define SMPP_DEFAULT_CHARSET   "UTF-8"
 

Definition at line 82 of file smsc_smpp.c.

Referenced by convert_addr_from_pdu(), data_sm_to_msg(), msg_to_pdu(), and pdu_to_msg().

#define SMPP_DEFAULT_CONNECTION_TIMEOUT   10 * SMPP_ENQUIRE_LINK_INTERVAL
 

Definition at line 114 of file smsc_smpp.c.

#define SMPP_DEFAULT_PRIORITY   0
 

Definition at line 112 of file smsc_smpp.c.

#define SMPP_DEFAULT_SHUTDOWN_TIMEOUT   30
 

Definition at line 116 of file smsc_smpp.c.

Referenced by io_thread().

#define SMPP_DEFAULT_VERSION   0x34
 

Definition at line 111 of file smsc_smpp.c.

#define SMPP_DEFAULT_WAITACK   60
 

Definition at line 115 of file smsc_smpp.c.

#define SMPP_ENQUIRE_LINK_INTERVAL   30.0
 

Definition at line 109 of file smsc_smpp.c.

#define SMPP_MAX_PENDING_SUBMITS   10
 

Definition at line 110 of file smsc_smpp.c.

#define SMPP_THROTTLING_SLEEP_TIME   15
 

Definition at line 113 of file smsc_smpp.c.

#define SMPP_WAITACK_NEVER_EXPIRE   0x02
 

Definition at line 124 of file smsc_smpp.c.

#define SMPP_WAITACK_RECONNECT   0x00
 

Definition at line 122 of file smsc_smpp.c.

Referenced by do_queue_cleanup().

#define SMPP_WAITACK_REQUEUE   0x01
 

Definition at line 123 of file smsc_smpp.c.

Referenced by do_queue_cleanup().


Function Documentation

long convert_addr_from_pdu Octstr id,
Octstr addr,
long  ton,
long  npi,
Octstr alt_addr_charset
[static]
 

Definition at line 338 of file smsc_smpp.c.

References charset_convert(), charset_gsm_to_utf8(), error(), GSM_ADDR_TON_ALPHANUMERIC, GSM_ADDR_TON_INTERNATIONAL, gw_isdigit(), octstr_check_range(), octstr_delete(), octstr_get_char(), octstr_get_cstr, octstr_imm(), octstr_insert_char(), octstr_len(), octstr_search(), octstr_str_case_compare(), reason, SMPP_DEFAULT_CHARSET, and warning().

Referenced by data_sm_to_msg(), and pdu_to_msg().

00339 {
00340     long reason = SMPP_ESME_ROK;
00341     
00342     if (addr == NULL)
00343         return reason;
00344 
00345     switch(ton) {
00346     case GSM_ADDR_TON_INTERNATIONAL:
00347         /*
00348          * Checks to perform:
00349          *   1) assume international number has at least 7 chars
00350          *   2) the whole source addr consist of digits, exception '+' in front
00351          */
00352         if (octstr_len(addr) < 7) {
00353             /* We consider this as a "non-hard" condition, since there "may"
00354              * be international numbers routable that are < 7 digits. Think
00355              * of 2 digit country code + 3 digit emergency code. */
00356             warning(0, "SMPP[%s]: Mallformed addr `%s', generally expected at least 7 digits. ",
00357                      octstr_get_cstr(id),
00358                      octstr_get_cstr(addr));
00359         } else if (octstr_get_char(addr, 0) == '+' &&
00360                    !octstr_check_range(addr, 1, 256, gw_isdigit)) {
00361             error(0, "SMPP[%s]: Mallformed addr `%s', expected all digits. ",
00362                      octstr_get_cstr(id),
00363                      octstr_get_cstr(addr));
00364             reason = SMPP_ESME_RINVSRCADR;
00365             goto error;
00366         } else if (octstr_get_char(addr, 0) != '+' &&
00367                    !octstr_check_range(addr, 0, 256, gw_isdigit)) {
00368             error(0, "SMPP[%s]: Mallformed addr `%s', expected all digits. ",
00369                      octstr_get_cstr(id),
00370                      octstr_get_cstr(addr));
00371             reason = SMPP_ESME_RINVSRCADR;
00372             goto error;
00373         }
00374         /* check if we received leading '00', then remove it*/
00375         if (octstr_search(addr, octstr_imm("00"), 0) == 0)
00376             octstr_delete(addr, 0, 2);
00377 
00378         /* international, insert '+' if not already here */
00379         if (octstr_get_char(addr, 0) != '+')
00380             octstr_insert_char(addr, 0, '+');
00381 
00382         break;
00383     case GSM_ADDR_TON_ALPHANUMERIC:
00384         if (octstr_len(addr) > 11) {
00385             /* alphanum sender, max. allowed length is 11 (according to GSM specs) */
00386             error(0, "SMPP[%s]: Mallformed addr `%s', alphanum length greater 11 chars. ",
00387                      octstr_get_cstr(id),
00388                      octstr_get_cstr(addr));
00389             reason = SMPP_ESME_RINVSRCADR;
00390             goto error;
00391         }
00392         if (alt_addr_charset) {
00393             if (octstr_str_case_compare(alt_addr_charset, "gsm") == 0)
00394         charset_gsm_to_utf8(addr);
00395             else if (charset_convert(addr, octstr_get_cstr(alt_addr_charset), SMPP_DEFAULT_CHARSET) != 0)
00396                 error(0, "Failed to convert address from charset <%s> to <%s>, leave as is.",
00397                     octstr_get_cstr(alt_addr_charset), SMPP_DEFAULT_CHARSET);
00398         }
00399         break;
00400     default: /* otherwise don't touch addr, user should handle it */
00401         break;
00402     }
00403     
00404 error:
00405     return reason;
00406 }

Here is the call graph for this function:

Msg* data_sm_to_msg SMPP smpp,
SMPP_PDU pdu,
long *  reason
[static]
 

Definition at line 576 of file smsc_smpp.c.

References SMPP::alt_addr_charset, SMPP::alt_charset, charset_convert(), charset_gsm_to_utf8(), SMPP::conn, convert_addr_from_pdu(), data_sm, DC_7BIT, DC_UNDEF, dcs_to_fields(), debug(), error(), gw_assert, smscconn::id, msg_create, msg_destroy(), octstr_copy, octstr_delete(), octstr_get_char(), octstr_get_cstr, octstr_len(), pdu, reason, SMPP_DEFAULT_CHARSET, sms, SMPP_PDU::type, and SMPP_PDU::u.

Referenced by handle_pdu().

00577 {
00578     Msg *msg;
00579     int ton, npi;
00580 
00581     gw_assert(pdu->type == data_sm);
00582 
00583     msg = msg_create(sms);
00584     gw_assert(msg != NULL);
00585     *reason = SMPP_ESME_ROK;
00586 
00587     /* 
00588      * Reset source addr to have a prefixed '+' in case we have an 
00589      * intl. TON to allow backend boxes (ie. smsbox) to distinguish
00590      * between national and international numbers.
00591      */
00592     ton = pdu->u.data_sm.source_addr_ton;
00593     npi = pdu->u.data_sm.source_addr_npi;
00594     /* check source addr */
00595     if ((*reason = convert_addr_from_pdu(smpp->conn->id, pdu->u.data_sm.source_addr, ton, npi, smpp->alt_addr_charset)) != SMPP_ESME_ROK)
00596         goto error;
00597     msg->sms.sender = pdu->u.data_sm.source_addr;
00598     pdu->u.data_sm.source_addr = NULL;
00599 
00600     /* 
00601      * Follows SMPP spec. v3.4. issue 1.2 
00602      * it's not allowed to have destination_addr NULL 
00603      */
00604     if (pdu->u.data_sm.destination_addr == NULL) {
00605         error(0, "SMPP[%s]: Mallformed destination_addr `%s', may not be empty. "
00606                  "Discarding MO message.", octstr_get_cstr(smpp->conn->id),
00607                      octstr_get_cstr(pdu->u.data_sm.destination_addr));
00608         *reason = SMPP_ESME_RINVDSTADR;
00609         goto error;
00610     }
00611 
00612     /* Same reset of destination number as for source */
00613     ton = pdu->u.data_sm.dest_addr_ton;
00614     npi = pdu->u.data_sm.dest_addr_npi;
00615     /* check destination addr */
00616     if ((*reason = convert_addr_from_pdu(smpp->conn->id, pdu->u.data_sm.destination_addr, ton, npi, smpp->alt_addr_charset)) != SMPP_ESME_ROK)
00617         goto error;
00618     msg->sms.receiver = pdu->u.data_sm.destination_addr;
00619     pdu->u.data_sm.destination_addr = NULL;
00620 
00621     /* SMSCs use service_type for billing information */
00622     msg->sms.binfo = pdu->u.data_sm.service_type;
00623     pdu->u.data_sm.service_type = NULL;
00624 
00625     if (pdu->u.data_sm.esm_class & ESM_CLASS_SUBMIT_RPI)
00626         msg->sms.rpi = 1;
00627 
00628     msg->sms.msgdata = pdu->u.data_sm.message_payload;
00629     pdu->u.data_sm.message_payload = NULL;
00630 
00631     /*
00632      * Encode udh if udhi set
00633      * for reference see GSM03.40, section 9.2.3.24
00634      */
00635     if (pdu->u.data_sm.esm_class & ESM_CLASS_SUBMIT_UDH_INDICATOR) {
00636         int udhl;
00637         udhl = octstr_get_char(msg->sms.msgdata, 0) + 1;
00638         debug("bb.sms.smpp",0,"SMPP[%s]: UDH length read as %d", 
00639               octstr_get_cstr(smpp->conn->id), udhl);
00640         if (udhl > octstr_len(msg->sms.msgdata)) {
00641             error(0, "SMPP[%s]: Mallformed UDH length indicator 0x%03x while message length "
00642                      "0x%03lx. Discarding MO message.", octstr_get_cstr(smpp->conn->id),
00643                      udhl, octstr_len(msg->sms.msgdata));
00644             *reason = SMPP_ESME_RINVESMCLASS;
00645             goto error;
00646         }
00647         msg->sms.udhdata = octstr_copy(msg->sms.msgdata, 0, udhl);
00648         octstr_delete(msg->sms.msgdata, 0, udhl);
00649     }
00650 
00651     dcs_to_fields(&msg, pdu->u.data_sm.data_coding);
00652 
00653     /* handle default data coding */
00654     switch (pdu->u.data_sm.data_coding) {
00655         case 0x00: /* default SMSC alphabet */
00656             /*
00657              * try to convert from something interesting if specified so
00658              * unless it was specified binary, ie. UDH indicator was detected
00659              */
00660             if (smpp->alt_charset && msg->sms.coding != DC_8BIT) {
00661                 if (charset_convert(msg->sms.msgdata, octstr_get_cstr(smpp->alt_charset), SMPP_DEFAULT_CHARSET) != 0)
00662                     error(0, "Failed to convert msgdata from charset <%s> to <%s>, will leave as is.",
00663                              octstr_get_cstr(smpp->alt_charset), SMPP_DEFAULT_CHARSET);
00664                 msg->sms.coding = DC_7BIT;
00665             } else { /* assume GSM 03.38 7-bit alphabet */
00666                 charset_gsm_to_utf8(msg->sms.msgdata);
00667                 msg->sms.coding = DC_7BIT;
00668             }
00669             break;
00670         case 0x01: /* ASCII or IA5 - not sure if I need to do anything */
00671         case 0x03: /* ISO-8859-1 - do nothing */
00672             msg->sms.coding = DC_7BIT; break;
00673         case 0x02: /* 8 bit binary - do nothing */
00674         case 0x04: /* 8 bit binary - do nothing */
00675             msg->sms.coding = DC_8BIT; break;
00676         case 0x05: /* JIS - what do I do with that ? */
00677             break;
00678         case 0x06: /* Cyrllic - iso-8859-5, I'll convert to unicode */
00679             if (charset_convert(msg->sms.msgdata, "ISO-8859-5", "UTF-8") != 0)
00680                 error(0, "Failed to convert msgdata from cyrllic to UTF-8, will leave as is");
00681             msg->sms.coding = DC_7BIT; break;
00682         case 0x07: /* Hebrew iso-8859-8, I'll convert to unicode */
00683             if (charset_convert(msg->sms.msgdata, "ISO-8859-8", "UTF-8") != 0)
00684                 error(0, "Failed to convert msgdata from hebrew to UTF-8, will leave as is");
00685             msg->sms.coding = DC_7BIT; break;
00686         case 0x08: /* unicode UCS-2, yey */
00687             msg->sms.coding = DC_UCS2; break;
00688 
00689             /*
00690              * don't much care about the others,
00691              * you implement them if you feel like it
00692              */
00693 
00694         default:
00695             /*
00696              * some of smsc send with dcs from GSM 03.38 , but these are reserved in smpp spec.
00697              * So we just look decoded values from dcs_to_fields and if none there make our assumptions.
00698              * if we have an UDH indicator, we assume DC_8BIT.
00699              */
00700             if (msg->sms.coding == DC_UNDEF && pdu->u.data_sm.esm_class & ESM_CLASS_SUBMIT_UDH_INDICATOR)
00701                 msg->sms.coding = DC_8BIT;
00702             else if (msg->sms.coding == DC_7BIT || msg->sms.coding == DC_UNDEF) { /* assume GSM 7Bit , reencode */
00703                 msg->sms.coding = DC_7BIT;
00704                 charset_gsm_to_utf8(msg->sms.msgdata);
00705             }
00706     }
00707 
00708     return msg;
00709 
00710 error:
00711     msg_destroy(msg);
00712     return NULL;
00713 }

Here is the call graph for this function:

int do_queue_cleanup SMPP smpp,
long *  pending_submits,
int  action
[static]
 

Definition at line 1665 of file smsc_smpp.c.

References action, bb_smscconn_send_failed(), SMPP::conn, dict_get(), dict_keys(), dict_remove(), error(), gwlist_destroy(), gwlist_extract_first(), smscconn::id, smpp_msg::msg, octstr_destroy(), octstr_destroy_item(), octstr_get_cstr, SMPP::sent_msgs, smpp_msg::sent_time, smpp_msg_destroy(), SMPP_WAITACK_RECONNECT, SMPP_WAITACK_REQUEUE, SMSCCONN_FAILED_TEMPORARILY, SMPP::wait_ack, and warning().

Referenced by io_thread().

01666 {
01667     List *keys;
01668     Octstr *key;
01669     struct smpp_msg *smpp_msg;
01670     time_t now = time(NULL);
01671                 
01672     if (*pending_submits <= 0)
01673         return 0;
01674 
01675     /* check if action set to wait ack for ever */
01676     if (action == SMPP_WAITACK_NEVER_EXPIRE)
01677         return 0;
01678                             
01679     keys = dict_keys(smpp->sent_msgs);
01680     if (keys == NULL)
01681         return 0;
01682                                             
01683     while ((key = gwlist_extract_first(keys)) != NULL) {
01684         smpp_msg = dict_get(smpp->sent_msgs, key);
01685         if (smpp_msg != NULL && difftime(now, smpp_msg->sent_time) > smpp->wait_ack) {
01686             switch(action) {
01687                 case SMPP_WAITACK_RECONNECT: /* reconnect */
01688                     /* found at least one not acked msg */
01689                     warning(0, "SMPP[%s]: Not ACKED message found, reconnecting.",
01690                                    octstr_get_cstr(smpp->conn->id));
01691                     octstr_destroy(key);
01692                     gwlist_destroy(keys, octstr_destroy_item);
01693                     return 1; /* io_thread will reconnect */
01694                 case SMPP_WAITACK_REQUEUE: /* requeue */
01695                     smpp_msg = dict_remove(smpp->sent_msgs, key);
01696                     if (smpp_msg != NULL) {
01697                         warning(0, "SMPP[%s]: Not ACKED message found, will retransmit."
01698                                    " SENT<%ld>sec. ago, SEQ<%s>, DST<%s>",
01699                                    octstr_get_cstr(smpp->conn->id),
01700                                    (long)difftime(now, smpp_msg->sent_time) ,
01701                                    octstr_get_cstr(key),
01702                                    octstr_get_cstr(smpp_msg->msg->sms.receiver));
01703                         bb_smscconn_send_failed(smpp->conn, smpp_msg->msg, SMSCCONN_FAILED_TEMPORARILY,NULL);
01704                         smpp_msg_destroy(smpp_msg, 0);
01705                         (*pending_submits)--;
01706                     }
01707                     break;
01708                 default:
01709                     error(0, "SMPP[%s] Unknown clenup action defined %xd.",
01710                              octstr_get_cstr(smpp->conn->id), action);
01711                     octstr_destroy(key);
01712                     gwlist_destroy(keys, octstr_destroy_item);
01713                     return 0;
01714             }
01715         }
01716         octstr_destroy(key);
01717     }
01718     gwlist_destroy(keys, octstr_destroy_item);
01719 
01720     return 0;
01721 }

Here is the call graph for this function:

Msg* handle_dlr SMPP smpp,
Octstr destination_addr,
Octstr short_message,
Octstr message_payload,
Octstr receipted_message_id,
long  message_state
[static]
 

Definition at line 1145 of file smsc_smpp.c.

References SMPP::conn, debug(), dlr_find(), error(), gw_isdigit(), smscconn::id, octstr_check_range(), octstr_compare(), octstr_copy, octstr_create, octstr_destroy(), octstr_duplicate, octstr_format(), octstr_get_cstr, octstr_imm(), octstr_len(), octstr_search(), octstr_search_char(), octstr_strip_blanks(), SMPP::smpp_msg_id_type, SMPP::version, and warning().

Referenced by handle_pdu().

01146 {
01147     Msg *dlrmsg = NULL;
01148     Octstr *respstr = NULL, *msgid = NULL, *tmp;
01149     int dlrstat = -1;
01150     
01151     /* first check for SMPP v3.4 and above */
01152     if (smpp->version > 0x33 && receipted_message_id) {
01153         msgid = octstr_duplicate(receipted_message_id);
01154         switch(message_state) {
01155         case 1: /* ENROUTE */
01156         case 6: /* ACCEPTED */
01157             dlrstat = DLR_BUFFERED;
01158             break;
01159         case 2: /* DELIVERED */
01160             dlrstat = DLR_SUCCESS;
01161             break;
01162         case 3: /* EXPIRED */
01163         case 4: /* DELETED */
01164         case 5: /* UNDELIVERABLE */
01165         case 7: /* UNKNOWN */
01166         case 8: /* REJECTED */
01167             dlrstat = DLR_FAIL;
01168             break;
01169         default:
01170             warning(0, "SMPP[%s]: Got DLR with unknown 'message_state' (%ld).",
01171                 octstr_get_cstr(smpp->conn->id), message_state);
01172             dlrstat = DLR_FAIL;
01173             break;
01174         }
01175     }
01176 
01177     /* check for SMPP v.3.4. and message_payload */
01178     if (smpp->version > 0x33 && octstr_len(short_message) == 0)
01179         respstr = message_payload;
01180     else
01181         respstr = short_message;
01182         
01183     /* still no msgid ? */
01184     if (!msgid && respstr) {
01185         long curr = 0, vpos = 0;
01186         Octstr *stat = NULL;
01187         char id_cstr[65], stat_cstr[16], sub_d_cstr[13], done_d_cstr[13];
01188         int sub, dlrvrd, ret;
01189     
01190         /* get server message id */
01191         /* first try sscanf way if thus failed then old way */
01192         ret = sscanf(octstr_get_cstr(respstr),
01193                     "id:%64[^s] sub:%d dlvrd:%d submit date:%12[0-9] done date:%12[0-9] stat:%10[^t^e]",
01194                     id_cstr, &sub, &dlrvrd, sub_d_cstr, done_d_cstr, stat_cstr);
01195         if (ret == 6) {
01196             msgid = octstr_create(id_cstr);
01197             octstr_strip_blanks(msgid);
01198             stat = octstr_create(stat_cstr);
01199             octstr_strip_blanks(stat);
01200         }
01201         else {
01202             debug("bb.sms.smpp", 0, "SMPP[%s]: Couldnot parse DLR string sscanf way,"
01203                 "fallback to old way. Please report!", octstr_get_cstr(smpp->conn->id));
01204         
01205             if ((curr = octstr_search(respstr, octstr_imm("id:"), 0)) != -1) {
01206                 vpos = octstr_search_char(respstr, ' ', curr);
01207                 if ((vpos-curr >0) && (vpos != -1))
01208                     msgid = octstr_copy(respstr, curr+3, vpos-curr-3);
01209             } else {
01210                 msgid = NULL;
01211             }
01212 
01213             /* get err & status code */
01214             if ((curr = octstr_search(respstr, octstr_imm("stat:"), 0)) != -1) {
01215                 vpos = octstr_search_char(respstr, ' ', curr);
01216                 if ((vpos-curr >0) && (vpos != -1))
01217                     stat = octstr_copy(respstr, curr+5, vpos-curr-5);
01218             } else {
01219                 stat = NULL;
01220             }
01221         }
01222         
01223         /*
01224          * we get the following status:
01225          * DELIVRD, ACCEPTD, EXPIRED, DELETED, UNDELIV, UNKNOWN, REJECTD
01226          *
01227          * Note: some buggy SMSC's send us immediately delivery notifications although
01228          *          we doesn't requested these.
01229          */
01230         
01231         if (stat != NULL && octstr_compare(stat, octstr_imm("DELIVRD")) == 0)
01232             dlrstat = DLR_SUCCESS;
01233         else if (stat != NULL && (octstr_compare(stat, octstr_imm("ACCEPTD")) == 0 ||
01234                         octstr_compare(stat, octstr_imm("ACKED")) == 0 ||
01235                         octstr_compare(stat, octstr_imm("BUFFRED")) == 0 ||
01236                         octstr_compare(stat, octstr_imm("BUFFERD")) == 0 ||                        
01237                         octstr_compare(stat, octstr_imm("ENROUTE")) == 0))
01238             dlrstat = DLR_BUFFERED;
01239         else
01240             dlrstat = DLR_FAIL;
01241                 
01242         if (stat != NULL)
01243             octstr_destroy(stat);
01244     }
01245 
01246     if (msgid != NULL) {
01247 
01248         /*
01249          * Obey which SMPP msg_id type this SMSC is using, where we
01250          * have the following semantics for the variable smpp_msg_id:
01251          *
01252          * bit 1: type for submit_sm_resp, bit 2: type for deliver_sm
01253          *
01254          * if bit is set value is hex otherwise dec
01255          *
01256          * 0x00 deliver_sm dec, submit_sm_resp dec
01257          * 0x01 deliver_sm dec, submit_sm_resp hex
01258          * 0x02 deliver_sm hex, submit_sm_resp dec
01259          * 0x03 deliver_sm hex, submit_sm_resp hex
01260          *
01261          * Default behaviour is SMPP spec compliant, which means
01262          * msg_ids should be C strings and hence non modified.
01263          */
01264         if (smpp->smpp_msg_id_type == -1) {
01265             /* the default, C string */
01266             tmp = octstr_duplicate(msgid);
01267         } else {
01268             if ((smpp->smpp_msg_id_type & 0x02) || 
01269                 (!octstr_check_range(msgid, 0, octstr_len(msgid), gw_isdigit))) {
01270                 tmp = octstr_format("%lu", strtoll(octstr_get_cstr(msgid), NULL, 16));
01271             } else {
01272                 tmp = octstr_format("%lu", strtoll(octstr_get_cstr(msgid), NULL, 10));
01273             }
01274         }
01275 
01276         dlrmsg = dlr_find(smpp->conn->id,
01277             tmp, /* smsc message id */
01278             destination_addr, /* destination */
01279             dlrstat);
01280 
01281         octstr_destroy(msgid);
01282     } else
01283         tmp = octstr_create("");
01284     
01285     if (dlrmsg != NULL) {
01286         /*
01287          * we found the delivery report in our storage, so recode the
01288          * message structure.
01289          * The DLR trigger URL is indicated by msg->sms.dlr_url.
01290          */
01291         dlrmsg->sms.msgdata = octstr_duplicate(respstr);
01292         dlrmsg->sms.sms_type = report_mo;
01293     } else {
01294         error(0,"SMPP[%s]: got DLR but could not find message or was not interested "
01295                 "in it id<%s> dst<%s>, type<%d>",
01296                 octstr_get_cstr(smpp->conn->id), octstr_get_cstr(tmp),
01297                 octstr_get_cstr(destination_addr), dlrstat);
01298     }
01299     octstr_destroy(tmp);
01300                 
01301     return dlrmsg;
01302 }

Here is the call graph for this function:

void handle_pdu SMPP smpp,
Connection conn,
SMPP_PDU pdu,
long *  pending_submits
[static]
 

Definition at line 1320 of file smsc_smpp.c.

References bb_alog_sms(), bb_smscconn_connected(), bb_smscconn_receive(), bb_smscconn_send_failed(), bb_smscconn_sent(), bind_receiver_resp, bind_transceiver_resp, bind_transmitter_resp, SMPP::conn, smscconn::connect_time, data_sm, data_sm_resp, data_sm_to_msg(), debug(), deliver_sm, deliver_sm_resp, dict_remove(), dlr_add(), DLR_IS_ENABLED_DEVICE, enquire_link, enquire_link_resp, error(), smscconn::flow_mutex, generic_nack, gw_isdigit(), handle_dlr(), smscconn::id, smscconn::is_stopped, smpp_msg::msg, msg_destroy(), mutex_lock, mutex_unlock, SMPP::my_number, octstr_check_range(), octstr_destroy(), octstr_duplicate, octstr_format(), octstr_get_cstr, octstr_len(), pdu, pdu_to_msg(), SMPP::quitting, reason, send_pdu(), SMPP::sent_msgs, smpp_error_to_string(), SMPP_ESME_RINVSYSID, smpp_msg_destroy(), SMPP::smpp_msg_id_type, smpp_pdu_create(), smpp_pdu_destroy(), smpp_status_to_smscconn_failure_reason(), smscconn_failure_reason_to_smpp_status(), smscconn::status, submit_sm_resp, SMPP::throttling_err_time, SMPP_PDU::type, SMPP_PDU::u, unbind, unbind_resp, and warning().

01322 {
01323     SMPP_PDU *resp;
01324     Octstr *os;
01325     Msg *msg, *dlrmsg = NULL;
01326     long reason;
01327     long cmd_stat;
01328     struct smpp_msg *smpp_msg = NULL;
01329 
01330     resp = NULL;
01331 
01332     switch (pdu->type) {
01333         case data_sm:
01334            resp = smpp_pdu_create(data_sm_resp, pdu->u.data_sm.sequence_number);
01335            /*
01336             * If SMSCConn stopped then send temp. error code
01337             */
01338            mutex_lock(smpp->conn->flow_mutex);
01339            if (smpp->conn->is_stopped) {
01340                  mutex_unlock(smpp->conn->flow_mutex);
01341                  resp->u.data_sm.command_status = SMPP_ESME_RX_T_APPN;
01342                  break;
01343            }
01344            mutex_unlock(smpp->conn->flow_mutex);
01345            /* got a deliver ack (DLR)?
01346              * NOTE: following SMPP v3.4. spec. we are interested
01347              *       only on bits 2-5 (some SMSC's send 0x44, and it's
01348              *       spec. conforme)
01349              */
01350            if (pdu->u.data_sm.esm_class & (0x04|0x08)) {
01351                 debug("bb.sms.smpp",0,"SMPP[%s] handle_pdu, got DLR",
01352                       octstr_get_cstr(smpp->conn->id));
01353                 dlrmsg = handle_dlr(smpp, pdu->u.data_sm.source_addr, NULL, pdu->u.data_sm.message_payload,
01354                                     pdu->u.data_sm.receipted_message_id, pdu->u.data_sm.message_state);
01355                 if (dlrmsg != NULL) {
01356                     /* passing DLR to upper layer */
01357                     reason = bb_smscconn_receive(smpp->conn, dlrmsg);
01358                 } else {
01359                     /* no DLR will be passed, but we write an access-log entry */
01360                     reason = SMSCCONN_SUCCESS;
01361                     msg = data_sm_to_msg(smpp, pdu, &reason);
01362                     bb_alog_sms(smpp->conn, msg, "FAILED DLR SMS");
01363                     msg_destroy(msg);
01364                 }
01365                 resp->u.data_sm_resp.command_status = smscconn_failure_reason_to_smpp_status(reason);
01366            } else { /* MO message */
01367                 msg = data_sm_to_msg(smpp, pdu, &reason);
01368                 if (msg == NULL || reason != SMPP_ESME_ROK) {
01369                     resp->u.data_sm_resp.command_status = reason;
01370                     break;
01371                 }
01372                 /* Replace MO destination number with my-number */
01373                 if (octstr_len(smpp->my_number)) {
01374                     octstr_destroy(msg->sms.receiver);
01375                     msg->sms.receiver = octstr_duplicate(smpp->my_number);
01376                 }
01377                 time(&msg->sms.time);
01378                 msg->sms.smsc_id = octstr_duplicate(smpp->conn->id);
01379                 reason =  bb_smscconn_receive(smpp->conn, msg);
01380                 resp->u.data_sm_resp.command_status = smscconn_failure_reason_to_smpp_status(reason);
01381            }
01382            break;
01383 
01384         case deliver_sm:
01385            /*
01386             * If SMSCConn stopped then send temp. error code
01387             */
01388            mutex_lock(smpp->conn->flow_mutex);
01389            if (smpp->conn->is_stopped) {
01390                  mutex_unlock(smpp->conn->flow_mutex);
01391                  resp = smpp_pdu_create(deliver_sm_resp,
01392                                pdu->u.deliver_sm.sequence_number);
01393                  resp->u.deliver_sm.command_status = SMPP_ESME_RX_T_APPN;
01394                  break;
01395            }
01396            mutex_unlock(smpp->conn->flow_mutex);
01397 
01398             /* got a deliver ack (DLR)?
01399              * NOTE: following SMPP v3.4. spec. we are interested
01400              *       only on bits 2-5 (some SMSC's send 0x44, and it's
01401              *       spec. conforme)
01402              */
01403             if (pdu->u.deliver_sm.esm_class & (0x04|0x08)) {
01404 
01405                 debug("bb.sms.smpp",0,"SMPP[%s] handle_pdu, got DLR",
01406                       octstr_get_cstr(smpp->conn->id));
01407 
01408                 dlrmsg = handle_dlr(smpp, pdu->u.deliver_sm.source_addr, pdu->u.deliver_sm.short_message, pdu->u.deliver_sm.message_payload,
01409                                     pdu->u.deliver_sm.receipted_message_id, pdu->u.deliver_sm.message_state);
01410                 resp = smpp_pdu_create(deliver_sm_resp,
01411                             pdu->u.deliver_sm.sequence_number);
01412                 if (dlrmsg != NULL)
01413                     reason = bb_smscconn_receive(smpp->conn, dlrmsg);
01414                 else
01415                     reason = SMSCCONN_SUCCESS;
01416                 resp->u.deliver_sm_resp.command_status = smscconn_failure_reason_to_smpp_status(reason);
01417             } else {/* MO-SMS */
01418                 resp = smpp_pdu_create(deliver_sm_resp,
01419                             pdu->u.deliver_sm.sequence_number);
01420                 /* ensure the smsc-id is set */
01421                 msg = pdu_to_msg(smpp, pdu, &reason);
01422                 if (msg == NULL) {
01423                     resp->u.deliver_sm_resp.command_status = reason;
01424                     break;
01425                 }
01426 
01427                 /* Replace MO destination number with my-number */
01428                 if (octstr_len(smpp->my_number)) {
01429                     octstr_destroy(msg->sms.receiver);
01430                     msg->sms.receiver = octstr_duplicate(smpp->my_number);
01431                 }
01432 
01433                 time(&msg->sms.time);
01434                 msg->sms.smsc_id = octstr_duplicate(smpp->conn->id);
01435                 reason =  bb_smscconn_receive(smpp->conn, msg);
01436                 resp->u.deliver_sm_resp.command_status = smscconn_failure_reason_to_smpp_status(reason);
01437             }
01438             break;
01439 
01440         case enquire_link:
01441             resp = smpp_pdu_create(enquire_link_resp,
01442                         pdu->u.enquire_link.sequence_number);
01443             break;
01444 
01445         case enquire_link_resp:
01446             break;
01447 
01448         case submit_sm_resp:
01449             os = octstr_format("%ld", pdu->u.submit_sm_resp.sequence_number);
01450             smpp_msg = dict_remove(smpp->sent_msgs, os);
01451             octstr_destroy(os);
01452             if (smpp_msg == NULL) {
01453                 warning(0, "SMPP[%s]: SMSC sent submit_sm_resp "
01454                         "with wrong sequence number 0x%08lx",
01455                         octstr_get_cstr(smpp->conn->id),
01456                         pdu->u.submit_sm_resp.sequence_number);
01457                 break;
01458             }
01459             msg = smpp_msg->msg;
01460             smpp_msg_destroy(smpp_msg, 0);
01461             if (pdu->u.submit_sm_resp.command_status != 0) {
01462                 error(0, "SMPP[%s]: SMSC returned error code 0x%08lx (%s) "
01463                       "in response to submit_sm.",
01464                       octstr_get_cstr(smpp->conn->id),
01465                       pdu->u.submit_sm_resp.command_status,
01466                       smpp_error_to_string(pdu->u.submit_sm_resp.command_status));
01467                 reason = smpp_status_to_smscconn_failure_reason(
01468                             pdu->u.submit_sm_resp.command_status);
01469 
01470                 /*
01471                  * check to see if we got a "throttling error", in which case we'll just
01472                  * sleep for a while
01473                  */
01474                 if (pdu->u.submit_sm_resp.command_status == SMPP_ESME_RTHROTTLED)
01475                     time(&(smpp->throttling_err_time));
01476                 else
01477                     smpp->throttling_err_time = 0;
01478 
01479                 bb_smscconn_send_failed(smpp->conn, msg, reason, 
01480                         octstr_format("%ld/%s", pdu->u.submit_sm_resp.command_status,
01481                             smpp_error_to_string(pdu->u.submit_sm_resp.command_status)));
01482                 --(*pending_submits);
01483             } else {
01484                 Octstr *tmp;
01485 
01486                 /* check if msg_id is C string, decimal or hex for this SMSC */
01487                 if (smpp->smpp_msg_id_type == -1) {
01488                     /* the default, C string */
01489                     tmp = octstr_duplicate(pdu->u.submit_sm_resp.message_id);
01490                 } else {
01491                     if ((smpp->smpp_msg_id_type & 0x01) || 
01492                        (!octstr_check_range(pdu->u.submit_sm_resp.message_id, 0, 
01493                             octstr_len(pdu->u.submit_sm_resp.message_id), gw_isdigit))) {
01494                         tmp = octstr_format("%lu", strtoll(  /* hex */
01495                             octstr_get_cstr(pdu->u.submit_sm_resp.message_id), NULL, 16));
01496                     } else {
01497                         tmp = octstr_format("%lu", strtoll(  /* decimal */
01498                             octstr_get_cstr(pdu->u.submit_sm_resp.message_id), NULL, 10));
01499                     }
01500                 }
01501 
01502                 /* SMSC ACK.. now we have the message id. */
01503                 if (DLR_IS_ENABLED_DEVICE(msg->sms.dlr_mask))
01504                     dlr_add(smpp->conn->id, tmp, msg);
01505 
01506                 octstr_destroy(tmp);
01507                 bb_smscconn_sent(smpp->conn, msg, NULL);
01508                 --(*pending_submits);
01509             } /* end if for SMSC ACK */
01510             break;
01511 
01512         case bind_transmitter_resp:
01513             if (pdu->u.bind_transmitter_resp.command_status != 0) {
01514                 error(0, "SMPP[%s]: SMSC rejected login to transmit, "
01515                       "code 0x%08lx (%s).",
01516                       octstr_get_cstr(smpp->conn->id),
01517                       pdu->u.bind_transmitter_resp.command_status,
01518               smpp_error_to_string(pdu->u.bind_transmitter_resp.command_status));
01519                 if (pdu->u.bind_transmitter_resp.command_status == SMPP_ESME_RINVSYSID ||
01520                     pdu->u.bind_transmitter_resp.command_status == SMPP_ESME_RINVPASWD)
01521                     smpp->quitting = 1;
01522             } else {
01523                 *pending_submits = 0;
01524                 mutex_lock(smpp->conn->flow_mutex);
01525                 smpp->conn->status = SMSCCONN_ACTIVE;
01526                 smpp->conn->connect_time = time(NULL);
01527                 mutex_unlock(smpp->conn->flow_mutex);
01528                 bb_smscconn_connected(smpp->conn);
01529             }
01530             break;
01531 
01532         case bind_transceiver_resp:
01533             if (pdu->u.bind_transceiver_resp.command_status != 0) {
01534                 error(0, "SMPP[%s]: SMSC rejected login to transmit, "
01535                       "code 0x%08lx (%s).",
01536                       octstr_get_cstr(smpp->conn->id),
01537                       pdu->u.bind_transceiver_resp.command_status,
01538               smpp_error_to_string(pdu->u.bind_transceiver_resp.command_status));
01539                 if (pdu->u.bind_transceiver_resp.command_status == SMPP_ESME_RINVSYSID ||
01540                     pdu->u.bind_transceiver_resp.command_status == SMPP_ESME_RINVPASWD)
01541                     smpp->quitting = 1;
01542             } else {
01543                 *pending_submits = 0;
01544                 mutex_lock(smpp->conn->flow_mutex);
01545                 smpp->conn->status = SMSCCONN_ACTIVE;
01546                 smpp->conn->connect_time = time(NULL);
01547                 mutex_unlock(smpp->conn->flow_mutex);
01548                 bb_smscconn_connected(smpp->conn);
01549             }
01550             break;
01551 
01552         case bind_receiver_resp:
01553             if (pdu->u.bind_receiver_resp.command_status != 0) {
01554                 error(0, "SMPP[%s]: SMSC rejected login to receive, "
01555                       "code 0x%08lx (%s).",
01556                       octstr_get_cstr(smpp->conn->id),
01557                       pdu->u.bind_receiver_resp.command_status,
01558               smpp_error_to_string(pdu->u.bind_receiver_resp.command_status));
01559                 if (pdu->u.bind_receiver_resp.command_status == SMPP_ESME_RINVSYSID ||
01560                     pdu->u.bind_receiver_resp.command_status == SMPP_ESME_RINVPASWD)
01561                     smpp->quitting = 1;
01562             } else {
01563                 /* set only resceive status if no transmitt is bind */
01564                 mutex_lock(smpp->conn->flow_mutex);
01565                 if (smpp->conn->status != SMSCCONN_ACTIVE) {
01566                     smpp->conn->status = SMSCCONN_ACTIVE_RECV;
01567                     smpp->conn->connect_time = time(NULL);
01568                 }
01569                 mutex_unlock(smpp->conn->flow_mutex);
01570             }
01571             break;
01572 
01573         case unbind:
01574             resp = smpp_pdu_create(unbind_resp, pdu->u.unbind.sequence_number);
01575             mutex_lock(smpp->conn->flow_mutex);
01576             smpp->conn->status = SMSCCONN_DISCONNECTED;
01577             mutex_unlock(smpp->conn->flow_mutex);
01578             break;
01579 
01580         case unbind_resp:
01581             mutex_lock(smpp->conn->flow_mutex);
01582             smpp->conn->status = SMSCCONN_DISCONNECTED;
01583             mutex_unlock(smpp->conn->flow_mutex);
01584             break;
01585 
01586         case generic_nack:
01587             cmd_stat  = pdu->u.generic_nack.command_status;
01588 
01589             os = octstr_format("%ld", pdu->u.generic_nack.sequence_number);
01590             smpp_msg = dict_remove(smpp->sent_msgs, os);
01591             octstr_destroy(os);
01592 
01593             if (smpp_msg == NULL) {
01594                 error(0, "SMPP[%s]: SMSC rejected last command"
01595               "code 0x%08lx (%s).",
01596                       octstr_get_cstr(smpp->conn->id),
01597                       cmd_stat,
01598               smpp_error_to_string(cmd_stat));
01599             } else {
01600                 msg = smpp_msg->msg;
01601                 smpp_msg_destroy(smpp_msg, 0);
01602                 
01603                 error(0, "SMPP[%s]: SMSC returned error code 0x%08lx (%s) "
01604                       "in response to submit_sm.",
01605                       octstr_get_cstr(smpp->conn->id),
01606                       cmd_stat,
01607               smpp_error_to_string(cmd_stat));
01608 
01609                 /*
01610                  * check to see if we got a "throttling error", in which case we'll just
01611                  * sleep for a while
01612                  */
01613                 if (cmd_stat == SMPP_ESME_RTHROTTLED)
01614                     time(&(smpp->throttling_err_time));
01615                 else
01616                     smpp->throttling_err_time = 0;
01617 
01618                 reason = smpp_status_to_smscconn_failure_reason(cmd_stat);
01619                 bb_smscconn_send_failed(smpp->conn, msg, reason,
01620                 octstr_format("%ld/%s", cmd_stat, smpp_error_to_string(cmd_stat)));
01621                 --(*pending_submits);
01622             }
01623             break;
01624         default:
01625             error(0, "SMPP[%s]: Unknown PDU type 0x%08lx, ignored.",
01626                   octstr_get_cstr(smpp->conn->id), pdu->type);
01627             /*
01628                 send gnack , see smpp3.4 spec., section 3.3
01629                 because we doesn't know what kind of pdu received, we assume generick_nack_resp
01630                 (header always the same)
01631             */
01632             resp = smpp_pdu_create(generic_nack, pdu->u.generic_nack.sequence_number);
01633             resp->u.generic_nack.command_status = SMPP_ESME_RINVCMDID;
01634             break;
01635     }
01636 
01637     if (resp != NULL) {
01638         send_pdu(conn, smpp->conn->id, resp);
01639         smpp_pdu_destroy(resp);
01640     }
01641 }

Here is the call graph for this function:

struct io_arg* io_arg_create SMPP smpp,
int  transmitter
[static]
 

Definition at line 1650 of file smsc_smpp.c.

References io_arg::smpp, and SMPP::transmitter.

Referenced by smsc_smpp_create().

01651 {
01652     struct io_arg *io_arg;
01653 
01654     io_arg = gw_malloc(sizeof(*io_arg));
01655     io_arg->smpp = smpp;
01656     io_arg->transmitter = transmitter;
01657     return io_arg;
01658 }

void io_thread void *  arg  )  [static]
 

Definition at line 1730 of file smsc_smpp.c.

References bb_smscconn_send_failed(), SMPP::conn, conn_destroy(), conn_wait(), SMPP::connection_timeout, date_universal_now(), debug(), dict_keys(), dict_remove(), do_queue_cleanup(), dump_pdu, SMPP::enquire_link_interval, error(), smscconn::flow_mutex, gwlist_destroy(), gwlist_extract_first(), gwthread_sleep(), handle_pdu(), smscconn::id, smscconn::log_idx, log_thread_to(), smpp_msg::msg, SMPP::msgs_to_send, mutex_lock, mutex_unlock, octstr_destroy(), octstr_get_cstr, open_receiver(), open_transceiver(), open_transmitter(), pdu, SMPP::quitting, read_pdu(), reason, smscconn::reconnect_delay, send_enquire_link(), send_messages(), send_unbind(), SMPP::sent_msgs, io_arg::smpp, SMPP_DEFAULT_SHUTDOWN_TIMEOUT, smpp_msg_destroy(), smpp_pdu_destroy(), SMSCCONN_ACTIVE, SMSCCONN_FAILED_SHUTDOWN, smscconn::status, SMPP::throttling_err_time, io_arg::transmitter, SMPP::wait_ack, and SMPP::wait_ack_action.

Referenced by smsc_smpp_create().

01731 {
01732     SMPP *smpp;
01733     struct io_arg *io_arg;
01734     int transmitter;
01735     Connection *conn;
01736     int ret;
01737     long last_enquire_sent;
01738     long pending_submits;
01739     long len;
01740     SMPP_PDU *pdu;
01741     double timeout;
01742     time_t last_response, last_cleanup;
01743 
01744     io_arg = arg;
01745     smpp = io_arg->smpp;
01746     transmitter = io_arg->transmitter;
01747     gw_free(io_arg);
01748 
01749     /* Make sure we log into our own log-file if defined */
01750     log_thread_to(smpp->conn->log_idx);
01751 
01752     conn = NULL;
01753     while (!smpp->quitting) {
01754         if (transmitter == 1)
01755             conn = open_transmitter(smpp);
01756         else if (transmitter == 2)
01757             conn = open_transceiver(smpp);
01758         else
01759             conn = open_receiver(smpp);
01760 
01761         last_enquire_sent = last_cleanup = last_response = date_universal_now();
01762         pending_submits = -1;
01763         len = 0;
01764         smpp->throttling_err_time = 0;
01765         for (;conn != NULL;) {
01766             timeout = last_enquire_sent + smpp->enquire_link_interval
01767                         - date_universal_now();
01768 
01769             if (conn_wait(conn, timeout) == -1)
01770                 break;
01771 
01772             /* unbind
01773              * Read so long as unbind_resp received or timeout passed. Otherwise we have
01774              * double delivered messages.
01775              */
01776             if (smpp->quitting) {
01777                 send_unbind(smpp, conn);
01778                 last_response = time(NULL);
01779                 while(conn_wait(conn, 1.00) != -1 &&
01780                       difftime(time(NULL), last_response) < SMPP_DEFAULT_SHUTDOWN_TIMEOUT &&
01781                       smpp->conn->status != SMSCCONN_DISCONNECTED) {
01782                     if (read_pdu(smpp, conn, &len, &pdu) == 1) {
01783                         dump_pdu("Got PDU:", smpp->conn->id, pdu);
01784                         handle_pdu(smpp, conn, pdu, &pending_submits);
01785                         smpp_pdu_destroy(pdu);
01786                     }
01787                 }
01788                 debug("bb.sms.smpp", 0, "SMPP[%s]: %s: break and shutting down",
01789                       octstr_get_cstr(smpp->conn->id), __func__);
01790 
01791                 break;
01792             }
01793 
01794             send_enquire_link(smpp, conn, &last_enquire_sent);
01795 
01796             while ((ret = read_pdu(smpp, conn, &len, &pdu)) == 1) {
01797                 last_response = time(NULL);
01798                 /* Deal with the PDU we just got */
01799                 dump_pdu("Got PDU:", smpp->conn->id, pdu);
01800                 handle_pdu(smpp, conn, pdu, &pending_submits);
01801                 smpp_pdu_destroy(pdu);
01802 
01803                 /*
01804                  * check if we are still connected.
01805                  * Note: smsc can send unbind request, so we must check it.
01806                  */
01807                 if (smpp->conn->status != SMSCCONN_ACTIVE && smpp->conn->status != SMSCCONN_ACTIVE_RECV) {
01808                      /* we are disconnected */
01809                      ret = -1;
01810                      break;
01811                 }
01812 
01813                 /* Make sure we send enquire_link even if we read a lot */
01814                 send_enquire_link(smpp, conn, &last_enquire_sent);
01815 
01816                 /* Make sure we send even if we read a lot */
01817                 if (transmitter && difftime(time(NULL), smpp->throttling_err_time) > SMPP_THROTTLING_SLEEP_TIME) {
01818                     smpp->throttling_err_time = 0;
01819                     send_messages(smpp, conn, &pending_submits);
01820                 }
01821             }
01822 
01823             if (ret == -1) {
01824                 error(0, "SMPP[%s]: I/O error or other error. Re-connecting.",
01825                       octstr_get_cstr(smpp->conn->id));
01826                 break;
01827             }
01828             
01829             /* if no PDU was received and connection timeout was set and over the limit */
01830             if (ret == 0 && smpp->connection_timeout > 0 &&
01831                 difftime(time(NULL), last_response) > smpp->connection_timeout) {
01832                 error(0, "SMPP[%s]: No responses from SMSC within %ld sec. Reconnecting.",
01833                          octstr_get_cstr(smpp->conn->id), smpp->connection_timeout);
01834                 break;
01835             }
01836 
01837 
01838             /* cleanup sent queue */
01839             if (transmitter && difftime(time(NULL), last_cleanup) > smpp->wait_ack) {
01840                 if (do_queue_cleanup(smpp, &pending_submits, smpp->wait_ack_action))
01841                     break; /* reconnect */
01842                 last_cleanup = time(NULL);
01843             }
01844                                                                     
01845             if (transmitter && difftime(time(NULL), smpp->throttling_err_time) > SMPP_THROTTLING_SLEEP_TIME) {
01846                 smpp->throttling_err_time = 0;
01847                 send_messages(smpp, conn, &pending_submits);
01848             }
01849         }
01850 
01851         if (conn != NULL) {
01852             conn_destroy(conn);
01853             conn = NULL;
01854         }
01855         /* set reconnect status */
01856         mutex_lock(smpp->conn->flow_mutex);
01857         smpp->conn->status = SMSCCONN_RECONNECTING;
01858         mutex_unlock(smpp->conn->flow_mutex);
01859         /*
01860          * Put all queued messages back into global queue,so if
01861          * we have another link running then messages will be delivered
01862          * quickly.
01863          */
01864         if (transmitter) {
01865             Msg *msg;
01866             struct smpp_msg *smpp_msg;
01867             List *noresp;
01868             Octstr *key;
01869 
01870             long reason = (smpp->quitting?SMSCCONN_FAILED_SHUTDOWN:SMSCCONN_FAILED_TEMPORARILY);
01871 
01872             while((msg = gwlist_extract_first(smpp->msgs_to_send)) != NULL)
01873                 bb_smscconn_send_failed(smpp->conn, msg, reason, NULL);
01874 
01875             noresp = dict_keys(smpp->sent_msgs);
01876             while((key = gwlist_extract_first(noresp)) != NULL) {
01877                 smpp_msg = dict_remove(smpp->sent_msgs, key);
01878                 if (smpp_msg != NULL && smpp_msg->msg) {
01879                     bb_smscconn_send_failed(smpp->conn, smpp_msg->msg, reason, NULL);
01880                     smpp_msg_destroy(smpp_msg, 0);
01881                 }
01882                 octstr_destroy(key);
01883             }
01884             gwlist_destroy(noresp, NULL);
01885         }
01886         /*
01887          * Reconnect if that was a connection problem.
01888          */
01889         if (!smpp->quitting) {
01890             error(0, "SMPP[%s]: Couldn't connect to SMS center (retrying in %ld seconds).",
01891                   octstr_get_cstr(smpp->conn->id), smpp->conn->reconnect_delay);
01892             gwthread_sleep(smpp->conn->reconnect_delay);
01893         }
01894     }
01895     mutex_lock(smpp->conn->flow_mutex);
01896     smpp->conn->status = SMSCCONN_DEAD;
01897     mutex_unlock(smpp->conn->flow_mutex);
01898 }

Here is the call graph for this function:

SMPP_PDU* msg_to_pdu SMPP smpp,
Msg msg
[static]
 

Definition at line 733 of file smsc_smpp.c.

References SMPP::alt_addr_charset, SMPP::alt_charset, smscconn::alt_dcs, SMPP::autodetect_addr, charset_convert(), charset_utf8_to_gsm(), SMPP::conn, counter_increase(), DC_7BIT, DC_UNDEF, debug(), SMPP::dest_addr_npi, SMPP::dest_addr_ton, DLR_IS_FAIL, DLR_IS_SUCCESS, DLR_IS_SUCCESS_OR_FAIL, error(), fields_to_dcs(), gw_gmtime(), gw_isdigit(), smscconn::id, SMPP::message_id_counter, MWI_UNDEF, octstr_check_range(), octstr_delete(), octstr_duplicate, octstr_format(), octstr_get_char(), octstr_get_cstr, octstr_imm(), octstr_insert(), octstr_len(), octstr_replace(), octstr_str_case_compare(), pdu, SMPP::priority, SMPP::service_type, SMPP_DEFAULT_CHARSET, smpp_pdu_create(), smpp_pdu_destroy(), SMS_PARAM_UNDEFINED, SMPP::source_addr_npi, SMPP::source_addr_ton, submit_sm, SMPP_PDU::u, SMPP::validityperiod, and SMPP::version.

Referenced by send_messages().

00734 {
00735     SMPP_PDU *pdu;
00736     int validity;
00737     
00738     pdu = smpp_pdu_create(submit_sm,
00739                           counter_increase(smpp->message_id_counter));
00740 
00741     pdu->u.submit_sm.source_addr = octstr_duplicate(msg->sms.sender);
00742     pdu->u.submit_sm.destination_addr = octstr_duplicate(msg->sms.receiver);
00743 
00744     /* Set the service type of the outgoing message. We'll use the config 
00745      * directive as default and 'binfo' as specific parameter. */
00746     pdu->u.submit_sm.service_type = octstr_len(msg->sms.binfo) ? 
00747         octstr_duplicate(msg->sms.binfo) : octstr_duplicate(smpp->service_type);
00748 
00749     /* Check for manual override of source ton and npi values */
00750     if(smpp->source_addr_ton > -1 && smpp->source_addr_npi > -1) {
00751         pdu->u.submit_sm.source_addr_ton = smpp->source_addr_ton;
00752         pdu->u.submit_sm.source_addr_npi = smpp->source_addr_npi;
00753         debug("bb.sms.smpp", 0, "SMPP[%s]: Manually forced source addr ton = %d, source add npi = %d",
00754               octstr_get_cstr(smpp->conn->id), smpp->source_addr_ton,
00755               smpp->source_addr_npi);
00756     } else {
00757         /* setup default values */
00758         pdu->u.submit_sm.source_addr_ton = GSM_ADDR_TON_NATIONAL; /* national */
00759         pdu->u.submit_sm.source_addr_npi = GSM_ADDR_NPI_E164; /* ISDN number plan */
00760     }
00761 
00762     if (smpp->autodetect_addr && pdu->u.submit_sm.source_addr) {
00763         /* lets see if its international or alphanumeric sender */
00764         if (octstr_get_char(pdu->u.submit_sm.source_addr, 0) == '+') {
00765             if (!octstr_check_range(pdu->u.submit_sm.source_addr, 1, 256, gw_isdigit)) {
00766                 pdu->u.submit_sm.source_addr_ton = GSM_ADDR_TON_ALPHANUMERIC; /* alphanum */
00767                 pdu->u.submit_sm.source_addr_npi = GSM_ADDR_NPI_UNKNOWN;    /* short code */
00768                 if (smpp->alt_addr_charset) {
00769                     if (octstr_str_case_compare(smpp->alt_addr_charset, "gsm") == 0) {
00770                         /* @ would break PDU if converted into GSM*/
00771                         octstr_replace(pdu->u.submit_sm.source_addr, octstr_imm("@"), octstr_imm("?"));
00772                         charset_utf8_to_gsm(pdu->u.submit_sm.source_addr);
00773                     } else if (charset_convert(pdu->u.submit_sm.source_addr, SMPP_DEFAULT_CHARSET, octstr_get_cstr(smpp->alt_addr_charset)) != 0)
00774                         error(0, "Failed to convert source_addr from charset <%s> to <%s>, will send as is.",
00775                                 SMPP_DEFAULT_CHARSET, octstr_get_cstr(smpp->alt_addr_charset));
00776                 }
00777             } else {
00778                /* numeric sender address with + in front -> international (remove the +) */
00779                octstr_delete(pdu->u.submit_sm.source_addr, 0, 1);
00780                pdu->u.submit_sm.source_addr_ton = GSM_ADDR_TON_INTERNATIONAL;
00781             }
00782         } else {
00783             if (!octstr_check_range(pdu->u.submit_sm.source_addr,0, 256, gw_isdigit)) {
00784                 pdu->u.submit_sm.source_addr_ton = GSM_ADDR_TON_ALPHANUMERIC;
00785                 pdu->u.submit_sm.source_addr_npi = GSM_ADDR_NPI_UNKNOWN;
00786                 if (smpp->alt_addr_charset) {
00787                     if (octstr_str_case_compare(smpp->alt_addr_charset, "gsm") == 0) {
00788                         /* @ would break PDU if converted into GSM */
00789                         octstr_replace(pdu->u.submit_sm.source_addr, octstr_imm("@"), octstr_imm("?")); 
00790                         charset_utf8_to_gsm(pdu->u.submit_sm.source_addr);
00791                     } else if (charset_convert(pdu->u.submit_sm.source_addr, SMPP_DEFAULT_CHARSET, octstr_get_cstr(smpp->alt_addr_charset)) != 0)
00792                         error(0, "Failed to convert source_addr from charset <%s> to <%s>, will send as is.",
00793                                 SMPP_DEFAULT_CHARSET, octstr_get_cstr(smpp->alt_addr_charset));
00794                 }
00795             }
00796         }
00797     }
00798 
00799     /* Check for manual override of destination ton and npi values */
00800     if (smpp->dest_addr_ton > -1 && smpp->dest_addr_npi > -1) {
00801         pdu->u.submit_sm.dest_addr_ton = smpp->dest_addr_ton;
00802         pdu->u.submit_sm.dest_addr_npi = smpp->dest_addr_npi;
00803         debug("bb.sms.smpp", 0, "SMPP[%s]: Manually forced dest addr ton = %d, dest add npi = %d",
00804               octstr_get_cstr(smpp->conn->id), smpp->dest_addr_ton,
00805               smpp->dest_addr_npi);
00806     } else {
00807         pdu->u.submit_sm.dest_addr_ton = GSM_ADDR_TON_NATIONAL; /* national */
00808         pdu->u.submit_sm.dest_addr_npi = GSM_ADDR_NPI_E164; /* ISDN number plan */
00809     }
00810 
00811     /*
00812      * if its a international number starting with +, lets remove the
00813      * '+' and set number type to international instead
00814      */
00815     if (octstr_get_char(pdu->u.submit_sm.destination_addr,0) == '+') {
00816         octstr_delete(pdu->u.submit_sm.destination_addr, 0,1);
00817         pdu->u.submit_sm.dest_addr_ton = GSM_ADDR_TON_INTERNATIONAL;
00818     }
00819 
00820     /* check length of src/dst address */
00821     if (octstr_len(pdu->u.submit_sm.destination_addr) > 20 ||
00822         octstr_len(pdu->u.submit_sm.source_addr) > 20) {
00823         smpp_pdu_destroy(pdu);
00824         return NULL;
00825     }
00826 
00827     /*
00828      * set the data coding scheme (DCS) field
00829      * check if we have a forced value for this from the smsc-group.
00830      * Note: if message class is set, then we _must_ force alt_dcs otherwise
00831      * dcs has reserved values (e.g. mclass=2, dcs=0x11). We check MWI flag
00832      * first here, because MWI and MCLASS can not be set at the same time and
00833      * function fields_to_dcs check MWI first, so we have no need to force alt_dcs
00834      * if MWI is set.
00835      */
00836     if (msg->sms.mwi == MWI_UNDEF && msg->sms.mclass != MC_UNDEF)
00837         pdu->u.submit_sm.data_coding = fields_to_dcs(msg, 1); /* force alt_dcs */
00838     else
00839         pdu->u.submit_sm.data_coding = fields_to_dcs(msg,
00840             (msg->sms.alt_dcs != SMS_PARAM_UNDEFINED ?
00841              msg->sms.alt_dcs : smpp->conn->alt_dcs));
00842 
00843     /* set protocol id */
00844     if(msg->sms.pid != SMS_PARAM_UNDEFINED)
00845         pdu->u.submit_sm.protocol_id = msg->sms.pid;
00846 
00847     /*
00848      * set the esm_class field
00849      * default is store and forward, plus udh and rpi if requested
00850      */
00851     pdu->u.submit_sm.esm_class = ESM_CLASS_SUBMIT_STORE_AND_FORWARD_MODE;
00852     if (octstr_len(msg->sms.udhdata))
00853         pdu->u.submit_sm.esm_class = pdu->u.submit_sm.esm_class |
00854             ESM_CLASS_SUBMIT_UDH_INDICATOR;
00855     if (msg->sms.rpi > 0)
00856         pdu->u.submit_sm.esm_class = pdu->u.submit_sm.esm_class |
00857             ESM_CLASS_SUBMIT_RPI;
00858 
00859     /*
00860      * set data segments and length
00861      */
00862 
00863     pdu->u.submit_sm.short_message = octstr_duplicate(msg->sms.msgdata);
00864 
00865     /*
00866      * only re-encoding if using default smsc charset that is defined via
00867      * alt-charset in smsc group and if MT is not binary
00868      */
00869     if (msg->sms.coding == DC_7BIT || (msg->sms.coding == DC_UNDEF && octstr_len(msg->sms.udhdata) == 0)) {
00870         /* 
00871          * consider 3 cases: 
00872          *  a) data_coding 0xFX: encoding should always be GSM 03.38 charset 
00873          *  b) data_coding 0x00: encoding may be converted according to alt-charset 
00874          *  c) data_coding 0x00: assume GSM 03.38 charset if alt-charset is not defined
00875          */
00876         if ((pdu->u.submit_sm.data_coding & 0xF0) ||
00877             (pdu->u.submit_sm.data_coding == 0 && !smpp->alt_charset)) {
00878             charset_utf8_to_gsm(pdu->u.submit_sm.short_message);
00879         } else if (pdu->u.submit_sm.data_coding == 0 && smpp->alt_charset) {
00880             /*
00881              * convert to the given alternative charset
00882              */
00883             if (charset_convert(pdu->u.submit_sm.short_message, SMPP_DEFAULT_CHARSET,
00884                                 octstr_get_cstr(smpp->alt_charset)) != 0)
00885                 error(0, "Failed to convert msgdata from charset <%s> to <%s>, will send as is.",
00886                              SMPP_DEFAULT_CHARSET, octstr_get_cstr(smpp->alt_charset));
00887         }
00888     }
00889 
00890     /* prepend udh if present */
00891     if (octstr_len(msg->sms.udhdata)) {
00892         octstr_insert(pdu->u.submit_sm.short_message, msg->sms.udhdata, 0);
00893     }
00894 
00895     pdu->u.submit_sm.sm_length = octstr_len(pdu->u.submit_sm.short_message);
00896 
00897     /*
00898      * check for validity and defered settings
00899      * were message value has higher priiority then smsc config group value
00900      */
00901     validity = msg->sms.validity >= 0 ? msg->sms.validity : smpp->validityperiod;
00902     if (validity >= 0) {
00903         struct tm tm = gw_gmtime(time(NULL) + validity * 60);
00904         pdu->u.submit_sm.validity_period = octstr_format("%02d%02d%02d%02d%02d%02d000+",
00905                 tm.tm_year % 100, tm.tm_mon + 1, tm.tm_mday,
00906                 tm.tm_hour, tm.tm_min, tm.tm_sec);
00907     }
00908 
00909     if (msg->sms.deferred >= 0) {
00910         struct tm tm = gw_gmtime(time(NULL) + msg->sms.deferred * 60);
00911         pdu->u.submit_sm.schedule_delivery_time = octstr_format("%02d%02d%02d%02d%02d%02d000+",
00912                 tm.tm_year % 100, tm.tm_mon + 1, tm.tm_mday,
00913                 tm.tm_hour, tm.tm_min, tm.tm_sec);
00914     }
00915 
00916     /* ask for the delivery reports if needed */
00917     if (DLR_IS_SUCCESS_OR_FAIL(msg->sms.dlr_mask))
00918         pdu->u.submit_sm.registered_delivery = 1;
00919     else if (DLR_IS_FAIL(msg->sms.dlr_mask) && !DLR_IS_SUCCESS(msg->sms.dlr_mask))
00920         pdu->u.submit_sm.registered_delivery = 2;
00921 
00922     /* set priority */
00923     if (msg->sms.priority >= 0 && msg->sms.priority <= 3)
00924         pdu->u.submit_sm.priority_flag = msg->sms.priority;
00925     else
00926         pdu->u.submit_sm.priority_flag = smpp->priority;
00927 
00928     /* set more messages to send */
00929     if (smpp->version > 0x33 && msg->sms.msg_left > 0)
00930         pdu->u.submit_sm.more_messages_to_send = 1;
00931 
00932     return pdu;
00933 }

Here is the call graph for this function:

Connection* open_receiver SMPP smpp  )  [static]
 

Definition at line 1112 of file smsc_smpp.c.

References SMPP::address_range, SMPP::bind_addr_npi, SMPP::bind_addr_ton, bind_receiver, SMPP::conn, conn_open_tcp(), counter_increase(), error(), SMPP::host, smscconn::id, SMPP::message_id_counter, octstr_create, octstr_duplicate, octstr_get_cstr, smscconn::our_host, SMPP::password, SMPP::receive_port, send_pdu(), smpp_pdu_create(), smpp_pdu_destroy(), SMPP::system_type, SMPP_PDU::u, SMPP::username, and SMPP::version.

Referenced by io_thread().

01113 {
01114     SMPP_PDU *bind;
01115     Connection *conn;
01116 
01117     conn = conn_open_tcp(smpp->host, smpp->receive_port, smpp->conn->our_host );
01118     if (conn == NULL) {
01119         error(0, "SMPP[%s]: Couldn't connect to server.",
01120               octstr_get_cstr(smpp->conn->id));
01121         return NULL;
01122     }
01123 
01124     bind = smpp_pdu_create(bind_receiver,
01125                 counter_increase(smpp->message_id_counter));
01126     bind->u.bind_receiver.system_id = octstr_duplicate(smpp->username);
01127     bind->u.bind_receiver.password = octstr_duplicate(smpp->password);
01128     if (smpp->system_type == NULL)
01129         bind->u.bind_receiver.system_type = octstr_create("VMA");
01130     else
01131         bind->u.bind_receiver.system_type =
01132             octstr_duplicate(smpp->system_type);
01133     bind->u.bind_receiver.interface_version = smpp->version;
01134     bind->u.bind_receiver.address_range =
01135         octstr_duplicate(smpp->address_range);
01136     bind->u.bind_receiver.addr_ton = smpp->bind_addr_ton;
01137     bind->u.bind_receiver.addr_npi = smpp->bind_addr_npi;
01138     send_pdu(conn, smpp->conn->id, bind);
01139     smpp_pdu_destroy(bind);
01140 
01141     return conn;
01142 }

Here is the call graph for this function:

Connection* open_transceiver SMPP smpp  )  [static]
 

Definition at line 1076 of file smsc_smpp.c.

References SMPP::address_range, SMPP::bind_addr_npi, SMPP::bind_addr_ton, bind_transceiver, SMPP::conn, conn_open_tcp(), counter_increase(), error(), SMPP::host, smscconn::id, SMPP::message_id_counter, octstr_create, octstr_duplicate, octstr_get_cstr, smscconn::our_host, SMPP::password, send_pdu(), smpp_pdu_create(), smpp_pdu_destroy(), SMPP::system_type, SMPP::transmit_port, SMPP_PDU::u, SMPP::username, and SMPP::version.

Referenced by io_thread().

01077 { 
01078     SMPP_PDU *bind;
01079     Connection *conn; 
01080      
01081     conn = conn_open_tcp(smpp->host, smpp->transmit_port, smpp->conn->our_host ); 
01082     if (conn == NULL) {  
01083        error(0, "SMPP[%s]: Couldn't connect to server.",
01084              octstr_get_cstr(smpp->conn->id));
01085        return NULL; 
01086     } 
01087  
01088     bind = smpp_pdu_create(bind_transceiver, 
01089                            counter_increase(smpp->message_id_counter)); 
01090     bind->u.bind_transceiver.system_id = octstr_duplicate(smpp->username); 
01091     bind->u.bind_transceiver.password = octstr_duplicate(smpp->password); 
01092     if (smpp->system_type == NULL) 
01093         bind->u.bind_transceiver.system_type = octstr_create("VMA"); 
01094     else    
01095         bind->u.bind_transceiver.system_type = octstr_duplicate(smpp->system_type); 
01096     bind->u.bind_transceiver.interface_version = smpp->version;
01097     bind->u.bind_transceiver.address_range = octstr_duplicate(smpp->address_range); 
01098     bind->u.bind_transceiver.addr_ton = smpp->bind_addr_ton;
01099     bind->u.bind_transceiver.addr_npi = smpp->bind_addr_npi;
01100     send_pdu(conn, smpp->conn->id, bind); 
01101     smpp_pdu_destroy(bind); 
01102  
01103     return conn; 
01104 } 

Here is the call graph for this function:

Connection* open_transmitter SMPP smpp  )  [static]
 

Definition at line 1038 of file smsc_smpp.c.

References SMPP::address_range, SMPP::bind_addr_npi, SMPP::bind_addr_ton, bind_transmitter, SMPP::conn, conn_open_tcp(), counter_increase(), error(), SMPP::host, smscconn::id, SMPP::message_id_counter, octstr_create, octstr_duplicate, octstr_get_cstr, smscconn::our_host, SMPP::password, send_pdu(), smpp_pdu_create(), smpp_pdu_destroy(), SMPP::system_type, SMPP::transmit_port, SMPP_PDU::u, SMPP::username, and SMPP::version.

Referenced by io_thread().

01039 { 
01040     SMPP_PDU *bind; 
01041     Connection *conn; 
01042  
01043     conn = conn_open_tcp(smpp->host, smpp->transmit_port, smpp->conn->our_host ); 
01044     if (conn == NULL) {
01045         error(0, "SMPP[%s]: Couldn't connect to server.",
01046               octstr_get_cstr(smpp->conn->id));
01047         return NULL; 
01048     } 
01049      
01050     bind = smpp_pdu_create(bind_transmitter, 
01051                 counter_increase(smpp->message_id_counter)); 
01052     bind->u.bind_transmitter.system_id = octstr_duplicate(smpp->username); 
01053     bind->u.bind_transmitter.password = octstr_duplicate(smpp->password); 
01054     if (smpp->system_type == NULL) 
01055         bind->u.bind_transmitter.system_type = octstr_create("VMA"); 
01056     else 
01057         bind->u.bind_transmitter.system_type =  
01058            octstr_duplicate(smpp->system_type); 
01059     bind->u.bind_transmitter.interface_version = smpp->version;
01060     bind->u.bind_transmitter.address_range =  
01061         octstr_duplicate(smpp->address_range); 
01062     bind->u.bind_transmitter.addr_ton = smpp->bind_addr_ton;
01063     bind->u.bind_transmitter.addr_npi = smpp->bind_addr_npi;
01064     send_pdu(conn, smpp->conn->id, bind); 
01065     smpp_pdu_destroy(bind); 
01066  
01067     return conn; 
01068 } 

Here is the call graph for this function:

Msg* pdu_to_msg SMPP smpp,
SMPP_PDU pdu,
long *  reason
[static]
 

Definition at line 416 of file smsc_smpp.c.

References SMPP::alt_addr_charset, SMPP::alt_charset, charset_convert(), charset_gsm_to_utf8(), SMPP::conn, convert_addr_from_pdu(), DC_7BIT, DC_UNDEF, dcs_to_fields(), debug(), deliver_sm, error(), gw_assert, smscconn::id, msg_create, msg_destroy(), octstr_copy, octstr_delete(), octstr_get_char(), octstr_get_cstr, octstr_len(), pdu, reason, SMPP_DEFAULT_CHARSET, sms, SMPP_PDU::type, SMPP_PDU::u, and SMPP::version.

Referenced by handle_pdu().

00417 {
00418     Msg *msg;
00419     int ton, npi;
00420 
00421     gw_assert(pdu->type == deliver_sm);
00422 
00423     msg = msg_create(sms);
00424     gw_assert(msg != NULL);
00425     *reason = SMPP_ESME_ROK;
00426 
00427     /* 
00428      * Reset source addr to have a prefixed '+' in case we have an 
00429      * intl. TON to allow backend boxes (ie. smsbox) to distinguish
00430      * between national and international numbers.
00431      */
00432     ton = pdu->u.deliver_sm.source_addr_ton;
00433     npi = pdu->u.deliver_sm.source_addr_npi;
00434     /* check source addr */
00435     if ((*reason = convert_addr_from_pdu(smpp->conn->id, pdu->u.deliver_sm.source_addr, ton, npi, smpp->alt_addr_charset)) != SMPP_ESME_ROK)
00436         goto error;
00437     msg->sms.sender = pdu->u.deliver_sm.source_addr;
00438     pdu->u.deliver_sm.source_addr = NULL;
00439 
00440     /* 
00441      * Follows SMPP spec. v3.4. issue 1.2 
00442      * it's not allowed to have destination_addr NULL 
00443      */
00444     if (pdu->u.deliver_sm.destination_addr == NULL) {
00445         error(0, "SMPP[%s]: Mallformed destination_addr `%s', may not be empty. "
00446                  "Discarding MO message.", octstr_get_cstr(smpp->conn->id),
00447                      octstr_get_cstr(pdu->u.deliver_sm.destination_addr));
00448         *reason = SMPP_ESME_RINVDSTADR;
00449         goto error;
00450     }
00451 
00452     /* Same reset of destination number as for source */
00453     ton = pdu->u.deliver_sm.dest_addr_ton;
00454     npi = pdu->u.deliver_sm.dest_addr_npi;
00455     /* check destination addr */
00456     if ((*reason = convert_addr_from_pdu(smpp->conn->id, pdu->u.deliver_sm.destination_addr, ton, npi, smpp->alt_addr_charset)) != SMPP_ESME_ROK)
00457         goto error;
00458     msg->sms.receiver = pdu->u.deliver_sm.destination_addr;
00459     pdu->u.deliver_sm.destination_addr = NULL;
00460 
00461     /* SMSCs use service_type for billing information */
00462     msg->sms.binfo = pdu->u.deliver_sm.service_type;
00463     pdu->u.deliver_sm.service_type = NULL;
00464 
00465     if (pdu->u.deliver_sm.esm_class & ESM_CLASS_SUBMIT_RPI)
00466         msg->sms.rpi = 1;
00467 
00468     /*
00469      * Check for message_payload if version > 0x33 and sm_length == 0
00470      * Note: SMPP spec. v3.4. doesn't allow to send both: message_payload & short_message!
00471      */
00472     if (smpp->version > 0x33 && pdu->u.deliver_sm.sm_length == 0 && pdu->u.deliver_sm.message_payload) {
00473         msg->sms.msgdata = pdu->u.deliver_sm.message_payload;
00474         pdu->u.deliver_sm.message_payload = NULL;
00475     }
00476     else {
00477         msg->sms.msgdata = pdu->u.deliver_sm.short_message;
00478         pdu->u.deliver_sm.short_message = NULL;
00479     }
00480 
00481     /*
00482      * Encode udh if udhi set
00483      * for reference see GSM03.40, section 9.2.3.24
00484      */
00485     if (pdu->u.deliver_sm.esm_class & ESM_CLASS_SUBMIT_UDH_INDICATOR) {
00486         int udhl;
00487         udhl = octstr_get_char(msg->sms.msgdata, 0) + 1;
00488         debug("bb.sms.smpp",0,"SMPP[%s]: UDH length read as %d", 
00489               octstr_get_cstr(smpp->conn->id), udhl);
00490         if (udhl > octstr_len(msg->sms.msgdata)) {
00491             error(0, "SMPP[%s]: Mallformed UDH length indicator 0x%03x while message length "
00492                      "0x%03lx. Discarding MO message.", octstr_get_cstr(smpp->conn->id),
00493                      udhl, octstr_len(msg->sms.msgdata));
00494             *reason = SMPP_ESME_RINVESMCLASS;
00495             goto error;
00496         }
00497         msg->sms.udhdata = octstr_copy(msg->sms.msgdata, 0, udhl);
00498         octstr_delete(msg->sms.msgdata, 0, udhl);
00499     }
00500 
00501     dcs_to_fields(&msg, pdu->u.deliver_sm.data_coding);
00502 
00503     /* handle default data coding */
00504     switch (pdu->u.deliver_sm.data_coding) {
00505         case 0x00: /* default SMSC alphabet */
00506             /*
00507              * try to convert from something interesting if specified so
00508              * unless it was specified binary, ie. UDH indicator was detected
00509              */
00510             if (smpp->alt_charset && msg->sms.coding != DC_8BIT) {
00511                 if (charset_convert(msg->sms.msgdata, octstr_get_cstr(smpp->alt_charset), SMPP_DEFAULT_CHARSET) != 0)
00512                     error(0, "Failed to convert msgdata from charset <%s> to <%s>, will leave as is.",
00513                              octstr_get_cstr(smpp->alt_charset), SMPP_DEFAULT_CHARSET);
00514                 msg->sms.coding = DC_7BIT;
00515             } else { /* assume GSM 03.38 7-bit alphabet */
00516                 charset_gsm_to_utf8(msg->sms.msgdata);
00517                 msg->sms.coding = DC_7BIT;
00518             }
00519             break;
00520         case 0x01: /* ASCII or IA5 - not sure if I need to do anything */
00521         case 0x03: /* ISO-8859-1 - do nothing */
00522             msg->sms.coding = DC_7BIT; break;
00523         case 0x02: /* 8 bit binary - do nothing */
00524         case 0x04: /* 8 bit binary - do nothing */
00525             msg->sms.coding = DC_8BIT; break;
00526         case 0x05: /* JIS - what do I do with that ? */
00527             break;
00528         case 0x06: /* Cyrllic - iso-8859-5, I'll convert to unicode */
00529             if (charset_convert(msg->sms.msgdata, "ISO-8859-5", "UTF-8") != 0)
00530                 error(0, "Failed to convert msgdata from cyrllic to UTF-8, will leave as is");
00531             msg->sms.coding = DC_7BIT; break;
00532         case 0x07: /* Hebrew iso-8859-8, I'll convert to unicode */
00533             if (charset_convert(msg->sms.msgdata, "ISO-8859-8", "UTF-8") != 0)
00534                 error(0, "Failed to convert msgdata from hebrew to UTF-8, will leave as is");
00535             msg->sms.coding = DC_7BIT; break;
00536         case 0x08: /* unicode UCS-2, yey */
00537             msg->sms.coding = DC_UCS2; break;
00538 
00539             /*
00540              * don't much care about the others,
00541              * you implement them if you feel like it
00542              */
00543 
00544         default:
00545             /*
00546              * some of smsc send with dcs from GSM 03.38 , but these are reserved in smpp spec.
00547              * So we just look decoded values from dcs_to_fields and if none there make our assumptions.
00548              * if we have an UDH indicator, we assume DC_8BIT.
00549              */
00550             if (msg->sms.coding == DC_UNDEF && pdu->u.deliver_sm.esm_class & ESM_CLASS_SUBMIT_UDH_INDICATOR)
00551                 msg->sms.coding = DC_8BIT;
00552             else if (msg->sms.coding == DC_7BIT || msg->sms.coding == DC_UNDEF) { /* assume GSM 7Bit , reencode */
00553                 msg->sms.coding = DC_7BIT;
00554                 charset_gsm_to_utf8(msg->sms.msgdata);
00555             }
00556     }
00557     msg->sms.pid = pdu->u.deliver_sm.protocol_id;
00558 
00559     /* set priority flag */
00560     msg->sms.priority = pdu->u.deliver_sm.priority_flag;
00561 
00562     return msg;
00563 
00564 error:
00565     msg_destroy(msg);
00566     return NULL;
00567 }

Here is the call graph for this function:

long queued_cb SMSCConn conn  )  [static]
 

Definition at line 1906 of file smsc_smpp.c.

References smscconn::data, gwlist_len(), smscconn::load, SMPP::msgs_to_send, SMSCConn, SMSCCONN_DEAD, and smscconn::status.

01907 {
01908     SMPP *smpp;
01909 
01910     smpp = conn->data;
01911     conn->load = (smpp ? (conn->status != SMSCCONN_DEAD ?
01912                   gwlist_len(smpp->msgs_to_send) : 0) : 0);
01913     return conn->load;
01914 }

Here is the call graph for this function:

int read_pdu SMPP smpp,
Connection conn,
long *  len,
SMPP_PDU **  pdu
[static]
 

Definition at line 297 of file smsc_smpp.c.

References SMPP::conn, conn_eof(), conn_error(), debug(), error(), smscconn::id, octstr_destroy(), octstr_dump, octstr_get_cstr, pdu, smpp_pdu_read_data(), smpp_pdu_read_len(), and smpp_pdu_unpack().

Referenced by io_thread(), and smasi_thread().

00298 { 
00299     Octstr *os; 
00300  
00301     if (*len == 0) { 
00302         *len = smpp_pdu_read_len(conn); 
00303         if (*len == -1) { 
00304             error(0, "SMPP[%s]: Server sent garbage, ignored.",
00305                   octstr_get_cstr(smpp->conn->id)); 
00306             return -1; 
00307         } else if (*len == 0) { 
00308             if (conn_eof(conn) || conn_error(conn)) 
00309                 return -1; 
00310             return 0; 
00311         } 
00312     } 
00313      
00314     os = smpp_pdu_read_data(conn, *len); 
00315     if (os == NULL) { 
00316         if (conn_eof(conn) || conn_error(conn)) 
00317             return -1; 
00318         return 0; 
00319     } 
00320     *len = 0; 
00321      
00322     *pdu = smpp_pdu_unpack(os); 
00323     if (*pdu == NULL) { 
00324         error(0, "SMPP[%s]: PDU unpacking failed.",
00325               octstr_get_cstr(smpp->conn->id)); 
00326         debug("bb.sms.smpp", 0, "SMPP[%s]: Failed PDU follows.",
00327               octstr_get_cstr(smpp->conn->id)); 
00328         octstr_dump(os, 0); 
00329         octstr_destroy(os);
00330         return -1;
00331     }
00332 
00333     octstr_destroy(os);
00334     return 1;
00335 }

Here is the call graph for this function:

void send_enquire_link SMPP smpp,
Connection conn,
long *  last_sent
[static]
 

Definition at line 936 of file smsc_smpp.c.

References SMPP::conn, conn_write(), counter_increase(), date_universal_now(), dump_pdu, enquire_link, SMPP::enquire_link_interval, smscconn::id, SMPP::message_id_counter, octstr_destroy(), pdu, smpp_pdu_create(), smpp_pdu_destroy(), and smpp_pdu_pack().

Referenced by io_thread(), and smasi_thread().

00937 {
00938     SMPP_PDU *pdu;
00939     Octstr *os;
00940 
00941     if (date_universal_now() - *last_sent < smpp->enquire_link_interval)
00942         return;
00943     *last_sent = date_universal_now();
00944 
00945     pdu = smpp_pdu_create(enquire_link, counter_increase(smpp->message_id_counter));
00946     dump_pdu("Sending enquire link:", smpp->conn->id, pdu);
00947     os = smpp_pdu_pack(pdu);
00948     if (os)
00949     conn_write(conn, os); /* Write errors checked by caller. */
00950     octstr_destroy(os);
00951     smpp_pdu_destroy(pdu);
00952 }

Here is the call graph for this function:

void send_messages SMPP smpp,
Connection conn,
long *  pending_submits
[static]
 

Definition at line 984 of file smsc_smpp.c.

References bb_smscconn_send_failed(), SMPP::conn, dict_put(), gwlist_extract_first(), gwthread_sleep(), smscconn::id, SMPP::max_pending_submits, msg_to_pdu(), SMPP::msgs_to_send, octstr_create, octstr_destroy(), octstr_format(), pdu, send_pdu(), SMPP::sent_msgs, smpp_msg_create(), smpp_pdu_destroy(), SMSCCONN_FAILED_MALFORMED, SMSCCONN_FAILED_TEMPORARILY, smscconn::throughput, and SMPP_PDU::u.

Referenced by io_thread(), and smasi_thread().

00985 {
00986     Msg *msg;
00987     SMPP_PDU *pdu;
00988     Octstr *os;
00989     double delay = 0;
00990 
00991     if (*pending_submits == -1)
00992         return;
00993 
00994     if (smpp->conn->throughput > 0) {
00995         delay = 1.0 / smpp->conn->throughput;
00996     }
00997 
00998     while (*pending_submits < smpp->max_pending_submits) {
00999         /* Get next message, quit if none to be sent */
01000         msg = gwlist_extract_first(smpp->msgs_to_send);
01001         if (msg == NULL)
01002             break;
01003 
01004         /* Send PDU, record it as waiting for ack from SMS center */
01005         pdu = msg_to_pdu(smpp, msg);
01006         if (pdu == NULL) {
01007             bb_smscconn_send_failed(smpp->conn, msg, SMSCCONN_FAILED_MALFORMED, octstr_create("MALFORMED SMS"));
01008             continue;
01009         }
01010         /* check for write errors */
01011         if (send_pdu(conn, smpp->conn->id, pdu) == 0) {
01012             struct smpp_msg *smpp_msg = smpp_msg_create(msg);
01013             os = octstr_format("%ld", pdu->u.submit_sm.sequence_number);
01014             dict_put(smpp->sent_msgs, os, smpp_msg);
01015             smpp_pdu_destroy(pdu);
01016             octstr_destroy(os);
01017             ++(*pending_submits);
01018             /*
01019              * obey throughput speed limit, if any.
01020              */
01021             if (smpp->conn->throughput > 0)
01022                 gwthread_sleep(delay);
01023         }
01024         else { /* write error occurs */
01025             smpp_pdu_destroy(pdu);
01026             bb_smscconn_send_failed(smpp->conn, msg, SMSCCONN_FAILED_TEMPORARILY, NULL);
01027             break;
01028         }
01029     }
01030 }

Here is the call graph for this function:

int send_msg_cb SMSCConn conn,
Msg msg
[static]
 

Definition at line 1917 of file smsc_smpp.c.

References smscconn::data, gwlist_produce(), gwthread_wakeup(), msg_duplicate(), SMPP::msgs_to_send, SMSCConn, and SMPP::transmitter.

01918 {
01919     SMPP *smpp;
01920 
01921     smpp = conn->data;
01922     gwlist_produce(smpp->msgs_to_send, msg_duplicate(msg));
01923     gwthread_wakeup(smpp->transmitter);
01924     return 0;
01925 }

Here is the call graph for this function:

int send_pdu Connection conn,
Octstr id,
SMPP_PDU pdu
[static]
 

Definition at line 968 of file smsc_smpp.c.

References conn_write(), dump_pdu, octstr_destroy(), pdu, and smpp_pdu_pack().

00969 {
00970     Octstr *os;
00971     int ret;
00972 
00973     dump_pdu("Sending PDU:", id, pdu);
00974     os = smpp_pdu_pack(pdu);
00975     if (os)
00976         ret = conn_write(conn, os);   /* Caller checks for write errors later */
00977     else
00978     ret = -1;
00979     octstr_destroy(os);
00980     return ret;
00981 }

Here is the call graph for this function:

void send_unbind SMPP smpp,
Connection conn
[static]
 

Definition at line 955 of file smsc_smpp.c.

References SMPP::conn, conn_write(), counter_increase(), dump_pdu, smscconn::id, SMPP::message_id_counter, octstr_destroy(), pdu, smpp_pdu_create(), smpp_pdu_destroy(), smpp_pdu_pack(), and unbind.

Referenced by io_thread().

00956 {
00957     SMPP_PDU *pdu;
00958     Octstr *os;
00959     pdu = smpp_pdu_create(unbind, counter_increase(smpp->message_id_counter));
00960     dump_pdu("Sending unbind:", smpp->conn->id, pdu);
00961     os = smpp_pdu_pack(pdu);
00962     conn_write(conn, os);
00963     octstr_destroy(os);
00964     smpp_pdu_destroy(pdu);
00965 }

Here is the call graph for this function:

int shutdown_cb SMSCConn conn,
int  finish_sending
[static]
 

Definition at line 1928 of file smsc_smpp.c.

References bb_smscconn_killed(), smscconn::data, debug(), gwthread_join(), gwthread_wakeup(), smscconn::name, octstr_get_cstr, SMPP::quitting, SMPP::receiver, smpp_destroy(), SMSCConn, smscconn::status, SMPP::transmitter, and smscconn::why_killed.

01929 {
01930     SMPP *smpp;
01931 
01932     debug("bb.smpp", 0, "Shutting down SMSCConn %s (%s)",
01933           octstr_get_cstr(conn->name),
01934           finish_sending ? "slow" : "instant");
01935 
01936     conn->why_killed = SMSCCONN_KILLED_SHUTDOWN;
01937 
01938     /* XXX implement finish_sending */
01939 
01940     smpp = conn->data;
01941     smpp->quitting = 1;
01942     if (smpp->transmitter != -1) {
01943         gwthread_wakeup(smpp->transmitter);
01944         gwthread_join(smpp->transmitter);
01945     }
01946     if (smpp->receiver != -1) {
01947         gwthread_wakeup(smpp->receiver);
01948         gwthread_join(smpp->receiver);
01949     }
01950     smpp_destroy(smpp);
01951 
01952     debug("bb.smpp", 0, "SMSCConn %s shut down.",
01953           octstr_get_cstr(conn->name));
01954     conn->status = SMSCCONN_DEAD;
01955     bb_smscconn_killed();
01956     return 0;
01957 }

Here is the call graph for this function:

SMPP* smpp_create SMSCConn conn,
Octstr host,
int  transmit_port,
int  receive_port,
Octstr system_type,
Octstr username,
Octstr password,
Octstr address_range,
int  source_addr_ton,
int  source_addr_npi,
int  dest_addr_ton,
int  dest_addr_npi,
int  enquire_link_interval,
int  max_pending_submits,
int  version,
int  priority,
int  validity,
Octstr my_number,
int  smpp_msg_id_type,
int  autodetect_addr,
Octstr alt_charset,
Octstr alt_addr_charset,
Octstr service_type,
long  connection_timeout,
long  wait_ack,
int  wait_ack_action
[static]
 

Definition at line 209 of file smsc_smpp.c.

References counter_create(), counter_increase(), dict_create(), gwlist_add_producer(), gwlist_create, SMPP::msgs_to_send, octstr_duplicate, password, SMPP::receiver, SMSCConn, SMPP::transmitter, and username.

Referenced by smsc_smpp_create().

00221 { 
00222     SMPP *smpp; 
00223      
00224     smpp = gw_malloc(sizeof(*smpp)); 
00225     smpp->transmitter = -1; 
00226     smpp->receiver = -1; 
00227     smpp->msgs_to_send = gwlist_create(); 
00228     smpp->sent_msgs = dict_create(max_pending_submits, NULL); 
00229     gwlist_add_producer(smpp->msgs_to_send); 
00230     smpp->received_msgs = gwlist_create(); 
00231     smpp->message_id_counter = counter_create(); 
00232     counter_increase(smpp->message_id_counter);
00233     smpp->host = octstr_duplicate(host); 
00234     smpp->system_type = octstr_duplicate(system_type); 
00235     smpp->username = octstr_duplicate(username); 
00236     smpp->password = octstr_duplicate(password); 
00237     smpp->address_range = octstr_duplicate(address_range); 
00238     smpp->source_addr_ton = source_addr_ton; 
00239     smpp->source_addr_npi = source_addr_npi; 
00240     smpp->dest_addr_ton = dest_addr_ton; 
00241     smpp->dest_addr_npi = dest_addr_npi; 
00242     smpp->my_number = octstr_duplicate(my_number); 
00243     smpp->service_type = octstr_duplicate(service_type);
00244     smpp->transmit_port = transmit_port; 
00245     smpp->receive_port = receive_port; 
00246     smpp->enquire_link_interval = enquire_link_interval;
00247     smpp->max_pending_submits = max_pending_submits; 
00248     smpp->quitting = 0; 
00249     smpp->version = version;
00250     smpp->priority = priority;
00251     smpp->validityperiod = validity;
00252     smpp->conn = conn; 
00253     smpp->throttling_err_time = 0;
00254     smpp->smpp_msg_id_type = smpp_msg_id_type;    
00255     smpp->autodetect_addr = autodetect_addr;
00256     smpp->alt_charset = octstr_duplicate(alt_charset);
00257     smpp->alt_addr_charset = octstr_duplicate(alt_addr_charset);
00258     smpp->connection_timeout = connection_timeout;
00259     smpp->wait_ack = wait_ack;
00260     smpp->wait_ack_action = wait_ack_action;
00261     smpp->bind_addr_ton = 0;
00262     smpp->bind_addr_npi = 0;
00263  
00264     return smpp; 
00265 } 

Here is the call graph for this function:

void smpp_destroy SMPP smpp  )  [static]
 

Definition at line 268 of file smsc_smpp.c.

References SMPP::address_range, SMPP::alt_addr_charset, SMPP::alt_charset, counter_destroy(), dict_destroy(), gwlist_destroy(), SMPP::host, SMPP::message_id_counter, msg_destroy_item(), SMPP::msgs_to_send, SMPP::my_number, octstr_destroy(), SMPP::password, SMPP::received_msgs, SMPP::sent_msgs, SMPP::service_type, SMPP::system_type, and SMPP::username.

Referenced by shutdown_cb(), and smsc_smpp_create().

00269 { 
00270     if (smpp != NULL) { 
00271         gwlist_destroy(smpp->msgs_to_send, msg_destroy_item); 
00272         dict_destroy(smpp->sent_msgs); 
00273         gwlist_destroy(smpp->received_msgs, msg_destroy_item); 
00274         counter_destroy(smpp->message_id_counter); 
00275         octstr_destroy(smpp->host); 
00276         octstr_destroy(smpp->username); 
00277         octstr_destroy(smpp->password); 
00278         octstr_destroy(smpp->system_type); 
00279         octstr_destroy(smpp->service_type); 
00280         octstr_destroy(smpp->address_range); 
00281         octstr_destroy(smpp->my_number);
00282         octstr_destroy(smpp->alt_charset);
00283         octstr_destroy(smpp->alt_addr_charset);
00284         gw_free(smpp); 
00285     } 
00286 } 

Here is the call graph for this function:

struct smpp_msg* smpp_msg_create Msg msg  )  [static]
 

Definition at line 181 of file smsc_smpp.c.

References gw_assert, smpp_msg::msg, result, and smpp_msg::sent_time.

Referenced by send_messages().

00182 {
00183     struct smpp_msg *result = gw_malloc(sizeof(struct smpp_msg));
00184     
00185     gw_assert(result != NULL);
00186     result->sent_time = time(NULL);
00187     result->msg = msg;
00188                 
00189     return result;
00190 }

void smpp_msg_destroy struct smpp_msg msg,
int  destroy_msg
[static]
 

Definition at line 196 of file smsc_smpp.c.

References smpp_msg::msg, and msg_destroy().

Referenced by do_queue_cleanup(), handle_pdu(), and io_thread().

00197 {
00198     /* sanity check */
00199     if (msg == NULL)
00200         return;
00201                 
00202     if (destroy_msg && msg->msg != NULL)
00203         msg_destroy(msg->msg);
00204                             
00205     gw_free(msg);
00206 }

Here is the call graph for this function:

long smpp_status_to_smscconn_failure_reason long  status  )  [static]
 

Definition at line 717 of file smsc_smpp.c.

References SMPP_ESME_RMSGQFUL, SMPP_ESME_RSYSERR, SMPP_ESME_RTHROTTLED, and SMPP_ESME_RX_T_APPN.

Referenced by handle_pdu().

00718 {
00719     switch(status) {
00720         case SMPP_ESME_RMSGQFUL:
00721         case SMPP_ESME_RTHROTTLED:
00722         case SMPP_ESME_RX_T_APPN:
00723         case SMPP_ESME_RSYSERR:
00724             return SMSCCONN_FAILED_TEMPORARILY;
00725             break;
00726 
00727         default:
00728             return SMSCCONN_FAILED_REJECTED;
00729     }
00730 }

int smsc_smpp_create SMSCConn conn,
CfgGroup grp
 

Definition at line 1966 of file smsc_smpp.c.

References SMPP::bind_addr_npi, SMPP::bind_addr_ton, cfg_get, cfg_get_bool(), cfg_get_integer(), SMPP::conn, smscconn::data, error(), gwthread_create, gwthread_join(), gwthread_wakeup(), smscconn::id, io_arg_create(), io_thread(), smscconn::name, octstr_destroy(), octstr_duplicate, octstr_format(), octstr_get_cstr, octstr_imm(), octstr_len(), ok, panic, password, port, smscconn::queued, SMPP::quitting, SMPP::receiver, smscconn::send_msg, smscconn::shutdown, smpp_create(), smpp_destroy(), SMSCConn, smscconn::status, SMPP::transmitter, username, and warning().

Referenced by smscconn_create().

01967 {
01968     Octstr *host;
01969     long port;
01970     long receive_port;
01971     Octstr *username;
01972     Octstr *password;
01973     Octstr *system_id;
01974     Octstr *system_type;
01975     Octstr *address_range;
01976     long source_addr_ton;
01977     long source_addr_npi;
01978     long dest_addr_ton;
01979     long dest_addr_npi;
01980     Octstr *my_number;
01981     Octstr *service_type;
01982     SMPP *smpp;
01983     int ok;
01984     int transceiver_mode;
01985     Octstr *smsc_id;
01986     long enquire_link_interval;
01987     long max_pending_submits;
01988     long version;
01989     long priority;
01990     long validity;
01991     long smpp_msg_id_type;
01992     int autodetect_addr;
01993     Octstr *alt_charset;
01994     Octstr *alt_addr_charset;
01995     long connection_timeout, wait_ack, wait_ack_action;
01996 
01997     my_number = alt_addr_charset = alt_charset = NULL;
01998     transceiver_mode = 0;
01999     autodetect_addr = 1;
02000  
02001     host = cfg_get(grp, octstr_imm("host")); 
02002     if (cfg_get_integer(&port, grp, octstr_imm("port")) == -1) 
02003         port = 0; 
02004     if (cfg_get_integer(&receive_port, grp, octstr_imm("receive-port")) == -1) 
02005         receive_port = 0; 
02006     cfg_get_bool(&transceiver_mode, grp, octstr_imm("transceiver-mode")); 
02007     username = cfg_get(grp, octstr_imm("smsc-username")); 
02008     password = cfg_get(grp, octstr_imm("smsc-password")); 
02009     system_type = cfg_get(grp, octstr_imm("system-type")); 
02010     address_range = cfg_get(grp, octstr_imm("address-range")); 
02011     my_number = cfg_get(grp, octstr_imm("my-number")); 
02012     service_type = cfg_get(grp, octstr_imm("service-type")); 
02013      
02014     system_id = cfg_get(grp, octstr_imm("system-id")); 
02015     if (system_id != NULL) { 
02016         warning(0, "SMPP: obsolete system-id variable is set, " 
02017                "use smsc-username instead."); 
02018         if (username == NULL) { 
02019             warning(0, "SMPP: smsc-username not set, using system-id instead"); 
02020             username = system_id; 
02021         } else 
02022             octstr_destroy(system_id); 
02023     } 
02024 
02025     /* 
02026      * check if timing values have been configured, otherwise
02027      * use the predefined default values.
02028      */
02029     if (cfg_get_integer(&enquire_link_interval, grp, 
02030                         octstr_imm("enquire-link-interval")) == -1)
02031         enquire_link_interval = SMPP_ENQUIRE_LINK_INTERVAL;
02032     if (cfg_get_integer(&max_pending_submits, grp, 
02033                         octstr_imm("max-pending-submits")) == -1)
02034         max_pending_submits = SMPP_MAX_PENDING_SUBMITS;
02035  
02036     /* Check that config is OK */ 
02037     ok = 1; 
02038     if (host == NULL) { 
02039         error(0,"SMPP: Configuration file doesn't specify host"); 
02040         ok = 0; 
02041     }     
02042     if (username == NULL) { 
02043         error(0, "SMPP: Configuration file doesn't specify username."); 
02044         ok = 0; 
02045     } 
02046     if (password == NULL) { 
02047         error(0, "SMPP: Configuration file doesn't specify password."); 
02048         ok = 0; 
02049     } 
02050     if (system_type == NULL) { 
02051         error(0, "SMPP: Configuration file doesn't specify system-type."); 
02052         ok = 0; 
02053     } 
02054     if (octstr_len(service_type) > 6) {
02055             error(0, "SMPP: Service type must be 6 characters or less.");
02056             ok = 0;
02057     }
02058 
02059     if (!ok) 
02060         return -1; 
02061  
02062     /* if the ton and npi values are forced, set them, else set them to -1 */ 
02063     if (cfg_get_integer(&source_addr_ton, grp, 
02064                         octstr_imm("source-addr-ton")) == -1) 
02065         source_addr_ton = -1; 
02066     if (cfg_get_integer(&source_addr_npi, grp, 
02067                         octstr_imm("source-addr-npi")) == -1) 
02068         source_addr_npi = -1; 
02069     if (cfg_get_integer(&dest_addr_ton, grp, 
02070                         octstr_imm("dest-addr-ton")) == -1) 
02071         dest_addr_ton = -1; 
02072     if (cfg_get_integer(&dest_addr_npi, grp, 
02073                         octstr_imm("dest-addr-npi")) == -1) 
02074         dest_addr_npi = -1; 
02075 
02076     /* if source addr autodetection should be used set this to 1 */
02077     if (cfg_get_bool(&autodetect_addr, grp, octstr_imm("source-addr-autodetect")) == -1)
02078         autodetect_addr = 1; /* default is autodetect if no option defined */
02079 
02080     /* check for any specified interface version */
02081     if (cfg_get_integer(&version, grp, octstr_imm("interface-version")) == -1)
02082         version = SMPP_DEFAULT_VERSION;
02083     else
02084         /* convert decimal to BCD */
02085         version = ((version / 10) << 4) + (version % 10);
02086 
02087     /* check for any specified priority value in range [0-5] */
02088     if (cfg_get_integer(&priority, grp, octstr_imm("priority")) == -1)
02089         priority = SMPP_DEFAULT_PRIORITY;
02090     else if (priority < 0 || priority > 3)
02091         panic(0, "SMPP: Invalid value for priority directive in configuraton (allowed range 0-3).");
02092 
02093     /* check for message validity period */
02094     if (cfg_get_integer(&validity, grp, octstr_imm("validityperiod")) == -1)
02095         validity = -1;
02096     else if (validity < 0)
02097         panic(0, "SMPP: Invalid value for validity period (allowed value >= 0).");
02098 
02099     /* set the msg_id type variable for this SMSC */
02100     if (cfg_get_integer(&smpp_msg_id_type, grp, octstr_imm("msg-id-type")) == -1) {
02101         /* 
02102          * defaults to C string "as-is" style 
02103          */
02104         smpp_msg_id_type = -1; 
02105     } else {
02106         if (smpp_msg_id_type < 0 || smpp_msg_id_type > 3)
02107             panic(0,"SMPP: Invalid value for msg-id-type directive in configuraton"); 
02108     }
02109 
02110     /* check for an alternative charset */
02111     alt_charset = cfg_get(grp, octstr_imm("alt-charset"));
02112     alt_addr_charset = cfg_get(grp, octstr_imm("alt-addr-charset"));
02113     
02114     /* check for connection timeout */
02115     if (cfg_get_integer(&connection_timeout, grp, octstr_imm("connection-timeout")) == -1)
02116         connection_timeout = SMPP_DEFAULT_CONNECTION_TIMEOUT;
02117 
02118     /* check if wait-ack timeout set */
02119     if (cfg_get_integer(&wait_ack, grp, octstr_imm("wait-ack")) == -1)
02120         wait_ack = SMPP_DEFAULT_WAITACK;
02121 
02122     if (cfg_get_integer(&wait_ack_action, grp, octstr_imm("wait-ack-expire")) == -1)
02123         wait_ack_action = SMPP_WAITACK_REQUEUE;
02124         
02125     if (wait_ack_action > 0x03 || wait_ack_action < 0)
02126         panic(0, "SMPP: Invalid wait-ack-expire directive in configuration.");
02127 
02128     smpp = smpp_create(conn, host, port, receive_port, system_type,  
02129                        username, password, address_range,
02130                        source_addr_ton, source_addr_npi, dest_addr_ton,  
02131                        dest_addr_npi, enquire_link_interval, 
02132                        max_pending_submits, version, priority, validity, my_number, 
02133                        smpp_msg_id_type, autodetect_addr, alt_charset, alt_addr_charset,
02134                        service_type, connection_timeout, wait_ack, wait_ack_action); 
02135  
02136     cfg_get_integer(&smpp->bind_addr_ton, grp, octstr_imm("bind-addr-ton"));
02137     cfg_get_integer(&smpp->bind_addr_npi, grp, octstr_imm("bind-addr-npi"));
02138 
02139     conn->data = smpp; 
02140     conn->name = octstr_format("SMPP:%S:%d/%d:%S:%S",  
02141                                host, port, 
02142                                (receive_port ? receive_port : port),  
02143                                username, system_type); 
02144  
02145     smsc_id = cfg_get(grp, octstr_imm("smsc-id")); 
02146     if (smsc_id == NULL) { 
02147         conn->id = octstr_duplicate(conn->name); 
02148     } 
02149 
02150     octstr_destroy(host); 
02151     octstr_destroy(username); 
02152     octstr_destroy(password); 
02153     octstr_destroy(system_type); 
02154     octstr_destroy(address_range); 
02155     octstr_destroy(my_number); 
02156     octstr_destroy(smsc_id);
02157     octstr_destroy(alt_charset); 
02158     octstr_destroy(alt_addr_charset);
02159     octstr_destroy(service_type);
02160 
02161     conn->status = SMSCCONN_CONNECTING; 
02162        
02163     /* 
02164      * I/O threads are only started if the corresponding ports 
02165      * have been configured with positive numbers. Use 0 to  
02166      * disable the creation of the corresponding thread. 
02167      */ 
02168     if (port != 0) 
02169         smpp->transmitter = gwthread_create(io_thread, io_arg_create(smpp,  
02170                                            (transceiver_mode ? 2 : 1))); 
02171     if (receive_port != 0) 
02172         smpp->receiver = gwthread_create(io_thread, io_arg_create(smpp, 0)); 
02173      
02174     if ((port != 0 && smpp->transmitter == -1) ||  
02175         (receive_port != 0 && smpp->receiver == -1)) { 
02176         error(0, "SMPP[%s]: Couldn't start I/O threads.",
02177               octstr_get_cstr(smpp->conn->id)); 
02178         smpp->quitting = 1; 
02179         if (smpp->transmitter != -1) { 
02180             gwthread_wakeup(smpp->transmitter); 
02181             gwthread_join(smpp->transmitter); 
02182         } 
02183         if (smpp->receiver != -1) { 
02184             gwthread_wakeup(smpp->receiver); 
02185             gwthread_join(smpp->receiver); 
02186         } 
02187         smpp_destroy(conn->data); 
02188         return -1; 
02189     } 
02190  
02191     conn->shutdown = shutdown_cb; 
02192     conn->queued = queued_cb; 
02193     conn->send_msg = send_msg_cb; 
02194  
02195     return 0; 
02196 }

Here is the call graph for this function:

long smscconn_failure_reason_to_smpp_status long  reason  )  [static]
 

Definition at line 1305 of file smsc_smpp.c.

References SMSCCONN_FAILED_QFULL, SMSCCONN_FAILED_REJECTED, SMSCCONN_FAILED_TEMPORARILY, and SMSCCONN_SUCCESS.

Referenced by handle_pdu().

01306 {
01307     switch (reason) {
01308     case SMSCCONN_FAILED_REJECTED:
01309         return SMPP_ESME_RX_R_APPN;
01310     case SMSCCONN_SUCCESS:
01311         return SMPP_ESME_ROK;
01312     case SMSCCONN_FAILED_QFULL:
01313     case SMSCCONN_FAILED_TEMPORARILY:
01314         return SMPP_ESME_RX_T_APPN;
01315     }
01316     return SMPP_ESME_RX_T_APPN;
01317 }

See file LICENSE for details about the license agreement for using, modifying, copying or deriving work from this software.