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

bb_boxc.c File Reference

#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <string.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <signal.h>
#include "gwlib/gwlib.h"
#include "msg.h"
#include "bearerbox.h"
#include "bb_smscconn_cb.h"

Include dependency graph for bb_boxc.c:

Include dependency graph

Go to the source code of this file.

Data Structures

struct  _boxc
struct  _addrpar

Defines

#define SMSBOX_MAX_PENDING   100

Typedefs

typedef _boxc Boxc
typedef _addrpar AddrPar

Functions

void sms_to_smsboxes (void *arg)
int send_msg (Boxc *boxconn, Msg *pmsg)
void boxc_sent_push (Boxc *, Msg *)
void boxc_sent_pop (Boxc *, Msg *, Msg **)
Msgread_from_box (Boxc *boxconn)
void deliver_sms_to_queue (Msg *msg, Boxc *conn)
void boxc_receiver (void *arg)
void boxc_sender (void *arg)
Boxcboxc_create (int fd, Octstr *ip, int ssl)
void boxc_destroy (Boxc *boxc)
Boxcaccept_boxc (int fd, int ssl)
void run_smsbox (void *arg)
void run_wapbox (void *arg)
void ap_destroy (AddrPar *addr)
int cmp_route (void *ap, void *ms)
int cmp_boxc (void *bc, void *ap)
Boxcroute_msg (List *route_info, Msg *msg)
void wdp_to_wapboxes (void *arg)
void wait_for_connections (int fd, void(*function)(void *arg), List *waited, int ssl)
void smsboxc_run (void *arg)
void wapboxc_run (void *arg)
void init_smsbox_routes (Cfg *cfg)
int smsbox_start (Cfg *cfg)
int smsbox_restart (Cfg *cfg)
int wapbox_start (Cfg *cfg)
Octstrboxc_status (int status_type)
int boxc_incoming_wdp_queue (void)
void boxc_cleanup (void)
int route_incoming_to_boxc (Msg *msg)

Variables

volatile sig_atomic_t bb_status
volatile sig_atomic_t restart
Listincoming_sms
Listoutgoing_sms
Listincoming_wdp
Listoutgoing_wdp
Listflow_threads
Listsuspended
long max_incoming_sms_qlength
volatile sig_atomic_t smsbox_running
volatile sig_atomic_t wapbox_running
Listwapbox_list
Listsmsbox_list
RWLocksmsbox_list_rwlock
Dictsmsbox_by_id
Dictsmsbox_by_smsc
Dictsmsbox_by_receiver
Dictsmsbox_by_smsc_receiver
long smsbox_port
int smsbox_port_ssl
long wapbox_port
int wapbox_port_ssl
long smsbox_max_pending
Octstrbox_allow_ip
Octstrbox_deny_ip
Counterboxid
long sms_dequeue_thread


Define Documentation

#define SMSBOX_MAX_PENDING   100
 

Definition at line 83 of file bb_boxc.c.


Typedef Documentation

typedef struct _addrpar AddrPar
 

Referenced by ap_destroy(), cmp_boxc(), cmp_route(), route_msg(), and wdp_to_wapboxes().

typedef struct _boxc Boxc
 

Referenced by accept_boxc(), boxc_create(), boxc_destroy(), boxc_incoming_wdp_queue(), boxc_receiver(), boxc_sender(), boxc_sent_pop(), boxc_sent_push(), boxc_status(), cmp_boxc(), deliver_sms_to_queue(), read_from_box(), route_incoming_to_boxc(), route_msg(), run_smsbox(), run_wapbox(), send_msg(), sms_to_smsboxes(), wait_for_connections(), and wdp_to_wapboxes().


Function Documentation

Boxc* accept_boxc int  fd,
int  ssl
[static]
 

Definition at line 542 of file bb_boxc.c.

References box_allow_ip, box_deny_ip, Boxc, boxc_create(), _boxc::conn, conn_get_ssl(), host_ip(), info(), is_allowed_ip(), octstr_destroy(), octstr_get_cstr, and ssl.

Referenced by wait_for_connections().

00543 {
00544     Boxc *newconn;
00545     Octstr *ip;
00546 
00547     int newfd;
00548     struct sockaddr_in client_addr;
00549     socklen_t client_addr_len;
00550 
00551     client_addr_len = sizeof(client_addr);
00552 
00553     newfd = accept(fd, (struct sockaddr *)&client_addr, &client_addr_len);
00554     if (newfd < 0)
00555         return NULL;
00556 
00557     ip = host_ip(client_addr);
00558 
00559     if (is_allowed_ip(box_allow_ip, box_deny_ip, ip) == 0) {
00560         info(0, "Box connection tried from denied host <%s>, disconnected",
00561                 octstr_get_cstr(ip));
00562         octstr_destroy(ip);
00563         close(newfd);
00564         return NULL;
00565     }
00566     newconn = boxc_create(newfd, ip, ssl);
00567 
00568     /*
00569      * check if the SSL handshake was successfull, otherwise
00570      * this is no valid box connection any more
00571      */
00572 #ifdef HAVE_LIBSSL
00573      if (ssl && !conn_get_ssl(newconn->conn))
00574         return NULL;
00575 #endif
00576 
00577     info(0, "Client connected from <%s> %s", octstr_get_cstr(ip), ssl?"using SSL":"");
00578 
00579     /* XXX TODO: do the hand-shake, baby, yeah-yeah! */
00580 
00581     return newconn;
00582 }

Here is the call graph for this function:

void ap_destroy AddrPar addr  )  [static]
 

Definition at line 744 of file bb_boxc.c.

References _addrpar::address, AddrPar, and octstr_destroy().

Referenced by route_msg(), and wdp_to_wapboxes().

00745 {
00746     octstr_destroy(addr->address);
00747     gw_free(addr);
00748 }

Here is the call graph for this function:

void boxc_cleanup void   ) 
 

Definition at line 1395 of file bb_boxc.c.

References box_allow_ip, box_deny_ip, boxid, counter_destroy(), and octstr_destroy().

Referenced by main().

01396 {
01397     octstr_destroy(box_allow_ip);
01398     octstr_destroy(box_deny_ip);
01399     box_allow_ip = NULL;
01400     box_deny_ip = NULL;
01401     counter_destroy(boxid);
01402     boxid = NULL;
01403 }

Here is the call graph for this function:

Boxc* boxc_create int  fd,
Octstr ip,
int  ssl
[static]
 

Definition at line 509 of file bb_boxc.c.

References _boxc::alive, Boxc, _boxc::boxc_id, boxid, _boxc::client_ip, _boxc::conn, conn_wrap_fd(), _boxc::connect_time, counter_increase(), _boxc::id, _boxc::is_wap, _boxc::load, _boxc::routable, and ssl.

Referenced by accept_boxc().

00510 {
00511     Boxc *boxc;
00512 
00513     boxc = gw_malloc(sizeof(Boxc));
00514     boxc->is_wap = 0;
00515     boxc->load = 0;
00516     boxc->conn = conn_wrap_fd(fd, ssl);
00517     boxc->id = counter_increase(boxid);
00518     boxc->client_ip = ip;
00519     boxc->alive = 1;
00520     boxc->connect_time = time(NULL);
00521     boxc->boxc_id = NULL;
00522     boxc->routable = 0;
00523     return boxc;
00524 }

Here is the call graph for this function:

void boxc_destroy Boxc boxc  )  [static]
 

Definition at line 526 of file bb_boxc.c.

References Boxc, _boxc::boxc_id, _boxc::client_ip, _boxc::conn, conn_destroy(), and octstr_destroy().

Referenced by run_smsbox(), and run_wapbox().

00527 {
00528     if (boxc == NULL)
00529         return;
00530 
00531     /* do nothing to the lists, as they are only references */
00532 
00533     if (boxc->conn)
00534         conn_destroy(boxc->conn);
00535     octstr_destroy(boxc->client_ip);
00536     octstr_destroy(boxc->boxc_id);
00537     gw_free(boxc);
00538 }

Here is the call graph for this function:

int boxc_incoming_wdp_queue void   ) 
 

Definition at line 1378 of file bb_boxc.c.

References Boxc, gwlist_get(), gwlist_len(), gwlist_lock(), gwlist_unlock(), _boxc::incoming, and wapbox_list.

Referenced by bb_print_status().

01379 {
01380     int i, q = 0;
01381     Boxc *boxc;
01382     
01383     if (wapbox_list) {
01384         gwlist_lock(wapbox_list);
01385         for(i=0; i < gwlist_len(wapbox_list); i++) {
01386             boxc = gwlist_get(wapbox_list, i);
01387             q += gwlist_len(boxc->incoming);
01388         }
01389         gwlist_unlock(wapbox_list);
01390     }
01391     return q;
01392 }

Here is the call graph for this function:

void boxc_receiver void *  arg  )  [static]
 

Definition at line 257 of file bb_boxc.c.

References ack, admin, _boxc::alive, BB_DEAD, BB_SHUTDOWN, bb_status, Boxc, _boxc::boxc_id, boxc_sent_pop(), _boxc::client_ip, debug(), deliver_sms_to_queue(), dict_put(), dict_remove(), gwlist_append(), gwlist_consume(), gwlist_produce(), gwthread_wakeup(), _boxc::is_wap, _boxc::load, msg_create, msg_destroy(), msg_type, octstr_destroy(), octstr_get_cstr, _boxc::outgoing, read_from_box(), _boxc::retry, _boxc::routable, send_msg(), sms, sms_dequeue_thread, smsbox_by_id, store_save, suspended, uuid_copy(), warning(), and wdp_datagram.

Referenced by run_smsbox(), and run_wapbox().

00258 {
00259     Boxc *conn = arg;
00260     Msg *msg, *mack;
00261 
00262     /* remove messages from socket until it is closed */
00263     while (bb_status != BB_DEAD && conn->alive) {
00264 
00265         gwlist_consume(suspended);  /* block here if suspended */
00266 
00267         msg = read_from_box(conn);
00268 
00269         if (msg == NULL) {  /* garbage/connection lost */
00270             conn->alive = 0;
00271             break;
00272         }
00273 
00274         /* we don't accept new messages in shutdown phase */
00275         if ((bb_status == BB_SHUTDOWN || bb_status == BB_DEAD) && msg_type(msg) == sms) {
00276             mack = msg_create(ack);
00277             uuid_copy(mack->ack.id, msg->sms.id);
00278             mack->ack.time = msg->sms.time;
00279             mack->ack.nack = ack_failed_tmp;
00280             msg_destroy(msg);
00281             send_msg(conn, mack);
00282             msg_destroy(mack);
00283             continue;
00284         }
00285 
00286         if (msg_type(msg) == sms && conn->is_wap == 0) {
00287             debug("bb.boxc", 0, "boxc_receiver: sms received");
00288 
00289             /* deliver message to queue */
00290             deliver_sms_to_queue(msg, conn);
00291 
00292             if (conn->routable == 0) {
00293                 conn->routable = 1;
00294                 /* wakeup the dequeue thread */
00295                 gwthread_wakeup(sms_dequeue_thread);
00296             }
00297         } else if (msg_type(msg) == wdp_datagram && conn->is_wap) {
00298             debug("bb.boxc", 0, "boxc_receiver: got wdp from wapbox");
00299 
00300             /* XXX we should block these in SHUTDOWN phase too, but
00301                we need ack/nack msgs implemented first. */
00302             gwlist_produce(conn->outgoing, msg);
00303 
00304         } else if (msg_type(msg) == sms && conn->is_wap) {
00305             debug("bb.boxc", 0, "boxc_receiver: got sms from wapbox");
00306 
00307             /* should be a WAP push message, so tried it the same way */
00308             deliver_sms_to_queue(msg, conn);
00309 
00310             if (conn->routable == 0) {
00311                 conn->routable = 1;
00312                 /* wakeup the dequeue thread */
00313                 gwthread_wakeup(sms_dequeue_thread);
00314             }
00315         } else {
00316             if (msg_type(msg) == heartbeat) {
00317                 if (msg->heartbeat.load != conn->load)
00318                     debug("bb.boxc", 0, "boxc_receiver: heartbeat with "
00319                           "load value %ld received", msg->heartbeat.load);
00320                 conn->load = msg->heartbeat.load;
00321             }
00322             else if (msg_type(msg) == ack) {
00323                 if (msg->ack.nack == ack_failed_tmp) {
00324                     Msg *orig;
00325                     boxc_sent_pop(conn, msg, &orig);
00326                     if (orig != NULL) /* retry this message */
00327                         gwlist_append(conn->retry, orig);
00328                 } else {
00329                     boxc_sent_pop(conn, msg, NULL);
00330                     store_save(msg);
00331                 }
00332                 debug("bb.boxc", 0, "boxc_receiver: got ack");
00333             }
00334             /* if this is an identification message from an smsbox instance */
00335             else if (msg_type(msg) == admin && msg->admin.command == cmd_identify) {
00336 
00337                 /*
00338                  * any smsbox sends this command even if boxc_id is NULL,
00339                  * but we will only consider real identified boxes
00340                  */
00341                 if (msg->admin.boxc_id != NULL) {
00342 
00343                     /* and add the boxc_id into conn for boxc_status() output */
00344                     if (conn->boxc_id != NULL) {
00345                         dict_remove(smsbox_by_id, msg->admin.boxc_id);
00346                         octstr_destroy(conn->boxc_id);
00347                     }
00348 
00349                     conn->boxc_id = msg->admin.boxc_id;
00350                     msg->admin.boxc_id = NULL;
00351 
00352                     /* add this identified smsbox to the dictionary */
00353                     /* XXX check for equal boxc_id in Dict, otherwise we overwrite it */
00354                     dict_put(smsbox_by_id, conn->boxc_id, conn);
00355                     debug("bb.boxc", 0, "boxc_receiver: got boxc_id <%s> from <%s>",
00356                           octstr_get_cstr(conn->boxc_id),
00357                           octstr_get_cstr(conn->client_ip));
00358                 }
00359 
00360                 conn->routable = 1;
00361                 /* wakeup the dequeue thread */
00362                 gwthread_wakeup(sms_dequeue_thread);
00363             }
00364             else
00365                 warning(0, "boxc_receiver: unknown msg received from <%s>, "
00366                            "ignored", octstr_get_cstr(conn->client_ip));
00367             msg_destroy(msg);
00368         }
00369     }
00370 }

Here is the call graph for this function:

void boxc_sender void *  arg  )  [static]
 

Definition at line 454 of file bb_boxc.c.

References admin, _boxc::alive, BB_DEAD, bb_status, Boxc, boxc_sent_pop(), boxc_sent_push(), _boxc::client_ip, cmd_restart, _boxc::conn, conn_flush(), debug(), flow_threads, gwlist_add_producer(), gwlist_consume(), gwlist_produce(), gwlist_remove_producer(), _boxc::incoming, msg_create, msg_destroy(), msg_type, octstr_get_cstr, restart, _boxc::retry, _boxc::routable, send_msg(), and suspended.

Referenced by run_smsbox(), and run_wapbox().

00455 {
00456     Msg *msg;
00457     Boxc *conn = arg;
00458 
00459     gwlist_add_producer(flow_threads);
00460 
00461     while (bb_status != BB_DEAD && conn->alive) {
00462 
00463         /*
00464          * Make sure there's no data left in the outgoing connection before
00465          * doing the potentially blocking gwlist_consume()s
00466          */
00467         conn_flush(conn->conn);
00468 
00469         gwlist_consume(suspended);  /* block here if suspended */
00470 
00471         if ((msg = gwlist_consume(conn->incoming)) == NULL) {
00472             /* tell sms/wapbox to die */
00473             msg = msg_create(admin);
00474             msg->admin.command = restart ? cmd_restart : cmd_shutdown;
00475             send_msg(conn, msg);
00476             msg_destroy(msg);
00477             break;
00478         }
00479         if (msg_type(msg) == heartbeat) {
00480             debug("bb.boxc", 0, "boxc_sender: catch an heartbeat - we are alive");
00481             msg_destroy(msg);
00482             continue;
00483         }
00484         boxc_sent_push(conn, msg);
00485         if (!conn->alive || send_msg(conn, msg) == -1) {
00486             /* we got message here */
00487             boxc_sent_pop(conn, msg, NULL);
00488             gwlist_produce(conn->retry, msg);
00489             break;
00490         }
00491         msg_destroy(msg);
00492         debug("bb.boxc", 0, "boxc_sender: sent message to <%s>",
00493                octstr_get_cstr(conn->client_ip));
00494     }
00495     /* the client closes the connection, after that die in receiver */
00496     /* conn->alive = 0; */
00497 
00498     /* set conn to unroutable */
00499     conn->routable = 0;
00500 
00501     gwlist_remove_producer(flow_threads);
00502 }

Here is the call graph for this function:

void boxc_sent_pop Boxc ,
Msg ,
Msg ** 
[static]
 

Definition at line 425 of file bb_boxc.c.

References ack, Boxc, dict_remove(), error(), _boxc::is_wap, m, msg_destroy(), msg_dump(), msg_type, octstr_create, octstr_destroy(), _boxc::pending, semaphore_up(), _boxc::sent, sms, UUID_STR_LEN, and uuid_unparse().

Referenced by boxc_receiver(), and boxc_sender().

00426 {
00427     Octstr *os;
00428     char id[UUID_STR_LEN + 1];
00429     Msg *msg;
00430 
00431     if (conn->is_wap || !conn->sent || !m || (msg_type(m) != ack && msg_type(m) != sms))
00432         return;
00433 
00434     if (orig != NULL)
00435         *orig = NULL;
00436     
00437     uuid_unparse((msg_type(m) == sms ? m->sms.id : m->ack.id), id);
00438     os = octstr_create(id);
00439     msg = dict_remove(conn->sent, os);
00440     octstr_destroy(os);
00441     if (!msg) {
00442         error(0, "BOXC: Got ack for nonexistend message!");
00443         msg_dump(m, 0);
00444         return;
00445     }
00446     semaphore_up(conn->pending);
00447     if (orig == NULL)
00448         msg_destroy(msg);
00449     else
00450         *orig = msg;
00451 }

Here is the call graph for this function:

void boxc_sent_push Boxc ,
Msg
[static]
 

Definition at line 405 of file bb_boxc.c.

References Boxc, dict_put(), _boxc::is_wap, m, msg_duplicate(), msg_type, octstr_create, octstr_destroy(), _boxc::pending, semaphore_down(), _boxc::sent, UUID_STR_LEN, and uuid_unparse().

Referenced by boxc_sender().

00406 {
00407     Octstr *os;
00408     char id[UUID_STR_LEN + 1];
00409     
00410     if (conn->is_wap || !conn->sent || !m || msg_type(m) != sms)
00411         return;
00412     
00413     uuid_unparse(m->sms.id, id);
00414     os = octstr_create(id);
00415     dict_put(conn->sent, os, msg_duplicate(m));
00416     semaphore_down(conn->pending);
00417     octstr_destroy(os);
00418 }

Here is the call graph for this function:

Octstr* boxc_status int  status_type  ) 
 

Definition at line 1254 of file bb_boxc.c.

References _boxc::alive, bb_status_linebreak(), BBSTATUS_HTML, Boxc, _boxc::boxc_id, _boxc::client_ip, _boxc::conn, conn_get_ssl(), _boxc::connect_time, dict_key_count(), gw_rwlock_rdlock(), gw_rwlock_unlock(), gwlist_get(), gwlist_len(), gwlist_lock(), gwlist_unlock(), HAVE_LIBSSL, _boxc::incoming, octstr_append_cstr(), octstr_create, octstr_destroy(), octstr_format(), octstr_format_append(), octstr_get_cstr, _boxc::sent, smsbox_list, smsbox_list_rwlock, and wapbox_list.

Referenced by bb_print_status().

01255 {
01256     Octstr *tmp;
01257     char *lb, *ws;
01258     int i, boxes, para = 0;
01259     time_t orig, t;
01260     Boxc *bi;
01261 
01262     orig = time(NULL);
01263 
01264     /*
01265      * XXX: this will cause segmentation fault if this is called
01266      *    between 'destroy_list and setting list to NULL calls.
01267      *    Ok, this has to be fixed, but now I am too tired.
01268      */
01269     
01270     if ((lb = bb_status_linebreak(status_type))==NULL)
01271         return octstr_create("Un-supported format");
01272 
01273     if (status_type == BBSTATUS_HTML)
01274         ws = "&nbsp;&nbsp;&nbsp;&nbsp;";
01275     else if (status_type == BBSTATUS_TEXT)
01276         ws = "    ";
01277     else
01278         ws = "";
01279 
01280     if (status_type == BBSTATUS_HTML || status_type == BBSTATUS_WML)
01281         para = 1;
01282     
01283     if (status_type == BBSTATUS_XML) {
01284         tmp = octstr_create ("");
01285         octstr_append_cstr(tmp, "<boxes>\n\t");
01286     }
01287     else
01288         tmp = octstr_format("%sBox connections:%s", para ? "<p>" : "", lb);
01289     boxes = 0;
01290     
01291     if (wapbox_list) {
01292         gwlist_lock(wapbox_list);
01293         for(i=0; i < gwlist_len(wapbox_list); i++) {
01294             bi = gwlist_get(wapbox_list, i);
01295             if (bi->alive == 0)
01296                 continue;
01297             t = orig - bi->connect_time;
01298             if (status_type == BBSTATUS_XML)
01299                 octstr_format_append(tmp,
01300                 "<box>\n\t\t<type>wapbox</type>\n\t\t<IP>%s</IP>\n"
01301                 "\t\t<status>on-line %ldd %ldh %ldm %lds</status>\n"
01302                 "\t\t<ssl>%s</ssl>\n\t</box>\n",
01303                 octstr_get_cstr(bi->client_ip),
01304                 t/3600/24, t/3600%24, t/60%60, t%60,
01305 #ifdef HAVE_LIBSSL
01306                 conn_get_ssl(bi->conn) != NULL ? "yes" : "no"
01307 #else 
01308                 "not installed"
01309 #endif
01310                 );
01311             else
01312                 octstr_format_append(tmp,
01313                 "%swapbox, IP %s (on-line %ldd %ldh %ldm %lds) %s %s",
01314                 ws, octstr_get_cstr(bi->client_ip),
01315                 t/3600/24, t/3600%24, t/60%60, t%60, 
01316 #ifdef HAVE_LIBSSL
01317                 conn_get_ssl(bi->conn) != NULL ? "using SSL" : "",
01318 #else
01319                 "",
01320 #endif 
01321                 lb);
01322                 boxes++;
01323            }
01324            gwlist_unlock(wapbox_list);
01325         }
01326         if (smsbox_list) {
01327             gw_rwlock_rdlock(smsbox_list_rwlock);
01328         for(i=0; i < gwlist_len(smsbox_list); i++) {
01329             bi = gwlist_get(smsbox_list, i);
01330             if (bi->alive == 0)
01331                 continue;
01332             t = orig - bi->connect_time;
01333             if (status_type == BBSTATUS_XML)
01334                 octstr_format_append(tmp, "<box>\n\t\t<type>smsbox</type>\n"
01335                     "\t\t<id>%s</id>\n\t\t<IP>%s</IP>\n"
01336                     "\t\t<queue>%ld</queue>\n"
01337                     "\t\t<status>on-line %ldd %ldh %ldm %lds</status>\n"
01338                     "\t\t<ssl>%s</ssl>\n\t</box>",
01339                     (bi->boxc_id ? octstr_get_cstr(bi->boxc_id) : ""),
01340                     octstr_get_cstr(bi->client_ip),
01341                     gwlist_len(bi->incoming) + dict_key_count(bi->sent),
01342                     t/3600/24, t/3600%24, t/60%60, t%60,
01343 #ifdef HAVE_LIBSSL
01344                     conn_get_ssl(bi->conn) != NULL ? "yes" : "no"
01345 #else 
01346                     "not installed"
01347 #endif
01348                     );
01349             else
01350                 octstr_format_append(tmp, "%ssmsbox:%s, IP %s (%ld queued), (on-line %ldd %ldh %ldm %lds) %s %s",
01351                     ws, (bi->boxc_id ? octstr_get_cstr(bi->boxc_id) : "(none)"), 
01352                     octstr_get_cstr(bi->client_ip), gwlist_len(bi->incoming) + dict_key_count(bi->sent),
01353                     t/3600/24, t/3600%24, t/60%60, t%60, 
01354 #ifdef HAVE_LIBSSL
01355                     conn_get_ssl(bi->conn) != NULL ? "using SSL" : "",
01356 #else
01357                     "",
01358 #endif 
01359                     lb);
01360            boxes++;
01361         }
01362         gw_rwlock_unlock(smsbox_list_rwlock);
01363     }
01364     if (boxes == 0 && status_type != BBSTATUS_XML) {
01365         octstr_destroy(tmp);
01366         tmp = octstr_format("%sNo boxes connected", para ? "<p>" : "");
01367     }
01368     if (para)
01369         octstr_append_cstr(tmp, "</p>");
01370     if (status_type == BBSTATUS_XML)
01371         octstr_append_cstr(tmp, "</boxes>\n");
01372     else
01373         octstr_append_cstr(tmp, "\n\n");
01374     return tmp;
01375 }

Here is the call graph for this function:

int cmp_boxc void *  bc,
void *  ap
[static]
 

Definition at line 762 of file bb_boxc.c.

References AddrPar, Boxc, _boxc::id, and _addrpar::wapboxid.

Referenced by route_msg().

00763 {
00764     Boxc *boxc = bc;
00765     AddrPar *addr = ap;
00766 
00767     if (boxc->id == addr->wapboxid) return 1;
00768         return 0;
00769 }

int cmp_route void *  ap,
void *  ms
[static]
 

Definition at line 750 of file bb_boxc.c.

References _addrpar::address, AddrPar, octstr_compare(), and _addrpar::port.

Referenced by route_msg().

00751 {
00752     AddrPar *addr = ap;
00753     Msg *msg = ms;
00754     
00755     if (msg->wdp_datagram.source_port == addr->port  &&
00756         octstr_compare(msg->wdp_datagram.source_address, addr->address)==0)
00757     return 1;
00758 
00759     return 0;
00760 }

Here is the call graph for this function:

void deliver_sms_to_queue Msg msg,
Boxc conn
[static]
 

Definition at line 211 of file bb_boxc.c.

References ack, ack_failed, ack_failed_tmp, Boxc, gw_assert, msg_create, msg_destroy(), send_msg(), smsc2_rout(), SMSCCONN_FAILED_DISCARDED, SMSCCONN_FAILED_QFULL, SMSCCONN_QUEUED, SMSCCONN_SUCCESS, store_save, store_save_ack, uuid_copy(), and warning().

Referenced by boxc_receiver().

00212 {
00213     Msg *mack;
00214     int rc;
00215 
00216     /*
00217      * save modifies ID and time, so if the smsbox uses it, save
00218      * it FIRST for the reply message!!!
00219      */
00220     mack = msg_create(ack);
00221     gw_assert(mack != NULL);
00222     uuid_copy(mack->ack.id, msg->sms.id);
00223     mack->ack.time = msg->sms.time;
00224 
00225     store_save(msg);
00226 
00227     rc = smsc2_rout(msg, 0);
00228     switch(rc) {
00229         case SMSCCONN_SUCCESS:
00230            mack->ack.nack = ack_success;
00231            break;
00232         case SMSCCONN_QUEUED:
00233            mack->ack.nack = ack_buffered;
00234            break;
00235         case SMSCCONN_FAILED_DISCARDED: /* no router at all */
00236         case SMSCCONN_FAILED_QFULL: /* queue full */
00237            warning(0, "Message rejected by bearerbox, %s!",
00238                              (rc == SMSCCONN_FAILED_DISCARDED) ? "no router" : "queue full");
00239            /*
00240             * first create nack for store-file, in order to delete
00241             * message from store-file.
00242             */
00243            store_save_ack(msg, (rc == SMSCCONN_FAILED_QFULL ? ack_failed_tmp : ack_failed));
00244            mack->ack.nack = (rc == SMSCCONN_FAILED_QFULL ? ack_failed_tmp : ack_failed);
00245 
00246            /* destroy original message */
00247            msg_destroy(msg);
00248            break;
00249     }
00250 
00251     /* put ack into incoming queue of conn */
00252     send_msg(conn, mack);
00253     msg_destroy(mack);
00254 }

Here is the call graph for this function:

void init_smsbox_routes Cfg cfg  )  [static]
 

Definition at line 1036 of file bb_boxc.c.

References cfg_get, cfg_get_multi_group(), debug(), dict_put_once(), grp_dump(), gwlist_destroy(), gwlist_extract_first(), gwlist_get(), gwlist_len(), octstr_destroy(), octstr_destroy_item(), octstr_duplicate, octstr_get_cstr, octstr_imm(), octstr_insert(), octstr_insert_char(), octstr_len(), octstr_split(), octstr_strip_blanks(), panic, smsbox_by_receiver, smsbox_by_smsc, and smsbox_by_smsc_receiver.

Referenced by smsbox_start().

01037 {
01038     CfgGroup *grp;
01039     List *list, *items;
01040     Octstr *boxc_id, *smsc_ids, *shortcuts;
01041     int i, j;
01042 
01043     boxc_id = smsc_ids = shortcuts = NULL;
01044 
01045     list = cfg_get_multi_group(cfg, octstr_imm("smsbox-route")); 
01046  
01047     /* loop multi-group "smsbox-route" */
01048     while (list && (grp = gwlist_extract_first(list)) != NULL) { 
01049          
01050         if ((boxc_id = cfg_get(grp, octstr_imm("smsbox-id"))) == NULL) { 
01051             grp_dump(grp); 
01052             panic(0,"'smsbox-route' group without valid 'smsbox-id' directive!"); 
01053         }
01054 
01055         /*
01056          * If smsc-id is given, then any message comming from the specified
01057          * smsc-id in the list will be routed to this smsbox instance.
01058          * If shortcode is given, then any message with receiver number 
01059          * matching those will be routed to this smsbox instance.
01060          * If both are given, then only receiver within shortcode originating
01061          * from smsc-id list will be routed to this smsbox instance. So if both
01062          * are present then this is a logical AND operation.
01063          */
01064         smsc_ids = cfg_get(grp, octstr_imm("smsc-id"));
01065         shortcuts = cfg_get(grp, octstr_imm("shortcode"));
01066 
01067         /* consider now the 3 possibilities: */
01068         if (smsc_ids && !shortcuts) {
01069             /* smsc-id only, so all MO traffic */
01070             items = octstr_split(smsc_ids, octstr_imm(";"));
01071             for (i = 0; i < gwlist_len(items); i++) {
01072                 Octstr *item = gwlist_get(items, i);
01073                 octstr_strip_blanks(item);
01074 
01075                 debug("bb.boxc",0,"Adding smsbox routing to id <%s> for smsc id <%s>",
01076                       octstr_get_cstr(boxc_id), octstr_get_cstr(item));
01077 
01078                 if (!dict_put_once(smsbox_by_smsc, item, octstr_duplicate(boxc_id)))
01079                     panic(0, "Routing for smsc-id <%s> already exists!",
01080                           octstr_get_cstr(item));
01081             }
01082             gwlist_destroy(items, octstr_destroy_item);
01083             octstr_destroy(smsc_ids);
01084         }
01085         else if (!smsc_ids && shortcuts) {
01086             /* shortcode only, so these MOs from all smscs */
01087             items = octstr_split(shortcuts, octstr_imm(";"));
01088             for (i = 0; i < gwlist_len(items); i++) {
01089                 Octstr *item = gwlist_get(items, i);
01090                 octstr_strip_blanks(item);
01091 
01092                 debug("bb.boxc",0,"Adding smsbox routing to id <%s> for receiver no <%s>",
01093                       octstr_get_cstr(boxc_id), octstr_get_cstr(item));
01094             
01095                 if (!dict_put_once(smsbox_by_receiver, item, octstr_duplicate(boxc_id)))
01096                     panic(0, "Routing for receiver no <%s> already exists!",
01097                           octstr_get_cstr(item));
01098             }
01099             gwlist_destroy(items, octstr_destroy_item);
01100             octstr_destroy(shortcuts);
01101         }
01102         else if (smsc_ids && shortcuts) {
01103             /* both, so only specified MOs from specified smscs */
01104             items = octstr_split(shortcuts, octstr_imm(";"));
01105             for (i = 0; i < gwlist_len(items); i++) {
01106                 List *subitems;
01107                 Octstr *item = gwlist_get(items, i);
01108                 octstr_strip_blanks(item);
01109                 subitems = octstr_split(smsc_ids, octstr_imm(";")); 
01110                 for (j = 0; j < gwlist_len(subitems); j++) {
01111                     Octstr *subitem = gwlist_get(subitems, j);
01112                     octstr_strip_blanks(subitem);
01113                     
01114                     debug("bb.boxc",0,"Adding smsbox routing to id <%s> "
01115                           "for receiver no <%s> and smsc id <%s>",
01116                           octstr_get_cstr(boxc_id), octstr_get_cstr(item),
01117                           octstr_get_cstr(subitem));
01118             
01119                     /* construct the dict key '<shortcode>:<smsc-id>' */
01120                     octstr_insert(subitem, item, 0);
01121                     octstr_insert_char(subitem, octstr_len(item), ':');
01122                     if (!dict_put_once(smsbox_by_smsc_receiver, subitem, octstr_duplicate(boxc_id)))
01123                         panic(0, "Routing for receiver:smsc <%s> already exists!",
01124                               octstr_get_cstr(subitem));
01125                 }
01126                 gwlist_destroy(subitems, octstr_destroy_item);
01127             }
01128             gwlist_destroy(items, octstr_destroy_item);
01129             octstr_destroy(shortcuts);
01130         }
01131         octstr_destroy(boxc_id);
01132     }
01133 
01134     gwlist_destroy(list, NULL);
01135 }

Here is the call graph for this function:

Msg* read_from_box Boxc boxconn  )  [static]
 

Definition at line 163 of file bb_boxc.c.

References _boxc::alive, BB_DEAD, bb_status, Boxc, _boxc::client_ip, _boxc::conn, conn_eof(), conn_error(), conn_read_withlen(), conn_wait(), error(), info(), and octstr_get_cstr.

Referenced by boxc_receiver().

00164 {
00165     int ret;
00166     Octstr *pack;
00167     Msg *msg;
00168 
00169     pack = NULL;
00170     while (bb_status != BB_DEAD && boxconn->alive) {
00171             /* XXX: if box doesn't send (just keep conn open) we block here while shutdown */
00172         pack = conn_read_withlen(boxconn->conn);
00173         gw_claim_area(pack);
00174         if (pack != NULL)
00175             break;
00176         if (conn_error(boxconn->conn)) {
00177             info(0, "Read error when reading from box <%s>, disconnecting",
00178                  octstr_get_cstr(boxconn->client_ip));
00179             return NULL;
00180         }
00181         if (conn_eof(boxconn->conn)) {
00182             info(0, "Connection closed by the box <%s>",
00183                  octstr_get_cstr(boxconn->client_ip));
00184             return NULL;
00185         }
00186 
00187         ret = conn_wait(boxconn->conn, -1.0);
00188         if (ret < 0) {
00189             error(0, "Connection to box <%s> broke.",
00190                   octstr_get_cstr(boxconn->client_ip));
00191             return NULL;
00192         }
00193     }
00194 
00195     if (pack == NULL)
00196         return NULL;
00197 
00198     msg = msg_unpack(pack);
00199     octstr_destroy(pack);
00200 
00201     if (msg == NULL)
00202         error(0, "Failed to unpack data!");
00203     return msg;
00204 }

Here is the call graph for this function:

int route_incoming_to_boxc Msg msg  ) 
 

Definition at line 1415 of file bb_boxc.c.

References Boxc, _boxc::boxc_id, dict_get(), gw_assert, gw_rand(), gw_rwlock_rdlock(), gw_rwlock_unlock(), gwlist_get(), gwlist_len(), gwlist_produce(), _boxc::incoming, incoming_sms, _boxc::load, max_incoming_sms_qlength, msg_type, octstr_destroy(), octstr_format(), octstr_get_cstr, octstr_len(), _boxc::routable, sms, smsbox_by_id, smsbox_by_receiver, smsbox_by_smsc, smsbox_by_smsc_receiver, smsbox_list, smsbox_list_rwlock, and warning().

Referenced by bb_smscconn_receive(), and sms_to_smsboxes().

01416 {
01417     Boxc *bc = NULL, *best = NULL;
01418     Octstr *s, *r, *rs;
01419     long len, b, i;
01420     int full_found = 0;
01421 
01422     s = r = NULL;
01423     gw_assert(msg_type(msg) == sms);
01424 
01425     /* msg_dump(msg, 0); */
01426 
01427     /* 
01428      * We have a specific route to pass this msg to smsbox-id 
01429      * Lookup the connection in the dictionary.
01430      */
01431     gw_rwlock_rdlock(smsbox_list_rwlock);
01432     if (gwlist_len(smsbox_list) == 0) {
01433         gw_rwlock_unlock(smsbox_list_rwlock);
01434         warning(0, "smsbox_list empty!");
01435         if (max_incoming_sms_qlength < 0 || max_incoming_sms_qlength > gwlist_len(incoming_sms)) {
01436             gwlist_produce(incoming_sms, msg);
01437         return 0;
01438          }
01439          else
01440              return -1;
01441     }
01442 
01443     if (octstr_len(msg->sms.boxc_id) > 0) {
01444         
01445         bc = dict_get(smsbox_by_id, msg->sms.boxc_id);
01446         if (bc == NULL) {
01447             /*
01448              * something is wrong, this was the smsbox connection we used
01449              * for sending, so it seems this smsbox is gone
01450              */
01451             warning(0,"Could not route message to smsbox id <%s>, smsbox is gone!",
01452                     octstr_get_cstr(msg->sms.boxc_id));
01453         }
01454     }
01455     else {
01456         /*
01457          * Check if we have a "smsbox-route" for this msg.
01458          * Where the shortcode route has a higher priority then the smsc-id rule.
01459          * Highest priority has the combined <shortcode>:<smsc-id> route.
01460          */
01461         Octstr *os = octstr_format("%s:%s", 
01462                                    octstr_get_cstr(msg->sms.receiver),
01463                                    octstr_get_cstr(msg->sms.smsc_id));
01464         s = (msg->sms.smsc_id ? dict_get(smsbox_by_smsc, msg->sms.smsc_id) : NULL);
01465         r = (msg->sms.receiver ? dict_get(smsbox_by_receiver, msg->sms.receiver) : NULL);
01466         rs = (os ? dict_get(smsbox_by_smsc_receiver, os) : NULL);
01467         octstr_destroy(os); 
01468         bc = rs ? dict_get(smsbox_by_id, rs) : 
01469             (r ? dict_get(smsbox_by_id, r) : (s ? dict_get(smsbox_by_id, s) : NULL));
01470     }
01471 
01472     /* check if we found our routing */
01473     if (bc != NULL) {
01474         if (max_incoming_sms_qlength < 0 || max_incoming_sms_qlength > gwlist_len(bc->incoming)) {
01475             gwlist_produce(bc->incoming, msg);
01476             gw_rwlock_unlock(smsbox_list_rwlock);
01477             return 1; /* we are done */
01478         }
01479         else {
01480             gw_rwlock_unlock(smsbox_list_rwlock);
01481             return -1;
01482         }
01483     }
01484     else if (s != NULL || r != NULL || octstr_len(msg->sms.boxc_id) > 0) {
01485         gw_rwlock_unlock(smsbox_list_rwlock);
01486         /*
01487          * we have routing defined, but no smsbox connected at the moment.
01488          * put msg into global incoming queue and wait until smsbox with
01489          * such boxc_id connected.
01490          */
01491         if (max_incoming_sms_qlength < 0 || max_incoming_sms_qlength > gwlist_len(incoming_sms)) {
01492             gwlist_produce(incoming_sms, msg);
01493             return 0;
01494         }
01495         else
01496             return -1;
01497     }
01498 
01499     /*
01500      * ok, none of the routing things applied previously, so route it to
01501      * a random smsbox.
01502      */
01503 
01504     /* take random smsbox from list, and then check all smsboxes
01505      * and select the one with lowest load level - if tied, the first
01506      * one
01507      */
01508     len = gwlist_len(smsbox_list);
01509     b = gw_rand() % len;
01510 
01511     for(i = 0; i < gwlist_len(smsbox_list); i++) {
01512     bc = gwlist_get(smsbox_list, (i+b) % len);
01513 
01514         if (bc->boxc_id != NULL || bc->routable == 0)
01515             bc = NULL;
01516 
01517         if (bc != NULL && max_incoming_sms_qlength > 0 &&
01518             gwlist_len(bc->incoming) > max_incoming_sms_qlength) {
01519             full_found = 1;
01520             bc = NULL;
01521         }
01522 
01523         if ((bc != NULL && best != NULL && bc->load < best->load) ||
01524              (bc != NULL && best == NULL)) {
01525         best = bc;
01526         }
01527     }
01528 
01529     if (best != NULL) {
01530         best->load++;
01531         gwlist_produce(best->incoming, msg);
01532     }
01533 
01534     gw_rwlock_unlock(smsbox_list_rwlock);
01535 
01536     if (best == NULL && full_found == 0) {
01537     warning(0, "smsbox_list empty!");
01538         if (max_incoming_sms_qlength < 0 || max_incoming_sms_qlength > gwlist_len(incoming_sms)) {
01539             gwlist_produce(incoming_sms, msg);
01540         return 0;
01541          }
01542          else
01543              return -1;
01544     }
01545     else if (best == NULL && full_found == 1)
01546         return -1;
01547 
01548     return 1;
01549 }

Here is the call graph for this function:

Boxc* route_msg List route_info,
Msg msg
[static]
 

Definition at line 771 of file bb_boxc.c.

References _addrpar::address, AddrPar, ap_destroy(), Boxc, cmp_boxc(), cmp_route(), debug(), gw_rand(), gwlist_delete_equal(), gwlist_get(), gwlist_len(), gwlist_lock(), gwlist_produce(), gwlist_search(), gwlist_unlock(), _boxc::id, _boxc::load, octstr_duplicate, _addrpar::port, wapbox_list, _addrpar::wapboxid, and warning().

Referenced by wdp_to_wapboxes().

00772 {
00773     AddrPar *ap;
00774     Boxc *conn, *best;
00775     int i, b, len;
00776     
00777     ap = gwlist_search(route_info, msg, cmp_route);
00778     if (ap == NULL) {
00779         debug("bb.boxc", 0, "Did not find previous routing info for WDP, "
00780               "generating new");
00781 route:
00782 
00783         if (gwlist_len(wapbox_list) == 0)
00784             return NULL;
00785 
00786         gwlist_lock(wapbox_list);
00787 
00788     /* take random wapbox from list, and then check all wapboxes
00789      * and select the one with lowest load level - if tied, the first
00790      * one
00791      */
00792         len = gwlist_len(wapbox_list);
00793         b = gw_rand() % len;
00794         best = gwlist_get(wapbox_list, b);
00795 
00796         for(i = 0; i < gwlist_len(wapbox_list); i++) {
00797             conn = gwlist_get(wapbox_list, (i+b) % len);
00798             if (conn != NULL && best != NULL)
00799                 if (conn->load < best->load)
00800                     best = conn;
00801         }
00802         if (best == NULL) {
00803             warning(0, "wapbox_list empty!");
00804             gwlist_unlock(wapbox_list);
00805             return NULL;
00806         }
00807         conn = best;
00808         conn->load++;   /* simulate new client until we get new values */
00809     
00810         ap = gw_malloc(sizeof(AddrPar));
00811         ap->address = octstr_duplicate(msg->wdp_datagram.source_address);
00812         ap->port = msg->wdp_datagram.source_port;
00813         ap->wapboxid = conn->id;
00814         gwlist_produce(route_info, ap);
00815 
00816         gwlist_unlock(wapbox_list);
00817     } else
00818         conn = gwlist_search(wapbox_list, ap, cmp_boxc);
00819 
00820     if (conn == NULL) {
00821     /* routing failed; wapbox has disappeared!
00822      * ..remove routing info and re-route   */
00823 
00824         debug("bb.boxc", 0, "Old wapbox has disappeared, re-routing");
00825 
00826         gwlist_delete_equal(route_info, ap);
00827         ap_destroy(ap);
00828         goto route;
00829     }
00830     return conn;
00831 }

Here is the call graph for this function:

void run_smsbox void *  arg  )  [static]
 

Definition at line 586 of file bb_boxc.c.

References Boxc, boxc_destroy(), _boxc::boxc_id, boxc_receiver(), boxc_sender(), _boxc::client_ip, dict_create(), dict_destroy(), dict_key_count(), dict_keys(), dict_remove(), error(), flow_threads, gw_assert, gw_rwlock_unlock(), gw_rwlock_wrlock(), gwlist_add_producer(), gwlist_append(), gwlist_create, gwlist_delete_equal(), gwlist_destroy(), gwlist_extract_first(), gwlist_len(), gwlist_produce(), gwlist_producer_count(), gwlist_remove_producer(), gwthread_create, gwthread_join(), gwthread_wakeup(), _boxc::incoming, incoming_sms, octstr_destroy(), octstr_destroy_item(), octstr_get_cstr, _boxc::outgoing, _boxc::pending, _boxc::retry, semaphore_create(), semaphore_destroy(), semaphore_up(), _boxc::sent, sms_dequeue_thread, smsbox_by_id, smsbox_list, smsbox_list_rwlock, and smsbox_max_pending.

Referenced by smsboxc_run().

00587 {
00588     Boxc *newconn;
00589     long sender;
00590     Msg *msg;
00591     List *keys;
00592     Octstr *key;
00593 
00594     gwlist_add_producer(flow_threads);
00595     newconn = arg;
00596     newconn->incoming = gwlist_create();
00597     gwlist_add_producer(newconn->incoming);
00598     newconn->retry = incoming_sms;
00599     newconn->outgoing = outgoing_sms;
00600     newconn->sent = dict_create(smsbox_max_pending, NULL);
00601     newconn->pending = semaphore_create(smsbox_max_pending);
00602 
00603     sender = gwthread_create(boxc_sender, newconn);
00604     if (sender == -1) {
00605         error(0, "Failed to start a new thread, disconnecting client <%s>",
00606               octstr_get_cstr(newconn->client_ip));
00607         goto cleanup;
00608     }
00609     /*
00610      * We register newconn in the smsbox_list here but mark newconn as routable
00611      * after identification or first message received from smsbox. So we can avoid
00612      * a race condition for routable smsboxes (otherwise between startup and
00613      * registration we will forward some messages to smsbox).
00614      */
00615     gw_rwlock_wrlock(smsbox_list_rwlock);
00616     gwlist_append(smsbox_list, newconn);
00617     gw_rwlock_unlock(smsbox_list_rwlock);
00618 
00619     gwlist_add_producer(newconn->outgoing);
00620     boxc_receiver(newconn);
00621     gwlist_remove_producer(newconn->outgoing);
00622 
00623     /* remove us from smsbox routing list */
00624     gw_rwlock_wrlock(smsbox_list_rwlock);
00625     gwlist_delete_equal(smsbox_list, newconn);
00626     if (newconn->boxc_id) {
00627         dict_remove(smsbox_by_id, newconn->boxc_id);
00628     }
00629     gw_rwlock_unlock(smsbox_list_rwlock);
00630 
00631     /*
00632      * check if we in the shutdown phase and sms dequeueing thread
00633      *   has removed the producer already
00634      */
00635     if (gwlist_producer_count(newconn->incoming) > 0)
00636         gwlist_remove_producer(newconn->incoming);
00637 
00638     /* check if we are still waiting for ack's and semaphore locked */
00639     if (dict_key_count(newconn->sent) >= smsbox_max_pending)
00640         semaphore_up(newconn->pending); /* allow sender to go down */
00641         
00642     gwthread_join(sender);
00643 
00644     /* put not acked msgs into incoming queue */    
00645     keys = dict_keys(newconn->sent);
00646     while((key = gwlist_extract_first(keys)) != NULL) {
00647         msg = dict_remove(newconn->sent, key);
00648         gwlist_produce(incoming_sms, msg);
00649         octstr_destroy(key);
00650     }
00651     gw_assert(gwlist_len(keys) == 0);
00652     gwlist_destroy(keys, octstr_destroy_item);
00653 
00654     /* clear our send queue */
00655     while((msg = gwlist_extract_first(newconn->incoming)) != NULL) {
00656         gwlist_produce(incoming_sms, msg);
00657     }
00658 
00659 cleanup:
00660     gw_assert(gwlist_len(newconn->incoming) == 0);
00661     gwlist_destroy(newconn->incoming, NULL);
00662     gw_assert(dict_key_count(newconn->sent) == 0);
00663     dict_destroy(newconn->sent);
00664     semaphore_destroy(newconn->pending);
00665     boxc_destroy(newconn);
00666 
00667     /* wakeup the dequeueing thread */
00668     gwthread_wakeup(sms_dequeue_thread);
00669 
00670     gwlist_remove_producer(flow_threads);
00671 }

Here is the call graph for this function:

void run_wapbox void *  arg  )  [static]
 

Definition at line 675 of file bb_boxc.c.

References _boxc::alive, Boxc, boxc_destroy(), boxc_receiver(), boxc_sender(), _boxc::client_ip, debug(), error(), flow_threads, gw_assert, gwlist_add_producer(), gwlist_append(), gwlist_create, gwlist_delete_equal(), gwlist_destroy(), gwlist_len(), gwlist_lock(), gwlist_producer_count(), gwlist_remove_producer(), gwlist_unlock(), gwthread_create, gwthread_join(), _boxc::incoming, _boxc::is_wap, octstr_get_cstr, _boxc::outgoing, _boxc::retry, and wapbox_list.

Referenced by wapboxc_run().

00676 {
00677     Boxc *newconn;
00678     List *newlist;
00679     long sender;
00680 
00681     gwlist_add_producer(flow_threads);
00682     newconn = arg;
00683     newconn->is_wap = 1;
00684     
00685     /*
00686      * create a new incoming list for just that box,
00687      * and add it to list of list pointers, so we can start
00688      * to route messages to it.
00689      */
00690 
00691     debug("bb", 0, "setting up systems for new wapbox");
00692     
00693     newlist = gwlist_create();
00694     /* this is released by the sender/receiver if it exits */
00695     gwlist_add_producer(newlist);
00696     
00697     newconn->incoming = newlist;
00698     newconn->retry = incoming_wdp;
00699     newconn->outgoing = outgoing_wdp;
00700 
00701     sender = gwthread_create(boxc_sender, newconn);
00702     if (sender == -1) {
00703         error(0, "Failed to start a new thread, disconnecting client <%s>",
00704               octstr_get_cstr(newconn->client_ip));
00705         goto cleanup;
00706     }
00707     gwlist_append(wapbox_list, newconn);
00708     gwlist_add_producer(newconn->outgoing);
00709     boxc_receiver(newconn);
00710 
00711     /* cleanup after receiver has exited */
00712     
00713     gwlist_remove_producer(newconn->outgoing);
00714     gwlist_lock(wapbox_list);
00715     gwlist_delete_equal(wapbox_list, newconn);
00716     gwlist_unlock(wapbox_list);
00717 
00718     while (gwlist_producer_count(newlist) > 0)
00719         gwlist_remove_producer(newlist);
00720 
00721     newconn->alive = 0;
00722     
00723     gwthread_join(sender);
00724 
00725 cleanup:
00726     gw_assert(gwlist_len(newlist) == 0);
00727     gwlist_destroy(newlist, NULL);
00728     boxc_destroy(newconn);
00729 
00730     gwlist_remove_producer(flow_threads);
00731 }

Here is the call graph for this function:

int send_msg Boxc boxconn,
Msg pmsg
[static]
 

Definition at line 377 of file bb_boxc.c.

References Boxc, _boxc::boxc_id, _boxc::client_ip, _boxc::conn, conn_write_withlen(), debug(), error(), msg_pack(), octstr_destroy(), and octstr_get_cstr.

Referenced by boxc_receiver(), boxc_sender(), and deliver_sms_to_queue().

00378 {
00379     Octstr *pack;
00380 
00381     pack = msg_pack(pmsg);
00382 
00383     if (pack == NULL)
00384         return -1;
00385 
00386     if (boxconn->boxc_id != NULL)
00387         debug("bb.boxc", 0, "send_msg: sending msg to boxc: <%s>",
00388           octstr_get_cstr(boxconn->boxc_id));
00389     else
00390         debug("bb.boxc", 0, "send_msg: sending msg to box: <%s>",
00391           octstr_get_cstr(boxconn->client_ip));
00392 
00393     if (conn_write_withlen(boxconn->conn, pack) == -1) {
00394         error(0, "Couldn't write Msg to box <%s>, disconnecting",
00395           octstr_get_cstr(boxconn->client_ip));
00396         octstr_destroy(pack);
00397         return -1;
00398     }
00399 
00400     octstr_destroy(pack);
00401     return 0;
00402 }

Here is the call graph for this function:

void sms_to_smsboxes void *  arg  )  [static]
 

Definition at line 1551 of file bb_boxc.c.

References bb_status, Boxc, flow_threads, gw_assert, gw_rwlock_rdlock(), gw_rwlock_unlock(), gwlist_add_producer(), gwlist_consume(), gwlist_get(), gwlist_insert(), gwlist_len(), gwlist_produce(), gwlist_producer_count(), gwlist_remove_producer(), gwthread_sleep(), _boxc::incoming, incoming_sms, msg_type, route_incoming_to_boxc(), sms, smsbox_list, and smsbox_list_rwlock.

Referenced by smsbox_start().

01552 {
01553     Msg *newmsg, *startmsg, *msg;
01554     long i, len;
01555     int ret = -1;
01556     Boxc *boxc;
01557 
01558     gwlist_add_producer(flow_threads);
01559 
01560     newmsg = startmsg = msg = NULL;
01561 
01562     while(bb_status != BB_DEAD) {
01563 
01564         if (newmsg == startmsg) {
01565             /* check if we are in shutdown phase */
01566             if (gwlist_producer_count(smsbox_list) == 0)
01567                 break;
01568 
01569             if (ret == 0 || ret == -1) {
01570                 /* debug("", 0, "time to sleep"); */
01571                 gwthread_sleep(60.0);
01572                 /* debug("", 0, "wake up list len %ld", gwlist_len(incoming_sms)); */
01573                 /* shutdown ? */
01574                 if (gwlist_producer_count(smsbox_list) == 0 && gwlist_len(smsbox_list) == 0)
01575                     break;
01576             }
01577             startmsg = msg = gwlist_consume(incoming_sms);
01578             /* debug("", 0, "gwlist_consume done 1"); */
01579             newmsg = NULL;
01580         }
01581         else {
01582             newmsg = msg = gwlist_consume(incoming_sms);
01583             
01584             /* Back at the first message? */
01585             if (newmsg == startmsg) {
01586                 gwlist_insert(incoming_sms, 0, msg);
01587                 continue;
01588             }
01589         }
01590 
01591         if (msg == NULL)
01592             break;
01593 
01594         gw_assert(msg_type(msg) == sms);
01595 
01596         /* debug("bb.sms", 0, "sms_boxc_router: handling message (%p vs %p)",
01597               msg, startmsg); */
01598 
01599         ret = route_incoming_to_boxc(msg);
01600         if (ret == 1)
01601             startmsg = newmsg = NULL;
01602         else if (ret == -1) {
01603             gwlist_produce(incoming_sms, msg);
01604         }
01605     }
01606 
01607     gw_rwlock_rdlock(smsbox_list_rwlock);
01608     len = gwlist_len(smsbox_list);
01609     for (i=0; i < len; i++) {
01610         boxc = gwlist_get(smsbox_list, i);
01611         gwlist_remove_producer(boxc->incoming);
01612     }
01613     gw_rwlock_unlock(smsbox_list_rwlock);
01614 
01615     gwlist_remove_producer(flow_threads);
01616 }

Here is the call graph for this function:

int smsbox_restart Cfg cfg  ) 
 

Definition at line 1198 of file bb_boxc.c.

01199 {
01200     if (!smsbox_running) return -1;
01201     
01202     /* send new config to clients */
01203 
01204     return 0;
01205 }

int smsbox_start Cfg cfg  ) 
 

Definition at line 1144 of file bb_boxc.c.

References boxid, cfg_get_bool(), cfg_get_integer(), cfg_get_single_group(), counter_create(), debug(), dict_create(), error(), gw_rwlock_create(), gwlist_add_producer(), gwlist_create, gwthread_create, info(), init_smsbox_routes(), octstr_destroy(), octstr_imm(), outgoing_sms, panic, sms_dequeue_thread, sms_to_smsboxes(), smsbox_by_id, smsbox_by_receiver, smsbox_by_smsc, smsbox_by_smsc_receiver, smsbox_list, smsbox_list_rwlock, smsbox_max_pending, smsbox_port, smsbox_port_ssl, smsbox_running, and smsboxc_run().

Referenced by start_smsc().

01145 {
01146     CfgGroup *grp;
01147     
01148     if (smsbox_running) return -1;
01149 
01150     debug("bb", 0, "starting smsbox connection module");
01151 
01152     grp = cfg_get_single_group(cfg, octstr_imm("core"));
01153     if (cfg_get_integer(&smsbox_port, grp, octstr_imm("smsbox-port")) == -1) {
01154         error(0, "Missing smsbox-port variable, cannot start smsboxes");
01155         return -1;
01156     }
01157 #ifdef HAVE_LIBSSL
01158     cfg_get_bool(&smsbox_port_ssl, grp, octstr_imm("smsbox-port-ssl"));
01159 #endif /* HAVE_LIBSSL */
01160 
01161     if (smsbox_port_ssl)
01162         debug("bb", 0, "smsbox connection module is SSL-enabled");
01163         
01164     if (cfg_get_integer(&smsbox_max_pending, grp, octstr_imm("smsbox-max-pending")) == -1) {
01165         smsbox_max_pending = SMSBOX_MAX_PENDING;
01166         info(0, "BOXC: 'smsbox-max-pending' not set, using default (%ld).", smsbox_max_pending);
01167     }
01168     
01169     smsbox_list = gwlist_create();  /* have a list of connections */
01170     smsbox_list_rwlock = gw_rwlock_create();
01171     if (!boxid)
01172         boxid = counter_create();
01173 
01174     /* the smsbox routing specific inits */
01175     smsbox_by_id = dict_create(10, NULL);  /* and a hash directory of identified */
01176     smsbox_by_smsc = dict_create(30, (void(*)(void *)) octstr_destroy);
01177     smsbox_by_receiver = dict_create(50, (void(*)(void *)) octstr_destroy);
01178     smsbox_by_smsc_receiver = dict_create(50, (void(*)(void *)) octstr_destroy);
01179 
01180     /* load the defined smsbox routing rules */
01181     init_smsbox_routes(cfg);
01182 
01183     gwlist_add_producer(outgoing_sms);
01184     gwlist_add_producer(smsbox_list);
01185 
01186     smsbox_running = 1;
01187     
01188     if ((sms_dequeue_thread = gwthread_create(sms_to_smsboxes, NULL)) == -1)
01189         panic(0, "Failed to start a new thread for smsbox routing");
01190 
01191     if (gwthread_create(smsboxc_run, &smsbox_port) == -1)
01192         panic(0, "Failed to start a new thread for smsbox connections");
01193 
01194     return 0;
01195 }

Here is the call graph for this function:

void smsboxc_run void *  arg  )  [static]
 

Definition at line 932 of file bb_boxc.c.

References dict_destroy(), flow_threads, gw_rwlock_destroy(), gwlist_add_producer(), gwlist_destroy(), gwlist_remove_producer(), gwlist_wait_until_nonempty(), gwthread_join(), gwthread_sleep(), gwthread_wakeup(), incoming_sms, MAIN_THREAD_ID, make_server_socket(), outgoing_sms, panic, port, run_smsbox(), sms_dequeue_thread, smsbox_by_id, smsbox_by_receiver, smsbox_by_smsc, smsbox_by_smsc_receiver, smsbox_list, smsbox_list_rwlock, smsbox_port_ssl, and wait_for_connections().

Referenced by smsbox_start().

00933 {
00934     int fd;
00935     int port;
00936 
00937     gwlist_add_producer(flow_threads);
00938     gwthread_wakeup(MAIN_THREAD_ID);
00939     port = (int) *((long *)arg);
00940     
00941     fd = make_server_socket(port, NULL); 
00942     /* XXX add interface_name if required */
00943 
00944     if (fd < 0) {
00945         panic(0, "Could not open smsbox port %d", port);
00946     }
00947 
00948     /*
00949      * infinitely wait for new connections;
00950      * to shut down the system, SIGTERM is send and then
00951      * select drops with error, so we can check the status
00952      */
00953     wait_for_connections(fd, run_smsbox, incoming_sms, smsbox_port_ssl);
00954 
00955     gwlist_remove_producer(smsbox_list);
00956 
00957     /* continue avalanche */
00958     gwlist_remove_producer(outgoing_sms);
00959 
00960     /* all connections do the same, so that all must remove() before it
00961      * is completely over
00962      */
00963     while(gwlist_wait_until_nonempty(smsbox_list) == 1)
00964         gwthread_sleep(1.0);
00965 
00966     /* close listen socket */
00967     close(fd);
00968 
00969     gwthread_wakeup(sms_dequeue_thread);
00970     gwthread_join(sms_dequeue_thread);
00971 
00972     gwlist_destroy(smsbox_list, NULL);
00973     smsbox_list = NULL;
00974     gw_rwlock_destroy(smsbox_list_rwlock);
00975     smsbox_list_rwlock = NULL;
00976 
00977     /* destroy things related to smsbox routing */
00978     dict_destroy(smsbox_by_id);
00979     smsbox_by_id = NULL;
00980     dict_destroy(smsbox_by_smsc);
00981     smsbox_by_smsc = NULL;
00982     dict_destroy(smsbox_by_receiver);
00983     smsbox_by_receiver = NULL;
00984     dict_destroy(smsbox_by_smsc_receiver);
00985     smsbox_by_smsc_receiver = NULL;
00986     
00987     gwlist_remove_producer(flow_threads);
00988 }

Here is the call graph for this function:

void wait_for_connections int  fd,
void(*)(void *arg)  function,
List waited,
int  ssl
[static]
 

Definition at line 889 of file bb_boxc.c.

References accept_boxc(), bb_status, Boxc, error(), gw_assert, gwlist_consume(), gwlist_wait_until_nonempty(), gwthread_create, gwthread_pollfd(), gwthread_sleep(), POLLIN, ssl, and suspended.

Referenced by smsboxc_run(), and wapboxc_run().

00891 {
00892     int ret;
00893     int timeout = 10; /* 10 sec. */
00894 
00895     gw_assert(function != NULL);
00896     
00897     while(bb_status != BB_DEAD) {
00898 
00899         /* if we are being shutdowned, as long as there is
00900          * messages in incoming list allow new connections, but when
00901          * list is empty, exit.
00902          * Note: We have timeout (defined above) for which we allow new connections.
00903          *           Otherwise we wait here for ever!
00904          */
00905         if (bb_status == BB_SHUTDOWN) {
00906             ret = gwlist_wait_until_nonempty(waited);
00907             if (ret == -1 || !timeout)
00908                 break;
00909             else
00910                 timeout--;
00911         }
00912 
00913         /* block here if suspended */
00914         gwlist_consume(suspended);
00915 
00916         ret = gwthread_pollfd(fd, POLLIN, 1.0);
00917         if (ret > 0) {
00918             Boxc *newconn = accept_boxc(fd, ssl);
00919             if (newconn != NULL) {
00920                 gwthread_create(function, newconn);
00921                 gwthread_sleep(1.0);
00922             } else {
00923                 error(0, "Failed to create new boxc connection.");
00924             }
00925         } else if (ret < 0 && errno != EINTR && errno != EAGAIN)
00926             error(errno, "bb_boxc::wait_for_connections failed");
00927     }
00928 }

Here is the call graph for this function:

int wapbox_start Cfg cfg  ) 
 

Definition at line 1211 of file bb_boxc.c.

References box_allow_ip, box_deny_ip, boxid, cfg_get, cfg_get_bool(), cfg_get_integer(), cfg_get_single_group(), counter_create(), debug(), error(), gwlist_add_producer(), gwlist_create, gwthread_create, info(), octstr_create, octstr_imm(), outgoing_wdp, panic, wapbox_list, wapbox_port, wapbox_port_ssl, wapbox_running, wapboxc_run(), and wdp_to_wapboxes().

Referenced by start_wap().

01212 {
01213     CfgGroup *grp;
01214 
01215     if (wapbox_running) return -1;
01216 
01217     debug("bb", 0, "starting wapbox connection module");
01218     
01219     grp = cfg_get_single_group(cfg, octstr_imm("core"));
01220     
01221     if (cfg_get_integer(&wapbox_port, grp, octstr_imm("wapbox-port")) == -1) {
01222         error(0, "Missing wapbox-port variable, cannot start WAP");
01223         return -1;
01224     }
01225 #ifdef HAVE_LIBSSL
01226     cfg_get_bool(&wapbox_port_ssl, grp, octstr_imm("wapbox-port-ssl"));
01227 #endif /* HAVE_LIBSSL */
01228   
01229     box_allow_ip = cfg_get(grp, octstr_imm("box-allow-ip"));
01230     if (box_allow_ip == NULL)
01231         box_allow_ip = octstr_create("");
01232     box_deny_ip = cfg_get(grp, octstr_imm("box-deny-ip"));
01233     if (box_deny_ip == NULL)
01234         box_deny_ip = octstr_create("");
01235     if (box_allow_ip != NULL && box_deny_ip == NULL)
01236         info(0, "Box connection allowed IPs defined without any denied...");
01237     
01238     wapbox_list = gwlist_create();  /* have a list of connections */
01239     gwlist_add_producer(outgoing_wdp);
01240     if (!boxid)
01241         boxid = counter_create();
01242 
01243     if (gwthread_create(wdp_to_wapboxes, NULL) == -1)
01244         panic(0, "Failed to start a new thread for wapbox routing");
01245  
01246     if (gwthread_create(wapboxc_run, &wapbox_port) == -1)
01247         panic(0, "Failed to start a new thread for wapbox connections");
01248 
01249     wapbox_running = 1;
01250     return 0;
01251 }

Here is the call graph for this function:

void wapboxc_run void *  arg  )  [static]
 

Definition at line 991 of file bb_boxc.c.

References flow_threads, gwlist_add_producer(), gwlist_consume(), gwlist_destroy(), gwlist_remove_producer(), gwlist_wait_until_nonempty(), gwthread_sleep(), gwthread_wakeup(), incoming_wdp, MAIN_THREAD_ID, make_server_socket(), outgoing_wdp, panic, port, run_wapbox(), wait_for_connections(), wapbox_list, and wapbox_port_ssl.

Referenced by wapbox_start().

00992 {
00993     int fd, port;
00994 
00995     gwlist_add_producer(flow_threads);
00996     gwthread_wakeup(MAIN_THREAD_ID);
00997     port = (int) *((long*)arg);
00998     
00999     fd = make_server_socket(port, NULL);
01000         /* XXX add interface_name if required */
01001 
01002     if (fd < 0) {
01003         panic(0, "Could not open wapbox port %d", port);
01004     }
01005 
01006     wait_for_connections(fd, run_wapbox, incoming_wdp, wapbox_port_ssl);
01007 
01008     /* continue avalanche */
01009 
01010     gwlist_remove_producer(outgoing_wdp);
01011 
01012 
01013     /* wait for all connections to die and then remove list
01014      */
01015     
01016     while(gwlist_wait_until_nonempty(wapbox_list) == 1)
01017         gwthread_sleep(1.0);
01018 
01019     /* wait for wdp_to_wapboxes to exit */
01020     while(gwlist_consume(wapbox_list)!=NULL)
01021     ;
01022     
01023     /* close listen socket */
01024     close(fd);   
01025  
01026     gwlist_destroy(wapbox_list, NULL);
01027     wapbox_list = NULL;
01028     
01029     gwlist_remove_producer(flow_threads);
01030 }

Here is the call graph for this function:

void wdp_to_wapboxes void *  arg  )  [static]
 

Definition at line 838 of file bb_boxc.c.

References AddrPar, _boxc::alive, ap_destroy(), bb_status, Boxc, debug(), flow_threads, gw_assert, gwlist_add_producer(), gwlist_consume(), gwlist_create, gwlist_destroy(), gwlist_extract_first(), gwlist_get(), gwlist_len(), gwlist_lock(), gwlist_produce(), gwlist_remove_producer(), gwlist_unlock(), _boxc::incoming, incoming_wdp, msg_destroy(), msg_type, route_msg(), suspended, wapbox_list, warning(), and wdp_datagram.

Referenced by wapbox_start().

00839 {
00840     List *route_info;
00841     AddrPar *ap;
00842     Boxc *conn;
00843     Msg *msg;
00844     int i;
00845 
00846     gwlist_add_producer(flow_threads);
00847     gwlist_add_producer(wapbox_list);
00848 
00849     route_info = gwlist_create();
00850 
00851     
00852     while(bb_status != BB_DEAD) {
00853 
00854         gwlist_consume(suspended);  /* block here if suspended */
00855 
00856         if ((msg = gwlist_consume(incoming_wdp)) == NULL)
00857              break;
00858 
00859         gw_assert(msg_type(msg) == wdp_datagram);
00860 
00861         conn = route_msg(route_info, msg);
00862         if (conn == NULL) {
00863             warning(0, "Cannot route message, discard it");
00864             msg_destroy(msg);
00865             continue;
00866         }
00867         gwlist_produce(conn->incoming, msg);
00868     }
00869     debug("bb", 0, "wdp_to_wapboxes: destroying lists");
00870     while((ap = gwlist_extract_first(route_info)) != NULL)
00871     ap_destroy(ap);
00872 
00873     gw_assert(gwlist_len(route_info) == 0);
00874     gwlist_destroy(route_info, NULL);
00875 
00876     gwlist_lock(wapbox_list);
00877     for(i=0; i < gwlist_len(wapbox_list); i++) {
00878         conn = gwlist_get(wapbox_list, i);
00879         gwlist_remove_producer(conn->incoming);
00880         conn->alive = 0;
00881     }
00882     gwlist_unlock(wapbox_list);
00883 
00884     gwlist_remove_producer(wapbox_list);
00885     gwlist_remove_producer(flow_threads);
00886 }

Here is the call graph for this function:


Variable Documentation

volatile sig_atomic_t bb_status
 

Definition at line 120 of file bearerbox.c.

Referenced by bb_flush_dlr(), bb_isolate(), bb_print_status(), bb_resume(), bb_suspend(), boxc_receiver(), boxc_sender(), check_args(), httpadmin_run(), httpd_check_status(), httpd_restart(), httpd_shutdown(), main(), read_from_box(), set_shutdown_status(), signal_handler(), sms_router(), sms_to_smsboxes(), smsc2_rout(), udp_receiver(), udp_sender(), wait_for_connections(), wdp_router(), and wdp_to_wapboxes().

Octstr* box_allow_ip [static]
 

Definition at line 123 of file bb_boxc.c.

Referenced by accept_boxc(), boxc_cleanup(), and wapbox_start().

Octstr* box_deny_ip [static]
 

Definition at line 124 of file bb_boxc.c.

Referenced by accept_boxc(), boxc_cleanup(), and wapbox_start().

Counter* boxid [static]
 

Definition at line 127 of file bb_boxc.c.

Referenced by boxc_cleanup(), boxc_create(), smsbox_start(), and wapbox_start().

List* flow_threads
 

Definition at line 107 of file bearerbox.c.

Referenced by bb_smscconn_killed(), bb_smscconn_ready(), boxc_sender(), main(), run_smsbox(), run_wapbox(), service_router(), sms_router(), sms_to_smsboxes(), smsboxc_run(), udp_receiver(), udp_sender(), wapboxc_run(), wdp_router(), and wdp_to_wapboxes().

List* incoming_sms
 

Definition at line 83 of file bearerbox.c.

Referenced by bb_print_status(), bb_smscconn_killed(), bb_smscconn_ready(), dispatch_into_queue(), empty_msg_lists(), init_bearerbox(), route_incoming_to_boxc(), run_smsbox(), sms_to_smsboxes(), smsboxc_run(), smsc2_shutdown(), and smsc2_start().

List* incoming_wdp
 

Definition at line 86 of file bearerbox.c.

Referenced by bb_print_status(), empty_msg_lists(), init_bearerbox(), main(), service_router(), udp_receiver(), udp_shutdown(), udp_start(), wapboxc_run(), and wdp_to_wapboxes().

long max_incoming_sms_qlength
 

Definition at line 95 of file bearerbox.c.

Referenced by init_bearerbox(), init_concat_handler(), and route_incoming_to_boxc().

List* outgoing_sms
 

Definition at line 84 of file bearerbox.c.

Referenced by bb_print_status(), bb_smscconn_send_failed(), dispatch_into_queue(), empty_msg_lists(), init_bearerbox(), sms_router(), smsbox_start(), smsboxc_run(), and smsc2_rout().

List* outgoing_wdp
 

Definition at line 87 of file bearerbox.c.

Referenced by bb_print_status(), empty_msg_lists(), init_bearerbox(), main(), udp_receiver(), wapbox_start(), wapboxc_run(), and wdp_router().

volatile sig_atomic_t restart
 

Definition at line 136 of file bearerbox.c.

Referenced by bb_restart(), boxc_sender(), main(), and read_messages_from_bearerbox().

long sms_dequeue_thread [static]
 

Definition at line 130 of file bb_boxc.c.

Referenced by boxc_receiver(), run_smsbox(), smsbox_start(), and smsboxc_run().

Dict* smsbox_by_id [static]
 

Definition at line 110 of file bb_boxc.c.

Referenced by boxc_receiver(), route_incoming_to_boxc(), run_smsbox(), smsbox_start(), and smsboxc_run().

Dict* smsbox_by_receiver [static]
 

Definition at line 112 of file bb_boxc.c.

Referenced by init_smsbox_routes(), route_incoming_to_boxc(), smsbox_start(), and smsboxc_run().

Dict* smsbox_by_smsc [static]
 

Definition at line 111 of file bb_boxc.c.

Referenced by init_smsbox_routes(), route_incoming_to_boxc(), smsbox_start(), and smsboxc_run().

Dict* smsbox_by_smsc_receiver [static]
 

Definition at line 113 of file bb_boxc.c.

Referenced by init_smsbox_routes(), route_incoming_to_boxc(), smsbox_start(), and smsboxc_run().

List* smsbox_list [static]
 

Definition at line 106 of file bb_boxc.c.

Referenced by boxc_status(), route_incoming_to_boxc(), run_smsbox(), sms_to_smsboxes(), smsbox_start(), and smsboxc_run().

RWLock* smsbox_list_rwlock [static]
 

Definition at line 107 of file bb_boxc.c.

Referenced by boxc_status(), route_incoming_to_boxc(), run_smsbox(), sms_to_smsboxes(), smsbox_start(), and smsboxc_run().

long smsbox_max_pending [static]
 

Definition at line 121 of file bb_boxc.c.

Referenced by run_smsbox(), and smsbox_start().

long smsbox_port [static]
 

Definition at line 115 of file bb_boxc.c.

Referenced by smsbox_start().

int smsbox_port_ssl [static]
 

Definition at line 116 of file bb_boxc.c.

Referenced by smsbox_start(), and smsboxc_run().

volatile sig_atomic_t smsbox_running [static]
 

Definition at line 103 of file bb_boxc.c.

Referenced by smsbox_start().

List* suspended
 

Definition at line 113 of file bearerbox.c.

Referenced by bb_isolate(), bb_resume(), bb_suspend(), boxc_receiver(), boxc_sender(), main(), set_shutdown_status(), udp_sender(), wait_for_connections(), and wdp_to_wapboxes().

List* wapbox_list [static]
 

Definition at line 105 of file bb_boxc.c.

Referenced by boxc_incoming_wdp_queue(), boxc_status(), route_msg(), run_wapbox(), wapbox_start(), wapboxc_run(), and wdp_to_wapboxes().

long wapbox_port [static]
 

Definition at line 117 of file bb_boxc.c.

Referenced by wapbox_start().

int wapbox_port_ssl [static]
 

Definition at line 118 of file bb_boxc.c.

Referenced by wapbox_start(), and wapboxc_run().

volatile sig_atomic_t wapbox_running [static]
 

Definition at line 104 of file bb_boxc.c.

Referenced by wapbox_start().

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