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

手机WAP编程

开发平台:

WINDOWS

  1. /*
  2.  * bb_boxc.c : bearerbox box connection module
  3.  *
  4.  * handles start/restart/stop/suspend/die operations of the sms and
  5.  * wapbox connections
  6.  *
  7.  * Kalle Marjola 2000 for project Kannel
  8.  */
  9. #include <errno.h>
  10. #include <stdlib.h>
  11. #include <stdio.h>
  12. #include <time.h>
  13. #include <string.h>
  14. #include <sys/time.h>
  15. #include <sys/types.h>
  16. #include <sys/socket.h>
  17. #include <unistd.h>
  18. #include <signal.h>
  19. #include "gwlib/gwlib.h"
  20. #include "msg.h"
  21. #include "bearerbox.h"
  22. #include "bb_smscconn_cb.h"
  23. /* passed from bearerbox core */
  24. extern volatile sig_atomic_t bb_status;
  25. extern List *incoming_sms;
  26. extern List *outgoing_sms;
  27. extern List *incoming_wdp;
  28. extern List *outgoing_wdp;
  29. extern List *flow_threads;
  30. extern List *suspended;
  31. /* our own thingies */
  32. static volatile sig_atomic_t smsbox_running;
  33. static volatile sig_atomic_t wapbox_running;
  34. static List *wapbox_list = NULL;
  35. static List *smsbox_list = NULL;
  36. static long smsbox_port;
  37. static int smsbox_port_ssl = 0;
  38. static long wapbox_port;
  39. static int wapbox_port_ssl = 0;
  40. static Octstr *box_allow_ip;
  41. static Octstr *box_deny_ip;
  42. static long boxid = 0;
  43. extern Mutex *boxid_mutex; 
  44. typedef struct _boxc {
  45.     Connection *conn;
  46.     int is_wap;
  47.     long       id;
  48.     int load;
  49.     time_t connect_time;
  50.     Octstr     *client_ip;
  51.     List       *incoming;
  52.     List       *retry;    /* If sending fails */
  53.     List        *outgoing;
  54.     volatile sig_atomic_t alive;
  55. } Boxc;
  56. /*-------------------------------------------------
  57.  *  receiver thingies
  58.  */
  59. static Msg *read_from_box(Boxc *boxconn)
  60. {
  61.     int ret;
  62.     Octstr *pack;
  63.     Msg *msg;
  64.     pack = NULL;
  65.     while (bb_status != BB_DEAD && boxconn->alive) {
  66.     pack = conn_read_withlen(boxconn->conn);
  67.     gw_claim_area(pack);
  68.     if (pack != NULL)
  69.         break;
  70.     if (conn_read_error(boxconn->conn)) {
  71.         info(0, "Read error when reading from box <%s>, disconnecting",
  72.          octstr_get_cstr(boxconn->client_ip));
  73.         return NULL;
  74.     }
  75.     if (conn_eof(boxconn->conn)) {
  76.         info(0, "Connection closed by the box <%s>",
  77.          octstr_get_cstr(boxconn->client_ip));
  78.         return NULL;
  79.     }
  80.     ret = conn_wait(boxconn->conn, -1.0);
  81.     if (ret < 0) {
  82.         error(0, "Connection to box <%s> broke.",
  83.           octstr_get_cstr(boxconn->client_ip));
  84.         return NULL;
  85.     }
  86.     }
  87.     
  88.     if (pack == NULL)
  89.      return NULL;
  90.     msg = msg_unpack(pack);
  91.     octstr_destroy(pack);
  92.     if (msg == NULL)
  93.     error(0, "Failed to unpack data!");
  94.     return msg;
  95. }
  96. static void boxc_receiver(void *arg)
  97. {
  98.     Boxc *conn = arg;
  99.     Msg *msg;
  100.     /* remove messages from socket until it is closed */
  101.     while(bb_status != BB_DEAD && conn->alive) {
  102.       list_consume(suspended); /* block here if suspended */
  103.       msg = read_from_box(conn);
  104.       if (msg == NULL) { /* garbage/connection lost */
  105.           conn->alive = 0;
  106.           break;
  107.       }
  108.       if (msg_type(msg) == sms && conn->is_wap == 0)
  109.       {
  110.           debug("bb.boxc", 0, "boxc_receiver: sms received");
  111.     /* XXXX save modifies ID, so if the smsbox uses it, save
  112.      *    it FIRST for the reply message!!! */
  113.           store_save(msg);
  114.           if (smsc2_rout(msg)== -1) {
  115.           warning(0, "Message rejected by bearerbox, no router!");
  116.           /* send NACK */
  117.               bb_smscconn_send_failed(NULL, msg, SMSCCONN_FAILED_DISCARDED);
  118.           }
  119.           if (msg->sms.sms_type == mt_push) {
  120. /* XXX generate ack-message and send it - in fact, this
  121.  *  should include information did it succeed, wa sit queued
  122.  *  or rejected... */
  123.           }
  124.      } else if (msg_type(msg) == wdp_datagram  && conn->is_wap) {
  125.           debug("bb.boxc", 0, "boxc_receiver: got wdp from wapbox");
  126.             
  127.           list_produce(conn->outgoing, msg);
  128.      } else if (msg_type(msg) == sms  && conn->is_wap) {
  129.               debug("bb.boxc", 0, "boxc_receiver: got sms from wapbox");
  130.               store_save(msg);
  131.               if (smsc2_rout(msg)== -1) {
  132.           warning(0, "Message rejected by bearerbox, no router!");
  133.           msg_destroy(msg);
  134.               }
  135.         /* Generate ack here. SM from wapbox is certainly mt push.*/
  136.          } else {
  137.           if (msg_type(msg) == heartbeat) {
  138.           if (msg->heartbeat.load != conn->load)
  139.               debug("bb.boxc", 0, "boxc_receiver: heartbeat with "
  140.                 "load value %ld received", msg->heartbeat.load);
  141.               conn->load = msg->heartbeat.load;
  142.           }
  143.      else if (msg_type(msg) == ack) {
  144.       store_save(msg);
  145.       debug("bb.boxc", 0, "boxc_receiver: got ack");
  146.      }
  147.      else
  148.       warning(0, "boxc_receiver: unknown msg received from <%s>, "
  149.      "ignored", octstr_get_cstr(conn->client_ip));
  150.           msg_destroy(msg);
  151.     }
  152.     }    
  153. }
  154. /*---------------------------------------------
  155.  * sender thingies
  156.  */
  157. static int send_msg(Boxc *boxconn, Msg *pmsg)
  158. {
  159.     Octstr *pack;
  160.     pack = msg_pack(pmsg);
  161.     if (conn_write_withlen(boxconn->conn, pack) == -1) {
  162.      error(0, "Couldn't write Msg to box <%s>, disconnecting",
  163.       octstr_get_cstr(boxconn->client_ip));
  164.     return -1;
  165.     }
  166.     octstr_destroy(pack);
  167.     return 0;
  168. }
  169. static void boxc_sender(void *arg)
  170. {
  171.     Msg *msg;
  172.     Boxc *conn = arg;
  173.     list_add_producer(flow_threads);
  174.     while(bb_status != BB_DEAD && conn->alive) {
  175. /* Make sure there's no data left in the outgoing connection before
  176.  * doing the potentially blocking list_consume()s */
  177.     conn_flush(conn->conn);
  178.     list_consume(suspended); /* block here if suspended */
  179.     if ((msg = list_consume(conn->incoming)) == NULL) {
  180.     /* tell sms/wapbox to die */
  181.         msg = msg_create(admin);
  182.         msg->admin.command = cmd_shutdown;
  183.         send_msg(conn, msg);
  184.         msg_destroy(msg);
  185.         break;
  186.     }
  187.     if (msg_type(msg) == heartbeat) {
  188.         debug("bb.boxc", 0, "boxc_sender: catch an heartbeat - we are alive");
  189.         msg_destroy(msg);
  190.         continue;
  191.     }
  192.     if (!conn->alive) {
  193.     /* we got message here */
  194.         list_produce(conn->retry, msg);
  195.         break;
  196.     }
  197.         if (send_msg(conn, msg) == -1) {
  198.     /* if we fail to send, return msg to the list it came from
  199.      * before dying off */
  200.         list_produce(conn->retry, msg);
  201.        break;
  202.     }
  203.     msg_destroy(msg);
  204.     debug("bb.boxc", 0, "boxc_sender: sent message to <%s>",
  205.           octstr_get_cstr(conn->client_ip));
  206.     }
  207.     /* the client closes the connection, after that die in receiver */
  208.     /* conn->alive = 0; */
  209.     list_remove_producer(flow_threads);
  210. }
  211. /*---------------------------------------------------------------
  212.  * accept/create/kill thingies
  213.  */
  214. static Boxc *boxc_create(int fd, Octstr *ip, int ssl)
  215. {
  216.     Boxc *boxc;
  217.     
  218.     boxc = gw_malloc(sizeof(Boxc));
  219.     boxc->is_wap = 0;
  220.     boxc->load = 0;
  221.     boxc->conn = conn_wrap_fd(fd, ssl);
  222.     mutex_lock(boxid_mutex); 
  223.     boxc->id = boxid++;
  224.     mutex_unlock(boxid_mutex);
  225.     boxc->client_ip = ip;
  226.     boxc->alive = 1;
  227.     boxc->connect_time = time(NULL);
  228.     return boxc;
  229. }    
  230. static void boxc_destroy(Boxc *boxc)
  231. {
  232.     if (boxc == NULL)
  233.     return;
  234.     
  235.     /* do nothing to the lists, as they are only references */
  236.     if (boxc->conn)
  237.     conn_destroy(boxc->conn);
  238.     octstr_destroy(boxc->client_ip);
  239.     gw_free(boxc);
  240. }    
  241. static Boxc *accept_boxc(int fd, int ssl)
  242. {
  243.     Boxc *newconn;
  244.     Octstr *ip;
  245.     int newfd;
  246.     struct sockaddr_in client_addr;
  247.     socklen_t client_addr_len;
  248.     client_addr_len = sizeof(client_addr);
  249.     newfd = accept(fd, (struct sockaddr *)&client_addr, &client_addr_len);
  250.     if (newfd < 0)
  251.     return NULL;
  252.     ip = host_ip(client_addr);
  253.     if (is_allowed_ip(box_allow_ip, box_deny_ip, ip) == 0) {
  254.         info(0, "Box connection tried from denied host <%s>, disconnected",
  255.                 octstr_get_cstr(ip));
  256.         octstr_destroy(ip);
  257.         close(newfd);
  258.         return NULL;
  259.     }
  260.     newconn = boxc_create(newfd, ip, ssl);
  261.     
  262.     /*
  263.      * check if the SSL handshake was successfull, otherwise
  264.      * this is no valid box connection any more
  265.      */
  266. #ifdef HAVE_LIBSSL
  267.      if (ssl && !conn_get_ssl(newconn->conn))
  268.         return NULL;
  269. #endif
  270.     if (ssl)
  271.         info(0, "Client connected from <%s> using SSL", octstr_get_cstr(ip));
  272.     else
  273.         info(0, "Client connected from <%s>", octstr_get_cstr(ip));
  274.         
  275.     /* XXX TODO: do the hand-shake, baby, yeah-yeah! */
  276.     return newconn;
  277. }
  278. static void run_smsbox(void *arg)
  279. {
  280.     int fd;
  281.     Boxc *newconn;
  282.     long sender;
  283.     
  284.     list_add_producer(flow_threads);
  285.     fd = (int)arg;
  286.     newconn = accept_boxc(fd, smsbox_port_ssl);
  287.     if (newconn == NULL) {
  288.     list_remove_producer(flow_threads);
  289.     return;
  290.     }
  291.     newconn->incoming = incoming_sms;
  292.     newconn->retry = incoming_sms;
  293.     newconn->outgoing = outgoing_sms;
  294.     
  295.     list_append(smsbox_list, newconn);
  296.     sender = gwthread_create(boxc_sender, newconn);
  297.     if (sender == -1) {
  298.     error(0, "Failed to start a new thread, disconnecting client <%s>",
  299.           octstr_get_cstr(newconn->client_ip));
  300.     goto cleanup;
  301.     }
  302.     list_add_producer(newconn->outgoing);
  303.     boxc_receiver(newconn);
  304.     list_remove_producer(newconn->outgoing);
  305.     gwthread_join(sender);
  306. cleanup:    
  307.     list_delete_equal(smsbox_list, newconn);
  308.     boxc_destroy(newconn);
  309.     list_remove_producer(flow_threads);
  310. }
  311. static void run_wapbox(void *arg)
  312. {
  313.     int fd;
  314.     Boxc *newconn;
  315.     List *newlist;
  316.     long sender;
  317.     list_add_producer(flow_threads);
  318.     fd = (int)arg;
  319.     newconn = accept_boxc(fd, wapbox_port_ssl);
  320.     if (newconn == NULL) {
  321.     list_remove_producer(flow_threads);
  322.     return;
  323.     }
  324.     newconn->is_wap = 1;
  325.     
  326.     /*
  327.      * create a new incoming list for just that box,
  328.      * and add it to list of list pointers, so we can start
  329.      * to route messages to it.
  330.      */
  331.     debug("bb", 0, "setting up systems for new wapbox");
  332.     
  333.     newlist = list_create();
  334.     list_add_producer(newlist);  /* this is released by the 
  335.                         sender/receiver if it exits */
  336.     
  337.     newconn->incoming = newlist;
  338.     newconn->retry = incoming_wdp;
  339.     newconn->outgoing = outgoing_wdp;
  340.     sender = gwthread_create(boxc_sender, newconn);
  341.     if (sender == -1) {
  342.     error(0, "Failed to start a new thread, disconnecting client <%s>",
  343.           octstr_get_cstr(newconn->client_ip));
  344.     goto cleanup;
  345.     }
  346.     list_append(wapbox_list, newconn);
  347.     list_add_producer(newconn->outgoing);
  348.     boxc_receiver(newconn);
  349.     /* cleanup after receiver has exited */
  350.     
  351.     list_remove_producer(newconn->outgoing);
  352.     list_lock(wapbox_list);
  353.     list_delete_equal(wapbox_list, newconn);
  354.     list_unlock(wapbox_list);
  355.     while (list_producer_count(newlist) > 0)
  356.     list_remove_producer(newlist);
  357.     newconn->alive = 0;
  358.     
  359.     gwthread_join(sender);
  360. cleanup:
  361.     gw_assert(list_len(newlist) == 0);
  362.     list_destroy(newlist, NULL);
  363.     boxc_destroy(newconn);
  364.     list_remove_producer(flow_threads);
  365. }
  366. /*------------------------------------------------
  367.  * main single thread functions
  368.  */
  369. typedef struct _addrpar {
  370.     Octstr *address;
  371.     int port;
  372.     int wapboxid;
  373. } AddrPar;
  374. static void ap_destroy(AddrPar *addr)
  375. {
  376.     octstr_destroy(addr->address);
  377.     gw_free(addr);
  378. }
  379. static int cmp_route(void *ap, void *ms)
  380. {
  381.     AddrPar *addr = ap;
  382.     Msg *msg = ms;
  383.     
  384.     if (msg->wdp_datagram.source_port == addr->port  &&
  385.     octstr_compare(msg->wdp_datagram.source_address, addr->address)==0)
  386. return 1;
  387.     return 0;
  388. }
  389. static int cmp_boxc(void *bc, void *ap)
  390. {
  391.     Boxc *boxc = bc;
  392.     AddrPar *addr = ap;
  393.     if (boxc->id == addr->wapboxid) return 1;
  394.         return 0;
  395. }
  396. static Boxc *route_msg(List *route_info, Msg *msg)
  397. {
  398.     AddrPar *ap;
  399.     Boxc *conn, *best;
  400.     int i, b, len;
  401.     
  402.     ap = list_search(route_info, msg, cmp_route);
  403.     if (ap == NULL) {
  404.     debug("bb.boxc", 0, "Did not find previous routing info for WDP, "
  405.        "generating new");
  406. route:
  407.     if (list_len(wapbox_list) == 0)
  408.         return NULL;
  409.     list_lock(wapbox_list);
  410. /* take random wapbox from list, and then check all wapboxes
  411.  * and select the one with lowest load level - if tied, the first
  412.  * one
  413.  */
  414.     len = list_len(wapbox_list);
  415.     b = gw_rand() % len;
  416.     best = list_get(wapbox_list, b);
  417.     for(i = 0; i < list_len(wapbox_list); i++) {
  418.         conn = list_get(wapbox_list, (i+b) % len);
  419.         if (conn != NULL && best != NULL)
  420.         if (conn->load < best->load)
  421.             best = conn;
  422.     }
  423.     if (best == NULL) {
  424.         warning(0, "wapbox_list empty!");
  425.         list_unlock(wapbox_list);
  426.         return NULL;
  427.     }
  428.     conn = best;
  429.     conn->load++; /* simulate new client until we get new values */
  430.     ap = gw_malloc(sizeof(AddrPar));
  431.     ap->address = octstr_duplicate(msg->wdp_datagram.source_address);
  432.     ap->port = msg->wdp_datagram.source_port;
  433.     ap->wapboxid = conn->id;
  434.     list_produce(route_info, ap);
  435.     list_unlock(wapbox_list);
  436.     } else
  437.     conn = list_search(wapbox_list, ap, cmp_boxc);
  438.     if (conn == NULL) {
  439. /* routing failed; wapbox has disappeared!
  440.  * ..remove routing info and re-route   */
  441.     debug("bb.boxc", 0, "Old wapbox has disappeared, re-routing");
  442.     list_delete_equal(route_info, ap);
  443.     ap_destroy(ap);
  444.     goto route;
  445.     }
  446.     return conn;
  447. }
  448. /*
  449.  * this thread listens to incoming_wdp list
  450.  * and then routs messages to proper wapbox
  451.  */
  452. static void wdp_to_wapboxes(void *arg)
  453. {
  454.     List *route_info;
  455.     AddrPar *ap;
  456.     Boxc *conn;
  457.     Msg *msg;
  458.     int i;
  459.     list_add_producer(flow_threads);
  460.     list_add_producer(wapbox_list);
  461.     route_info = list_create();
  462.     
  463.     while(bb_status != BB_DEAD) {
  464.     list_consume(suspended); /* block here if suspended */
  465.     if ((msg = list_consume(incoming_wdp)) == NULL)
  466.          break;
  467.     gw_assert(msg_type(msg) == wdp_datagram);
  468.     conn = route_msg(route_info, msg);
  469.     if (conn == NULL) {
  470.         warning(0, "Cannot route message, discard it");
  471.         msg_destroy(msg);
  472.         continue;
  473.     }
  474.     list_produce(conn->incoming, msg);
  475.     }
  476.     debug("bb", 0, "wdp_to_wapboxes: destroying lists");
  477.     while((ap = list_extract_first(route_info)) != NULL)
  478. ap_destroy(ap);
  479.     gw_assert(list_len(route_info) == 0);
  480.     list_destroy(route_info, NULL);
  481.     list_lock(wapbox_list);
  482.     for(i=0; i < list_len(wapbox_list); i++) {
  483.     conn = list_get(wapbox_list, i);
  484.     list_remove_producer(conn->incoming);
  485.     conn->alive = 0;
  486.     }
  487.     list_unlock(wapbox_list);
  488.     list_remove_producer(wapbox_list);
  489.     list_remove_producer(flow_threads);
  490. }
  491. static void wait_for_connections(int fd, void (*function) (void *arg), 
  492.                      List *waited)
  493. {
  494.     fd_set rf;
  495.     struct timeval tv;
  496.     int ret;
  497.     
  498.     while(bb_status != BB_DEAD) {
  499. /* XXX: if we are being shutdowned, as long as there is
  500.  * messages in incoming list allow new connections, but when
  501.  * list is empty, exit
  502.  */
  503.     if (bb_status == BB_SHUTDOWN) {
  504.         ret = list_wait_until_nonempty(waited);
  505.         if (ret == -1) break;
  506.     }
  507.     FD_ZERO(&rf);
  508.     tv.tv_sec = 1;
  509.     tv.tv_usec = 0;
  510.     if (bb_status != BB_SUSPENDED)
  511.         FD_SET(fd, &rf);
  512.     ret = select(FD_SETSIZE, &rf, NULL, NULL, &tv);
  513.     if (ret > 0) {
  514.         gwthread_create(function, (void *)fd);
  515.         sleep(1);
  516.     } else if (ret < 0) {
  517.         if(errno==EINTR) continue;
  518.         if(errno==EAGAIN) continue;
  519.         error(errno, "wait_for_connections failed");
  520.     }
  521.     }
  522. }
  523. static void smsboxc_run(void *arg)
  524. {
  525.     int fd;
  526.     int port;
  527.     list_add_producer(flow_threads);
  528.     gwthread_wakeup(MAIN_THREAD_ID);
  529.     port = (int)arg;
  530.     
  531.     fd = make_server_socket(port, NULL); 
  532.      /* XXX add interface_name if required */
  533.     if (fd < 0) {
  534.     panic(0, "Could not open smsbox port %d", port);
  535.     }
  536.     /*
  537.      * infinitely wait for new connections;
  538.      * to shut down the system, SIGTERM is send and then
  539.      * select drops with error, so we can check the status
  540.      */
  541.     wait_for_connections(fd, run_smsbox, incoming_sms);
  542.     /* continue avalanche */
  543.     list_remove_producer(outgoing_sms);
  544.     /* all connections do the same, so that all must remove() before it
  545.      * is completely over
  546.      */
  547.     /* XXX KLUDGE fix when list_wait_until_empty() exists */
  548.     while(list_wait_until_nonempty(smsbox_list)!= -1)
  549.     sleep(1);
  550.     list_destroy(smsbox_list, NULL);
  551.     smsbox_list = NULL;
  552.     
  553.     list_remove_producer(flow_threads);
  554. }
  555. static void wapboxc_run(void *arg)
  556. {
  557.     int fd, port;
  558.     list_add_producer(flow_threads);
  559.     gwthread_wakeup(MAIN_THREAD_ID);
  560.     port = (int)arg;
  561.     
  562.     fd = make_server_socket(port, NULL);
  563.      /* XXX add interface_name if required */
  564.     if (fd < 0) {
  565.     panic(0, "Could not open wapbox port %d", port);
  566.     }
  567.     wait_for_connections(fd, run_wapbox, incoming_wdp);
  568.     /* continue avalanche */
  569.     list_remove_producer(outgoing_wdp);
  570.     /* wait for all connections to die and then remove list
  571.      */
  572.     
  573.     /* XXX KLUDGE fix when list_wait_until_empty() exists */
  574.     while(list_wait_until_nonempty(wapbox_list)== 1)
  575.       sleep(1);
  576.     /* wait for wdp_to_wapboxes to exit */
  577.     while(list_consume(wapbox_list)!=NULL)
  578. ;
  579.     
  580.     list_destroy(wapbox_list, NULL);
  581.     wapbox_list = NULL;
  582.     
  583.     list_remove_producer(flow_threads);
  584. }
  585. /*-------------------------------------------------------------
  586.  * public functions
  587.  *
  588.  * SMSBOX
  589.  */
  590. int smsbox_start(Cfg *cfg)
  591. {
  592.     CfgGroup *grp;
  593.     
  594.     if (smsbox_running) return -1;
  595.     debug("bb", 0, "starting smsbox connection module");
  596.     grp = cfg_get_single_group(cfg, octstr_imm("core"));
  597.     if (cfg_get_integer(&smsbox_port, grp, octstr_imm("smsbox-port")) == -1) {
  598.     error(0, "Missing smsbox-port variable, cannot start smsboxes");
  599.     return -1;
  600.     }
  601. #ifdef HAVE_LIBSSL
  602.     cfg_get_bool(&smsbox_port_ssl, grp, octstr_imm("smsbox-port-ssl"));
  603. #endif /* HAVE_LIBSSL */
  604.     if (smsbox_port_ssl)
  605.         debug("bb", 0, "smsbox connection module is SSL-enabled");
  606.     
  607.     smsbox_list = list_create(); /* have a list of connections */
  608.     list_add_producer(outgoing_sms);
  609.     smsbox_running = 1;
  610.     
  611.     if (gwthread_create(smsboxc_run, (void *)smsbox_port) == -1)
  612.     panic(0, "Failed to start a new thread for smsbox connections");
  613.     return 0;
  614. }
  615. int smsbox_restart(Cfg *cfg)
  616. {
  617.     if (!smsbox_running) return -1;
  618.     
  619.     /* send new config to clients */
  620.     return 0;
  621. }
  622. /* WAPBOX */
  623. int wapbox_start(Cfg *cfg)
  624. {
  625.     CfgGroup *grp;
  626.     if (wapbox_running) return -1;
  627.     debug("bb", 0, "starting wapbox connection module");
  628.     
  629.     grp = cfg_get_single_group(cfg, octstr_imm("core"));
  630.     
  631.     if (cfg_get_integer(&wapbox_port, grp, octstr_imm("wapbox-port")) == -1) {
  632.     error(0, "Missing wapbox-port variable, cannot start WAP");
  633.     return -1;
  634.     }
  635. #ifdef HAVE_LIBSSL
  636.     cfg_get_bool(&wapbox_port_ssl, grp, octstr_imm("wapbox-port-ssl"));
  637. #endif /* HAVE_LIBSSL */
  638.   
  639.     box_allow_ip = cfg_get(grp, octstr_imm("box-allow-ip"));
  640.     if (box_allow_ip == NULL)
  641.      box_allow_ip = octstr_create("");
  642.     box_deny_ip = cfg_get(grp, octstr_imm("box-deny-ip"));
  643.     if (box_deny_ip == NULL)
  644.      box_deny_ip = octstr_create("");
  645.     if (box_allow_ip != NULL && box_deny_ip == NULL)
  646.     info(0, "Box connection allowed IPs defined without any denied...");
  647.     
  648.     wapbox_list = list_create(); /* have a list of connections */
  649.     list_add_producer(outgoing_wdp);
  650.     if (gwthread_create(wdp_to_wapboxes, NULL) == -1)
  651.       panic(0, "Failed to start a new thread for wapbox routing");
  652.  
  653.     if (gwthread_create(wapboxc_run, (void *)wapbox_port) == -1)
  654.     panic(0, "Failed to start a new thread for wapbox connections");
  655.     wapbox_running = 1;
  656.     return 0;
  657. }
  658. Octstr *boxc_status(int status_type)
  659. {
  660.     Octstr *tmp;
  661.     char *lb, *ws;
  662.     int i, boxes, para = 0;
  663.     time_t orig, t;
  664.     Boxc *bi;
  665.     orig = time(NULL);
  666.     /*
  667.      * XXX: this will cause segmentation fault if this is called
  668.      *    between 'destroy_list and setting list to NULL calls.
  669.      *    Ok, this has to be fixed, but now I am too tired.
  670.      */
  671.     
  672.     if ((lb = bb_status_linebreak(status_type))==NULL)
  673.     return octstr_create("Un-supported format");
  674.     if (status_type == BBSTATUS_HTML)
  675.     ws = "&nbsp;&nbsp;&nbsp;&nbsp;";
  676.     else if (status_type == BBSTATUS_TEXT)
  677.     ws = "    ";
  678.     else
  679.     ws = "";
  680.     if (status_type == BBSTATUS_HTML || status_type == BBSTATUS_WML)
  681.     para = 1;
  682.     
  683.     if (status_type == BBSTATUS_XML) {
  684.         tmp = octstr_create ("");
  685.         octstr_append_cstr(tmp, "<boxes>nt");
  686.     }
  687.     else
  688.         tmp = octstr_format("%sBox connections:%s", para ? "<p>" : "", lb);
  689.     boxes = 0;
  690.     
  691.     if (wapbox_list) {
  692.     list_lock(wapbox_list);
  693.     for(i=0; i < list_len(wapbox_list); i++) {
  694.         bi = list_get(wapbox_list, i);
  695.         if (bi->alive == 0)
  696.         continue;
  697.         t = orig - bi->connect_time;
  698.             if (status_type == BBSTATUS_XML)
  699.             octstr_format_append(tmp,
  700.         "<box>ntt<type>wapbox</type>ntt<IP>%s</IP>n"
  701.                 "tt<status>on-line %ldd %ldh %ldm %lds</status>n"
  702.                 "tt<ssl>%s</ssl>nt</box>n",
  703. octstr_get_cstr(bi->client_ip),
  704. t/3600/24, t/3600%24, t/60%60, t%60,
  705. #ifdef HAVE_LIBSSL
  706.                 conn_get_ssl(bi->conn) != NULL ? "yes" : "no"
  707. #else 
  708.                 "not installed"
  709. #endif
  710.                 );
  711.             else
  712.             octstr_format_append(tmp,
  713.         "%swapbox, IP %s (on-line %ldd %ldh %ldm %lds) %s %s",
  714. ws, octstr_get_cstr(bi->client_ip),
  715. t/3600/24, t/3600%24, t/60%60, t%60, 
  716. #ifdef HAVE_LIBSSL
  717.                 conn_get_ssl(bi->conn) != NULL ? "using SSL" : "",
  718. #else
  719.                 "",
  720. #endif 
  721.                 lb);
  722.             boxes++;
  723.        }
  724.        list_unlock(wapbox_list);
  725.         }
  726.         if (smsbox_list) {
  727.         list_lock(smsbox_list);
  728.     for(i=0; i < list_len(smsbox_list); i++) {
  729.         bi = list_get(smsbox_list, i);
  730.         if (bi->alive == 0)
  731.         continue;
  732.         t = orig - bi->connect_time;
  733.             if (status_type == BBSTATUS_XML)
  734.             octstr_format_append(tmp, "<box>ntt<type>smsbox</type>ntt<IP>%s</IP>n"
  735.                     "tt<status>on-line %ldd %ldh %ldm %lds</status>n"
  736.                     "tt<ssl>%s</ssl>nt</box>",
  737.             octstr_get_cstr(bi->client_ip),
  738.             t/3600/24, t/3600%24, t/60%60, t%60,
  739. #ifdef HAVE_LIBSSL
  740.                     conn_get_ssl(bi->conn) != NULL ? "yes" : "no"
  741. #else 
  742.                     "not installed"
  743. #endif
  744.                     );
  745.             else
  746.             octstr_format_append(tmp, "%ssmsbox, IP %s (on-line %ldd %ldh %ldm %lds) %s %s",
  747.             ws, octstr_get_cstr(bi->client_ip),
  748.             t/3600/24, t/3600%24, t/60%60, t%60, 
  749. #ifdef HAVE_LIBSSL
  750.                     conn_get_ssl(bi->conn) != NULL ? "using SSL" : "",
  751. #else
  752.                     "",
  753. #endif 
  754.                     lb);
  755.        boxes++;
  756.     }
  757.     list_unlock(smsbox_list);
  758.     }
  759.     if (boxes == 0 && status_type != BBSTATUS_XML) {
  760.     octstr_destroy(tmp);
  761.     tmp = octstr_format("%sNo boxes connected", para ? "<p>" : "");
  762.     }
  763.     if (para)
  764.     octstr_append_cstr(tmp, "</p>");
  765.     if (status_type == BBSTATUS_XML)
  766.         octstr_append_cstr(tmp, "</boxes>n");
  767.     else
  768.         octstr_append_cstr(tmp, "nn");
  769.     return tmp;
  770. }
  771. int boxc_incoming_wdp_queue(void)
  772. {
  773.     int i, q = 0;
  774.     Boxc *boxc;
  775.     
  776.     if (wapbox_list) {
  777.     list_lock(wapbox_list);
  778.     for(i=0; i < list_len(wapbox_list); i++) {
  779.         boxc = list_get(wapbox_list, i);
  780.         q += list_len(boxc->incoming);
  781.     }
  782.     list_unlock(wapbox_list);
  783.     }
  784.     return q;
  785. }
  786. void boxc_cleanup(void)
  787. {
  788.     octstr_destroy(box_allow_ip);
  789.     octstr_destroy(box_deny_ip);
  790.     box_allow_ip = NULL;
  791.     box_deny_ip = NULL;
  792. }