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

smsc_smpp.c

Go to the documentation of this file.
00001 /* ==================================================================== 
00002  * The Kannel Software License, Version 1.0 
00003  * 
00004  * Copyright (c) 2001-2008 Kannel Group  
00005  * Copyright (c) 1998-2001 WapIT Ltd.   
00006  * All rights reserved. 
00007  * 
00008  * Redistribution and use in source and binary forms, with or without 
00009  * modification, are permitted provided that the following conditions 
00010  * are met: 
00011  * 
00012  * 1. Redistributions of source code must retain the above copyright 
00013  *    notice, this list of conditions and the following disclaimer. 
00014  * 
00015  * 2. Redistributions in binary form must reproduce the above copyright 
00016  *    notice, this list of conditions and the following disclaimer in 
00017  *    the documentation and/or other materials provided with the 
00018  *    distribution. 
00019  * 
00020  * 3. The end-user documentation included with the redistribution, 
00021  *    if any, must include the following acknowledgment: 
00022  *       "This product includes software developed by the 
00023  *        Kannel Group (http://www.kannel.org/)." 
00024  *    Alternately, this acknowledgment may appear in the software itself, 
00025  *    if and wherever such third-party acknowledgments normally appear. 
00026  * 
00027  * 4. The names "Kannel" and "Kannel Group" must not be used to 
00028  *    endorse or promote products derived from this software without 
00029  *    prior written permission. For written permission, please  
00030  *    contact org@kannel.org. 
00031  * 
00032  * 5. Products derived from this software may not be called "Kannel", 
00033  *    nor may "Kannel" appear in their name, without prior written 
00034  *    permission of the Kannel Group. 
00035  * 
00036  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED 
00037  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 
00038  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
00039  * DISCLAIMED.  IN NO EVENT SHALL THE KANNEL GROUP OR ITS CONTRIBUTORS 
00040  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,  
00041  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT  
00042  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR  
00043  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,  
00044  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE  
00045  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,  
00046  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
00047  * ==================================================================== 
00048  * 
00049  * This software consists of voluntary contributions made by many 
00050  * individuals on behalf of the Kannel Group.  For more information on  
00051  * the Kannel Group, please see <http://www.kannel.org/>. 
00052  * 
00053  * Portions of this software are based upon software originally written at  
00054  * WapIT Ltd., Helsinki, Finland for the Kannel project.  
00055  */ 
00056 
00057 /*
00058  * smsc_smpp.c - SMPP v3.3 and v3.4 implementation
00059  *
00060  * Lars Wirzenius
00061  * Stipe Tolj <stolj@wapme.de>
00062  * Alexander Malysh  <amalysh at kannel.org>
00063  */
00064 
00065 /* XXX check SMSCConn conformance */
00066 /* XXX UDH reception */
00067 /* XXX check UDH sending fields esm_class and data_coding from GSM specs */
00068 /* XXX charset conversions on incoming messages (didn't work earlier,
00069        either) */
00070 /* XXX numbering plans and type of number: check spec */
00071 
00072 #include "gwlib/gwlib.h"
00073 #include "msg.h"
00074 #include "smsc_p.h"
00075 #include "smpp_pdu.h"
00076 #include "smscconn_p.h"
00077 #include "bb_smscconn_cb.h"
00078 #include "sms.h"
00079 #include "dlr.h"
00080 #include "bearerbox.h"
00081 
00082 #define SMPP_DEFAULT_CHARSET "UTF-8"
00083 
00084 /*
00085  * Select these based on whether you want to dump SMPP PDUs as they are
00086  * sent and received or not. Not dumping should be the default in at least
00087  * stable releases.
00088  */
00089 
00090 #define DEBUG 1
00091 
00092 #ifndef DEBUG
00093 #define dump_pdu(msg, id, pdu) do{}while(0)
00094 #else
00095 
00096 #define dump_pdu(msg, id, pdu)                  \
00097     do {                                        \
00098         debug("bb.sms.smpp", 0, "SMPP[%s]: %s", \
00099             octstr_get_cstr(id), msg);          \
00100         smpp_pdu_dump(pdu);                     \
00101     } while(0)
00102 #endif
00103 
00104 
00105 /*
00106  * Some defaults.
00107  */
00108 
00109 #define SMPP_ENQUIRE_LINK_INTERVAL  30.0
00110 #define SMPP_MAX_PENDING_SUBMITS    10
00111 #define SMPP_DEFAULT_VERSION        0x34
00112 #define SMPP_DEFAULT_PRIORITY       0
00113 #define SMPP_THROTTLING_SLEEP_TIME  15
00114 #define SMPP_DEFAULT_CONNECTION_TIMEOUT  10 * SMPP_ENQUIRE_LINK_INTERVAL
00115 #define SMPP_DEFAULT_WAITACK        60
00116 #define SMPP_DEFAULT_SHUTDOWN_TIMEOUT 30
00117 
00118 
00119 /* 
00120  * Some defines
00121  */
00122 #define SMPP_WAITACK_RECONNECT      0x00
00123 #define SMPP_WAITACK_REQUEUE        0x01
00124 #define SMPP_WAITACK_NEVER_EXPIRE   0x02
00125 
00126 /***********************************************************************
00127  * Implementation of the actual SMPP protocol: reading and writing
00128  * PDUs in the correct order.
00129  */
00130 
00131 
00132 typedef struct {
00133     long transmitter;
00134     long receiver;
00135     List *msgs_to_send;
00136     Dict *sent_msgs; 
00137     List *received_msgs; 
00138     Counter *message_id_counter; 
00139     Octstr *host; 
00140     Octstr *system_type; 
00141     Octstr *username; 
00142     Octstr *password; 
00143     Octstr *address_range; 
00144     Octstr *my_number; 
00145     Octstr *service_type;
00146     int source_addr_ton; 
00147     int source_addr_npi; 
00148     int dest_addr_ton; 
00149     int dest_addr_npi;
00150     long bind_addr_ton;
00151     long bind_addr_npi;
00152     int transmit_port; 
00153     int receive_port; 
00154     int quitting; 
00155     long enquire_link_interval;
00156     long max_pending_submits;
00157     int version;
00158     int priority;       /* set default priority for messages */    
00159     int validityperiod;    
00160     time_t throttling_err_time;
00161     int smpp_msg_id_type;  /* msg id in C string, hex or decimal */
00162     int autodetect_addr;
00163     Octstr *alt_charset;
00164     Octstr *alt_addr_charset;
00165     long connection_timeout;
00166     long wait_ack;
00167     int wait_ack_action;
00168     SMSCConn *conn; 
00169 } SMPP; 
00170  
00171 
00172 struct smpp_msg {
00173     time_t sent_time;
00174     Msg *msg;
00175 };
00176 
00177 
00178 /*
00179  * create smpp_msg struct 
00180  */
00181 static struct smpp_msg* smpp_msg_create(Msg *msg)
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 }
00191 
00192 
00193 /*
00194  * destroy smpp_msg struct. If destroy_msg flag is set, then message will be freed as well
00195  */
00196 static void smpp_msg_destroy(struct smpp_msg *msg, int destroy_msg)
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 }
00207 
00208  
00209 static SMPP *smpp_create(SMSCConn *conn, Octstr *host, int transmit_port,  
00210                          int receive_port, Octstr *system_type,  
00211                          Octstr *username, Octstr *password, 
00212                          Octstr *address_range,
00213                          int source_addr_ton, int source_addr_npi,  
00214                          int dest_addr_ton, int dest_addr_npi, 
00215                          int enquire_link_interval, int max_pending_submits, 
00216                          int version, int priority, int validity,
00217                          Octstr *my_number, int smpp_msg_id_type, 
00218                          int autodetect_addr, Octstr *alt_charset, Octstr *alt_addr_charset,
00219                          Octstr *service_type, long connection_timeout,
00220                          long wait_ack, int wait_ack_action) 
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 } 
00266  
00267  
00268 static void smpp_destroy(SMPP *smpp) 
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 } 
00287  
00288  
00289 /* 
00290  * Try to read an SMPP PDU from a Connection. Return -1 for error (caller 
00291  * should close the connection), 0 for no PDU to ready yet, or 1 for PDU 
00292  * read and unpacked. Return a pointer to the PDU in `*pdu'. Use `*len' 
00293  * to store the length of the PDU to read (it may be possible to read the 
00294  * length, but not the rest of the PDU - we need to remember the lenght 
00295  * for the next call). `*len' should be zero at the first call. 
00296  */
00297 static int read_pdu(SMPP *smpp, Connection *conn, long *len, SMPP_PDU **pdu) 
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 }
00336 
00337 
00338 static long convert_addr_from_pdu(Octstr *id, Octstr *addr, long ton, long npi, Octstr *alt_addr_charset)
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 }
00407 
00408 
00409 
00410 /*
00411  * Convert SMPP PDU to internal Msgs structure.
00412  * Return the Msg if all was fine and NULL otherwise, while getting 
00413  * the failing reason delivered back in *reason.
00414  * XXX semantical check on the incoming values can be extended here.
00415  */
00416 static Msg *pdu_to_msg(SMPP *smpp, SMPP_PDU *pdu, long *reason)
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 }
00568 
00569 
00570 /*
00571  * Convert SMPP PDU to internal Msgs structure.
00572  * Return the Msg if all was fine and NULL otherwise, while getting 
00573  * the failing reason delivered back in *reason.
00574  * XXX semantical check on the incoming values can be extended here.
00575  */
00576 static Msg *data_sm_to_msg(SMPP *smpp, SMPP_PDU *pdu, long *reason)
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 }
00714 
00715 
00716 
00717 static long smpp_status_to_smscconn_failure_reason(long status)
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 }
00731 
00732 
00733 static SMPP_PDU *msg_to_pdu(SMPP *smpp, Msg *msg)
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 }
00934 
00935 
00936 static void send_enquire_link(SMPP *smpp, Connection *conn, long *last_sent)
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 }
00953 
00954 
00955 static void send_unbind(SMPP *smpp, Connection *conn)
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 }
00966 
00967 
00968 static int send_pdu(Connection *conn, Octstr *id, SMPP_PDU *pdu)
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 }
00982 
00983 
00984 static void send_messages(SMPP *smpp, Connection *conn, long *pending_submits)
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 }
01031 
01032 
01033 /*
01034  * Open transmission connection to SMS center. Return NULL for error,
01035  * open Connection for OK. Caller must set smpp->conn->status correctly
01036  * before calling this.
01037  */
01038 static Connection *open_transmitter(SMPP *smpp)
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 } 
01069  
01070  
01071 /* 
01072  * Open transceiver connection to SMS center. Return NULL for error, 
01073  * open Connection for OK. Caller must set smpp->conn->status correctly 
01074  * before calling this. 
01075  */ 
01076 static Connection *open_transceiver(SMPP *smpp) 
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 } 
01105  
01106  
01107 /* 
01108  * Open reception connection to SMS center. Return NULL for error,  
01109  * open Connection for OK. Caller must set smpp->conn->status correctly  
01110  * before calling this. 
01111  */ 
01112 static Connection *open_receiver(SMPP *smpp)
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 }
01143 
01144 
01145 static Msg *handle_dlr(SMPP *smpp, Octstr *destination_addr, Octstr *short_message, Octstr *message_payload, Octstr *receipted_message_id, long message_state)
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 }
01303 
01304 
01305 static long smscconn_failure_reason_to_smpp_status(long reason)
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 }
01318 
01319 
01320 static void handle_pdu(SMPP *smpp, Connection *conn, SMPP_PDU *pdu,
01321                        long *pending_submits)
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 }
01642 
01643 
01644 struct io_arg {
01645     SMPP *smpp;
01646     int transmitter;
01647 };
01648 
01649 
01650 static struct io_arg *io_arg_create(SMPP *smpp, int transmitter)
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 }
01659 
01660 
01661 /* 
01662  * sent queue cleanup.
01663  * @return 1 if io_thread should reconnect; 0 if not
01664  */
01665 static int do_queue_cleanup(SMPP *smpp, long *pending_submits, int action)
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 }
01722 
01723 
01724 /*
01725  * This is the main function for the background thread for doing I/O on
01726  * one SMPP connection (the one for transmitting or receiving messages).
01727  * It makes the initial connection to the SMPP server and re-connects
01728  * if there are I/O errors or other errors that require it.
01729  */
01730 static void io_thread(void *arg)
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 }
01899 
01900 
01901 /***********************************************************************
01902  * Functions called by smscconn.c via the SMSCConn function pointers.
01903  */
01904 
01905 
01906 static long queued_cb(SMSCConn *conn)
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 }
01915 
01916 
01917 static int send_msg_cb(SMSCConn *conn, Msg *msg)
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 }
01926 
01927 
01928 static int shutdown_cb(SMSCConn *conn, int finish_sending)
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 }
01958 
01959 
01960 /***********************************************************************
01961  * Public interface. This version is suitable for the Kannel bearerbox
01962  * SMSCConn interface.
01963  */
01964 
01965 
01966 int smsc_smpp_create(SMSCConn *conn, CfgGroup *grp)
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 }
02197  
See file LICENSE for details about the license agreement for using, modifying, copying or deriving work from this software.