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 = &current_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 + -
显示快捷键?