#include "gw-config.h"#include <errno.h>#include <stdlib.h>#include <stdio.h>#include <time.h>#include <string.h>#include <sys/time.h>#include <sys/types.h>#include <unistd.h>#include <signal.h>#include <fcntl.h>#include "gwlib/gwlib.h"#include "msg.h"#include "sms.h"#include "bearerbox.h"#include "numhash.h"#include "smscconn.h"#include "dlr.h"#include "bb_smscconn_cb.h"#include "smscconn_p.h"Include dependency graph for bb_smscconn.c:

Go to the source code of this file.
|
|
|
|
|
Definition at line 143 of file bb_smscconn.c. 00143 {concat_error = -1, concat_complete = 0, concat_pending = 1, concat_none};
|
|
|
Definition at line 168 of file bb_smscconn.c. References gwthread_wakeup(), router_thread, and SMSCConn. Referenced by at2_device_thread(), cgw_open_send_connection(), cgw_sender(), fake_listener(), handle_pdu(), io_thread(), open_send_connection(), reconnect(), and soap_listener(). 00169 {
00170 if (router_thread >= 0)
00171 gwthread_wakeup(router_thread);
00172 }
|
Here is the call graph for this function:

|
|
Definition at line 175 of file bb_smscconn.c. References flow_threads, gwlist_remove_producer(), and incoming_sms. Referenced by at2_device_thread(), cgw_sender(), cimd2_shutdown_cb(), emi2_sender(), fake_listener(), httpsmsc_send_cb(), oisd_shutdown_cb(), shutdown_cb(), soap_listener(), and wrapper_sender(). 00176 {
00177 /* NOTE: after status has been set to SMSCCONN_DEAD, bearerbox
00178 * is free to release/delete 'conn'
00179 */
00180 gwlist_remove_producer(incoming_sms);
00181 gwlist_remove_producer(flow_threads);
00182 }
|
Here is the call graph for this function:

|
|
Definition at line 161 of file bb_smscconn.c. References flow_threads, gwlist_add_producer(), incoming_sms, and SMSCConn. Referenced by smscconn_create(). 00162 {
00163 gwlist_add_producer(flow_threads);
00164 gwlist_add_producer(incoming_sms);
00165 }
|
Here is the call graph for this function:

|
||||||||||||
|
Definition at line 350 of file bb_smscconn.c. References ack_failed, bb_alog_sms(), black_list, black_list_regex, check_concatenation(), concat_complete, concat_error, concat_none, concat_pending, counter_increase(), gwthread_sleep(), handle_concatenated_mo, smscconn::id, incoming_sms_counter, info(), msg_destroy(), msg_duplicate(), normalize_number(), numhash_find_number(), octstr_get_cstr, panic, smscconn::received, route_incoming_to_boxc(), route_incoming_to_smsc(), sms, SMSCConn, SMSCCONN_FAILED_QFULL, SMSCCONN_SUCCESS, store_save, store_save_ack, smscconn::unified_prefix, unified_prefix, warning(), white_list, and white_list_regex. Referenced by at2_wait_modem_command(), bb_smscconn_send_failed(), bb_smscconn_sent(), brunet_receive_sms(), cgw_handle_op(), clear_old_concat_parts(), clickatell_receive_sms(), handle_operation(), handle_pdu(), io_thread(), kannel_receive_sms(), main_connection_loop(), msg_to_bb(), soap_parse_dlr(), soap_parse_mo(), wrapper_receiver(), and xidris_receive_sms(). 00351 {
00352 char *uf;
00353 int rc;
00354 Msg *copy;
00355
00356 /*
00357 * First normalize in smsc level and then on global level.
00358 * In outbound direction it's vise versa, hence first global then smsc.
00359 */
00360 uf = (conn && conn->unified_prefix) ? octstr_get_cstr(conn->unified_prefix) : NULL;
00361 normalize_number(uf, &(sms->sms.sender));
00362
00363 uf = unified_prefix ? octstr_get_cstr(unified_prefix) : NULL;
00364 normalize_number(uf, &(sms->sms.sender));
00365
00366 if (white_list &&
00367 numhash_find_number(white_list, sms->sms.sender) < 1) {
00368 info(0, "Number <%s> is not in white-list, message discarded",
00369 octstr_get_cstr(sms->sms.sender));
00370 bb_alog_sms(conn, sms, "REJECTED - not white-listed SMS");
00371 msg_destroy(sms);
00372 return SMSCCONN_FAILED_REJECTED;
00373 }
00374
00375 if (white_list_regex && gw_regex_match_pre(white_list_regex, sms->sms.sender) == 0) {
00376 info(0, "Number <%s> is not in white-list, message discarded",
00377 octstr_get_cstr(sms->sms.sender));
00378 bb_alog_sms(conn, sms, "REJECTED - not white-regex-listed SMS");
00379 msg_destroy(sms);
00380 return SMSCCONN_FAILED_REJECTED;
00381 }
00382
00383 if (black_list &&
00384 numhash_find_number(black_list, sms->sms.sender) == 1) {
00385 info(0, "Number <%s> is in black-list, message discarded",
00386 octstr_get_cstr(sms->sms.sender));
00387 bb_alog_sms(conn, sms, "REJECTED - black-listed SMS");
00388 msg_destroy(sms);
00389 return SMSCCONN_FAILED_REJECTED;
00390 }
00391
00392 if (black_list_regex && gw_regex_match_pre(black_list_regex, sms->sms.sender) == 0) {
00393 info(0, "Number <%s> is not in black-list, message discarded",
00394 octstr_get_cstr(sms->sms.sender));
00395 bb_alog_sms(conn, sms, "REJECTED - black-regex-listed SMS");
00396 msg_destroy(sms);
00397 return SMSCCONN_FAILED_REJECTED;
00398 }
00399
00400 /* fix sms type if not set already */
00401 if (sms->sms.sms_type != report_mo)
00402 sms->sms.sms_type = mo;
00403
00404 /* write to store (if enabled) */
00405 if (store_save(sms) == -1) {
00406 msg_destroy(sms);
00407 return SMSCCONN_FAILED_TEMPORARILY;
00408 }
00409
00410 copy = msg_duplicate(sms);
00411
00412 /*
00413 * Try to reroute internally to an smsc-id without leaving
00414 * actually bearerbox scope.
00415 * Scope: internal routing (to smsc-ids)
00416 */
00417 if ((rc = route_incoming_to_smsc(conn, copy)) == -1) {
00418 int ret;
00419 /* Before routing to some box, do concat handling
00420 * and replace copy as such.
00421 */
00422 if (handle_concatenated_mo && copy->sms.sms_type == mo) {
00423 ret = check_concatenation(©, (conn ? conn->id : NULL));
00424 switch(ret) {
00425 case concat_pending:
00426 counter_increase(incoming_sms_counter); /* ?? */
00427 if (conn != NULL)
00428 counter_increase(conn->received);
00429 msg_destroy(sms);
00430 return SMSCCONN_SUCCESS;
00431 case concat_complete:
00432 /* Combined sms received! save new one since it is now combined. */
00433 msg_destroy(sms);
00434 /* Change the sms. */
00435 sms = msg_duplicate(copy);
00436 break;
00437 case concat_error:
00438 /* failed to save, go away. */
00439 msg_destroy(sms);
00440 return SMSCCONN_FAILED_TEMPORARILY;
00441 case concat_none:
00442 break;
00443 default:
00444 panic(0, "Internal error: Unhandled concat result.");
00445 break;
00446 }
00447 }
00448 /*
00449 * Now try to route the message to a specific smsbox
00450 * connection based on the existing msg->sms.boxc_id or
00451 * the registered receiver numbers for specific smsbox'es.
00452 * Scope: external routing (to smsbox connections)
00453 */
00454 rc = route_incoming_to_boxc(copy);
00455 }
00456
00457 if (rc == -1 || (rc != SMSCCONN_SUCCESS && rc != SMSCCONN_QUEUED)) {
00458 warning(0, "incoming messages queue too long, dropping a message");
00459 if (sms->sms.sms_type == report_mo)
00460 bb_alog_sms(conn, sms, "DROPPED Received DLR");
00461 else
00462 bb_alog_sms(conn, sms, "DROPPED Received SMS");
00463
00464 /* put nack into store-file */
00465 store_save_ack(sms, ack_failed);
00466
00467 msg_destroy(copy);
00468 msg_destroy(sms);
00469 gwthread_sleep(0.1); /* letting the queue go down */
00470 return (rc == -1 ? SMSCCONN_FAILED_QFULL : rc);
00471 }
00472
00473 if (sms->sms.sms_type != report_mo)
00474 bb_alog_sms(conn, sms, "Receive SMS");
00475 else
00476 bb_alog_sms(conn, sms, "Receive DLR");
00477
00478 counter_increase(incoming_sms_counter);
00479 if (conn != NULL) counter_increase(conn->received);
00480
00481 msg_destroy(sms);
00482
00483 return SMSCCONN_SUCCESS;
00484 }
|
Here is the call graph for this function:

|
||||||||||||||||||||
|
Definition at line 281 of file bb_smscconn.c. References ack_failed, bb_alog_sms(), bb_smscconn_receive(), counter_increase(), create_dlr_from_msg(), DLR_IS_FAIL, DLR_IS_SMSC_FAIL, DLR_SMSC_FAIL, smscconn::failed, gwlist_produce(), handle_split(), smscconn::id, msg_destroy(), smscconn::name, octstr_create, octstr_destroy(), octstr_insert_data(), outgoing_sms, reason, sms, sms_resend_retry, SMSCConn, SMSCCONN_FAILED_DISCARDED, SMSCCONN_FAILED_SHUTDOWN, SMSCCONN_FAILED_TEMPORARILY, smscconn_status(), store_save_ack, and warning(). Referenced by at2_send_one_message(), at2_shutdown_cb(), brunet_parse_reply(), cgw_handle_op(), cgw_open_send_connection(), cgw_sender(), cgw_shutdown_cb(), cimd2_shutdown_cb(), cimd2_submit_msg(), clickatell_parse_reply(), do_queue_cleanup(), emi2_handle_smscreq(), emi2_sender(), fake_listener(), generic_parse_reply(), handle_pdu(), handle_split(), io_thread(), kannel_parse_reply(), main_connection_loop(), oisd_shutdown_cb(), oisd_submit_msg(), open_send_connection(), reconnect(), send_messages(), shutdown_cb(), sms_send(), smsc2_rout(), soap_listener(), soap_read_response(), soap_send_loop(), soap_shutdown_cb(), wapme_smsproxy_parse_reply(), wrapper_sender(), wrapper_shutdown(), and xidris_parse_reply(). 00282 {
00283 if (sms->sms.split_parts != NULL) {
00284 handle_split(conn, sms, reason);
00285 octstr_destroy(reply);
00286 return;
00287 }
00288
00289 switch (reason) {
00290 case SMSCCONN_FAILED_TEMPORARILY:
00291 /*
00292 * Check if SMSC link alive and if so increase resend_try and set resend_time.
00293 * If SMSC link is not active don't increase resend_try and don't set resend_time
00294 * because we don't want to delay messages because of connection broken.
00295 */
00296 if (conn && smscconn_status(conn) == SMSCCONN_ACTIVE) {
00297 /*
00298 * Check if sms_resend_retry set and this msg has exceeded a limit also
00299 * honor "single shot" with sms_resend_retry set to zero.
00300 */
00301 if (sms_resend_retry >= 0 && sms->sms.resend_try >= sms_resend_retry) {
00302 warning(0, "Maximum retries for message exceeded, discarding it!");
00303 bb_smscconn_send_failed(NULL, sms, SMSCCONN_FAILED_DISCARDED,
00304 octstr_create("Retries Exceeded"));
00305 break;
00306 }
00307 sms->sms.resend_try = (sms->sms.resend_try > 0 ? sms->sms.resend_try + 1 : 1);
00308 time(&sms->sms.resend_time);
00309 }
00310 gwlist_produce(outgoing_sms, sms);
00311 break;
00312
00313 case SMSCCONN_FAILED_SHUTDOWN:
00314 gwlist_produce(outgoing_sms, sms);
00315 break;
00316
00317 default:
00318 /* write NACK to store file */
00319 store_save_ack(sms, ack_failed);
00320
00321 if (conn) counter_increase(conn->failed);
00322 if (reason == SMSCCONN_FAILED_DISCARDED)
00323 bb_alog_sms(conn, sms, "DISCARDED SMS");
00324 else
00325 bb_alog_sms(conn, sms, "FAILED Send SMS");
00326
00327 /* generate relay confirmancy message */
00328 if (DLR_IS_SMSC_FAIL(sms->sms.dlr_mask) ||
00329 DLR_IS_FAIL(sms->sms.dlr_mask)) {
00330 Msg *dlrmsg;
00331
00332 if (reply == NULL)
00333 reply = octstr_create("");
00334
00335 octstr_insert_data(reply, 0, "NACK/", 5);
00336 dlrmsg = create_dlr_from_msg((conn ? (conn->id?conn->id:conn->name) : NULL), sms,
00337 reply, DLR_SMSC_FAIL);
00338 if (dlrmsg != NULL) {
00339 bb_smscconn_receive(conn, dlrmsg);
00340 }
00341 }
00342
00343 msg_destroy(sms);
00344 break;
00345 }
00346
00347 octstr_destroy(reply);
00348 }
|
Here is the call graph for this function:

|
||||||||||||||||
Here is the call graph for this function:

|
||||||||||||
|
Definition at line 1341 of file bb_smscconn.c. References ack_success, concat_lock, debug(), dict_get(), dict_put(), error(), incoming_concat_msgs, ConcatMsg::key, msg_destroy(), msg_dump(), msg_duplicate(), mutex_lock, mutex_unlock, ConcatMsg::num_parts, octstr_append(), octstr_delete(), octstr_destroy(), octstr_duplicate, octstr_format(), octstr_get_char(), octstr_get_cstr, octstr_len(), octstr_set_char(), ConcatMsg::parts, ConcatMsg::refnum, store_save, store_save_ack, ConcatMsg::total_parts, ConcatMsg::trecv, uuid_generate(), and warning(). Referenced by bb_smscconn_receive(). 01342 {
01343 Msg *msg = *pmsg;
01344 int l, iel, refnum, pos, c, part, totalparts, i, sixteenbit;
01345 Octstr *udh = msg->sms.udhdata, *key;
01346 ConcatMsg *cmsg;
01347 int ret = concat_complete;
01348
01349 /* ... module not initialised or there is no UDH or smscid is NULL. */
01350 if (incoming_concat_msgs == NULL || (l = octstr_len(udh)) == 0 || smscid == NULL)
01351 return concat_none;
01352
01353 for (pos = 1, c = -1; pos < l - 1; pos += iel + 2) {
01354 iel = octstr_get_char(udh, pos + 1);
01355 if ((c = octstr_get_char(udh,pos)) == 0 || c == 8)
01356 break;
01357 }
01358 if (pos >= l) /* no concat UDH found. */
01359 return concat_none;
01360
01361 /* c = 0 means 8 bit, c = 8 means 16 bit concat info */
01362 sixteenbit = (c == 8);
01363 refnum = (!sixteenbit) ? octstr_get_char(udh, pos + 2) :
01364 (octstr_get_char(udh, pos + 2) << 8) | octstr_get_char(udh, pos + 3);
01365 totalparts = octstr_get_char(udh, pos + 3 + sixteenbit);
01366 part = octstr_get_char(udh, pos + 4 + sixteenbit);
01367
01368 if (part < 1 || part > totalparts) {
01369 warning(0, "Invalid concatenation UDH [ref = %d] in message from %s!",
01370 refnum, octstr_get_cstr(msg->sms.sender));
01371 return concat_none;
01372 }
01373
01374 debug("bb.sms.splits", 0, "Got part %d [ref %d, total parts %d] of message from %s. Dump follows:",
01375 part, refnum,totalparts, octstr_get_cstr(msg->sms.sender));
01376
01377 msg_dump(msg,0);
01378
01379 key = octstr_format("%S %S %S %d", msg->sms.sender, msg->sms.receiver, smscid, refnum);
01380 mutex_lock(concat_lock);
01381 if ((cmsg = dict_get(incoming_concat_msgs, key)) == NULL) {
01382 cmsg = gw_malloc(sizeof(*cmsg));
01383 cmsg->refnum = refnum;
01384 cmsg->total_parts = totalparts;
01385 cmsg->num_parts = 0;
01386 cmsg->key = octstr_duplicate(key);
01387 cmsg->ack = ack_success;
01388 cmsg->parts = gw_malloc(totalparts * sizeof(*cmsg->parts));
01389 memset(cmsg->parts, 0, cmsg->total_parts * sizeof(*cmsg->parts)); /* clear it. */
01390
01391 dict_put(incoming_concat_msgs, key, cmsg);
01392 }
01393 octstr_destroy(key);
01394
01395 if (totalparts != cmsg->total_parts) {
01396 /* totalparts in udh and cmsg not equal assume bad message */
01397 error(0, "Totalparts in UDH doesn't match received before, "
01398 "total parts <%d>:<%d> part %d, ref %d, from %s, to %s. Discarded!",
01399 cmsg->total_parts, totalparts, part, refnum, octstr_get_cstr(msg->sms.sender), octstr_get_cstr(msg->sms.receiver));
01400 mutex_unlock(concat_lock);
01401 store_save_ack(msg, ack_success);
01402 msg_destroy(msg);
01403 *pmsg = msg = NULL;
01404 return concat_error;
01405 }
01406
01407 /* check if we have seen message part before... */
01408 if (cmsg->parts[part - 1] != NULL) {
01409 warning(0, "Duplicate message part %d, ref %d, from %s, to %s. Discarded!",
01410 part, refnum, octstr_get_cstr(msg->sms.sender), octstr_get_cstr(msg->sms.receiver));
01411 store_save_ack(msg, ack_success);
01412 msg_destroy(msg);
01413 *pmsg = msg = NULL;
01414 } else {
01415 cmsg->parts[part -1] = msg;
01416 cmsg->num_parts++;
01417 /* always update receive time so we have it from last part and don't timeout */
01418 cmsg->trecv = time(NULL);
01419 }
01420
01421 if (cmsg->num_parts < cmsg->total_parts) { /* wait for more parts. */
01422 *pmsg = msg = NULL;
01423 mutex_unlock(concat_lock);
01424 return concat_pending;
01425 }
01426
01427 /* we have all the parts: Put them together, mod UDH, return message. */
01428 msg = msg_duplicate(cmsg->parts[0]);
01429 uuid_generate(msg->sms.id); /* give it a new ID. */
01430
01431 debug("bb.sms.splits",0,"Received all concatenated message parts from %s, to %s, refnum %d",
01432 octstr_get_cstr(msg->sms.sender), octstr_get_cstr(msg->sms.receiver), refnum);
01433
01434 for (i = 1; i < cmsg->total_parts; i++)
01435 octstr_append(msg->sms.msgdata, cmsg->parts[i]->sms.msgdata);
01436
01437 /* Attempt to save the new one, if that fails, then reply with fail. */
01438 if (store_save(msg) == -1) {
01439 mutex_unlock(concat_lock);
01440 msg_destroy(msg);
01441 *pmsg = msg = NULL;
01442 return concat_error;
01443 } else
01444 *pmsg = msg; /* return the message part. */
01445
01446 /* Delete it from the queue and from the Dict. */
01447 /* Note: dict_put with NULL value delete and destroy value */
01448 dict_put(incoming_concat_msgs, cmsg->key, NULL);
01449 mutex_unlock(concat_lock);
01450
01451 /* fix up UDH */
01452 udh = msg->sms.udhdata;
01453 l = octstr_len(udh);
01454 for (pos = 1; pos < l - 1; pos += iel + 2) {
01455 iel = octstr_get_char(udh, pos + 1);
01456 if ((c = octstr_get_char(udh, pos)) == 0 || c == 8) {
01457 octstr_delete(udh, pos, iel + 2);
01458
01459 if (octstr_len(udh) <= 1) /* no other UDH elements. */
01460 octstr_delete(udh, 0, octstr_len(udh));
01461 else
01462 octstr_set_char(udh, 0, octstr_len(udh) - 1);
01463 break;
01464 }
01465 }
01466 debug("bb.sms.splits", 0, "Got full message [ref %d] of message from %s to %s. Dumping: ",
01467 refnum, octstr_get_cstr(msg->sms.sender), octstr_get_cstr(msg->sms.receiver));
01468 msg_dump(msg,0);
01469
01470 return ret;
01471 }
|
Here is the call graph for this function:

|
|
Definition at line 1251 of file bb_smscconn.c. References ack_success, bb_smscconn_receive(), concat_lock, debug(), destroy_concatMsg(), dict_get(), dict_keys(), dict_put(), dict_remove(), gwlist_destroy(), gwlist_extract_first(), incoming_concat_msgs, ConcatMsg::key, msg_destroy(), msg_duplicate(), mutex_lock, mutex_unlock, ConcatMsg::num_parts, octstr_destroy(), octstr_destroy_item(), octstr_format_append(), octstr_get_cstr, ConcatMsg::parts, SMSCCONN_FAILED_QFULL, SMSCCONN_FAILED_REJECTED, SMSCCONN_FAILED_TEMPORARILY, SMSCCONN_SUCCESS, store_save, store_save_ack, ConcatMsg::total_parts, ConcatMsg::trecv, and warning(). Referenced by sms_router(). 01252 {
01253 List *keys;
01254 Octstr *key;
01255
01256 /* not initialised, go away */
01257 if (incoming_concat_msgs == NULL)
01258 return;
01259
01260 debug("bb.sms.splits", 0, "clear_old_concat_parts called");
01261
01262 /* Remove any pending messages that are too old. */
01263 keys = dict_keys(incoming_concat_msgs);
01264 while((key = gwlist_extract_first(keys)) != NULL) {
01265 ConcatMsg *x;
01266 Msg *msg;
01267 int i, destroy = 1;
01268
01269 mutex_lock(concat_lock);
01270 x = dict_get(incoming_concat_msgs, key);
01271 octstr_destroy(key);
01272 if (x == NULL || difftime(time(NULL), x->trecv) < concatenated_mo_timeout) {
01273 mutex_unlock(concat_lock);
01274 continue;
01275 }
01276 dict_remove(incoming_concat_msgs, x->key);
01277 mutex_unlock(concat_lock);
01278 warning(0, "Time-out waiting for concatenated message '%s'. Send message parts as is.",
01279 octstr_get_cstr(x->key));
01280 for (i = 0; i < x->total_parts && destroy == 1; i++) {
01281 if (x->parts[i] == NULL)
01282 continue;
01283 msg = msg_duplicate(x->parts[i]);
01284 store_save_ack(x->parts[i], ack_success);
01285 switch(bb_smscconn_receive(NULL, msg)) {
01286 case SMSCCONN_FAILED_REJECTED:
01287 case SMSCCONN_SUCCESS:
01288 msg_destroy(x->parts[i]);
01289 x->parts[i] = NULL;
01290 x->num_parts--;
01291 break;
01292 case SMSCCONN_FAILED_TEMPORARILY:
01293 case SMSCCONN_FAILED_QFULL:
01294 default:
01295 /* oops put it back into dict and retry on next run */
01296 store_save(x->parts[i]);
01297 destroy = 0;
01298 break;
01299 }
01300 }
01301 if (destroy) {
01302 destroy_concatMsg(x);
01303 } else {
01304 ConcatMsg *x1;
01305 mutex_lock(concat_lock);
01306 x1 = dict_get(incoming_concat_msgs, x->key);
01307 if (x1 != NULL) { /* oops we have new part */
01308 int i;
01309 if (x->total_parts != x1->total_parts) {
01310 /* broken handset, don't know what todo here??
01311 * for now just put old concatMsg into dict with
01312 * another key and it will be cleaned up on next run.
01313 */
01314 octstr_format_append(x->key, " %d", x->total_parts);
01315 dict_put(incoming_concat_msgs, x->key, x);
01316 } else {
01317 for (i = 0; i < x->total_parts; i++) {
01318 if (x->parts[i] == NULL)
01319 continue;
01320 if (x1->parts[i] == NULL) {
01321 x1->parts[i] = x->parts[i];
01322 x->parts[i] = NULL;
01323 }
01324 }
01325 destroy_concatMsg(x);
01326 }
01327 } else {
01328 dict_put(incoming_concat_msgs, x->key, x);
01329 }
01330 mutex_unlock(concat_lock);
01331 }
01332 }
01333 gwlist_destroy(keys, octstr_destroy_item);
01334 }
|
Here is the call graph for this function:

|
|
Definition at line 1212 of file bb_smscconn.c. References ConcatMsg::ack, gw_assert, ConcatMsg::key, msg_destroy(), octstr_destroy(), ConcatMsg::parts, store_save_ack, and ConcatMsg::total_parts. Referenced by clear_old_concat_parts(), and init_concat_handler(). 01213 {
01214 int i;
01215 ConcatMsg *msg = x;
01216
01217 gw_assert(msg);
01218 for (i = 0; i < msg->total_parts; i++) {
01219 if (msg->parts[i]) {
01220 store_save_ack(msg->parts[i], msg->ack);
01221 msg_destroy(msg->parts[i]);
01222 }
01223 }
01224 gw_free(msg->parts);
01225 octstr_destroy(msg->key);
01226 gw_free(msg);
01227 }
|
Here is the call graph for this function:

|
||||||||||||||||
|
Definition at line 185 of file bb_smscconn.c. References bb_smscconn_send_failed(), bb_smscconn_sent(), counter_decrease(), counter_destroy(), debug(), msg_destroy(), split_parts::orig, split_parts::parts_left, reason, SMSCConn, SMSCCONN_ACTIVE, SMSCCONN_FAILED_DISCARDED, SMSCCONN_FAILED_MALFORMED, SMSCCONN_FAILED_REJECTED, SMSCCONN_FAILED_TEMPORARILY, smscconn_send(), smscconn_status(), SMSCCONN_SUCCESS, and split_parts::status. Referenced by bb_smscconn_send_failed(), and bb_smscconn_sent(). 00186 {
00187 struct split_parts *split = msg->sms.split_parts;
00188
00189 /*
00190 * If temporarely failed, try again immediately but only if connection active.
00191 * Because if connection is not active we will loop for ever here consuming 100% CPU
00192 * time due to internal queue cleanup in smsc module that call bb_smscconn_failed.
00193 */
00194 if (reason == SMSCCONN_FAILED_TEMPORARILY && smscconn_status(conn) == SMSCCONN_ACTIVE &&
00195 smscconn_send(conn, msg) == 0) {
00196 /* destroy this message because it will be duplicated in smsc module */
00197 msg_destroy(msg);
00198 return;
00199 }
00200
00201 /*
00202 * if the reason is not a success and status is still success
00203 * then set status of a split to the reason.
00204 * Note: reason 'malformed','discarded' or 'rejected' has higher priority!
00205 */
00206 switch(reason) {
00207 case SMSCCONN_FAILED_DISCARDED:
00208 case SMSCCONN_FAILED_REJECTED:
00209 case SMSCCONN_FAILED_MALFORMED:
00210 debug("bb.sms.splits", 0, "Set split msg status to %ld", reason);
00211 split->status = reason;
00212 break;
00213 case SMSCCONN_SUCCESS:
00214 break; /* nothing todo */
00215 default:
00216 if (split->status == SMSCCONN_SUCCESS) {
00217 debug("bb.sms.splits", 0, "Set split msg status to %ld", reason);
00218 split->status = reason;
00219 }
00220 break;
00221 }
00222
00223 /*
00224 * now destroy this message, because we don't need it anymore.
00225 * we will split it again in smscconn_send(...).
00226 */
00227 msg_destroy(msg);
00228
00229 if (counter_decrease(split->parts_left) <= 1) {
00230 /* all splited parts were processed */
00231 counter_destroy(split->parts_left);
00232 msg = split->orig;
00233 msg->sms.split_parts = NULL;
00234 if (split->status == SMSCCONN_SUCCESS)
00235 bb_smscconn_sent(conn, msg, NULL);
00236 else {
00237 debug("bb.sms.splits", 0, "Parts of concatenated message failed.");
00238 bb_smscconn_send_failed(conn, msg, split->status, NULL);
00239 }
00240 gw_free(split);
00241 }
00242 }
|
Here is the call graph for this function:

|
|
Definition at line 1229 of file bb_smscconn.c. References concat_lock, debug(), destroy_concatMsg(), dict_create(), incoming_concat_msgs, max_incoming_sms_qlength, and mutex_create. Referenced by smsc2_start(). 01230 {
01231 if (incoming_concat_msgs != NULL) /* already initialised? */
01232 return;
01233 incoming_concat_msgs = dict_create(max_incoming_sms_qlength > 0 ? max_incoming_sms_qlength : 1024,
01234 destroy_concatMsg);
01235 concat_lock = mutex_create();
01236 debug("bb.sms",0,"smsbox MO concatenated message handling enabled");
01237 }
|
Here is the call graph for this function:

|
||||||||||||
|
Definition at line 1141 of file bb_smscconn.c. References ack_success, dict_get(), octstr_destroy(), octstr_duplicate, report_mo, smscconn::reroute, smscconn::reroute_by_receiver, smscconn::reroute_dlr, smscconn::reroute_to_smsc, smsc2_rout(), SMSCConn, store_save, and store_save_ack. Referenced by bb_smscconn_receive(). 01142 {
01143 Octstr *smsc;
01144
01145 /* sanity check */
01146 if (!conn || !msg)
01147 return -1;
01148
01149 /* check for dlr rerouting */
01150 if (!conn->reroute_dlr && (msg->sms.sms_type == report_mo || msg->sms.sms_type == report_mt))
01151 return -1;
01152
01153 /*
01154 * Check if we have any "reroute" rules to obey. Which means msg gets
01155 * transported internally from MO to MT msg.
01156 */
01157 if (conn->reroute) {
01158 /* change message direction */
01159 store_save_ack(msg, ack_success);
01160 msg->sms.sms_type = mt_push;
01161 store_save(msg);
01162 /* drop into outbound queue again for routing */
01163 return smsc2_rout(msg, 0);
01164 }
01165
01166 if (conn->reroute_to_smsc) {
01167 /* change message direction */
01168 store_save_ack(msg, ack_success);
01169 msg->sms.sms_type = mt_push;
01170 store_save(msg);
01171 /* apply directly to the given smsc-id for MT traffic */
01172 octstr_destroy(msg->sms.smsc_id);
01173 msg->sms.smsc_id = octstr_duplicate(conn->reroute_to_smsc);
01174 return smsc2_rout(msg, 0);
01175 }
01176
01177 if (conn->reroute_by_receiver && msg->sms.receiver &&
01178 (smsc = dict_get(conn->reroute_by_receiver, msg->sms.receiver))) {
01179 /* change message direction */
01180 store_save_ack(msg, ack_success);
01181 msg->sms.sms_type = mt_push;
01182 store_save(msg);
01183 /* route by receiver number */
01184 /* XXX implement wildcard matching too! */
01185 octstr_destroy(msg->sms.smsc_id);
01186 msg->sms.smsc_id = octstr_duplicate(smsc);
01187 return smsc2_rout(msg, 0);
01188 }
01189
01190 return -1;
01191 }
|
Here is the call graph for this function:

|
|
Definition at line 1239 of file bb_smscconn.c. References concat_lock, debug(), dict_destroy(), incoming_concat_msgs, and mutex_destroy(). Referenced by smsc2_cleanup(). 01240 {
01241 if (incoming_concat_msgs == NULL)
01242 return;
01243 dict_destroy(incoming_concat_msgs);
01244 mutex_destroy(concat_lock);
01245
01246 incoming_concat_msgs = NULL;
01247 concat_lock = NULL;
01248 debug("bb.sms",0,"smsbox MO concatenated message handling cleaned up");
01249 }
|
Here is the call graph for this function:

|
|
Definition at line 496 of file bb_smscconn.c. References BB_SHUTDOWN, bb_status, clear_old_concat_parts(), concatenated_mo_timeout, debug(), flow_threads, gwlist_add_producer(), gwlist_len(), gwlist_produce(), gwlist_remove_producer(), gwlist_timed_consume(), gwthread_sleep(), gwthread_wakeup(), MAIN_THREAD_ID, msg_destroy(), outgoing_sms, sms_resend_frequency, smsc2_rout(), SMSCCONN_FAILED_DISCARDED, SMSCCONN_FAILED_QFULL, SMSCCONN_QUEUED, and SMSCCONN_SUCCESS. Referenced by smsc2_start(). 00497 {
00498 Msg *msg, *startmsg, *newmsg;
00499 long ret;
00500 time_t concat_mo_check;
00501
00502 gwlist_add_producer(flow_threads);
00503 gwthread_wakeup(MAIN_THREAD_ID);
00504
00505 startmsg = newmsg = NULL;
00506 ret = SMSCCONN_SUCCESS;
00507 concat_mo_check = time(NULL);
00508
00509 while(bb_status != BB_SHUTDOWN && bb_status != BB_DEAD) {
00510
00511 if (newmsg == startmsg) {
00512 if (ret == SMSCCONN_QUEUED || ret == SMSCCONN_FAILED_QFULL) {
00513 /* sleep: sms_resend_frequency / 2 , so we reduce amount of msgs to send */
00514 double sleep_time = (sms_resend_frequency / 2 > 1 ? sms_resend_frequency / 2 : sms_resend_frequency);
00515 debug("bb.sms", 0, "sms_router: time to sleep %.2f secs.", sleep_time);
00516 gwthread_sleep(sleep_time);
00517 debug("bb.sms", 0, "sms_router: gwlist_len = %ld", gwlist_len(outgoing_sms));
00518 }
00519 startmsg = msg = gwlist_timed_consume(outgoing_sms, concatenated_mo_timeout);
00520 newmsg = NULL;
00521 } else {
00522 newmsg = msg = gwlist_timed_consume(outgoing_sms, concatenated_mo_timeout);
00523 }
00524
00525 if (difftime(time(NULL), concat_mo_check) > concatenated_mo_timeout) {
00526 concat_mo_check = time(NULL);
00527 clear_old_concat_parts();
00528 }
00529
00530 /* shutdown or timeout */
00531 if (msg == NULL) {
00532 newmsg = startmsg = NULL;
00533 continue;
00534 }
00535
00536 debug("bb.sms", 0, "sms_router: handling message (%p vs %p)",
00537 msg, startmsg);
00538
00539 /* handle delayed msgs */
00540 if (msg->sms.resend_try > 0 && difftime(time(NULL), msg->sms.resend_time) < sms_resend_frequency &&
00541 bb_status != BB_SHUTDOWN && bb_status != BB_DEAD) {
00542 debug("bb.sms", 0, "re-queing SMS not-yet-to-be resent");
00543 gwlist_produce(outgoing_sms, msg);
00544 ret = SMSCCONN_QUEUED;
00545 continue;
00546 }
00547
00548 ret = smsc2_rout(msg, 1);
00549 switch(ret) {
00550 case SMSCCONN_SUCCESS:
00551 debug("bb.sms", 0, "Message routed successfully.");
00552 newmsg = startmsg = NULL;
00553 break;
00554 case SMSCCONN_QUEUED:
00555 debug("bb.sms", 0, "Routing failed, re-queued.");
00556 break;
00557 case SMSCCONN_FAILED_DISCARDED:
00558 msg_destroy(msg);
00559 newmsg = startmsg = NULL;
00560 break;
00561 case SMSCCONN_FAILED_QFULL:
00562 debug("bb.sms", 0, "Routing failed, re-queuing.");
00563 gwlist_produce(outgoing_sms, msg);
00564 break;
00565 }
00566 }
00567 gwlist_remove_producer(flow_threads);
00568 }
|
Here is the call graph for this function:

|
|
Definition at line 846 of file bb_smscconn.c. References black_list, black_list_regex, counter_destroy(), debug(), gw_regex_destroy(), gw_rwlock_destroy(), gw_rwlock_unlock(), gw_rwlock_wrlock(), gwlist_destroy(), gwlist_get(), gwlist_len(), numhash_destroy(), octstr_destroy(), shutdown_concat_handler(), smsc_groups, smsc_list, smsc_list_lock, smsc_running, SMSCConn, smscconn_destroy(), split_msg_counter, unified_prefix, white_list, and white_list_regex. Referenced by main(). 00847 {
00848 SMSCConn *conn;
00849 long i;
00850
00851 if (!smsc_running)
00852 return;
00853
00854 debug("smscconn", 0, "final clean-up for SMSCConn");
00855
00856 gw_rwlock_wrlock(&smsc_list_lock);
00857 for (i = 0; i < gwlist_len(smsc_list); i++) {
00858 conn = gwlist_get(smsc_list, i);
00859 smscconn_destroy(conn);
00860 }
00861 gwlist_destroy(smsc_list, NULL);
00862 smsc_list = NULL;
00863 gw_rwlock_unlock(&smsc_list_lock);
00864 gwlist_destroy(smsc_groups, NULL);
00865 octstr_destroy(unified_prefix);
00866 numhash_destroy(white_list);
00867 numhash_destroy(black_list);
00868 if (white_list_regex != NULL)
00869 gw_regex_destroy(white_list_regex);
00870 if (black_list_regex != NULL)
00871 gw_regex_destroy(black_list_regex);
00872 /* destroy msg split counter */
00873 counter_destroy(split_msg_counter);
00874 gw_rwlock_destroy(&smsc_list_lock);
00875
00876 /* Stop concat handling */
00877 shutdown_concat_handler();
00878
00879 smsc_running = 0;
00880 }
|
Here is the call graph for this function:

|
||||||||||||
|
Definition at line 665 of file bb_smscconn.c. References gwlist_get(), gwlist_len(), smscconn::id, octstr_compare(), smsc_list, and SMSCConn. Referenced by smsc2_restart_smsc(), and smsc2_stop_smsc(). 00666 {
00667 SMSCConn *conn = NULL;
00668 long i;
00669
00670 if (start > gwlist_len(smsc_list) || start < 0)
00671 return -1;
00672
00673 for (i = start; i < gwlist_len(smsc_list); i++) {
00674 conn = gwlist_get(smsc_list, i);
00675 if (conn != NULL && octstr_compare(conn->id, id) == 0) {
00676 break;
00677 }
00678 }
00679 if (i >= gwlist_len(smsc_list))
00680 i = -1;
00681 return i;
00682 }
|
Here is the call graph for this function:

|
|
Definition at line 708 of file bb_smscconn.c. References cfg_get, error(), gw_rwlock_unlock(), gw_rwlock_wrlock(), gwlist_delete(), gwlist_get(), gwlist_insert(), gwlist_len(), gwthread_wakeup(), info(), octstr_compare(), octstr_destroy(), octstr_get_cstr, octstr_imm(), router_thread, smsc2_find(), smsc_groups, smsc_list, smsc_list_lock, SMSCConn, smscconn_create(), smscconn_destroy(), smscconn_start(), smscconn_status(), and warning(). Referenced by bb_restart_smsc(). 00709 {
00710 CfgGroup *grp;
00711 SMSCConn *conn, *new_conn;
00712 Octstr *smscid = NULL;
00713 long i = -1;
00714 int num = 0;
00715
00716 if (!smsc_running)
00717 return -1;
00718
00719 gw_rwlock_wrlock(&smsc_list_lock);
00720 /* find the specific smsc via id */
00721 while((i = smsc2_find(id, ++i)) != -1) {
00722 int hit;
00723 long group_index;
00724 /* check if smsc has online status already */
00725 conn = gwlist_get(smsc_list, i);
00726 if (conn != NULL && smscconn_status(conn) != SMSCCONN_DEAD) {
00727 warning(0, "HTTP: Could not re-start already running smsc-id `%s'",
00728 octstr_get_cstr(id));
00729 continue;
00730 }
00731 /* find the group with equal smsc id */
00732 hit = 0;
00733 grp = NULL;
00734 for (group_index = 0; group_index < gwlist_len(smsc_groups) &&
00735 (grp = gwlist_get(smsc_groups, group_index)) != NULL; group_index++) {
00736 smscid = cfg_get(grp, octstr_imm("smsc-id"));
00737 if (smscid != NULL && octstr_compare(smscid, id) == 0) {
00738 if (hit == num)
00739 break;
00740 else
00741 hit++;
00742 }
00743 octstr_destroy(smscid);
00744 smscid = NULL;
00745 }
00746 octstr_destroy(smscid);
00747 if (hit != num) {
00748 /* config group not found */
00749 error(0, "HTTP: Could not find config for smsc-id `%s'", octstr_get_cstr(id));
00750 break;
00751 }
00752
00753 info(0,"HTTP: Re-starting smsc-id `%s'", octstr_get_cstr(id));
00754
00755 new_conn = smscconn_create(grp, 1);
00756 if (new_conn == NULL) {
00757 error(0, "Start of SMSC connection failed, smsc-id `%s'", octstr_get_cstr(id));
00758 continue; /* keep old connection on the list */
00759 }
00760
00761 /* drop old connection from the active smsc list */
00762 gwlist_delete(smsc_list, i, 1);
00763 /* destroy the connection */
00764 smscconn_destroy(conn);
00765 gwlist_insert(smsc_list, i, new_conn);
00766 smscconn_start(new_conn);
00767 num++;
00768 }
00769 gw_rwlock_unlock(&smsc_list_lock);
00770
00771 /* wake-up the router */
00772 if (router_thread >= 0)
00773 gwthread_wakeup(router_thread);
00774
00775 return 0;
00776 }
|
Here is the call graph for this function:

|
|
Definition at line 778 of file bb_smscconn.c. References gw_rwlock_rdlock(), gw_rwlock_unlock(), gwlist_get(), gwlist_len(), gwthread_wakeup(), router_thread, smsc_list, smsc_list_lock, SMSCConn, and smscconn_start(). Referenced by bb_resume(), and main(). 00779 {
00780 SMSCConn *conn;
00781 long i;
00782
00783 if (!smsc_running)
00784 return;
00785
00786 gw_rwlock_rdlock(&smsc_list_lock);
00787 for (i = 0; i < gwlist_len(smsc_list); i++) {
00788 conn = gwlist_get(smsc_list, i);
00789 smscconn_start(conn);
00790 }
00791 gw_rwlock_unlock(&smsc_list_lock);
00792
00793 if (router_thread >= 0)
00794 gwthread_wakeup(router_thread);
00795 }
|
Here is the call graph for this function:

|
||||||||||||
|
Definition at line 1004 of file bb_smscconn.c. References bb_smscconn_send_failed(), bb_status, debug(), error(), gw_rand(), gw_rwlock_rdlock(), gw_rwlock_unlock(), gwlist_get(), gwlist_len(), gwlist_produce(), info(), smsc_state::load, max_outgoing_sms_qlength, msg_destroy(), msg_duplicate(), msg_type, normalize_number(), octstr_create, octstr_get_cstr, outgoing_sms, smsc_state::queued, resend, smsc_list, smsc_list_lock, SMSCConn, SMSCCONN_FAILED_DISCARDED, smscconn_info(), smscconn_send(), smscconn_usable(), smsc_state::status, StatusInfo, unified_prefix, and warning(). Referenced by deliver_sms_to_queue(), route_incoming_to_smsc(), and sms_router(). 01005 {
01006 StatusInfo info;
01007 SMSCConn *conn, *best_preferred, *best_ok;
01008 long bp_load, bo_load;
01009 int i, s, ret, bad_found, full_found;
01010 long max_queue, queue_length;
01011 char *uf;
01012
01013 /* XXX handle ack here? */
01014 if (msg_type(msg) != sms) {
01015 error(0, "Attempt to route non SMS message through smsc2_rout!");
01016 return SMSCCONN_FAILED_DISCARDED;
01017 }
01018
01019 /* unify prefix of receiver, in case of it has not been
01020 * already done */
01021
01022 uf = unified_prefix ? octstr_get_cstr(unified_prefix) : NULL;
01023 normalize_number(uf, &(msg->sms.receiver));
01024
01025 /* select in which list to add this
01026 * start - from random SMSCConn, as they are all 'equal'
01027 */
01028 gw_rwlock_rdlock(&smsc_list_lock);
01029 if (gwlist_len(smsc_list) == 0) {
01030 warning(0, "No SMSCes to receive message");
01031 gw_rwlock_unlock(&smsc_list_lock);
01032 return SMSCCONN_FAILED_DISCARDED;
01033 }
01034
01035 /*
01036 * if global queue not empty then 20% reserved for old msgs
01037 * and 80% for new msgs. So we can guarantee that old msgs find
01038 * place in the SMSC's queue.
01039 */
01040 if (max_outgoing_sms_qlength > 0 && gwlist_len(outgoing_sms) > 0) {
01041 max_queue = (resend ? max_outgoing_sms_qlength :
01042 max_outgoing_sms_qlength * 0.8);
01043 }
01044 else
01045 max_queue = (max_outgoing_sms_qlength > 0 ? max_outgoing_sms_qlength : 1000000);
01046
01047 s = gw_rand() % gwlist_len(smsc_list);
01048 best_preferred = best_ok = NULL;
01049 bad_found = full_found = 0;
01050 bp_load = bo_load = queue_length = 0;
01051
01052 conn = NULL;
01053 for (i=0; i < gwlist_len(smsc_list); i++) {
01054 conn = gwlist_get(smsc_list, (i+s) % gwlist_len(smsc_list));
01055
01056 smscconn_info(conn, &info);
01057 queue_length += (info.queued > 0 ? info.queued : 0);
01058
01059 ret = smscconn_usable(conn,msg);
01060 if (ret == -1)
01061 continue;
01062
01063 /* if we already have a preferred one, skip non-preferred */
01064 if (ret != 1 && best_preferred)
01065 continue;
01066
01067 /* If connection is not currently answering ... */
01068 if (info.status != SMSCCONN_ACTIVE) {
01069 bad_found = 1;
01070 continue;
01071 }
01072 /* check queue length */
01073 if (info.queued > max_queue) {
01074 full_found = 1;
01075 continue;
01076 }
01077 if (ret == 1) { /* preferred */
01078 if (best_preferred == NULL || info.load < bp_load) {
01079 best_preferred = conn;
01080 bp_load = info.load;
01081 continue;
01082 }
01083 }
01084 if (best_ok == NULL || info.load < bo_load) {
01085 best_ok = conn;
01086 bo_load = info.load;
01087 }
01088 }
01089 queue_length += gwlist_len(outgoing_sms);
01090 if (max_outgoing_sms_qlength > 0 && !resend &&
01091 queue_length > gwlist_len(smsc_list) * max_outgoing_sms_qlength) {
01092 gw_rwlock_unlock(&smsc_list_lock);
01093 debug("bb.sms", 0, "sum(#queues) limit");
01094 return SMSCCONN_FAILED_QFULL;
01095 }
01096
01097 if (best_preferred)
01098 ret = smscconn_send(best_preferred, msg);
01099 else if (best_ok)
01100 ret = smscconn_send(best_ok, msg);
01101 else if (bad_found) {
01102 gw_rwlock_unlock(&smsc_list_lock);
01103 if (max_outgoing_sms_qlength < 0 || gwlist_len(outgoing_sms) < max_outgoing_sms_qlength) {
01104 gwlist_produce(outgoing_sms, msg);
01105 return SMSCCONN_QUEUED;
01106 }
01107 debug("bb.sms", 0, "bad_found queue full");
01108 return SMSCCONN_FAILED_QFULL; /* queue full */
01109 }
01110 else if (full_found) {
01111 gw_rwlock_unlock(&smsc_list_lock);
01112 debug("bb.sms", 0, "full_found queue full");
01113 return SMSCCONN_FAILED_QFULL;
01114 }
01115 else {
01116 gw_rwlock_unlock(&smsc_list_lock);
01117 if (bb_status == BB_SHUTDOWN) {
01118 msg_destroy(msg);
01119 return SMSCCONN_QUEUED;
01120 }
01121 warning(0, "Cannot find SMSCConn for message to <%s>, rejected.",
01122 octstr_get_cstr(msg->sms.receiver));
01123 bb_smscconn_send_failed(NULL, msg_duplicate(msg), SMSCCONN_FAILED_DISCARDED, octstr_create("no SMSC"));
01124 return SMSCCONN_FAILED_DISCARDED;
01125 }
01126
01127 gw_rwlock_unlock(&smsc_list_lock);
01128 /* check the status of sending operation */
01129 if (ret == -1)
01130 return smsc2_rout(msg, resend); /* re-try */
01131
01132 msg_destroy(msg);
01133 return SMSCCONN_SUCCESS;
01134 }
|
Here is the call graph for this function:

|
|
Definition at line 815 of file bb_smscconn.c. References gw_rwlock_rdlock(), gw_rwlock_unlock(), gwlist_get(), gwlist_len(), gwlist_remove_producer(), gwthread_wakeup(), incoming_sms, router_thread, smsc_list, smsc_list_lock, SMSCConn, and smscconn_shutdown(). Referenced by bb_shutdown(). 00816 {
00817 SMSCConn *conn;
00818 long i;
00819
00820 if (!smsc_running)
00821 return -1;
00822
00823 /* Call shutdown for all SMSC Connections; they should
00824 * handle that they quit, by emptying queues and then dying off
00825 */
00826 gw_rwlock_rdlock(&smsc_list_lock);
00827 for(i=0; i < gwlist_len(smsc_list); i++) {
00828 conn = gwlist_get(smsc_list, i);
00829 smscconn_shutdown(conn, 1);
00830 }
00831 gw_rwlock_unlock(&smsc_list_lock);
00832 if (router_thread >= 0)
00833 gwthread_wakeup(router_thread);
00834
00835 /* start avalanche by calling shutdown */
00836
00837 /* XXX shouldn'w we be sure that all smsces have closed their
00838 * receive thingies? Is this guaranteed by setting bb_status
00839 * to shutdown before calling these?
00840 */
00841 gwlist_remove_producer(incoming_sms);
00842 return 0;
00843 }
|
Here is the call graph for this function:

|
|
Definition at line 578 of file bb_smscconn.c. References black_list, black_list_regex, cfg_get, cfg_get_bool(), cfg_get_integer(), cfg_get_multi_group(), cfg_get_single_group(), concatenated_mo_timeout, counter_create(), gw_rwlock_init_static(), gwlist_add_producer(), gwlist_append(), gwlist_create, gwlist_get(), gwlist_len(), gwlist_remove_producer(), gwthread_create, handle_concatenated_mo, incoming_sms, info(), init_concat_handler(), numhash_create(), octstr_destroy(), octstr_get_cstr, octstr_imm(), panic, router_thread, sms_resend_frequency, sms_resend_retry, sms_router(), smsc_groups, smsc_list, smsc_list_lock, smsc_running, SMSCConn, smscconn_create(), split_msg_counter, unified_prefix, white_list, and white_list_regex. Referenced by start_smsc(). 00579 {
00580 CfgGroup *grp;
00581 SMSCConn *conn;
00582 Octstr *os;
00583 int i;
00584
00585 if (smsc_running) return -1;
00586
00587 /* create split sms counter */
00588 split_msg_counter = counter_create();
00589
00590 /* create smsc list and rwlock for it */
00591 smsc_list = gwlist_create();
00592 gw_rwlock_init_static(&smsc_list_lock);
00593
00594 grp = cfg_get_single_group(cfg, octstr_imm("core"));
00595 unified_prefix = cfg_get(grp, octstr_imm("unified-prefix"));
00596
00597 white_list = black_list = NULL;
00598 os = cfg_get(grp, octstr_imm("white-list"));
00599 if (os != NULL) {
00600 white_list = numhash_create(octstr_get_cstr(os));
00601 octstr_destroy(os);
00602 }
00603 if ((os = cfg_get(grp, octstr_imm("white-list-regex"))) != NULL) {
00604 if ((white_list_regex = gw_regex_comp(os, REG_EXTENDED)) == NULL)
00605 panic(0, "Could not compile pattern '%s'", octstr_get_cstr(os));
00606 octstr_destroy(os);
00607 }
00608
00609 os = cfg_get(grp, octstr_imm("black-list"));
00610 if (os != NULL) {
00611 black_list = numhash_create(octstr_get_cstr(os));
00612 octstr_destroy(os);
00613 }
00614 if ((os = cfg_get(grp, octstr_imm("black-list-regex"))) != NULL) {
00615 if ((black_list_regex = gw_regex_comp(os, REG_EXTENDED)) == NULL)
00616 panic(0, "Could not compile pattern '%s'", octstr_get_cstr(os));
00617 octstr_destroy(os);
00618 }
00619
00620 if (cfg_get_integer(&sms_resend_frequency, grp,
00621 octstr_imm("sms-resend-freq")) == -1 || sms_resend_frequency <= 0) {
00622 sms_resend_frequency = 60;
00623 }
00624 info(0, "Set SMS resend frequency to %ld seconds.", sms_resend_frequency);
00625
00626 if (cfg_get_integer(&sms_resend_retry, grp, octstr_imm("sms-resend-retry")) == -1) {
00627 sms_resend_retry = -1;
00628 info(0, "SMS resend retry set to unlimited.");
00629 }
00630 else
00631 info(0, "SMS resend retry set to %ld.", sms_resend_retry);
00632
00633 if (cfg_get_bool(&handle_concatenated_mo, grp, octstr_imm("sms-combine-concatenated-mo")) == -1)
00634 handle_concatenated_mo = 1; /* default is TRUE. */
00635
00636 if (cfg_get_integer(&concatenated_mo_timeout, grp, octstr_imm("sms-combine-concatenated-mo-timeout")) == -1)
00637 concatenated_mo_timeout = 1800;
00638
00639 if (handle_concatenated_mo)
00640 init_concat_handler();
00641
00642 smsc_groups = cfg_get_multi_group(cfg, octstr_imm("smsc"));
00643 gwlist_add_producer(smsc_list);
00644 for (i = 0; i < gwlist_len(smsc_groups) &&
00645 (grp = gwlist_get(smsc_groups, i)) != NULL; i++) {
00646 conn = smscconn_create(grp, 1);
00647 if (conn == NULL)
00648 panic(0, "Cannot start with SMSC connection failing");
00649 gwlist_append(smsc_list, conn);
00650 }
00651 gwlist_remove_producer(smsc_list);
00652
00653 if ((router_thread = gwthread_create(sms_router, NULL)) == -1)
00654 panic(0, "Failed to start a new thread for SMS routing");
00655
00656 gwlist_add_producer(incoming_sms);
00657 smsc_running = 1;
00658 return 0;
00659 }
|
Here is the call graph for this function:

|
|
Definition at line 883 of file bb_smscconn.c. References bb_status_linebreak(), BBSTATUS_HTML, smsc_state::failed, gw_rwlock_rdlock(), gw_rwlock_unlock(), gwlist_get(), gwlist_len(), info(), octstr_append(), octstr_append_cstr(), octstr_create, octstr_format(), octstr_format_append(), octstr_imm(), smsc_state::online, smsc_state::queued, smsc_state::received, smsc_state::sent, smsc_list, smsc_list_lock, SMSCConn, SMSCCONN_ACTIVE, SMSCCONN_ACTIVE_RECV, SMSCCONN_CONNECTING, SMSCCONN_DEAD, SMSCCONN_DISCONNECTED, smscconn_id(), smscconn_info(), smscconn_name(), SMSCCONN_RECONNECTING, smsc_state::status, and StatusInfo. Referenced by bb_print_status(). 00884 {
00885 Octstr *tmp;
00886 char tmp3[64];
00887 char *lb;
00888 long i;
00889 int para = 0;
00890 SMSCConn *conn;
00891 StatusInfo info;
00892 const Octstr *conn_id = NULL;
00893 const Octstr *conn_name = NULL;
00894
00895 if ((lb = bb_status_linebreak(status_type)) == NULL)
00896 return octstr_create("Un-supported format");
00897
00898 if (status_type == BBSTATUS_HTML || status_type == BBSTATUS_WML)
00899 para = 1;
00900
00901 if (!smsc_running) {
00902 if (status_type == BBSTATUS_XML)
00903 return octstr_create ("<smscs>\n\t<count>0</count>\n</smscs>");
00904 else
00905 return octstr_format("%sNo SMSC connections%s\n\n", para ? "<p>" : "",
00906 para ? "</p>" : "");
00907 }
00908
00909 if (status_type != BBSTATUS_XML)
00910 tmp = octstr_format("%sSMSC connections:%s", para ? "<p>" : "", lb);
00911 else
00912 tmp = octstr_format("<smscs><count>%d</count>\n\t", gwlist_len(smsc_list));
00913
00914 gw_rwlock_rdlock(&smsc_list_lock);
00915 for (i = 0; i < gwlist_len(smsc_list); i++) {
00916 conn = gwlist_get(smsc_list, i);
00917
00918 if ((smscconn_info(conn, &info) == -1)) {
00919 /*
00920 * we do not delete SMSCs from the list
00921 * this way we can show in the status which links are dead
00922 */
00923 continue;
00924 }
00925
00926 conn_id = conn ? smscconn_id(conn) : octstr_imm("unknown");
00927 conn_id = conn_id ? conn_id : octstr_imm("unknown");
00928 conn_name = conn ? smscconn_name(conn) : octstr_imm("unknown");
00929
00930 if (status_type == BBSTATUS_HTML) {
00931 octstr_append_cstr(tmp, " <b>");
00932 octstr_append(tmp, conn_id);
00933 octstr_append_cstr(tmp, "</b> ");
00934 } else if (status_type == BBSTATUS_TEXT) {
00935 octstr_append_cstr(tmp, " ");
00936 octstr_append(tmp, conn_id);
00937 octstr_append_cstr(tmp, " ");
00938 }
00939 if (status_type == BBSTATUS_XML) {
00940 octstr_append_cstr(tmp, "<smsc>\n\t\t<name>");
00941 octstr_append(tmp, conn_name);
00942 octstr_append_cstr(tmp, "</name>\n\t\t");
00943 octstr_append_cstr(tmp, "<id>");
00944 octstr_append(tmp, conn_id);
00945 octstr_append_cstr(tmp, "</id>\n\t\t");
00946 } else
00947 octstr_append(tmp, conn_name);
00948
00949 switch (info.status) {
00950 case SMSCCONN_ACTIVE:
00951 case SMSCCONN_ACTIVE_RECV:
00952 sprintf(tmp3, "online %lds", info.online);
00953 break;
00954 case SMSCCONN_DISCONNECTED:
00955 sprintf(tmp3, "disconnected");
00956 break;
00957 case SMSCCONN_CONNECTING:
00958 sprintf(tmp3, "connecting");
00959 break;
00960 case SMSCCONN_RECONNECTING:
00961 sprintf(tmp3, "re-connecting");
00962 break;
00963 case SMSCCONN_DEAD:
00964 sprintf(tmp3, "dead");
00965 break;
00966 default:
00967 sprintf(tmp3, "unknown");
00968 }
00969
00970 if (status_type == BBSTATUS_XML)
00971 octstr_format_append(tmp, "<status>%s</status>\n\t\t<received>%ld</received>"
00972 "\n\t\t<sent>%ld</sent>\n\t\t<failed>%ld</failed>\n\t\t"
00973 "<queued>%ld</queued>\n\t</smsc>\n", tmp3,
00974 info.received, info.sent, info.failed,
00975 info.queued);
00976 else
00977 octstr_format_append(tmp, " (%s, rcvd %ld, sent %ld, failed %ld, "
00978 "queued %ld msgs)%s", tmp3,
00979 info.received, info.sent, info.failed,
00980 info.queued, lb);
00981 }
00982 gw_rwlock_unlock(&smsc_list_lock);
00983
00984 if (para)
00985 octstr_append_cstr(tmp, "</p>");
00986 if (status_type == BBSTATUS_XML)
00987 octstr_append_cstr(tmp, "</smscs>\n");
00988 else
00989 octstr_append_cstr(tmp, "\n\n");
00990 return tmp;
00991 }
|
Here is the call graph for this function:

|
|
Definition at line 684 of file bb_smscconn.c. References gw_rwlock_rdlock(), gw_rwlock_unlock(), gwlist_get(), info(), octstr_get_cstr, smsc2_find(), smsc_list, smsc_list_lock, SMSCConn, smscconn_shutdown(), and smscconn_status(). Referenced by bb_stop_smsc(). 00685 {
00686 SMSCConn *conn;
00687 long i = -1;
00688
00689 if (!smsc_running)
00690 return -1;
00691
00692 gw_rwlock_rdlock(&smsc_list_lock);
00693 /* find the specific smsc via id */
00694 while((i = smsc2_find(id, ++i)) != -1) {
00695 conn = gwlist_get(smsc_list, i);
00696 if (conn != NULL && smscconn_status(conn) == SMSCCONN_DEAD) {
00697 info(0, "HTTP: Could not shutdown already dead smsc-id `%s'",
00698 octstr_get_cstr(id));
00699 } else {
00700 info(0,"HTTP: Shutting down smsc-id `%s'", octstr_get_cstr(id));
00701 smscconn_shutdown(conn, 1); /* shutdown the smsc */
00702 }
00703 }
00704 gw_rwlock_unlock(&smsc_list_lock);
00705 return 0;
00706 }
|
Here is the call graph for this function:

|
|
Definition at line 798 of file bb_smscconn.c. References gw_rwlock_rdlock(), gw_rwlock_unlock(), gwlist_get(), gwlist_len(), smsc_list, smsc_list_lock, SMSCConn, and smscconn_stop(). Referenced by bb_isolate(), and bb_suspend(). 00799 {
00800 SMSCConn *conn;
00801 long i;
00802
00803 if (!smsc_running)
00804 return;
00805
00806 gw_rwlock_rdlock(&smsc_list_lock);
00807 for (i = 0; i < gwlist_len(smsc_list); i++) {
00808 conn = gwlist_get(smsc_list, i);
00809 smscconn_stop(conn);
00810 }
00811 gw_rwlock_unlock(&smsc_list_lock);
00812 }
|
Here is the call graph for this function:

|
|
Definition at line 120 of file bearerbox.c. |
|
|
Definition at line 120 of file bb_smscconn.c. Referenced by bb_smscconn_receive(), smsc2_cleanup(), and smsc2_start(). |
|
|
Definition at line 124 of file bb_smscconn.c. Referenced by bb_smscconn_receive(), smsc2_cleanup(), and smsc2_start(). |
|
|
Definition at line 1210 of file bb_smscconn.c. Referenced by check_concatenation(), clear_old_concat_parts(), init_concat_handler(), and shutdown_concat_handler(). |
|
|
Definition at line 141 of file bb_smscconn.c. Referenced by sms_router(), and smsc2_start(). |
|
|
Definition at line 107 of file bearerbox.c. |
|
|
Definition at line 139 of file bb_smscconn.c. Referenced by bb_smscconn_receive(), and smsc2_start(). |
|
|
Definition at line 1209 of file bb_smscconn.c. Referenced by check_concatenation(), clear_old_concat_parts(), init_concat_handler(), and shutdown_concat_handler(). |
|
|
Definition at line 83 of file bearerbox.c. |
|
|
Definition at line 89 of file bearerbox.c. Referenced by bb_print_status(), bb_smscconn_receive(), empty_msg_lists(), and init_bearerbox(). |
|
|
Definition at line 118 of file bearerbox.c. Referenced by bb_isolate(), bb_resume(), bb_suspend(), main(), set_shutdown_status(), and udp_receiver(). |
|
|
Definition at line 95 of file bearerbox.c. |
|
|
Definition at line 96 of file bearerbox.c. Referenced by init_bearerbox(), and smsc2_rout(). |
|
|
Definition at line 84 of file bearerbox.c. |
|
|
Definition at line 90 of file bearerbox.c. Referenced by bb_print_status(), bb_smscconn_sent(), empty_msg_lists(), and init_bearerbox(). |
|
|
Definition at line 126 of file bb_smscconn.c. Referenced by bb_smscconn_connected(), smsc2_restart_smsc(), smsc2_resume(), smsc2_shutdown(), and smsc2_start(). |
|
|
Definition at line 129 of file bb_smscconn.c. Referenced by sms_router(), and smsc2_start(). |
|
|
Definition at line 130 of file bb_smscconn.c. Referenced by bb_smscconn_send_failed(), and smsc2_start(). |
|
|
Definition at line 117 of file bb_smscconn.c. Referenced by smsc2_cleanup(), smsc2_restart_smsc(), and smsc2_start(). |
|
|
Definition at line 115 of file bb_smscconn.c. Referenced by smsc2_cleanup(), smsc2_find(), smsc2_restart_smsc(), smsc2_resume(), smsc2_rout(), smsc2_shutdown(), smsc2_start(), smsc2_status(), smsc2_stop_smsc(), and smsc2_suspend(). |
|
|
Definition at line 116 of file bb_smscconn.c. Referenced by smsc2_cleanup(), smsc2_restart_smsc(), smsc2_resume(), smsc2_rout(), smsc2_shutdown(), smsc2_start(), smsc2_status(), smsc2_stop_smsc(), and smsc2_suspend(). |
|
|
Definition at line 114 of file bb_smscconn.c. Referenced by smsc2_cleanup(), and smsc2_start(). |
|
|
Definition at line 136 of file bb_smscconn.c. Referenced by smsc2_cleanup(), smsc2_start(), and smscconn_send(). |
|
|
Definition at line 113 of file bearerbox.c. |
|
|
Definition at line 118 of file bb_smscconn.c. Referenced by bb_smscconn_receive(), smsc2_cleanup(), smsc2_rout(), and smsc2_start(). |
|
|
Definition at line 121 of file bb_smscconn.c. Referenced by bb_smscconn_receive(), smsc2_cleanup(), and smsc2_start(). |
|
|
Definition at line 123 of file bb_smscconn.c. Referenced by bb_smscconn_receive(), smsc2_cleanup(), and smsc2_start(). |