1 /* ====================================================================
2 * The Kannel Software License, Version 1.0
4 * Copyright (c) 2001-2018 Kannel Group
5 * Copyright (c) 1998-2001 WapIT Ltd.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in
17 * the documentation and/or other materials provided with the
20 * 3. The end-user documentation included with the redistribution,
21 * if any, must include the following acknowledgment:
22 * "This product includes software developed by the
23 * Kannel Group (http://www.kannel.org/)."
24 * Alternately, this acknowledgment may appear in the software itself,
25 * if and wherever such third-party acknowledgments normally appear.
27 * 4. The names "Kannel" and "Kannel Group" must not be used to
28 * endorse or promote products derived from this software without
29 * prior written permission. For written permission, please
30 * contact org@kannel.org.
32 * 5. Products derived from this software may not be called "Kannel",
33 * nor may "Kannel" appear in their name, without prior written
34 * permission of the Kannel Group.
36 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39 * DISCLAIMED. IN NO EVENT SHALL THE KANNEL GROUP OR ITS CONTRIBUTORS
40 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
41 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
42 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
43 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
44 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
45 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
46 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
47 * ====================================================================
49 * This software consists of voluntary contributions made by many
50 * individuals on behalf of the Kannel Group. For more information on
51 * the Kannel Group, please see <http://www.kannel.org/>.
53 * Portions of this software are based upon software originally written at
54 * WapIT Ltd., Helsinki, Finland for the Kannel project.
58 * Macro calls to generate rows of the state table. See the documentation for
59 * guidance how to use and update these.
61 * Macros have following arguments:
63 * STATE_NAME(name of a wtp machine state)
65 * ROW(the name of the current state,
66 * the event feeded to wtp machine,
67 * the condition for the action,
68 * {the action itself},
69 * the state wtp machine will transit)
71 * Condition 1 means that the action will be performed unconditionally, action
72 * {} means that the event in question will be ignored (of course, the state
73 * of the machine can change).
75 * There are many ROWS generating code for ignoring a certain event (ones hav-
76 * ing {} as their action). In these cases the event in question is caused by a
77 * duplicate message and the first one has already changed wtp responder mach-
78 * ine. In this case ignoring the event is natural.
80 * State tables use the phrase "abort transaction" many times. In this imple-
81 * mentation this means "clear data structures used for storing transaction
82 * data". This happens in function resp_event_handle, after included state
85 * Commenting the state table is perhaps best done by pointing out how various
86 * services provided by WTP contribute rows to the state table.
88 * Normal transaction goes as follows (timers excluded):
89 * - WTP get an invoke pdu from the peer. WTP does TR-Invoke.ind (trans-
90 * mitting to WSP its PDU) and the state changes to INVOKE_RESP_WAIT
91 * - WSP does TR-Invoke.res, telling that it has handled the
93 * The state changes to RESULT_WAIT.
94 * - WSP tells that it has results from the content server, or reply
95 * pdu to send. It does TR-Result.req. State changes to
97 * - WTP gets acknowledgement from the peer. It generates TR_Result.cnf
98 * and state changes to LISTEN. The transaction is over.
100 * Retransmission until acknowledgement guarantees reliability of the trans-
101 * action, if the peer stays up. It is implemented by using retransmissions
102 * controlled by timers and counters. There are two kind of timers, retrans-
103 * mission and acknowledgement timers. (Actually, there is one timer
104 * iniatilised with two intervals. But let us keep the language simple).
105 * These are used in concert with corresponding counters, RCR (retransmission
106 * counter) and AEC (acknowledgement expiration counter). AEC counts expired
107 * acknowledgement intervals.
109 * WTP starts an acknowledgement timer when it waits a WSP acknowledgement,
110 * and retransmission timer when it sends something. So when the acknowledge_
111 * ment timer expires, the action is to increment AEC, and when the retrans-
112 * mission timer expires, the action is to resend a packet. (Note, however,
113 * the chapter concerning user acknowledgement.)
115 * WTP ignores invoke pdus having same tid as the current transaction. This
116 * quarantees rejection of the duplicates. Note, however, how reliability is
117 * achieved when WTP is doing tid verification (next chapter).
119 * Tid verification is done if tid validation fails (which happens when the
120 * message is a duplicate or when tid wrapping-up could confuse the protocol).
121 * In this case, the state changes to TIDOK_WAIT. WSP is indicated only after
122 * an acknowledgement is received. After a negative answer (Abort PDU) the
123 * transaction is teared down. Reliablity is quaranteed by resending, which
124 * happens when WTP receives a resent invoke pdu, when its state TIDOK_WAIT.
125 * Abort pdu now means a negative answer to a question "have you a transaction
126 * having tid included in the tid verification message". So there is no need
129 * Error handling is mostly done before feeding an event to the state machine.
130 * However, when a pdu with an illegal header (header WTP does not understand)
131 * is received, this is a special kind of event, because its handling depends
132 * of the state. WTP must always send an abort pdu. If a transaction is
133 * established, it must be teared down. If WSP has been indicated about a
134 * transaction, WTP must do TR-Abort.ind.
136 * There are two kind of aborts: by the peer, when it sends abort pdu and by the
137 * wsp, when it does a primitive TR-Abort.req. When WSP does an abort, WTP
138 * must send an abort pdu to the peer; when WTP receives an abort, WSP must be
139 * indicated (note, however, the special meaning abort pdu has in tid
140 * verification; see the relevant chapter).
142 * User acknowledgement means that WTP waits WSP (which in most cases is WTP
143 * user) acknowledgement, instead of doing it by itself. This means, that if
144 * user acknowledgement flag is off, WTP sends an ack pdu when acknowledgement
147 * By Aarno Syvänen for WapIT Ltd.
151 STATE_NAME(TIDOK_WAIT)
152 STATE_NAME(INVOKE_RESP_WAIT)
153 STATE_NAME(RESULT_WAIT)
154 STATE_NAME(RESULT_RESP_WAIT)
155 STATE_NAME(WAIT_TIMEOUT_STATE)
159 (event->u.RcvInvoke.tcl == 2 || event->u.RcvInvoke.tcl == 1) &&
160 wtp_tid_is_valid(event, resp_machine) == ok,
162 resp_machine->u_ack = event->u.RcvInvoke.up_flag;
163 resp_machine->tcl = event->u.RcvInvoke.tcl;
165 wsp_event = create_tr_invoke_ind(resp_machine,
166 event->u.RcvInvoke.user_data);
167 if (resp_machine->tcl == 1)
168 wsp_push_client_dispatch_event(wsp_event);
170 wsp_session_dispatch_event(wsp_event);
172 start_timer_A(resp_machine);
173 resp_machine->ack_pdu_sent = 0;
178 * We must here store event fields and wsp indication into the wtp responder
179 * state machine: if tid is valid, we will continue the transaction without a
184 (event->u.RcvInvoke.tcl == 2 || event->u.RcvInvoke.tcl == 1) &&
185 (wtp_tid_is_valid(event, resp_machine) == fail ||
186 wtp_tid_is_valid(event, resp_machine) == no_cached_tid),
188 send_ack(resp_machine, TID_VERIFICATION, resp_machine->rid);
190 resp_machine->u_ack = event->u.RcvInvoke.up_flag;
191 resp_machine->tcl = event->u.RcvInvoke.tcl;
192 resp_machine->invoke_indication = create_tr_invoke_ind(resp_machine,
193 event->u.RcvInvoke.user_data);
194 debug("wap.wtp", 0, "WTP_STATE: generating invoke indication, tid being"
200 * Do not change state when class 0 message is received.
204 event->u.RcvInvoke.tcl == 0,
206 wsp_event = create_tr_invoke_ind(resp_machine,
207 event->u.RcvInvoke.user_data);
208 wsp_session_dispatch_event(wsp_event);
213 * No user indication here: transaction is not yet started.
219 send_abort(resp_machine, PROVIDER, PROTOERR);
224 * Need to control SAR incomplete packets
233 * We must cache the newly accepted tid item, otherwise every tid after a
234 * suspected one will be validated. We use wsp event stored by the responder
239 (resp_machine->tcl == 2 || resp_machine->tcl == 1) &&
240 event->u.RcvAck.tid_ok == 1,
242 wsp_event = wap_event_duplicate(resp_machine->invoke_indication);
243 if (resp_machine->tcl == 1)
244 wsp_push_client_dispatch_event(wsp_event);
246 wsp_session_dispatch_event(wsp_event);
248 wtp_tid_set_by_machine(resp_machine, event->u.RcvAck.tid);
250 start_timer_A(resp_machine);
251 resp_machine->ack_pdu_sent = 0;
256 * When we get a negative answer to tid verification, we just abort trans-
257 * action. Because wtp machines are destroyed when their state return to
258 * LISTEN and because no transaction is yet started, there is no need to do
269 event->u.RcvInvoke.rid == 0,
274 * Because the phone sends invoke again, previous ack was dropped by the
279 event->u.RcvInvoke.rid == 1,
281 send_ack(resp_machine, TID_VERIFICATION, resp_machine->rid);
286 * No need for wsp indication: the transaction is not yet started.
292 send_abort(resp_machine, PROVIDER, PROTOERR);
296 ROW(INVOKE_RESP_WAIT,
302 ROW(INVOKE_RESP_WAIT,
304 resp_machine->tcl == 2,
306 start_timer_A(resp_machine);
307 resp_machine->aec = 0;
311 ROW(INVOKE_RESP_WAIT,
313 resp_machine->tcl == 1,
315 send_ack(resp_machine, ACKNOWLEDGEMENT, resp_machine->rid);
316 start_timer_W(resp_machine);
320 ROW(INVOKE_RESP_WAIT,
324 wsp_event = create_tr_abort_ind(resp_machine,
325 event->u.RcvAbort.abort_reason);
326 if (resp_machine->tcl == 1)
327 wsp_push_client_dispatch_event(wsp_event);
329 wsp_session_dispatch_event(wsp_event);
333 ROW(INVOKE_RESP_WAIT,
337 send_abort(resp_machine, USER, event->u.TR_Abort_Req.abort_reason);
344 ROW(INVOKE_RESP_WAIT,
346 resp_machine->sar == NULL,
350 resp_machine->rcr = 0;
352 start_timer_R(resp_machine);
353 wap_event_destroy(resp_machine->result);
354 resp_machine->rid = 0;
355 result = wtp_pack_result(resp_machine, event);
356 resp_machine->result = wap_event_duplicate(result);
357 dispatch_to_wdp(result);
358 resp_machine->rid = 1;
365 ROW(INVOKE_RESP_WAIT,
367 resp_machine->sar != NULL,
369 resp_machine->rcr = 0;
371 start_timer_R(resp_machine);
372 wap_event_destroy(resp_machine->result);
373 resp_machine->rid = 0;
374 begin_sar_result(resp_machine, event);
379 * Conditions below do not correspond wholly ones found from the spec. (If
380 * they does, user acknowledgement flag would never be used by the protocol,
381 * which cannot be the original intention.)
382 * User acknowledgement flag is used following way: if it is on, WTP does not
383 * send an acknowledgement (user acknowledgement in form of TR-Invoke.res or
384 * TR-Result.req instead of provider acknowledgement is awaited); if it is
385 * off, WTP does this. IMHO, specs support this exegesis: there is condition
386 * Uack == False && class == 2 with action send ack pdu. In addition, WTP
387 * 8.3.1 says " When [user acknowledgement] is enabled WTP provider does not
388 * respond to a received message until after WTP user has confirmed the
389 * indication service primitive by issuing the response primitive".
391 * BTW: CR correcting this shall appear soonish.
393 ROW(INVOKE_RESP_WAIT,
395 resp_machine->aec < AEC_MAX && resp_machine->u_ack == 1,
398 start_timer_A(resp_machine);
402 ROW(INVOKE_RESP_WAIT,
404 (resp_machine->aec < AEC_MAX && resp_machine->u_ack == 0),
407 start_timer_A(resp_machine);
408 send_ack(resp_machine, ACKNOWLEDGEMENT, resp_machine->rid);
409 if (resp_machine->ack_pdu_sent == 0)
410 resp_machine->ack_pdu_sent = 1;
415 * When a transaction is aborted, WSP must surely know this. One of corrections
416 * in MOT_WTP_CR_01. What to do when a counter reaches its maximum value dep-
417 * ends on whether we have opened the connection or not. In previous case, we
418 * must go to the state WAIT_TIMEOUT_STATE, for instance to prevent bad incarn-
421 ROW(INVOKE_RESP_WAIT,
423 resp_machine->aec == AEC_MAX && resp_machine->tcl == 2,
425 send_abort(resp_machine, PROVIDER, NORESPONSE);
426 wsp_event = create_tr_abort_ind(resp_machine, NORESPONSE);
427 wsp_session_dispatch_event(wsp_event);
431 ROW(INVOKE_RESP_WAIT,
433 resp_machine->aec == AEC_MAX && resp_machine->tcl == 1,
435 start_timer_W(resp_machine);
439 ROW(INVOKE_RESP_WAIT,
443 send_abort(resp_machine, PROVIDER, PROTOERR);
445 wsp_event = create_tr_abort_ind(resp_machine, PROTOERR);
446 if (resp_machine->tcl == 1)
447 wsp_push_client_dispatch_event(wsp_event);
449 wsp_session_dispatch_event(wsp_event);
458 resp_machine->sar == NULL,
461 resp_machine->rcr = 0;
463 start_timer_R(resp_machine);
465 wap_event_destroy(resp_machine->result);
466 resp_machine->rid = 0;
467 result = wtp_pack_result(resp_machine, event);
468 resp_machine->result = wap_event_duplicate(result);
469 dispatch_to_wdp(result);
470 resp_machine->rid = 1;
479 (resp_machine->sar != NULL) && ((octstr_len(event->u.TR_Result_Req.user_data)-1)/SAR_SEGM_SIZE < 255),
481 resp_machine->rcr = 0;
483 start_timer_R(resp_machine);
485 wap_event_destroy(resp_machine->result);
486 resp_machine->rid = 0;
487 begin_sar_result(resp_machine, event);
493 (resp_machine->sar != NULL) && ((octstr_len(event->u.TR_Result_Req.user_data)-1)/SAR_SEGM_SIZE >= 255),
495 send_abort(resp_machine, PROVIDER, NOTIMPLEMENTEDESAR);
496 wsp_event = create_tr_abort_ind(resp_machine, NOTIMPLEMENTEDESAR);
497 wsp_session_dispatch_event(wsp_event);
499 wap_event_destroy(resp_machine->result);
507 wsp_event = create_tr_abort_ind(resp_machine,
508 event->u.RcvAbort.abort_reason);
509 wsp_session_dispatch_event(wsp_event);
515 event->u.RcvInvoke.rid == 0,
521 event->u.RcvInvoke.rid == 1 && resp_machine->ack_pdu_sent == 0,
527 event->u.RcvInvoke.rid == 1 && resp_machine->ack_pdu_sent == 1,
529 send_ack(resp_machine, ACKNOWLEDGEMENT, resp_machine->rid);
537 send_abort(resp_machine, USER, event->u.TR_Abort_Req.abort_reason);
545 send_abort(resp_machine, PROVIDER, PROTOERR);
547 wsp_event = create_tr_abort_ind(resp_machine, PROTOERR);
548 wsp_session_dispatch_event(wsp_event);
553 * This state follows two possible ones: INVOKE_RESP_WAIT & TR-Invoke.res and
554 * INVOKE_RESP_WAIT & TimerTO_A & Class == 2 & Uack == FALSE. Contrary what
555 * spec says, in first case we are now sending first time. We must, too, abort
556 * after AEC_MAX timer periods.
560 resp_machine->aec < AEC_MAX,
562 start_timer_A(resp_machine);
563 send_ack(resp_machine, ACKNOWLEDGEMENT, resp_machine->rid);
564 if (resp_machine->ack_pdu_sent == 0)
565 resp_machine->ack_pdu_sent = 1;
572 resp_machine->aec == AEC_MAX,
574 send_abort(resp_machine, PROVIDER, NORESPONSE);
575 wsp_event = create_tr_abort_ind(resp_machine, NORESPONSE);
576 wsp_session_dispatch_event(wsp_event);
581 * A duplicate ack(tidok) caused by a heavy load (the original changed state
582 * from TIDOK_WAIT). This implements CR-Nokia-WTP-20-March-2000/2.
586 event->u.RcvAck.tid_ok,
593 ROW(RESULT_RESP_WAIT,
595 resp_machine->sar == NULL || event->u.RcvAck.psn == resp_machine->sar->nsegm,
597 wsp_event = create_tr_result_cnf(resp_machine);
598 wsp_session_dispatch_event(wsp_event);
605 ROW(RESULT_RESP_WAIT,
607 resp_machine->sar != NULL && event->u.RcvAck.psn != resp_machine->sar->nsegm,
609 continue_sar_result(resp_machine, event);
613 ROW(RESULT_RESP_WAIT,
615 resp_machine->sar != NULL,
617 resend_sar_result(resp_machine, event);
622 * Specs does not tell what to do, when wtp responder receives invoke pdu and
623 * its state is RESULT_RESP_WAIT. This can happen, however: event causing the
624 * transition RESULT_WAIT -> RESULT_RESP_WAIT is TR-Result.req, an internal
627 ROW(RESULT_RESP_WAIT,
633 ROW(RESULT_RESP_WAIT,
637 wsp_event = create_tr_abort_ind(resp_machine,
638 event->u.RcvAbort.abort_reason);
639 wsp_session_dispatch_event(wsp_event);
643 ROW(RESULT_RESP_WAIT,
647 send_abort(resp_machine, USER, event->u.TR_Abort_Req.abort_reason);
651 ROW(RESULT_RESP_WAIT,
653 resp_machine->rcr < MAX_RCR,
657 start_timer_R(resp_machine);
658 resend = wap_event_duplicate(resp_machine->result);
659 wtp_pack_set_rid(resend, resp_machine->rid);
660 dispatch_to_wdp(resend);
665 ROW(RESULT_RESP_WAIT,
667 resp_machine->rcr == MAX_RCR,
669 send_abort(resp_machine, PROVIDER, NORESPONSE);
670 wsp_event = create_tr_abort_ind(resp_machine, NORESPONSE);
671 wsp_session_dispatch_event(wsp_event);
675 ROW(RESULT_RESP_WAIT,
679 send_abort(resp_machine, PROVIDER, PROTOERR);
681 wsp_event = create_tr_abort_ind(resp_machine, PROTOERR);
682 wsp_session_dispatch_event(wsp_event);
686 ROW(WAIT_TIMEOUT_STATE,
688 event->u.RcvInvoke.rid == 0,
692 ROW(WAIT_TIMEOUT_STATE,
694 event->u.RcvInvoke.rid == 1,
696 send_ack(resp_machine, ACKNOWLEDGEMENT, resp_machine->rid);
700 ROW(WAIT_TIMEOUT_STATE,
704 send_abort(resp_machine, PROVIDER, PROTOERR);
706 wsp_event = create_tr_abort_ind(resp_machine, PROTOERR);
707 wsp_push_client_dispatch_event(wsp_event);
711 ROW(WAIT_TIMEOUT_STATE,
715 wsp_event = create_tr_abort_ind(resp_machine, PROTOERR);
716 wsp_push_client_dispatch_event(wsp_event);
721 * Waiting to prevent premature incarnations.
723 ROW(WAIT_TIMEOUT_STATE,
727 wsp_event = create_tr_abort_ind(resp_machine, NORESPONSE);
728 wsp_push_client_dispatch_event(wsp_event);
732 ROW(WAIT_TIMEOUT_STATE,
736 send_abort(resp_machine, USER, event->u.TR_Abort_Req.abort_reason);