/* ==================================================================== * The Kannel Software License, Version 1.0 * * Copyright (c) 2001-2014 Kannel Group * Copyright (c) 1998-2001 WapIT Ltd. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, * if any, must include the following acknowledgment: * "This product includes software developed by the * Kannel Group (http://www.kannel.org/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The names "Kannel" and "Kannel Group" must not be used to * endorse or promote products derived from this software without * prior written permission. For written permission, please * contact org@kannel.org. * * 5. Products derived from this software may not be called "Kannel", * nor may "Kannel" appear in their name, without prior written * permission of the Kannel Group. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE KANNEL GROUP OR ITS CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Kannel Group. For more information on * the Kannel Group, please see . * * Portions of this software are based upon software originally written at * WapIT Ltd., Helsinki, Finland for the Kannel project. */ /* * wsp_server_session_states.def - states for WSP session state machines * * Macro calls to generate rows of the state table. See the documentation for * guidance how to use and update these. * * Note that `NULL' state is renamed to `NULL_SESSION' because NULL is * reserved by C. * * Lars Wirzenius */ STATE_NAME(NULL_SESSION) STATE_NAME(CONNECTING) STATE_NAME(TERMINATING) STATE_NAME(CONNECTING_2) STATE_NAME(CONNECTED) STATE_NAME(SUSPENDED) STATE_NAME(RESUMING) STATE_NAME(RESUMING_2) ROW(NULL_SESSION, TR_Invoke_Ind, e->tcl == 2 && pdu->type == Connect, { WAPEvent *new_event; WAPEvent *wtp_event; /* Send TR-Invoke.res to WTP */ wtp_event = wap_event_create(TR_Invoke_Res); wtp_event->u.TR_Invoke_Res.handle = e->handle; dispatch_to_wtp_resp(wtp_event); /* Assign a session ID for this session. We do this * early, instead of in the CONNECTING state, because * we want to use the session id as a way for the * application layer to refer back to this machine. */ sm->session_id = next_wsp_session_id(); if (pdu->u.Connect.capabilities_len > 0) { unsigned long sdu; sm->request_caps = wsp_cap_unpack_list( pdu->u.Connect.capabilities); if (wsp_cap_get_client_sdu(sm->request_caps,&sdu)) { sm->client_SDU_size = sdu; } } else { sm->request_caps = gwlist_create(); } if (pdu->u.Connect.headers_len > 0) { List *hdrs; Octstr *encoding; hdrs = wsp_headers_unpack(pdu->u.Connect.headers, 0); http_header_pack(hdrs); gw_assert(sm->http_headers == NULL); sm->http_headers = hdrs; /* * Get WSP encoding version if provided by device and remember in * session machine for later use in encoding tokenized values. */ encoding = http_header_value(sm->http_headers, octstr_imm("Encoding-Version")); if (encoding != NULL) { debug("wsp",0,"WSP: Session machine: Encoding-Version: %s", octstr_get_cstr(encoding)); sm->encoding_version = wsp_encoding_string_to_version(encoding); } else { /* WAP-230-WSP-20010705-a, section 8.4.2.70, page 97 defines * by a MUST argument that a non-present Encoding-Version header * should be interpreted as WSP 1.2 compliant. */ sm->encoding_version = WSP_1_2; } octstr_destroy(encoding); } /* Send S-Connect.ind to application layer */ new_event = wap_event_create(S_Connect_Ind); new_event->u.S_Connect_Ind.addr_tuple = wap_addr_tuple_duplicate(e->addr_tuple); new_event->u.S_Connect_Ind.client_headers = http_header_duplicate(sm->http_headers); new_event->u.S_Connect_Ind.requested_capabilities = wsp_cap_duplicate_list(sm->request_caps); new_event->u.S_Connect_Ind.session_id = sm->session_id; dispatch_to_appl(new_event); }, CONNECTING) ROW(CONNECTING, S_Connect_Res, 1, { WAPEvent *wtp_event; Octstr *ospdu; sm->reply_caps = wsp_cap_duplicate_list( e->negotiated_capabilities); /* Send Disconnect event to existing sessions for client. */ disconnect_other_sessions(sm); /* Assign a Session_ID for this session. */ /* We've already done that in the NULL_STATE. */ /* TR-Result.req(ConnectReply) */ ospdu = make_connectreply_pdu(sm); wtp_event = wap_event_create(TR_Result_Req); wtp_event->u.TR_Result_Req.user_data = ospdu; wtp_event->u.TR_Result_Req.handle = sm->connect_handle; dispatch_to_wtp_resp(wtp_event); /* Release all method transactions in HOLDING state. */ release_holding_methods(sm); }, CONNECTING_2) /* MISSING: CONNECTING, S_Disconnect_Req, reason == 301 (moved permanently) or * 302 (moved temporarily). */ /* MISSING: CONNECTING, S_Disconnect_Req, reason == anything else */ ROW(CONNECTING, Disconnect_Event, 1, { /* TR-Abort.req(DISCONNECT) the Connect transaction */ send_abort(WSP_ABORT_DISCONNECT, sm->connect_handle); /* Abort(DISCONNECT) all method transactions */ abort_methods(sm, WSP_ABORT_DISCONNECT); /* S-Disconnect.ind(DISCONNECT) */ indicate_disconnect(sm, WSP_ABORT_DISCONNECT); }, NULL_SESSION) ROW(CONNECTING, Suspend_Event, 1, { /* TR-Abort.req(DISCONNECT) the Connect transaction */ send_abort(WSP_ABORT_DISCONNECT, sm->connect_handle); /* Abort(DISCONNECT) all method transactions */ abort_methods(sm, WSP_ABORT_DISCONNECT); /* S-Disconnect.ind(SUSPEND) */ indicate_disconnect(sm, WSP_ABORT_SUSPEND); }, NULL_SESSION) ROW(CONNECTING, TR_Invoke_Ind, e->tcl == 2 && (pdu->type == Get || pdu->type == Post), { WSPMethodMachine *msm; /* Start new method transaction */ msm = method_machine_create(sm, e->handle); /* Hand off the event to the new method machine */ handle_method_event(sm, msm, current_event, pdu); }, CONNECTING) ROW(CONNECTING, TR_Invoke_Ind, e->tcl == 2 && pdu->type == Resume, { /* TR-Abort.req(DISCONNECT) the TR-Invoke */ send_abort(WSP_ABORT_DISCONNECT, e->handle); }, CONNECTING) ROW(CONNECTING, TR_Abort_Ind, e->handle == sm->connect_handle, { /* Abort(DISCONNECT) all method transactions */ abort_methods(sm, WSP_ABORT_DISCONNECT); /* S-Disconnect.ind(abort reason) */ indicate_disconnect(sm, e->abort_code); }, NULL_SESSION) ROW(CONNECTING, TR_Abort_Ind, e->handle != sm->connect_handle, { WSPMethodMachine *msm; /* See method state table */ msm = find_method_machine(sm, e->handle); handle_method_event(sm, msm, current_event, pdu); }, CONNECTING) ROW(TERMINATING, Disconnect_Event, 1, { /* TR-Abort.req(DISCONNECT) remaining transport transaction */ send_abort(WSP_ABORT_DISCONNECT, sm->connect_handle); }, NULL_SESSION) ROW(TERMINATING, Suspend_Event, 1, { /* TR-Abort.req(SUSPEND) remaining transport transaction */ send_abort(WSP_ABORT_SUSPEND, sm->connect_handle); }, NULL_SESSION) ROW(TERMINATING, TR_Result_Cnf, 1, { /* Ignore */ }, NULL_SESSION) ROW(TERMINATING, TR_Abort_Ind, 1, { /* Ignore */ }, NULL_SESSION) /* MISSING: CONNECTING_2, S-Disconnect.req */ ROW(CONNECTING_2, Disconnect_Event, 1, { /* TR-Abort.req(DISCONNECT) the Connect transaction */ send_abort(WSP_ABORT_DISCONNECT, sm->connect_handle); /* Abort(DISCONNECT) all method and push transactions */ abort_methods(sm, WSP_ABORT_DISCONNECT); /* S-Disconnect.ind(DISCONNECT) */ indicate_disconnect(sm, WSP_ABORT_DISCONNECT); }, NULL_SESSION) ROW(CONNECTING_2, S_MethodInvoke_Res, 1, { WSPMethodMachine *msm; /* See method state table */ msm = find_method_machine(sm, e->server_transaction_id); handle_method_event(sm, msm, current_event, pdu); }, CONNECTING_2) ROW(CONNECTING_2, S_MethodResult_Req, 1, { WSPMethodMachine *msm; /* See method state table */ msm = find_method_machine(sm, e->server_transaction_id); handle_method_event(sm, msm, current_event, pdu); }, CONNECTING_2) ROW(CONNECTING_2, S_Push_Req, 1, { WSP_PDU *pdu; pdu = make_push_pdu(current_event); send_invoke(sm, pdu, current_event, TRANSACTION_CLASS_0); }, CONNECTING_2) ROW(CONNECTING_2, S_ConfirmedPush_Req, 1, { /* Start new push transaction*/ WSPPushMachine *spm; spm = push_machine_create(sm, e->server_push_id); handle_push_event(sm, spm, current_event); }, CONNECTING_2) ROW(CONNECTING_2, Suspend_Event, !resume_enabled, { /* Session Resume facility disabled */ /* TR-Abort.req(DISCONNECT) the Connect transaction */ send_abort(WSP_ABORT_DISCONNECT, sm->connect_handle); /* Abort(DISCONNECT) all method and push transactions */ abort_methods(sm, WSP_ABORT_DISCONNECT); /* S-Disconnect.ind(SUSPEND) */ indicate_disconnect(sm, WSP_ABORT_SUSPEND); }, NULL_SESSION) ROW(CONNECTING_2, Suspend_Event, resume_enabled, { /* Session Resume facility enabled */ /* TR-Abort.req(SUSPEND) the Connect transaction */ send_abort(WSP_ABORT_SUSPEND, sm->connect_handle); /* Abort(SUSPEND) all method and push transactions */ abort_methods(sm, WSP_ABORT_SUSPEND); /* S-Suspend.ind(SUSPEND) */ indicate_suspend(sm, WSP_ABORT_SUSPEND); }, SUSPENDED) ROW(CONNECTING_2, TR_Invoke_Ind, e->tcl == 2 && (pdu->type == Get || pdu->type == Post), { WSPMethodMachine *msm; WAPEvent *new_event; /* Start new method transaction */ msm = method_machine_create(sm, e->handle); /* Hand off the event to the new method machine */ handle_method_event(sm, msm, current_event, pdu); /* Release the new method transaction */ new_event = wap_event_create(Release_Event); handle_method_event(sm, msm, new_event, NULL); wap_event_destroy(new_event); }, CONNECTING_2) ROW(CONNECTING_2, TR_Invoke_Ind, e->tcl == 2 && pdu->type == Resume && !resume_enabled, { /* Resume facility disabled */ /* TR-Abort.req(DISCONNECT) the TR-Invoke */ send_abort(WSP_ABORT_DISCONNECT, e->handle); }, CONNECTING_2) ROW(CONNECTING_2, TR_Invoke_Ind, e->tcl == 2 && pdu->type == Resume && resume_enabled, { /* Resume facility enabled */ WAPEvent *wtp_event; List *new_headers; /* TR-Invoke.res */ wtp_event = wap_event_create(TR_Invoke_Res); wtp_event->u.TR_Invoke_Res.handle = e->handle; dispatch_to_wtp_resp(wtp_event); /* TR-Abort.req(RESUME) the Connect transaction */ send_abort(WSP_ABORT_RESUME, sm->connect_handle); /* Abort(RESUME) all method and push transactions */ abort_methods(sm, WSP_ABORT_RESUME); /* S-Suspend.ind(RESUME) */ indicate_suspend(sm, WSP_ABORT_RESUME); /* S-Resume.ind */ new_headers = unpack_new_headers(sm, pdu->u.Resume.headers); indicate_resume(sm, e->addr_tuple, new_headers); http_destroy_headers(new_headers); sm->resume_handle = e->handle; }, RESUMING) ROW(CONNECTING_2, TR_Invoke_Ind, e->tcl == 0 && pdu->type == Disconnect, { /* TR-Abort.req(DISCONNECT) the Connect transaction */ send_abort(WSP_ABORT_DISCONNECT, sm->connect_handle); /* Abort(DISCONNECT) all method and push transactions */ abort_methods(sm, WSP_ABORT_DISCONNECT); /* S-Disconnect.ind(DISCONNECT) */ indicate_disconnect(sm, WSP_ABORT_DISCONNECT); }, NULL_SESSION) ROW(CONNECTING_2, TR_Invoke_Ind, e->tcl == 0 && pdu->type == Suspend && resume_enabled, { /* Resume facility enabled */ /* TR-Abort.req(SUSPEND) the Connect transaction */ send_abort(WSP_ABORT_SUSPEND, sm->connect_handle); /* Abort(SUSPEND) all method and push transactions */ abort_methods(sm, WSP_ABORT_SUSPEND); /* S-Suspend.ind(SUSPEND) */ indicate_suspend(sm, WSP_ABORT_SUSPEND); }, SUSPENDED) ROW(CONNECTING_2, TR_Invoke_Cnf, 1, { /* See push state table*/ WSPPushMachine *spm; spm = find_push_machine(sm, e->handle); handle_push_event(sm, spm, current_event); }, CONNECTING_2) ROW(CONNECTING_2, TR_Result_Cnf, e->handle == sm->connect_handle, { }, CONNECTED) ROW(CONNECTING_2, TR_Result_Cnf, e->handle != sm->connect_handle, { WSPMethodMachine *msm; /* See method state table */ msm = find_method_machine(sm, e->handle); handle_method_event(sm, msm, current_event, pdu); }, CONNECTING_2) ROW(CONNECTING_2, TR_Abort_Ind, e->handle == sm->connect_handle, { /* Abort(DISCONNECT) all method and push transactions */ abort_methods(sm, WSP_ABORT_DISCONNECT); /* S-Disconnect.ind(abort reason) */ indicate_disconnect(sm, e->abort_code); }, NULL_SESSION) /* * A separate flag tells is the indicator the initiator or the responder. */ ROW(CONNECTING_2, TR_Abort_Ind, e->handle != sm->connect_handle && e->ir_flag == RESPONDER_INDICATION, { WSPMethodMachine *msm; /* See method state table */ msm = find_method_machine(sm, e->handle); handle_method_event(sm, msm, current_event, pdu); }, CONNECTING_2) ROW(CONNECTING_2, TR_Abort_Ind, e->handle != sm->connect_handle && e->ir_flag == INITIATOR_INDICATION, { WSPPushMachine *m; /* See push state table */ m = find_push_machine(sm, e->handle); handle_push_event(sm, m, current_event); }, CONNECTING_2) /* MISSING: CONNECTED, S-Disconnect.req */ ROW(CONNECTED, Disconnect_Event, 1, { /* Abort(DISCONNECT) all method and push transactions */ abort_methods(sm, WSP_ABORT_DISCONNECT); /* S-Disconnect.ind(DISCONNECT) */ indicate_disconnect(sm, WSP_ABORT_DISCONNECT); }, NULL_SESSION) ROW(CONNECTED, S_MethodInvoke_Res, 1, { WSPMethodMachine *msm; /* See method state table */ msm = find_method_machine(sm, e->server_transaction_id); handle_method_event(sm, msm, current_event, pdu); }, CONNECTED) ROW(CONNECTED, S_MethodResult_Req, 1, { WSPMethodMachine *msm; /* See method state table */ msm = find_method_machine(sm, e->server_transaction_id); handle_method_event(sm, msm, current_event, pdu); }, CONNECTED) ROW(CONNECTED, S_Push_Req, 1, { WSP_PDU *pdu; pdu = make_push_pdu(current_event); send_invoke(sm, pdu, current_event, TRANSACTION_CLASS_0); }, CONNECTED) ROW(CONNECTED, S_ConfirmedPush_Req, 1, { /* Start new push transaction*/ WSPPushMachine *spm; spm = push_machine_create(sm, e->server_push_id); handle_push_event(sm, spm, current_event); }, CONNECTED) ROW(CONNECTED, Suspend_Event, !resume_enabled, { /* Session Resume facility disabled */ /* Abort(SUSPEND) all method and push transactions */ abort_methods(sm, WSP_ABORT_SUSPEND); /* S-Disconnect.ind(SUSPEND) */ indicate_disconnect(sm, WSP_ABORT_SUSPEND); }, NULL_SESSION) ROW(CONNECTED, Suspend_Event, resume_enabled, { /* Session Resume facility enabled */ /* Abort(SUSPEND) all method and push transactions */ abort_methods(sm, WSP_ABORT_SUSPEND); /* S-Suspend.ind(SUSPEND) */ indicate_suspend(sm, WSP_ABORT_SUSPEND); }, SUSPENDED) ROW(CONNECTED, TR_Invoke_Ind, e->tcl == 2 && (pdu->type == Get || pdu->type == Post), { WSPMethodMachine *msm; WAPEvent *new_event; /* Start new method transaction */ msm = method_machine_create(sm, e->handle); /* Hand off the event to the new method machine */ handle_method_event(sm, msm, current_event, pdu); /* Release the new method transaction */ new_event = wap_event_create(Release_Event); handle_method_event(sm, msm, new_event, NULL); wap_event_destroy(new_event); }, CONNECTED) ROW(CONNECTED, TR_Invoke_Ind, e->tcl == 2 && pdu->type == Resume && !resume_enabled, { /* Resume facility disabled */ /* TR-Abort.req(DISCONNECT) the TR-Invoke */ send_abort(WSP_ABORT_DISCONNECT, e->handle); }, CONNECTED) ROW(CONNECTED, TR_Invoke_Ind, e->tcl == 2 && pdu->type == Resume && resume_enabled, { /* Resume facility enabled */ WAPEvent *wtp_event; List *new_headers; /* TR-Invoke.res */ wtp_event = wap_event_create(TR_Invoke_Res); wtp_event->u.TR_Invoke_Res.handle = e->handle; dispatch_to_wtp_resp(wtp_event); /* Abort(RESUME) all method and push transactions */ abort_methods(sm, WSP_ABORT_RESUME); /* S-Suspend.ind(RESUME) */ indicate_suspend(sm, WSP_ABORT_RESUME); /* S-Resume.ind */ new_headers = unpack_new_headers(sm, pdu->u.Resume.headers); indicate_resume(sm, e->addr_tuple, new_headers); http_destroy_headers(new_headers); sm->resume_handle = e->handle; }, RESUMING) ROW(CONNECTED, TR_Invoke_Ind, e->tcl == 0 && pdu->type == Disconnect, { /* Abort(DISCONNECT) all method and push transactions */ abort_methods(sm, WSP_ABORT_DISCONNECT); /* S-Disconnect.ind(DISCONNECT) */ indicate_disconnect(sm, WSP_ABORT_DISCONNECT); }, NULL_SESSION) ROW(CONNECTED, TR_Invoke_Ind, e->tcl == 0 && pdu->type == Suspend && resume_enabled, { /* Abort(SUSPEND) all method and push transactions */ abort_methods(sm, WSP_ABORT_SUSPEND); /* S-Suspend.ind(SUSPEND) */ indicate_suspend(sm, WSP_ABORT_SUSPEND); }, SUSPENDED) ROW(CONNECTED, TR_Invoke_Cnf, 1, { /* See push state table*/ WSPPushMachine *spm; spm = find_push_machine(sm, e->handle); handle_push_event(sm, spm, current_event); }, CONNECTED) ROW(CONNECTED, TR_Result_Cnf, e->handle != sm->connect_handle, { WSPMethodMachine *msm; /* See method state table */ msm = find_method_machine(sm, e->handle); handle_method_event(sm, msm, current_event, pdu); }, CONNECTED) /* * Event TR-Abort.ind has a separate flag telling is the indicator the * initiator or the responder. */ ROW(CONNECTED, TR_Abort_Ind, e->handle != sm->connect_handle && e->ir_flag == RESPONDER_INDICATION, { WSPMethodMachine *msm; /* See method state table */ msm = find_method_machine(sm, e->handle); handle_method_event(sm, msm, current_event, pdu); }, CONNECTED) ROW(CONNECTED, TR_Abort_Ind, e->handle != sm->connect_handle && e->ir_flag == INITIATOR_INDICATION, { WSPPushMachine *m; /* See push state table */ m = find_push_machine(sm, e->handle); handle_push_event(sm, m, current_event); }, CONNECTED) /* MISSING: SUSPENDED, S-Disconnect.req */ ROW(SUSPENDED, Disconnect_Event, 1, { /* S-Disconnect.ind(DISCONNECT) */ indicate_disconnect(sm, WSP_ABORT_DISCONNECT); }, NULL_SESSION) ROW(SUSPENDED, TR_Invoke_Ind, e->tcl == 2 && (pdu->type == Get || pdu->type == Post), { /* TR-Abort.req(SUSPEND) the TR-Invoke */ send_abort(WSP_ABORT_SUSPEND, e->handle); }, SUSPENDED) ROW(SUSPENDED, TR_Invoke_Ind, e->tcl == 2 && pdu->type == Resume, { WAPEvent *wtp_event; List *new_headers; /* TR-Invoke.res */ wtp_event = wap_event_create(TR_Invoke_Res); wtp_event->u.TR_Invoke_Res.handle = e->handle; dispatch_to_wtp_resp(wtp_event); /* S-Resume.ind */ new_headers = unpack_new_headers(sm, pdu->u.Resume.headers); indicate_resume(sm, e->addr_tuple, new_headers); http_destroy_headers(new_headers); sm->resume_handle = e->handle; }, RESUMING) ROW(SUSPENDED, TR_Invoke_Ind, e->tcl == 0 && pdu->type == Disconnect, { /* S-Disconnect.ind(DISCONNECT) */ indicate_disconnect(sm, WSP_ABORT_DISCONNECT); }, NULL_SESSION) /* MISSING: RESUMING, S-Disconnect.req */ ROW(RESUMING, Disconnect_Event, 1, { /* TR-Abort.req(DISCONNECT) the Resume transaction */ send_abort(WSP_ABORT_DISCONNECT, sm->resume_handle); /* Abort(DISCONNECT) all method transactions */ abort_methods(sm, WSP_ABORT_DISCONNECT); /* S-Disconnect.ind(DISCONNECT) */ indicate_disconnect(sm, WSP_ABORT_DISCONNECT); }, NULL_SESSION) ROW(RESUMING, S_Resume_Res, 1, { WAPEvent *wtp_event; Octstr *ospdu; /* Disconnect any other session for the peer address quadruplet */ disconnect_other_sessions(sm); /* Bind session to new peer address quadruplet */ /* this happens automatically XXX Not true */ /* TR-Result.req(Reply) */ if (e->server_headers == NULL) e->server_headers = http_create_empty_headers(); ospdu = make_resume_reply_pdu(sm, e->server_headers); wtp_event = wap_event_create(TR_Result_Req); wtp_event->u.TR_Result_Req.user_data = ospdu; wtp_event->u.TR_Result_Req.handle = sm->resume_handle; dispatch_to_wtp_resp(wtp_event); /* Release all method transactions in HOLDING state */ release_holding_methods(sm); }, RESUMING_2) ROW(RESUMING, Suspend_Event, 1, { /* TR-Abort.req(SUSPEND) the Resume transaction */ send_abort(WSP_ABORT_SUSPEND, sm->resume_handle); /* Abort(SUSPEND) all method transactions */ abort_methods(sm, WSP_ABORT_SUSPEND); /* S-Suspend.ind(SUSPEND) */ indicate_suspend(sm, WSP_ABORT_SUSPEND); }, SUSPENDED) ROW(RESUMING, TR_Invoke_Ind, e->tcl == 2 && (pdu->type == Get || pdu->type == Post), { /* Start new method transaction (see method state table) */ WSPMethodMachine *msm; msm = method_machine_create(sm, e->handle); handle_method_event(sm, msm, current_event, pdu); }, RESUMING) ROW(RESUMING, TR_Invoke_Ind, e->tcl == 2 && pdu->type == Resume, { WAPEvent *wtp_event; List *new_headers; /* TR-Invoke.res */ wtp_event = wap_event_create(TR_Invoke_Res); wtp_event->u.TR_Invoke_Res.handle = e->handle; dispatch_to_wtp_resp(wtp_event); /* TR-Abort.req(RESUME) the old Resume transaction */ send_abort(WSP_ABORT_RESUME, sm->resume_handle); /* Abort(RESUME) all method transactions */ abort_methods(sm, WSP_ABORT_RESUME); /* S-Suspend.ind(RESUME) */ indicate_suspend(sm, WSP_ABORT_RESUME); /* S-Resume.ind */ new_headers = unpack_new_headers(sm, pdu->u.Resume.headers); indicate_resume(sm, e->addr_tuple, new_headers); http_destroy_headers(new_headers); sm->resume_handle = e->handle; }, RESUMING) ROW(RESUMING, TR_Invoke_Ind, e->tcl == 0 && pdu->type == Suspend, { /* TR-Abort.req(SUSPEND) the Resume transaction */ send_abort(WSP_ABORT_SUSPEND, sm->resume_handle); /* Abort(SUSPEND) all method transactions */ abort_methods(sm, WSP_ABORT_SUSPEND); /* S-Suspend.ind(SUSPEND) */ indicate_suspend(sm, WSP_ABORT_SUSPEND); }, SUSPENDED) ROW(RESUMING, TR_Invoke_Ind, e->tcl == 0 && pdu->type == Disconnect, { /* TR-Abort.req(DISCONNECT) the Resume transaction */ send_abort(WSP_ABORT_DISCONNECT, sm->resume_handle); /* Abort(DISCONNECT) all method transactions */ abort_methods(sm, WSP_ABORT_DISCONNECT); /* S-Disconnect.ind(DISCONNECT) */ indicate_disconnect(sm, WSP_ABORT_DISCONNECT); }, NULL_SESSION) ROW(RESUMING, TR_Abort_Ind, e->handle == sm->resume_handle, { /* Abort(SUSPEND) all method transactions */ abort_methods(sm, WSP_ABORT_SUSPEND); /* S-Suspend.ind(abort reason) */ indicate_suspend(sm, e->abort_code); }, SUSPENDED) /* MISSING: RESUMING_2, S-Disconnect.req */ ROW(RESUMING_2, Disconnect_Event, 1, { /* TR-Abort.req(DISCONNECT) the Resume */ send_abort(WSP_ABORT_DISCONNECT, sm->resume_handle); /* Abort(DISCONNECT) all method and push transactions */ abort_methods(sm, WSP_ABORT_DISCONNECT); /* S-Disconnect.ind(DISCONNECT) */ indicate_disconnect(sm, WSP_ABORT_DISCONNECT); }, NULL_SESSION) ROW(RESUMING_2, S_MethodInvoke_Res, 1, { WSPMethodMachine *msm; /* See method state table */ msm = find_method_machine(sm, e->server_transaction_id); handle_method_event(sm, msm, current_event, pdu); }, RESUMING_2) ROW(RESUMING_2, S_MethodResult_Req, 1, { WSPMethodMachine *msm; /* See method state table */ msm = find_method_machine(sm, e->server_transaction_id); handle_method_event(sm, msm, current_event, pdu); }, RESUMING_2) ROW(RESUMING_2, S_Push_Req, 1, { WSP_PDU *pdu; pdu = make_push_pdu(current_event); send_invoke(sm, pdu, current_event, TRANSACTION_CLASS_0); }, RESUMING_2) ROW(RESUMING_2, S_ConfirmedPush_Req, 1, { /* Start new push transaction*/ WSPPushMachine *spm; spm = push_machine_create(sm, e->server_push_id); handle_push_event(sm, spm, current_event); }, RESUMING_2) ROW(RESUMING_2, Suspend_Event, 1, { /* TR-Abort.req(SUSPEND) the Resume transaction */ send_abort(WSP_ABORT_SUSPEND, sm->resume_handle); /* Abort(SUSPEND) all method and push transactions */ abort_methods(sm, WSP_ABORT_SUSPEND); /* S-Suspend.ind(SUSPEND) */ indicate_suspend(sm, WSP_ABORT_SUSPEND); }, SUSPENDED) ROW(RESUMING_2, TR_Invoke_Ind, e->tcl == 2 && (pdu->type == Get || pdu->type == Post), { WSPMethodMachine *msm; WAPEvent *new_event; /* Start new method transaction (see method state table) */ msm = method_machine_create(sm, e->handle); handle_method_event(sm, msm, current_event, pdu); /* Release the new method transaction */ new_event = wap_event_create(Release_Event); handle_method_event(sm, msm, new_event, NULL); wap_event_destroy(new_event); }, RESUMING_2) ROW(RESUMING_2, TR_Invoke_Ind, e->tcl == 2 && pdu->type == Resume, { WAPEvent *wtp_event; List *new_headers; /* TR-Invoke.res */ wtp_event = wap_event_create(TR_Invoke_Res); wtp_event->u.TR_Invoke_Res.handle = e->handle; dispatch_to_wtp_resp(wtp_event); /* TR-Abort.req(RESUME) the old Resume transaction*/ send_abort(WSP_ABORT_RESUME, sm->resume_handle); /* Abort(RESUME) all method and push transactions */ abort_methods(sm, WSP_ABORT_RESUME); /* S-Suspend.ind(RESUME) */ indicate_suspend(sm, WSP_ABORT_RESUME); /* S-Resume.ind */ new_headers = unpack_new_headers(sm, pdu->u.Resume.headers); indicate_resume(sm, e->addr_tuple, new_headers); http_destroy_headers(new_headers); sm->resume_handle = e->handle; }, RESUMING) ROW(RESUMING_2, TR_Invoke_Ind, e->tcl == 0 && pdu->type == Suspend, { /* TR-Abort.req(SUSPEND) the Resume transaction */ send_abort(WSP_ABORT_SUSPEND, sm->resume_handle); /* Abort(SUSPEND) all method and push transactions */ abort_methods(sm, WSP_ABORT_SUSPEND); /* S-Suspend.ind(SUSPEND) */ indicate_suspend(sm, WSP_ABORT_SUSPEND); }, SUSPENDED) ROW(RESUMING_2, TR_Invoke_Ind, e->tcl == 0 && pdu->type == Disconnect, { /* TR-Abort.req(DISCONNECT) the Resume */ send_abort(WSP_ABORT_DISCONNECT, sm->resume_handle); /* Abort(DISCONNECT) all method and push transactions */ abort_methods(sm, WSP_ABORT_DISCONNECT); /* S-Disconnect.ind(DISCONNECT) */ indicate_disconnect(sm, WSP_ABORT_DISCONNECT); }, NULL_SESSION) ROW(RESUMING_2, TR_Invoke_Cnf, 1, { /* See push state table*/ WSPPushMachine *spm; spm = find_push_machine(sm, e->handle); handle_push_event(sm, spm, current_event); }, RESUMING_2) ROW(RESUMING_2, TR_Result_Cnf, e->handle == sm->resume_handle, { }, CONNECTED) ROW(RESUMING_2, TR_Result_Cnf, e->handle != sm->resume_handle, { WSPMethodMachine *msm; /* See method state table */ msm = find_method_machine(sm, e->handle); handle_method_event(sm, msm, current_event, pdu); }, RESUMING_2) ROW(RESUMING_2, TR_Abort_Ind, e->handle == sm->resume_handle, { /* Abort(SUSPEND) all method and push transactions */ abort_methods(sm, WSP_ABORT_SUSPEND); /* S-Suspend.ind(abort reason) */ indicate_suspend(sm, e->abort_code); }, SUSPENDED) /* * A separate flag tells is the indicator the initiator or the responder */ ROW(RESUMING_2, TR_Abort_Ind, e->handle != sm->resume_handle && e->ir_flag == RESPONDER_INDICATION, { WSPMethodMachine *msm; /* See method state table */ msm = find_method_machine(sm, e->handle); handle_method_event(sm, msm, current_event, pdu); }, RESUMING_2) ROW(CONNECTING_2, TR_Abort_Ind, e->handle != sm->connect_handle && e->ir_flag == INITIATOR_INDICATION, { WSPPushMachine *m; /* See push state table */ m = find_push_machine(sm, e->handle); handle_push_event(sm, m, current_event); }, CONNECTING_2) #undef ROW #undef STATE_NAME