Main Page | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals

wtp_tid.c

Go to the documentation of this file.
00001 /* ==================================================================== 
00002  * The Kannel Software License, Version 1.0 
00003  * 
00004  * Copyright (c) 2001-2008 Kannel Group  
00005  * Copyright (c) 1998-2001 WapIT Ltd.   
00006  * All rights reserved. 
00007  * 
00008  * Redistribution and use in source and binary forms, with or without 
00009  * modification, are permitted provided that the following conditions 
00010  * are met: 
00011  * 
00012  * 1. Redistributions of source code must retain the above copyright 
00013  *    notice, this list of conditions and the following disclaimer. 
00014  * 
00015  * 2. Redistributions in binary form must reproduce the above copyright 
00016  *    notice, this list of conditions and the following disclaimer in 
00017  *    the documentation and/or other materials provided with the 
00018  *    distribution. 
00019  * 
00020  * 3. The end-user documentation included with the redistribution, 
00021  *    if any, must include the following acknowledgment: 
00022  *       "This product includes software developed by the 
00023  *        Kannel Group (http://www.kannel.org/)." 
00024  *    Alternately, this acknowledgment may appear in the software itself, 
00025  *    if and wherever such third-party acknowledgments normally appear. 
00026  * 
00027  * 4. The names "Kannel" and "Kannel Group" must not be used to 
00028  *    endorse or promote products derived from this software without 
00029  *    prior written permission. For written permission, please  
00030  *    contact org@kannel.org. 
00031  * 
00032  * 5. Products derived from this software may not be called "Kannel", 
00033  *    nor may "Kannel" appear in their name, without prior written 
00034  *    permission of the Kannel Group. 
00035  * 
00036  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED 
00037  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 
00038  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
00039  * DISCLAIMED.  IN NO EVENT SHALL THE KANNEL GROUP OR ITS CONTRIBUTORS 
00040  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,  
00041  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT  
00042  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR  
00043  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,  
00044  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE  
00045  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,  
00046  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
00047  * ==================================================================== 
00048  * 
00049  * This software consists of voluntary contributions made by many 
00050  * individuals on behalf of the Kannel Group.  For more information on  
00051  * the Kannel Group, please see <http://www.kannel.org/>. 
00052  * 
00053  * Portions of this software are based upon software originally written at  
00054  * WapIT Ltd., Helsinki, Finland for the Kannel project.  
00055  */ 
00056 
00057 /*
00058  * wtp_tid.c - Implementation of WTP tid validation tests. Note that only 
00059  * WTP responder uses tid validation.
00060  *
00061  * By Aarno Syvänen for Wapit Ltd.
00062  */
00063 
00064 #include "gwlib/gwlib.h"
00065 #include "wtp_tid.h"
00066 
00067 /*
00068  * Constants used for defining the tid cache status
00069  */
00070 enum {
00071     no_cache = -1,
00072     iniatilised = -2,
00073     not_iniatilised = -3,
00074     cached = 0
00075 };
00076 
00077 /*
00078  * Global data structure:
00079  *
00080  * Tid cache is implemented by using a library object List
00081  */
00082  static List *tid_cache = NULL;   
00083 
00084 /*****************************************************************************
00085  * Prototypes of internal functions
00086  */
00087 static WTPCached_tid *cache_item_create_empty(void);
00088 static void cache_item_destroy(void *item);
00089 /*
00090 static void cache_item_dump(WTPCached_tid *item);
00091 */
00092 static void add_tid(WTPRespMachine *resp_machine, long tid);
00093 static void set_tid_by_item(WTPCached_tid *item, long tid);
00094 static int tid_in_window(long rcv_tid, long last_tid);
00095 static WTPCached_tid *tid_cached(WTPRespMachine *resp_machine);
00096 
00097 /******************************************************************************
00098  *
00099  * External functions:
00100  */
00101 
00102 void wtp_tid_cache_init(void) 
00103 {
00104     tid_cache = gwlist_create();
00105 }
00106 
00107 void wtp_tid_cache_shutdown(void) 
00108 {
00109     debug("wap.wtp_tid", 0, "%ld items left in the tid cache", 
00110           gwlist_len(tid_cache));
00111     gwlist_destroy(tid_cache, cache_item_destroy);
00112 }
00113 
00114 /*
00115  * Tid verification is invoked, when tid_new flag of the incoming message is 
00116  * on. It is not, if the initiator is not yet cached. If initiator is cached, 
00117  * the received tid is stored.
00118  */
00119 int wtp_tid_is_valid(WAPEvent *event, WTPRespMachine *resp_machine)
00120 {
00121     long rcv_tid = -1,
00122          last_tid = -1;
00123 
00124     WTPCached_tid *item = NULL;
00125 
00126 #if 0
00127     debug("wap.wtp.tid", 0, "starting validation");
00128 #endif
00129     rcv_tid = resp_machine->tid;
00130    
00131     if (!event->u.RcvInvoke.tid_new) {
00132 /*
00133  * First we check whether the current initiator has a cache item for it.
00134  */      
00135         if ((item = tid_cached(resp_machine)) == NULL) {
00136             if (event->u.RcvInvoke.no_cache_supported)
00137                 return no_cached_tid;
00138             else {
00139 #if 0
00140              debug("wap.wtp.tid", 0, "empty cache");    
00141 #endif
00142             add_tid(resp_machine, rcv_tid);
00143                 return ok;
00144             }
00145         }
00146 /*
00147  * If it has, we check if the message is a duplicate or has tid wrapped up 
00148  * confusingly.
00149  */      
00150         last_tid = item->tid; 
00151       
00152         if (tid_in_window(rcv_tid, last_tid) == 0){
00153             info(0, "WTP_TID: tid out of the window");
00154             return fail;
00155         } else {
00156 #if 0
00157             debug("wap.wtp.tid", 0, "tid in the window");
00158 #endif
00159             set_tid_by_item(item, rcv_tid);
00160             return ok;
00161         }
00162 
00163     } else {
00164         info(0, "WTP_TID: tid_new flag on");
00165         rcv_tid = 0;
00166 
00167         if (item == NULL) {
00168             add_tid(resp_machine, rcv_tid);
00169         } else {
00170             set_tid_by_item(item, rcv_tid);
00171         }
00172      
00173         return fail;
00174    }
00175 /*
00176  * This return is unnecessary but the compiler demands it
00177  */
00178    return fail;
00179 }
00180 
00181 /*
00182  * Changes tid value used by an existing initiator. Input responder machine 
00183  * and the new tid.
00184  */
00185 void wtp_tid_set_by_machine(WTPRespMachine *resp_machine, long tid)
00186 {
00187     WTPCached_tid *item = NULL;
00188        
00189     item = tid_cached(resp_machine);
00190     set_tid_by_item(item, tid);
00191 }
00192 
00193 /*****************************************************************************
00194  *
00195  * Internal functions:
00196  *
00197  * Checks whether the received tid is inside the window of acceptable ones. 
00198  * The size of the window is set by the constant WTP_TID_WINDOW_SIZE (half of 
00199  * the tid space is the recommended value). 
00200  *
00201  * Inputs: stored tid, received tid. Output 0, if received tid is outside the 
00202  * window, 1, if it is inside.
00203  */
00204 static int tid_in_window(long rcv_tid, long last_tid)
00205 {
00206 #if 0
00207     debug("wap.wtp.tid", 0, "tids were rcv_tid, %ld and last_tid, %ld"
00208           " and test window %ld", rcv_tid, last_tid, WTP_TID_WINDOW_SIZE); 
00209 #endif
00210     if (last_tid == rcv_tid) {
00211     return 0;
00212     } 
00213 
00214     if (rcv_tid > last_tid) {
00215     if (abs(rcv_tid - last_tid) <= WTP_TID_WINDOW_SIZE) {
00216             return 1;
00217         } else {
00218             return 0;
00219         }
00220     }
00221        
00222     if (rcv_tid < last_tid) {
00223         if (abs(rcv_tid - last_tid) >= WTP_TID_WINDOW_SIZE){
00224             return 1;
00225         } else {
00226            return 0;
00227         }
00228     }
00229 
00230 /*
00231  * Following return is unnecessary but our compiler demands it
00232  */
00233        return 0;
00234 }
00235 
00236 static WTPCached_tid *cache_item_create_empty(void)
00237 {
00238     WTPCached_tid *item = NULL;
00239 
00240     item = gw_malloc(sizeof(*item));
00241     item->addr_tuple = NULL;
00242     item->tid = 0;
00243 
00244     return item;
00245 }
00246 
00247 static void cache_item_destroy(void *p)
00248 {
00249     WTPCached_tid *item;
00250     
00251     item = p;
00252     wap_addr_tuple_destroy(item->addr_tuple);
00253     gw_free(item);
00254 }
00255 
00256 /*
00257  * Checking whether there is an item stored for a specific initiator. Receives 
00258  * address quadruplet - the identifier it uses - from object WTPRespMachine. 
00259  * Ditto tid. Returns the item or NULL, if there is not one. Initiator is 
00260  * identified by the address four-tuple.
00261  */
00262 
00263 static int tid_is_cached(void *a, void *b)
00264 {
00265     WAPAddrTuple *initiator_profile;
00266     WTPCached_tid *item;
00267 
00268     item = a;
00269     initiator_profile = b;
00270 
00271     return wap_addr_tuple_same(item->addr_tuple, initiator_profile);
00272 }
00273 
00274 static WTPCached_tid *tid_cached(WTPRespMachine *resp_machine)
00275 {
00276     WTPCached_tid *item = NULL;
00277 
00278     item = gwlist_search(tid_cache, resp_machine->addr_tuple, tid_is_cached);
00279 
00280     return item;
00281 }
00282 
00283 /*
00284  * Adds an item to the tid cache, one item per every initiator. Initiator is 
00285  * identified by the address four-tuple, fetched from a wtp responder machine.
00286  */ 
00287 static void add_tid(WTPRespMachine *resp_machine, long tid)
00288 {
00289     WTPCached_tid *new_item = NULL;
00290        
00291     new_item = cache_item_create_empty(); 
00292     new_item->addr_tuple = wap_addr_tuple_duplicate(resp_machine->addr_tuple);
00293     new_item->tid = tid; 
00294 
00295     gwlist_append(tid_cache, new_item);
00296 }
00297 
00298 /*
00299  * Set tid for an existing initiator. Input a cache item and the new tid.
00300  */
00301 static void set_tid_by_item(WTPCached_tid *item, long tid)
00302 {
00303     gwlist_lock(tid_cache);
00304     item->tid = tid;
00305     gwlist_unlock(tid_cache);
00306 }
See file LICENSE for details about the license agreement for using, modifying, copying or deriving work from this software.