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

📄 wtp.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.   */ /* * wtp.c - WTP common functions implementation * * Aarno Syv鋘en * Lars Wirzenius */#include "wtp.h" #include "wap_events.h"#include "wtp_pdu.h"/***************************************************************************** * * Prototypes of internal functions: * * Parse a datagram event (T-DUnitdata.ind) to create a corresponding * WTPEvents list object. Also check that the datagram is syntactically * valid. Return a pointer to the event structure that has been created. * This will be a RcvError packet if there was a problem unpacking the * datagram. */static WAPEvent *unpack_wdp_datagram_real(WAPEvent *datagram);static int deduce_tid(Octstr *user_data);static int concatenated_message(Octstr *user_data);static int truncated_datagram(WAPEvent *event);static WAPEvent *unpack_invoke(WTP_PDU *pdu, WAPAddrTuple *addr_tuple);static WAPEvent *unpack_segmented_invoke(WTP_PDU *pdu, WAPAddrTuple *addr_tuple);static WAPEvent *unpack_result(WTP_PDU *pdu, WAPAddrTuple *addr_tuple);static WAPEvent *unpack_ack(WTP_PDU *pdu, WAPAddrTuple *addr_tuple);static WAPEvent *unpack_negative_ack(WTP_PDU *pdu, WAPAddrTuple *addr_tuple);static WAPEvent *unpack_abort(WTP_PDU *pdu, WAPAddrTuple *addr_tuple);static WAPEvent *pack_error(WAPEvent *datagram);/****************************************************************************** * * EXTERNAL FUNCTIONS: * * Handles a possible concatenated message. Creates a list of wap events. */List *wtp_unpack_wdp_datagram(WAPEvent *datagram){     List *events = NULL;     WAPEvent *event = NULL;     WAPEvent *subdgram = NULL;     Octstr *data = NULL;     long pdu_len;     gw_assert(datagram->type == T_DUnitdata_Ind);     events = list_create();             if (concatenated_message(datagram->u.T_DUnitdata_Ind.user_data)) {         data = octstr_duplicate(datagram->u.T_DUnitdata_Ind.user_data);	 octstr_delete(data, 0, 1);         while (octstr_len(data) != 0) {	     if (octstr_get_bits(data, 0, 1) == 0) {	         pdu_len = octstr_get_char(data, 0);                 octstr_delete(data, 0, 1);             } else {		    pdu_len = octstr_get_bits(data, 1, 15);                    octstr_delete(data, 0, 2);             }      	     subdgram = wap_event_duplicate(datagram);	     octstr_destroy(subdgram->u.T_DUnitdata_Ind.user_data);             subdgram->u.T_DUnitdata_Ind.user_data =	          octstr_copy(data, 0, pdu_len);             wap_event_assert(subdgram);             event = unpack_wdp_datagram_real(subdgram);             wap_event_assert(event);             list_append(events, event);             octstr_delete(data, 0, pdu_len);             wap_event_destroy(subdgram);         }     octstr_destroy(data);     } else {          event = unpack_wdp_datagram_real(datagram);           wap_event_assert(event);          list_append(events, event);     }      return events;}/* * Responder set the first bit of the tid field. If we get a packet from the  * responder, we are the initiator and vice versa. * * Return 1, when the event is for responder, 0 when it is for initiator and  * -1 when error. */int wtp_event_is_for_responder(WAPEvent *event){     switch(event->type){               case RcvInvoke:         return event->u.RcvInvoke.tid < INITIATOR_TID_LIMIT;     case RcvSegInvoke:        return event->u.RcvSegInvoke.tid < INITIATOR_TID_LIMIT;     case RcvResult:         return event->u.RcvResult.tid < INITIATOR_TID_LIMIT;     case RcvAck:        return event->u.RcvAck.tid < INITIATOR_TID_LIMIT;     case RcvNegativeAck:        return event->u.RcvNegativeAck.tid < INITIATOR_TID_LIMIT;     case RcvAbort:        return event->u.RcvAbort.tid < INITIATOR_TID_LIMIT;     case RcvErrorPDU:        return event->u.RcvErrorPDU.tid < INITIATOR_TID_LIMIT;     default:        error(1, "Received an erroneous PDU corresponding an event");        wap_event_dump(event);        return -1;     }}/***************************************************************************** * * INTERNAL FUNCTIONS: * * If pdu was truncated, tid cannot be trusted. We ignore this message. */static int truncated_datagram(WAPEvent *dgram){    gw_assert(dgram->type == T_DUnitdata_Ind);    if (octstr_len(dgram->u.T_DUnitdata_Ind.user_data) < 3) {        debug("wap.wtp", 0, "A too short PDU received");        wap_event_dump(dgram);        return 1;    } else        return 0;}static WAPEvent *unpack_invoke(WTP_PDU *pdu, WAPAddrTuple *addr_tuple){    WAPEvent *event;    event = wap_event_create(RcvInvoke);    event->u.RcvInvoke.user_data =         octstr_duplicate(pdu->u.Invoke.user_data);    event->u.RcvInvoke.tcl = pdu->u.Invoke.class;    event->u.RcvInvoke.tid = pdu->u.Invoke.tid;    event->u.RcvInvoke.tid_new = pdu->u.Invoke.tidnew;    event->u.RcvInvoke.rid = pdu->u.Invoke.rid;    event->u.RcvInvoke.up_flag = pdu->u.Invoke.uack;    event->u.RcvInvoke.no_cache_supported = 0;    event->u.RcvInvoke.version = pdu->u.Invoke.version;    event->u.RcvInvoke.gtr = pdu->u.Invoke.gtr;    event->u.RcvInvoke.ttr = pdu->u.Invoke.ttr;    event->u.RcvInvoke.addr_tuple = wap_addr_tuple_duplicate(addr_tuple);    return event;}static WAPEvent *unpack_segmented_invoke(WTP_PDU *pdu, WAPAddrTuple *addr_tuple){    WAPEvent *event;    event = wap_event_create(RcvSegInvoke);    event->u.RcvSegInvoke.user_data =         octstr_duplicate(pdu->u.Segmented_invoke.user_data);    event->u.RcvSegInvoke.tid = pdu->u.Segmented_invoke.tid;    event->u.RcvSegInvoke.rid = pdu->u.Segmented_invoke.rid;    event->u.RcvSegInvoke.no_cache_supported = 0;    event->u.RcvSegInvoke.gtr = pdu->u.Segmented_invoke.gtr;    event->u.RcvSegInvoke.ttr = pdu->u.Segmented_invoke.ttr;    event->u.RcvSegInvoke.psn = pdu->u.Segmented_invoke.psn;    event->u.RcvSegInvoke.addr_tuple = wap_addr_tuple_duplicate(addr_tuple);    return event;}static WAPEvent *unpack_result(WTP_PDU *pdu, WAPAddrTuple *addr_tuple){    WAPEvent *event;    event = wap_event_create(RcvResult);    event->u.RcvResult.user_data =         octstr_duplicate(pdu->u.Result.user_data);    event->u.RcvResult.tid = pdu->u.Result.tid;    event->u.RcvResult.rid = pdu->u.Result.rid;    event->u.RcvResult.gtr = pdu->u.Result.gtr;    event->u.RcvResult.ttr = pdu->u.Result.ttr;    event->u.RcvResult.addr_tuple = wap_addr_tuple_duplicate(addr_tuple);    return event;}static WAPEvent *unpack_ack(WTP_PDU *pdu, WAPAddrTuple *addr_tuple){    WAPEvent *event;    WTP_TPI *tpi;    int	i, num_tpis;    event = wap_event_create(RcvAck);    event->u.RcvAck.tid = pdu->u.Ack.tid;    event->u.RcvAck.tid_ok = pdu->u.Ack.tidverify;    event->u.RcvAck.rid = pdu->u.Ack.rid;    event->u.RcvAck.addr_tuple = wap_addr_tuple_duplicate(addr_tuple);    /* Set default to 0 because Ack on 1 piece message has no tpi */    event->u.RcvAck.psn = 0;    num_tpis = list_len(pdu->options);    for (i = 0; i < num_tpis; i++) {        tpi = list_get(pdu->options, i);        if (tpi->type == TPI_PSN) {            event->u.RcvAck.psn = octstr_get_bits(tpi->data,0,8);            break;        }    }    return event;}static WAPEvent *unpack_negative_ack(WTP_PDU *pdu, WAPAddrTuple *addr_tuple){    WAPEvent *event;    event = wap_event_create(RcvNegativeAck);    event->u.RcvNegativeAck.tid = pdu->u.Negative_ack.tid;    event->u.RcvNegativeAck.rid = pdu->u.Negative_ack.rid;    event->u.RcvNegativeAck.nmissing = pdu->u.Negative_ack.nmissing;    event->u.RcvNegativeAck.missing = octstr_duplicate(pdu->u.Negative_ack.missing);    event->u.RcvNegativeAck.addr_tuple = wap_addr_tuple_duplicate(addr_tuple);        return event;}static WAPEvent *unpack_abort(WTP_PDU *pdu, WAPAddrTuple *addr_tuple){     WAPEvent *event;     event = wap_event_create(RcvAbort);     event->u.RcvAbort.tid = pdu->u.Abort.tid;     event->u.RcvAbort.abort_type = pdu->u.Abort.abort_type;     event->u.RcvAbort.abort_reason = pdu->u.Abort.abort_reason;     event->u.RcvAbort.addr_tuple = wap_addr_tuple_duplicate(addr_tuple);     return event;}static WAPEvent *pack_error(WAPEvent *datagram){    WAPEvent *event;    gw_assert(datagram->type == T_DUnitdata_Ind);    event = wap_event_create(RcvErrorPDU);    event->u.RcvErrorPDU.tid = deduce_tid(datagram->u.T_DUnitdata_Ind.user_data);    event->u.RcvErrorPDU.addr_tuple = 	wap_addr_tuple_duplicate(datagram->u.T_DUnitdata_Ind.addr_tuple);    return event;}/* * Transfers data from fields of a message to fields of WTP event. User data  * has the host byte order. Updates the log.  * * This function does incoming events check nro 4 (checking illegal headers * WTP 10.2). * * Return event, when we have a partially correct message or the message  * received has illegal header (WTP 10.2 nro 4); NULL, when the message was  * truncated or unpacking function returned NULL. */WAPEvent *unpack_wdp_datagram_real(WAPEvent *datagram){    WTP_PDU *pdu;    WAPEvent *event;    Octstr *data;    gw_assert(datagram->type == T_DUnitdata_Ind);    data = datagram->u.T_DUnitdata_Ind.user_data;    if (truncated_datagram(datagram)) {        warning(0, "WTP: got a truncated datagram, ignoring");	return NULL;    }    pdu = wtp_pdu_unpack(data);/* * Wtp_pdu_unpack returned NULL, we build a rcv error event.  */    if (pdu == NULL) {        error(0, "WTP: cannot unpack pdu, creating an error pdu");        event = pack_error(datagram);        return event;    }   		    event = NULL;    switch (pdu->type) {    case Invoke:        event = unpack_invoke(pdu, datagram->u.T_DUnitdata_Ind.addr_tuple);        /* if an WTP initiator gets invoke, it would be an illegal pdu. */        if (!wtp_event_is_for_responder(event)){            debug("wap.wtp", 0, "WTP: Invoke when initiator. Message was");            wap_event_destroy(event);            event = pack_error(datagram);        }        break;    case Segmented_invoke:        event = unpack_segmented_invoke(pdu, datagram->u.T_DUnitdata_Ind.addr_tuple);        break;    case Result:        event = unpack_result(pdu, datagram->u.T_DUnitdata_Ind.addr_tuple);        /* if an WTP responder gets result, it would be an illegal pdu. */        if (wtp_event_is_for_responder(event)){            debug("wap.wtp", 0, "WTP: Result when responder. Message was");            wap_event_destroy(event);            event = pack_error(datagram);        }        break;    case Ack:	    event = unpack_ack(pdu, datagram->u.T_DUnitdata_Ind.addr_tuple);            break;    case Negative_ack:        event = unpack_negative_ack(pdu, datagram->u.T_DUnitdata_Ind.addr_tuple);            break;	case Abort:	    event = unpack_abort(pdu, datagram->u.T_DUnitdata_Ind.addr_tuple);        break;         	default:	    event = pack_error(datagram);	    debug("wap.wtp", 0, "WTP: Unhandled PDU type. Message was");            wap_event_dump(datagram);	    return event;	}    wtp_pdu_destroy(pdu);	    wap_event_assert(event);    return event;}/* * Used for debugging and when wtp unpack does not return a tid. We include * first bit; it tells does message received belong to the initiator or to the * responder. */static int deduce_tid(Octstr *user_data){     return octstr_get_bits(user_data, 8, 16);}static int concatenated_message(Octstr *user_data){       return octstr_get_char(user_data, 0) == 0x00;}

⌨️ 快捷键说明

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