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

手机WAP编程

开发平台:

WINDOWS

  1. /*
  2.  * wsp_unit.c - Implement WSP Connectionless mode
  3.  *
  4.  * Lars Wirzenius
  5.  */
  6. #include <string.h>
  7. #include "gwlib/gwlib.h"
  8. #include "wsp.h"
  9. #include "wsp_pdu.h"
  10. #include "wsp_headers.h"
  11. #include "wap_events.h"
  12. #include "wsp_strings.h"
  13. #include "wap.h"
  14. /*
  15.  * Give the status the module:
  16.  *
  17.  * limbo
  18.  * not running at all
  19.  * running
  20.  * operating normally
  21.  * terminating
  22.  * waiting for operations to terminate, returning to limbo
  23.  */
  24. static enum { limbo, running, terminating } run_status = limbo;
  25. static wap_dispatch_func_t *dispatch_to_wdp;
  26. static wap_dispatch_func_t *dispatch_to_appl;
  27. static List *queue = NULL;
  28. static void main_thread(void *);
  29. static WAPEvent *pack_into_result_datagram(WAPEvent *event);
  30. static WAPEvent *pack_into_push_datagram(WAPEvent *event);
  31. /***********************************************************************
  32.  * Public functions
  33.  */
  34. void wsp_unit_init(wap_dispatch_func_t *datagram_dispatch,
  35.                    wap_dispatch_func_t *application_dispatch) {
  36. queue = list_create();
  37. list_add_producer(queue);
  38. dispatch_to_wdp = datagram_dispatch;
  39. dispatch_to_appl = application_dispatch;
  40.         wsp_strings_init();
  41. run_status = running;
  42. gwthread_create(main_thread, NULL);
  43. }
  44. void wsp_unit_shutdown(void) {
  45. gw_assert(run_status == running);
  46. run_status = terminating;
  47. list_remove_producer(queue);
  48. gwthread_join_every(main_thread);
  49. list_destroy(queue, wap_event_destroy_item);
  50.         wsp_strings_shutdown();
  51. }
  52. void wsp_unit_dispatch_event(WAPEvent *event) {
  53. wap_event_assert(event);
  54. list_produce(queue, event);
  55. }
  56. static WAPEvent *unpack_datagram(WAPEvent *datagram) {
  57. WAPEvent *event;
  58. Octstr *os;
  59. WSP_PDU *pdu;
  60. long tid_byte;
  61. int method;
  62. Octstr *method_name;
  63. gw_assert(datagram->type == T_DUnitdata_Ind);
  64. os = NULL;
  65. pdu = NULL;
  66. event = NULL;
  67. os = octstr_duplicate(datagram->u.T_DUnitdata_Ind.user_data);
  68. if (octstr_len(os) == 0) {
  69. warning(0, "WSP UNIT: Empty datagram.");
  70. goto error;
  71. }
  72. tid_byte = octstr_get_char(os, 0);
  73. octstr_delete(os, 0, 1);
  74. pdu = wsp_pdu_unpack(os);
  75. if (pdu == NULL)
  76. goto error;
  77. if (pdu->type != Get && pdu->type != Post) {
  78. warning(0, "WSP UNIT: Unsupported PDU type %d", pdu->type);
  79. goto error;
  80. }
  81.         
  82. event = wap_event_create(S_Unit_MethodInvoke_Ind);
  83. event->u.S_Unit_MethodInvoke_Ind.addr_tuple = wap_addr_tuple_duplicate(
  84.                 datagram->u.T_DUnitdata_Ind.addr_tuple);
  85. event->u.S_Unit_MethodInvoke_Ind.transaction_id = tid_byte;
  86.         
  87. switch (pdu->type) {
  88. case Get:
  89. debug("wap.wsp", 0, "Connectionless Get request received.");
  90. method = GET_METHODS + pdu->u.Get.subtype;
  91. event->u.S_Unit_MethodInvoke_Ind.request_uri = 
  92. octstr_duplicate(pdu->u.Get.uri);
  93. event->u.S_Unit_MethodInvoke_Ind.request_headers = 
  94. wsp_headers_unpack(pdu->u.Get.headers, 0);
  95. event->u.S_Unit_MethodInvoke_Ind.request_body = NULL;
  96. break;
  97. case Post:
  98. debug("wap.wsp", 0, "Connectionless Post request received.");
  99.                 method = POST_METHODS + pdu->u.Post.subtype;
  100. event->u.S_Unit_MethodInvoke_Ind.request_uri = 
  101. octstr_duplicate(pdu->u.Post.uri);
  102. event->u.S_Unit_MethodInvoke_Ind.request_headers = 
  103. wsp_headers_unpack(pdu->u.Post.headers, 1);
  104. event->u.S_Unit_MethodInvoke_Ind.request_body = 
  105. octstr_duplicate(pdu->u.Post.data);
  106. break;
  107. default:
  108. warning(0, "WSP UNIT: Unsupported PDU type %d", pdu->type);
  109. goto error;
  110. }
  111. method_name = wsp_method_to_string(method);
  112. if (method_name == NULL)
  113. method_name = octstr_format("UNKNOWN%02X", method);
  114. event->u.S_Unit_MethodInvoke_Ind.method = method_name;
  115. octstr_destroy(os);
  116. wsp_pdu_destroy(pdu);
  117. return event;
  118. error:
  119. octstr_destroy(os);
  120. wsp_pdu_destroy(pdu);
  121. wap_event_destroy(event);
  122. return NULL;
  123. }
  124. /***********************************************************************
  125.  * Local functions
  126.  */
  127. static void main_thread(void *arg) {
  128. WAPEvent *e;
  129. WAPEvent *newevent;
  130. while (run_status == running && (e = list_consume(queue)) != NULL) {
  131. wap_event_assert(e);
  132. switch (e->type) {
  133. case T_DUnitdata_Ind:
  134. newevent = unpack_datagram(e);
  135. dispatch_to_appl(newevent);
  136. break;
  137. case S_Unit_MethodResult_Req:
  138. newevent = pack_into_result_datagram(e);
  139. if (newevent != NULL)
  140. dispatch_to_wdp(newevent);
  141. break;
  142.                 case S_Unit_Push_Req:
  143.         newevent = pack_into_push_datagram(e);
  144.                         if (newevent != NULL) 
  145. dispatch_to_wdp(newevent);
  146.         break;
  147. default:
  148. warning(0, "WSP UNIT: Unknown event type %d", e->type);
  149. break;
  150. }
  151.                 wap_event_destroy(e);
  152. }
  153. }
  154. /*
  155.  * We do not set TUnitData.ind's SMS-specific fields here, because we do not
  156.  * support sending results to the phone over SMS.
  157.  */
  158. static WAPEvent *pack_into_result_datagram(WAPEvent *event) {
  159. WAPEvent *datagram;
  160. struct S_Unit_MethodResult_Req *p;
  161. WSP_PDU *pdu;
  162. Octstr *ospdu;
  163. unsigned char tid;
  164. gw_assert(event->type == S_Unit_MethodResult_Req);
  165. p = &event->u.S_Unit_MethodResult_Req;
  166. pdu = wsp_pdu_create(Reply);
  167. pdu->u.Reply.status = wsp_convert_http_status_to_wsp_status(p->status);
  168. pdu->u.Reply.headers = wsp_headers_pack(p->response_headers, 1);
  169. pdu->u.Reply.data = octstr_duplicate(p->response_body);
  170. ospdu = wsp_pdu_pack(pdu);
  171. wsp_pdu_destroy(pdu);
  172. if (ospdu == NULL)
  173. return NULL;
  174. tid = p->transaction_id;
  175. octstr_insert_data(ospdu, 0, &tid, 1);
  176. datagram = wap_event_create(T_DUnitdata_Req);
  177. datagram->u.T_DUnitdata_Req.addr_tuple =
  178. wap_addr_tuple_duplicate(p->addr_tuple);
  179. datagram->u.T_DUnitdata_Req.user_data = ospdu;
  180. return datagram;
  181. }
  182. /*
  183.  * According to WSP table 12, p. 63, push id and transaction id are stored 
  184.  * into same field. T-UnitData.ind is different for IP and SMS bearer.
  185.  */
  186. static WAPEvent *pack_into_push_datagram(WAPEvent *event) {
  187.         WAPEvent *datagram;
  188.         WSP_PDU *pdu;
  189.         Octstr *ospdu;
  190. unsigned char push_id;
  191.         gw_assert(event->type == S_Unit_Push_Req);
  192.         debug("wap.wsp.unit", 0, "WSP_UNIT: Connectionless push accepted");
  193.         pdu = wsp_pdu_create(Push);
  194. pdu->u.Push.headers = wsp_headers_pack(
  195.             event->u.S_Unit_Push_Req.push_headers, 1);
  196. pdu->u.Push.data = octstr_duplicate(
  197.             event->u.S_Unit_Push_Req.push_body);
  198.         ospdu = wsp_pdu_pack(pdu);
  199. wsp_pdu_destroy(pdu);
  200. if (ospdu == NULL)
  201.     return NULL;
  202.         push_id = event->u.S_Unit_Push_Req.push_id;
  203. octstr_insert_data(ospdu, 0, &push_id, 1);
  204.         datagram = wap_event_create(T_DUnitdata_Req);
  205.         datagram->u.T_DUnitdata_Req.addr_tuple =
  206.     wap_addr_tuple_duplicate(event->u.S_Unit_Push_Req.addr_tuple);
  207.         datagram->u.T_DUnitdata_Req.address_type = 
  208.     event->u.S_Unit_Push_Req.address_type;
  209. datagram->u.T_DUnitdata_Req.user_data = ospdu;
  210.         debug("wap.wsp.unit", 0, "WSP_UNIT: delivering to wdp");
  211.         
  212.         return datagram;
  213. }