📄 wtp.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 + -