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

手机WAP编程

开发平台:

WINDOWS

  1. /*
  2.  * bb_udpc.c : bearerbox UDP sender/receiver module
  3.  *
  4.  * handles start/restart/shutdown/suspend/die operations of the UDP
  5.  * WDP interface
  6.  *
  7.  * Kalle Marjola <rpr@wapit.com> 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 <unistd.h>
  17. #include <signal.h>
  18. #include <fcntl.h>
  19. #include <assert.h>
  20. #include "gwlib/gwlib.h"
  21. #include "msg.h"
  22. #include "bearerbox.h"
  23. /* passed from bearerbox core */
  24. extern volatile sig_atomic_t bb_status;
  25. extern List *incoming_wdp;
  26. extern Counter *incoming_wdp_counter;
  27. extern Counter *outgoing_wdp_counter;
  28. extern List *flow_threads;
  29. extern List *suspended;
  30. extern List *isolated;
  31. /* our own thingies */
  32. static volatile sig_atomic_t udp_running;
  33. static List *udpc_list;
  34. typedef struct _udpc {
  35.     int fd;
  36.     Octstr *addr;
  37.     List *outgoing_list;
  38.     long receiver;
  39. } Udpc;
  40. /*
  41.  * IP numbers which are allowed or denied us of the bearerbox via UDP.
  42.  */
  43. static Octstr *allow_ip;
  44. static Octstr *deny_ip;
  45. /* forward declarations */
  46. static void udpc_destroy(Udpc *udpc);
  47. /*-------------------------------------------------
  48.  *  receiver thingies
  49.  */
  50. static void udp_receiver(void *arg)
  51. {
  52.     Octstr *datagram, *cliaddr;
  53.     int ret;
  54.     Msg *msg;
  55.     Udpc *conn = arg;
  56.     Octstr *ip;
  57.     list_add_producer(incoming_wdp);
  58.     list_add_producer(flow_threads);
  59.     gwthread_wakeup(MAIN_THREAD_ID);
  60.     
  61.     /* remove messages from socket until it is closed */
  62.     while (bb_status != BB_DEAD && bb_status != BB_SHUTDOWN) {
  63. list_consume(isolated); /* block here if suspended/isolated */
  64. if (read_available(conn->fd, 100000) < 1)
  65.     continue;
  66. ret = udp_recvfrom(conn->fd, &datagram, &cliaddr);
  67. if (ret == -1) {
  68.     if (errno == EAGAIN)
  69. /* No datagram available, don't block. */
  70. continue;
  71.     error(errno, "Failed to receive an UDP");
  72.     /*
  73.      * just continue, or is there ANY error that would result
  74.      * in situation where it would be better to break; or even
  75.      * die off?     - Kalle 28.2
  76.      */
  77.     continue;
  78. }
  79. /* discard the message if the client is not allowed */
  80.      ip = udp_get_ip(cliaddr);
  81. if (!is_allowed_ip(allow_ip, deny_ip, ip)) {
  82.          warning(0, "UDP: Discarding packet from %s, IP is denied.",
  83.        octstr_get_cstr(ip));
  84.          octstr_destroy(datagram);
  85. } else {
  86.     debug("bb.udp", 0, "datagram received");
  87.     msg = msg_create(wdp_datagram);
  88.     
  89.     msg->wdp_datagram.source_address = udp_get_ip(cliaddr);
  90.     msg->wdp_datagram.source_port    = udp_get_port(cliaddr);
  91.     msg->wdp_datagram.destination_address = udp_get_ip(conn->addr);
  92.     msg->wdp_datagram.destination_port    = udp_get_port(conn->addr);
  93.     msg->wdp_datagram.user_data = datagram;
  94.     
  95.     list_produce(incoming_wdp, msg);
  96.     counter_increase(incoming_wdp_counter);
  97. }
  98. octstr_destroy(cliaddr);
  99. octstr_destroy(ip);
  100.     }    
  101.     list_remove_producer(incoming_wdp);
  102.     list_remove_producer(flow_threads);
  103. }
  104. /*---------------------------------------------
  105.  * sender thingies
  106.  */
  107. static int send_udp(int fd, Msg *msg)
  108. {
  109.     Octstr *cliaddr;
  110.     int ret;
  111.     cliaddr = udp_create_address(msg->wdp_datagram.destination_address,
  112.  msg->wdp_datagram.destination_port);
  113.     ret = udp_sendto(fd, msg->wdp_datagram.user_data, cliaddr);
  114.     if (ret == -1)
  115. error(0, "WDP/UDP: could not send UDP datagram");
  116.     octstr_destroy(cliaddr);
  117.     return ret;
  118. }
  119. static void udp_sender(void *arg)
  120. {
  121.     Msg *msg;
  122.     Udpc *conn = arg;
  123.     list_add_producer(flow_threads);
  124.     while(bb_status != BB_DEAD) {
  125. list_consume(suspended); /* block here if suspended */
  126. if ((msg = list_consume(conn->outgoing_list)) == NULL)
  127.     break;
  128. debug("bb.udp", 0, "udp: sending message");
  129.         if (send_udp(conn->fd, msg) == -1)
  130.     /* ok, we failed... tough
  131.      * XXX log the message or something like that... but this
  132.      * is not as fatal as it is with SMS-messages...
  133.      */ {
  134.     msg_destroy(msg);
  135.     continue;
  136. }
  137. counter_increase(outgoing_wdp_counter);
  138. msg_destroy(msg);
  139.     }
  140.     gwthread_join(conn->receiver);
  141.     udpc_destroy(conn);
  142.     list_remove_producer(flow_threads);
  143. }
  144. /*---------------------------------------------------------------
  145.  * accept/create thingies
  146.  */
  147. static Udpc *udpc_create(int port, char *interface_name)
  148. {
  149.     Udpc *udpc;
  150.     Octstr *os;
  151.     int fl;
  152.     
  153.     udpc = gw_malloc(sizeof(Udpc));
  154.     udpc->fd = udp_bind(port, interface_name);
  155.     os = octstr_create(interface_name);
  156.     udpc->addr = udp_create_address(os, port);
  157.     octstr_destroy(os);
  158.     if (udpc->addr == NULL) {
  159. error(0, "updc_create: could not resolve interface <%s>",
  160.       interface_name);
  161. close(udpc->fd);
  162. gw_free(udpc);
  163. return NULL;
  164.     }
  165.     fl = fcntl(udpc->fd, F_GETFL);
  166.     fcntl(udpc->fd, F_SETFL, fl | O_NONBLOCK);
  167.     os = udp_get_ip(udpc->addr);
  168.     debug("bb.udp", 0, "udpc_create: Bound to UDP <%s:%d>",
  169.   octstr_get_cstr(os), udp_get_port(udpc->addr));
  170.     octstr_destroy(os);
  171.     
  172.     udpc->outgoing_list = list_create();
  173.     return udpc;
  174. }    
  175. static void udpc_destroy(Udpc *udpc)
  176. {
  177.     if (udpc == NULL)
  178. return;
  179.     if (udpc->fd >= 0)
  180. close(udpc->fd);
  181.     octstr_destroy(udpc->addr);
  182.     gw_assert(list_len(udpc->outgoing_list) == 0);
  183.     list_destroy(udpc->outgoing_list, NULL);
  184.     gw_free(udpc);
  185. }    
  186. static int add_service(int port, char *interface_name)
  187. {
  188.     Udpc *udpc;
  189.     
  190.     if ((udpc = udpc_create(port, interface_name)) == NULL)
  191. goto error;
  192.     list_add_producer(udpc->outgoing_list);
  193.     udpc->receiver = gwthread_create(udp_receiver, udpc);
  194.     if (udpc->receiver == -1)
  195. goto error;
  196.     if (gwthread_create(udp_sender, udpc) == -1)
  197. goto error;
  198.     list_append(udpc_list, udpc);
  199.     return 0;
  200.     
  201. error:    
  202.     error(0, "Failed to start UDP receiver/sender thread");
  203.     udpc_destroy(udpc);
  204.     return -1;
  205. }
  206. /*-------------------------------------------------------------
  207.  * public functions
  208.  *
  209.  */
  210. int udp_start(Cfg *cfg)
  211. {
  212.     Octstr *interface_name;
  213.     CfgGroup *grp;
  214.     int allow_wtls;
  215.     
  216.     if (udp_running) return -1;
  217.     
  218.     debug("bb.udp", 0, "starting UDP sender/receiver module");
  219.     grp = cfg_get_single_group(cfg, octstr_imm("core"));
  220.     interface_name = cfg_get(grp, octstr_imm("wdp-interface-name"));
  221.     if (interface_name == NULL) {
  222.         error(0, "Missing wdp-interface-name variable, cannot start UDP");
  223.         return -1;
  224.     }
  225.     allow_ip = cfg_get(grp, octstr_imm("udp-allow-ip"));
  226.     deny_ip = cfg_get(grp, octstr_imm("udp-deny-ip"));
  227.     /*  we'll activate WTLS as soon as we have a 'wtls' config group */
  228.     grp = cfg_get_single_group(cfg, octstr_imm("wtls"));
  229.     allow_wtls = grp != NULL ? 1 : 0;
  230.     udpc_list = list_create(); /* have a list of running systems */
  231.     add_service(9200, octstr_get_cstr(interface_name));    /* wsp  */
  232.     add_service(9201, octstr_get_cstr(interface_name));    /* wsp/wtp */
  233. #ifdef HAVE_WTLS_OPENSSL
  234.     if (allow_wtls) {
  235.         add_service(9202, octstr_get_cstr(interface_name));    /* wsp/wtls */
  236.         add_service(9203, octstr_get_cstr(interface_name));    /* wsp/wtp/wtls */
  237.     }
  238. #else
  239.     if (allow_wtls)
  240.      error(0, "These is a 'wtls' group in configuration, but no WTLS support compiled in!");
  241. #endif
  242.     /* add_service(9204, octstr_get_cstr(interface_name));  * vcard */
  243.     /* add_service(9205, octstr_get_cstr(interface_name));  * vcal */
  244.     /* add_service(9206, octstr_get_cstr(interface_name));  * vcard/wtls */
  245.     /* add_service(9207, octstr_get_cstr(interface_name));  * vcal/wtls */
  246.     
  247.     octstr_destroy(interface_name);
  248.     
  249.     list_add_producer(incoming_wdp);
  250.     udp_running = 1;
  251.     return 0;
  252. }
  253. /*
  254.  * this function receives an WDP message and adds it to
  255.  * corresponding outgoing_list.
  256.  */
  257. int udp_addwdp(Msg *msg)
  258. {
  259.     int i;
  260.     Udpc *udpc;
  261.     
  262.     if (!udp_running) return -1;
  263.     assert(msg != NULL);
  264.     assert(msg_type(msg) == wdp_datagram);
  265.     
  266.     list_lock(udpc_list);
  267.     /* select in which list to add this */
  268.     for (i=0; i < list_len(udpc_list); i++) {
  269. udpc = list_get(udpc_list, i);
  270. if (msg->wdp_datagram.source_port == udp_get_port(udpc->addr))
  271. {
  272.      list_produce(udpc->outgoing_list, msg);
  273.      list_unlock(udpc_list);
  274.      return 0;
  275. }
  276.     }
  277.     list_unlock(udpc_list);
  278.     return -1;
  279. }
  280. int udp_shutdown(void)
  281. {
  282.     if (!udp_running) return -1;
  283.     debug("bb.thread", 0, "udp_shutdown: Starting avalanche");
  284.     list_remove_producer(incoming_wdp);
  285.     return 0;
  286. }
  287. int udp_die(void)
  288. {
  289.     Udpc *udpc;
  290.     if (!udp_running) return -1;
  291.     
  292.     /*
  293.      * remove producers from all outgoing lists.
  294.      */
  295.     debug("bb.udp", 0, "udp_die: removing producers from udp-lists");
  296.     while((udpc = list_consume(udpc_list)) != NULL) {
  297. list_remove_producer(udpc->outgoing_list);
  298.     }
  299.     list_destroy(udpc_list, NULL);
  300.     udp_running = 0;
  301.     
  302.     octstr_destroy(allow_ip);
  303.     octstr_destroy(deny_ip);
  304.     allow_ip = NULL;
  305.     deny_ip = NULL;
  306.     
  307.     return 0;
  308. }
  309. int udp_outgoing_queue(void)
  310. {
  311.     int i, q = 0;
  312.     Udpc *udpc;
  313.     if (!udp_running || udpc_list == NULL)
  314. return 0;
  315.     list_lock(udpc_list);
  316.     for (i=0; i < list_len(udpc_list); i++) {
  317. udpc = list_get(udpc_list, i);
  318. q += list_len(udpc->outgoing_list);
  319.     }
  320.     list_unlock(udpc_list);
  321.     return q;
  322. }