00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
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
00086
00087
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
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
00121
00122 #define SMPP_WAITACK_RECONNECT 0x00
00123 #define SMPP_WAITACK_REQUEUE 0x01
00124 #define SMPP_WAITACK_NEVER_EXPIRE 0x02
00125
00126
00127
00128
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;
00159 int validityperiod;
00160 time_t throttling_err_time;
00161 int smpp_msg_id_type;
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
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
00195
00196 static void smpp_msg_destroy(struct smpp_msg *msg, int destroy_msg)
00197 {
00198
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
00291
00292
00293
00294
00295
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
00349
00350
00351
00352 if (octstr_len(addr) < 7) {
00353
00354
00355
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
00375 if (octstr_search(addr, octstr_imm("00"), 0) == 0)
00376 octstr_delete(addr, 0, 2);
00377
00378
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
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:
00401 break;
00402 }
00403
00404 error:
00405 return reason;
00406 }
00407
00408
00409
00410
00411
00412
00413
00414
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
00429
00430
00431
00432 ton = pdu->u.deliver_sm.source_addr_ton;
00433 npi = pdu->u.deliver_sm.source_addr_npi;
00434
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
00442
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
00453 ton = pdu->u.deliver_sm.dest_addr_ton;
00454 npi = pdu->u.deliver_sm.dest_addr_npi;
00455
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
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
00470
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
00483
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
00504 switch (pdu->u.deliver_sm.data_coding) {
00505 case 0x00:
00506
00507
00508
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 {
00516 charset_gsm_to_utf8(msg->sms.msgdata);
00517 msg->sms.coding = DC_7BIT;
00518 }
00519 break;
00520 case 0x01:
00521 case 0x03:
00522 msg->sms.coding = DC_7BIT; break;
00523 case 0x02:
00524 case 0x04:
00525 msg->sms.coding = DC_8BIT; break;
00526 case 0x05:
00527 break;
00528 case 0x06:
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:
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:
00537 msg->sms.coding = DC_UCS2; break;
00538
00539
00540
00541
00542
00543
00544 default:
00545
00546
00547
00548
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) {
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
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
00572
00573
00574
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
00589
00590
00591
00592 ton = pdu->u.data_sm.source_addr_ton;
00593 npi = pdu->u.data_sm.source_addr_npi;
00594
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
00602
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
00613 ton = pdu->u.data_sm.dest_addr_ton;
00614 npi = pdu->u.data_sm.dest_addr_npi;
00615
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
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
00633
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
00654 switch (pdu->u.data_sm.data_coding) {
00655 case 0x00:
00656
00657
00658
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 {
00666 charset_gsm_to_utf8(msg->sms.msgdata);
00667 msg->sms.coding = DC_7BIT;
00668 }
00669 break;
00670 case 0x01:
00671 case 0x03:
00672 msg->sms.coding = DC_7BIT; break;
00673 case 0x02:
00674 case 0x04:
00675 msg->sms.coding = DC_8BIT; break;
00676 case 0x05:
00677 break;
00678 case 0x06:
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:
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:
00687 msg->sms.coding = DC_UCS2; break;
00688
00689
00690
00691
00692
00693
00694 default:
00695
00696
00697
00698
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) {
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
00745
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
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
00758 pdu->u.submit_sm.source_addr_ton = GSM_ADDR_TON_NATIONAL;
00759 pdu->u.submit_sm.source_addr_npi = GSM_ADDR_NPI_E164;
00760 }
00761
00762 if (smpp->autodetect_addr && pdu->u.submit_sm.source_addr) {
00763
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;
00767 pdu->u.submit_sm.source_addr_npi = GSM_ADDR_NPI_UNKNOWN;
00768 if (smpp->alt_addr_charset) {
00769 if (octstr_str_case_compare(smpp->alt_addr_charset, "gsm") == 0) {
00770
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
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
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
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;
00808 pdu->u.submit_sm.dest_addr_npi = GSM_ADDR_NPI_E164;
00809 }
00810
00811
00812
00813
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
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
00829
00830
00831
00832
00833
00834
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);
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
00844 if(msg->sms.pid != SMS_PARAM_UNDEFINED)
00845 pdu->u.submit_sm.protocol_id = msg->sms.pid;
00846
00847
00848
00849
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
00861
00862
00863 pdu->u.submit_sm.short_message = octstr_duplicate(msg->sms.msgdata);
00864
00865
00866
00867
00868
00869 if (msg->sms.coding == DC_7BIT || (msg->sms.coding == DC_UNDEF && octstr_len(msg->sms.udhdata) == 0)) {
00870
00871
00872
00873
00874
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
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
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
00899
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
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
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
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);
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);
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
01000 msg = gwlist_extract_first(smpp->msgs_to_send);
01001 if (msg == NULL)
01002 break;
01003
01004
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
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
01020
01021 if (smpp->conn->throughput > 0)
01022 gwthread_sleep(delay);
01023 }
01024 else {
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
01035
01036
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
01073
01074
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
01109
01110
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
01152 if (smpp->version > 0x33 && receipted_message_id) {
01153 msgid = octstr_duplicate(receipted_message_id);
01154 switch(message_state) {
01155 case 1:
01156 case 6:
01157 dlrstat = DLR_BUFFERED;
01158 break;
01159 case 2:
01160 dlrstat = DLR_SUCCESS;
01161 break;
01162 case 3:
01163 case 4:
01164 case 5:
01165 case 7:
01166 case 8:
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
01178 if (smpp->version > 0x33 && octstr_len(short_message) == 0)
01179 respstr = message_payload;
01180 else
01181 respstr = short_message;
01182
01183
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
01191
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
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
01225
01226
01227
01228
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
01250
01251
01252
01253
01254
01255
01256
01257
01258
01259
01260
01261
01262
01263
01264 if (smpp->smpp_msg_id_type == -1) {
01265
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,
01278 destination_addr,
01279 dlrstat);
01280
01281 octstr_destroy(msgid);
01282 } else
01283 tmp = octstr_create("");
01284
01285 if (dlrmsg != NULL) {
01286
01287
01288
01289
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
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
01346
01347
01348
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
01357 reason = bb_smscconn_receive(smpp->conn, dlrmsg);
01358 } else {
01359
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 {
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
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
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
01399
01400
01401
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 {
01418 resp = smpp_pdu_create(deliver_sm_resp,
01419 pdu->u.deliver_sm.sequence_number);
01420
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
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
01472
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
01487 if (smpp->smpp_msg_id_type == -1) {
01488
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(
01495 octstr_get_cstr(pdu->u.submit_sm_resp.message_id), NULL, 16));
01496 } else {
01497 tmp = octstr_format("%lu", strtoll(
01498 octstr_get_cstr(pdu->u.submit_sm_resp.message_id), NULL, 10));
01499 }
01500 }
01501
01502
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 }
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
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
01611
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
01629
01630
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
01663
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
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:
01688
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;
01694 case SMPP_WAITACK_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
01726
01727
01728
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
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
01773
01774
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
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
01805
01806
01807 if (smpp->conn->status != SMSCCONN_ACTIVE && smpp->conn->status != SMSCCONN_ACTIVE_RECV) {
01808
01809 ret = -1;
01810 break;
01811 }
01812
01813
01814 send_enquire_link(smpp, conn, &last_enquire_sent);
01815
01816
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
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
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;
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
01856 mutex_lock(smpp->conn->flow_mutex);
01857 smpp->conn->status = SMSCCONN_RECONNECTING;
01858 mutex_unlock(smpp->conn->flow_mutex);
01859
01860
01861
01862
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
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
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
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
01962
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
02027
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
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
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
02077 if (cfg_get_bool(&autodetect_addr, grp, octstr_imm("source-addr-autodetect")) == -1)
02078 autodetect_addr = 1;
02079
02080
02081 if (cfg_get_integer(&version, grp, octstr_imm("interface-version")) == -1)
02082 version = SMPP_DEFAULT_VERSION;
02083 else
02084
02085 version = ((version / 10) << 4) + (version % 10);
02086
02087
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
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
02100 if (cfg_get_integer(&smpp_msg_id_type, grp, octstr_imm("msg-id-type")) == -1) {
02101
02102
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
02111 alt_charset = cfg_get(grp, octstr_imm("alt-charset"));
02112 alt_addr_charset = cfg_get(grp, octstr_imm("alt-addr-charset"));
02113
02114
02115 if (cfg_get_integer(&connection_timeout, grp, octstr_imm("connection-timeout")) == -1)
02116 connection_timeout = SMPP_DEFAULT_CONNECTION_TIMEOUT;
02117
02118
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
02165
02166
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.