wsp_client_session.c
来自「mms client」· C语言 代码 · 共 1,077 行 · 第 1/3 页
C
1,077 行
/* * wsp_session.c - Implement WSP session oriented service * * Lars Wirzenius */#include <string.h>#include <limits.h>#include "gwlib/gwlib.h"#include "wsp.h"#include "wsp_pdu.h"#include "wsp_headers.h"#include "wsp_caps.h"#include "wsp_strings.h"#include "cookies.h"#include "wap.h"#include "wtp.h"typedef enum {#define STATE_NAME(name) name,#define ROW(state, event, condition, action, next_state)#include "wsp_client_session_states.def"#define STATE_NAME(name) name,#define ROW(state, event, condition, action, next_state)#include "wsp_client_method_states.def"#define STATE_NAME(name) name,#define ROW(state, event, condition, action, next_state)#include "wsp_client_push_states.def" WSPState_count} WSPState;/* * Give the status the module: * * limbo * not running at all * running * operating normally * terminating * waiting for operations to terminate, returning to limbo */static enum { limbo, running, terminating} run_status = limbo;static wap_dispatch_func_t *dispatch_to_wtp_init;static wap_dispatch_func_t *dispatch_to_wtp_init;static wap_dispatch_func_t *dispatch_to_appl;/* * True iff "Session resume facility" is enabled. This means we are * willing to let sessions go to SUSPENDED state, and later resume them. * Currently we always support it, but this may become configurable * at some point. */static int resume_enabled = 1;static List *queue = NULL;static List *session_machines = NULL;static Counter *client_push_id_counter = NULL;static WSPClientMachine *find_session_machine(WAPEvent *event);static void handle_session_event(WSPClientMachine *sm, WAPEvent *current_event, WSP_PDU *pdu);static void cant_handle_event(WSPClientMachine *sm, WAPEvent *event);static WSPClientMachine *machine_create(void);static void destroy_methodmachines(List *machines);static void destroy_pushmachines(List *machines);static void machine_destroy(void *pp);static void handle_method_event(WSPClientMachine *sm, WSPClientMethodMachine *msm, WAPEvent *current_event, WSP_PDU *pdu);static WSPClientMethodMachine *method_machine_create(WSPClientMachine *sm, long wtp_handle);static void method_machine_destroy(void *p);static WSPClientPushMachine *client_push_machine_create(WSPClientMachine *sm);static void push_machine_destroy(void *p);static char *state_name(WSPState state);static Octstr *make_connect_pdu(WSPClientMachine *m);static Octstr *make_disconnect_pdu(WSPClientMachine *m);static Octstr *make_get_pdu(List *httpHeaders, Octstr *uri);static Octstr *make_post_pdu(List *httpHeaders, Octstr *uri, Octstr *data);static Octstr *make_suspend_pdu(WSPClientMachine *m);static Octstr *make_resume_pdu(List *caps, List *headers);static int transaction_belongs_to_session(void *wsp_ptr, void *tuple_ptr);static int find_by_session_handle(void *wsp_ptr, void *id_ptr);static int find_by_method_id(void *wspm_ptr, void *id_ptr);static int find_by_push_id(void *m_ptr, void *id_ptr);static WSPClientMethodMachine *find_client_method_machine(WSPClientMachine *sm, long id);static WSPClientPushMachine *find_push_machine(WSPClientMachine *m, long id);static int same_client(void *a, void *b);static void disconnect_other_sessions(WSPClientMachine *sm);static List *unpack_new_headers(WSPClientMachine *sm, Octstr *hdrs);static WAPEvent *make_abort(long reason, long handle);static void send_abort(long reason, long handle);static void sendResultResponse(long handle);static void sendResultDataResponse(long handle);static void send_invoke(WSPClientMachine *m, Octstr *pdu, long handle, long acknowledgement, long class);static void indicate_disconnect(WSPClientMachine *sm, long reason);static void indicate_suspend(WSPClientMachine *sm, long reason);static void indicate_resume(WSPClientMachine *sm, WAPAddrTuple *tuple, List *headers);static void indicate_push(WSPClientMachine *sm, WSP_PDU *pdu);static void indicate_pushabort(WSPClientPushMachine *spm, long reason);static void indicate_confirmedpush(WSPClientMachine *sm, WSP_PDU *pdu, long client_push_id);static void confirm_connect(WSPClientMachine *sm, List *httpHeaders, List *caps);static void confirm_resume(WSPClientMachine *sm, List *httpHeaders);static void confirm_methodinvoke(WSPClientMethodMachine *msm);static void confirm_push(WSPClientPushMachine *m);static void method_abort(WSPClientMethodMachine *msm, long reason);static void indicate_method_result(WSPClientMethodMachine *msm, List *headers, Octstr *body, long status);static void indicate_method_abort(WSPClientMethodMachine *msm, long reason);static int method_is_holding(void *item, void *pattern);static void release_holding_methods(WSPClientMachine *sm);static void abort_methods(WSPClientMachine *sm, long reason);static void abort_method(WSPClientMachine *sm, long handle, long reason);static void abort_pushes(WSPClientMachine *sm, long reason);static void handle_push_event(WSPClientMachine *sm, WSPClientPushMachine *pm, WAPEvent *current_event, WSP_PDU *pdu);static void main_thread(void *);static int id_belongs_to_session (void *, void *);/*********************************************************************** * Public functions. */void wsp_client_session_init(wap_dispatch_func_t *initiator_dispatch, wap_dispatch_func_t *application_dispatch) { queue = list_create(); list_add_producer(queue); session_machines = list_create(); client_push_id_counter = counter_create(); dispatch_to_wtp_init = initiator_dispatch; dispatch_to_appl = application_dispatch; wsp_strings_init(); run_status = running; gwthread_create(main_thread, NULL);}void wsp_client_session_shutdown(void) { gw_assert(run_status == running); run_status = terminating; list_remove_producer(queue); counter_destroy(client_push_id_counter); gwthread_join_every(main_thread); list_destroy(queue, wap_event_destroy_item); debug("wap.wsp", 0, "WSP: %ld session machines left.", list_len(session_machines)); list_destroy(session_machines, machine_destroy); wsp_strings_shutdown();}void wsp_client_session_dispatch_event(WAPEvent *event) { wap_event_assert(event); list_produce(queue, event);}/*********************************************************************** * Local functions */static void main_thread(void *arg) { WAPEvent *e; WSPClientMachine *sm; WSP_PDU *pdu; while (run_status == running && (e = list_consume(queue)) != NULL) { wap_event_assert(e); /* the content of the following WTP primitives sometimes needs to be inspected */ switch (e->type) { case TR_Invoke_Ind: pdu = wsp_pdu_unpack(e->u.TR_Invoke_Ind.user_data); if (pdu == NULL) { warning(0, "WSP: Broken PDU ignored."); wap_event_destroy(e); continue; } break; case TR_Result_Ind: pdu = wsp_pdu_unpack(e->u.TR_Result_Ind.user_data); if (pdu == NULL) { warning(0, "WSP: Broken PDU ignored."); wap_event_destroy(e); continue; } break; default: pdu = NULL; break; } sm = find_session_machine(e); if (sm == NULL) { wap_event_destroy(e); } else { handle_session_event(sm, e, pdu); } wsp_pdu_destroy(pdu); }}static WSPClientMachine *find_session_machine(WAPEvent *event) { WSPClientMachine *sm; long session_handle; WAPAddrTuple *tuple; tuple = NULL; session_handle = -1; switch (event->type) { case TR_Invoke_Ind: tuple = wap_addr_tuple_duplicate(event->u.TR_Invoke_Ind.addr_tuple); break; case TR_Invoke_Cnf: tuple = wap_addr_tuple_duplicate(event->u.TR_Invoke_Cnf.addr_tuple); break; case TR_Result_Cnf: tuple = wap_addr_tuple_duplicate(event->u.TR_Result_Cnf.addr_tuple); break; case TR_Abort_Ind: tuple = wap_addr_tuple_duplicate(event->u.TR_Abort_Ind.addr_tuple); break; /* linking address tuple to WTP handle */ case TR_Invoke_Req: tuple = wap_addr_tuple_duplicate(event->u.TR_Invoke_Req.addr_tuple); break; case TR_Result_Ind: tuple = wap_addr_tuple_duplicate(event->u.TR_Result_Ind.addr_tuple); break; case Disconnect_Event: session_handle = event->u.Disconnect_Event.session_handle; break; case Suspend_Event: session_handle = event->u.Suspend_Event.session_handle; break; case S_Connect_Req: tuple = wap_addr_tuple_duplicate(event->u.S_Connect_Req.addr_tuple); break; case S_Disconnect_Req: session_handle = event->u.S_Disconnect_Req.session_handle; break; case S_MethodInvoke_Req: session_handle = event->u.S_MethodInvoke_Req.session_handle; break; case S_MethodAbort_Req: session_handle = event->u.S_MethodAbort_Req.session_handle; break; case S_Connect_Res: session_handle = event->u.S_Connect_Res.session_id; break; case S_MethodResult_Res: session_handle = event->u.S_MethodResult_Res.session_handle; break; case S_Suspend_Req: session_handle = event->u.S_Suspend_Req.session_handle; break; case S_Resume_Req: session_handle = event->u.S_Resume_Req.session_handle; break; case S_ConfirmedPush_Res: session_handle = event->u.S_ConfirmedPush_Res.session_handle; break; case S_PushAbort_Req: session_handle = event->u.S_PushAbort_Req.session_handle; break; default: error(0, "WSP: Cannot find machine for %s event", wap_event_name(event->type)); } gw_assert(tuple != NULL || session_handle != -1); sm = NULL; if (session_handle != -1) { sm = list_search(session_machines, &session_handle, find_by_session_handle); } else { sm = list_search(session_machines, tuple, transaction_belongs_to_session); } if (sm != NULL && event->type == S_Connect_Req) { /* need to disonnect that session */ disconnect_other_sessions(sm); sm = NULL; } if (sm == NULL && event->type == S_Connect_Req) { /* need a new state machine */ sm = machine_create(); sm->request_caps = wsp_cap_duplicate_list(event->u.S_Connect_Req.requested_capabilities); sm->http_headers = http_header_duplicate(event->u.S_Connect_Req.client_headers); sm->addr_tuple = tuple; sm->session_handle = event->u.S_Connect_Req.session_handle; } else wap_addr_tuple_destroy(tuple); return sm;}static void handle_session_event(WSPClientMachine *sm, WAPEvent *current_event, WSP_PDU *pdu) { debug("wap.wsp", 0, "WSP: machine %p, state %s, event %s", (void *) sm, state_name(sm->state), wap_event_name(current_event->type));#define STATE_NAME(name)#define ROW(state_name, event, condition, action, next_state) \ { \ struct event *e; \ e = ¤t_event->u.event; \ if (sm->state == state_name && \ current_event->type == event && \ (condition)) { \ action \ sm->state = next_state; \ debug("wap.wsp", 0, "WSP %ld: New state %s", \ sm->session_handle, #next_state); \ goto end; \ } \ }#include "wsp_client_session_states.def" cant_handle_event(sm, current_event); end: wap_event_destroy(current_event); if (sm->state == NULL_SESSION) machine_destroy(sm);}static void cant_handle_event(WSPClientMachine *sm, WAPEvent *event) { /* We do the rest of the pre-state-machine tests here. The first * four were done in find_session_machine(). The fifth is a * class 1 or 2 TR-Invoke.ind not handled by the state tables. */ if (event->type == TR_Invoke_Ind && (event->u.TR_Invoke_Ind.tcl == 1 ||
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?