⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 wsp_push_client.c

📁 The Kannel Open Source WAP and SMS gateway works as both an SMS gateway, for implementing keyword b
💻 C
字号:
/* ====================================================================  * The Kannel Software License, Version 1.0  *  * Copyright (c) 2001-2004 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 <http://www.kannel.org/>.  *  * Portions of this software are based upon software originally written at   * WapIT Ltd., Helsinki, Finland for the Kannel project.   */ /* * wsp_push_client.c: Client WSP Push implementation, for testing purposes * * Aarno Syv鋘en for Wapit Ltd */#include "wsp_push_client.h"#include "wsp.h"#include "wtp.h"#include "wsp_pdu.h"#include "wsp_headers.h"#include "wap.h"/************************************************************************** *  * Internal data structures: * * List of client WSP push machines. */static List *push_client_machines = NULL;/* * Counter for client push machine id numbers, to make sure that they are  * unique. */static Counter *push_client_machine_id_counter = NULL;/* * Give the status of push client: * *	limbo *		not running at all *	running *		operating normally *	terminating *		waiting for operations to terminate, returning to limbo */static enum {limbo, running, terminating } push_client_run_status = limbo;/* * Queue of events to be handled by the push client. */static List *push_client_queue = NULL;wap_dispatch_func_t *dispatch_to_self;wap_dispatch_func_t *dispatch_to_wtp_resp;/***************************************************************************** * * Prototypes of internal functions: * * Create and destroy an uniniatilised push client state machine. */static WSPPushClientMachine *push_client_machine_create(long cpid);static void push_client_machine_destroy(void *a);/* * Checks whether the client push machines list includes a specific machine. * Creates it, if the event is TR-Invoke.ind */static WSPPushClientMachine *push_client_machine_find_or_create(WAPEvent *e);/* * Feed an event to the client push state machine. Do not report errors to * caller. */static void push_client_event_handle(WSPPushClientMachine *cpm, WAPEvent *e);/* * Print WSP client push machine state as a string. */static unsigned char *name_push_client_state(int name);static void main_thread(void *);static WAPEvent *indicate_confirmedpush(WSPPushClientMachine *cpm,                                             Octstr *push_body);static WAPEvent *indicate_pushabort(WSPPushClientMachine *cpm,                                         long abort_reason);static WAPEvent *response_confirmedpush(WSPPushClientMachine *cpm);static WAPEvent *send_abort_to_responder(WSPPushClientMachine *cpm, long reason);static WAPEvent *response_responder_invoke(WSPPushClientMachine *cpm);/************************************************************************** * * EXTERNAL FUNCTIONS: * */void wsp_push_client_init(wap_dispatch_func_t *dispatch_self,                           wap_dispatch_func_t *dispatch_wtp_resp){    push_client_machines = list_create();    push_client_machine_id_counter = counter_create();    push_client_queue = list_create();    list_add_producer(push_client_queue);    dispatch_to_self = dispatch_self;    dispatch_to_wtp_resp = dispatch_wtp_resp;    gw_assert(push_client_run_status == limbo);    push_client_run_status = running;    gwthread_create(main_thread, NULL);}void wsp_push_client_shutdown(void){    gw_assert(push_client_run_status == running);    push_client_run_status = terminating;    list_remove_producer(push_client_queue);    gwthread_join_every(main_thread);    debug("wap.wsp", 0, "wsp_push_client_shutdown: %ld push client machines"          "left", list_len(push_client_machines));    list_destroy(push_client_machines, push_client_machine_destroy);    list_destroy(push_client_queue, wap_event_destroy_item);    counter_destroy(push_client_machine_id_counter);}void wsp_push_client_dispatch_event(WAPEvent *e){    list_produce(push_client_queue, e);}/*************************************************************************** * * INTERNAL FUNCTIONS: * */static void main_thread(void *arg){    WSPPushClientMachine *cpm;    WAPEvent *e;    while (push_client_run_status == running &&            (e = list_consume(push_client_queue)) != NULL) {         cpm = push_client_machine_find_or_create(e);         if (cpm == NULL)	     wap_event_destroy(e);         else	     push_client_event_handle(cpm, e);    }}/* * Give the name of a push client machine state in a readable form */static unsigned char *name_push_client_state(int n) {    switch (n) {    #define PUSH_CLIENT_STATE_NAME(state) case state : return #state;    #define ROW(state, event, condition, action, new_state)    #include "wsp_push_client_states.def"    default:        return "unknown state";    }}/* * Feed an event to a WSP push client state machine. Do not report errors to * the caller. */static void push_client_event_handle(WSPPushClientMachine *cpm,                                      WAPEvent *e){    WAPEvent *wtp_event;    WSP_PDU *pdu = NULL;    wap_event_assert(e);    gw_assert(cpm);        if (e->type == TR_Invoke_Ind) {        pdu = wsp_pdu_unpack(e->u.TR_Invoke_Ind.user_data);/* * Class 1 tests here * Case 4, no session matching address quadruplet, handled by the session mach- * ine. * Tests from table WSP, page 45. Case 5, a PDU state tables cannot handle. */        if (pdu == NULL || pdu->type != ConfirmedPush) {	    wap_event_destroy(e);            wtp_event = send_abort_to_responder(cpm, PROTOERR);            wtp_resp_dispatch_event(wtp_event);            return;        }    }    debug("wap.wsp", 0, "WSP_PUSH: WSPPushClientMachine %ld, state %s,"          " event %s",           cpm->client_push_id,          name_push_client_state(cpm->state),          wap_event_name(e->type));    #define PUSH_CLIENT_STATE_NAME(state)    #define ROW(push_state, event_type, condition, action, next_state) \         if (cpm->state == push_state && \             e->type == event_type && \             (condition)) { \             action \             cpm->state = next_state; \             debug("wap.wsp", 0, "WSP_PUSH %ld: new state %s", \                   cpm->client_push_id, #next_state); \         } else    #include "wsp_push_client_states.def"         {             error(0, "WSP_PUSH: handle_event: unhandled event!");             debug("wap.wsp", 0, "Unhandled event was:");             wap_event_dump(e);             wap_event_destroy(e);             return;         }    wsp_pdu_destroy(pdu);    wap_event_destroy(e);        if (cpm->state == PUSH_CLIENT_NULL_STATE)        push_client_machine_destroy(cpm);}static int push_client_machine_has_transid(void *a, void *b){    long transid;    WSPPushClientMachine *m;    m = a;    transid = *(long *)b;    return m->transaction_id == transid;   }static WSPPushClientMachine *push_client_machine_find_using_transid(           long transid){    WSPPushClientMachine *m;      m = list_search(push_client_machines, &transid,                     push_client_machine_has_transid);    return m;}/* * Checks client push machines list for a specific machine. Creates it, if the * event is TR-Invoke.ind. * Client push machine is identified (when searching) by transcation identifi- * er.  * Note that only WTP responder send its class 1 messages to client push state * machine. So, it is no need to specify WTP machine type.  */static WSPPushClientMachine *push_client_machine_find_or_create(WAPEvent *e){    WSPPushClientMachine *cpm;    long transid;    cpm = NULL;    transid = -1;       switch (e->type) {    case TR_Invoke_Ind:         transid = e->u.TR_Invoke_Ind.handle;    break;    case S_ConfirmedPush_Res:         transid = e->u.S_ConfirmedPush_Res.client_push_id;    break;    case S_PushAbort_Req:         transid = e->u.S_PushAbort_Req.push_id;    break;    case Abort_Event:    break;    case TR_Abort_Ind:         transid = e->u.TR_Abort_Ind.handle;    break;    default:        debug("wap.wsp", 0, "WSP PUSH: push_client_find_or_create: unhandled"	      " event");        wap_event_dump(e);        wap_event_destroy(e);        return NULL;    }    gw_assert(transid != -1);    cpm = push_client_machine_find_using_transid(transid);        if (cpm == NULL) {        switch (e->type) {        case TR_Invoke_Ind:	    cpm = push_client_machine_create(transid);	break;        case S_ConfirmedPush_Res:        case S_PushAbort_Req:	    error(0, "WSP_PUSH_CLIENT: POT primitive to a nonexisting"                  "  push client machine");	break;        case Abort_Event:	    error(0, "WSP_PUSH_CLIENT: internal abort to a nonexisting"                  " push client machine");	break;        case TR_Abort_Ind:	    error(0, "WSP_PUSH_CLIENT: WTP abort to a nonexisting push client"                  " machine");	break;	default:	    error(0, "WSP_PUSH_CLIENT: Cannot handle event type %s",		wap_event_name(e->type));	break;        }    }    return cpm;}static WSPPushClientMachine *push_client_machine_create(long transid){    WSPPushClientMachine *m;    m = gw_malloc(sizeof(WSPPushClientMachine));    debug("wap.wsp", 0, "WSP_PUSH_CLIENT: Created WSPPushClientMachine %p",          (void *) m);    #define INTEGER(name) m->name = 0;    #define HTTPHEADERS(name) m->name = NULL;    #define MACHINE(fields) fields    #include "wsp_push_client_machine.def"    m->state = PUSH_CLIENT_NULL_STATE;    m->transaction_id = transid;    m->client_push_id = counter_increase(push_client_machine_id_counter);    list_append(push_client_machines, m);    return m;}static void push_client_machine_destroy(void *a) {    WSPPushClientMachine *m;    m = a;    debug("wap.wsp", 0, "Destroying WSPPushClientMachine %p", (void *) m);    list_delete_equal(push_client_machines, m);     #define INTEGER(name) m->name = 0;    #define HTTPHEADERS(name) http_destroy_headers(m->name);      #define MACHINE(fields) fields;    #include "wsp_push_client_machine.def"    gw_free(m);}static WAPEvent *indicate_confirmedpush(WSPPushClientMachine *cpm,                                             Octstr *push_body){    WAPEvent *e;    e = wap_event_create(S_ConfirmedPush_Ind);    e->u.S_ConfirmedPush_Ind.client_push_id = cpm->client_push_id;    e->u.S_ConfirmedPush_Ind.push_headers =         http_header_duplicate(cpm->push_headers);    e->u.S_ConfirmedPush_Ind.push_body = octstr_duplicate(push_body);    return e;}static WAPEvent *indicate_pushabort(WSPPushClientMachine *cpm,                                         long abort_reason){    WAPEvent *e;    e = wap_event_create(S_PushAbort_Ind);    e->u.S_PushAbort_Ind.push_id = cpm->client_push_id;    e->u.S_PushAbort_Ind.reason = abort_reason;    return e;}/* * For debugging: create S-ConfirmedPush.res by ourselves.  */static WAPEvent *response_confirmedpush(WSPPushClientMachine *cpm){    WAPEvent *e;    e = wap_event_create(S_ConfirmedPush_Res);    e->u.S_ConfirmedPush_Res.client_push_id = cpm->client_push_id;    return e;}static WAPEvent *send_abort_to_responder(WSPPushClientMachine *cpm,                                          long reason){    WAPEvent *e;    e = wap_event_create(TR_Abort_Req);    e->u.TR_Abort_Req.abort_type = USER;    e->u.TR_Abort_Req.abort_reason = reason;    e->u.TR_Abort_Req.handle = cpm->client_push_id;    return e;}static WAPEvent *response_responder_invoke(WSPPushClientMachine *cpm){    WAPEvent *e;    e = wap_event_create(TR_Invoke_Res);    e->u.TR_Invoke_Res.handle = cpm->transaction_id;    return e;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -