Main Page | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals

wtp_resp_states.def

Go to the documentation of this file.
00001 /* ==================================================================== 
00002  * The Kannel Software License, Version 1.0 
00003  * 
00004  * Copyright (c) 2001-2008 Kannel Group  
00005  * Copyright (c) 1998-2001 WapIT Ltd.   
00006  * All rights reserved. 
00007  * 
00008  * Redistribution and use in source and binary forms, with or without 
00009  * modification, are permitted provided that the following conditions 
00010  * are met: 
00011  * 
00012  * 1. Redistributions of source code must retain the above copyright 
00013  *    notice, this list of conditions and the following disclaimer. 
00014  * 
00015  * 2. Redistributions in binary form must reproduce the above copyright 
00016  *    notice, this list of conditions and the following disclaimer in 
00017  *    the documentation and/or other materials provided with the 
00018  *    distribution. 
00019  * 
00020  * 3. The end-user documentation included with the redistribution, 
00021  *    if any, must include the following acknowledgment: 
00022  *       "This product includes software developed by the 
00023  *        Kannel Group (http://www.kannel.org/)." 
00024  *    Alternately, this acknowledgment may appear in the software itself, 
00025  *    if and wherever such third-party acknowledgments normally appear. 
00026  * 
00027  * 4. The names "Kannel" and "Kannel Group" must not be used to 
00028  *    endorse or promote products derived from this software without 
00029  *    prior written permission. For written permission, please  
00030  *    contact org@kannel.org. 
00031  * 
00032  * 5. Products derived from this software may not be called "Kannel", 
00033  *    nor may "Kannel" appear in their name, without prior written 
00034  *    permission of the Kannel Group. 
00035  * 
00036  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED 
00037  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 
00038  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
00039  * DISCLAIMED.  IN NO EVENT SHALL THE KANNEL GROUP OR ITS CONTRIBUTORS 
00040  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,  
00041  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT  
00042  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR  
00043  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,  
00044  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE  
00045  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,  
00046  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
00047  * ==================================================================== 
00048  * 
00049  * This software consists of voluntary contributions made by many 
00050  * individuals on behalf of the Kannel Group.  For more information on  
00051  * the Kannel Group, please see <http://www.kannel.org/>. 
00052  * 
00053  * Portions of this software are based upon software originally written at  
00054  * WapIT Ltd., Helsinki, Finland for the Kannel project.  
00055  */ 
00056 
00057 /*
00058  * Macro calls to generate rows of the state table. See the documentation for
00059  * guidance how to use and update these. 
00060  *
00061  * Macros have following arguments:
00062  *
00063  * STATE_NAME(name of a wtp machine state)
00064  *
00065  * ROW(the name of the current state,
00066  *     the event feeded to wtp machine,
00067  *     the condition for the action,
00068  *     {the action itself},
00069  *     the state wtp machine will transit)
00070  *
00071  * Condition 1 means that the action will be performed unconditionally, action
00072  * {} means that the event in question will be ignored (of course, the state 
00073  * of the machine can change). 
00074  *
00075  * There are many ROWS generating code for ignoring a certain event (ones hav-
00076  * ing {} as their action). In these cases the event in question is caused by a
00077  * duplicate message and the first one has already changed wtp responder mach-
00078  * ine. In this case ignoring the event is natural.
00079  *
00080  * State tables use the phrase "abort transaction" many times. In this imple-
00081  * mentation this means "clear data structures used for storing transaction 
00082  * data". This happens in function resp_event_handle, after included state 
00083  * table code.
00084  *
00085  * Commenting the state table is perhaps best done by pointing out how various 
00086  * services provided by WTP contribute rows to the state table.
00087  *
00088  * Normal transaction goes as follows (timers excluded):
00089  *        - WTP get an invoke pdu from the peer. WTP does TR-Invoke.ind (trans-
00090  *          mitting to WSP its PDU) and the state changes to INVOKE_RESP_WAIT
00091  *        - WSP does TR-Invoke.res, telling that it has handled the 
00092  *          indication. 
00093  *          The state changes to RESULT_WAIT.
00094  *        - WSP tells that it has results from the content server, or reply 
00095  *          pdu to send. It does TR-Result.req. State changes to 
00096  *          RESULT_RESP_WAIT. 
00097  *        - WTP gets acknowledgement from the peer. It generates TR_Result.cnf
00098  *          and state changes to LISTEN. The transaction is over.
00099  *
00100  * Retransmission until acknowledgement guarantees reliability of the trans-
00101  * action, if the peer stays up. It is implemented by using retransmissions 
00102  * controlled by timers and counters. There are two kind of timers, retrans-
00103  * mission and acknowledgement timers. (Actually, there is one timer 
00104  * iniatilised with two intervals. But let us keep the language simple). 
00105  * These are used in concert with corresponding counters, RCR (retransmission 
00106  * counter) and AEC (acknowledgement expiration counter). AEC counts expired 
00107  * acknowledgement intervals.
00108  *
00109  * WTP starts an acknowledgement timer when it waits a WSP acknowledgement, 
00110  * and retransmission timer when it sends something. So when the acknowledge_
00111  * ment timer expires, the action is to increment AEC, and when the retrans-
00112  * mission timer expires, the action is to resend a packet. (Note, however, 
00113  * the chapter concerning user acknowledgement.)
00114  *
00115  * WTP ignores invoke pdus having same tid as the current transaction. This 
00116  * quarantees rejection of the duplicates. Note, however, how reliability is 
00117  * achieved when WTP is doing tid verification (next chapter).
00118  *
00119  * Tid verification is done if tid validation fails (which happens when the 
00120  * message is a duplicate or when tid wrapping-up could confuse the protocol).
00121  * In this case, the state changes to TIDOK_WAIT. WSP is indicated only after 
00122  * an acknowledgement is received. After a negative answer (Abort PDU) the 
00123  * transaction is teared down. Reliablity is quaranteed by resending, which 
00124  * happens when WTP receives a resent invoke pdu, when its state TIDOK_WAIT.
00125  * Abort pdu now means a negative answer to a question "have you a transaction
00126  * having tid included in the tid verification message". So there is no need 
00127  * to indicate WSP.
00128  *
00129  * Error handling is mostly done before feeding an event to the state machine. 
00130  * However, when a pdu with an illegal header (header WTP does not understand)
00131  * is received, this is a special kind of event, because its handling depends
00132  * of the state. WTP must always send an abort pdu. If a transaction is 
00133  * established, it must be teared down. If WSP has been indicated about a 
00134  * transaction, WTP must do TR-Abort.ind.
00135  *
00136  * There are two kind of aborts: by the peer, when it sends abort pdu and by the 
00137  * wsp, when it does a primitive TR-Abort.req. When WSP does an abort, WTP 
00138  * must send an abort pdu to the peer; when WTP receives an abort, WSP must be
00139  * indicated (note, however, the special meaning abort pdu has in tid 
00140  * verification; see the relevant chapter).
00141  *
00142  * User acknowledgement means that WTP waits WSP (which in most cases is WTP
00143  * user) acknowledgement, instead of doing it by itself. This means, that if 
00144  * user acknowledgement flag is off, WTP sends an ack pdu when acknowledgement
00145  * timer expires.
00146  *
00147  * By Aarno Syvänen for WapIT Ltd.
00148  */
00149 
00150 STATE_NAME(LISTEN)
00151 STATE_NAME(TIDOK_WAIT)
00152 STATE_NAME(INVOKE_RESP_WAIT)
00153 STATE_NAME(RESULT_WAIT)
00154 STATE_NAME(RESULT_RESP_WAIT)
00155 STATE_NAME(WAIT_TIMEOUT_STATE)
00156 
00157 ROW(LISTEN,
00158     RcvInvoke,
00159     (event->u.RcvInvoke.tcl == 2 || event->u.RcvInvoke.tcl == 1) &&
00160      wtp_tid_is_valid(event, resp_machine) == ok,
00161     {
00162      resp_machine->u_ack = event->u.RcvInvoke.up_flag;
00163      resp_machine->tcl = event->u.RcvInvoke.tcl;
00164 
00165      wsp_event = create_tr_invoke_ind(resp_machine, 
00166          event->u.RcvInvoke.user_data);
00167      if (resp_machine->tcl == 1)
00168          wsp_push_client_dispatch_event(wsp_event);
00169      else
00170          wsp_session_dispatch_event(wsp_event);
00171 
00172      start_timer_A(resp_machine); 
00173      resp_machine->ack_pdu_sent = 0;
00174     },
00175     INVOKE_RESP_WAIT)
00176 
00177 /*
00178  * We must here store event fields and wsp indication into the wtp responder 
00179  * state machine: if tid is valid, we will continue the transaction without a 
00180  * new event.
00181  */
00182 ROW(LISTEN,
00183     RcvInvoke,
00184     (event->u.RcvInvoke.tcl == 2 || event->u.RcvInvoke.tcl == 1) &&
00185      (wtp_tid_is_valid(event, resp_machine) == fail || 
00186      wtp_tid_is_valid(event, resp_machine) == no_cached_tid),
00187     { 
00188      send_ack(resp_machine, TID_VERIFICATION, resp_machine->rid);
00189      
00190      resp_machine->u_ack = event->u.RcvInvoke.up_flag;
00191      resp_machine->tcl = event->u.RcvInvoke.tcl;
00192      resp_machine->invoke_indication = create_tr_invoke_ind(resp_machine, 
00193                                        event->u.RcvInvoke.user_data);
00194      debug("wap.wtp", 0, "WTP_STATE: generating invoke indication, tid being" 
00195            "invalid");
00196     },
00197     TIDOK_WAIT)
00198 
00199 /*
00200  * Do not change state when class 0 message is received.
00201  */
00202 ROW(LISTEN,
00203     RcvInvoke,
00204     event->u.RcvInvoke.tcl == 0,
00205     {
00206      wsp_event = create_tr_invoke_ind(resp_machine, 
00207          event->u.RcvInvoke.user_data);
00208      wsp_session_dispatch_event(wsp_event);
00209     },
00210     LISTEN)
00211 
00212 /*
00213  * No user indication here: transaction is not yet started.
00214  */
00215 ROW(LISTEN,
00216     RcvErrorPDU,
00217     1,
00218     { 
00219      send_abort(resp_machine, PROVIDER, PROTOERR);
00220     },
00221     LISTEN)
00222 
00223 /*
00224  * Need to control SAR incomplete packets
00225  */ 
00226 ROW(LISTEN,
00227     TimerTO_W,
00228     1,
00229     {},
00230     LISTEN)
00231 
00232 /*
00233  * We must cache the newly accepted tid item, otherwise every tid after a 
00234  * suspected one will be validated. We use wsp event stored by the responder
00235  * machine.
00236  */
00237 ROW(TIDOK_WAIT,
00238     RcvAck,
00239     (resp_machine->tcl == 2 || resp_machine->tcl == 1) && 
00240      event->u.RcvAck.tid_ok == 1,
00241     { 
00242      wsp_event = wap_event_duplicate(resp_machine->invoke_indication);
00243      if (resp_machine->tcl == 1)
00244          wsp_push_client_dispatch_event(wsp_event);
00245      else
00246          wsp_session_dispatch_event(wsp_event);
00247      
00248      wtp_tid_set_by_machine(resp_machine, event->u.RcvAck.tid);
00249 
00250      start_timer_A(resp_machine); 
00251      resp_machine->ack_pdu_sent = 0;
00252     },
00253     INVOKE_RESP_WAIT)
00254 
00255 /*
00256  * When we get a negative answer to tid verification, we just abort trans-
00257  * action. Because wtp machines are destroyed when their state return to 
00258  * LISTEN and because no transaction is yet started, there is no need to do 
00259  * anything here.
00260  */
00261 ROW(TIDOK_WAIT,
00262     RcvAbort,
00263     1,
00264     { },
00265     LISTEN)
00266 
00267 ROW(TIDOK_WAIT,
00268     RcvInvoke,
00269     event->u.RcvInvoke.rid == 0,
00270     { },
00271     TIDOK_WAIT)
00272 
00273 /*
00274  * Because the phone sends invoke again, previous ack was dropped by the 
00275  * bearer.
00276  */
00277 ROW(TIDOK_WAIT,
00278     RcvInvoke,
00279     event->u.RcvInvoke.rid == 1,
00280     { 
00281      send_ack(resp_machine, TID_VERIFICATION, resp_machine->rid);
00282     },
00283     TIDOK_WAIT)
00284 
00285 /*
00286  * No need for wsp indication: the transaction is not yet started.
00287  */
00288 ROW(TIDOK_WAIT,
00289     RcvErrorPDU,
00290     1,
00291     {
00292      send_abort(resp_machine, PROVIDER, PROTOERR);
00293     },
00294     LISTEN)
00295 
00296 ROW(INVOKE_RESP_WAIT,
00297     RcvInvoke,
00298     1,
00299     { },
00300     INVOKE_RESP_WAIT)
00301 
00302 ROW(INVOKE_RESP_WAIT,
00303     TR_Invoke_Res,
00304     resp_machine->tcl == 2,
00305     { 
00306      start_timer_A(resp_machine); 
00307      resp_machine->aec = 0;
00308     },
00309     RESULT_WAIT)
00310 
00311 ROW(INVOKE_RESP_WAIT,
00312     TR_Invoke_Res,
00313     resp_machine->tcl == 1,
00314     {
00315       send_ack(resp_machine, ACKNOWLEDGEMENT, resp_machine->rid);
00316       start_timer_W(resp_machine);
00317     },
00318     WAIT_TIMEOUT_STATE)
00319 
00320 ROW(INVOKE_RESP_WAIT,
00321     RcvAbort,
00322     1,
00323     {
00324      wsp_event = create_tr_abort_ind(resp_machine, 
00325          event->u.RcvAbort.abort_reason);
00326      if (resp_machine->tcl == 1)
00327          wsp_push_client_dispatch_event(wsp_event);
00328      else
00329          wsp_session_dispatch_event(wsp_event);
00330     },
00331     LISTEN)
00332 
00333 ROW(INVOKE_RESP_WAIT,
00334     TR_Abort_Req,
00335     1,
00336     { 
00337      send_abort(resp_machine, USER, event->u.TR_Abort_Req.abort_reason);
00338     },
00339     LISTEN)
00340 
00341 /*
00342  * non-SARed
00343  */
00344 ROW(INVOKE_RESP_WAIT,
00345     TR_Result_Req,
00346     resp_machine->sar == NULL,
00347     {
00348      WAPEvent *result;
00349 
00350      resp_machine->rcr = 0;
00351 
00352      start_timer_R(resp_machine);
00353      wap_event_destroy(resp_machine->result);
00354      resp_machine->rid = 0;
00355      result = wtp_pack_result(resp_machine, event);
00356      resp_machine->result = wap_event_duplicate(result);
00357      dispatch_to_wdp(result);
00358      resp_machine->rid = 1;
00359     },
00360     RESULT_RESP_WAIT)
00361 
00362 /*
00363  * SARed
00364  */
00365 ROW(INVOKE_RESP_WAIT,
00366      TR_Result_Req,
00367      resp_machine->sar != NULL,
00368      {
00369       resp_machine->rcr = 0;
00370 
00371       start_timer_R(resp_machine);
00372       wap_event_destroy(resp_machine->result);
00373       resp_machine->rid = 0;
00374       begin_sar_result(resp_machine, event);    
00375      },
00376      RESULT_RESP_WAIT)
00377 
00378 /*
00379  * Conditions below do not correspond wholly ones found from the spec. (If 
00380  * they does, user acknowledgement flag would never be used by the protocol, 
00381  * which cannot be the original intention.) 
00382  * User acknowledgement flag is used following way: if it is on, WTP does not
00383  * send an acknowledgement (user acknowledgement in form of TR-Invoke.res or 
00384  * TR-Result.req instead of provider acknowledgement is awaited); if it is 
00385  * off, WTP does this. IMHO, specs support this exegesis: there is condition 
00386  * Uack == False && class == 2 with action send ack pdu. In addition, WTP 
00387  * 8.3.1 says " When [user acknowledgement] is enabled WTP provider does not
00388  * respond to a received message until after WTP user has confirmed the 
00389  * indication service primitive by issuing the response primitive".
00390  *
00391  * BTW: CR correcting this shall appear soonish.
00392  */
00393 ROW(INVOKE_RESP_WAIT,
00394     TimerTO_A,
00395     resp_machine->aec < AEC_MAX && resp_machine->u_ack == 1,
00396     { 
00397      ++resp_machine->aec;
00398      start_timer_A(resp_machine);
00399     },
00400     INVOKE_RESP_WAIT)
00401 
00402 ROW(INVOKE_RESP_WAIT,
00403     TimerTO_A,
00404     (resp_machine->aec < AEC_MAX && resp_machine->u_ack == 0),
00405     { 
00406      ++resp_machine->aec;
00407      start_timer_A(resp_machine);
00408      send_ack(resp_machine, ACKNOWLEDGEMENT, resp_machine->rid);
00409      if (resp_machine->ack_pdu_sent == 0)
00410          resp_machine->ack_pdu_sent = 1;
00411     },
00412     INVOKE_RESP_WAIT)
00413 
00414 /*
00415  * When a transaction is aborted, WSP must surely know this. One of corrections
00416  * in MOT_WTP_CR_01. What to do when a counter reaches its maximum value dep-
00417  * ends on whether we have opened the connection or not. In previous case, we 
00418  * must go to the state WAIT_TIMEOUT_STATE, for instance to prevent bad incarn-
00419  * ations.
00420  */
00421 ROW(INVOKE_RESP_WAIT,
00422     TimerTO_A,
00423     resp_machine->aec == AEC_MAX && resp_machine->tcl == 2,
00424     {
00425      send_abort(resp_machine, PROVIDER, NORESPONSE);
00426      wsp_event = create_tr_abort_ind(resp_machine, NORESPONSE);
00427      wsp_session_dispatch_event(wsp_event);
00428     },
00429     LISTEN)
00430 
00431 ROW(INVOKE_RESP_WAIT,
00432     TimerTO_A,
00433     resp_machine->aec == AEC_MAX && resp_machine->tcl == 1,
00434     {
00435       start_timer_W(resp_machine);
00436     },
00437     WAIT_TIMEOUT_STATE)
00438 
00439 ROW(INVOKE_RESP_WAIT,
00440     RcvErrorPDU,
00441     1,
00442     {
00443      send_abort(resp_machine, PROVIDER, PROTOERR);
00444      
00445      wsp_event = create_tr_abort_ind(resp_machine, PROTOERR);
00446      if (resp_machine->tcl == 1)
00447          wsp_push_client_dispatch_event(wsp_event);
00448      else
00449          wsp_session_dispatch_event(wsp_event);
00450     },
00451     LISTEN)
00452 
00453 /*
00454  * Non-SARed
00455  */
00456 ROW(RESULT_WAIT,
00457     TR_Result_Req,
00458     resp_machine->sar == NULL,
00459     {
00460      WAPEvent *result;
00461      resp_machine->rcr = 0;
00462 
00463      start_timer_R(resp_machine);
00464 
00465      wap_event_destroy(resp_machine->result);
00466      resp_machine->rid = 0;
00467      result = wtp_pack_result(resp_machine, event);
00468      resp_machine->result = wap_event_duplicate(result);
00469      dispatch_to_wdp(result);
00470      resp_machine->rid = 1;
00471     },
00472     RESULT_RESP_WAIT)
00473 
00474 /*
00475  * SARed
00476  */
00477 ROW(RESULT_WAIT,
00478     TR_Result_Req,
00479     (resp_machine->sar != NULL) && ((octstr_len(event->u.TR_Result_Req.user_data)-1)/SAR_SEGM_SIZE < 255),
00480     {
00481      resp_machine->rcr = 0;
00482 
00483      start_timer_R(resp_machine);
00484 
00485      wap_event_destroy(resp_machine->result);
00486      resp_machine->rid = 0;
00487      begin_sar_result(resp_machine, event); 
00488     },
00489     RESULT_RESP_WAIT)
00490 
00491 ROW(RESULT_WAIT,
00492     TR_Result_Req,
00493     (resp_machine->sar != NULL) && ((octstr_len(event->u.TR_Result_Req.user_data)-1)/SAR_SEGM_SIZE >= 255),
00494     {
00495      send_abort(resp_machine, PROVIDER, NOTIMPLEMENTEDESAR);
00496      wsp_event = create_tr_abort_ind(resp_machine, NOTIMPLEMENTEDESAR);
00497      wsp_session_dispatch_event(wsp_event);
00498 
00499      wap_event_destroy(resp_machine->result);
00500     },
00501     LISTEN)
00502 
00503 ROW(RESULT_WAIT,
00504     RcvAbort,
00505     1,
00506     {
00507      wsp_event = create_tr_abort_ind(resp_machine, 
00508          event->u.RcvAbort.abort_reason);
00509      wsp_session_dispatch_event(wsp_event);
00510     },
00511     LISTEN)
00512 
00513 ROW(RESULT_WAIT,
00514     RcvInvoke,
00515     event->u.RcvInvoke.rid == 0,
00516     { },
00517     RESULT_WAIT)
00518 
00519 ROW(RESULT_WAIT,
00520     RcvInvoke,
00521     event->u.RcvInvoke.rid == 1 && resp_machine->ack_pdu_sent == 0,
00522     { },
00523     RESULT_WAIT)
00524 
00525 ROW(RESULT_WAIT,
00526     RcvInvoke,
00527     event->u.RcvInvoke.rid == 1 && resp_machine->ack_pdu_sent == 1,
00528     {
00529      send_ack(resp_machine, ACKNOWLEDGEMENT, resp_machine->rid);
00530     },
00531     RESULT_WAIT)
00532 
00533 ROW(RESULT_WAIT,
00534     TR_Abort_Req,
00535     1,
00536     { 
00537      send_abort(resp_machine, USER, event->u.TR_Abort_Req.abort_reason);
00538     },
00539     LISTEN)
00540 
00541 ROW(RESULT_WAIT,
00542     RcvErrorPDU,
00543     1,
00544     {
00545      send_abort(resp_machine, PROVIDER, PROTOERR);
00546      
00547      wsp_event = create_tr_abort_ind(resp_machine, PROTOERR);
00548      wsp_session_dispatch_event(wsp_event);
00549     },
00550     LISTEN)
00551    
00552 /*
00553  * This state follows two possible ones: INVOKE_RESP_WAIT & TR-Invoke.res and 
00554  * INVOKE_RESP_WAIT & TimerTO_A & Class == 2 & Uack == FALSE. Contrary what 
00555  * spec says, in first case we are now sending first time. We must, too, abort
00556  * after AEC_MAX timer periods.
00557  */
00558 ROW(RESULT_WAIT,
00559     TimerTO_A,
00560     resp_machine->aec < AEC_MAX,
00561     { 
00562      start_timer_A(resp_machine);
00563      send_ack(resp_machine, ACKNOWLEDGEMENT, resp_machine->rid);
00564      if (resp_machine->ack_pdu_sent == 0)
00565         resp_machine->ack_pdu_sent = 1;
00566      resp_machine->aec++;
00567     },
00568     RESULT_WAIT)
00569 
00570 ROW(RESULT_WAIT,
00571     TimerTO_A,
00572     resp_machine->aec == AEC_MAX,
00573     {
00574      send_abort(resp_machine, PROVIDER, NORESPONSE);
00575      wsp_event = create_tr_abort_ind(resp_machine, NORESPONSE);
00576      wsp_session_dispatch_event(wsp_event);
00577     },
00578     LISTEN)
00579 
00580 /*
00581  * A duplicate ack(tidok) caused by a heavy load (the original changed state
00582  * from TIDOK_WAIT). This implements CR-Nokia-WTP-20-March-2000/2.
00583  */
00584 ROW(RESULT_WAIT,
00585     RcvAck,
00586     event->u.RcvAck.tid_ok,
00587     {},
00588     RESULT_WAIT)
00589 
00590 /*
00591  * Non-SARed
00592  */
00593 ROW(RESULT_RESP_WAIT,
00594     RcvAck,
00595     resp_machine->sar == NULL || event->u.RcvAck.psn == resp_machine->sar->nsegm,
00596     {
00597      wsp_event = create_tr_result_cnf(resp_machine);
00598      wsp_session_dispatch_event(wsp_event);
00599     },
00600     LISTEN)
00601 
00602 /*
00603  * SARed
00604  */
00605 ROW(RESULT_RESP_WAIT,
00606     RcvAck,
00607     resp_machine->sar != NULL && event->u.RcvAck.psn != resp_machine->sar->nsegm,
00608     {
00609      continue_sar_result(resp_machine, event);   
00610     },
00611     RESULT_RESP_WAIT)
00612 
00613 ROW(RESULT_RESP_WAIT,
00614     RcvNegativeAck,
00615     resp_machine->sar != NULL,
00616     {
00617      resend_sar_result(resp_machine, event);     
00618     },
00619     RESULT_RESP_WAIT)
00620 
00621 /*
00622  * Specs does not tell what to do, when wtp responder receives invoke pdu and
00623  * its state is RESULT_RESP_WAIT. This can happen, however: event causing the 
00624  * transition RESULT_WAIT -> RESULT_RESP_WAIT is TR-Result.req, an internal 
00625  * responder event. 
00626  */
00627 ROW(RESULT_RESP_WAIT,
00628     RcvInvoke,
00629     1,
00630     { },
00631     RESULT_RESP_WAIT)
00632 
00633 ROW(RESULT_RESP_WAIT,
00634     RcvAbort,
00635     1,
00636     {
00637      wsp_event = create_tr_abort_ind(resp_machine, 
00638          event->u.RcvAbort.abort_reason);
00639      wsp_session_dispatch_event(wsp_event);
00640     },
00641     LISTEN)
00642 
00643 ROW(RESULT_RESP_WAIT,
00644     TR_Abort_Req,
00645     1,
00646     { 
00647      send_abort(resp_machine, USER, event->u.TR_Abort_Req.abort_reason);
00648     },
00649     LISTEN)
00650 
00651 ROW(RESULT_RESP_WAIT,
00652     TimerTO_R,
00653     resp_machine->rcr < MAX_RCR,
00654     {
00655      WAPEvent *resend;
00656 
00657      start_timer_R(resp_machine);
00658      resend = wap_event_duplicate(resp_machine->result);
00659      wtp_pack_set_rid(resend, resp_machine->rid);
00660      dispatch_to_wdp(resend);
00661      ++resp_machine->rcr;
00662     },
00663     RESULT_RESP_WAIT)
00664 
00665 ROW(RESULT_RESP_WAIT,
00666     TimerTO_R,
00667     resp_machine->rcr == MAX_RCR,
00668     {
00669      send_abort(resp_machine, PROVIDER, NORESPONSE);
00670      wsp_event = create_tr_abort_ind(resp_machine, NORESPONSE);
00671      wsp_session_dispatch_event(wsp_event);
00672     },
00673     LISTEN)
00674 
00675 ROW(RESULT_RESP_WAIT,
00676     RcvErrorPDU,
00677     1,
00678     {
00679      send_abort(resp_machine, PROVIDER, PROTOERR);
00680       
00681      wsp_event = create_tr_abort_ind(resp_machine, PROTOERR);
00682      wsp_session_dispatch_event(wsp_event);
00683     },
00684     LISTEN)
00685 
00686 ROW(WAIT_TIMEOUT_STATE,
00687     RcvInvoke,
00688     event->u.RcvInvoke.rid == 0,
00689     { },
00690     WAIT_TIMEOUT_STATE)
00691 
00692 ROW(WAIT_TIMEOUT_STATE,
00693     RcvInvoke,
00694     event->u.RcvInvoke.rid == 1,
00695     {
00696      send_ack(resp_machine, ACKNOWLEDGEMENT, resp_machine->rid);
00697     },
00698     WAIT_TIMEOUT_STATE)
00699 
00700 ROW(WAIT_TIMEOUT_STATE,
00701     RcvErrorPDU,
00702     1,
00703     {
00704      send_abort(resp_machine, PROVIDER, PROTOERR);
00705       
00706      wsp_event = create_tr_abort_ind(resp_machine, PROTOERR);
00707      wsp_push_client_dispatch_event(wsp_event);
00708     },
00709     LISTEN)
00710 
00711 ROW(WAIT_TIMEOUT_STATE,
00712     RcvAbort,
00713     1,
00714     {
00715      wsp_event = create_tr_abort_ind(resp_machine, PROTOERR);
00716      wsp_push_client_dispatch_event(wsp_event);
00717     },
00718     LISTEN)
00719 
00720 /*
00721  * Waiting to prevent premature incarnations.
00722  */
00723 ROW(WAIT_TIMEOUT_STATE,
00724     TimerTO_W,
00725     1,
00726     {
00727      wsp_event = create_tr_abort_ind(resp_machine, NORESPONSE);
00728      wsp_push_client_dispatch_event(wsp_event); 
00729     },
00730     LISTEN)
00731 
00732 ROW(WAIT_TIMEOUT_STATE,
00733     TR_Abort_Req,
00734     1,
00735     {
00736      send_abort(resp_machine, USER, event->u.TR_Abort_Req.abort_reason);
00737     },
00738     LISTEN)
00739 
00740 #undef ROW
00741 #undef STATE_NAME
See file LICENSE for details about the license agreement for using, modifying, copying or deriving work from this software.