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

手机WAP编程

开发平台:

WINDOWS

  1. /*
  2.  * Wap_push_ota.c: implementation of push related requests of OTA protocol
  3.  *
  4.  * This module implements requirement primitives of WAP-189-PushOTA-20000217-a
  5.  * (hereafter called ota).
  6.  * In addition, WAP-203-WSP-20000504-a (wsp) is referred.
  7.  *
  8.  * This module forwards push  requests made by the wap_push_ppg module to 
  9.  * connected or connectionless session services.
  10.  * Indications (for confirmed push, push abort and disconnect, e.g., in the 
  11.  * case of unability to create a session) of OTA protocol are done for wap_
  12.  * push_ppg module by a module common with pull, wap-appl. 
  13.  *
  14.  * Note that push header encoding and decoding are divided into two parts:
  15.  * first decoding and encoding numeric values and then packing these values
  16.  * into WSP format and unpacking them from WSP format. This module contains
  17.  * decoding part.
  18.  *
  19.  * By Aarno Syv鋘en for Wapit Ltd and Global Networks Inc.
  20.  */
  21. #include <errno.h>
  22. #include "wap_push_ota.h"
  23. #include "gwlib/gwlib.h"
  24. #include "wap/wsp.h"
  25. #include "wap/wsp_strings.h"
  26. #include "wap/wsp_pdu.h"
  27. /**************************************************************************
  28.  *
  29.  * Internal data structures
  30.  */ 
  31. /*
  32.  * Give the status of the push ota module:
  33.  *
  34.  * limbo
  35.  * not running at all
  36.  * running
  37.  * operating normally
  38.  * terminating
  39.  * waiting for operations to terminate, returning to limbo
  40.  */
  41. static enum {limbo, running, terminating} run_status = limbo;
  42. /*
  43.  * Bearerbox address for the phone (it needs to know who it is talking with)
  44.  */
  45. struct BearerboxAddress {
  46.     Octstr *address;
  47.     Mutex *mutex;
  48. }; 
  49. typedef struct BearerboxAddress BearerboxAddress;
  50. static BearerboxAddress *bearerbox = NULL;
  51. static List *ota_queue = NULL;
  52. wap_dispatch_func_t *dispatch_to_wsp;
  53. wap_dispatch_func_t *dispatch_to_wsp_unit;
  54. /**************************************************************************
  55.  *
  56.  * Prototypes of internal functions
  57.  */
  58. static void main_thread(void *arg);
  59. static void handle_ota_event(WAPEvent *e);
  60. static void make_session_request(WAPEvent *e);
  61. static void make_push_request(WAPEvent *e);
  62. static void make_confirmed_push_request(WAPEvent *e);
  63. static void make_unit_push_request(WAPEvent *e);
  64. static void abort_push(WAPEvent *e);
  65. /*
  66.  * Add push flag into push headers. Push flag is defined in PushOTA, p. 17-18.
  67.  */
  68. static List *add_push_flag(WAPEvent *e);
  69. /*
  70.  * When server is requesting a session with a client, content type and applic-
  71.  * ation headers must be present (this behaviour is defined in PushOTA, p. 14).
  72.  * We check headers for them and add them if they are not already present.
  73.  */
  74. static void check_session_request_headers(List *headers);
  75. /*
  76.  * Contact points and application ids in the push initiator are packed into a
  77.  * specific structure, being like WSP PDUs.
  78.  */
  79. static Octstr *pack_sia(List *headers);
  80. static void flags_assert(WAPEvent *e);
  81. static void reason_assert(long reason);
  82. static Octstr *pack_server_address(void);
  83. static Octstr *pack_appid_list(List *headers);
  84. /*
  85.  * Returns bearerbox ip address. Resolve it, if the address is localhost.
  86.  */
  87. static Octstr *name(Octstr *os);
  88. static BearerboxAddress *bearerbox_address_create(void);
  89. static void bearerbox_address_destroy(BearerboxAddress *ba);
  90. /***************************************************************************
  91.  *
  92.  * EXTERNAL FUNCTIONS
  93.  */
  94. void wap_push_ota_init(wap_dispatch_func_t *wsp_dispatch,
  95.                        wap_dispatch_func_t *wsp_unit_dispatch)
  96. {
  97.     ota_queue = list_create();
  98.     list_add_producer(ota_queue);
  99.     dispatch_to_wsp = wsp_dispatch;
  100.     dispatch_to_wsp_unit = wsp_unit_dispatch;
  101.     bearerbox = bearerbox_address_create();
  102.     gw_assert(run_status == limbo);
  103.     run_status = running;
  104.     gwthread_create(main_thread, NULL);
  105. }
  106. void wap_push_ota_shutdown(void)
  107. {
  108.     gw_assert(run_status == running);
  109.     run_status = terminating;
  110.     list_remove_producer(ota_queue);
  111.     gwthread_join_every(main_thread);
  112.     list_destroy(ota_queue, wap_event_destroy_item);
  113.     bearerbox_address_destroy(bearerbox);
  114. }
  115. void wap_push_ota_dispatch_event(WAPEvent *e)
  116. {
  117.     gw_assert(run_status == running); 
  118.     list_produce(ota_queue, e);
  119. }
  120. /*
  121.  * Sets bearerbox address, used for push contact point. Resolve address local-
  122.  * host before assignment.
  123.  */
  124. void wap_push_ota_bb_address_set(Octstr *in)
  125. {
  126.     gw_assert(in);
  127.     mutex_lock(bearerbox->mutex);
  128.     bearerbox->address = name(in);
  129.     mutex_unlock(bearerbox->mutex);
  130. }
  131. /**************************************************************************
  132.  *
  133.  * INTERNAL FUNCTIONS
  134.  */
  135. static void main_thread(void *arg)
  136. {
  137.     WAPEvent *e;
  138.     while (run_status == running && (e = list_consume(ota_queue)) != NULL) {
  139.         handle_ota_event(e);
  140.     } 
  141. }
  142. static void handle_ota_event(WAPEvent *e)
  143. {
  144.     debug("wap.push.ota", 0, "OTA: event arrived");
  145.     switch (e->type) {
  146.     case Pom_SessionRequest_Req:
  147.         make_session_request(e);
  148.     break;
  149.     case Po_Push_Req:
  150.         make_push_request(e);
  151.     break;
  152.     case Po_ConfirmedPush_Req:
  153.         make_confirmed_push_request(e);
  154.     break;
  155.     case Po_Unit_Push_Req:
  156.         make_unit_push_request(e);
  157.     break;
  158.     case Po_PushAbort_Req:
  159.         abort_push(e);
  160.     break;
  161.     default:
  162.         debug("wap.push.ota", 0, "OTA: unhandled event");
  163.         wap_event_dump(e);
  164.     break;
  165.     }
  166.     wap_event_destroy(e);
  167. }
  168. static void make_session_request(WAPEvent *e)
  169. {
  170.     WAPEvent *wsp_event;
  171.     List *appid_headers, *push_headers;
  172.     gw_assert(e->type == Pom_SessionRequest_Req);
  173.     push_headers = e->u.Pom_SessionRequest_Req.push_headers;
  174.     check_session_request_headers(push_headers);
  175.     wsp_event = wap_event_create(S_Unit_Push_Req);
  176.     wsp_event->u.S_Unit_Push_Req.address_type =
  177.         e->u.Pom_SessionRequest_Req.address_type;
  178.     wsp_event->u.S_Unit_Push_Req.push_id = 
  179.         e->u.Pom_SessionRequest_Req.push_id;
  180.     wsp_event->u.S_Unit_Push_Req.addr_tuple = 
  181.         wap_addr_tuple_duplicate(e->u.Pom_SessionRequest_Req.addr_tuple);
  182.     wsp_event->u.S_Unit_Push_Req.push_headers = 
  183.         http_header_duplicate(push_headers);
  184.     appid_headers = http_header_find_all(push_headers, "X-WAP-Application-Id");
  185.     wsp_event->u.S_Unit_Push_Req.push_body = pack_sia(appid_headers);
  186.     
  187.     debug("wap.push.ota", 0, "OTA: making a connectionless session request for"
  188.           " creating a session");
  189.     dispatch_to_wsp_unit(wsp_event);
  190. }
  191. static void make_push_request(WAPEvent *e)
  192. {
  193.     WAPEvent *wsp_event;
  194.     List *push_headers;
  195.     gw_assert(e->type == Po_Push_Req);
  196.     push_headers = add_push_flag(e);
  197.     
  198.     wsp_event = wap_event_create(S_Push_Req);
  199.     wsp_event->u.S_Push_Req.push_headers = push_headers;
  200.     if (e->u.Po_Push_Req.push_body != NULL)
  201.         wsp_event->u.S_Push_Req.push_body = 
  202.             octstr_duplicate(e->u.Po_Push_Req.push_body);
  203.     else
  204.         wsp_event->u.S_Push_Req.push_body = NULL;
  205.     wsp_event->u.S_Push_Req.session_id = e->u.Po_Push_Req.session_handle;
  206.     dispatch_to_wsp(wsp_event);
  207. }
  208. static void make_confirmed_push_request(WAPEvent *e)
  209. {
  210.     WAPEvent *wsp_event;
  211.     List *push_headers;
  212.     gw_assert(e->type == Po_ConfirmedPush_Req);
  213.     push_headers = add_push_flag(e);
  214.     
  215.     wsp_event = wap_event_create(S_ConfirmedPush_Req);
  216.     wsp_event->u.S_ConfirmedPush_Req.server_push_id = 
  217.         e->u.Po_ConfirmedPush_Req.server_push_id;
  218.     wsp_event->u.S_ConfirmedPush_Req.push_headers = push_headers;
  219.     if (e->u.Po_ConfirmedPush_Req.push_body != NULL)
  220.         wsp_event->u.S_ConfirmedPush_Req.push_body =
  221.         octstr_duplicate(e->u.Po_ConfirmedPush_Req.push_body);
  222.     else
  223.         wsp_event->u.S_ConfirmedPush_Req.push_body = NULL;
  224.      
  225.     wsp_event->u.S_ConfirmedPush_Req.session_id = 
  226.         e->u.Po_ConfirmedPush_Req.session_handle;
  227.     debug("wap.push.ota", 0, "OTA: making confirmed push request to wsp");
  228.     
  229.     dispatch_to_wsp(wsp_event);
  230. }
  231. static void make_unit_push_request(WAPEvent *e)
  232. {
  233.     WAPEvent *wsp_event;
  234.     List *push_headers;
  235.     gw_assert(e->type == Po_Unit_Push_Req);
  236.     push_headers = add_push_flag(e);
  237.     wsp_event = wap_event_create(S_Unit_Push_Req);
  238.     wsp_event->u.S_Unit_Push_Req.addr_tuple = 
  239.         wap_addr_tuple_duplicate(e->u.Po_Unit_Push_Req.addr_tuple);
  240.     wsp_event->u.S_Unit_Push_Req.push_id = e->u.Po_Unit_Push_Req.push_id;
  241.     wsp_event->u.S_Unit_Push_Req.push_headers = push_headers;
  242.     wsp_event->u.S_Unit_Push_Req.address_type = 
  243.         e->u.Po_Unit_Push_Req.address_type;
  244.     if (e->u.Po_Unit_Push_Req.push_body != NULL)
  245.         wsp_event->u.S_Unit_Push_Req.push_body =
  246.     octstr_duplicate(e->u.Po_Unit_Push_Req.push_body);
  247.     dispatch_to_wsp_unit(wsp_event);
  248.     debug("wap.push.ota", 0, "OTA: made connectionless session service"
  249.           " request");
  250. }
  251. static void abort_push(WAPEvent *e)
  252. {
  253.     WAPEvent *wsp_event;
  254.     long reason;
  255.     
  256.     reason = e->u.Po_PushAbort_Req.reason;
  257.     gw_assert(e->type == Po_PushAbort_Req);
  258.     reason_assert(reason);
  259.     wsp_event = wap_event_create(S_PushAbort_Req);
  260.     wsp_event->u.S_PushAbort_Req.push_id = e->u.Po_PushAbort_Req.push_id;
  261.     wsp_event->u.S_PushAbort_Req.reason = reason;
  262.     wsp_event->u.S_PushAbort_Req.session_handle = 
  263.         e->u.Po_PushAbort_Req.session_id;
  264.     dispatch_to_wsp(wsp_event);    
  265. }
  266. /*
  267.  * Add push flag into push headers. Push flag is defined in otaa, p. 17-18.
  268.  */
  269. static List *add_push_flag(WAPEvent *e)
  270. {
  271.     int push_flag,
  272.         trusted,
  273.         authenticated,
  274.         last;
  275.     Octstr *buf;
  276.     List *headers;
  277.     flags_assert(e);
  278.     if (e->type == Po_Unit_Push_Req) {
  279.         trusted = e->u.Po_Unit_Push_Req.trusted << 1;
  280.         authenticated = e->u.Po_Unit_Push_Req.authenticated;
  281.         last = e->u.Po_Unit_Push_Req.last << 2;
  282.         headers = http_header_duplicate(e->u.Po_Unit_Push_Req.push_headers);
  283.     } else if (e->type == Po_Push_Req) {
  284.         trusted = e->u.Po_Push_Req.trusted << 1;
  285.         authenticated = e->u.Po_Push_Req.authenticated;
  286.         last = e->u.Po_Push_Req.last << 2;
  287.         headers = http_header_duplicate(e->u.Po_Push_Req.push_headers);
  288.     } else if (e->type == Po_ConfirmedPush_Req) {
  289.         trusted = e->u.Po_ConfirmedPush_Req.trusted << 1;
  290.         authenticated = e->u.Po_ConfirmedPush_Req.authenticated;
  291.         last = e->u.Po_ConfirmedPush_Req.last << 2;
  292.         headers = http_header_duplicate(
  293.             e->u.Po_ConfirmedPush_Req.push_headers);
  294.     } else {
  295.         debug("wap.ota", 0, "OTA: no push flag when the event is: n");
  296.         wap_event_dump(e);
  297.         return NULL;
  298.     }
  299.     push_flag = 0;
  300.     push_flag = push_flag | authenticated | trusted | last;
  301.     
  302.     buf = octstr_format("%d", push_flag);
  303.     http_header_add(headers, "Push-Flag", octstr_get_cstr(buf)); 
  304.     octstr_destroy(buf);
  305.     return headers;
  306. }
  307. static void flags_assert(WAPEvent *e)
  308. {
  309.     if (e->type == Po_Unit_Push_Req) {
  310.         gw_assert(e->u.Po_Unit_Push_Req.trusted == 0 || 
  311.             e->u.Po_Unit_Push_Req.trusted == 1);
  312.         gw_assert(e->u.Po_Unit_Push_Req.authenticated == 0 || 
  313.             e->u.Po_Unit_Push_Req.authenticated == 1);
  314.         gw_assert(e->u.Po_Unit_Push_Req.last == 0 || 
  315.             e->u.Po_Unit_Push_Req.last == 1);
  316.     } else if (e->type == Po_Push_Req) {
  317.         gw_assert(e->u.Po_Push_Req.trusted == 0 || 
  318.             e->u.Po_Push_Req.trusted == 1);
  319.         gw_assert(e->u.Po_Push_Req.authenticated == 0 || 
  320.             e->u.Po_Push_Req.authenticated == 1);
  321.         gw_assert(e->u.Po_Push_Req.last == 0 || 
  322.             e->u.Po_Push_Req.last == 1);
  323.     } else if (e->type == Po_ConfirmedPush_Req) {
  324.         gw_assert(e->u.Po_ConfirmedPush_Req.trusted == 0 || 
  325.             e->u.Po_ConfirmedPush_Req.trusted == 1);
  326.         gw_assert(e->u.Po_ConfirmedPush_Req.authenticated == 0 || 
  327.             e->u.Po_ConfirmedPush_Req.authenticated == 1);
  328.         gw_assert(e->u.Po_ConfirmedPush_Req.last == 0 || 
  329.             e->u.Po_ConfirmedPush_Req.last == 1);
  330.     }
  331. }
  332. /*
  333.  * Accepted reasons are defined in ota 6.3.3.
  334.  */
  335. static void reason_assert(long reason)
  336. {
  337.     gw_assert(reason == WSP_ABORT_USERREQ || reason == WSP_ABORT_USERRFS || 
  338.               reason == WSP_ABORT_USERPND || reason == WSP_ABORT_USERDCR || 
  339.               reason == WSP_ABORT_USERDCU);
  340. }
  341. /*
  342.  * When server is requesting a session with a client, content type and applic-
  343.  * ation headers must be present (this behaviour is defined in ota, p. 14).
  344.  * We check headers for them and add them if they are not already present. 
  345.  * X-WAP-Application-Id has been added by ppg module.
  346.  */
  347. static void check_session_request_headers(List *headers)
  348. {
  349.     if (!http_type_accepted(headers, "application/wnd.wap.sia"))
  350.          http_header_add(headers, "Content-Type", "application/vnd.wap.sia"); 
  351. }
  352. /*
  353.  * Pack contact points and application id list into sia content type. It is 
  354.  * defined in ota, p. 18. 
  355.  */
  356. static Octstr *pack_sia(List *headers)
  357. {
  358.     Octstr *sia_content;
  359.     WSP_PDU *pdu;
  360.    
  361.     pdu = wsp_pdu_create(sia);
  362.     
  363.     pdu->u.sia.version = CURRENT_VERSION;
  364.     pdu->u.sia.application_id_list = pack_appid_list(headers);
  365.     pdu->u.sia.contactpoints = pack_server_address();
  366.     sia_content = wsp_pdu_pack(pdu);
  367.     
  368.     wsp_pdu_destroy(pdu);
  369.     http_destroy_headers(headers);
  370.     return sia_content;
  371. }
  372. /*
  373.  * Input: List of headers containing only X-Wap-Application-Id headers, values
  374.  * being numeric application id codes. (Ppg module does coding of the header 
  375.  * value part of the X-WAP-Application-Id header).
  376.  * Output: Octstr containing them in a byte list (one id per byte). 
  377.  *
  378.  * Returns: Octstr containing headers, if succesfull, otherwise an empty 
  379.  * octstr.
  380.  */
  381. static Octstr *pack_appid_list(List *headers)
  382. {
  383.     Octstr *appid_os,
  384.            *header_name,
  385.            *header_value;
  386.     long i;
  387.     size_t len;
  388.     i = 0;
  389.     appid_os = octstr_create("");
  390.     len = (size_t) list_len(headers);
  391.     gw_assert(len);
  392.     while (i < len) {
  393.         http_header_get(headers, i, &header_name, &header_value);
  394.         gw_assert(octstr_compare(header_name, 
  395.                   octstr_imm("X-WAP-Application-Id")) == 0);
  396.         octstr_format_append(appid_os, "%S", header_value);
  397.         octstr_destroy(header_name);
  398.         octstr_destroy(header_value);
  399.         ++i;
  400.     }
  401.     
  402.     return appid_os;
  403. }
  404. /*
  405.  * NB: This data includes bearer information. We use IPv4 values. Address Type
  406.  * is defined in wsp, table 16, p. 65
  407.  */
  408. static Octstr *pack_server_address(void)
  409. {
  410.     Octstr *address,
  411.            *ip_address;
  412.     unsigned char address_len;
  413.     long port;
  414.     int bearer_type;
  415.     bearer_type = GSM_CSD_IPV4;
  416.     port = CONNECTED_PORT;
  417.     mutex_lock(bearerbox->mutex);  
  418.     ip_address = octstr_duplicate(bearerbox->address);
  419.     address_len = octstr_len(bearerbox->address);
  420.     mutex_unlock(bearerbox->mutex);  
  421.     address = octstr_create("");
  422.     octstr_append_char(address, address_len);
  423.     octstr_set_bits(address, 0, 1, 1); /* bearer type included */
  424.     octstr_set_bits(address, 1, 1, 1); /* port number included */
  425.     octstr_append_char(address, bearer_type);
  426.     octstr_append_decimal(address, port);
  427.     octstr_append(address, ip_address);
  428.     octstr_destroy(ip_address);
  429.     
  430.     return address;
  431. }
  432. /*
  433.  * Returns bearerbox ip address. Resolve it, if the address is localhost. Do 
  434.  * not panic here. Even if we cannot do push, we still can do pull.
  435.  */ 
  436. static Octstr *name(Octstr *in)
  437. {
  438.     if (octstr_compare(in, octstr_imm("localhost")) != 0)
  439.      return octstr_duplicate(in);
  440.     else
  441.     return octstr_duplicate(get_official_ip());
  442. }
  443. static BearerboxAddress *bearerbox_address_create(void) 
  444. {
  445.     BearerboxAddress *ba;    
  446.     ba = gw_malloc(sizeof(BearerboxAddress));
  447.     ba->mutex = mutex_create();
  448.     ba->address = NULL;
  449.     
  450.     return ba;
  451. }
  452. static void bearerbox_address_destroy(BearerboxAddress *ba)
  453. {
  454.     if (ba == NULL)
  455.         return;
  456.     mutex_lock(ba->mutex);
  457.     octstr_destroy(ba->address);
  458.     mutex_destroy(ba->mutex);
  459.     gw_free(ba);
  460. }