smsc_smpp.c
上传用户:gzpyjq
上传日期:2013-01-31
资源大小:1852k
文件大小:45k
源码类别:

手机WAP编程

开发平台:

WINDOWS

  1. /* 
  2.  * smsc_smpp.c - SMPP v3.3 and v3.4 implementation 
  3.  * 
  4.  * Lars Wirzenius 
  5.  */ 
  6.   
  7. /* XXX check SMSCConn conformance */ 
  8. /* XXX UDH reception */ 
  9. /* XXX check UDH sending fields esm_class and data_coding from GSM specs */ 
  10. /* XXX charset conversions on incoming messages (didn't work earlier,  
  11.        either) */ 
  12. /* XXX numbering plans and type of number: check spec */ 
  13.   
  14. #include "gwlib/gwlib.h" 
  15. #include "msg.h" 
  16. #include "smsc_p.h" 
  17. #include "smpp_pdu.h" 
  18. #include "smscconn_p.h" 
  19. #include "bb_smscconn_cb.h" 
  20. #include "sms.h" 
  21. #include "dlr.h" 
  22.  
  23. /* 
  24.  * Select these based on whether you want to dump SMPP PDUs as they are  
  25.  * sent and received or not. Not dumping should be the default in at least 
  26.  * stable releases. 
  27.  */ 
  28. #define DEBUG 1
  29. #ifndef DEBUG 
  30. /* This version doesn't dump. */ 
  31. static void dump_pdu(const char *msg, Octstr *id, SMPP_PDU *pdu) 
  32. #else 
  33. /* This version does dump. */ 
  34. static void dump_pdu(const char *msg, Octstr *id, SMPP_PDU *pdu) 
  35.     debug("bb.sms.smpp", 0, "SMPP[%s]: %s", 
  36.           octstr_get_cstr(id), msg); 
  37.     smpp_pdu_dump(pdu); 
  38. #endif 
  39.  
  40.  
  41. /*  
  42.  * Some defaults.
  43.  */ 
  44.  
  45. #define SMPP_ENQUIRE_LINK_INTERVAL  30.0 
  46. #define SMPP_MAX_PENDING_SUBMITS    10 
  47. #define SMPP_RECONNECT_DELAY     10.0 
  48. #define SMPP_DEFAULT_VERSION        0x34
  49. #define SMPP_DEFAULT_PRIORITY       0
  50. #define SMPP_THROTTLING_SLEEP_TIME  15
  51. /*
  52.  * Some SMPP error messages we come across
  53.  */
  54. enum {
  55.     SMPP_ESME_RMSGQFUL   = 0x00000014,
  56.     SMPP_ESME_RTHROTTLED = 0x00000058
  57. } SMPP_ERROR_MESSAGES;
  58.  
  59.  
  60. /*********************************************************************** 
  61.  * Implementation of the actual SMPP protocol: reading and writing 
  62.  * PDUs in the correct order. 
  63.  */ 
  64.  
  65.  
  66. typedef struct { 
  67.     long transmitter; 
  68.     long receiver; 
  69.     List *msgs_to_send; 
  70.     Dict *sent_msgs; 
  71.     List *received_msgs; 
  72.     Counter *message_id_counter; 
  73.     Octstr *host; 
  74.     Octstr *system_type; 
  75.     Octstr *username; 
  76.     Octstr *password; 
  77.     Octstr *address_range; 
  78.     Octstr *our_host; 
  79.     Octstr *my_number; 
  80.     int source_addr_ton; 
  81.     int source_addr_npi; 
  82.     int dest_addr_ton; 
  83.     int dest_addr_npi;
  84.     int alt_dcs;
  85.     int transmit_port; 
  86.     int receive_port; 
  87.     int quitting; 
  88.     long enquire_link_interval;
  89.     long max_pending_submits;
  90.     long reconnect_delay;
  91.     int version;
  92.     int priority;       /* set default priority for messages */    
  93.     time_t throttling_err_time;
  94.     int smpp_msg_id_type;  /* msg id in C string, hex or decimal */
  95.     int autodetect_addr;
  96.     SMSCConn *conn; 
  97. } SMPP; 
  98.  
  99.  
  100. static SMPP *smpp_create(SMSCConn *conn, Octstr *host, int transmit_port,  
  101.                 int receive_port, Octstr *system_type,  
  102.                          Octstr *username, Octstr *password, 
  103.                 Octstr *address_range, Octstr *our_host,  
  104.                          int source_addr_ton, int source_addr_npi,  
  105.                          int dest_addr_ton, int dest_addr_npi, 
  106.                          int alt_dcs, int enquire_link_interval, 
  107.                          int max_pending_submits, int reconnect_delay,
  108.                          int version, int priority, Octstr *my_number,
  109.                          int smpp_msg_id_type, int autodetect_addr) 
  110.     SMPP *smpp; 
  111.      
  112.     smpp = gw_malloc(sizeof(*smpp)); 
  113.     smpp->transmitter = -1; 
  114.     smpp->receiver = -1; 
  115.     smpp->msgs_to_send = list_create(); 
  116.     smpp->sent_msgs = dict_create(16, NULL); 
  117.     list_add_producer(smpp->msgs_to_send); 
  118.     smpp->received_msgs = list_create(); 
  119.     smpp->message_id_counter = counter_create(); 
  120.     smpp->host = octstr_duplicate(host); 
  121.     smpp->system_type = octstr_duplicate(system_type); 
  122.     smpp->username = octstr_duplicate(username); 
  123.     smpp->password = octstr_duplicate(password); 
  124.     smpp->address_range = octstr_duplicate(address_range); 
  125.     smpp->source_addr_ton = source_addr_ton; 
  126.     smpp->source_addr_npi = source_addr_npi; 
  127.     smpp->dest_addr_ton = dest_addr_ton; 
  128.     smpp->dest_addr_npi = dest_addr_npi; 
  129.     smpp->alt_dcs = alt_dcs;
  130.     smpp->our_host = octstr_duplicate(our_host); 
  131.     smpp->my_number = octstr_duplicate(my_number); 
  132.     smpp->transmit_port = transmit_port; 
  133.     smpp->receive_port = receive_port; 
  134.     smpp->enquire_link_interval = enquire_link_interval;
  135.     smpp->max_pending_submits = max_pending_submits; 
  136.     smpp->reconnect_delay = reconnect_delay;
  137.     smpp->quitting = 0; 
  138.     smpp->version = version;
  139.     smpp->priority = priority;
  140.     smpp->conn = conn; 
  141.     smpp->throttling_err_time = 0; 
  142.     smpp->smpp_msg_id_type = smpp_msg_id_type;    
  143.     smpp->autodetect_addr = autodetect_addr;
  144.  
  145.     return smpp; 
  146.  
  147.  
  148. static void smpp_destroy(SMPP *smpp) 
  149.     if (smpp != NULL) { 
  150. list_destroy(smpp->msgs_to_send, msg_destroy_item); 
  151. dict_destroy(smpp->sent_msgs); 
  152. list_destroy(smpp->received_msgs, msg_destroy_item); 
  153. counter_destroy(smpp->message_id_counter); 
  154. octstr_destroy(smpp->host); 
  155. octstr_destroy(smpp->username); 
  156. octstr_destroy(smpp->password); 
  157. octstr_destroy(smpp->system_type); 
  158. octstr_destroy(smpp->address_range); 
  159. octstr_destroy(smpp->our_host); 
  160. gw_free(smpp); 
  161.     } 
  162.  
  163.  
  164. /* 
  165.  * Try to read an SMPP PDU from a Connection. Return -1 for error (caller 
  166.  * should close the connection), 0 for no PDU to ready yet, or 1 for PDU 
  167.  * read and unpacked. Return a pointer to the PDU in `*pdu'. Use `*len' 
  168.  * to store the length of the PDU to read (it may be possible to read the 
  169.  * length, but not the rest of the PDU - we need to remember the lenght 
  170.  * for the next call). `*len' should be zero at the first call. 
  171.  */ 
  172. static int read_pdu(SMPP *smpp, Connection *conn, long *len, SMPP_PDU **pdu) 
  173.     Octstr *os; 
  174.  
  175.     if (*len == 0) { 
  176.         *len = smpp_pdu_read_len(conn); 
  177.         if (*len == -1) { 
  178.             error(0, "SMPP[%s]: Server sent garbage, ignored.",
  179.                   octstr_get_cstr(smpp->conn->id)); 
  180.             return -1; 
  181.         } else if (*len == 0) { 
  182.             if (conn_eof(conn) || conn_read_error(conn)) 
  183.                 return -1; 
  184.             return 0; 
  185.         } 
  186.     } 
  187.      
  188.     os = smpp_pdu_read_data(conn, *len); 
  189.     if (os == NULL) { 
  190.         if (conn_eof(conn) || conn_read_error(conn)) 
  191.             return -1; 
  192.         return 0; 
  193.     } 
  194.     *len = 0; 
  195.      
  196.     *pdu = smpp_pdu_unpack(os); 
  197.     if (*pdu == NULL) { 
  198.         error(0, "SMPP[%s]: PDU unpacking failed.",
  199.               octstr_get_cstr(smpp->conn->id)); 
  200.         debug("bb.sms.smpp", 0, "SMPP[%s]: Failed PDU follows.",
  201.               octstr_get_cstr(smpp->conn->id)); 
  202.         octstr_dump(os, 0); 
  203.         octstr_destroy(os); 
  204.         return -1; 
  205.     } 
  206.      
  207.     octstr_destroy(os); 
  208.     return 1; 
  209.  
  210.  
  211. static Msg *pdu_to_msg(SMPP_PDU *pdu) 
  212.     Msg *msg; 
  213.  
  214.     gw_assert(pdu->type == deliver_sm); 
  215.      
  216.     msg = msg_create(sms); 
  217.     msg->sms.sender = pdu->u.deliver_sm.source_addr; 
  218.     pdu->u.deliver_sm.source_addr = NULL; 
  219.     msg->sms.receiver = pdu->u.deliver_sm.destination_addr; 
  220.     pdu->u.deliver_sm.destination_addr = NULL; 
  221.     msg->sms.msgdata = pdu->u.deliver_sm.short_message; 
  222.     pdu->u.deliver_sm.short_message = NULL; 
  223.     charset_gsm_to_latin1(msg->sms.msgdata); 
  224.     msg->sms.pid = pdu->u.deliver_sm.protocol_id; 
  225.     dcs_to_fields(&msg, pdu->u.deliver_sm.data_coding); 
  226.  
  227.     return msg; 
  228.  
  229.  
  230. static long smpp_status_to_smscconn_failure_reason(long status) 
  231.     switch(status) {
  232.         case SMPP_ESME_RMSGQFUL:
  233.             return SMSCCONN_FAILED_TEMPORARILY;
  234.             break;
  235.         case SMPP_ESME_RTHROTTLED:
  236.             return SMSCCONN_FAILED_TEMPORARILY; 
  237.             break;
  238.         default:
  239.             return SMSCCONN_FAILED_REJECTED; 
  240.     }
  241.  
  242.  
  243. static SMPP_PDU *msg_to_pdu(SMPP *smpp, Msg *msg) 
  244.     SMPP_PDU *pdu; 
  245.     Octstr *buffer;
  246.     Octstr *relation_UTC_time = NULL;
  247.     struct tm gmtime, localtime, tm;
  248.     int gwqdiff;
  249.     pdu = smpp_pdu_create(submit_sm,  
  250.                  counter_increase(smpp->message_id_counter)); 
  251.               
  252.     pdu->u.submit_sm.source_addr = octstr_duplicate(msg->sms.sender); 
  253.     pdu->u.submit_sm.destination_addr = octstr_duplicate(msg->sms.receiver); 
  254.   
  255.     /* Check for manual override of source ton and npi values */ 
  256.     if(smpp->source_addr_ton > -1 && smpp->source_addr_npi > -1) { 
  257.         pdu->u.submit_sm.source_addr_ton = smpp->source_addr_ton; 
  258.         pdu->u.submit_sm.source_addr_npi = smpp->source_addr_npi; 
  259.         debug("bb.sms.smpp", 0, "SMPP[%s]: Manually forced source addr ton = %d, source add npi = %d", 
  260.               octstr_get_cstr(smpp->conn->id), smpp->source_addr_ton, 
  261.               smpp->source_addr_npi); 
  262.     } else { 
  263.         /* setup default values */ 
  264.         pdu->u.submit_sm.source_addr_ton = GSM_ADDR_TON_NATIONAL; /* national */ 
  265.         pdu->u.submit_sm.source_addr_npi = GSM_ADDR_NPI_E164; /* ISDN number plan */ 
  266.     }
  267.     if (smpp->autodetect_addr) {
  268.         /* lets see if its international or alphanumeric sender */ 
  269.         if (octstr_get_char(pdu->u.submit_sm.source_addr,0) == '+') { 
  270.             if (!octstr_check_range(pdu->u.submit_sm.source_addr, 1, 256, gw_isdigit)) { 
  271.                 pdu->u.submit_sm.source_addr_ton = GSM_ADDR_TON_ALPHANUMERIC; /* alphanum */ 
  272.                 pdu->u.submit_sm.source_addr_npi = GSM_ADDR_NPI_UNKNOWN;    /* short code */ 
  273.             } else { 
  274.                /* numeric sender address with + in front -> international (remove the +) */ 
  275.                octstr_delete(pdu->u.submit_sm.source_addr, 0, 1); 
  276.                pdu->u.submit_sm.source_addr_ton = GSM_ADDR_TON_INTERNATIONAL; 
  277.          } 
  278.         } else { 
  279.             if (!octstr_check_range(pdu->u.submit_sm.source_addr,0, 256, gw_isdigit)) { 
  280.                 pdu->u.submit_sm.source_addr_ton = GSM_ADDR_TON_ALPHANUMERIC; 
  281.                 pdu->u.submit_sm.source_addr_npi = GSM_ADDR_NPI_UNKNOWN; 
  282.             } 
  283.         } 
  284.     } 
  285.  
  286.     /* Check for manual override of destination ton and npi values */ 
  287.     if (smpp->dest_addr_ton > -1 && smpp->dest_addr_npi > -1) { 
  288.         pdu->u.submit_sm.dest_addr_ton = smpp->dest_addr_ton; 
  289.         pdu->u.submit_sm.dest_addr_npi = smpp->dest_addr_npi; 
  290.         debug("bb.sms.smpp", 0, "SMPP[%s]: Manually forced dest addr ton = %d, source add npi = %d", 
  291.               octstr_get_cstr(smpp->conn->id), smpp->dest_addr_ton, 
  292.               smpp->dest_addr_npi); 
  293.     } else { 
  294.         pdu->u.submit_sm.dest_addr_ton = GSM_ADDR_TON_NATIONAL; /* national */ 
  295.         pdu->u.submit_sm.dest_addr_npi = GSM_ADDR_NPI_E164; /* ISDN number plan */ 
  296.     } 
  297.  
  298.     /* 
  299.      * if its a international number starting with +, lets remove the 
  300.      * '+' and set number type to international instead  
  301.      */ 
  302.     if (octstr_get_char(pdu->u.submit_sm.destination_addr,0) == '+') { 
  303.         octstr_delete(pdu->u.submit_sm.destination_addr, 0,1); 
  304.         pdu->u.submit_sm.dest_addr_ton = GSM_ADDR_TON_INTERNATIONAL; 
  305.     } 
  306.  
  307.     /* 
  308.      * set the data coding scheme (DCS) field 
  309.      * check if we have a forced value for this from the smsc-group.
  310.      */
  311.     pdu->u.submit_sm.data_coding = fields_to_dcs(msg, (msg->sms.alt_dcs ? 
  312.         2 - msg->sms.alt_dcs : smpp->alt_dcs));
  313.     /* set protocoll id */
  314.     if(msg->sms.pid) 
  315.         pdu->u.submit_sm.protocol_id = msg->sms.pid; 
  316.     /*
  317.      * set the esm_class field
  318.      * default is store and forward, plus udh and rpi if requested
  319.      */
  320.     pdu->u.submit_sm.esm_class = ESM_CLASS_SUBMIT_STORE_AND_FORWARD_MODE;
  321.     if (octstr_len(msg->sms.udhdata)) 
  322.         pdu->u.submit_sm.esm_class = pdu->u.submit_sm.esm_class |
  323.             ESM_CLASS_SUBMIT_UDH_INDICATOR;
  324.     if (msg->sms.rpi) 
  325.         pdu->u.submit_sm.esm_class = pdu->u.submit_sm.esm_class |
  326.             ESM_CLASS_SUBMIT_RPI;
  327.     /*
  328.      * set data segments
  329.      */
  330.     if (octstr_len(msg->sms.udhdata)) { 
  331.         pdu->u.submit_sm.short_message = 
  332.        octstr_format("%S%S", msg->sms.udhdata, msg->sms.msgdata); 
  333.     } else { 
  334.         pdu->u.submit_sm.short_message = octstr_duplicate(msg->sms.msgdata); 
  335.         if (pdu->u.submit_sm.data_coding == 0 ) /* no reencoding for unicode! */ 
  336.             charset_latin1_to_gsm(pdu->u.submit_sm.short_message);  
  337.     } 
  338.     /*
  339.      * check for validity and defered settings
  340.      */
  341.     if (msg->sms.validity || msg->sms.deferred) {
  342.         /* work out 1/4 hour difference between local time and UTC/GMT */
  343.         gmtime = gw_gmtime(time(NULL));
  344.         localtime = gw_localtime(time(NULL));
  345.         gwqdiff = ((localtime.tm_hour - gmtime.tm_hour) * 4)
  346.                   + ((localtime.tm_min - gmtime.tm_min) / 15);
  347.         
  348.         if (gwqdiff >= 0) {
  349.             relation_UTC_time = octstr_create("+");
  350.         } else {
  351.             relation_UTC_time = octstr_create("-");
  352.             gwqdiff *= -1;  /* make absolute */
  353.         }
  354.         if (msg->sms.validity) {
  355.             tm = gw_localtime(time(NULL) + msg->sms.validity * 60);
  356.             buffer = octstr_format("%02d%02d%02d%02d%02d%02d0%02d%1s",
  357.                     tm.tm_year % 100, tm.tm_mon + 1, tm.tm_mday,
  358.                     tm.tm_hour, tm.tm_min, tm.tm_sec,
  359.                     gwqdiff, octstr_get_cstr(relation_UTC_time));
  360.             pdu->u.submit_sm.validity_period = octstr_copy(buffer,0,16);
  361.             octstr_destroy(buffer);
  362.         }
  363.         if (msg->sms.deferred) {
  364.             tm = gw_localtime(time(NULL) + msg->sms.deferred * 60);
  365.             buffer = octstr_format("%02d%02d%02d%02d%02d%02d0%02d%1s",
  366.                     tm.tm_year % 100, tm.tm_mon + 1, tm.tm_mday,
  367.                     tm.tm_hour, tm.tm_min, tm.tm_sec,
  368.                     gwqdiff, octstr_get_cstr(relation_UTC_time));
  369.             pdu->u.submit_sm.schedule_delivery_time = octstr_copy(buffer,0,16);
  370.             octstr_destroy(buffer);
  371.         }
  372.     }
  373.     /* ask for the delivery reports if needed */ 
  374.     if (msg->sms.dlr_mask & (DLR_SUCCESS|DLR_FAIL)) 
  375.         pdu->u.submit_sm.registered_delivery = 1;  
  376.     octstr_destroy(relation_UTC_time);
  377.     /* set priority */
  378.     if (smpp->priority >= 0 && smpp->priority <= 5) {
  379.         pdu->u.submit_sm.priority_flag = smpp->priority;       
  380.     } else {      
  381.         /* default priority is 0 */         
  382.         pdu->u.submit_sm.priority_flag = 0;         
  383.     }              
  384.     return pdu; 
  385.  
  386.  
  387. static void send_enquire_link(SMPP *smpp, Connection *conn, long *last_sent) 
  388.     SMPP_PDU *pdu; 
  389.     Octstr *os; 
  390.  
  391.     if (date_universal_now() - *last_sent < smpp->enquire_link_interval)
  392.         return; 
  393.     *last_sent = date_universal_now(); 
  394.  
  395.     pdu = smpp_pdu_create(enquire_link, counter_increase(smpp->message_id_counter)); 
  396.     dump_pdu("Sending enquire link:", smpp->conn->id, pdu); 
  397.     os = smpp_pdu_pack(pdu); 
  398.     if (os)
  399. conn_write(conn, os); /* Write errors checked by caller. */ 
  400.     octstr_destroy(os); 
  401.     smpp_pdu_destroy(pdu); 
  402.  
  403.  
  404. static void send_unbind(SMPP *smpp, Connection *conn)
  405. {
  406.     SMPP_PDU *pdu;
  407.     Octstr *os;
  408.     pdu = smpp_pdu_create(unbind, counter_increase(smpp->message_id_counter));
  409.     dump_pdu("Sending unbind:", smpp->conn->id, pdu);
  410.     os = smpp_pdu_pack(pdu);
  411.     conn_write(conn, os);
  412.     octstr_destroy(os);
  413.     smpp_pdu_destroy(pdu);
  414. }
  415. static int send_pdu(Connection *conn, Octstr *id, SMPP_PDU *pdu) 
  416.     Octstr *os; 
  417.     int ret; 
  418.      
  419.     dump_pdu("Sending PDU:", id, pdu); 
  420.     os = smpp_pdu_pack(pdu); 
  421.     if (os)
  422.         ret = conn_write(conn, os);   /* Caller checks for write errors later */ 
  423.     else
  424. ret = -1;
  425.     octstr_destroy(os); 
  426.     return ret; 
  427.  
  428.  
  429. static void send_messages(SMPP *smpp, Connection *conn, long *pending_submits) 
  430.     Msg *msg; 
  431.     SMPP_PDU *pdu; 
  432.     Octstr *os; 
  433.  
  434.     if (*pending_submits == -1) 
  435.         return; 
  436.  
  437.     while (*pending_submits < smpp->max_pending_submits) {
  438.      /* Get next message, quit if none to be sent */ 
  439.      msg = list_extract_first(smpp->msgs_to_send); 
  440.         if (msg == NULL) 
  441.             break; 
  442.      
  443.         /* Send PDU, record it as waiting for ack from SMS center */ 
  444.         pdu = msg_to_pdu(smpp, msg); 
  445.         os = octstr_format("%ld", pdu->u.submit_sm.sequence_number); 
  446.         dict_put(smpp->sent_msgs, os, msg); 
  447.         octstr_destroy(os); 
  448.         send_pdu(conn, smpp->conn->id, pdu); 
  449.         smpp_pdu_destroy(pdu); 
  450.  
  451.         ++(*pending_submits); 
  452.     } 
  453.  
  454.  
  455. /* 
  456.  * Open transmission connection to SMS center. Return NULL for error,  
  457.  * open Connection for OK. Caller must set smpp->conn->status correctly  
  458.  * before calling this. 
  459.  */ 
  460. static Connection *open_transmitter(SMPP *smpp) 
  461.     SMPP_PDU *bind; 
  462.     Connection *conn; 
  463.  
  464.     conn = conn_open_tcp(smpp->host, smpp->transmit_port, smpp->our_host ); 
  465.     if (conn == NULL) { 
  466.         error(0, "SMPP[%s]: Couldn't connect to server.",
  467.               octstr_get_cstr(smpp->conn->id)); 
  468.         return NULL; 
  469.     } 
  470.      
  471.     bind = smpp_pdu_create(bind_transmitter, 
  472.                 counter_increase(smpp->message_id_counter)); 
  473.     bind->u.bind_transmitter.system_id = octstr_duplicate(smpp->username); 
  474.     bind->u.bind_transmitter.password = octstr_duplicate(smpp->password); 
  475.     if (smpp->system_type == NULL) 
  476.         bind->u.bind_transmitter.system_type = octstr_create("VMA"); 
  477.     else 
  478.         bind->u.bind_transmitter.system_type =  
  479.        octstr_duplicate(smpp->system_type); 
  480.     bind->u.bind_transmitter.interface_version = smpp->version;
  481.     bind->u.bind_transmitter.address_range =  
  482.      octstr_duplicate(smpp->address_range); 
  483.     send_pdu(conn, smpp->conn->id, bind); 
  484.     smpp_pdu_destroy(bind); 
  485.  
  486.     return conn; 
  487.  
  488.  
  489. /* 
  490.  * Open transceiver connection to SMS center. Return NULL for error, 
  491.  * open Connection for OK. Caller must set smpp->conn->status correctly 
  492.  * before calling this. 
  493.  */ 
  494. static Connection *open_transceiver(SMPP *smpp) 
  495.     SMPP_PDU *bind; 
  496.     Connection *conn; 
  497.      
  498.     conn = conn_open_tcp(smpp->host, smpp->transmit_port, smpp->our_host ); 
  499.     if (conn == NULL) {  
  500.        error(0, "SMPP[%s]: Couldn't connect to server.",
  501.              octstr_get_cstr(smpp->conn->id)); 
  502.        return NULL; 
  503.     } 
  504.  
  505.     bind = smpp_pdu_create(bind_transceiver, 
  506.                            counter_increase(smpp->message_id_counter)); 
  507.     bind->u.bind_transmitter.system_id = octstr_duplicate(smpp->username); 
  508.     bind->u.bind_transmitter.password = octstr_duplicate(smpp->password); 
  509.     if (smpp->system_type == NULL) 
  510.         bind->u.bind_transmitter.system_type = octstr_create("VMA"); 
  511.     else    
  512.         bind->u.bind_transmitter.system_type = octstr_duplicate(smpp->system_type); 
  513.     bind->u.bind_transmitter.interface_version = smpp->version;
  514.     bind->u.bind_transmitter.address_range = octstr_duplicate(smpp->address_range); 
  515.     send_pdu(conn, smpp->conn->id, bind); 
  516.     smpp_pdu_destroy(bind); 
  517.  
  518.     return conn; 
  519.  
  520.  
  521. /* 
  522.  * Open reception connection to SMS center. Return NULL for error,  
  523.  * open Connection for OK. Caller must set smpp->conn->status correctly  
  524.  * before calling this. 
  525.  */ 
  526. static Connection *open_receiver(SMPP *smpp) 
  527.     SMPP_PDU *bind; 
  528.     Connection *conn; 
  529.  
  530.     conn = conn_open_tcp(smpp->host, smpp->receive_port, smpp->our_host ); 
  531.     if (conn == NULL) { 
  532.         error(0, "SMPP[%s]: Couldn't connect to server.",
  533.               octstr_get_cstr(smpp->conn->id)); 
  534.         return NULL; 
  535.     } 
  536.      
  537.     bind = smpp_pdu_create(bind_receiver, 
  538.                 counter_increase(smpp->message_id_counter)); 
  539.     bind->u.bind_receiver.system_id = octstr_duplicate(smpp->username); 
  540.     bind->u.bind_receiver.password = octstr_duplicate(smpp->password); 
  541.     if (smpp->system_type == NULL) 
  542.         bind->u.bind_receiver.system_type = octstr_create("VMA"); 
  543.     else 
  544.         bind->u.bind_receiver.system_type =  
  545.             octstr_duplicate(smpp->system_type); 
  546.     bind->u.bind_receiver.interface_version = smpp->version;
  547.     bind->u.bind_receiver.address_range =  
  548.         octstr_duplicate(smpp->address_range); 
  549.     send_pdu(conn, smpp->conn->id, bind); 
  550.     smpp_pdu_destroy(bind); 
  551.  
  552.     return conn; 
  553.  
  554.  
  555. static void handle_pdu(SMPP *smpp, Connection *conn, SMPP_PDU *pdu,  
  556.                  long *pending_submits) 
  557.     SMPP_PDU *resp; 
  558.     Octstr *os; 
  559.     Msg *msg, *dlrmsg=NULL; 
  560.     long reason; 
  561.     resp = NULL; 
  562.  
  563.     switch (pdu->type) { 
  564.         case deliver_sm: 
  565.         /* XXX UDH */ 
  566.             /* 
  567.              * bb_smscconn_receive can fail, but we ignore that since we 
  568.              * have no way to usefull tell the SMS center about this 
  569.              * (no suitable error code for the deliver_sm_resp is defined) 
  570.              */ 
  571.             /* got a deliver ack (DLR)? */ 
  572.             if ((pdu->u.deliver_sm.esm_class == 0x02 || 
  573.                  pdu->u.deliver_sm.esm_class == 0x04)) { 
  574.                 Octstr *respstr;      
  575.                 Octstr *msgid = NULL; 
  576.                 Octstr *stat = NULL; 
  577.                 int dlrstat; 
  578.                 long curr = 0, vpos = 0; 
  579.        
  580.                 debug("bb.sms.smpp",0,"SMPP[%s] handle_pdu, got DLR",
  581.                       octstr_get_cstr(smpp->conn->id)); 
  582.        
  583.                 respstr = pdu->u.deliver_sm.short_message; 
  584.    
  585.                 /* get server message id */ 
  586.                 if ((curr = octstr_search(respstr, octstr_imm("id:"), 0)) != -1) {    
  587.                     vpos = octstr_search_char(respstr, ' ', curr); 
  588.                     if ((vpos-curr >0) && (vpos != -1)) 
  589.                         msgid = octstr_copy(respstr, curr+3, vpos-curr-3); 
  590.                 } else { 
  591.                     msgid = NULL; 
  592.                 }
  593.     
  594.                 /* get err & status code */ 
  595.                 if ((curr = octstr_search(respstr, octstr_imm("stat:"), 0)) != -1) {   
  596.                     vpos = octstr_search_char(respstr, ' ', curr); 
  597.                     if ((vpos-curr >0) && (vpos != -1)) 
  598.                         stat = octstr_copy(respstr, curr+5, vpos-curr-5); 
  599.                 } else { 
  600.                     stat = NULL; 
  601.                 }
  602.  
  603.                 /* 
  604.                  * we get the following status: 
  605.                  * DELIVRD, ACCEPTD, EXPIRED, DELETED, UNDELIV, UNKNOWN, REJECTD 
  606.                  */ 
  607.    
  608.                 if ((stat != NULL) && ((octstr_compare(stat, octstr_imm("DELIVRD")) == 0) || 
  609.                     (octstr_compare(stat, octstr_imm("ACCEPTD")) == 0))) 
  610.                     dlrstat = DLR_SUCCESS; 
  611.                 else 
  612.                     dlrstat = DLR_FAIL; 
  613.    
  614.                 if (msgid != NULL) { 
  615.                     Octstr *tmp;
  616.                     
  617.                     /* 
  618.                      * Obey which SMPP msg_id type this SMSC is using, where we 
  619.                      * have the following semantics for the variable smpp_msg_id:
  620.                      *
  621.                      * bit 1: type for submit_sm_resp, bit 2: type for deliver_sm 
  622.                      *
  623.                      * if bit is set value is hex otherwise dec
  624.                      *
  625.                      * 0x00 deliver_sm dec, submit_sm_resp dec
  626.                      * 0x01 deliver_sm dec, submit_sm_resp hex
  627.                      * 0x02 deliver_sm hex, submit_sm_resp dec
  628.                      * 0x03 deliver_sm hex, submit_sm_resp hex 
  629.                      *
  630.                      * Default behaviour is SMPP spec compliant, which means
  631.                      * msg_ids should be C strings and hence non modified.
  632.                      */
  633.                     if (smpp->smpp_msg_id_type == -1) {
  634.                         /* the default, C string */
  635.                         tmp = octstr_duplicate(msgid);
  636.                     } else {
  637.                         if (smpp->smpp_msg_id_type & 0x02) {                         
  638.                             tmp = octstr_format("%ld", strtol(octstr_get_cstr(msgid), NULL, 16));
  639.                         } else {
  640.                             tmp = octstr_format("%ld", strtol(octstr_get_cstr(msgid), NULL, 10));
  641.                         }
  642.                     }
  643.  
  644.                     dlrmsg = dlr_find(octstr_get_cstr(smpp->conn->id),  
  645.                                       octstr_get_cstr(tmp), /* smsc message id */ 
  646.                                       octstr_get_cstr(pdu->u.deliver_sm.destination_addr), /* destination */ 
  647.                                       dlrstat);
  648.                     octstr_destroy(tmp); 
  649.                 } 
  650.                 if (dlrmsg != NULL) {
  651.                     /* 
  652.                      * we found the delivery report in our storage, so recode the 
  653.                      * message structure. 
  654.                      * The DLR trigger URL is indicated by msg->sms.dlr_url. 
  655.                      */
  656.                     dlrmsg->sms.msgdata = octstr_duplicate(respstr);
  657.                     dlrmsg->sms.sms_type = report;
  658.                     bb_smscconn_receive(smpp->conn, dlrmsg);
  659.                 } else { 
  660.                     error(0,"SMPP[%s]: got DLR but could not find message or was not interested in it",
  661.                           octstr_get_cstr(smpp->conn->id));      
  662.                 }  
  663.                 resp = smpp_pdu_create(deliver_sm_resp,  
  664.                 pdu->u.deliver_sm.sequence_number); 
  665.           
  666.                 if (msgid != NULL) 
  667.                     octstr_destroy(msgid);      
  668.                 if (stat != NULL) 
  669.                     octstr_destroy(stat); 
  670.        
  671.             } else /* MO-SMS */
  672.             {
  673.                 /* ensure the smsc-id is set */ 
  674.                 msg = pdu_to_msg(pdu); 
  675.  
  676.                 /* Replace MO destination number with my-number */ 
  677.                 if (octstr_len(smpp->my_number)) { 
  678.                     octstr_destroy(msg->sms.receiver); 
  679.                     msg->sms.receiver = octstr_duplicate(smpp->my_number); 
  680.                 } 
  681.                 time(&msg->sms.time); 
  682.                 msg->sms.smsc_id = octstr_duplicate(smpp->conn->id); 
  683.                 (void) bb_smscconn_receive(smpp->conn, msg); 
  684.                 resp = smpp_pdu_create(deliver_sm_resp,  
  685.                             pdu->u.deliver_sm.sequence_number); 
  686.             } 
  687.             break; 
  688.  
  689.         case enquire_link: 
  690.             resp = smpp_pdu_create(enquire_link_resp,  
  691.                         pdu->u.enquire_link.sequence_number); 
  692.             break; 
  693.  
  694.         case enquire_link_resp: 
  695.             break; 
  696.  
  697.         case submit_sm_resp: 
  698.             os = octstr_format("%ld", pdu->u.submit_sm.sequence_number); 
  699.             msg = dict_remove(smpp->sent_msgs, os); 
  700.             octstr_destroy(os); 
  701.             if (msg == NULL) { 
  702.                 warning(0, "SMPP[%s]: SMSC sent submit_sm_resp " 
  703.                         "with wrong sequence number 0x%08lx",
  704.                         octstr_get_cstr(smpp->conn->id),
  705.                         pdu->u.submit_sm.sequence_number); 
  706.             } else if (pdu->u.submit_sm_resp.command_status != 0) { 
  707.                 error(0, "SMPP[%s]: SMSC returned error code 0x%08lx " 
  708.                       "in response to submit_sm.",
  709.                       octstr_get_cstr(smpp->conn->id),
  710.                       pdu->u.submit_sm_resp.command_status); 
  711.                 reason = smpp_status_to_smscconn_failure_reason( 
  712.                             pdu->u.submit_sm.command_status); 
  713.                 /* 
  714.                  * check to see if we got a "throttling error", in which case we'll just
  715.                  * sleep for a while 
  716.                  */
  717.                 if (pdu->u.submit_sm.command_status == SMPP_ESME_RTHROTTLED)
  718.                     time(&(smpp->throttling_err_time));
  719.                 else
  720.                     smpp->throttling_err_time = 0;
  721.  
  722.                 /* gen DLR_SMSC_FAIL */  
  723.                 if (reason == SMSCCONN_FAILED_REJECTED &&
  724.                     (msg->sms.dlr_mask & (DLR_SMSC_FAIL|DLR_FAIL))) { 
  725.                     Octstr *reply; 
  726.    
  727.                     reply = octstr_format("0x%08lx", 
  728.                                 pdu->u.submit_sm_resp.command_status); 
  729.                     /* generate DLR */ 
  730.                     info(0,"SMPP[%s]: creating DLR message",
  731.                          octstr_get_cstr(smpp->conn->id)); 
  732.                     dlrmsg = msg_create(sms); 
  733.                     dlrmsg->sms.service = octstr_duplicate(msg->sms.service); 
  734.                     dlrmsg->sms.dlr_mask = DLR_SMSC_FAIL; 
  735.                     dlrmsg->sms.sms_type = report; 
  736.                     dlrmsg->sms.smsc_id = octstr_duplicate(smpp->conn->id); 
  737.                     dlrmsg->sms.sender = octstr_duplicate(msg->sms.receiver); 
  738.                     dlrmsg->sms.receiver = octstr_create("000"); 
  739.                     dlrmsg->sms.dlr_url = octstr_duplicate(msg->sms.dlr_url);
  740.                     dlrmsg->sms.msgdata = reply;
  741.                     time(&dlrmsg->sms.time); 
  742.    
  743.                     info(0,"SMPP[%s]: DLR = %s", octstr_get_cstr(smpp->conn->id),
  744.                          octstr_get_cstr(dlrmsg->sms.dlr_url)); 
  745.                     bb_smscconn_receive(smpp->conn, dlrmsg); 
  746.                 } 
  747.                 bb_smscconn_send_failed(smpp->conn, msg, reason);
  748.                 --(*pending_submits); 
  749.             } else {  
  750.                 Octstr *tmp; 
  751.  
  752.                 /* check if msg_id is C string, decimal or hex for this SMSC */
  753.                 if (smpp->smpp_msg_id_type == -1) {
  754.                     /* the default, C string */
  755.                     tmp = octstr_duplicate(pdu->u.submit_sm_resp.message_id);
  756.                 } else {
  757.                     if (smpp->smpp_msg_id_type & 0x01) {   
  758.                         tmp = octstr_format("%ld", strtol(  /* hex */
  759.                             octstr_get_cstr(pdu->u.submit_sm_resp.message_id), NULL, 16));
  760.                     } else {
  761.                         tmp = octstr_format("%ld", strtol(  /* decimal */
  762.                             octstr_get_cstr(pdu->u.submit_sm_resp.message_id), NULL, 10));
  763.                     }
  764.                 }
  765.  
  766.                 /* SMSC ACK.. now we have the message id. */ 
  767.    
  768.                 if (msg->sms.dlr_mask & (DLR_SMSC_SUCCESS|DLR_SUCCESS|DLR_FAIL|DLR_BUFFERED)) 
  769.                     dlr_add(octstr_get_cstr(smpp->conn->id), 
  770.                             octstr_get_cstr(tmp), 
  771.                             octstr_get_cstr(msg->sms.sender), 
  772.                             octstr_get_cstr(msg->sms.receiver), 
  773.                             octstr_get_cstr(msg->sms.service), 
  774.                             octstr_get_cstr(msg->sms.dlr_url), 
  775.                             msg->sms.dlr_mask); 
  776.   
  777.                 /* gen DLR_SMSC_SUCCESS */ 
  778.                 if (msg->sms.dlr_mask & DLR_SMSC_SUCCESS) { 
  779.                     Octstr *reply; 
  780.    
  781.                     reply = octstr_format("0x%08lx", pdu->u.submit_sm_resp.command_status); 
  782.   
  783.                     dlrmsg = dlr_find(octstr_get_cstr(smpp->conn->id),  
  784.                                       octstr_get_cstr(tmp), /* smsc message id */ 
  785.                                       octstr_get_cstr(msg->sms.receiver), /* destination */ 
  786.                                       (DLR_SMSC_SUCCESS|((msg->sms.dlr_mask & (DLR_SUCCESS|DLR_FAIL)) ? DLR_BUFFERED : 0))); 
  787.    
  788.                     if (dlrmsg != NULL) { 
  789.                         octstr_append_char(reply, '/'); 
  790.                         dlrmsg->sms.msgdata = octstr_duplicate(reply);
  791.                         octstr_destroy(reply); 
  792.                         bb_smscconn_receive(smpp->conn, dlrmsg); 
  793.                     } else 
  794.                         error(0,"SMPP[%s]: Got SMSC_ACK but could not find message",
  795.                               octstr_get_cstr(smpp->conn->id)); 
  796.                 } 
  797.                 octstr_destroy(tmp); 
  798.                 bb_smscconn_sent(smpp->conn, msg); 
  799.                 --(*pending_submits); 
  800.             } /* end if for SMSC ACK */ 
  801.             break; 
  802.  
  803.         case bind_transmitter_resp: 
  804.             if (pdu->u.bind_transmitter_resp.command_status != 0) { 
  805.                 error(0, "SMPP[%s]: SMSC rejected login to transmit, " 
  806.               "code 0x%08lx.",
  807.                       octstr_get_cstr(smpp->conn->id),
  808.                       pdu->u.bind_transmitter_resp.command_status); 
  809.             } else { 
  810.                 *pending_submits = 0; 
  811.                 smpp->conn->status = SMSCCONN_ACTIVE; 
  812.                 smpp->conn->connect_time = time(NULL); 
  813.                 bb_smscconn_connected(smpp->conn); 
  814.             } 
  815.             break; 
  816.  
  817.         case bind_transceiver_resp: 
  818.             if (pdu->u.bind_transceiver_resp.command_status != 0) { 
  819.                 error(0, "SMPP[%s]: SMSC rejected login to transmit, " 
  820.                       "code 0x%08lx.",
  821.                       octstr_get_cstr(smpp->conn->id),
  822.                       pdu->u.bind_transceiver_resp.command_status); 
  823.             } else { 
  824.                 *pending_submits = 0; 
  825.                 smpp->conn->status = SMSCCONN_ACTIVE; 
  826.                 smpp->conn->connect_time = time(NULL); 
  827.                 bb_smscconn_connected(smpp->conn); 
  828.             } 
  829.             break; 
  830.  
  831.         case bind_receiver_resp: 
  832.             if (pdu->u.bind_receiver_resp.command_status != 0) { 
  833.                 error(0, "SMPP[%s]: SMSC rejected login to receive, " 
  834.                       "code 0x%08lx.", 
  835.                       octstr_get_cstr(smpp->conn->id),
  836.                       pdu->u.bind_receiver_resp.command_status); 
  837.             } else { 
  838.                 /* set only resceive status if no transmitt is bind */
  839.                 if (smpp->conn->status != SMSCCONN_ACTIVE) {
  840.                     smpp->conn->status = SMSCCONN_ACTIVE_RECV; 
  841.                     smpp->conn->connect_time = time(NULL);
  842.                 }
  843.             } 
  844.             break; 
  845.  
  846.         case unbind:
  847.             break;          
  848.  
  849.         case unbind_resp:       
  850.             break;
  851.         default: 
  852.             error(0, "SMPP[%s]: Unknown PDU type 0x%08lx, ignored.",
  853.                   octstr_get_cstr(smpp->conn->id), pdu->type); 
  854.             break; 
  855.     } 
  856.      
  857.     if (resp != NULL) { 
  858.      send_pdu(conn, smpp->conn->id, resp); 
  859.         smpp_pdu_destroy(resp); 
  860.     } 
  861.  
  862.  
  863. struct io_arg { 
  864.     SMPP *smpp; 
  865.     int transmitter; 
  866. }; 
  867.  
  868.  
  869. static struct io_arg *io_arg_create(SMPP *smpp, int transmitter) 
  870.     struct io_arg *io_arg; 
  871.      
  872.     io_arg = gw_malloc(sizeof(*io_arg)); 
  873.     io_arg->smpp = smpp; 
  874.     io_arg->transmitter = transmitter; 
  875.     return io_arg; 
  876.  
  877.  
  878.  
  879. /* 
  880.  * This is the main function for the background thread for doing I/O on 
  881.  * one SMPP connection (the one for transmitting or receiving messages). 
  882.  * It makes the initial connection to the SMPP server and re-connects 
  883.  * if there are I/O errors or other errors that require it. 
  884.  */ 
  885. static void io_thread(void *arg) 
  886.     SMPP *smpp; 
  887.     struct io_arg *io_arg; 
  888.     int transmitter; 
  889.     Connection *conn; 
  890.     int ret; 
  891.     long last_enquire_sent; 
  892.     long pending_submits; 
  893.     long len; 
  894.     SMPP_PDU *pdu; 
  895.     double timeout; 
  896.  
  897.     io_arg = arg; 
  898.     smpp = io_arg->smpp; 
  899.     transmitter = io_arg->transmitter; 
  900.     gw_free(io_arg); 
  901.  
  902.     conn = NULL; 
  903.     while (!smpp->quitting) { 
  904.         if (transmitter == 1) 
  905.             conn = open_transmitter(smpp); 
  906.         else if (transmitter == 2) 
  907.             conn = open_transceiver(smpp); 
  908.         else 
  909.             conn = open_receiver(smpp); 
  910.         if (conn == NULL) { 
  911.             error(0, "SMPP[%s]: Couldn't connect to SMS center (retrying in %ld seconds).",
  912.                   octstr_get_cstr(smpp->conn->id), smpp->reconnect_delay);
  913.             gwthread_sleep(smpp->reconnect_delay);
  914.             smpp->conn->status = SMSCCONN_RECONNECTING; 
  915.             continue; 
  916.         } 
  917.  
  918.         last_enquire_sent = date_universal_now(); 
  919.         pending_submits = -1; 
  920.         len = 0; 
  921.         for (;;) { 
  922.             timeout = last_enquire_sent + smpp->enquire_link_interval
  923.                         - date_universal_now(); 
  924.             /* unbind */
  925.             if (smpp->quitting) {
  926.                 send_unbind(smpp, conn);
  927.                 while ((ret = read_pdu(smpp, conn, &len, &pdu)) == 1) {
  928.                     dump_pdu("Got PDU:", smpp->conn->id, pdu);
  929.                     handle_pdu(smpp, conn, pdu, &pending_submits);
  930.                     smpp_pdu_destroy(pdu);
  931.                 }
  932.                 debug("bb.sms.smpp", 0, "SMPP[%s]: %s: break and shutting down",
  933.                       octstr_get_cstr(smpp->conn->id), __PRETTY_FUNCTION__);
  934.             }
  935.             if (smpp->quitting || conn_wait(conn, timeout) == -1) 
  936.                 break; 
  937.  
  938.             send_enquire_link(smpp, conn, &last_enquire_sent); 
  939.      
  940.             while ((ret = read_pdu(smpp, conn, &len, &pdu)) == 1) { 
  941.                 /* Deal with the PDU we just got */ 
  942.                 dump_pdu("Got PDU:", smpp->conn->id, pdu); 
  943.                 handle_pdu(smpp, conn, pdu, &pending_submits); 
  944.                 smpp_pdu_destroy(pdu); 
  945.  
  946.                 /* Make sure we send enquire_link even if we read a lot */ 
  947.                 send_enquire_link(smpp, conn, &last_enquire_sent); 
  948.  
  949.                 /* Make sure we send even if we read a lot */ 
  950.                 if (transmitter &&
  951.                     (!smpp->throttling_err_time || 
  952.                     ((time(NULL) - smpp->throttling_err_time) > SMPP_THROTTLING_SLEEP_TIME 
  953.                         && !(smpp->throttling_err_time = 0)))
  954.                     )
  955.                     send_messages(smpp, conn, &pending_submits); 
  956.             } 
  957.      
  958.             if (ret == -1) { 
  959.                 error(0, "SMPP[%s]: I/O error or other error. Re-connecting.",
  960.                       octstr_get_cstr(smpp->conn->id)); 
  961.                 break; 
  962.             } 
  963.      
  964.             if (transmitter &&
  965.                 (!smpp->throttling_err_time || 
  966.                 ((time(NULL) - smpp->throttling_err_time) > SMPP_THROTTLING_SLEEP_TIME 
  967.                     && !(smpp->throttling_err_time = 0)))
  968.                 )
  969.                 send_messages(smpp, conn, &pending_submits); 
  970.         } 
  971.  
  972.         conn_destroy(conn); 
  973.         conn = NULL; 
  974.     } 
  975.     conn_destroy(conn); 
  976.      
  977.  
  978. /*********************************************************************** 
  979.  * Functions called by smscconn.c via the SMSCConn function pointers. 
  980.  */ 
  981.   
  982.  
  983. static long queued_cb(SMSCConn *conn) 
  984.     SMPP *smpp; 
  985.  
  986.     smpp = conn->data;
  987.     conn->load = (smpp ? (conn->status != SMSCCONN_DEAD ? 
  988.                   list_len(smpp->msgs_to_send) : 0) : 0);
  989.     return conn->load; 
  990.  
  991.  
  992. static int send_msg_cb(SMSCConn *conn, Msg *msg) 
  993.     SMPP *smpp; 
  994.      
  995.     smpp = conn->data; 
  996.     list_produce(smpp->msgs_to_send, msg_duplicate(msg)); 
  997.     gwthread_wakeup(smpp->transmitter); 
  998.     return 0; 
  999.  
  1000.  
  1001. static int shutdown_cb(SMSCConn *conn, int finish_sending) 
  1002.     SMPP *smpp; 
  1003.  
  1004.     debug("bb.smpp", 0, "Shutting down SMSCConn %s (%s)", 
  1005.           octstr_get_cstr(conn->name), 
  1006.           finish_sending ? "slow" : "instant"); 
  1007.  
  1008.     conn->why_killed = SMSCCONN_KILLED_SHUTDOWN; 
  1009.  
  1010.     /* XXX implement finish_sending */ 
  1011.  
  1012.     smpp = conn->data; 
  1013.     smpp->quitting = 1; 
  1014.     gwthread_wakeup(smpp->transmitter); 
  1015.     gwthread_wakeup(smpp->receiver); 
  1016.     gwthread_join(smpp->transmitter); 
  1017.     gwthread_join(smpp->receiver); 
  1018.     smpp_destroy(smpp); 
  1019.      
  1020.     debug("bb.smpp", 0, "SMSCConn %s shut down.",  
  1021.           octstr_get_cstr(conn->name)); 
  1022.     conn->status = SMSCCONN_DEAD; 
  1023.     bb_smscconn_killed(); 
  1024.     return 0; 
  1025.  
  1026.  
  1027. /*********************************************************************** 
  1028.  * Public interface. This version is suitable for the Kannel bearerbox 
  1029.  * SMSCConn interface. 
  1030.  */ 
  1031.  
  1032.  
  1033. int smsc_smpp_create(SMSCConn *conn, CfgGroup *grp) 
  1034.     Octstr *host; 
  1035.     long port; 
  1036.     long receive_port; 
  1037.     Octstr *username; 
  1038.     Octstr *password; 
  1039.     Octstr *system_id; 
  1040.     Octstr *system_type; 
  1041.     Octstr *address_range; 
  1042.     long source_addr_ton; 
  1043.     long source_addr_npi; 
  1044.     long dest_addr_ton; 
  1045.     long dest_addr_npi; 
  1046.     Octstr *our_host; 
  1047.     Octstr *my_number; 
  1048.     SMPP *smpp; 
  1049.     int ok; 
  1050.     int transceiver_mode; 
  1051.     Octstr *smsc_id; 
  1052.     int alt_dcs;
  1053.     long enquire_link_interval;
  1054.     long max_pending_submits;
  1055.     long reconnect_delay;
  1056.     long version;
  1057.     long priority;
  1058.     long smpp_msg_id_type;
  1059.     int autodetect_addr;
  1060.  
  1061.     my_number = NULL; 
  1062.     transceiver_mode = 0;
  1063.     alt_dcs = 0;
  1064.     autodetect_addr = 0;
  1065.  
  1066.     host = cfg_get(grp, octstr_imm("host")); 
  1067.     if (cfg_get_integer(&port, grp, octstr_imm("port")) == -1) 
  1068.         port = 0; 
  1069.     if (cfg_get_integer(&receive_port, grp, octstr_imm("receive-port")) == -1) 
  1070.         receive_port = 0; 
  1071.     cfg_get_bool(&transceiver_mode, grp, octstr_imm("transceiver-mode")); 
  1072.     cfg_get_bool(&alt_dcs, grp, octstr_imm("alt-dcs")); 
  1073.     username = cfg_get(grp, octstr_imm("smsc-username")); 
  1074.     password = cfg_get(grp, octstr_imm("smsc-password")); 
  1075.     system_type = cfg_get(grp, octstr_imm("system-type")); 
  1076.     address_range = cfg_get(grp, octstr_imm("address-range")); 
  1077.     our_host = cfg_get(grp, octstr_imm("our-host")); 
  1078.     my_number = cfg_get(grp, octstr_imm("my-number")); 
  1079.      
  1080.     system_id = cfg_get(grp, octstr_imm("system-id")); 
  1081.     if (system_id != NULL) { 
  1082.         warning(0, "SMPP: obsolete system-id variable is set, " 
  1083.         "use smsc-username instead."); 
  1084.         if (username == NULL) { 
  1085.             warning(0, "SMPP: smsc-username not set, using system-id instead"); 
  1086.             username = system_id; 
  1087.         } else 
  1088.             octstr_destroy(system_id); 
  1089.     } 
  1090.     /* 
  1091.      * check if timing values have been configured, otherwise
  1092.      * use the predefined default values.
  1093.      */
  1094.     if (cfg_get_integer(&enquire_link_interval, grp, 
  1095.                         octstr_imm("enquire-link-interval")) == -1)
  1096.         enquire_link_interval = SMPP_ENQUIRE_LINK_INTERVAL;
  1097.     if (cfg_get_integer(&max_pending_submits, grp, 
  1098.                         octstr_imm("max-pending-submits")) == -1)
  1099.         max_pending_submits = SMPP_MAX_PENDING_SUBMITS;
  1100.     if (cfg_get_integer(&reconnect_delay, grp, 
  1101.                         octstr_imm("reconnect-delay")) == -1)
  1102.         reconnect_delay = SMPP_RECONNECT_DELAY;
  1103.  
  1104.     /* Check that config is OK */ 
  1105.     ok = 1; 
  1106.     if (host == NULL) { 
  1107.         error(0,"SMPP: Configuration file doesn't specify host"); 
  1108.         ok = 0; 
  1109.     }     
  1110.     if (username == NULL) { 
  1111.     error(0, "SMPP: Configuration file doesn't specify username."); 
  1112.     ok = 0; 
  1113.     } 
  1114.     if (password == NULL) { 
  1115.     error(0, "SMPP: Configuration file doesn't specify password."); 
  1116.     ok = 0; 
  1117.     } 
  1118.     if (system_type == NULL) { 
  1119.     error(0, "SMPP: Configuration file doesn't specify system-type."); 
  1120.     ok = 0; 
  1121.     } 
  1122.     if (!ok) 
  1123.         return -1; 
  1124.  
  1125.     /* if the ton and npi values are forced, set them, else set them to -1 */ 
  1126.     if (cfg_get_integer(&source_addr_ton, grp, 
  1127.                         octstr_imm("source-addr-ton")) == -1) 
  1128.         source_addr_ton = -1; 
  1129.     if (cfg_get_integer(&source_addr_npi, grp, 
  1130.                         octstr_imm("source-addr-npi")) == -1) 
  1131.         source_addr_npi = -1; 
  1132.     if (cfg_get_integer(&dest_addr_ton, grp, 
  1133.                         octstr_imm("dest-addr-ton")) == -1) 
  1134.         dest_addr_ton = -1; 
  1135.     if (cfg_get_integer(&dest_addr_npi, grp, 
  1136.                         octstr_imm("dest-addr-npi")) == -1) 
  1137.         dest_addr_npi = -1; 
  1138.     /* if source addr autodetection should be used set this to 1 */
  1139.     cfg_get_bool(&autodetect_addr, grp, octstr_imm("source-addr-autodetect")); 
  1140.     /* check for any specified interface version */
  1141.     if (cfg_get_integer(&version, grp, octstr_imm("interface-version")) == -1)
  1142.         version = SMPP_DEFAULT_VERSION;
  1143.     else
  1144.         /* convert decimal to BCD */
  1145.         version = ((version / 10) << 4) + (version % 10);
  1146.     /* check for any specified priority value in range [0-5] */
  1147.     if (cfg_get_integer(&priority, grp, octstr_imm("priority")) == -1)
  1148.         priority = SMPP_DEFAULT_PRIORITY;
  1149.     /* set the msg_id type variable for this SMSC */
  1150.     if (cfg_get_integer(&smpp_msg_id_type, grp, octstr_imm("msg-id-type")) == -1) {
  1151.         /* 
  1152.          * defaults to C string "as-is" style 
  1153.          */
  1154.         smpp_msg_id_type = -1; 
  1155.     } else {
  1156.         if (smpp_msg_id_type < 0 || smpp_msg_id_type > 3)
  1157.             panic(0,"SMPP: Invlid value for msg-id-type directive in configuraton"); 
  1158.     }
  1159.     smpp = smpp_create(conn, host, port, receive_port, system_type,  
  1160.                  username, password, address_range, our_host, 
  1161.                        source_addr_ton, source_addr_npi, dest_addr_ton,  
  1162.                        dest_addr_npi, alt_dcs, enquire_link_interval, 
  1163.                        max_pending_submits, reconnect_delay, 
  1164.                        version, priority, my_number, smpp_msg_id_type,
  1165.                        autodetect_addr); 
  1166.  
  1167.     conn->data = smpp; 
  1168.     conn->name = octstr_format("SMPP:%S:%d/%d:%S:%S",  
  1169.                       host, port, 
  1170.                                (receive_port ? receive_port : port),  
  1171.                                username, system_type); 
  1172.  
  1173.     smsc_id = cfg_get(grp, octstr_imm("smsc-id")); 
  1174.     if (smsc_id == NULL) { 
  1175.         conn->id = octstr_duplicate(conn->name); 
  1176.     } 
  1177.     octstr_destroy(host); 
  1178.     octstr_destroy(username); 
  1179.     octstr_destroy(password); 
  1180.     octstr_destroy(system_type); 
  1181.     octstr_destroy(address_range); 
  1182.     octstr_destroy(our_host); 
  1183.     octstr_destroy(my_number); 
  1184.     octstr_destroy(smsc_id);
  1185.  
  1186.     conn->status = SMSCCONN_CONNECTING; 
  1187.        
  1188.     /* 
  1189.      * I/O threads are only started if the corresponding ports 
  1190.      * have been configured with positive numbers. Use 0 to  
  1191.      * disable the creation of the corresponding thread. 
  1192.      */ 
  1193.     if (port != 0) 
  1194.         smpp->transmitter = gwthread_create(io_thread, io_arg_create(smpp,  
  1195.                                            (transceiver_mode ? 2 : 1))); 
  1196.     if (receive_port != 0) 
  1197.         smpp->receiver = gwthread_create(io_thread, io_arg_create(smpp, 0)); 
  1198.      
  1199.     if ((port != 0 && smpp->transmitter == -1) ||  
  1200.         (receive_port != 0 && smpp->receiver == -1)) { 
  1201.         error(0, "SMPP[%s]: Couldn't start I/O threads.",
  1202.               octstr_get_cstr(smpp->conn->id)); 
  1203.         smpp->quitting = 1; 
  1204.         if (smpp->transmitter != -1) { 
  1205.             gwthread_wakeup(smpp->transmitter); 
  1206.             gwthread_join(smpp->transmitter); 
  1207.         } 
  1208.         if (smpp->receiver != -1) { 
  1209.             gwthread_wakeup(smpp->receiver); 
  1210.             gwthread_join(smpp->receiver); 
  1211.         } 
  1212.      smpp_destroy(conn->data); 
  1213.         return -1; 
  1214.     } 
  1215.  
  1216.     conn->shutdown = shutdown_cb; 
  1217.     conn->queued = queued_cb; 
  1218.     conn->send_msg = send_msg_cb; 
  1219.  
  1220.     return 0; 
  1221. }
  1222.