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

手机WAP编程

开发平台:

WINDOWS

  1. /*
  2.  * wtp.c - WTP common functions implementation
  3.  *
  4.  * Aarno Syv鋘en
  5.  * Lars Wirzenius
  6.  */
  7. #include "wtp.h" 
  8. #include "wap_events.h"
  9. #include "wtp_pdu.h"
  10. /*****************************************************************************
  11.  *
  12.  * Prototypes of internal functions:
  13.  *
  14.  * Parse a datagram event (T-DUnitdata.ind) to create a corresponding
  15.  * WTPEvents list object. Also check that the datagram is syntactically
  16.  * valid. Return a pointer to the event structure that has been created.
  17.  * This will be a RcvError packet if there was a problem unpacking the
  18.  * datagram.
  19.  */
  20. static WAPEvent *unpack_wdp_datagram_real(WAPEvent *datagram);
  21. static int deduce_tid(Octstr *user_data);
  22. static int concatenated_message(Octstr *user_data);
  23. static int truncated_datagram(WAPEvent *event);
  24. static WAPEvent *unpack_invoke(WTP_PDU *pdu, WAPAddrTuple *addr_tuple);
  25. static WAPEvent *unpack_result(WTP_PDU *pdu, WAPAddrTuple *addr_tuple);
  26. static WAPEvent *unpack_ack(WTP_PDU *pdu, WAPAddrTuple *addr_tuple);
  27. static WAPEvent *unpack_abort(WTP_PDU *pdu, WAPAddrTuple *addr_tuple);
  28. static WAPEvent *pack_error(WAPEvent *datagram);
  29. /******************************************************************************
  30.  *
  31.  * EXTERNAL FUNCTIONS:
  32.  *
  33.  * Handles a possible concatenated message. Creates a list of wap events.
  34.  */
  35. List *wtp_unpack_wdp_datagram(WAPEvent *datagram)
  36. {
  37.      List *events = NULL;
  38.      WAPEvent *event = NULL;
  39.      WAPEvent *subdgram = NULL;
  40.      Octstr *data = NULL;
  41.      long pdu_len;
  42.      gw_assert(datagram->type == T_DUnitdata_Ind);
  43.      events = list_create();
  44.         
  45.      if (concatenated_message(datagram->u.T_DUnitdata_Ind.user_data)) {
  46.          data = octstr_duplicate(datagram->u.T_DUnitdata_Ind.user_data);
  47.  octstr_delete(data, 0, 1);
  48.          while (octstr_len(data) != 0) {
  49.      if (octstr_get_bits(data, 0, 1) == 0) {
  50.          pdu_len = octstr_get_char(data, 0);
  51.                  octstr_delete(data, 0, 1);
  52.              } else {
  53.     pdu_len = octstr_get_bits(data, 1, 15);
  54.                     octstr_delete(data, 0, 2);
  55.              }
  56.       
  57.      subdgram = wap_event_duplicate(datagram);
  58.      octstr_destroy(subdgram->u.T_DUnitdata_Ind.user_data);
  59.              subdgram->u.T_DUnitdata_Ind.user_data =
  60.           octstr_copy(data, 0, pdu_len);
  61.              wap_event_assert(subdgram);
  62.              event = unpack_wdp_datagram_real(subdgram);
  63.              wap_event_assert(event);
  64.              list_append(events, event);
  65.              octstr_delete(data, 0, pdu_len);
  66.              wap_event_destroy(subdgram);
  67.          }
  68.      octstr_destroy(data);
  69.      } else {
  70.           event = unpack_wdp_datagram_real(datagram); 
  71.           wap_event_assert(event);
  72.           list_append(events, event);
  73.      } 
  74.      return events;
  75. }
  76. /*
  77.  * Responder set the first bit of the tid field. If we get a packet from the 
  78.  * responder, we are the initiator and vice versa.
  79.  *
  80.  * Return 1, when the event is for responder, 0 when it is for initiator and 
  81.  * -1 when error.
  82.  */
  83. int wtp_event_is_for_responder(WAPEvent *event)
  84. {
  85.      switch(event->type){
  86.           
  87.      case RcvInvoke:
  88.          return event->u.RcvInvoke.tid < INITIATOR_TID_LIMIT;
  89.      case RcvResult:
  90.          return event->u.RcvResult.tid < INITIATOR_TID_LIMIT;
  91.      case RcvAck:
  92.         return event->u.RcvAck.tid < INITIATOR_TID_LIMIT;
  93.      case RcvAbort:
  94.         return event->u.RcvAbort.tid < INITIATOR_TID_LIMIT;
  95.      case RcvErrorPDU:
  96.         return event->u.RcvErrorPDU.tid < INITIATOR_TID_LIMIT;
  97.      default:
  98.         error(1, "Received an erroneous PDU corresponding an event");
  99.         wap_event_dump(event);
  100.         return -1;
  101.      }
  102. }
  103. /*****************************************************************************
  104.  *
  105.  * INTERNAL FUNCTIONS:
  106.  *
  107.  * If pdu was truncated, tid cannot be trusted. We ignore this message.
  108.  */
  109. static int truncated_datagram(WAPEvent *dgram)
  110. {
  111.     gw_assert(dgram->type == T_DUnitdata_Ind);
  112.     if (octstr_len(dgram->u.T_DUnitdata_Ind.user_data) < 3) {
  113.         debug("wap.wtp", 0, "A too short PDU received");
  114.         wap_event_dump(dgram);
  115.         return 1;
  116.     } else
  117.         return 0;
  118. }
  119. static WAPEvent *unpack_invoke(WTP_PDU *pdu, WAPAddrTuple *addr_tuple)
  120. {
  121.     WAPEvent *event;
  122.     event = wap_event_create(RcvInvoke);
  123.     event->u.RcvInvoke.user_data = 
  124.         octstr_duplicate(pdu->u.Invoke.user_data);
  125.     event->u.RcvInvoke.tcl = pdu->u.Invoke.class;
  126.     event->u.RcvInvoke.tid = pdu->u.Invoke.tid;
  127.     event->u.RcvInvoke.tid_new = pdu->u.Invoke.tidnew;
  128.     event->u.RcvInvoke.rid = pdu->u.Invoke.rid;
  129.     event->u.RcvInvoke.up_flag = pdu->u.Invoke.uack;
  130.     event->u.RcvInvoke.no_cache_supported = 0;
  131.     event->u.RcvInvoke.version = pdu->u.Invoke.version;
  132.     event->u.RcvInvoke.gtr = pdu->u.Invoke.gtr;
  133.     event->u.RcvInvoke.ttr = pdu->u.Invoke.ttr;
  134.     event->u.RcvInvoke.addr_tuple = wap_addr_tuple_duplicate(addr_tuple);
  135.     return event;
  136. }
  137. static WAPEvent *unpack_result(WTP_PDU *pdu, WAPAddrTuple *addr_tuple)
  138. {
  139.     WAPEvent *event;
  140.     event = wap_event_create(RcvResult);
  141.     event->u.RcvResult.user_data = 
  142.         octstr_duplicate(pdu->u.Result.user_data);
  143.     event->u.RcvResult.tid = pdu->u.Result.tid;
  144.     event->u.RcvResult.rid = pdu->u.Result.rid;
  145.     event->u.RcvResult.gtr = pdu->u.Result.gtr;
  146.     event->u.RcvResult.ttr = pdu->u.Result.ttr;
  147.     event->u.RcvResult.addr_tuple = wap_addr_tuple_duplicate(addr_tuple);
  148.     return event;
  149. }
  150. static WAPEvent *unpack_ack(WTP_PDU *pdu, WAPAddrTuple *addr_tuple)
  151. {
  152.     WAPEvent *event;
  153.     event = wap_event_create(RcvAck);
  154.     event->u.RcvAck.tid = pdu->u.Ack.tid;
  155.     event->u.RcvAck.tid_ok = pdu->u.Ack.tidverify;
  156.     event->u.RcvAck.rid = pdu->u.Ack.rid;
  157.     event->u.RcvAck.addr_tuple = wap_addr_tuple_duplicate(addr_tuple);
  158.     return event;
  159. }
  160. static WAPEvent *unpack_abort(WTP_PDU *pdu, WAPAddrTuple *addr_tuple)
  161. {
  162.      WAPEvent *event;
  163.      event = wap_event_create(RcvAbort);
  164.      event->u.RcvAbort.tid = pdu->u.Abort.tid;
  165.      event->u.RcvAbort.abort_type = pdu->u.Abort.abort_type;
  166.      event->u.RcvAbort.abort_reason = pdu->u.Abort.abort_reason;
  167.      event->u.RcvAbort.addr_tuple = wap_addr_tuple_duplicate(addr_tuple);
  168.      return event;
  169. }
  170. static WAPEvent *pack_error(WAPEvent *datagram)
  171. {
  172.     WAPEvent *event;
  173.     gw_assert(datagram->type == T_DUnitdata_Ind);
  174.     event = wap_event_create(RcvErrorPDU);
  175.     event->u.RcvErrorPDU.tid = deduce_tid(datagram->u.T_DUnitdata_Ind.user_data);
  176.     event->u.RcvErrorPDU.addr_tuple = 
  177. wap_addr_tuple_duplicate(datagram->u.T_DUnitdata_Ind.addr_tuple);
  178.     return event;
  179. }
  180. /*
  181.  * Transfers data from fields of a message to fields of WTP event. User data 
  182.  * has the host byte order. Updates the log. 
  183.  *
  184.  * This function does incoming events check nro 4 (checking illegal headers
  185.  * WTP 10.2).
  186.  *
  187.  * Return event, when we have a partially correct message or the message 
  188.  * received has illegal header (WTP 10.2 nro 4); NULL, when the message was 
  189.  * truncated or unpacking function returned NULL.
  190.  */
  191. WAPEvent *unpack_wdp_datagram_real(WAPEvent *datagram)
  192. {
  193.     WTP_PDU *pdu;
  194.     WAPEvent *event;
  195.     Octstr *data;
  196.     gw_assert(datagram->type == T_DUnitdata_Ind);
  197.     data = datagram->u.T_DUnitdata_Ind.user_data;
  198.     if (truncated_datagram(datagram))
  199. return NULL;
  200.     pdu = wtp_pdu_unpack(data);
  201. /*
  202.  * Wtp_pdu_unpack returned NULL, we build a rcv error event. 
  203.  */
  204.     if (pdu == NULL) {
  205.         error(0, "pdu unpacking returned NULL");
  206.         event = pack_error(datagram);
  207.         return event;
  208.     }   
  209.     event = NULL;
  210.     switch (pdu->type) {
  211.     case Invoke:
  212.         event = unpack_invoke(pdu, datagram->u.T_DUnitdata_Ind.addr_tuple);
  213.         /* if an WTP initiator gets invoke, it would be an illegal pdu. */
  214.         if (!wtp_event_is_for_responder(event)){
  215.             debug("wap.wtp", 0, "Invoke when initiator. Message was");
  216.             wap_event_destroy(event);
  217.             event = pack_error(datagram);
  218.         }
  219.         break;
  220.     case Result:
  221.         event = unpack_result(pdu, datagram->u.T_DUnitdata_Ind.addr_tuple);
  222.         /* if an WTP responder gets result, it would be an illegal pdu. */
  223.         if (wtp_event_is_for_responder(event)){
  224.             debug("wap.wtp", 0, "Result when responder. Message was");
  225.             wap_event_destroy(event);
  226.             event = pack_error(datagram);
  227.         }
  228.         break;
  229.     case Ack:
  230.     event = unpack_ack(pdu, datagram->u.T_DUnitdata_Ind.addr_tuple);    
  231.         break;
  232. case Abort:
  233.     event = unpack_abort(pdu, datagram->u.T_DUnitdata_Ind.addr_tuple);
  234.         break;         
  235. default:
  236.     event = pack_error(datagram);
  237.     debug("wap.wtp", 0, "Unhandled PDU type. Message was");
  238.             wap_event_dump(datagram);
  239.     return event;
  240. }
  241.     wtp_pdu_destroy(pdu);
  242.     wap_event_assert(event);
  243.     return event;
  244. }
  245. /*
  246.  * Used for debugging and when wtp unpack does not return a tid. We include
  247.  * first bit; it tells does message received belong to the initiator or to the
  248.  * responder.
  249.  */
  250. static int deduce_tid(Octstr *user_data)
  251.     return octstr_get_bits(user_data, 8, 16);
  252. }
  253. static int concatenated_message(Octstr *user_data)
  254. {
  255.        return octstr_get_char(user_data, 0) == 0x00;
  256. }