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

手机WAP编程

开发平台:

WINDOWS

  1.  /*
  2.  * wtp_resp.c - WTP responder implementation
  3.  *
  4.  * Aarno Syv鋘en
  5.  * Lars Wirzenius
  6.  */
  7. #include "gwlib/gwlib.h"
  8. #include "wtp_resp.h"
  9. #include "wtp_pack.h"
  10. #include "wtp_tid.h"
  11. #include "wtp.h"
  12. #include "timers.h"
  13. #include "wap.h"
  14. /***********************************************************************
  15.  * Internal data structures.
  16.  *
  17.  * List of responder WTP machines.
  18.  */
  19. static List *resp_machines = NULL;
  20. /*
  21.  * Counter for responder WTP machine id numbers, to make sure they are unique.
  22.  */
  23. static Counter *resp_machine_id_counter = NULL;
  24. /*
  25.  * Give the status of wtp responder:
  26.  *
  27.  * limbo
  28.  * not running at all
  29.  * running
  30.  * operating normally
  31.  * terminating
  32.  * waiting for operations to terminate, returning to limbo
  33.  */
  34. static enum { limbo, running, terminating } resp_run_status = limbo;
  35. wap_dispatch_func_t *dispatch_to_wdp;
  36. wap_dispatch_func_t *dispatch_to_wsp;
  37. wap_dispatch_func_t *dispatch_to_push;
  38. /*
  39.  * Queue of events to be handled by WTP responder.
  40.  */
  41. static List *resp_queue = NULL;
  42. /*
  43.  * Indicator for forced WTP-SAR client kludge
  44.  */
  45. extern int wtp_forced_sar;
  46. /*****************************************************************************
  47.  *
  48.  * Prototypes of internal functions:
  49.  *
  50.  * Create and destroy an uniniatilized wtp responder state machine.
  51.  */
  52. static WTPRespMachine *resp_machine_create(WAPAddrTuple *tuple, long tid, 
  53.                                            long tcl);
  54. static void resp_machine_destroy(void *sm);
  55. /*
  56.  * Checks whether wtp responser machines data structure includes a specific 
  57.  * machine.
  58.  * The machine in question is identified with with source and destination
  59.  * address and port and tid. If the machine does not exist and the event is 
  60.  * RcvInvoke, a new machine is created and added in the machines data 
  61.  * structure. 
  62.  * First test incoming events (WTP 10.2) (Exception is tests nro 4 and 5: if 
  63.  * we have a memory error, we panic. Nro 4 is already checked)  If event was 
  64.  * validated and If the event was RcvAck or RcvAbort, the event is ignored. 
  65.  * If the event is RcvErrorPDU, new machine is created.
  66.  */
  67. static WTPRespMachine *resp_machine_find_or_create(WAPEvent *event);
  68. /*
  69.  * Feed an event to a WTP responder state machine. Handle all errors by 
  70.  * itself, do not report them to the caller. WSP indication or confirmation 
  71.  * is handled by an included state table.
  72.  */
  73. static void resp_event_handle(WTPRespMachine *machine, WAPEvent *event);
  74. /*
  75.  * Print a wtp responder machine state as a string.
  76.  */
  77. static unsigned char *name_resp_state(int name);
  78. /*
  79.  * Find the wtp responder machine from the global list of wtp responder 
  80.  * structures that corresponds to the five-tuple of source and destination 
  81.  * addresses and ports and the transaction identifier. Return a pointer to 
  82.  * the machine, or NULL if not found.
  83.  */
  84. static WTPRespMachine *resp_machine_find(WAPAddrTuple *tuple, long tid, 
  85.                                          long mid);
  86. static void main_thread(void *);
  87. /*
  88.  * Start acknowledgement interval timer
  89.  */
  90. static void start_timer_A(WTPRespMachine *machine);
  91. /*
  92.  * Start retry interval timer
  93.  */
  94. static void start_timer_R(WTPRespMachine *machine);
  95. /*
  96.  * Start timeout interval timer.
  97.  */
  98. static void start_timer_W(WTPRespMachine *machine);
  99. static WAPEvent *create_tr_invoke_ind(WTPRespMachine *sm, Octstr *user_data);
  100. static WAPEvent *create_tr_abort_ind(WTPRespMachine *sm, long abort_reason);
  101. static WAPEvent *create_tr_result_cnf(WTPRespMachine *sm);
  102. static int erroneous_field_in(WAPEvent *event);
  103. static void handle_no_sar(WAPEvent *event);
  104. static void handle_wrong_version(WAPEvent *event);
  105. /*
  106.  * Create a datagram with an Abort PDU and send it to the WDP layer.
  107.  */
  108. static void send_abort(WTPRespMachine *machine, long type, long reason);
  109. /*
  110.  * Create a datagram with an Ack PDU and send it to the WDP layer.
  111.  */
  112. static void send_ack(WTPRespMachine *machine, long ack_type, int rid_flag);
  113. /******************************************************************************
  114.  *
  115.  * EXTERNAL FUNCTIONS:
  116.  *
  117.  */
  118. void wtp_resp_init(wap_dispatch_func_t *datagram_dispatch,
  119.                    wap_dispatch_func_t *session_dispatch,
  120.                    wap_dispatch_func_t *push_dispatch) 
  121. {
  122.     resp_machines = list_create();
  123.     resp_machine_id_counter = counter_create();
  124.     resp_queue = list_create();
  125.     list_add_producer(resp_queue);
  126.     dispatch_to_wdp = datagram_dispatch;
  127.     dispatch_to_wsp = session_dispatch;
  128.     dispatch_to_push = push_dispatch;
  129.     timers_init();
  130.     wtp_tid_cache_init();
  131.     gw_assert(resp_run_status == limbo);
  132.     resp_run_status = running;
  133.     gwthread_create(main_thread, NULL);
  134. }
  135. void wtp_resp_shutdown(void) 
  136. {
  137.     gw_assert(resp_run_status == running);
  138.     resp_run_status = terminating;
  139.     list_remove_producer(resp_queue);
  140.     gwthread_join_every(main_thread);
  141.     debug("wap.wtp", 0, "wtp_resp_shutdown: %ld resp_machines left",
  142.         list_len(resp_machines));
  143.     list_destroy(resp_machines, resp_machine_destroy);
  144.     list_destroy(resp_queue, wap_event_destroy_item);
  145.     counter_destroy(resp_machine_id_counter);
  146.     wtp_tid_cache_shutdown();
  147.     timers_shutdown();
  148. }
  149. void wtp_resp_dispatch_event(WAPEvent *event) 
  150. {
  151.     list_produce(resp_queue, event);
  152. }
  153. /*****************************************************************************
  154.  *
  155.  * INTERNAL FUNCTIONS:
  156.  *
  157.  */
  158. static void main_thread(void *arg) 
  159. {
  160.     WTPRespMachine *sm;
  161.     WAPEvent *e;
  162.     while (resp_run_status == running && 
  163.            (e = list_consume(resp_queue)) != NULL) {
  164. sm = resp_machine_find_or_create(e);
  165. if (sm == NULL)
  166.     wap_event_destroy(e);
  167. else
  168.     resp_event_handle(sm, e);
  169. }
  170. }
  171. /*
  172.  * Give the name of a responder state in a readable form. 
  173.  */
  174. static unsigned char *name_resp_state(int s)
  175. {
  176.        switch (s) {
  177.        #define STATE_NAME(state) case state: return #state;
  178.        #define ROW(state, event, condition, action, new_state)
  179.        #include "wtp_resp_states.def"
  180.        default:
  181.            return "unknown state";
  182.        }
  183. }
  184. /*
  185.  * Feed an event to a WTP responder state machine. Handle all errors yourself,
  186.  * do not report them to the caller. Note: Do not put {}s of the else block 
  187.  * inside the macro definition. 
  188.  */
  189. static void resp_event_handle(WTPRespMachine *resp_machine, WAPEvent *event)
  190. {
  191.     WAPEvent *wsp_event = NULL;
  192.     debug("wap.wtp", 0, "WTP: resp_machine %ld, state %s, event %s.", 
  193.   resp_machine->mid, 
  194.   name_resp_state(resp_machine->state), 
  195.   wap_event_name(event->type));
  196.     #define STATE_NAME(state)
  197.     #define ROW(wtp_state, event_type, condition, action, next_state) 
  198.  if (resp_machine->state == wtp_state && 
  199.      event->type == event_type && 
  200.      (condition)) { 
  201.      action 
  202.      resp_machine->state = next_state; 
  203.      debug("wap.wtp", 0, "WTP %ld: New state %s", resp_machine->mid,                      #next_state); 
  204.  } else 
  205.     #include "wtp_resp_states.def"
  206.  {
  207.      error(0, "WTP: handle_event: unhandled event!");
  208.      debug("wap.wtp", 0, "WTP: handle_event: Unhandled event was:");
  209.      wap_event_dump(event);
  210.              wap_event_destroy(event);
  211.              return;
  212.  }
  213.     if (event != NULL) {
  214. wap_event_destroy(event);  
  215.     }
  216.     if (resp_machine->state == LISTEN)
  217.       resp_machine_destroy(resp_machine);
  218. }
  219. static void handle_wrong_version(WAPEvent *event)
  220. {       
  221.     WAPEvent *ab;
  222.     if (event->type == RcvInvoke) {
  223.         ab = wtp_pack_abort(PROVIDER, WTPVERSIONZERO, event->u.RcvInvoke.tid, 
  224.                             event->u.RcvInvoke.addr_tuple);
  225.         dispatch_to_wdp(ab);
  226.     }
  227. }
  228. /*
  229.  * This function will be removed when we have SAR
  230.  */
  231. static void handle_no_sar(WAPEvent *event)
  232. {
  233.     WAPEvent *ab;
  234.     if (event->type == RcvInvoke) {
  235.         ab = wtp_pack_abort(PROVIDER, NOTIMPLEMENTEDSAR, 
  236.                             event->u.RcvInvoke.tid,
  237.                             event->u.RcvInvoke.addr_tuple);
  238.         dispatch_to_wdp(ab);
  239.     }
  240. }
  241. /*
  242.  * Check for features 7 and 9 in WTP 10.2.
  243.  */
  244. static int erroneous_field_in(WAPEvent *event)
  245. {
  246.     /*
  247.      * If clients request WTP-SAR should we force to continue
  248.      * or act as be should do by telling the client to call back.
  249.      */
  250.     if (wtp_forced_sar) 
  251.         return 0;
  252.     return event->type == RcvInvoke && (event->u.RcvInvoke.version != 0 || 
  253.                !event->u.RcvInvoke.ttr || !event->u.RcvInvoke.gtr);
  254. }
  255. /*
  256.  * React features 7 and 9 in WTP 10.2, by aborting with an appropiate error 
  257.  * message.
  258.  */
  259. static void handle_erroneous_field_in(WAPEvent *event)
  260. {
  261.     if (event->type == RcvInvoke){
  262.         if (event->u.RcvInvoke.version != 0){
  263.    debug("wap.wtp_resp", 0, "WTP_RESP: wrong version, aborting"
  264.                  "transaction");
  265.        handle_wrong_version(event);
  266.         }
  267.         if (!event->u.RcvInvoke.ttr || !event->u.RcvInvoke.gtr){
  268.             debug("wap.wtp_resp", 0, "WTP_RESP: no sar implemented," 
  269.                   "aborting transaction");
  270.             handle_no_sar(event);
  271.         }
  272.     }
  273. }
  274. /*
  275.  * Checks whether wtp machines data structure includes a specific machine.
  276.  * The machine in question is identified with with source and destination
  277.  * address and port and tid.  First test incoming events (WTP 10.2)
  278.  * (Exception is tests nro 4 and 5: if we have a memory error, we panic. Nro 5 
  279.  * is already checked)  If event was validated and if the machine does not 
  280.  * exist and the event is RcvInvoke, a new machine is created and added in 
  281.  * the machines data structure. If the event was RcvAck or RcvAbort, the 
  282.  * event is ignored (test nro 3). If the event is RcvErrorPDU (test nro 4) 
  283.  * new machine is created for handling this event. If the event is one of WSP 
  284.  * primitives, we have an error.
  285.  */
  286. static WTPRespMachine *resp_machine_find_or_create(WAPEvent *event)
  287. {
  288.     WTPRespMachine *resp_machine = NULL;
  289.     long tid, mid;
  290.     WAPAddrTuple *tuple;
  291.     tid = -1;
  292.     tuple = NULL;
  293.     mid = -1;
  294.     switch (event->type) {
  295.         case RcvInvoke:
  296.             /* check if erroneous fields are given */
  297.             if (erroneous_field_in(event)) {
  298.                 handle_erroneous_field_in(event);
  299.                 return NULL;
  300.             } else {
  301.                 tid = event->u.RcvInvoke.tid;
  302.                 tuple = event->u.RcvInvoke.addr_tuple;
  303.             }
  304.             break;
  305.        case RcvAck:
  306.             tid = event->u.RcvAck.tid;
  307.             tuple = event->u.RcvAck.addr_tuple;
  308.             break;
  309.         case RcvAbort:
  310.             tid = event->u.RcvAbort.tid;
  311.             tuple = event->u.RcvAbort.addr_tuple;
  312.             break;
  313.         case RcvErrorPDU:
  314.             tid = event->u.RcvErrorPDU.tid;
  315.             tuple = event->u.RcvErrorPDU.addr_tuple;
  316.             break;
  317.         case TR_Invoke_Res:
  318.             mid = event->u.TR_Invoke_Res.handle;
  319.             break;
  320.         case TR_Result_Req:
  321.             mid = event->u.TR_Result_Req.handle;
  322.             break;
  323.         case TR_Abort_Req:
  324.             mid = event->u.TR_Abort_Req.handle;
  325.             break;
  326.         case TimerTO_A:
  327.             mid = event->u.TimerTO_A.handle;
  328.             break;
  329.         case TimerTO_R:
  330.             mid = event->u.TimerTO_R.handle;
  331.             break;
  332.         case TimerTO_W:
  333.             mid = event->u.TimerTO_W.handle;
  334.             break;
  335.         default:
  336.             debug("wap.wtp", 0, "WTP: resp_machine_find_or_create:"
  337.                   "unhandled event"); 
  338.             wap_event_dump(event);
  339.             return NULL;
  340.     }
  341.     gw_assert(tuple != NULL || mid != -1);
  342.     resp_machine = resp_machine_find(tuple, tid, mid);
  343.            
  344.     if (resp_machine == NULL){
  345.         switch (event->type) {
  346.         /*
  347.          * When PDU with an illegal header is received, its tcl-field is 
  348.          * irrelevant and possibly meaningless). In this case we must create 
  349.          * a new machine, if there is any. There is a machine for all events 
  350.          * handled stateful manner.
  351.          */
  352.         case RcvErrorPDU:
  353.             debug("wap.wtp_resp", 0, "an erronous pdu received");
  354.             wap_event_dump(event);
  355.             resp_machine = resp_machine_create(tuple, tid, 
  356.                                                event->u.RcvInvoke.tcl); 
  357.             break;
  358.            
  359.         case RcvInvoke:
  360.        resp_machine = resp_machine_create(tuple, tid, 
  361.                                               event->u.RcvInvoke.tcl);
  362.             break;
  363.         /*
  364.          * This and the following branch implement test nro 3 in WTP 10.2.
  365.          */
  366.         case RcvAck: 
  367.             info(0, "WTP_RESP: resp_machine_find_or_create:"
  368.                  " ack received, yet having no machine");
  369.             break;
  370.         case RcvAbort: 
  371.             info(0, "WTP_RESP: resp_machine_find_or_create:"
  372.                  " abort received, yet having no machine");
  373.             break;
  374.         case TR_Invoke_Res: 
  375.         case TR_Result_Req: 
  376.         case TR_Abort_Req:
  377.             error(0, "WTP_RESP: resp_machine_find_or_create: WSP primitive to"
  378.                   " a wrong WTP machine");
  379.             break;
  380.         case TimerTO_A: 
  381.         case TimerTO_R: 
  382.         case TimerTO_W:
  383.             error(0, "WTP_RESP: resp_machine_find_or_create: timer event"
  384.                   " without a corresponding machine");
  385.             break;
  386.                  
  387.         default:
  388.             error(0, "WTP_RESP: resp_machine_find_or_create: unhandled event");
  389.             wap_event_dump(event);
  390.             break;
  391.         }
  392.    } /* if machine == NULL */   
  393.    return resp_machine;
  394. }
  395. static int is_wanted_resp_machine(void *a, void *b) 
  396. {
  397.     machine_pattern *pat;
  398.     WTPRespMachine *m;
  399.     m = a;
  400.     pat = b;
  401.     if (m->mid == pat->mid)
  402. return 1;
  403.     if (pat->mid != -1)
  404. return 0;
  405.     return m->tid == pat->tid && 
  406.            wap_addr_tuple_same(m->addr_tuple, pat->tuple);
  407. }
  408. static WTPRespMachine *resp_machine_find(WAPAddrTuple *tuple, long tid, 
  409.                                          long mid) 
  410. {
  411.     machine_pattern pat;
  412.     WTPRespMachine *m;
  413.     pat.tuple = tuple;
  414.     pat.tid = tid;
  415.     pat.mid = mid;
  416.     m = list_search(resp_machines, &pat, is_wanted_resp_machine);
  417.     return m;
  418. }
  419. static WTPRespMachine *resp_machine_create(WAPAddrTuple *tuple, long tid, 
  420.                                            long tcl) 
  421. {
  422.     WTPRespMachine *resp_machine;
  423.     resp_machine = gw_malloc(sizeof(WTPRespMachine)); 
  424.         
  425.     #define ENUM(name) resp_machine->name = LISTEN;
  426.     #define EVENT(name) resp_machine->name = NULL;
  427.     #define INTEGER(name) resp_machine->name = 0; 
  428.     #define TIMER(name) resp_machine->name = gwtimer_create(resp_queue); 
  429.     #define ADDRTUPLE(name) resp_machine->name = NULL; 
  430.     #define MACHINE(field) field
  431.     #include "wtp_resp_machine.def"
  432.     list_append(resp_machines, resp_machine);
  433.     resp_machine->mid = counter_increase(resp_machine_id_counter);
  434.     resp_machine->addr_tuple = wap_addr_tuple_duplicate(tuple);
  435.     resp_machine->tid = tid;
  436.     resp_machine->tcl = tcl;
  437.     debug("wap.wtp", 0, "WTP: Created WTPRespMachine %p (%ld)", 
  438.   (void *) resp_machine, resp_machine->mid);
  439.     return resp_machine;
  440. /*
  441.  * Destroys a WTPRespMachine. Assumes it is safe to do so. Assumes it has 
  442.  * already been deleted from the machines list.
  443.  */
  444. static void resp_machine_destroy(void * p)
  445. {
  446.     WTPRespMachine *resp_machine;
  447.     resp_machine = p;
  448.     debug("wap.wtp", 0, "WTP: Destroying WTPRespMachine %p (%ld)", 
  449.   (void *) resp_machine, resp_machine->mid);
  450.     list_delete_equal(resp_machines, resp_machine);
  451.         
  452.     #define ENUM(name) resp_machine->name = LISTEN;
  453.     #define EVENT(name) wap_event_destroy(resp_machine->name);
  454.     #define INTEGER(name) resp_machine->name = 0; 
  455.     #define TIMER(name) gwtimer_destroy(resp_machine->name); 
  456.     #define ADDRTUPLE(name) wap_addr_tuple_destroy(resp_machine->name); 
  457.     #define MACHINE(field) field
  458.     #include "wtp_resp_machine.def"
  459.     gw_free(resp_machine);
  460. }
  461. /*
  462.  * Create a TR-Invoke.ind event.
  463.  */
  464. static WAPEvent *create_tr_invoke_ind(WTPRespMachine *sm, Octstr *user_data) 
  465. {
  466.     WAPEvent *event;
  467.     event = wap_event_create(TR_Invoke_Ind);
  468.     event->u.TR_Invoke_Ind.ack_type = sm->u_ack;
  469.     event->u.TR_Invoke_Ind.user_data = octstr_duplicate(user_data);
  470.     event->u.TR_Invoke_Ind.tcl = sm->tcl;
  471.     event->u.TR_Invoke_Ind.addr_tuple = 
  472. wap_addr_tuple_duplicate(sm->addr_tuple);
  473.     event->u.TR_Invoke_Ind.handle = sm->mid;
  474.     return event;
  475. }
  476. /*
  477.  * Create a TR-Result.cnf event.
  478.  */
  479. static WAPEvent *create_tr_result_cnf(WTPRespMachine *sm) 
  480. {
  481.     WAPEvent *event;
  482.     event = wap_event_create(TR_Result_Cnf);
  483.     event->u.TR_Result_Cnf.addr_tuple = 
  484. wap_addr_tuple_duplicate(sm->addr_tuple);
  485.     event->u.TR_Result_Cnf.handle = sm->mid;
  486.     return event;
  487. }
  488. /*
  489.  * Creates TR-Abort.ind event from a responder state machine. In addition, set
  490.  * the responder indication flag.
  491.  */
  492. static WAPEvent *create_tr_abort_ind(WTPRespMachine *sm, long abort_reason) {
  493.     WAPEvent *event;
  494.     event = wap_event_create(TR_Abort_Ind);
  495.     event->u.TR_Abort_Ind.abort_code = abort_reason;
  496.     event->u.TR_Abort_Ind.addr_tuple = 
  497. wap_addr_tuple_duplicate(sm->addr_tuple);
  498.     event->u.TR_Abort_Ind.handle = sm->mid;
  499.     event->u.TR_Abort_Ind.ir_flag = RESPONDER_INDICATION;
  500.     return event;
  501. }
  502. /*
  503.  * Start acknowledgement interval timer
  504.  */
  505. static void start_timer_A(WTPRespMachine *machine) 
  506. {
  507.     WAPEvent *timer_event;
  508.     timer_event = wap_event_create(TimerTO_A);
  509.     timer_event->u.TimerTO_A.handle = machine->mid;
  510.     gwtimer_start(machine->timer, L_A_WITH_USER_ACK, timer_event);
  511. }
  512. /*
  513.  * Start retry interval timer
  514.  */
  515. static void start_timer_R(WTPRespMachine *machine) 
  516. {
  517.     WAPEvent *timer_event;
  518.     timer_event = wap_event_create(TimerTO_R);
  519.     timer_event->u.TimerTO_R.handle = machine->mid;
  520.     gwtimer_start(machine->timer, L_R_WITH_USER_ACK, timer_event);
  521. }
  522. /*
  523.  * Start timeout interval timer
  524.  */
  525. static void start_timer_W(WTPRespMachine *machine)
  526. {
  527.     WAPEvent *timer_event;
  528.     timer_event = wap_event_create(TimerTO_W);
  529.     timer_event->u.TimerTO_W.handle = machine->mid;
  530.     gwtimer_start(machine->timer, W_WITH_USER_ACK, timer_event);
  531. }
  532. static void send_abort(WTPRespMachine *machine, long type, long reason)
  533. {
  534.     WAPEvent *e;
  535.     e = wtp_pack_abort(type, reason, machine->tid, machine->addr_tuple);
  536.     dispatch_to_wdp(e);
  537. }
  538. static void send_ack(WTPRespMachine *machine, long ack_type, int rid_flag)
  539. {
  540.     WAPEvent *e;
  541.     e = wtp_pack_ack(ack_type, rid_flag, machine->tid, machine->addr_tuple);
  542.     dispatch_to_wdp(e);
  543. }