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 * wtp_init_state.h: Macro calls for implementing wtp initiator state tables 00059 * See documentation for guidance how to use and update these. 00060 * 00061 * Only classes 0 and 1 are implemented. State NULL is called INITIATOR_NULL_ 00062 * STATE. 1 in the action field means that action is unconditional. 00063 * 00064 * Class 0 service is here a stateless invoke message (used for disconnection 00065 * or unconfirmed push). 00066 * 00067 * Basic class 1 transaction, without timers, is following: 00068 * - initiator sends an invoke message to the responder 00069 * - responder acknowledges it, with an pdu with tid verification 00070 * off (if it is on, we have a tid verification transaction, 00071 * see below). 00072 * 00073 * Retransmission until acknowledgement is implemented using timers and 00074 * retransmission counters. When the initiator sends an invoke it starts a 00075 * timer. When it expires, it resends the packet (either ack or invoke), until 00076 * counter reaches the maximum value. Then the transaction is aborted. 00077 * 00078 * If user acknowledgement is on, timers have different values. 00079 * 00080 * When the initiator aborts the transaction, it sends an abort pdu. When the 00081 * responder does it, the initiator wtp user is indicated. 00082 * 00083 * Tid verification in the initiator means answering the question posed by the 00084 * responder: "Have you an outstanding transaction having this tid". If we do 00085 * not have it, we have already, before feeding the event into the state 00086 * machine, sent an abort with reason INVALIDTID. So here we answer to an 00087 * ack pdu with tidve-flag set with an ack pdu with tidok-flag set. See WTP 00088 * 5.6, table 2; WTP 8.9; WTP 9.3.4.1. 00089 * 00090 * By Aarno Syvänen for Wapit Ltd. 00091 */ 00092 00093 INIT_STATE_NAME(INITIATOR_NULL_STATE) 00094 INIT_STATE_NAME(INITIATOR_RESULT_WAIT) 00095 00096 /* 00097 * We do not use transaction class 2 here: Server is initiator only when it is 00098 * pushing (class 1 or class 0) or disconnecting (class 0). First and second 00099 * rows are similar, with exception of timer period. 00100 */ 00101 ROW(INITIATOR_NULL_STATE, 00102 TR_Invoke_Req, 00103 event->u.TR_Invoke_Req.tcl == 1, 00104 { 00105 WAPEvent *invoke; 00106 /* 00107 * A special counter is used for storing value used (1) for tidnew flag when 00108 * restarting (See WTP 8.8.3.2) 00109 */ 00110 init_machine->tidnew = tidnew; 00111 00112 wap_event_destroy(init_machine->invoke); 00113 init_machine->rid = 0; 00114 init_machine->rcr = 0; 00115 00116 invoke = wtp_pack_invoke(init_machine, event); 00117 init_machine->invoke = wap_event_duplicate(invoke); 00118 dispatch_to_wdp(invoke); 00119 init_machine->rid = 1; 00120 /* 00121 * Turn the tidnew-flag off if it was on. (This can happen when tid was 00122 * wrapped or when we are restarting, see WTP 8.8.3.2) 00123 */ 00124 if (init_machine->tidnew) { 00125 init_machine->tidnew = 0; 00126 tidnew = 0; 00127 } 00128 init_machine->u_ack = event->u.TR_Invoke_Req.up_flag; 00129 init_machine->rcr = 0; 00130 start_initiator_timer_R(init_machine); 00131 }, 00132 INITIATOR_RESULT_WAIT) 00133 00134 /* 00135 * No need to turn tidnew flag when sending class 0 message; tid validation is 00136 * not invoked in this case. 00137 */ 00138 ROW(INITIATOR_NULL_STATE, 00139 TR_Invoke_Req, 00140 event->u.TR_Invoke_Req.tcl == 0, 00141 { 00142 WAPEvent *invoke; 00143 00144 wap_event_destroy(init_machine->invoke); 00145 invoke = wtp_pack_invoke(init_machine, event); 00146 init_machine->invoke = wap_event_duplicate(invoke); 00147 dispatch_to_wdp(invoke); 00148 }, 00149 INITIATOR_NULL_STATE) 00150 00151 ROW(INITIATOR_RESULT_WAIT, 00152 TR_Abort_Req, 00153 1, 00154 { 00155 send_abort(init_machine, USER, event->u.TR_Abort_Req.abort_reason); 00156 }, 00157 INITIATOR_NULL_STATE) 00158 00159 /* 00160 * Neither we check transaction class here: this can only be acknowledgement of 00161 * class 1 transaction. 00162 */ 00163 ROW(INITIATOR_RESULT_WAIT, 00164 RcvAck, 00165 event->u.RcvAck.tid_ok == 0, 00166 { 00167 stop_initiator_timer(init_machine->timer); 00168 00169 wsp_event = create_tr_invoke_cnf(init_machine); 00170 dispatch_to_wsp(wsp_event); 00171 }, 00172 INITIATOR_NULL_STATE) 00173 00174 /* 00175 * This is a positive answer to a tid verification (negative one being 00176 * already sent by init_machine_find_or_create). 00177 */ 00178 ROW(INITIATOR_RESULT_WAIT, 00179 RcvAck, 00180 event->u.RcvAck.tid_ok == 1 && init_machine->rcr < MAX_RCR, 00181 { 00182 send_ack(init_machine, TID_VERIFICATION, init_machine->rid); 00183 init_machine->tidok_sent = 1; 00184 00185 ++init_machine->rcr; 00186 00187 start_initiator_timer_R(init_machine); 00188 }, 00189 INITIATOR_RESULT_WAIT) 00190 00191 /* 00192 * RCR must not be greater than RCR_MAX. One of corrections from MOT_WTP_CR_01. 00193 */ 00194 ROW(INITIATOR_RESULT_WAIT, 00195 RcvAck, 00196 event->u.RcvAck.tid_ok, 00197 { }, 00198 INITIATOR_RESULT_WAIT) 00199 00200 ROW(INITIATOR_RESULT_WAIT, 00201 RcvAbort, 00202 1, 00203 { 00204 wsp_event = create_tr_abort_ind(init_machine, 00205 event->u.RcvAbort.abort_reason); 00206 dispatch_to_wsp(wsp_event); 00207 }, 00208 INITIATOR_NULL_STATE) 00209 00210 ROW(INITIATOR_RESULT_WAIT, 00211 RcvErrorPDU, 00212 1, 00213 { 00214 send_abort(init_machine, USER, PROTOERR); 00215 00216 wsp_event = create_tr_abort_ind(init_machine, PROTOERR); 00217 dispatch_to_wsp(wsp_event); 00218 }, 00219 INITIATOR_NULL_STATE) 00220 00221 ROW(INITIATOR_RESULT_WAIT, 00222 TimerTO_R, 00223 init_machine->rcr < MAX_RCR && !init_machine->tidok_sent, 00224 { 00225 WAPEvent *resend; 00226 00227 ++init_machine->rcr; 00228 00229 start_initiator_timer_R(init_machine); 00230 00231 resend = wap_event_duplicate(init_machine->invoke); 00232 wtp_pack_set_rid(resend, init_machine->rid); 00233 dispatch_to_wdp(resend); 00234 }, 00235 INITIATOR_RESULT_WAIT) 00236 00237 ROW(INITIATOR_RESULT_WAIT, 00238 TimerTO_R, 00239 init_machine->rcr < MAX_RCR && init_machine->tidok_sent, 00240 { 00241 ++init_machine->rcr; 00242 00243 start_initiator_timer_R(init_machine); 00244 00245 send_ack(init_machine, TID_VERIFICATION, init_machine->tidok_sent); 00246 }, 00247 INITIATOR_RESULT_WAIT) 00248 00249 ROW(INITIATOR_RESULT_WAIT, 00250 TimerTO_R, 00251 init_machine->rcr == MAX_RCR, 00252 { 00253 wsp_event = create_tr_abort_ind(init_machine, NORESPONSE); 00254 dispatch_to_wsp(wsp_event); 00255 }, 00256 INITIATOR_NULL_STATE) 00257 00258 #undef ROW 00259 #undef INIT_STATE_NAME