Committer: Mircea Gherzan <mircea.gherzan@xxxxxxxxxxxxxx> Date: Thu Feb 11 12:49:47 2010 +0100 Revision: 3605 Revision-id: mircea.gherzan@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Branch nick: trunk Log: Uncrustify the i3 source files. Modified: M i3/aeshash/aes.h M i3/aeshash/aescpp.h M i3/aeshash/aescrypp.c M i3/aeshash/aescrypt.c M i3/aeshash/aeshash.c M i3/aeshash/aeskey.c M i3/aeshash/aeskeypp.c M i3/aeshash/aesopt.h M i3/aeshash/aestab.c M i3/chord/api.c M i3/chord/chord.c M i3/chord/chord.h M i3/chord/chord_api.h M i3/chord/chord_getfingers.c M i3/chord/chord_traceroute.c M i3/chord/debug.h M i3/chord/eprintf.c M i3/chord/eprintf.h M i3/chord/finger.c M i3/chord/gen_conf.c M i3/chord/gen_conf_same.c M i3/chord/hosts.c M i3/chord/join.c M i3/chord/pack.c M i3/chord/process.c M i3/chord/sendpkt.c M i3/chord/stabilize.c M i3/chord/test.c M i3/chord/util.c M i3/i3/debug_fns.h M i3/i3/i3.h M i3/i3/i3_addr.c M i3/i3/i3_addr.h M i3/i3/i3_api.c M i3/i3/i3_api.h M i3/i3/i3_config.c M i3/i3/i3_config.h M i3/i3/i3_debug.c M i3/i3/i3_debug.h M i3/i3/i3_fun.h M i3/i3/i3_header.c M i3/i3/i3_header.h M i3/i3/i3_id.c M i3/i3/i3_id.h M i3/i3/i3_misc.c M i3/i3/i3_misc.h M i3/i3/i3_options.c M i3/i3/i3_options.h M i3/i3/i3_ping.c M i3/i3/i3_ping.h M i3/i3/i3_stack.c M i3/i3/i3_stack.h M i3/i3/i3_tcp_fns.c M i3/i3/i3_tcp_fns.h M i3/i3/i3_trigger.c M i3/i3/i3_trigger.h M i3/i3/i3_utils.c M i3/i3/i3_utils.h M i3/i3/token_bucket.c M i3/i3/token_bucket.h M i3/i3_client/coordinates.c M i3/i3_client/coordinates.h M i3/i3_client/downhill_simplex.c M i3/i3_client/downhill_simplex.h M i3/i3_client/http.c M i3/i3_client/http.h M i3/i3_client/i3_client.h M i3/i3_client/i3_client_api.c M i3/i3_client/i3_client_api.h M i3/i3_client/i3_client_api_ctx.c M i3/i3_client/i3_client_api_ctx.h M i3/i3_client/i3_client_api_ext.c M i3/i3_client/i3_client_callback.c M i3/i3_client/i3_client_callback.h M i3/i3_client/i3_client_context.c M i3/i3_client/i3_client_context.h M i3/i3_client/i3_client_fd.c M i3/i3_client/i3_client_fd.h M i3/i3_client/i3_client_fun.h M i3/i3_client/i3_client_id.c M i3/i3_client/i3_client_id.h M i3/i3_client/i3_client_params.h M i3/i3_client/i3_client_pkt.c M i3/i3_client/i3_client_pkt.h M i3/i3_client/i3_client_timer.c M i3/i3_client/i3_client_timer.h M i3/i3_client/i3_client_trigger.c M i3/i3_client/i3_client_trigger.h M i3/i3_client/i3server_list.c M i3/i3_client/i3server_list.h M i3/i3_client/ping.c M i3/i3_client/ping.h M i3/i3_client/ping_thread.c M i3/i3_client/ping_thread.h M i3/i3_client/qsort.c M i3/utils/byteorder.c M i3/utils/byteorder.h M i3/utils/eprintf.c M i3/utils/eprintf.h M i3/utils/event.c M i3/utils/event.h M i3/utils/fwint.h M i3/utils/gen_utils.c M i3/utils/gen_utils.h M i3/utils/inetfns.c M i3/utils/inetfns.h M i3/utils/netwrap.h M i3/utils/netwrap_posix.c M i3/utils/netwrap_win32.c M i3/utils/utils.h === modified file 'i3/aeshash/aes.h' --- i3/aeshash/aes.h 2009-12-29 21:08:52 +0000 +++ i3/aeshash/aes.h 2010-02-11 11:49:47 +0000 @@ -1,110 +1,110 @@ -/* - ------------------------------------------------------------------------- - Copyright (c) 2001, Dr Brian Gladman <brg@xxxxxxxxxxxxx>, Worcester, UK. - All rights reserved. - - LICENSE TERMS - - The free distribution and use of this software in both source and binary - form is allowed (with or without changes) provided that: - - 1. distributions of this source code include the above copyright - notice, this list of conditions and the following disclaimer; - - 2. distributions in binary form include the above copyright - notice, this list of conditions and the following disclaimer - in the documentation and/or other associated materials; - - 3. the copyright holder's name is not used to endorse products - built using this software without specific written permission. - - DISCLAIMER - - This software is provided 'as is' with no explicit or implied warranties - in respect of its properties, including, but not limited to, correctness - and fitness for purpose. - ------------------------------------------------------------------------- - Issue Date: 29/07/2002 - - This file contains the definitions required to use AES (Rijndael) in C. -*/ - -#ifndef _AES_H -#define _AES_H - - -#define __int64 long long - -/* This include is used only to find 8 and 32 bit unsigned integer types */ - -#include <limits.h> - -#if UCHAR_MAX == 0xff /* an unsigned 8 bit type for internal AES use */ - typedef unsigned char aes_08t; -#else -#error Please define an unsigned 8 bit type in aes.h -#endif - -#if UINT_MAX == 0xffffffff /* an unsigned 32 bit type for internal AES use */ - typedef unsigned int aes_32t; -#elif ULONG_MAX == 0xffffffff - typedef unsigned long aes_32t; -#else -#error Please define an unsigned 32 bit type in aes.h -#endif - -/* BLOCK_SIZE is in BYTES: 16, 24, 32 or undefined for aes.c and 16, 20, - 24, 28, 32 or undefined for aespp.c. When left undefined a slower - version that provides variable block length is compiled. -*/ - -#define BLOCK_SIZE 16 - -/* key schedule length (in 32-bit words) */ - -#if !defined(BLOCK_SIZE) -#define KS_LENGTH 128 -#else -#define KS_LENGTH 4 * BLOCK_SIZE -#endif - -#if defined(__cplusplus) -extern "C" -{ -#endif - -typedef unsigned int aes_fret; /* type for function return value */ -#define aes_bad 0 /* bad function return value */ -#define aes_good 1 /* good function return value */ -#ifndef AES_DLL /* implement normal or DLL functions */ -#define aes_rval aes_fret -#else -#define aes_rval aes_fret __declspec(dllexport) _stdcall -#endif - - -typedef struct /* the AES context for encryption */ -{ aes_32t k_sch[KS_LENGTH]; /* the encryption key schedule */ - aes_32t n_rnd; /* the number of cipher rounds */ - aes_32t n_blk; /* the number of bytes in the state */ -} aes_ctx; - -#if !defined(BLOCK_SIZE) -aes_rval aes_blk_len(unsigned int blen, aes_ctx cx[1]); -#endif - -aes_rval aes_enc_key(const unsigned char in_key[], unsigned int klen, aes_ctx cx[1]); -aes_rval aes_enc_blk(const unsigned char in_blk[], unsigned char out_blk[], const aes_ctx cx[1]); - -aes_rval aes_dec_key(const unsigned char in_key[], unsigned int klen, aes_ctx cx[1]); -aes_rval aes_dec_blk(const unsigned char in_blk[], unsigned char out_blk[], const aes_ctx cx[1]); - -void aeshash_l(const unsigned char in[], unsigned char out[]); -void aeshash_r(const unsigned char in[], unsigned char out[]); -void aeshash_init(void); - -#if defined(__cplusplus) -} -#endif - -#endif +/* + * ------------------------------------------------------------------------- + * Copyright (c) 2001, Dr Brian Gladman <brg@xxxxxxxxxxxxx>, Worcester, UK. + * All rights reserved. + * + * LICENSE TERMS + * + * The free distribution and use of this software in both source and binary + * form is allowed (with or without changes) provided that: + * + * 1. distributions of this source code include the above copyright + * notice, this list of conditions and the following disclaimer; + * + * 2. distributions in binary form include the above copyright + * notice, this list of conditions and the following disclaimer + * in the documentation and/or other associated materials; + * + * 3. the copyright holder's name is not used to endorse products + * built using this software without specific written permission. + * + * DISCLAIMER + * + * This software is provided 'as is' with no explicit or implied warranties + * in respect of its properties, including, but not limited to, correctness + * and fitness for purpose. + * ------------------------------------------------------------------------- + * Issue Date: 29/07/2002 + * + * This file contains the definitions required to use AES (Rijndael) in C. + */ + +#ifndef _AES_H +#define _AES_H + + +#define __int64 long long + +/* This include is used only to find 8 and 32 bit unsigned integer types */ + +#include <limits.h> + +#if UCHAR_MAX == 0xff /* an unsigned 8 bit type for internal AES use */ +typedef unsigned char aes_08t; +#else +#error Please define an unsigned 8 bit type in aes.h +#endif + +#if UINT_MAX == 0xffffffff /* an unsigned 32 bit type for internal AES use */ +typedef unsigned int aes_32t; +#elif ULONG_MAX == 0xffffffff +typedef unsigned long aes_32t; +#else +#error Please define an unsigned 32 bit type in aes.h +#endif + +/* BLOCK_SIZE is in BYTES: 16, 24, 32 or undefined for aes.c and 16, 20, + * 24, 28, 32 or undefined for aespp.c. When left undefined a slower + * version that provides variable block length is compiled. + */ + +#define BLOCK_SIZE 16 + +/* key schedule length (in 32-bit words) */ + +#if !defined(BLOCK_SIZE) +#define KS_LENGTH 128 +#else +#define KS_LENGTH 4 * BLOCK_SIZE +#endif + +#if defined(__cplusplus) +extern "C" +{ +#endif + +typedef unsigned int aes_fret; /* type for function return value */ +#define aes_bad 0 /* bad function return value */ +#define aes_good 1 /* good function return value */ +#ifndef AES_DLL /* implement normal or DLL functions */ +#define aes_rval aes_fret +#else +#define aes_rval aes_fret __declspec(dllexport) _stdcall +#endif + + +typedef struct /* the AES context for encryption */ +{ aes_32t k_sch[KS_LENGTH]; /* the encryption key schedule */ + aes_32t n_rnd; /* the number of cipher rounds */ + aes_32t n_blk; /* the number of bytes in the state */ +} aes_ctx; + +#if !defined(BLOCK_SIZE) +aes_rval aes_blk_len(unsigned int blen, aes_ctx cx[1]); +#endif + +aes_rval aes_enc_key(const unsigned char in_key[], unsigned int klen, aes_ctx cx[1]); +aes_rval aes_enc_blk(const unsigned char in_blk[], unsigned char out_blk[], const aes_ctx cx[1]); + +aes_rval aes_dec_key(const unsigned char in_key[], unsigned int klen, aes_ctx cx[1]); +aes_rval aes_dec_blk(const unsigned char in_blk[], unsigned char out_blk[], const aes_ctx cx[1]); + +void aeshash_l(const unsigned char in[], unsigned char out[]); +void aeshash_r(const unsigned char in[], unsigned char out[]); +void aeshash_init(void); + +#if defined(__cplusplus) +} +#endif + +#endif === modified file 'i3/aeshash/aescpp.h' --- i3/aeshash/aescpp.h 2009-12-11 22:49:11 +0000 +++ i3/aeshash/aescpp.h 2010-02-11 11:49:47 +0000 @@ -1,54 +1,79 @@ -/* - ------------------------------------------------------------------------- - Copyright (c) 2001, Dr Brian Gladman <brg@xxxxxxxxxxxxxx>, Worcester, UK. - All rights reserved. - - TERMS - - Redistribution and use in source and binary forms, with or without - modification, are permitted subject to the following conditions: - - 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 copyright holder's name must not be used to endorse or promote - any products derived from this software without his specific prior - written permission. - - This software is provided 'as is' with no express or implied warranties - of correctness or fitness for purpose. - ------------------------------------------------------------------------- - Issue Date: 21/01/2002 - - This file contains the definitions required to use AES (Rijndael) in C++. -*/ - -#ifndef _AESCPP_H -#define _AESCPP_H - -#include "aes.h" - -class AESclass -{ aes_ctx cx[1]; -public: -#if defined(BLOCK_SIZE) - AESclass() { cx->n_blk = BLOCK_SIZE; cx->n_rnd = 0; } -#else - AESclass(unsigned int blen = 16) { cx->n_blk = blen; cx->n_rnd = 0; } - aes_rval blk_len(unsigned int blen) { return aes_blk_len(blen, cx); } -#endif - aes_rval enc_key(const unsigned char in_key[], unsigned int klen) - { return aes_enc_key(in_key, klen, cx); } - aes_rval dec_key(const unsigned char in_key[], unsigned int klen) - { return aes_dec_key(in_key, klen, cx); } - aes_rval enc_blk(const unsigned char in_blk[], unsigned char out_blk[]) - { return aes_enc_blk(in_blk, out_blk, cx); } - aes_rval dec_blk(const unsigned char in_blk[], unsigned char out_blk[]) - { return aes_dec_blk(in_blk, out_blk, cx); } -}; - -#endif +/* + * ------------------------------------------------------------------------- + * Copyright (c) 2001, Dr Brian Gladman <brg@xxxxxxxxxxxxxx>, Worcester, UK. + * All rights reserved. + * + * TERMS + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted subject to the following conditions: + * + * 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 copyright holder's name must not be used to endorse or promote + * any products derived from this software without his specific prior + * written permission. + * + * This software is provided 'as is' with no express or implied warranties + * of correctness or fitness for purpose. + * ------------------------------------------------------------------------- + * Issue Date: 21/01/2002 + * + * This file contains the definitions required to use AES (Rijndael) in C++. + */ + +#ifndef _AESCPP_H +#define _AESCPP_H + +#include "aes.h" + +class AESclass +{ aes_ctx cx[1]; +public: +#if defined(BLOCK_SIZE) + AESclass() + { + cx->n_blk = BLOCK_SIZE; + cx->n_rnd = 0; + } + +#else + AESclass(unsigned int blen = 16) + { + cx->n_blk = blen; + cx->n_rnd = 0; + } + + aes_rval blk_len(unsigned int blen) + { + return aes_blk_len(blen, cx); + } + +#endif + aes_rval enc_key(const unsigned char in_key[], unsigned int klen) + { + return aes_enc_key(in_key, klen, cx); + } + + aes_rval dec_key(const unsigned char in_key[], unsigned int klen) + { + return aes_dec_key(in_key, klen, cx); + } + + aes_rval enc_blk(const unsigned char in_blk[], unsigned char out_blk[]) + { + return aes_enc_blk(in_blk, out_blk, cx); + } + + aes_rval dec_blk(const unsigned char in_blk[], unsigned char out_blk[]) + { + return aes_dec_blk(in_blk, out_blk, cx); + } +}; + +#endif === modified file 'i3/aeshash/aescrypp.c' --- i3/aeshash/aescrypp.c 2009-12-11 22:49:11 +0000 +++ i3/aeshash/aescrypp.c 2010-02-11 11:49:47 +0000 @@ -1,487 +1,481 @@ -/* - ------------------------------------------------------------------------- - Copyright (c) 2001, Dr Brian Gladman <brg@xxxxxxxxxxxxx>, Worcester, UK. - All rights reserved. - - LICENSE TERMS - - The free distribution and use of this software in both source and binary - form is allowed (with or without changes) provided that: - - 1. distributions of this source code include the above copyright - notice, this list of conditions and the following disclaimer; - - 2. distributions in binary form include the above copyright - notice, this list of conditions and the following disclaimer - in the documentation and/or other associated materials; - - 3. the copyright holder's name is not used to endorse products - built using this software without specific written permission. - - DISCLAIMER - - This software is provided 'as is' with no explicit or implied warranties - in respect of its properties, including, but not limited to, correctness - and fitness for purpose. - ------------------------------------------------------------------------- - Issue Date: 29/07/2002 - - This file contains the code for implementing encryption and decryption - for AES (Rijndael) for block and key sizes of 16, 20, 24, 28 and 32 bytes. - It can optionally be replaced by code written in assembler using NASM. -*/ - -#include "aesopt.h" - -#define unused 77 /* Sunset Strip */ - -#define si(y,x,k,c) s(y,c) = word_in(x + 4 * c) ^ k[c] -#define so(y,x,c) word_out(y + 4 * c, s(x,c)) - -#if BLOCK_SIZE == 16 - -#if defined(ARRAYS) -#define locals(y,x) x[4],y[4] -#else -#define locals(y,x) x##0,x##1,x##2,x##3,y##0,y##1,y##2,y##3 - /* - the following defines prevent the compiler requiring the declaration - of generated but unused variables in the fwd_var and inv_var macros - */ -#define b04 unused -#define b05 unused -#define b06 unused -#define b07 unused -#define b14 unused -#define b15 unused -#define b16 unused -#define b17 unused -#endif -#define l_copy(y, x) s(y,0) = s(x,0); s(y,1) = s(x,1); \ - s(y,2) = s(x,2); s(y,3) = s(x,3); -#define state_in(y,x,k) si(y,x,k,0); si(y,x,k,1); si(y,x,k,2); si(y,x,k,3) -#define state_out(y,x) so(y,x,0); so(y,x,1); so(y,x,2); so(y,x,3) -#define round(rm,y,x,k) rm(y,x,k,0); rm(y,x,k,1); rm(y,x,k,2); rm(y,x,k,3) - -#elif BLOCK_SIZE == 20 - -#if defined(ARRAYS) -#define locals(y,x) x[5],y[5] -#else -#define locals(y,x) x##0,x##1,x##2,x##3,x##4,y##0,y##1,y##2,y##3,y##4 -#define b05 unused -#define b06 unused -#define b07 unused -#define b15 unused -#define b16 unused -#define b17 unused -#endif -#define l_copy(y, x) s(y,0) = s(x,0); s(y,1) = s(x,1); \ - s(y,2) = s(x,2); s(y,3) = s(x,3); s(y,4) = s(x,4); -#define state_in(y,x,k) si(y,x,k,0); si(y,x,k,1); si(y,x,k,2); si(y,x,k,3); si(y,x,k,4) -#define state_out(y,x) so(y,x,0); so(y,x,1); so(y,x,2); -#define round(rm,y,x,k) rm(y,x,k,0); rm(y,x,k,1); rm(y,x,k,2); rm(y,x,k,3); rm(y,x,k,4) - -#elif BLOCK_SIZE == 24 - -#if defined(ARRAYS) -#define locals(y,x) x[6],y[6] -#else -#define locals(y,x) x##0,x##1,x##2,x##3,x##4,x##5, \ - y##0,y##1,y##2,y##3,y##4,y##5 -#define b06 unused -#define b07 unused -#define b16 unused -#define b17 unused -#endif -#define l_copy(y, x) s(y,0) = s(x,0); s(y,1) = s(x,1); \ - s(y,2) = s(x,2); s(y,3) = s(x,3); \ - s(y,4) = s(x,4); s(y,5) = s(x,5); -#define state_in(y,x,k) si(y,x,k,0); si(y,x,k,1); si(y,x,k,2); \ - si(y,x,k,3); si(y,x,k,4); si(y,x,k,5) -#define state_out(y,x) so(y,x,0); so(y,x,1); so(y,x,2); \ - so(y,x,3); so(y,x,4); so(y,x,5) -#define round(rm,y,x,k) rm(y,x,k,0); rm(y,x,k,1); rm(y,x,k,2); \ - rm(y,x,k,3); rm(y,x,k,4); rm(y,x,k,5) - -#elif BLOCK_SIZE == 28 - -#if defined(ARRAYS) -#define locals(y,x) x[7],y[7] -#else -#define locals(y,x) x##0,x##1,x##2,x##3,x##4,x##5,x##6 \ - y##0,y##1,y##2,y##3,y##4,y##5,y##6 -#define b07 unused -#define b17 unused -#endif -#define l_copy(y, x) s(y,0) = s(x,0); s(y,1) = s(x,1); \ - s(y,2) = s(x,2); s(y,3) = s(x,3); \ - s(y,4) = s(x,4); s(y,5) = s(x,5);; s(y,6) = s(x,6); -#define state_in(y,x,k) si(y,x,k,0); si(y,x,k,1); si(y,x,k,2); \ - si(y,x,k,3); si(y,x,k,4); si(y,x,k,5); si(y,x,k,6) -#define state_out(y,x) so(y,x,0); so(y,x,1); so(y,x,2); \ - so(y,x,3); so(y,x,4); so(y,x,5); so(y,x,6) -#define round(rm,y,x,k) rm(y,x,k,0); rm(y,x,k,1); rm(y,x,k,2); \ - rm(y,x,k,3); rm(y,x,k,4); rm(y,x,k,5); rm(y,x,k,6) -#else - -#if defined(ARRAYS) -#define locals(y,x) x[8],y[8] -#else -#define locals(y,x) x##0,x##1,x##2,x##3,x##4,x##5,x##6,x##7, \ - y##0,y##1,y##2,y##3,y##4,y##5,y##6,y##7 -#endif -#define l_copy(y, x) s(y,0) = s(x,0); s(y,1) = s(x,1); \ - s(y,2) = s(x,2); s(y,3) = s(x,3); \ - s(y,4) = s(x,4); s(y,5) = s(x,5); \ - s(y,6) = s(x,6); s(y,7) = s(x,7); - -#if BLOCK_SIZE == 32 - -#define state_in(y,x,k) si(y,x,k,0); si(y,x,k,1); si(y,x,k,2); si(y,x,k,3); \ - si(y,x,k,4); si(y,x,k,5); si(y,x,k,6); si(y,x,k,7) -#define state_out(y,x) so(y,x,0); so(y,x,1); so(y,x,2); so(y,x,3); \ - so(y,x,4); so(y,x,5); so(y,x,6); so(y,x,7) -#define round(rm,y,x,k) rm(y,x,k,0); rm(y,x,k,1); rm(y,x,k,2); rm(y,x,k,3); \ - rm(y,x,k,4); rm(y,x,k,5); rm(y,x,k,6); rm(y,x,k,7) -#else - -#define state_in(y,x,k) \ -switch(nc) \ -{ case 8: si(y,x,k,7); \ - case 7: si(y,x,k,6); \ - case 6: si(y,x,k,5); \ - case 5: si(y,x,k,4); \ - case 4: si(y,x,k,3); si(y,x,k,2); \ - si(y,x,k,1); si(y,x,k,0); \ -} - -#define state_out(y,x) \ -switch(nc) \ -{ case 8: so(y,x,7); \ - case 7: so(y,x,6); \ - case 6: so(y,x,5); \ - case 5: so(y,x,4); \ - case 4: so(y,x,3); so(y,x,2); \ - so(y,x,1); so(y,x,0); \ -} - -#if defined(FAST_VARIABLE) - -#define round(rm,y,x,k) \ -switch(nc) \ -{ case 8: rm(y,x,k,7); rm(y,x,k,6); \ - rm(y,x,k,5); rm(y,x,k,4); \ - rm(y,x,k,3); rm(y,x,k,2); \ - rm(y,x,k,1); rm(y,x,k,0); \ - break; \ - case 7: rm(y,x,k,6); rm(y,x,k,5); \ - rm(y,x,k,4); rm(y,x,k,3); \ - rm(y,x,k,2); rm(y,x,k,1); \ - rm(y,x,k,0); \ - break; \ - case 6: rm(y,x,k,5); rm(y,x,k,4); \ - rm(y,x,k,3); rm(y,x,k,2); \ - rm(y,x,k,1); rm(y,x,k,0); \ - break; \ - case 5: rm(y,x,k,4); rm(y,x,k,3); \ - rm(y,x,k,2); rm(y,x,k,1); \ - rm(y,x,k,0); \ - break; \ - case 4: rm(y,x,k,3); rm(y,x,k,2); \ - rm(y,x,k,1); rm(y,x,k,0); \ - break; \ -} -#else - -#define round(rm,y,x,k) \ -switch(nc) \ -{ case 8: rm(y,x,k,7); \ - case 7: rm(y,x,k,6); \ - case 6: rm(y,x,k,5); \ - case 5: rm(y,x,k,4); \ - case 4: rm(y,x,k,3); rm(y,x,k,2); \ - rm(y,x,k,1); rm(y,x,k,0); \ -} - -#endif - -#endif -#endif - -#if defined(ENCRYPTION) - -/* I am grateful to Frank Yellin for the following construction - (and that for decryption) which, given the column (c) of the - output state variable, gives the input state variables which - are needed for each row (r) of the state. - - For the fixed block size options, compilers should reduce these - two expressions to fixed variable references. But for variable - block size code conditional clauses will sometimes be returned. - - y = output word, x = input word, r = row, c = column for r = 0, - 1, 2 and 3 = column accessed for row r. -*/ - -#define fwd_var(x,r,c)\ - ( r == 0 ? \ - ( c == 0 ? s(x,0) \ - : c == 1 ? s(x,1) \ - : c == 2 ? s(x,2) \ - : c == 3 ? s(x,3) \ - : c == 4 ? s(x,4) \ - : c == 5 ? s(x,5) \ - : c == 6 ? s(x,6) \ - : s(x,7))\ - : r == 1 ? \ - ( c == 0 ? s(x,1) \ - : c == 1 ? s(x,2) \ - : c == 2 ? s(x,3) \ - : c == 3 ? nc == 4 ? s(x,0) : s(x,4) \ - : c == 4 ? nc == 5 ? s(x,0) : s(x,5) \ - : c == 5 ? nc == 6 ? s(x,0) : s(x,6) \ - : c == 6 ? nc == 7 ? s(x,0) : s(x,7) \ - : s(x,0))\ - : r == 2 ? \ - ( c == 0 ? nc == 8 ? s(x,3) : s(x,2) \ - : c == 1 ? nc == 8 ? s(x,4) : s(x,3) \ - : c == 2 ? nc == 8 ? s(x,5) : nc == 4 ? s(x,0) : s(x,4) \ - : c == 3 ? nc == 8 ? s(x,6) : nc == 5 ? s(x,0) : nc == 4 ? s(x,1) : s(x,5) \ - : c == 4 ? nc == 8 ? s(x,7) : nc == 7 ? s(x,6) : nc == 6 ? s(x,0) : s(x,1) \ - : c == 5 ? nc == 6 ? s(x,1) : s(x,0) \ - : c == 6 ? s(x,1) \ - : s(x,2))\ - : \ - ( c == 0 ? nc > 6 ? s(x,4) : s(x,3) \ - : c == 1 ? nc > 6 ? s(x,5) : nc == 4 ? s(x,0) : s(x,4) \ - : c == 2 ? nc > 6 ? s(x,6) : nc == 6 ? s(x,5) : nc == 5 ? s(x,0) : s(x,1) \ - : c == 3 ? nc == 8 ? s(x,7) : nc == 5 ? s(x,1) : nc == 4 ? s(x,2) : s(x,0) \ - : c == 4 ? nc == 8 ? s(x,0) : nc == 5 ? s(x,2) : s(x,1) \ - : c == 5 ? nc == 8 ? s(x,1) : s(x,2) \ - : c == 6 ? nc == 8 ? s(x,2) : s(x,3) \ - : s(x,3))) - -#if defined(FT4_SET) -#undef dec_fmvars -#define dec_fmvars -#define fwd_rnd(y,x,k,c) s(y,c)= (k)[c] ^ four_tables(x,ft_tab,fwd_var,rf1,c) -#elif defined(FT1_SET) -#undef dec_fmvars -#define dec_fmvars -#define fwd_rnd(y,x,k,c) s(y,c)= (k)[c] ^ one_table(x,upr,ft_tab,fwd_var,rf1,c) -#else -#define fwd_rnd(y,x,k,c) s(y,c) = fwd_mcol(no_table(x,s_box,fwd_var,rf1,c)) ^ (k)[c] -#endif - -#if defined(FL4_SET) -#define fwd_lrnd(y,x,k,c) s(y,c)= (k)[c] ^ four_tables(x,fl_tab,fwd_var,rf1,c) -#elif defined(FL1_SET) -#define fwd_lrnd(y,x,k,c) s(y,c)= (k)[c] ^ one_table(x,ups,fl_tab,fwd_var,rf1,c) -#else -#define fwd_lrnd(y,x,k,c) s(y,c) = no_table(x,s_box,fwd_var,rf1,c) ^ (k)[c] -#endif - -aes_rval aes_enc_blk_(const unsigned char in_blk[], unsigned char out_blk[], const aes_ctx cx[1]) -{ aes_32t locals(b0, b1); - const aes_32t *kp = cx->k_sch; - dec_fmvars /* declare variables for fwd_mcol() if needed */ - - if(!(cx->n_blk & 1)) return aes_bad; - -#if (ENC_UNROLL == FULL) - - state_in((cx->n_rnd & 1 ? b1 : b0), in_blk, kp); - kp += (cx->n_rnd - 9) * nc; - - switch(cx->n_rnd) - { - case 14: round(fwd_rnd, b1, b0, kp - 4 * nc); - case 13: round(fwd_rnd, b0, b1, kp - 3 * nc); - case 12: round(fwd_rnd, b1, b0, kp - 2 * nc); - case 11: round(fwd_rnd, b0, b1, kp - nc); - case 10: round(fwd_rnd, b1, b0, kp ); - round(fwd_rnd, b0, b1, kp + nc); - round(fwd_rnd, b1, b0, kp + 2 * nc); - round(fwd_rnd, b0, b1, kp + 3 * nc); - round(fwd_rnd, b1, b0, kp + 4 * nc); - round(fwd_rnd, b0, b1, kp + 5 * nc); - round(fwd_rnd, b1, b0, kp + 6 * nc); - round(fwd_rnd, b0, b1, kp + 7 * nc); - round(fwd_rnd, b1, b0, kp + 8 * nc); - round(fwd_lrnd, b0, b1, kp + 9 * nc); - } -#else - { aes_32t rnd; - - state_in(b0, in_blk, kp); - -#if (ENC_UNROLL == PARTIAL) - - for(rnd = 0; rnd < (cx->n_rnd - 1) >> 1; ++rnd) - { - kp += nc; - round(fwd_rnd, b1, b0, kp); - kp += nc; - round(fwd_rnd, b0, b1, kp); - } - - if(cx->n_rnd & 1) - { - l_copy(b1, b0); - } - else - { - kp += nc; - round(fwd_rnd, b1, b0, kp); - } -#else - for(rnd = 0; rnd < cx->n_rnd - 1; ++rnd) - { - kp += nc; - round(fwd_rnd, b1, b0, kp); - l_copy(b0, b1); - } -#endif - kp += nc; - round(fwd_lrnd, b0, b1, kp); - } -#endif - - state_out(out_blk, b0); - return aes_good; -} - -#endif - -#if defined(DECRYPTION) - -#define inv_var(x,r,c)\ - ( r == 0 ? \ - ( c == 0 ? s(x,0) \ - : c == 1 ? s(x,1) \ - : c == 2 ? s(x,2) \ - : c == 3 ? s(x,3) \ - : c == 4 ? s(x,4) \ - : c == 5 ? s(x,5) \ - : c == 6 ? s(x,6) \ - : s(x,7))\ - : r == 1 ? \ - ( c == 0 ? nc == 8 ? s(x,7) : nc == 7 ? s(x,6) : nc == 6 ? s(x,5) : nc == 5 ? s(x,4) : s(x,3) \ - : c == 1 ? s(x,0) \ - : c == 2 ? s(x,1) \ - : c == 3 ? s(x,2) \ - : c == 4 ? s(x,3) \ - : c == 5 ? s(x,4) \ - : c == 6 ? s(x,5) \ - : s(x,6))\ - : r == 2 ? \ - ( c == 0 ? nc > 6 ? s(x,5) : nc == 6 ? s(x,4) : nc == 5 ? s(x,3) : s(x,2) \ - : c == 1 ? nc > 6 ? s(x,6) : nc == 6 ? s(x,5) : nc == 5 ? s(x,4) : s(x,3) \ - : c == 2 ? nc == 8 ? s(x,7) : s(x,0) \ - : c == 3 ? nc == 8 ? s(x,0) : s(x,1) \ - : c == 4 ? nc == 8 ? s(x,1) : s(x,2) \ - : c == 5 ? nc == 8 ? s(x,2) : s(x,3) \ - : c == 6 ? nc == 8 ? s(x,3) : s(x,4) \ - : s(x,4))\ - : \ - ( c == 0 ? nc == 8 ? s(x,4) : nc == 5 ? s(x,2) : nc == 4 ? s(x,1) : s(x,3) \ - : c == 1 ? nc == 8 ? s(x,5) : nc == 5 ? s(x,3) : nc == 4 ? s(x,2) : s(x,4) \ - : c == 2 ? nc == 8 ? s(x,6) : nc == 5 ? s(x,4) : nc == 4 ? s(x,3) : s(x,5) \ - : c == 3 ? nc == 8 ? s(x,7) : nc == 7 ? s(x,6) : s(x,0) \ - : c == 4 ? nc > 6 ? s(x,0) : s(x,1) \ - : c == 5 ? nc == 6 ? s(x,2) : s(x,1) \ - : c == 6 ? s(x,2) \ - : s(x,3))) - -#if defined(IT4_SET) -#undef dec_imvars -#define dec_imvars -#define inv_rnd(y,x,k,c) s(y,c)= (k)[c] ^ four_tables(x,it_tab,inv_var,rf1,c) -#elif defined(IT1_SET) -#undef dec_imvars -#define dec_imvars -#define inv_rnd(y,x,k,c) s(y,c)= (k)[c] ^ one_table(x,upr,it_tab,inv_var,rf1,c) -#else -#define inv_rnd(y,x,k,c) s(y,c) = inv_mcol(no_table(x,inv_s_box,inv_var,rf1,c) ^ (k)[c]) -#endif - -#if defined(IL4_SET) -#define inv_lrnd(y,x,k,c) s(y,c)= (k)[c] ^ four_tables(x,il_tab,inv_var,rf1,c) -#elif defined(IL1_SET) -#define inv_lrnd(y,x,k,c) s(y,c)= (k)[c] ^ one_table(x,ups,il_tab,inv_var,rf1,c) -#else -#define inv_lrnd(y,x,k,c) s(y,c) = no_table(x,inv_s_box,inv_var,rf1,c) ^ (k)[c] -#endif - -aes_rval aes_dec_blk_(const unsigned char in_blk[], unsigned char out_blk[], const aes_ctx cx[1]) -{ aes_32t locals(b0, b1); - const aes_32t *kp = cx->k_sch + nc * cx->n_rnd; - dec_imvars /* declare variables for inv_mcol() if needed */ - - if(!(cx->n_blk & 2)) return aes_bad; - -#if (DEC_UNROLL == FULL) - - state_in((cx->n_rnd & 1 ? b1 : b0), in_blk, kp); - kp = cx->k_sch + 9 * nc; - - switch(cx->n_rnd) - { - case 14: round(inv_rnd, b1, b0, kp + 4 * nc); - case 13: round(inv_rnd, b0, b1, kp + 3 * nc); - case 12: round(inv_rnd, b1, b0, kp + 2 * nc); - case 11: round(inv_rnd, b0, b1, kp + nc); - case 10: round(inv_rnd, b1, b0, kp ); - round(inv_rnd, b0, b1, kp - nc); - round(inv_rnd, b1, b0, kp - 2 * nc); - round(inv_rnd, b0, b1, kp - 3 * nc); - round(inv_rnd, b1, b0, kp - 4 * nc); - round(inv_rnd, b0, b1, kp - 5 * nc); - round(inv_rnd, b1, b0, kp - 6 * nc); - round(inv_rnd, b0, b1, kp - 7 * nc); - round(inv_rnd, b1, b0, kp - 8 * nc); - round(inv_lrnd, b0, b1, kp - 9 * nc); - } -#else - { aes_32t rnd; - - state_in(b0, in_blk, kp); - -#if (DEC_UNROLL == PARTIAL) - - for(rnd = 0; rnd < (cx->n_rnd - 1) >> 1; ++rnd) - { - kp -= nc; - round(inv_rnd, b1, b0, kp); - kp -= nc; - round(inv_rnd, b0, b1, kp); - } - - if(cx->n_rnd & 1) - { - l_copy(b1, b0); - } - else - { - kp -= nc; - round(inv_rnd, b1, b0, kp); - } -#else - for(rnd = 0; rnd < cx->n_rnd - 1; ++rnd) - { - kp -= nc; - round(inv_rnd, b1, b0, kp); - l_copy(b0, b1); - } -#endif - kp -= nc; - round(inv_lrnd, b0, b1, kp); - } -#endif - - state_out(out_blk, b0); - return aes_good; -} - -#endif +/* + * ------------------------------------------------------------------------- + * Copyright (c) 2001, Dr Brian Gladman <brg@xxxxxxxxxxxxx>, Worcester, UK. + * All rights reserved. + * + * LICENSE TERMS + * + * The free distribution and use of this software in both source and binary + * form is allowed (with or without changes) provided that: + * + * 1. distributions of this source code include the above copyright + * notice, this list of conditions and the following disclaimer; + * + * 2. distributions in binary form include the above copyright + * notice, this list of conditions and the following disclaimer + * in the documentation and/or other associated materials; + * + * 3. the copyright holder's name is not used to endorse products + * built using this software without specific written permission. + * + * DISCLAIMER + * + * This software is provided 'as is' with no explicit or implied warranties + * in respect of its properties, including, but not limited to, correctness + * and fitness for purpose. + * ------------------------------------------------------------------------- + * Issue Date: 29/07/2002 + * + * This file contains the code for implementing encryption and decryption + * for AES (Rijndael) for block and key sizes of 16, 20, 24, 28 and 32 bytes. + * It can optionally be replaced by code written in assembler using NASM. + */ + +#include "aesopt.h" + +#define unused 77 /* Sunset Strip */ + +#define si(y, x, k, c) s(y, c) = word_in(x + 4 * c) ^ k[c] +#define so(y, x, c) word_out(y + 4 * c, s(x, c)) + +#if BLOCK_SIZE == 16 + +#if defined(ARRAYS) +#define locals(y, x) x[4], y[4] +#else +#define locals(y, x) x ## 0, x ## 1, x ## 2, x ## 3, y ## 0, y ## 1, y ## 2, y ## 3 +/* + * the following defines prevent the compiler requiring the declaration + * of generated but unused variables in the fwd_var and inv_var macros + */ +#define b04 unused +#define b05 unused +#define b06 unused +#define b07 unused +#define b14 unused +#define b15 unused +#define b16 unused +#define b17 unused +#endif +#define l_copy(y, x) s(y, 0) = s(x, 0); s(y, 1) = s(x, 1); \ + s(y, 2) = s(x, 2); s(y, 3) = s(x, 3); +#define state_in(y, x, k) si(y, x, k, 0); si(y, x, k, 1); si(y, x, k, 2); si(y, x, k, 3) +#define state_out(y, x) so(y, x, 0); so(y, x, 1); so(y, x, 2); so(y, x, 3) +#define round(rm, y, x, k) rm(y, x, k, 0); rm(y, x, k, 1); rm(y, x, k, 2); rm(y, x, k, 3) + +#elif BLOCK_SIZE == 20 + +#if defined(ARRAYS) +#define locals(y, x) x[5], y[5] +#else +#define locals(y, x) x ## 0, x ## 1, x ## 2, x ## 3, x ## 4, y ## 0, y ## 1, y ## 2, y ## 3, y ## 4 +#define b05 unused +#define b06 unused +#define b07 unused +#define b15 unused +#define b16 unused +#define b17 unused +#endif +#define l_copy(y, x) s(y, 0) = s(x, 0); s(y, 1) = s(x, 1); \ + s(y, 2) = s(x, 2); s(y, 3) = s(x, 3); s(y, 4) = s(x, 4); +#define state_in(y, x, k) si(y, x, k, 0); si(y, x, k, 1); si(y, x, k, 2); si(y, x, k, 3); si(y, x, k, 4) +#define state_out(y, x) so(y, x, 0); so(y, x, 1); so(y, x, 2); +#define round(rm, y, x, k) rm(y, x, k, 0); rm(y, x, k, 1); rm(y, x, k, 2); rm(y, x, k, 3); rm(y, x, k, 4) + +#elif BLOCK_SIZE == 24 + +#if defined(ARRAYS) +#define locals(y, x) x[6], y[6] +#else +#define locals(y, x) x ## 0, x ## 1, x ## 2, x ## 3, x ## 4, x ## 5, \ + y ## 0, y ## 1, y ## 2, y ## 3, y ## 4, y ## 5 +#define b06 unused +#define b07 unused +#define b16 unused +#define b17 unused +#endif +#define l_copy(y, x) s(y, 0) = s(x, 0); s(y, 1) = s(x, 1); \ + s(y, 2) = s(x, 2); s(y, 3) = s(x, 3); \ + s(y, 4) = s(x, 4); s(y, 5) = s(x, 5); +#define state_in(y, x, k) si(y, x, k, 0); si(y, x, k, 1); si(y, x, k, 2); \ + si(y, x, k, 3); si(y, x, k, 4); si(y, x, k, 5) +#define state_out(y, x) so(y, x, 0); so(y, x, 1); so(y, x, 2); \ + so(y, x, 3); so(y, x, 4); so(y, x, 5) +#define round(rm, y, x, k) rm(y, x, k, 0); rm(y, x, k, 1); rm(y, x, k, 2); \ + rm(y, x, k, 3); rm(y, x, k, 4); rm(y, x, k, 5) + +#elif BLOCK_SIZE == 28 + +#if defined(ARRAYS) +#define locals(y, x) x[7], y[7] +#else +#define locals(y, x) x ## 0, x ## 1, x ## 2, x ## 3, x ## 4, x ## 5, x ## 6 \ + y ## 0, y ## 1, y ## 2, y ## 3, y ## 4, y ## 5, y ## 6 +#define b07 unused +#define b17 unused +#endif +#define l_copy(y, x) s(y, 0) = s(x, 0); s(y, 1) = s(x, 1); \ + s(y, 2) = s(x, 2); s(y, 3) = s(x, 3); \ + s(y, 4) = s(x, 4); s(y, 5) = s(x, 5);; s(y, 6) = s(x, 6); +#define state_in(y, x, k) si(y, x, k, 0); si(y, x, k, 1); si(y, x, k, 2); \ + si(y, x, k, 3); si(y, x, k, 4); si(y, x, k, 5); si(y, x, k, 6) +#define state_out(y, x) so(y, x, 0); so(y, x, 1); so(y, x, 2); \ + so(y, x, 3); so(y, x, 4); so(y, x, 5); so(y, x, 6) +#define round(rm, y, x, k) rm(y, x, k, 0); rm(y, x, k, 1); rm(y, x, k, 2); \ + rm(y, x, k, 3); rm(y, x, k, 4); rm(y, x, k, 5); rm(y, x, k, 6) +#else + +#if defined(ARRAYS) +#define locals(y, x) x[8], y[8] +#else +#define locals(y, x) x ## 0, x ## 1, x ## 2, x ## 3, x ## 4, x ## 5, x ## 6, x ## 7, \ + y ## 0, y ## 1, y ## 2, y ## 3, y ## 4, y ## 5, y ## 6, y ## 7 +#endif +#define l_copy(y, x) s(y, 0) = s(x, 0); s(y, 1) = s(x, 1); \ + s(y, 2) = s(x, 2); s(y, 3) = s(x, 3); \ + s(y, 4) = s(x, 4); s(y, 5) = s(x, 5); \ + s(y, 6) = s(x, 6); s(y, 7) = s(x, 7); + +#if BLOCK_SIZE == 32 + +#define state_in(y, x, k) si(y, x, k, 0); si(y, x, k, 1); si(y, x, k, 2); si(y, x, k, 3); \ + si(y, x, k, 4); si(y, x, k, 5); si(y, x, k, 6); si(y, x, k, 7) +#define state_out(y, x) so(y, x, 0); so(y, x, 1); so(y, x, 2); so(y, x, 3); \ + so(y, x, 4); so(y, x, 5); so(y, x, 6); so(y, x, 7) +#define round(rm, y, x, k) rm(y, x, k, 0); rm(y, x, k, 1); rm(y, x, k, 2); rm(y, x, k, 3); \ + rm(y, x, k, 4); rm(y, x, k, 5); rm(y, x, k, 6); rm(y, x, k, 7) +#else + +#define state_in(y, x, k) \ + switch (nc) \ + { case 8: si(y, x, k, 7); \ + case 7: si(y, x, k, 6); \ + case 6: si(y, x, k, 5); \ + case 5: si(y, x, k, 4); \ + case 4: si(y, x, k, 3); si(y, x, k, 2); \ + si(y, x, k, 1); si(y, x, k, 0); \ + } + +#define state_out(y, x) \ + switch (nc) \ + { case 8: so(y, x, 7); \ + case 7: so(y, x, 6); \ + case 6: so(y, x, 5); \ + case 5: so(y, x, 4); \ + case 4: so(y, x, 3); so(y, x, 2); \ + so(y, x, 1); so(y, x, 0); \ + } + +#if defined(FAST_VARIABLE) + +#define round(rm, y, x, k) \ + switch (nc) \ + { case 8: rm(y, x, k, 7); rm(y, x, k, 6); \ + rm(y, x, k, 5); rm(y, x, k, 4); \ + rm(y, x, k, 3); rm(y, x, k, 2); \ + rm(y, x, k, 1); rm(y, x, k, 0); \ + break; \ + case 7: rm(y, x, k, 6); rm(y, x, k, 5); \ + rm(y, x, k, 4); rm(y, x, k, 3); \ + rm(y, x, k, 2); rm(y, x, k, 1); \ + rm(y, x, k, 0); \ + break; \ + case 6: rm(y, x, k, 5); rm(y, x, k, 4); \ + rm(y, x, k, 3); rm(y, x, k, 2); \ + rm(y, x, k, 1); rm(y, x, k, 0); \ + break; \ + case 5: rm(y, x, k, 4); rm(y, x, k, 3); \ + rm(y, x, k, 2); rm(y, x, k, 1); \ + rm(y, x, k, 0); \ + break; \ + case 4: rm(y, x, k, 3); rm(y, x, k, 2); \ + rm(y, x, k, 1); rm(y, x, k, 0); \ + break; \ + } +#else + +#define round(rm, y, x, k) \ + switch (nc) \ + { case 8: rm(y, x, k, 7); \ + case 7: rm(y, x, k, 6); \ + case 6: rm(y, x, k, 5); \ + case 5: rm(y, x, k, 4); \ + case 4: rm(y, x, k, 3); rm(y, x, k, 2); \ + rm(y, x, k, 1); rm(y, x, k, 0); \ + } + +#endif + +#endif +#endif + +#if defined(ENCRYPTION) + +/* I am grateful to Frank Yellin for the following construction + * (and that for decryption) which, given the column (c) of the + * output state variable, gives the input state variables which + * are needed for each row (r) of the state. + * + * For the fixed block size options, compilers should reduce these + * two expressions to fixed variable references. But for variable + * block size code conditional clauses will sometimes be returned. + * + * y = output word, x = input word, r = row, c = column for r = 0, + * 1, 2 and 3 = column accessed for row r. + */ + +#define fwd_var(x, r, c) \ + (r == 0 ? \ + (c == 0 ? s(x, 0) \ + : c == 1 ? s(x, 1) \ + : c == 2 ? s(x, 2) \ + : c == 3 ? s(x, 3) \ + : c == 4 ? s(x, 4) \ + : c == 5 ? s(x, 5) \ + : c == 6 ? s(x, 6) \ + : s(x, 7)) \ + : r == 1 ? \ + (c == 0 ? s(x, 1) \ + : c == 1 ? s(x, 2) \ + : c == 2 ? s(x, 3) \ + : c == 3 ? nc == 4 ? s(x, 0) : s(x, 4) \ + : c == 4 ? nc == 5 ? s(x, 0) : s(x, 5) \ + : c == 5 ? nc == 6 ? s(x, 0) : s(x, 6) \ + : c == 6 ? nc == 7 ? s(x, 0) : s(x, 7) \ + : s(x, 0)) \ + : r == 2 ? \ + (c == 0 ? nc == 8 ? s(x, 3) : s(x, 2) \ + : c == 1 ? nc == 8 ? s(x, 4) : s(x, 3) \ + : c == 2 ? nc == 8 ? s(x, 5) : nc == 4 ? s(x, 0) : s(x, 4) \ + : c == 3 ? nc == 8 ? s(x, 6) : nc == 5 ? s(x, 0) : nc == 4 ? s(x, 1) : s(x, 5) \ + : c == 4 ? nc == 8 ? s(x, 7) : nc == 7 ? s(x, 6) : nc == 6 ? s(x, 0) : s(x, 1) \ + : c == 5 ? nc == 6 ? s(x, 1) : s(x, 0) \ + : c == 6 ? s(x, 1) \ + : s(x, 2)) \ + : \ + (c == 0 ? nc > 6 ? s(x, 4) : s(x, 3) \ + : c == 1 ? nc > 6 ? s(x, 5) : nc == 4 ? s(x, 0) : s(x, 4) \ + : c == 2 ? nc > 6 ? s(x, 6) : nc == 6 ? s(x, 5) : nc == 5 ? s(x, 0) : s(x, 1) \ + : c == 3 ? nc == 8 ? s(x, 7) : nc == 5 ? s(x, 1) : nc == 4 ? s(x, 2) : s(x, 0) \ + : c == 4 ? nc == 8 ? s(x, 0) : nc == 5 ? s(x, 2) : s(x, 1) \ + : c == 5 ? nc == 8 ? s(x, 1) : s(x, 2) \ + : c == 6 ? nc == 8 ? s(x, 2) : s(x, 3) \ + : s(x, 3))) + +#if defined(FT4_SET) +#undef dec_fmvars +#define dec_fmvars +#define fwd_rnd(y, x, k, c) s(y, c) = (k)[c] ^ four_tables(x, ft_tab, fwd_var, rf1, c) +#elif defined(FT1_SET) +#undef dec_fmvars +#define dec_fmvars +#define fwd_rnd(y, x, k, c) s(y, c) = (k)[c] ^ one_table(x, upr, ft_tab, fwd_var, rf1, c) +#else +#define fwd_rnd(y, x, k, c) s(y, c) = fwd_mcol(no_table(x, s_box, fwd_var, rf1, c)) ^ (k)[c] +#endif + +#if defined(FL4_SET) +#define fwd_lrnd(y, x, k, c) s(y, c) = (k)[c] ^ four_tables(x, fl_tab, fwd_var, rf1, c) +#elif defined(FL1_SET) +#define fwd_lrnd(y, x, k, c) s(y, c) = (k)[c] ^ one_table(x, ups, fl_tab, fwd_var, rf1, c) +#else +#define fwd_lrnd(y, x, k, c) s(y, c) = no_table(x, s_box, fwd_var, rf1, c) ^ (k)[c] +#endif + +aes_rval aes_enc_blk_(const unsigned char in_blk[], unsigned char out_blk[], const aes_ctx cx[1]) +{ + aes_32t locals(b0, b1); + const aes_32t *kp = cx->k_sch; + dec_fmvars /* declare variables for fwd_mcol() if needed */ + + if (!(cx->n_blk & 1)) { + return aes_bad; + } + +#if (ENC_UNROLL == FULL) + + state_in((cx->n_rnd & 1 ? b1 : b0), in_blk, kp); + kp += (cx->n_rnd - 9) * nc; + + switch (cx->n_rnd) { + case 14: round(fwd_rnd, b1, b0, kp - 4 * nc); + case 13: round(fwd_rnd, b0, b1, kp - 3 * nc); + case 12: round(fwd_rnd, b1, b0, kp - 2 * nc); + case 11: round(fwd_rnd, b0, b1, kp - nc); + case 10: round(fwd_rnd, b1, b0, kp ); + round(fwd_rnd, b0, b1, kp + nc); + round(fwd_rnd, b1, b0, kp + 2 * nc); + round(fwd_rnd, b0, b1, kp + 3 * nc); + round(fwd_rnd, b1, b0, kp + 4 * nc); + round(fwd_rnd, b0, b1, kp + 5 * nc); + round(fwd_rnd, b1, b0, kp + 6 * nc); + round(fwd_rnd, b0, b1, kp + 7 * nc); + round(fwd_rnd, b1, b0, kp + 8 * nc); + round(fwd_lrnd, b0, b1, kp + 9 * nc); + } +#else + { aes_32t rnd; + + state_in(b0, in_blk, kp); + +#if (ENC_UNROLL == PARTIAL) + + for (rnd = 0; rnd < (cx->n_rnd - 1) >> 1; ++rnd) { + kp += nc; + round(fwd_rnd, b1, b0, kp); + kp += nc; + round(fwd_rnd, b0, b1, kp); + } + + if (cx->n_rnd & 1) { + l_copy(b1, b0); + } else { + kp += nc; + round(fwd_rnd, b1, b0, kp); + } +#else + for (rnd = 0; rnd < cx->n_rnd - 1; ++rnd) { + kp += nc; + round(fwd_rnd, b1, b0, kp); + l_copy(b0, b1); + } +#endif + kp += nc; + round(fwd_lrnd, b0, b1, kp); + } +#endif + + state_out(out_blk, b0); + return aes_good; +} + +#endif + +#if defined(DECRYPTION) + +#define inv_var(x, r, c) \ + (r == 0 ? \ + (c == 0 ? s(x, 0) \ + : c == 1 ? s(x, 1) \ + : c == 2 ? s(x, 2) \ + : c == 3 ? s(x, 3) \ + : c == 4 ? s(x, 4) \ + : c == 5 ? s(x, 5) \ + : c == 6 ? s(x, 6) \ + : s(x, 7)) \ + : r == 1 ? \ + (c == 0 ? nc == 8 ? s(x, 7) : nc == 7 ? s(x, 6) : nc == 6 ? s(x, 5) : nc == 5 ? s(x, 4) : s(x, 3) \ + : c == 1 ? s(x, 0) \ + : c == 2 ? s(x, 1) \ + : c == 3 ? s(x, 2) \ + : c == 4 ? s(x, 3) \ + : c == 5 ? s(x, 4) \ + : c == 6 ? s(x, 5) \ + : s(x, 6)) \ + : r == 2 ? \ + (c == 0 ? nc > 6 ? s(x, 5) : nc == 6 ? s(x, 4) : nc == 5 ? s(x, 3) : s(x, 2) \ + : c == 1 ? nc > 6 ? s(x, 6) : nc == 6 ? s(x, 5) : nc == 5 ? s(x, 4) : s(x, 3) \ + : c == 2 ? nc == 8 ? s(x, 7) : s(x, 0) \ + : c == 3 ? nc == 8 ? s(x, 0) : s(x, 1) \ + : c == 4 ? nc == 8 ? s(x, 1) : s(x, 2) \ + : c == 5 ? nc == 8 ? s(x, 2) : s(x, 3) \ + : c == 6 ? nc == 8 ? s(x, 3) : s(x, 4) \ + : s(x, 4)) \ + : \ + (c == 0 ? nc == 8 ? s(x, 4) : nc == 5 ? s(x, 2) : nc == 4 ? s(x, 1) : s(x, 3) \ + : c == 1 ? nc == 8 ? s(x, 5) : nc == 5 ? s(x, 3) : nc == 4 ? s(x, 2) : s(x, 4) \ + : c == 2 ? nc == 8 ? s(x, 6) : nc == 5 ? s(x, 4) : nc == 4 ? s(x, 3) : s(x, 5) \ + : c == 3 ? nc == 8 ? s(x, 7) : nc == 7 ? s(x, 6) : s(x, 0) \ + : c == 4 ? nc > 6 ? s(x, 0) : s(x, 1) \ + : c == 5 ? nc == 6 ? s(x, 2) : s(x, 1) \ + : c == 6 ? s(x, 2) \ + : s(x, 3))) + +#if defined(IT4_SET) +#undef dec_imvars +#define dec_imvars +#define inv_rnd(y, x, k, c) s(y, c) = (k)[c] ^ four_tables(x, it_tab, inv_var, rf1, c) +#elif defined(IT1_SET) +#undef dec_imvars +#define dec_imvars +#define inv_rnd(y, x, k, c) s(y, c) = (k)[c] ^ one_table(x, upr, it_tab, inv_var, rf1, c) +#else +#define inv_rnd(y, x, k, c) s(y, c) = inv_mcol(no_table(x, inv_s_box, inv_var, rf1, c) ^ (k)[c]) +#endif + +#if defined(IL4_SET) +#define inv_lrnd(y, x, k, c) s(y, c) = (k)[c] ^ four_tables(x, il_tab, inv_var, rf1, c) +#elif defined(IL1_SET) +#define inv_lrnd(y, x, k, c) s(y, c) = (k)[c] ^ one_table(x, ups, il_tab, inv_var, rf1, c) +#else +#define inv_lrnd(y, x, k, c) s(y, c) = no_table(x, inv_s_box, inv_var, rf1, c) ^ (k)[c] +#endif + +aes_rval aes_dec_blk_(const unsigned char in_blk[], unsigned char out_blk[], const aes_ctx cx[1]) +{ + aes_32t locals(b0, b1); + const aes_32t *kp = cx->k_sch + nc * cx->n_rnd; + dec_imvars /* declare variables for inv_mcol() if needed */ + + if (!(cx->n_blk & 2)) { + return aes_bad; + } + +#if (DEC_UNROLL == FULL) + + state_in((cx->n_rnd & 1 ? b1 : b0), in_blk, kp); + kp = cx->k_sch + 9 * nc; + + switch (cx->n_rnd) { + case 14: round(inv_rnd, b1, b0, kp + 4 * nc); + case 13: round(inv_rnd, b0, b1, kp + 3 * nc); + case 12: round(inv_rnd, b1, b0, kp + 2 * nc); + case 11: round(inv_rnd, b0, b1, kp + nc); + case 10: round(inv_rnd, b1, b0, kp ); + round(inv_rnd, b0, b1, kp - nc); + round(inv_rnd, b1, b0, kp - 2 * nc); + round(inv_rnd, b0, b1, kp - 3 * nc); + round(inv_rnd, b1, b0, kp - 4 * nc); + round(inv_rnd, b0, b1, kp - 5 * nc); + round(inv_rnd, b1, b0, kp - 6 * nc); + round(inv_rnd, b0, b1, kp - 7 * nc); + round(inv_rnd, b1, b0, kp - 8 * nc); + round(inv_lrnd, b0, b1, kp - 9 * nc); + } +#else + { aes_32t rnd; + + state_in(b0, in_blk, kp); + +#if (DEC_UNROLL == PARTIAL) + + for (rnd = 0; rnd < (cx->n_rnd - 1) >> 1; ++rnd) { + kp -= nc; + round(inv_rnd, b1, b0, kp); + kp -= nc; + round(inv_rnd, b0, b1, kp); + } + + if (cx->n_rnd & 1) { + l_copy(b1, b0); + } else { + kp -= nc; + round(inv_rnd, b1, b0, kp); + } +#else + for (rnd = 0; rnd < cx->n_rnd - 1; ++rnd) { + kp -= nc; + round(inv_rnd, b1, b0, kp); + l_copy(b0, b1); + } +#endif + kp -= nc; + round(inv_lrnd, b0, b1, kp); + } +#endif + + state_out(out_blk, b0); + return aes_good; +} + +#endif === modified file 'i3/aeshash/aescrypt.c' --- i3/aeshash/aescrypt.c 2009-12-11 22:49:11 +0000 +++ i3/aeshash/aescrypt.c 2010-02-11 11:49:47 +0000 @@ -1,421 +1,421 @@ -/* - ------------------------------------------------------------------------- - Copyright (c) 2001, Dr Brian Gladman <brg@xxxxxxxxxxxxx>, Worcester, UK. - All rights reserved. - - LICENSE TERMS - - The free distribution and use of this software in both source and binary - form is allowed (with or without changes) provided that: - - 1. distributions of this source code include the above copyright - notice, this list of conditions and the following disclaimer; - - 2. distributions in binary form include the above copyright - notice, this list of conditions and the following disclaimer - in the documentation and/or other associated materials; - - 3. the copyright holder's name is not used to endorse products - built using this software without specific written permission. - - DISCLAIMER - - This software is provided 'as is' with no explicit or implied warranties - in respect of its properties, including, but not limited to, correctness - and fitness for purpose. - ------------------------------------------------------------------------- - Issue Date: 29/07/2002 - - This file contains the code for implementing encryption and decryption - for AES (Rijndael) for block and key sizes of 16, 24 and 32 bytes. It - can optionally be replaced by code written in assembler using NASM. -*/ - -#include "aesopt.h" - -#if defined(BLOCK_SIZE) && (BLOCK_SIZE & 7) -#error An illegal block size has been specified. -#endif - -#define unused 77 /* Sunset Strip */ - -#define si(y,x,k,c) s(y,c) = word_in(x + 4 * c) ^ k[c] -#define so(y,x,c) word_out(y + 4 * c, s(x,c)) - -#if BLOCK_SIZE == 16 - -#if defined(ARRAYS) -#define locals(y,x) x[4],y[4] -#else -#define locals(y,x) x##0,x##1,x##2,x##3,y##0,y##1,y##2,y##3 - /* - the following defines prevent the compiler requiring the declaration - of generated but unused variables in the fwd_var and inv_var macros - */ -#define b04 unused -#define b05 unused -#define b06 unused -#define b07 unused -#define b14 unused -#define b15 unused -#define b16 unused -#define b17 unused -#endif -#define l_copy(y, x) s(y,0) = s(x,0); s(y,1) = s(x,1); \ - s(y,2) = s(x,2); s(y,3) = s(x,3); -#define state_in(y,x,k) si(y,x,k,0); si(y,x,k,1); si(y,x,k,2); si(y,x,k,3) -#define state_out(y,x) so(y,x,0); so(y,x,1); so(y,x,2); so(y,x,3) -#define round(rm,y,x,k) rm(y,x,k,0); rm(y,x,k,1); rm(y,x,k,2); rm(y,x,k,3) - -#elif BLOCK_SIZE == 24 - -#if defined(ARRAYS) -#define locals(y,x) x[6],y[6] -#else -#define locals(y,x) x##0,x##1,x##2,x##3,x##4,x##5, \ - y##0,y##1,y##2,y##3,y##4,y##5 -#define b06 unused -#define b07 unused -#define b16 unused -#define b17 unused -#endif -#define l_copy(y, x) s(y,0) = s(x,0); s(y,1) = s(x,1); \ - s(y,2) = s(x,2); s(y,3) = s(x,3); \ - s(y,4) = s(x,4); s(y,5) = s(x,5); -#define state_in(y,x,k) si(y,x,k,0); si(y,x,k,1); si(y,x,k,2); \ - si(y,x,k,3); si(y,x,k,4); si(y,x,k,5) -#define state_out(y,x) so(y,x,0); so(y,x,1); so(y,x,2); \ - so(y,x,3); so(y,x,4); so(y,x,5) -#define round(rm,y,x,k) rm(y,x,k,0); rm(y,x,k,1); rm(y,x,k,2); \ - rm(y,x,k,3); rm(y,x,k,4); rm(y,x,k,5) -#else - -#if defined(ARRAYS) -#define locals(y,x) x[8],y[8] -#else -#define locals(y,x) x##0,x##1,x##2,x##3,x##4,x##5,x##6,x##7, \ - y##0,y##1,y##2,y##3,y##4,y##5,y##6,y##7 -#endif -#define l_copy(y, x) s(y,0) = s(x,0); s(y,1) = s(x,1); \ - s(y,2) = s(x,2); s(y,3) = s(x,3); \ - s(y,4) = s(x,4); s(y,5) = s(x,5); \ - s(y,6) = s(x,6); s(y,7) = s(x,7); - -#if BLOCK_SIZE == 32 - -#define state_in(y,x,k) si(y,x,k,0); si(y,x,k,1); si(y,x,k,2); si(y,x,k,3); \ - si(y,x,k,4); si(y,x,k,5); si(y,x,k,6); si(y,x,k,7) -#define state_out(y,x) so(y,x,0); so(y,x,1); so(y,x,2); so(y,x,3); \ - so(y,x,4); so(y,x,5); so(y,x,6); so(y,x,7) -#define round(rm,y,x,k) rm(y,x,k,0); rm(y,x,k,1); rm(y,x,k,2); rm(y,x,k,3); \ - rm(y,x,k,4); rm(y,x,k,5); rm(y,x,k,6); rm(y,x,k,7) -#else - -#define state_in(y,x,k) \ -switch(nc) \ -{ case 8: si(y,x,k,7); si(y,x,k,6); \ - case 6: si(y,x,k,5); si(y,x,k,4); \ - case 4: si(y,x,k,3); si(y,x,k,2); \ - si(y,x,k,1); si(y,x,k,0); \ -} - -#define state_out(y,x) \ -switch(nc) \ -{ case 8: so(y,x,7); so(y,x,6); \ - case 6: so(y,x,5); so(y,x,4); \ - case 4: so(y,x,3); so(y,x,2); \ - so(y,x,1); so(y,x,0); \ -} - -#if defined(FAST_VARIABLE) - -#define round(rm,y,x,k) \ -switch(nc) \ -{ case 8: rm(y,x,k,7); rm(y,x,k,6); \ - rm(y,x,k,5); rm(y,x,k,4); \ - rm(y,x,k,3); rm(y,x,k,2); \ - rm(y,x,k,1); rm(y,x,k,0); \ - break; \ - case 6: rm(y,x,k,5); rm(y,x,k,4); \ - rm(y,x,k,3); rm(y,x,k,2); \ - rm(y,x,k,1); rm(y,x,k,0); \ - break; \ - case 4: rm(y,x,k,3); rm(y,x,k,2); \ - rm(y,x,k,1); rm(y,x,k,0); \ - break; \ -} -#else - -#define round(rm,y,x,k) \ -switch(nc) \ -{ case 8: rm(y,x,k,7); rm(y,x,k,6); \ - case 6: rm(y,x,k,5); rm(y,x,k,4); \ - case 4: rm(y,x,k,3); rm(y,x,k,2); \ - rm(y,x,k,1); rm(y,x,k,0); \ -} - -#endif - -#endif -#endif - -#if defined(ENCRYPTION) - -/* I am grateful to Frank Yellin for the following construction - (and that for decryption) which, given the column (c) of the - output state variable, gives the input state variables which - are needed in its computation for each row (r) of the state. - - For the fixed block size options, compilers should be able to - reduce this complex expression (and the equivalent one for - decryption) to a static variable reference at compile time. - But for variable block size code, there will be some limbs on - which conditional clauses will be returned. -*/ - -/* y = output word, x = input word, r = row, c = column for r = 0, - 1, 2 and 3 = column accessed for row r. -*/ - -#define fwd_var(x,r,c)\ - ( r == 0 ? \ - ( c == 0 ? s(x,0) \ - : c == 1 ? s(x,1) \ - : c == 2 ? s(x,2) \ - : c == 3 ? s(x,3) \ - : c == 4 ? s(x,4) \ - : c == 5 ? s(x,5) \ - : c == 6 ? s(x,6) \ - : s(x,7))\ - : r == 1 ? \ - ( c == 0 ? s(x,1) \ - : c == 1 ? s(x,2) \ - : c == 2 ? s(x,3) \ - : c == 3 ? nc == 4 ? s(x,0) : s(x,4) \ - : c == 4 ? s(x,5) \ - : c == 5 ? nc == 8 ? s(x,6) : s(x,0) \ - : c == 6 ? s(x,7) \ - : s(x,0))\ - : r == 2 ? \ - ( c == 0 ? nc == 8 ? s(x,3) : s(x,2) \ - : c == 1 ? nc == 8 ? s(x,4) : s(x,3) \ - : c == 2 ? nc == 4 ? s(x,0) : nc == 8 ? s(x,5) : s(x,4) \ - : c == 3 ? nc == 4 ? s(x,1) : nc == 8 ? s(x,6) : s(x,5) \ - : c == 4 ? nc == 8 ? s(x,7) : s(x,0) \ - : c == 5 ? nc == 8 ? s(x,0) : s(x,1) \ - : c == 6 ? s(x,1) \ - : s(x,2))\ - : \ - ( c == 0 ? nc == 8 ? s(x,4) : s(x,3) \ - : c == 1 ? nc == 4 ? s(x,0) : nc == 8 ? s(x,5) : s(x,4) \ - : c == 2 ? nc == 4 ? s(x,1) : nc == 8 ? s(x,6) : s(x,5) \ - : c == 3 ? nc == 4 ? s(x,2) : nc == 8 ? s(x,7) : s(x,0) \ - : c == 4 ? nc == 8 ? s(x,0) : s(x,1) \ - : c == 5 ? nc == 8 ? s(x,1) : s(x,2) \ - : c == 6 ? s(x,2) \ - : s(x,3))) - -#if defined(FT4_SET) -#undef dec_fmvars -#define dec_fmvars -#define fwd_rnd(y,x,k,c) s(y,c)= (k)[c] ^ four_tables(x,ft_tab,fwd_var,rf1,c) -#elif defined(FT1_SET) -#undef dec_fmvars -#define dec_fmvars -#define fwd_rnd(y,x,k,c) s(y,c)= (k)[c] ^ one_table(x,upr,ft_tab,fwd_var,rf1,c) -#else -#define fwd_rnd(y,x,k,c) s(y,c) = fwd_mcol(no_table(x,s_box,fwd_var,rf1,c)) ^ (k)[c] -#endif - -#if defined(FL4_SET) -#define fwd_lrnd(y,x,k,c) s(y,c)= (k)[c] ^ four_tables(x,fl_tab,fwd_var,rf1,c) -#elif defined(FL1_SET) -#define fwd_lrnd(y,x,k,c) s(y,c)= (k)[c] ^ one_table(x,ups,fl_tab,fwd_var,rf1,c) -#else -#define fwd_lrnd(y,x,k,c) s(y,c) = no_table(x,s_box,fwd_var,rf1,c) ^ (k)[c] -#endif - -aes_rval aes_enc_blk(const unsigned char in_blk[], unsigned char out_blk[], const aes_ctx cx[1]) -{ aes_32t locals(b0, b1); - const aes_32t *kp = cx->k_sch; - dec_fmvars /* declare variables for fwd_mcol() if needed */ - - if(!(cx->n_blk & 1)) return aes_bad; - - state_in(b0, in_blk, kp); - -#if (ENC_UNROLL == FULL) - - kp += (cx->n_rnd - 9) * nc; - - switch(cx->n_rnd) - { - case 14: round(fwd_rnd, b1, b0, kp - 4 * nc); - round(fwd_rnd, b0, b1, kp - 3 * nc); - case 12: round(fwd_rnd, b1, b0, kp - 2 * nc); - round(fwd_rnd, b0, b1, kp - nc); - case 10: round(fwd_rnd, b1, b0, kp ); - round(fwd_rnd, b0, b1, kp + nc); - round(fwd_rnd, b1, b0, kp + 2 * nc); - round(fwd_rnd, b0, b1, kp + 3 * nc); - round(fwd_rnd, b1, b0, kp + 4 * nc); - round(fwd_rnd, b0, b1, kp + 5 * nc); - round(fwd_rnd, b1, b0, kp + 6 * nc); - round(fwd_rnd, b0, b1, kp + 7 * nc); - round(fwd_rnd, b1, b0, kp + 8 * nc); - round(fwd_lrnd, b0, b1, kp + 9 * nc); - } -#else - -#if (ENC_UNROLL == PARTIAL) - { aes_32t rnd; - for(rnd = 0; rnd < (cx->n_rnd >> 1) - 1; ++rnd) - { - kp += nc; - round(fwd_rnd, b1, b0, kp); - kp += nc; - round(fwd_rnd, b0, b1, kp); - } - kp += nc; - round(fwd_rnd, b1, b0, kp); -#else - { aes_32t rnd, *p0 = b0, *p1 = b1, *pt; - for(rnd = 0; rnd < cx->n_rnd - 1; ++rnd) - { - kp += nc; - round(fwd_rnd, p1, p0, kp); - pt = p0, p0 = p1, p1 = pt; - } -#endif - kp += nc; - round(fwd_lrnd, b0, b1, kp); - } -#endif - - state_out(out_blk, b0); - return aes_good; -} - -#endif - -#if defined(DECRYPTION) - -#define inv_var(x,r,c) \ - ( r == 0 ? \ - ( c == 0 ? s(x,0) \ - : c == 1 ? s(x,1) \ - : c == 2 ? s(x,2) \ - : c == 3 ? s(x,3) \ - : c == 4 ? s(x,4) \ - : c == 5 ? s(x,5) \ - : c == 6 ? s(x,6) \ - : s(x,7))\ - : r == 1 ? \ - ( c == 0 ? nc == 4 ? s(x,3) : nc == 8 ? s(x,7) : s(x,5) \ - : c == 1 ? s(x,0) \ - : c == 2 ? s(x,1) \ - : c == 3 ? s(x,2) \ - : c == 4 ? s(x,3) \ - : c == 5 ? s(x,4) \ - : c == 6 ? s(x,5) \ - : s(x,6))\ - : r == 2 ? \ - ( c == 0 ? nc == 4 ? s(x,2) : nc == 8 ? s(x,5) : s(x,4) \ - : c == 1 ? nc == 4 ? s(x,3) : nc == 8 ? s(x,6) : s(x,5) \ - : c == 2 ? nc == 8 ? s(x,7) : s(x,0) \ - : c == 3 ? nc == 8 ? s(x,0) : s(x,1) \ - : c == 4 ? nc == 8 ? s(x,1) : s(x,2) \ - : c == 5 ? nc == 8 ? s(x,2) : s(x,3) \ - : c == 6 ? s(x,3) \ - : s(x,4))\ - : \ - ( c == 0 ? nc == 4 ? s(x,1) : nc == 8 ? s(x,4) : s(x,3) \ - : c == 1 ? nc == 4 ? s(x,2) : nc == 8 ? s(x,5) : s(x,4) \ - : c == 2 ? nc == 4 ? s(x,3) : nc == 8 ? s(x,6) : s(x,5) \ - : c == 3 ? nc == 8 ? s(x,7) : s(x,0) \ - : c == 4 ? nc == 8 ? s(x,0) : s(x,1) \ - : c == 5 ? nc == 8 ? s(x,1) : s(x,2) \ - : c == 6 ? s(x,2) \ - : s(x,3))) - -#if defined(IT4_SET) -#undef dec_imvars -#define dec_imvars -#define inv_rnd(y,x,k,c) s(y,c)= (k)[c] ^ four_tables(x,it_tab,inv_var,rf1,c) -#elif defined(IT1_SET) -#undef dec_imvars -#define dec_imvars -#define inv_rnd(y,x,k,c) s(y,c)= (k)[c] ^ one_table(x,upr,it_tab,inv_var,rf1,c) -#else -#define inv_rnd(y,x,k,c) s(y,c) = inv_mcol(no_table(x,inv_s_box,inv_var,rf1,c) ^ (k)[c]) -#endif - -#if defined(IL4_SET) -#define inv_lrnd(y,x,k,c) s(y,c)= (k)[c] ^ four_tables(x,il_tab,inv_var,rf1,c) -#elif defined(IL1_SET) -#define inv_lrnd(y,x,k,c) s(y,c)= (k)[c] ^ one_table(x,ups,il_tab,inv_var,rf1,c) -#else -#define inv_lrnd(y,x,k,c) s(y,c) = no_table(x,inv_s_box,inv_var,rf1,c) ^ (k)[c] -#endif - -aes_rval aes_dec_blk(const unsigned char in_blk[], unsigned char out_blk[], const aes_ctx cx[1]) -{ aes_32t locals(b0, b1); - const aes_32t *kp = cx->k_sch + nc * cx->n_rnd; - dec_imvars /* declare variables for inv_mcol() if needed */ - - if(!(cx->n_blk & 2)) return aes_bad; - - state_in(b0, in_blk, kp); - -#if (DEC_UNROLL == FULL) - - kp = cx->k_sch + 9 * nc; - switch(cx->n_rnd) - { - case 14: round(inv_rnd, b1, b0, kp + 4 * nc); - round(inv_rnd, b0, b1, kp + 3 * nc); - case 12: round(inv_rnd, b1, b0, kp + 2 * nc); - round(inv_rnd, b0, b1, kp + nc ); - case 10: round(inv_rnd, b1, b0, kp ); - round(inv_rnd, b0, b1, kp - nc); - round(inv_rnd, b1, b0, kp - 2 * nc); - round(inv_rnd, b0, b1, kp - 3 * nc); - round(inv_rnd, b1, b0, kp - 4 * nc); - round(inv_rnd, b0, b1, kp - 5 * nc); - round(inv_rnd, b1, b0, kp - 6 * nc); - round(inv_rnd, b0, b1, kp - 7 * nc); - round(inv_rnd, b1, b0, kp - 8 * nc); - round(inv_lrnd, b0, b1, kp - 9 * nc); - } -#else - -#if (DEC_UNROLL == PARTIAL) - { aes_32t rnd; - for(rnd = 0; rnd < (cx->n_rnd >> 1) - 1; ++rnd) - { - kp -= nc; - round(inv_rnd, b1, b0, kp); - kp -= nc; - round(inv_rnd, b0, b1, kp); - } - kp -= nc; - round(inv_rnd, b1, b0, kp); -#else - { aes_32t rnd, *p0 = b0, *p1 = b1, *pt; - for(rnd = 0; rnd < cx->n_rnd - 1; ++rnd) - { - kp -= nc; - round(inv_rnd, p1, p0, kp); - pt = p0, p0 = p1, p1 = pt; - } -#endif - kp -= nc; - round(inv_lrnd, b0, b1, kp); - } -#endif - - state_out(out_blk, b0); - return aes_good; -} - -#endif +/* + * ------------------------------------------------------------------------- + * Copyright (c) 2001, Dr Brian Gladman <brg@xxxxxxxxxxxxx>, Worcester, UK. + * All rights reserved. + * + * LICENSE TERMS + * + * The free distribution and use of this software in both source and binary + * form is allowed (with or without changes) provided that: + * + * 1. distributions of this source code include the above copyright + * notice, this list of conditions and the following disclaimer; + * + * 2. distributions in binary form include the above copyright + * notice, this list of conditions and the following disclaimer + * in the documentation and/or other associated materials; + * + * 3. the copyright holder's name is not used to endorse products + * built using this software without specific written permission. + * + * DISCLAIMER + * + * This software is provided 'as is' with no explicit or implied warranties + * in respect of its properties, including, but not limited to, correctness + * and fitness for purpose. + * ------------------------------------------------------------------------- + * Issue Date: 29/07/2002 + * + * This file contains the code for implementing encryption and decryption + * for AES (Rijndael) for block and key sizes of 16, 24 and 32 bytes. It + * can optionally be replaced by code written in assembler using NASM. + */ + +#include "aesopt.h" + +#if defined(BLOCK_SIZE) && (BLOCK_SIZE & 7) +#error An illegal block size has been specified. +#endif + +#define unused 77 /* Sunset Strip */ + +#define si(y, x, k, c) s(y, c) = word_in(x + 4 * c) ^ k[c] +#define so(y, x, c) word_out(y + 4 * c, s(x, c)) + +#if BLOCK_SIZE == 16 + +#if defined(ARRAYS) +#define locals(y, x) x[4], y[4] +#else +#define locals(y, x) x ## 0, x ## 1, x ## 2, x ## 3, y ## 0, y ## 1, y ## 2, y ## 3 +/* + * the following defines prevent the compiler requiring the declaration + * of generated but unused variables in the fwd_var and inv_var macros + */ +#define b04 unused +#define b05 unused +#define b06 unused +#define b07 unused +#define b14 unused +#define b15 unused +#define b16 unused +#define b17 unused +#endif +#define l_copy(y, x) s(y, 0) = s(x, 0); s(y, 1) = s(x, 1); \ + s(y, 2) = s(x, 2); s(y, 3) = s(x, 3); +#define state_in(y, x, k) si(y, x, k, 0); si(y, x, k, 1); si(y, x, k, 2); si(y, x, k, 3) +#define state_out(y, x) so(y, x, 0); so(y, x, 1); so(y, x, 2); so(y, x, 3) +#define round(rm, y, x, k) rm(y, x, k, 0); rm(y, x, k, 1); rm(y, x, k, 2); rm(y, x, k, 3) + +#elif BLOCK_SIZE == 24 + +#if defined(ARRAYS) +#define locals(y, x) x[6], y[6] +#else +#define locals(y, x) x ## 0, x ## 1, x ## 2, x ## 3, x ## 4, x ## 5, \ + y ## 0, y ## 1, y ## 2, y ## 3, y ## 4, y ## 5 +#define b06 unused +#define b07 unused +#define b16 unused +#define b17 unused +#endif +#define l_copy(y, x) s(y, 0) = s(x, 0); s(y, 1) = s(x, 1); \ + s(y, 2) = s(x, 2); s(y, 3) = s(x, 3); \ + s(y, 4) = s(x, 4); s(y, 5) = s(x, 5); +#define state_in(y, x, k) si(y, x, k, 0); si(y, x, k, 1); si(y, x, k, 2); \ + si(y, x, k, 3); si(y, x, k, 4); si(y, x, k, 5) +#define state_out(y, x) so(y, x, 0); so(y, x, 1); so(y, x, 2); \ + so(y, x, 3); so(y, x, 4); so(y, x, 5) +#define round(rm, y, x, k) rm(y, x, k, 0); rm(y, x, k, 1); rm(y, x, k, 2); \ + rm(y, x, k, 3); rm(y, x, k, 4); rm(y, x, k, 5) +#else + +#if defined(ARRAYS) +#define locals(y, x) x[8], y[8] +#else +#define locals(y, x) x ## 0, x ## 1, x ## 2, x ## 3, x ## 4, x ## 5, x ## 6, x ## 7, \ + y ## 0, y ## 1, y ## 2, y ## 3, y ## 4, y ## 5, y ## 6, y ## 7 +#endif +#define l_copy(y, x) s(y, 0) = s(x, 0); s(y, 1) = s(x, 1); \ + s(y, 2) = s(x, 2); s(y, 3) = s(x, 3); \ + s(y, 4) = s(x, 4); s(y, 5) = s(x, 5); \ + s(y, 6) = s(x, 6); s(y, 7) = s(x, 7); + +#if BLOCK_SIZE == 32 + +#define state_in(y, x, k) si(y, x, k, 0); si(y, x, k, 1); si(y, x, k, 2); si(y, x, k, 3); \ + si(y, x, k, 4); si(y, x, k, 5); si(y, x, k, 6); si(y, x, k, 7) +#define state_out(y, x) so(y, x, 0); so(y, x, 1); so(y, x, 2); so(y, x, 3); \ + so(y, x, 4); so(y, x, 5); so(y, x, 6); so(y, x, 7) +#define round(rm, y, x, k) rm(y, x, k, 0); rm(y, x, k, 1); rm(y, x, k, 2); rm(y, x, k, 3); \ + rm(y, x, k, 4); rm(y, x, k, 5); rm(y, x, k, 6); rm(y, x, k, 7) +#else + +#define state_in(y, x, k) \ + switch (nc) \ + { case 8: si(y, x, k, 7); si(y, x, k, 6); \ + case 6: si(y, x, k, 5); si(y, x, k, 4); \ + case 4: si(y, x, k, 3); si(y, x, k, 2); \ + si(y, x, k, 1); si(y, x, k, 0); \ + } + +#define state_out(y, x) \ + switch (nc) \ + { case 8: so(y, x, 7); so(y, x, 6); \ + case 6: so(y, x, 5); so(y, x, 4); \ + case 4: so(y, x, 3); so(y, x, 2); \ + so(y, x, 1); so(y, x, 0); \ + } + +#if defined(FAST_VARIABLE) + +#define round(rm, y, x, k) \ + switch (nc) \ + { case 8: rm(y, x, k, 7); rm(y, x, k, 6); \ + rm(y, x, k, 5); rm(y, x, k, 4); \ + rm(y, x, k, 3); rm(y, x, k, 2); \ + rm(y, x, k, 1); rm(y, x, k, 0); \ + break; \ + case 6: rm(y, x, k, 5); rm(y, x, k, 4); \ + rm(y, x, k, 3); rm(y, x, k, 2); \ + rm(y, x, k, 1); rm(y, x, k, 0); \ + break; \ + case 4: rm(y, x, k, 3); rm(y, x, k, 2); \ + rm(y, x, k, 1); rm(y, x, k, 0); \ + break; \ + } +#else + +#define round(rm, y, x, k) \ + switch (nc) \ + { case 8: rm(y, x, k, 7); rm(y, x, k, 6); \ + case 6: rm(y, x, k, 5); rm(y, x, k, 4); \ + case 4: rm(y, x, k, 3); rm(y, x, k, 2); \ + rm(y, x, k, 1); rm(y, x, k, 0); \ + } + +#endif + +#endif +#endif + +#if defined(ENCRYPTION) + +/* I am grateful to Frank Yellin for the following construction + * (and that for decryption) which, given the column (c) of the + * output state variable, gives the input state variables which + * are needed in its computation for each row (r) of the state. + * + * For the fixed block size options, compilers should be able to + * reduce this complex expression (and the equivalent one for + * decryption) to a static variable reference at compile time. + * But for variable block size code, there will be some limbs on + * which conditional clauses will be returned. + */ + +/* y = output word, x = input word, r = row, c = column for r = 0, + * 1, 2 and 3 = column accessed for row r. + */ + +#define fwd_var(x, r, c) \ + (r == 0 ? \ + (c == 0 ? s(x, 0) \ + : c == 1 ? s(x, 1) \ + : c == 2 ? s(x, 2) \ + : c == 3 ? s(x, 3) \ + : c == 4 ? s(x, 4) \ + : c == 5 ? s(x, 5) \ + : c == 6 ? s(x, 6) \ + : s(x, 7)) \ + : r == 1 ? \ + (c == 0 ? s(x, 1) \ + : c == 1 ? s(x, 2) \ + : c == 2 ? s(x, 3) \ + : c == 3 ? nc == 4 ? s(x, 0) : s(x, 4) \ + : c == 4 ? s(x, 5) \ + : c == 5 ? nc == 8 ? s(x, 6) : s(x, 0) \ + : c == 6 ? s(x, 7) \ + : s(x, 0)) \ + : r == 2 ? \ + (c == 0 ? nc == 8 ? s(x, 3) : s(x, 2) \ + : c == 1 ? nc == 8 ? s(x, 4) : s(x, 3) \ + : c == 2 ? nc == 4 ? s(x, 0) : nc == 8 ? s(x, 5) : s(x, 4) \ + : c == 3 ? nc == 4 ? s(x, 1) : nc == 8 ? s(x, 6) : s(x, 5) \ + : c == 4 ? nc == 8 ? s(x, 7) : s(x, 0) \ + : c == 5 ? nc == 8 ? s(x, 0) : s(x, 1) \ + : c == 6 ? s(x, 1) \ + : s(x, 2)) \ + : \ + (c == 0 ? nc == 8 ? s(x, 4) : s(x, 3) \ + : c == 1 ? nc == 4 ? s(x, 0) : nc == 8 ? s(x, 5) : s(x, 4) \ + : c == 2 ? nc == 4 ? s(x, 1) : nc == 8 ? s(x, 6) : s(x, 5) \ + : c == 3 ? nc == 4 ? s(x, 2) : nc == 8 ? s(x, 7) : s(x, 0) \ + : c == 4 ? nc == 8 ? s(x, 0) : s(x, 1) \ + : c == 5 ? nc == 8 ? s(x, 1) : s(x, 2) \ + : c == 6 ? s(x, 2) \ + : s(x, 3))) + +#if defined(FT4_SET) +#undef dec_fmvars +#define dec_fmvars +#define fwd_rnd(y, x, k, c) s(y, c) = (k)[c] ^ four_tables(x, ft_tab, fwd_var, rf1, c) +#elif defined(FT1_SET) +#undef dec_fmvars +#define dec_fmvars +#define fwd_rnd(y, x, k, c) s(y, c) = (k)[c] ^ one_table(x, upr, ft_tab, fwd_var, rf1, c) +#else +#define fwd_rnd(y, x, k, c) s(y, c) = fwd_mcol(no_table(x, s_box, fwd_var, rf1, c)) ^ (k)[c] +#endif + +#if defined(FL4_SET) +#define fwd_lrnd(y, x, k, c) s(y, c) = (k)[c] ^ four_tables(x, fl_tab, fwd_var, rf1, c) +#elif defined(FL1_SET) +#define fwd_lrnd(y, x, k, c) s(y, c) = (k)[c] ^ one_table(x, ups, fl_tab, fwd_var, rf1, c) +#else +#define fwd_lrnd(y, x, k, c) s(y, c) = no_table(x, s_box, fwd_var, rf1, c) ^ (k)[c] +#endif + +aes_rval aes_enc_blk(const unsigned char in_blk[], unsigned char out_blk[], const aes_ctx cx[1]) +{ + aes_32t locals(b0, b1); + const aes_32t *kp = cx->k_sch; + dec_fmvars /* declare variables for fwd_mcol() if needed */ + + if (!(cx->n_blk & 1)) { + return aes_bad; + } + + state_in(b0, in_blk, kp); + +#if (ENC_UNROLL == FULL) + + kp += (cx->n_rnd - 9) * nc; + + switch (cx->n_rnd) { + case 14: round(fwd_rnd, b1, b0, kp - 4 * nc); + round(fwd_rnd, b0, b1, kp - 3 * nc); + case 12: round(fwd_rnd, b1, b0, kp - 2 * nc); + round(fwd_rnd, b0, b1, kp - nc); + case 10: round(fwd_rnd, b1, b0, kp ); + round(fwd_rnd, b0, b1, kp + nc); + round(fwd_rnd, b1, b0, kp + 2 * nc); + round(fwd_rnd, b0, b1, kp + 3 * nc); + round(fwd_rnd, b1, b0, kp + 4 * nc); + round(fwd_rnd, b0, b1, kp + 5 * nc); + round(fwd_rnd, b1, b0, kp + 6 * nc); + round(fwd_rnd, b0, b1, kp + 7 * nc); + round(fwd_rnd, b1, b0, kp + 8 * nc); + round(fwd_lrnd, b0, b1, kp + 9 * nc); + } +#else + +#if (ENC_UNROLL == PARTIAL) + { aes_32t rnd; + for (rnd = 0; rnd < (cx->n_rnd >> 1) - 1; ++rnd) { + kp += nc; + round(fwd_rnd, b1, b0, kp); + kp += nc; + round(fwd_rnd, b0, b1, kp); + } + kp += nc; + round(fwd_rnd, b1, b0, kp); +#else + { aes_32t rnd, *p0 = b0, *p1 = b1, *pt; + for (rnd = 0; rnd < cx->n_rnd - 1; ++rnd) { + kp += nc; + round(fwd_rnd, p1, p0, kp); + pt = p0, p0 = p1, p1 = pt; + } +#endif + kp += nc; + round(fwd_lrnd, b0, b1, kp); + } +#endif + + state_out(out_blk, b0); + return aes_good; +} + +#endif + +#if defined(DECRYPTION) + +#define inv_var(x, r, c) \ + (r == 0 ? \ + (c == 0 ? s(x, 0) \ + : c == 1 ? s(x, 1) \ + : c == 2 ? s(x, 2) \ + : c == 3 ? s(x, 3) \ + : c == 4 ? s(x, 4) \ + : c == 5 ? s(x, 5) \ + : c == 6 ? s(x, 6) \ + : s(x, 7)) \ + : r == 1 ? \ + (c == 0 ? nc == 4 ? s(x, 3) : nc == 8 ? s(x, 7) : s(x, 5) \ + : c == 1 ? s(x, 0) \ + : c == 2 ? s(x, 1) \ + : c == 3 ? s(x, 2) \ + : c == 4 ? s(x, 3) \ + : c == 5 ? s(x, 4) \ + : c == 6 ? s(x, 5) \ + : s(x, 6)) \ + : r == 2 ? \ + (c == 0 ? nc == 4 ? s(x, 2) : nc == 8 ? s(x, 5) : s(x, 4) \ + : c == 1 ? nc == 4 ? s(x, 3) : nc == 8 ? s(x, 6) : s(x, 5) \ + : c == 2 ? nc == 8 ? s(x, 7) : s(x, 0) \ + : c == 3 ? nc == 8 ? s(x, 0) : s(x, 1) \ + : c == 4 ? nc == 8 ? s(x, 1) : s(x, 2) \ + : c == 5 ? nc == 8 ? s(x, 2) : s(x, 3) \ + : c == 6 ? s(x, 3) \ + : s(x, 4)) \ + : \ + (c == 0 ? nc == 4 ? s(x, 1) : nc == 8 ? s(x, 4) : s(x, 3) \ + : c == 1 ? nc == 4 ? s(x, 2) : nc == 8 ? s(x, 5) : s(x, 4) \ + : c == 2 ? nc == 4 ? s(x, 3) : nc == 8 ? s(x, 6) : s(x, 5) \ + : c == 3 ? nc == 8 ? s(x, 7) : s(x, 0) \ + : c == 4 ? nc == 8 ? s(x, 0) : s(x, 1) \ + : c == 5 ? nc == 8 ? s(x, 1) : s(x, 2) \ + : c == 6 ? s(x, 2) \ + : s(x, 3))) + +#if defined(IT4_SET) +#undef dec_imvars +#define dec_imvars +#define inv_rnd(y, x, k, c) s(y, c) = (k)[c] ^ four_tables(x, it_tab, inv_var, rf1, c) +#elif defined(IT1_SET) +#undef dec_imvars +#define dec_imvars +#define inv_rnd(y, x, k, c) s(y, c) = (k)[c] ^ one_table(x, upr, it_tab, inv_var, rf1, c) +#else +#define inv_rnd(y, x, k, c) s(y, c) = inv_mcol(no_table(x, inv_s_box, inv_var, rf1, c) ^ (k)[c]) +#endif + +#if defined(IL4_SET) +#define inv_lrnd(y, x, k, c) s(y, c) = (k)[c] ^ four_tables(x, il_tab, inv_var, rf1, c) +#elif defined(IL1_SET) +#define inv_lrnd(y, x, k, c) s(y, c) = (k)[c] ^ one_table(x, ups, il_tab, inv_var, rf1, c) +#else +#define inv_lrnd(y, x, k, c) s(y, c) = no_table(x, inv_s_box, inv_var, rf1, c) ^ (k)[c] +#endif + +aes_rval aes_dec_blk(const unsigned char in_blk[], unsigned char out_blk[], const aes_ctx cx[1]) +{ + aes_32t locals(b0, b1); + const aes_32t *kp = cx->k_sch + nc * cx->n_rnd; + dec_imvars /* declare variables for inv_mcol() if needed */ + + if (!(cx->n_blk & 2)) { + return aes_bad; + } + + state_in(b0, in_blk, kp); + +#if (DEC_UNROLL == FULL) + + kp = cx->k_sch + 9 * nc; + switch (cx->n_rnd) { + case 14: round(inv_rnd, b1, b0, kp + 4 * nc); + round(inv_rnd, b0, b1, kp + 3 * nc); + case 12: round(inv_rnd, b1, b0, kp + 2 * nc); + round(inv_rnd, b0, b1, kp + nc ); + case 10: round(inv_rnd, b1, b0, kp ); + round(inv_rnd, b0, b1, kp - nc); + round(inv_rnd, b1, b0, kp - 2 * nc); + round(inv_rnd, b0, b1, kp - 3 * nc); + round(inv_rnd, b1, b0, kp - 4 * nc); + round(inv_rnd, b0, b1, kp - 5 * nc); + round(inv_rnd, b1, b0, kp - 6 * nc); + round(inv_rnd, b0, b1, kp - 7 * nc); + round(inv_rnd, b1, b0, kp - 8 * nc); + round(inv_lrnd, b0, b1, kp - 9 * nc); + } +#else + +#if (DEC_UNROLL == PARTIAL) + { aes_32t rnd; + for (rnd = 0; rnd < (cx->n_rnd >> 1) - 1; ++rnd) { + kp -= nc; + round(inv_rnd, b1, b0, kp); + kp -= nc; + round(inv_rnd, b0, b1, kp); + } + kp -= nc; + round(inv_rnd, b1, b0, kp); +#else + { aes_32t rnd, *p0 = b0, *p1 = b1, *pt; + for (rnd = 0; rnd < cx->n_rnd - 1; ++rnd) { + kp -= nc; + round(inv_rnd, p1, p0, kp); + pt = p0, p0 = p1, p1 = pt; + } +#endif + kp -= nc; + round(inv_lrnd, b0, b1, kp); + } +#endif + + state_out(out_blk, b0); + return aes_good; +} + +#endif === modified file 'i3/aeshash/aeshash.c' --- i3/aeshash/aeshash.c 2009-12-11 22:49:11 +0000 +++ i3/aeshash/aeshash.c 2010-02-11 11:49:47 +0000 @@ -1,45 +1,48 @@ -#include <stdio.h> -#include <stdlib.h> -#include <ctype.h> -#include <string.h> - -#include "aes.h" - -enum { - l_c = 0, - r_c = 1 -}; - -static const unsigned char key[2][32] = {{0x23, 0xce, 0x45, 0x19, 0xc5, 0xb6, 0xb5, 0x82, - 0x19, 0x14, 0x36, 0x26, 0xa4, 0xe0, 0x9c, 0xa2}, - {0x20, 0xce, 0x49, 0x19, 0xc5, 0xb6, 0xd5, 0xe2, - 0xb6, 0x1d, 0xf6, 0x56, 0xa5, 0xef, 0xfc, 0xe2}}; -static aes_ctx ctx[2]; - -void aeshash_type(const unsigned char in[], unsigned char out[], int type) -{ - memset(out, 0, BLOCK_SIZE); - aes_enc_blk(in, out, ctx + type); - ((unsigned __int64 *) out)[0] ^= ((unsigned __int64 *) in)[0]; - ((unsigned __int64 *) out)[1] ^= ((unsigned __int64 *) in)[1]; -} -void aeshash_l(const unsigned char in[], unsigned char out[]) -{ - aeshash_type(in, out, l_c); -} -void aeshash_r(const unsigned char in[], unsigned char out[]) -{ - aeshash_type(in, out, r_c); -} - -void aeshash_init_type(int type) -{ - ctx[type].n_rnd = 0; // ensure all flags are initially set to zero - ctx[type].n_blk = 0; - aes_enc_key(key[type], 16, ctx + type); -} -void aeshash_init(void) -{ - aeshash_init_type(l_c); - aeshash_init_type(r_c); -} +#include <stdio.h> +#include <stdlib.h> +#include <ctype.h> +#include <string.h> + +#include "aes.h" + +enum { + l_c = 0, + r_c = 1 +}; + +static const unsigned char key[2][32] = {{0x23, 0xce, 0x45, 0x19, 0xc5, 0xb6, 0xb5, 0x82, + 0x19, 0x14, 0x36, 0x26, 0xa4, 0xe0, 0x9c, 0xa2}, + {0x20, 0xce, 0x49, 0x19, 0xc5, 0xb6, 0xd5, 0xe2, + 0xb6, 0x1d, 0xf6, 0x56, 0xa5, 0xef, 0xfc, 0xe2}}; +static aes_ctx ctx[2]; + +void aeshash_type(const unsigned char in[], unsigned char out[], int type) +{ + memset(out, 0, BLOCK_SIZE); + aes_enc_blk(in, out, ctx + type); + ((unsigned __int64 *) out)[0] ^= ((unsigned __int64 *) in)[0]; + ((unsigned __int64 *) out)[1] ^= ((unsigned __int64 *) in)[1]; +} + +void aeshash_l(const unsigned char in[], unsigned char out[]) +{ + aeshash_type(in, out, l_c); +} + +void aeshash_r(const unsigned char in[], unsigned char out[]) +{ + aeshash_type(in, out, r_c); +} + +void aeshash_init_type(int type) +{ + ctx[type].n_rnd = 0; // ensure all flags are initially set to zero + ctx[type].n_blk = 0; + aes_enc_key(key[type], 16, ctx + type); +} + +void aeshash_init(void) +{ + aeshash_init_type(l_c); + aeshash_init_type(r_c); +} === modified file 'i3/aeshash/aeskey.c' --- i3/aeshash/aeskey.c 2009-12-11 22:49:11 +0000 +++ i3/aeshash/aeskey.c 2010-02-11 11:49:47 +0000 @@ -1,363 +1,412 @@ -/* - ------------------------------------------------------------------------- - Copyright (c) 2001, Dr Brian Gladman <brg@xxxxxxxxxxxxx>, Worcester, UK. - All rights reserved. - - LICENSE TERMS - - The free distribution and use of this software in both source and binary - form is allowed (with or without changes) provided that: - - 1. distributions of this source code include the above copyright - notice, this list of conditions and the following disclaimer; - - 2. distributions in binary form include the above copyright - notice, this list of conditions and the following disclaimer - in the documentation and/or other associated materials; - - 3. the copyright holder's name is not used to endorse products - built using this software without specific written permission. - - DISCLAIMER - - This software is provided 'as is' with no explicit or implied warranties - in respect of its properties, including, but not limited to, correctness - and fitness for purpose. - ------------------------------------------------------------------------- - Issue Date: 29/07/2002 - - This file contains the code for implementing the key schedule for AES - (Rijndael) for block and key sizes of 16, 24, and 32 bytes. -*/ - -#include "aesopt.h" - -#if defined(BLOCK_SIZE) && (BLOCK_SIZE & 7) -#error An illegal block size has been specified. -#endif - -/* Subroutine to set the block size (if variable) in bytes, legal - values being 16, 24 and 32. -*/ - -#if !defined(BLOCK_SIZE) - -aes_rval aes_blk_len(unsigned int blen, aes_ctx cx[1]) -{ -#if !defined(FIXED_TABLES) - if(!tab_init) gen_tabs(); -#endif - - if((blen & 7) || blen < 16 || blen > 32) - { - cx->n_blk = 0; return aes_bad; - } - - cx->n_blk = blen; - return aes_good; -} - -#endif - -/* Initialise the key schedule from the user supplied key. The key - length is now specified in bytes - 16, 24 or 32 as appropriate. - This corresponds to bit lengths of 128, 192 and 256 bits, and - to Nk values of 4, 6 and 8 respectively. - - The following macros implement a single cycle in the key - schedule generation process. The number of cycles needed - for each cx->n_col and nk value is: - - nk = 4 5 6 7 8 - ------------------------------ - cx->n_col = 4 10 9 8 7 7 - cx->n_col = 5 14 11 10 9 9 - cx->n_col = 6 19 15 12 11 11 - cx->n_col = 7 21 19 16 13 14 - cx->n_col = 8 29 23 19 17 14 -*/ - -#define ke4(k,i) \ -{ k[4*(i)+4] = ss[0] ^= ls_box(ss[3],3) ^ rcon_tab[i]; k[4*(i)+5] = ss[1] ^= ss[0]; \ - k[4*(i)+6] = ss[2] ^= ss[1]; k[4*(i)+7] = ss[3] ^= ss[2]; \ -} -#define kel4(k,i) \ -{ k[4*(i)+4] = ss[0] ^= ls_box(ss[3],3) ^ rcon_tab[i]; k[4*(i)+5] = ss[1] ^= ss[0]; \ - k[4*(i)+6] = ss[2] ^= ss[1]; k[4*(i)+7] = ss[3] ^= ss[2]; \ -} - -#define ke6(k,i) \ -{ k[6*(i)+ 6] = ss[0] ^= ls_box(ss[5],3) ^ rcon_tab[i]; k[6*(i)+ 7] = ss[1] ^= ss[0]; \ - k[6*(i)+ 8] = ss[2] ^= ss[1]; k[6*(i)+ 9] = ss[3] ^= ss[2]; \ - k[6*(i)+10] = ss[4] ^= ss[3]; k[6*(i)+11] = ss[5] ^= ss[4]; \ -} -#define kel6(k,i) \ -{ k[6*(i)+ 6] = ss[0] ^= ls_box(ss[5],3) ^ rcon_tab[i]; k[6*(i)+ 7] = ss[1] ^= ss[0]; \ - k[6*(i)+ 8] = ss[2] ^= ss[1]; k[6*(i)+ 9] = ss[3] ^= ss[2]; \ -} - -#define ke8(k,i) \ -{ k[8*(i)+ 8] = ss[0] ^= ls_box(ss[7],3) ^ rcon_tab[i]; k[8*(i)+ 9] = ss[1] ^= ss[0]; \ - k[8*(i)+10] = ss[2] ^= ss[1]; k[8*(i)+11] = ss[3] ^= ss[2]; \ - k[8*(i)+12] = ss[4] ^= ls_box(ss[3],0); k[8*(i)+13] = ss[5] ^= ss[4]; \ - k[8*(i)+14] = ss[6] ^= ss[5]; k[8*(i)+15] = ss[7] ^= ss[6]; \ -} -#define kel8(k,i) \ -{ k[8*(i)+ 8] = ss[0] ^= ls_box(ss[7],3) ^ rcon_tab[i]; k[8*(i)+ 9] = ss[1] ^= ss[0]; \ - k[8*(i)+10] = ss[2] ^= ss[1]; k[8*(i)+11] = ss[3] ^= ss[2]; \ -} - -#if defined(ENCRYPTION_KEY_SCHEDULE) - -aes_rval aes_enc_key(const unsigned char in_key[], unsigned int klen, aes_ctx cx[1]) -{ aes_32t ss[8]; - -#if !defined(FIXED_TABLES) - if(!tab_init) gen_tabs(); -#endif - -#if !defined(BLOCK_SIZE) - if(!cx->n_blk) cx->n_blk = 16; -#else - cx->n_blk = BLOCK_SIZE; -#endif - - cx->n_blk = (cx->n_blk & ~3) | 1; - - cx->k_sch[0] = ss[0] = word_in(in_key ); - cx->k_sch[1] = ss[1] = word_in(in_key + 4); - cx->k_sch[2] = ss[2] = word_in(in_key + 8); - cx->k_sch[3] = ss[3] = word_in(in_key + 12); - -#if (BLOCK_SIZE == 16) && (ENC_UNROLL != NONE) - - switch(klen) - { - case 16: ke4(cx->k_sch, 0); ke4(cx->k_sch, 1); - ke4(cx->k_sch, 2); ke4(cx->k_sch, 3); - ke4(cx->k_sch, 4); ke4(cx->k_sch, 5); - ke4(cx->k_sch, 6); ke4(cx->k_sch, 7); - ke4(cx->k_sch, 8); kel4(cx->k_sch, 9); - cx->n_rnd = 10; break; - case 24: cx->k_sch[4] = ss[4] = word_in(in_key + 16); - cx->k_sch[5] = ss[5] = word_in(in_key + 20); - ke6(cx->k_sch, 0); ke6(cx->k_sch, 1); - ke6(cx->k_sch, 2); ke6(cx->k_sch, 3); - ke6(cx->k_sch, 4); ke6(cx->k_sch, 5); - ke6(cx->k_sch, 6); kel6(cx->k_sch, 7); - cx->n_rnd = 12; break; - case 32: cx->k_sch[4] = ss[4] = word_in(in_key + 16); - cx->k_sch[5] = ss[5] = word_in(in_key + 20); - cx->k_sch[6] = ss[6] = word_in(in_key + 24); - cx->k_sch[7] = ss[7] = word_in(in_key + 28); - ke8(cx->k_sch, 0); ke8(cx->k_sch, 1); - ke8(cx->k_sch, 2); ke8(cx->k_sch, 3); - ke8(cx->k_sch, 4); ke8(cx->k_sch, 5); - kel8(cx->k_sch, 6); - cx->n_rnd = 14; break; - default: cx->n_rnd = 0; return aes_bad; - } -#else - { aes_32t i, l; - cx->n_rnd = ((klen >> 2) > nc ? (klen >> 2) : nc) + 6; - l = (nc * cx->n_rnd + nc - 1) / (klen >> 2); - - switch(klen) - { - case 16: for(i = 0; i < l; ++i) - ke4(cx->k_sch, i); - break; - case 24: cx->k_sch[4] = ss[4] = word_in(in_key + 16); - cx->k_sch[5] = ss[5] = word_in(in_key + 20); - for(i = 0; i < l; ++i) - ke6(cx->k_sch, i); - break; - case 32: cx->k_sch[4] = ss[4] = word_in(in_key + 16); - cx->k_sch[5] = ss[5] = word_in(in_key + 20); - cx->k_sch[6] = ss[6] = word_in(in_key + 24); - cx->k_sch[7] = ss[7] = word_in(in_key + 28); - for(i = 0; i < l; ++i) - ke8(cx->k_sch, i); - break; - default: cx->n_rnd = 0; return aes_bad; - } - } -#endif - - return aes_good; -} - -#endif - -#if defined(DECRYPTION_KEY_SCHEDULE) - -#if (DEC_ROUND != NO_TABLES) -#define d_vars dec_imvars -#define ff(x) inv_mcol(x) -#else -#define ff(x) (x) -#define d_vars -#endif - -#if 1 -#define kdf4(k,i) \ -{ ss[0] = ss[0] ^ ss[2] ^ ss[1] ^ ss[3]; ss[1] = ss[1] ^ ss[3]; ss[2] = ss[2] ^ ss[3]; ss[3] = ss[3]; \ - ss[4] = ls_box(ss[(i+3) % 4], 3) ^ rcon_tab[i]; ss[i % 4] ^= ss[4]; \ - ss[4] ^= k[4*(i)]; k[4*(i)+4] = ff(ss[4]); ss[4] ^= k[4*(i)+1]; k[4*(i)+5] = ff(ss[4]); \ - ss[4] ^= k[4*(i)+2]; k[4*(i)+6] = ff(ss[4]); ss[4] ^= k[4*(i)+3]; k[4*(i)+7] = ff(ss[4]); \ -} -#define kd4(k,i) \ -{ ss[4] = ls_box(ss[(i+3) % 4], 3) ^ rcon_tab[i]; ss[i % 4] ^= ss[4]; ss[4] = ff(ss[4]); \ - k[4*(i)+4] = ss[4] ^= k[4*(i)]; k[4*(i)+5] = ss[4] ^= k[4*(i)+1]; \ - k[4*(i)+6] = ss[4] ^= k[4*(i)+2]; k[4*(i)+7] = ss[4] ^= k[4*(i)+3]; \ -} -#define kdl4(k,i) \ -{ ss[4] = ls_box(ss[(i+3) % 4], 3) ^ rcon_tab[i]; ss[i % 4] ^= ss[4]; \ - k[4*(i)+4] = (ss[0] ^= ss[1]) ^ ss[2] ^ ss[3]; k[4*(i)+5] = ss[1] ^ ss[3]; \ - k[4*(i)+6] = ss[0]; k[4*(i)+7] = ss[1]; \ -} -#else -#define kdf4(k,i) \ -{ ss[0] ^= ls_box(ss[3],3) ^ rcon_tab[i]; k[4*(i)+ 4] = ff(ss[0]); ss[1] ^= ss[0]; k[4*(i)+ 5] = ff(ss[1]); \ - ss[2] ^= ss[1]; k[4*(i)+ 6] = ff(ss[2]); ss[3] ^= ss[2]; k[4*(i)+ 7] = ff(ss[3]); \ -} -#define kd4(k,i) \ -{ ss[4] = ls_box(ss[3],3) ^ rcon_tab[i]; \ - ss[0] ^= ss[4]; ss[4] = ff(ss[4]); k[4*(i)+ 4] = ss[4] ^= k[4*(i)]; \ - ss[1] ^= ss[0]; k[4*(i)+ 5] = ss[4] ^= k[4*(i)+ 1]; \ - ss[2] ^= ss[1]; k[4*(i)+ 6] = ss[4] ^= k[4*(i)+ 2]; \ - ss[3] ^= ss[2]; k[4*(i)+ 7] = ss[4] ^= k[4*(i)+ 3]; \ -} -#define kdl4(k,i) \ -{ ss[0] ^= ls_box(ss[3],3) ^ rcon_tab[i]; k[4*(i)+ 4] = ss[0]; ss[1] ^= ss[0]; k[4*(i)+ 5] = ss[1]; \ - ss[2] ^= ss[1]; k[4*(i)+ 6] = ss[2]; ss[3] ^= ss[2]; k[4*(i)+ 7] = ss[3]; \ -} -#endif - -#define kdf6(k,i) \ -{ ss[0] ^= ls_box(ss[5],3) ^ rcon_tab[i]; k[6*(i)+ 6] = ff(ss[0]); ss[1] ^= ss[0]; k[6*(i)+ 7] = ff(ss[1]); \ - ss[2] ^= ss[1]; k[6*(i)+ 8] = ff(ss[2]); ss[3] ^= ss[2]; k[6*(i)+ 9] = ff(ss[3]); \ - ss[4] ^= ss[3]; k[6*(i)+10] = ff(ss[4]); ss[5] ^= ss[4]; k[6*(i)+11] = ff(ss[5]); \ -} -#define kd6(k,i) \ -{ ss[6] = ls_box(ss[5],3) ^ rcon_tab[i]; \ - ss[0] ^= ss[6]; ss[6] = ff(ss[6]); k[6*(i)+ 6] = ss[6] ^= k[6*(i)]; \ - ss[1] ^= ss[0]; k[6*(i)+ 7] = ss[6] ^= k[6*(i)+ 1]; \ - ss[2] ^= ss[1]; k[6*(i)+ 8] = ss[6] ^= k[6*(i)+ 2]; \ - ss[3] ^= ss[2]; k[6*(i)+ 9] = ss[6] ^= k[6*(i)+ 3]; \ - ss[4] ^= ss[3]; k[6*(i)+10] = ss[6] ^= k[6*(i)+ 4]; \ - ss[5] ^= ss[4]; k[6*(i)+11] = ss[6] ^= k[6*(i)+ 5]; \ -} -#define kdl6(k,i) \ -{ ss[0] ^= ls_box(ss[5],3) ^ rcon_tab[i]; k[6*(i)+ 6] = ss[0]; ss[1] ^= ss[0]; k[6*(i)+ 7] = ss[1]; \ - ss[2] ^= ss[1]; k[6*(i)+ 8] = ss[2]; ss[3] ^= ss[2]; k[6*(i)+ 9] = ss[3]; \ -} - -#define kdf8(k,i) \ -{ ss[0] ^= ls_box(ss[7],3) ^ rcon_tab[i]; k[8*(i)+ 8] = ff(ss[0]); ss[1] ^= ss[0]; k[8*(i)+ 9] = ff(ss[1]); \ - ss[2] ^= ss[1]; k[8*(i)+10] = ff(ss[2]); ss[3] ^= ss[2]; k[8*(i)+11] = ff(ss[3]); \ - ss[4] ^= ls_box(ss[3],0); k[8*(i)+12] = ff(ss[4]); ss[5] ^= ss[4]; k[8*(i)+13] = ff(ss[5]); \ - ss[6] ^= ss[5]; k[8*(i)+14] = ff(ss[6]); ss[7] ^= ss[6]; k[8*(i)+15] = ff(ss[7]); \ -} -#define kd8(k,i) \ -{ aes_32t g = ls_box(ss[7],3) ^ rcon_tab[i]; \ - ss[0] ^= g; g = ff(g); k[8*(i)+ 8] = g ^= k[8*(i)]; \ - ss[1] ^= ss[0]; k[8*(i)+ 9] = g ^= k[8*(i)+ 1]; \ - ss[2] ^= ss[1]; k[8*(i)+10] = g ^= k[8*(i)+ 2]; \ - ss[3] ^= ss[2]; k[8*(i)+11] = g ^= k[8*(i)+ 3]; \ - g = ls_box(ss[3],0); \ - ss[4] ^= g; g = ff(g); k[8*(i)+12] = g ^= k[8*(i)+ 4]; \ - ss[5] ^= ss[4]; k[8*(i)+13] = g ^= k[8*(i)+ 5]; \ - ss[6] ^= ss[5]; k[8*(i)+14] = g ^= k[8*(i)+ 6]; \ - ss[7] ^= ss[6]; k[8*(i)+15] = g ^= k[8*(i)+ 7]; \ -} -#define kdl8(k,i) \ -{ ss[0] ^= ls_box(ss[7],3) ^ rcon_tab[i]; k[8*(i)+ 8] = ss[0]; ss[1] ^= ss[0]; k[8*(i)+ 9] = ss[1]; \ - ss[2] ^= ss[1]; k[8*(i)+10] = ss[2]; ss[3] ^= ss[2]; k[8*(i)+11] = ss[3]; \ -} - -aes_rval aes_dec_key(const unsigned char in_key[], unsigned int klen, aes_ctx cx[1]) -{ aes_32t ss[8]; - d_vars - -#if !defined(FIXED_TABLES) - if(!tab_init) gen_tabs(); -#endif - -#if !defined(BLOCK_SIZE) - if(!cx->n_blk) cx->n_blk = 16; -#else - cx->n_blk = BLOCK_SIZE; -#endif - - cx->n_blk = (cx->n_blk & ~3) | 2; - - cx->k_sch[0] = ss[0] = word_in(in_key ); - cx->k_sch[1] = ss[1] = word_in(in_key + 4); - cx->k_sch[2] = ss[2] = word_in(in_key + 8); - cx->k_sch[3] = ss[3] = word_in(in_key + 12); - -#if (BLOCK_SIZE == 16) && (DEC_UNROLL != NONE) - - switch(klen) - { - case 16: kdf4(cx->k_sch, 0); kd4(cx->k_sch, 1); - kd4(cx->k_sch, 2); kd4(cx->k_sch, 3); - kd4(cx->k_sch, 4); kd4(cx->k_sch, 5); - kd4(cx->k_sch, 6); kd4(cx->k_sch, 7); - kd4(cx->k_sch, 8); kdl4(cx->k_sch, 9); - cx->n_rnd = 10; break; - case 24: cx->k_sch[4] = ff(ss[4] = word_in(in_key + 16)); - cx->k_sch[5] = ff(ss[5] = word_in(in_key + 20)); - kdf6(cx->k_sch, 0); kd6(cx->k_sch, 1); - kd6(cx->k_sch, 2); kd6(cx->k_sch, 3); - kd6(cx->k_sch, 4); kd6(cx->k_sch, 5); - kd6(cx->k_sch, 6); kdl6(cx->k_sch, 7); - cx->n_rnd = 12; break; - case 32: cx->k_sch[4] = ff(ss[4] = word_in(in_key + 16)); - cx->k_sch[5] = ff(ss[5] = word_in(in_key + 20)); - cx->k_sch[6] = ff(ss[6] = word_in(in_key + 24)); - cx->k_sch[7] = ff(ss[7] = word_in(in_key + 28)); - kdf8(cx->k_sch, 0); kd8(cx->k_sch, 1); - kd8(cx->k_sch, 2); kd8(cx->k_sch, 3); - kd8(cx->k_sch, 4); kd8(cx->k_sch, 5); - kdl8(cx->k_sch, 6); - cx->n_rnd = 14; break; - default: cx->n_rnd = 0; return aes_bad; - } -#else - { aes_32t i, l; - cx->n_rnd = ((klen >> 2) > nc ? (klen >> 2) : nc) + 6; - l = (nc * cx->n_rnd + nc - 1) / (klen >> 2); - - switch(klen) - { - case 16: - for(i = 0; i < l; ++i) - ke4(cx->k_sch, i); - break; - case 24: cx->k_sch[4] = ss[4] = word_in(in_key + 16); - cx->k_sch[5] = ss[5] = word_in(in_key + 20); - for(i = 0; i < l; ++i) - ke6(cx->k_sch, i); - break; - case 32: cx->k_sch[4] = ss[4] = word_in(in_key + 16); - cx->k_sch[5] = ss[5] = word_in(in_key + 20); - cx->k_sch[6] = ss[6] = word_in(in_key + 24); - cx->k_sch[7] = ss[7] = word_in(in_key + 28); - for(i = 0; i < l; ++i) - ke8(cx->k_sch, i); - break; - default: cx->n_rnd = 0; return aes_bad; - } -#if (DEC_ROUND != NO_TABLES) - for(i = nc; i < nc * cx->n_rnd; ++i) - cx->k_sch[i] = inv_mcol(cx->k_sch[i]); -#endif - } -#endif - - return aes_good; -} - -#endif +/* + * ------------------------------------------------------------------------- + * Copyright (c) 2001, Dr Brian Gladman <brg@xxxxxxxxxxxxx>, Worcester, UK. + * All rights reserved. + * + * LICENSE TERMS + * + * The free distribution and use of this software in both source and binary + * form is allowed (with or without changes) provided that: + * + * 1. distributions of this source code include the above copyright + * notice, this list of conditions and the following disclaimer; + * + * 2. distributions in binary form include the above copyright + * notice, this list of conditions and the following disclaimer + * in the documentation and/or other associated materials; + * + * 3. the copyright holder's name is not used to endorse products + * built using this software without specific written permission. + * + * DISCLAIMER + * + * This software is provided 'as is' with no explicit or implied warranties + * in respect of its properties, including, but not limited to, correctness + * and fitness for purpose. + * ------------------------------------------------------------------------- + * Issue Date: 29/07/2002 + * + * This file contains the code for implementing the key schedule for AES + * (Rijndael) for block and key sizes of 16, 24, and 32 bytes. + */ + +#include "aesopt.h" + +#if defined(BLOCK_SIZE) && (BLOCK_SIZE & 7) +#error An illegal block size has been specified. +#endif + +/* Subroutine to set the block size (if variable) in bytes, legal + * values being 16, 24 and 32. + */ + +#if !defined(BLOCK_SIZE) + +aes_rval aes_blk_len(unsigned int blen, aes_ctx cx[1]) +{ +#if !defined(FIXED_TABLES) + if (!tab_init) { + gen_tabs(); + } +#endif + + if ((blen & 7) || blen < 16 || blen > 32) { + cx->n_blk = 0; + return aes_bad; + } + + cx->n_blk = blen; + return aes_good; +} + +#endif + +/* Initialise the key schedule from the user supplied key. The key + * length is now specified in bytes - 16, 24 or 32 as appropriate. + * This corresponds to bit lengths of 128, 192 and 256 bits, and + * to Nk values of 4, 6 and 8 respectively. + * + * The following macros implement a single cycle in the key + * schedule generation process. The number of cycles needed + * for each cx->n_col and nk value is: + * + * nk = 4 5 6 7 8 + * ------------------------------ + * cx->n_col = 4 10 9 8 7 7 + * cx->n_col = 5 14 11 10 9 9 + * cx->n_col = 6 19 15 12 11 11 + * cx->n_col = 7 21 19 16 13 14 + * cx->n_col = 8 29 23 19 17 14 + */ + +#define ke4(k, i) \ + { k[4 * (i) + 4] = ss[0] ^= ls_box(ss[3], 3) ^ rcon_tab[i]; k[4 * (i) + 5] = ss[1] ^= ss[0]; \ + k[4 * (i) + 6] = ss[2] ^= ss[1]; k[4 * (i) + 7] = ss[3] ^= ss[2]; \ + } +#define kel4(k, i) \ + { k[4 * (i) + 4] = ss[0] ^= ls_box(ss[3], 3) ^ rcon_tab[i]; k[4 * (i) + 5] = ss[1] ^= ss[0]; \ + k[4 * (i) + 6] = ss[2] ^= ss[1]; k[4 * (i) + 7] = ss[3] ^= ss[2]; \ + } + +#define ke6(k, i) \ + { k[6 * (i) + 6] = ss[0] ^= ls_box(ss[5], 3) ^ rcon_tab[i]; k[6 * (i) + 7] = ss[1] ^= ss[0]; \ + k[6 * (i) + 8] = ss[2] ^= ss[1]; k[6 * (i) + 9] = ss[3] ^= ss[2]; \ + k[6 * (i) + 10] = ss[4] ^= ss[3]; k[6 * (i) + 11] = ss[5] ^= ss[4]; \ + } +#define kel6(k, i) \ + { k[6 * (i) + 6] = ss[0] ^= ls_box(ss[5], 3) ^ rcon_tab[i]; k[6 * (i) + 7] = ss[1] ^= ss[0]; \ + k[6 * (i) + 8] = ss[2] ^= ss[1]; k[6 * (i) + 9] = ss[3] ^= ss[2]; \ + } + +#define ke8(k, i) \ + { k[8 * (i) + 8] = ss[0] ^= ls_box(ss[7], 3) ^ rcon_tab[i]; k[8 * (i) + 9] = ss[1] ^= ss[0]; \ + k[8 * (i) + 10] = ss[2] ^= ss[1]; k[8 * (i) + 11] = ss[3] ^= ss[2]; \ + k[8 * (i) + 12] = ss[4] ^= ls_box(ss[3], 0); k[8 * (i) + 13] = ss[5] ^= ss[4]; \ + k[8 * (i) + 14] = ss[6] ^= ss[5]; k[8 * (i) + 15] = ss[7] ^= ss[6]; \ + } +#define kel8(k, i) \ + { k[8 * (i) + 8] = ss[0] ^= ls_box(ss[7], 3) ^ rcon_tab[i]; k[8 * (i) + 9] = ss[1] ^= ss[0]; \ + k[8 * (i) + 10] = ss[2] ^= ss[1]; k[8 * (i) + 11] = ss[3] ^= ss[2]; \ + } + +#if defined(ENCRYPTION_KEY_SCHEDULE) + +aes_rval aes_enc_key(const unsigned char in_key[], unsigned int klen, aes_ctx cx[1]) +{ + aes_32t ss[8]; + +#if !defined(FIXED_TABLES) + if (!tab_init) { + gen_tabs(); + } +#endif + +#if !defined(BLOCK_SIZE) + if (!cx->n_blk) { + cx->n_blk = 16; + } +#else + cx->n_blk = BLOCK_SIZE; +#endif + + cx->n_blk = (cx->n_blk & ~3) | 1; + + cx->k_sch[0] = ss[0] = word_in(in_key ); + cx->k_sch[1] = ss[1] = word_in(in_key + 4); + cx->k_sch[2] = ss[2] = word_in(in_key + 8); + cx->k_sch[3] = ss[3] = word_in(in_key + 12); + +#if (BLOCK_SIZE == 16) && (ENC_UNROLL != NONE) + + switch (klen) { + case 16: ke4(cx->k_sch, 0); + ke4(cx->k_sch, 1); + ke4(cx->k_sch, 2); + ke4(cx->k_sch, 3); + ke4(cx->k_sch, 4); + ke4(cx->k_sch, 5); + ke4(cx->k_sch, 6); + ke4(cx->k_sch, 7); + ke4(cx->k_sch, 8); + kel4(cx->k_sch, 9); + cx->n_rnd = 10; + break; + case 24: cx->k_sch[4] = ss[4] = word_in(in_key + 16); + cx->k_sch[5] = ss[5] = word_in(in_key + 20); + ke6(cx->k_sch, 0); + ke6(cx->k_sch, 1); + ke6(cx->k_sch, 2); + ke6(cx->k_sch, 3); + ke6(cx->k_sch, 4); + ke6(cx->k_sch, 5); + ke6(cx->k_sch, 6); + kel6(cx->k_sch, 7); + cx->n_rnd = 12; + break; + case 32: cx->k_sch[4] = ss[4] = word_in(in_key + 16); + cx->k_sch[5] = ss[5] = word_in(in_key + 20); + cx->k_sch[6] = ss[6] = word_in(in_key + 24); + cx->k_sch[7] = ss[7] = word_in(in_key + 28); + ke8(cx->k_sch, 0); + ke8(cx->k_sch, 1); + ke8(cx->k_sch, 2); + ke8(cx->k_sch, 3); + ke8(cx->k_sch, 4); + ke8(cx->k_sch, 5); + kel8(cx->k_sch, 6); + cx->n_rnd = 14; + break; + default: cx->n_rnd = 0; + return aes_bad; + } +#else + { aes_32t i, l; + cx->n_rnd = ((klen >> 2) > nc ? (klen >> 2) : nc) + 6; + l = (nc * cx->n_rnd + nc - 1) / (klen >> 2); + + switch (klen) { + case 16: for (i = 0; i < l; ++i) { + ke4(cx->k_sch, i); + } + break; + case 24: cx->k_sch[4] = ss[4] = word_in(in_key + 16); + cx->k_sch[5] = ss[5] = word_in(in_key + 20); + for (i = 0; i < l; ++i) { + ke6(cx->k_sch, i); + } + break; + case 32: cx->k_sch[4] = ss[4] = word_in(in_key + 16); + cx->k_sch[5] = ss[5] = word_in(in_key + 20); + cx->k_sch[6] = ss[6] = word_in(in_key + 24); + cx->k_sch[7] = ss[7] = word_in(in_key + 28); + for (i = 0; i < l; ++i) { + ke8(cx->k_sch, i); + } + break; + default: cx->n_rnd = 0; + return aes_bad; + } + } +#endif + + return aes_good; +} + +#endif + +#if defined(DECRYPTION_KEY_SCHEDULE) + +#if (DEC_ROUND != NO_TABLES) +#define d_vars dec_imvars +#define ff(x) inv_mcol(x) +#else +#define ff(x) (x) +#define d_vars +#endif + +#if 1 +#define kdf4(k, i) \ + { ss[0] = ss[0] ^ ss[2] ^ ss[1] ^ ss[3]; ss[1] = ss[1] ^ ss[3]; ss[2] = ss[2] ^ ss[3]; ss[3] = ss[3]; \ + ss[4] = ls_box(ss[(i + 3) % 4], 3) ^ rcon_tab[i]; ss[i % 4] ^= ss[4]; \ + ss[4] ^= k[4 * (i)]; k[4 * (i) + 4] = ff(ss[4]); ss[4] ^= k[4 * (i) + 1]; k[4 * (i) + 5] = ff(ss[4]); \ + ss[4] ^= k[4 * (i) + 2]; k[4 * (i) + 6] = ff(ss[4]); ss[4] ^= k[4 * (i) + 3]; k[4 * (i) + 7] = ff(ss[4]); \ + } +#define kd4(k, i) \ + { ss[4] = ls_box(ss[(i + 3) % 4], 3) ^ rcon_tab[i]; ss[i % 4] ^= ss[4]; ss[4] = ff(ss[4]); \ + k[4 * (i) + 4] = ss[4] ^= k[4 * (i)]; k[4 * (i) + 5] = ss[4] ^= k[4 * (i) + 1]; \ + k[4 * (i) + 6] = ss[4] ^= k[4 * (i) + 2]; k[4 * (i) + 7] = ss[4] ^= k[4 * (i) + 3]; \ + } +#define kdl4(k, i) \ + { ss[4] = ls_box(ss[(i + 3) % 4], 3) ^ rcon_tab[i]; ss[i % 4] ^= ss[4]; \ + k[4 * (i) + 4] = (ss[0] ^= ss[1]) ^ ss[2] ^ ss[3]; k[4 * (i) + 5] = ss[1] ^ ss[3]; \ + k[4 * (i) + 6] = ss[0]; k[4 * (i) + 7] = ss[1]; \ + } +#else +#define kdf4(k, i) \ + { ss[0] ^= ls_box(ss[3], 3) ^ rcon_tab[i]; k[4 * (i) + 4] = ff(ss[0]); ss[1] ^= ss[0]; k[4 * (i) + 5] = ff(ss[1]); \ + ss[2] ^= ss[1]; k[4 * (i) + 6] = ff(ss[2]); ss[3] ^= ss[2]; k[4 * (i) + 7] = ff(ss[3]); \ + } +#define kd4(k, i) \ + { ss[4] = ls_box(ss[3], 3) ^ rcon_tab[i]; \ + ss[0] ^= ss[4]; ss[4] = ff(ss[4]); k[4 * (i) + 4] = ss[4] ^= k[4 * (i)]; \ + ss[1] ^= ss[0]; k[4 * (i) + 5] = ss[4] ^= k[4 * (i) + 1]; \ + ss[2] ^= ss[1]; k[4 * (i) + 6] = ss[4] ^= k[4 * (i) + 2]; \ + ss[3] ^= ss[2]; k[4 * (i) + 7] = ss[4] ^= k[4 * (i) + 3]; \ + } +#define kdl4(k, i) \ + { ss[0] ^= ls_box(ss[3], 3) ^ rcon_tab[i]; k[4 * (i) + 4] = ss[0]; ss[1] ^= ss[0]; k[4 * (i) + 5] = ss[1]; \ + ss[2] ^= ss[1]; k[4 * (i) + 6] = ss[2]; ss[3] ^= ss[2]; k[4 * (i) + 7] = ss[3]; \ + } +#endif + +#define kdf6(k, i) \ + { ss[0] ^= ls_box(ss[5], 3) ^ rcon_tab[i]; k[6 * (i) + 6] = ff(ss[0]); ss[1] ^= ss[0]; k[6 * (i) + 7] = ff(ss[1]); \ + ss[2] ^= ss[1]; k[6 * (i) + 8] = ff(ss[2]); ss[3] ^= ss[2]; k[6 * (i) + 9] = ff(ss[3]); \ + ss[4] ^= ss[3]; k[6 * (i) + 10] = ff(ss[4]); ss[5] ^= ss[4]; k[6 * (i) + 11] = ff(ss[5]); \ + } +#define kd6(k, i) \ + { ss[6] = ls_box(ss[5], 3) ^ rcon_tab[i]; \ + ss[0] ^= ss[6]; ss[6] = ff(ss[6]); k[6 * (i) + 6] = ss[6] ^= k[6 * (i)]; \ + ss[1] ^= ss[0]; k[6 * (i) + 7] = ss[6] ^= k[6 * (i) + 1]; \ + ss[2] ^= ss[1]; k[6 * (i) + 8] = ss[6] ^= k[6 * (i) + 2]; \ + ss[3] ^= ss[2]; k[6 * (i) + 9] = ss[6] ^= k[6 * (i) + 3]; \ + ss[4] ^= ss[3]; k[6 * (i) + 10] = ss[6] ^= k[6 * (i) + 4]; \ + ss[5] ^= ss[4]; k[6 * (i) + 11] = ss[6] ^= k[6 * (i) + 5]; \ + } +#define kdl6(k, i) \ + { ss[0] ^= ls_box(ss[5], 3) ^ rcon_tab[i]; k[6 * (i) + 6] = ss[0]; ss[1] ^= ss[0]; k[6 * (i) + 7] = ss[1]; \ + ss[2] ^= ss[1]; k[6 * (i) + 8] = ss[2]; ss[3] ^= ss[2]; k[6 * (i) + 9] = ss[3]; \ + } + +#define kdf8(k, i) \ + { ss[0] ^= ls_box(ss[7], 3) ^ rcon_tab[i]; k[8 * (i) + 8] = ff(ss[0]); ss[1] ^= ss[0]; k[8 * (i) + 9] = ff(ss[1]); \ + ss[2] ^= ss[1]; k[8 * (i) + 10] = ff(ss[2]); ss[3] ^= ss[2]; k[8 * (i) + 11] = ff(ss[3]); \ + ss[4] ^= ls_box(ss[3], 0); k[8 * (i) + 12] = ff(ss[4]); ss[5] ^= ss[4]; k[8 * (i) + 13] = ff(ss[5]); \ + ss[6] ^= ss[5]; k[8 * (i) + 14] = ff(ss[6]); ss[7] ^= ss[6]; k[8 * (i) + 15] = ff(ss[7]); \ + } +#define kd8(k, i) \ + { aes_32t g = ls_box(ss[7], 3) ^ rcon_tab[i]; \ + ss[0] ^= g; g = ff(g); k[8 * (i) + 8] = g ^= k[8 * (i)]; \ + ss[1] ^= ss[0]; k[8 * (i) + 9] = g ^= k[8 * (i) + 1]; \ + ss[2] ^= ss[1]; k[8 * (i) + 10] = g ^= k[8 * (i) + 2]; \ + ss[3] ^= ss[2]; k[8 * (i) + 11] = g ^= k[8 * (i) + 3]; \ + g = ls_box(ss[3], 0); \ + ss[4] ^= g; g = ff(g); k[8 * (i) + 12] = g ^= k[8 * (i) + 4]; \ + ss[5] ^= ss[4]; k[8 * (i) + 13] = g ^= k[8 * (i) + 5]; \ + ss[6] ^= ss[5]; k[8 * (i) + 14] = g ^= k[8 * (i) + 6]; \ + ss[7] ^= ss[6]; k[8 * (i) + 15] = g ^= k[8 * (i) + 7]; \ + } +#define kdl8(k, i) \ + { ss[0] ^= ls_box(ss[7], 3) ^ rcon_tab[i]; k[8 * (i) + 8] = ss[0]; ss[1] ^= ss[0]; k[8 * (i) + 9] = ss[1]; \ + ss[2] ^= ss[1]; k[8 * (i) + 10] = ss[2]; ss[3] ^= ss[2]; k[8 * (i) + 11] = ss[3]; \ + } + +aes_rval aes_dec_key(const unsigned char in_key[], unsigned int klen, aes_ctx cx[1]) +{ + aes_32t ss[8]; + d_vars + +#if !defined(FIXED_TABLES) + if (!tab_init) { + gen_tabs(); + } +#endif + +#if !defined(BLOCK_SIZE) + if (!cx->n_blk) { + cx->n_blk = 16; + } +#else + cx->n_blk = BLOCK_SIZE; +#endif + + cx->n_blk = (cx->n_blk & ~3) | 2; + + cx->k_sch[0] = ss[0] = word_in(in_key ); + cx->k_sch[1] = ss[1] = word_in(in_key + 4); + cx->k_sch[2] = ss[2] = word_in(in_key + 8); + cx->k_sch[3] = ss[3] = word_in(in_key + 12); + +#if (BLOCK_SIZE == 16) && (DEC_UNROLL != NONE) + + switch (klen) { + case 16: kdf4(cx->k_sch, 0); + kd4(cx->k_sch, 1); + kd4(cx->k_sch, 2); + kd4(cx->k_sch, 3); + kd4(cx->k_sch, 4); + kd4(cx->k_sch, 5); + kd4(cx->k_sch, 6); + kd4(cx->k_sch, 7); + kd4(cx->k_sch, 8); + kdl4(cx->k_sch, 9); + cx->n_rnd = 10; + break; + case 24: cx->k_sch[4] = ff(ss[4] = word_in(in_key + 16)); + cx->k_sch[5] = ff(ss[5] = word_in(in_key + 20)); + kdf6(cx->k_sch, 0); + kd6(cx->k_sch, 1); + kd6(cx->k_sch, 2); + kd6(cx->k_sch, 3); + kd6(cx->k_sch, 4); + kd6(cx->k_sch, 5); + kd6(cx->k_sch, 6); + kdl6(cx->k_sch, 7); + cx->n_rnd = 12; + break; + case 32: cx->k_sch[4] = ff(ss[4] = word_in(in_key + 16)); + cx->k_sch[5] = ff(ss[5] = word_in(in_key + 20)); + cx->k_sch[6] = ff(ss[6] = word_in(in_key + 24)); + cx->k_sch[7] = ff(ss[7] = word_in(in_key + 28)); + kdf8(cx->k_sch, 0); + kd8(cx->k_sch, 1); + kd8(cx->k_sch, 2); + kd8(cx->k_sch, 3); + kd8(cx->k_sch, 4); + kd8(cx->k_sch, 5); + kdl8(cx->k_sch, 6); + cx->n_rnd = 14; + break; + default: cx->n_rnd = 0; + return aes_bad; + } +#else + { aes_32t i, l; + cx->n_rnd = ((klen >> 2) > nc ? (klen >> 2) : nc) + 6; + l = (nc * cx->n_rnd + nc - 1) / (klen >> 2); + + switch (klen) { + case 16: + for (i = 0; i < l; ++i) { + ke4(cx->k_sch, i); + } + break; + case 24: cx->k_sch[4] = ss[4] = word_in(in_key + 16); + cx->k_sch[5] = ss[5] = word_in(in_key + 20); + for (i = 0; i < l; ++i) { + ke6(cx->k_sch, i); + } + break; + case 32: cx->k_sch[4] = ss[4] = word_in(in_key + 16); + cx->k_sch[5] = ss[5] = word_in(in_key + 20); + cx->k_sch[6] = ss[6] = word_in(in_key + 24); + cx->k_sch[7] = ss[7] = word_in(in_key + 28); + for (i = 0; i < l; ++i) { + ke8(cx->k_sch, i); + } + break; + default: cx->n_rnd = 0; + return aes_bad; + } +#if (DEC_ROUND != NO_TABLES) + for (i = nc; i < nc * cx->n_rnd; ++i) { + cx->k_sch[i] = inv_mcol(cx->k_sch[i]); + } +#endif + } +#endif + + return aes_good; +} + +#endif === modified file 'i3/aeshash/aeskeypp.c' --- i3/aeshash/aeskeypp.c 2009-12-11 22:49:11 +0000 +++ i3/aeshash/aeskeypp.c 2010-02-11 11:49:47 +0000 @@ -1,399 +1,488 @@ -/* - ------------------------------------------------------------------------- - Copyright (c) 2001, Dr Brian Gladman <brg@xxxxxxxxxxxxx>, Worcester, UK. - All rights reserved. - - LICENSE TERMS - - The free distribution and use of this software in both source and binary - form is allowed (with or without changes) provided that: - - 1. distributions of this source code include the above copyright - notice, this list of conditions and the following disclaimer; - - 2. distributions in binary form include the above copyright - notice, this list of conditions and the following disclaimer - in the documentation and/or other associated materials; - - 3. the copyright holder's name is not used to endorse products - built using this software without specific written permission. - - DISCLAIMER - - This software is provided 'as is' with no explicit or implied warranties - in respect of its properties, including, but not limited to, correctness - and fitness for purpose. - ------------------------------------------------------------------------- - Issue Date: 29/07/2002 - - This file contains the code for implementing the key schedule for AES - (Rijndael) for block and key sizes of 16, 20, 24, 28 and 32 bytes. -*/ - -#include "aesopt.h" - -/* Subroutine to set the block size (if variable) in bytes, legal - values being 16, 24 and 32. -*/ - -#if !defined(BLOCK_SIZE) - -/* Subroutine to set the block size (if variable) in bytes, legal - values being 16, 24 and 32. -*/ - -aes_rval aes_blk_len(unsigned int blen, aes_ctx cx[1]) -{ -#if !defined(FIXED_TABLES) - if(!tab_init) gen_tabs(); -#endif - - if((blen & 3) || blen < 16 || blen > 32) - { - cx->n_blk = 0; return aes_bad; - } - - cx->n_blk = blen; - return aes_good; -} - -#endif - -/* Initialise the key schedule from the user supplied key. The key - length is now specified in bytes - 16, 24 or 32 as appropriate. - This corresponds to bit lengths of 128, 192 and 256 bits, and - to Nk values of 4, 6 and 8 respectively. - - The following macros implement a single cycle in the key - schedule generation process. The number of cycles needed - for each cx->n_blk and nk value is: - - nk = 4 5 6 7 8 - ------------------------------ - cx->n_blk = 4 10 9 8 7 7 - cx->n_blk = 5 14 11 10 9 9 - cx->n_blk = 6 19 15 12 11 11 - cx->n_blk = 7 21 19 16 13 14 - cx->n_blk = 8 29 23 19 17 14 -*/ - -/* Initialise the key schedule from the user supplied key. The key - length is now specified in bytes - 16, 20, 24, 28 or 32 as - appropriate. This corresponds to bit lengths of 128, 160, 192, - 224 and 256 bits, and to Nk values of 4, 5, 6, 7 & 8 respectively. - */ - -#define mx(t,f) (*t++ = inv_mcol(*f),f++) -#define cp(t,f) *t++ = *f++ - -#if BLOCK_SIZE == 16 -#define cpy(d,s) cp(d,s); cp(d,s); cp(d,s); cp(d,s) -#define mix(d,s) mx(d,s); mx(d,s); mx(d,s); mx(d,s) -#elif BLOCK_SIZE == 20 -#define cpy(d,s) cp(d,s); cp(d,s); cp(d,s); cp(d,s); \ - cp(d,s) -#define mix(d,s) mx(d,s); mx(d,s); mx(d,s); mx(d,s); \ - mx(d,s) -#elif BLOCK_SIZE == 24 -#define cpy(d,s) cp(d,s); cp(d,s); cp(d,s); cp(d,s); \ - cp(d,s); cp(d,s) -#define mix(d,s) mx(d,s); mx(d,s); mx(d,s); mx(d,s); \ - mx(d,s); mx(d,s) -#elif BLOCK_SIZE == 28 -#define cpy(d,s) cp(d,s); cp(d,s); cp(d,s); cp(d,s); \ - cp(d,s); cp(d,s); cp(d,s) -#define mix(d,s) mx(d,s); mx(d,s); mx(d,s); mx(d,s); \ - mx(d,s); mx(d,s); mx(d,s) -#elif BLOCK_SIZE == 32 -#define cpy(d,s) cp(d,s); cp(d,s); cp(d,s); cp(d,s); \ - cp(d,s); cp(d,s); cp(d,s); cp(d,s) -#define mix(d,s) mx(d,s); mx(d,s); mx(d,s); mx(d,s); \ - mx(d,s); mx(d,s); mx(d,s); mx(d,s) -#else - -#define cpy(d,s) \ -switch(nc) \ -{ case 8: cp(d,s); \ - case 7: cp(d,s); \ - case 6: cp(d,s); \ - case 5: cp(d,s); \ - case 4: cp(d,s); cp(d,s); \ - cp(d,s); cp(d,s); \ -} - -#define mix(d,s) \ -switch(nc) \ -{ case 8: mx(d,s); \ - case 7: mx(d,s); \ - case 6: mx(d,s); \ - case 5: mx(d,s); \ - case 4: mx(d,s); mx(d,s); \ - mx(d,s); mx(d,s); \ -} - -#endif - -/* The following macros implement a single cycle in the key - schedule generation process. The number of cycles needed - for each cx->n_blk and nk value is: - - nk = 4 5 6 7 8 - ----------------------- - cx->n_blk = 4 10 9 8 7 7 - cx->n_blk = 5 14 11 10 9 9 - cx->n_blk = 6 19 15 12 11 11 - cx->n_blk = 7 21 19 16 13 14 - cx->n_blk = 8 29 23 19 17 14 -*/ - -#define ks4(i) \ -{ p ^= ls_box(s,3) ^ rcon_tab[i]; q ^= p; r ^= q; s ^= r; \ - cx->k_sch[4*(i)+4] = p; \ - cx->k_sch[4*(i)+5] = q; \ - cx->k_sch[4*(i)+6] = r; \ - cx->k_sch[4*(i)+7] = s; \ -} - -#define ks5(i) \ -{ p ^= ls_box(t,3) ^ rcon_tab[i]; q ^= p; \ - r ^= q; s ^= r; t ^= s; \ - cx->k_sch[5*(i)+ 5] = p; \ - cx->k_sch[5*(i)+ 6] = q; \ - cx->k_sch[5*(i)+ 7] = r; \ - cx->k_sch[5*(i)+ 8] = s; \ - cx->k_sch[5*(i)+ 9] = t; \ -} - -#define ks6(i) \ -{ p ^= ls_box(u,3) ^ rcon_tab[i]; q ^= p; \ - r ^= q; s ^= r; t ^= s; u ^= t; \ - cx->k_sch[6*(i)+ 6] = p; \ - cx->k_sch[6*(i)+ 7] = q; \ - cx->k_sch[6*(i)+ 8] = r; \ - cx->k_sch[6*(i)+ 9] = s; \ - cx->k_sch[6*(i)+10] = t; \ - cx->k_sch[6*(i)+11] = u; \ -} - -#define ks7(i) \ -{ p ^= ls_box(v,3) ^ rcon_tab[i]; q ^= p; r ^= q; s ^= r; \ - t ^= ls_box(s,0); u ^= t; v ^= u; \ - cx->k_sch[7*(i)+ 7] = p; \ - cx->k_sch[7*(i)+ 8] = q; \ - cx->k_sch[7*(i)+ 9] = r; \ - cx->k_sch[7*(i)+10] = s; \ - cx->k_sch[7*(i)+11] = t; \ - cx->k_sch[7*(i)+12] = u; \ - cx->k_sch[7*(i)+13] = v; \ -} - -#define ks8(i) \ -{ p ^= ls_box(w,3) ^ rcon_tab[i]; q ^= p; r ^= q; s ^= r; \ - t ^= ls_box(s,0); u ^= t; v ^= u; w ^= v; \ - cx->k_sch[8*(i)+ 8] = p; \ - cx->k_sch[8*(i)+ 9] = q; \ - cx->k_sch[8*(i)+10] = r; \ - cx->k_sch[8*(i)+11] = s; \ - cx->k_sch[8*(i)+12] = t; \ - cx->k_sch[8*(i)+13] = u; \ - cx->k_sch[8*(i)+14] = v; \ - cx->k_sch[8*(i)+15] = w; \ -} - -#if defined(ENCRYPTION_KEY_SCHEDULE) - -aes_rval aes_enc_key(const unsigned char in_key[], unsigned int klen, aes_ctx cx[1]) -{ aes_32t i,p,q,r,s,t,u,v,w; - -#if !defined(FIXED_TABLES) - if(!tab_init) gen_tabs(); -#endif - -#if !defined(BLOCK_SIZE) - if(!cx->n_blk) cx->n_blk = 16; -#else - cx->n_blk = BLOCK_SIZE; -#endif - - cx->n_blk = (cx->n_blk & ~3) | 1; - cx->n_rnd = ((klen >> 2) > nc ? (klen >> 2) : nc) + 6; - - cx->k_sch[0] = p = word_in(in_key ); - cx->k_sch[1] = q = word_in(in_key + 4); - cx->k_sch[2] = r = word_in(in_key + 8); - cx->k_sch[3] = s = word_in(in_key + 12); - -#if BLOCK_SIZE == 16 && defined(UNROLL) - - switch(klen >> 2) - { - case 4: ks4(0); ks4(1); ks4(2); ks4(3); - ks4(4); ks4(5); ks4(6); ks4(7); - ks4(8); ks4(9); - cx->n_rnd = 10; break; - case 5: cx->k_sch[4] = t = word_in(in_key + 16); - ks5(0); ks5(1); ks5(2); ks5(3); - ks5(4); ks5(5); ks5(6); ks5(7); - ks5(8); - cx->n_rnd = 11; break; - case 6: cx->k_sch[4] = t = word_in(in_key + 16); - cx->k_sch[5] = u = word_in(in_key + 20); - ks6(0); ks6(1); ks6(2); ks6(3); - ks6(4); ks6(5); ks6(6); ks6(7); - cx->n_rnd = 12; break; - case 7: cx->k_sch[4] = t = word_in(in_key + 16); - cx->k_sch[5] = u = word_in(in_key + 20); - cx->k_sch[6] = v = word_in(in_key + 24); - ks7(0); ks7(1); ks7(2); ks7(3); - ks7(4); ks7(5); ks7(6); - cx->n_rnd = 13; break; - case 8: cx->k_sch[4] = t = word_in(in_key + 16); - cx->k_sch[5] = u = word_in(in_key + 20); - cx->k_sch[6] = v = word_in(in_key + 24); - cx->k_sch[7] = w = word_in(in_key + 28); - ks8(0); ks8(1); ks8(2); ks8(3); - ks8(4); ks8(5); ks8(6); - cx->n_rnd = 14; break; - default:cx->n_rnd = 0; return aes_bad; - } -#else - cx->n_rnd = ((klen >> 2) > nc ? (klen >> 2) : nc) + 6; - { - aes_32t l = (nc * (cx->n_rnd + 1) - 1) / (klen >> 2); - switch(klen >> 2) - { - case 4: for(i = 0; i < l; ++i) - ks4(i); - break; - case 5: cx->k_sch[4] = t = word_in(in_key + 16); - for(i = 0; i < l; ++i) - ks5(i); - break; - case 6: cx->k_sch[4] = t = word_in(in_key + 16); - cx->k_sch[5] = u = word_in(in_key + 20); - for(i = 0; i < l; ++i) - ks6(i); - break; - case 7: cx->k_sch[4] = t = word_in(in_key + 16); - cx->k_sch[5] = u = word_in(in_key + 20); - cx->k_sch[6] = v = word_in(in_key + 24); - for(i = 0; i < l; ++i) - ks7(i); - break; - case 8: cx->k_sch[4] = t = word_in(in_key + 16); - cx->k_sch[5] = u = word_in(in_key + 20); - cx->k_sch[6] = v = word_in(in_key + 24); - cx->k_sch[7] = w = word_in(in_key + 28); - for(i = 0; i < l; ++i) - ks8(i); - break; - } - } -#endif - - return aes_good; -} - -#endif - -#if defined(DECRYPTION_KEY_SCHEDULE) - -aes_rval aes_dec_key(const unsigned char in_key[], unsigned int klen, aes_ctx cx[1]) -{ aes_32t i,p,q,r,s,t,u,v,w; - dec_imvars - -#if !defined(FIXED_TABLES) - if(!tab_init) gen_tabs(); -#endif - -#if !defined(BLOCK_SIZE) - if(!cx->n_blk) cx->n_blk = 16; -#else - cx->n_blk = BLOCK_SIZE; -#endif - - cx->n_blk = (cx->n_blk & ~3) | 2; - cx->n_rnd = ((klen >> 2) > nc ? (klen >> 2) : nc) + 6; - - cx->k_sch[0] = p = word_in(in_key ); - cx->k_sch[1] = q = word_in(in_key + 4); - cx->k_sch[2] = r = word_in(in_key + 8); - cx->k_sch[3] = s = word_in(in_key + 12); - -#if BLOCK_SIZE == 16 && defined(UNROLL) - - switch(klen >> 2) - { - case 4: ks4(0); ks4(1); ks4(2); ks4(3); - ks4(4); ks4(5); ks4(6); ks4(7); - ks4(8); ks4(9); - cx->n_rnd = 10; break; - case 5: cx->k_sch[4] = t = word_in(in_key + 16); - ks5(0); ks5(1); ks5(2); ks5(3); - ks5(4); ks5(5); ks5(6); ks5(7); - ks5(8); - cx->n_rnd = 11; break; - case 6: cx->k_sch[4] = t = word_in(in_key + 16); - cx->k_sch[5] = u = word_in(in_key + 20); - ks6(0); ks6(1); ks6(2); ks6(3); - ks6(4); ks6(5); ks6(6); ks6(7); - cx->n_rnd = 12; break; - case 7: cx->k_sch[4] = t = word_in(in_key + 16); - cx->k_sch[5] = u = word_in(in_key + 20); - cx->k_sch[6] = v = word_in(in_key + 24); - ks7(0); ks7(1); ks7(2); ks7(3); - ks7(4); ks7(5); ks7(6); - cx->n_rnd = 13; break; - case 8: cx->k_sch[4] = t = word_in(in_key + 16); - cx->k_sch[5] = u = word_in(in_key + 20); - cx->k_sch[6] = v = word_in(in_key + 24); - cx->k_sch[7] = w = word_in(in_key + 28); - ks8(0); ks8(1); ks8(2); ks8(3); - ks8(4); ks8(5); ks8(6); - cx->n_rnd = 14; break; - default:cx->n_rnd = 0; return aes_bad; - } -#else - cx->n_rnd = ((klen >> 2) > nc ? (klen >> 2) : nc) + 6; - { - aes_32t l = (nc * (cx->n_rnd + 1) - 1) / (klen >> 2); - switch(klen >> 2) - { - case 4: for(i = 0; i < l; ++i) - ks4(i); - break; - case 5: cx->k_sch[4] = t = word_in(in_key + 16); - for(i = 0; i < l; ++i) - ks5(i); - break; - case 6: cx->k_sch[4] = t = word_in(in_key + 16); - cx->k_sch[5] = u = word_in(in_key + 20); - for(i = 0; i < l; ++i) - ks6(i); - break; - case 7: cx->k_sch[4] = t = word_in(in_key + 16); - cx->k_sch[5] = u = word_in(in_key + 20); - cx->k_sch[6] = v = word_in(in_key + 24); - for(i = 0; i < l; ++i) - ks7(i); - break; - case 8: cx->k_sch[4] = t = word_in(in_key + 16); - cx->k_sch[5] = u = word_in(in_key + 20); - cx->k_sch[6] = v = word_in(in_key + 24); - cx->k_sch[7] = w = word_in(in_key + 28); - for(i = 0; i < l; ++i) - ks8(i); - break; - } - } -#endif - -#if (DEC_ROUND != NO_TABLES) - for(i = nc; i < nc * cx->n_rnd; ++i) - cx->k_sch[i] = inv_mcol(cx->k_sch[i]); -#endif - - return aes_good; -} - -#endif +/* + * ------------------------------------------------------------------------- + * Copyright (c) 2001, Dr Brian Gladman <brg@xxxxxxxxxxxxx>, Worcester, UK. + * All rights reserved. + * + * LICENSE TERMS + * + * The free distribution and use of this software in both source and binary + * form is allowed (with or without changes) provided that: + * + * 1. distributions of this source code include the above copyright + * notice, this list of conditions and the following disclaimer; + * + * 2. distributions in binary form include the above copyright + * notice, this list of conditions and the following disclaimer + * in the documentation and/or other associated materials; + * + * 3. the copyright holder's name is not used to endorse products + * built using this software without specific written permission. + * + * DISCLAIMER + * + * This software is provided 'as is' with no explicit or implied warranties + * in respect of its properties, including, but not limited to, correctness + * and fitness for purpose. + * ------------------------------------------------------------------------- + * Issue Date: 29/07/2002 + * + * This file contains the code for implementing the key schedule for AES + * (Rijndael) for block and key sizes of 16, 20, 24, 28 and 32 bytes. + */ + +#include "aesopt.h" + +/* Subroutine to set the block size (if variable) in bytes, legal + * values being 16, 24 and 32. + */ + +#if !defined(BLOCK_SIZE) + +/* Subroutine to set the block size (if variable) in bytes, legal + * values being 16, 24 and 32. + */ + +aes_rval aes_blk_len(unsigned int blen, aes_ctx cx[1]) +{ +#if !defined(FIXED_TABLES) + if (!tab_init) { + gen_tabs(); + } +#endif + + if ((blen & 3) || blen < 16 || blen > 32) { + cx->n_blk = 0; + return aes_bad; + } + + cx->n_blk = blen; + return aes_good; +} + +#endif + +/* Initialise the key schedule from the user supplied key. The key + * length is now specified in bytes - 16, 24 or 32 as appropriate. + * This corresponds to bit lengths of 128, 192 and 256 bits, and + * to Nk values of 4, 6 and 8 respectively. + * + * The following macros implement a single cycle in the key + * schedule generation process. The number of cycles needed + * for each cx->n_blk and nk value is: + * + * nk = 4 5 6 7 8 + * ------------------------------ + * cx->n_blk = 4 10 9 8 7 7 + * cx->n_blk = 5 14 11 10 9 9 + * cx->n_blk = 6 19 15 12 11 11 + * cx->n_blk = 7 21 19 16 13 14 + * cx->n_blk = 8 29 23 19 17 14 + */ + +/* Initialise the key schedule from the user supplied key. The key + * length is now specified in bytes - 16, 20, 24, 28 or 32 as + * appropriate. This corresponds to bit lengths of 128, 160, 192, + * 224 and 256 bits, and to Nk values of 4, 5, 6, 7 & 8 respectively. + */ + +#define mx(t, f) (*t++ = inv_mcol(*f), f++) +#define cp(t, f) *t++ = *f++ + +#if BLOCK_SIZE == 16 +#define cpy(d, s) cp(d, s); cp(d, s); cp(d, s); cp(d, s) +#define mix(d, s) mx(d, s); mx(d, s); mx(d, s); mx(d, s) +#elif BLOCK_SIZE == 20 +#define cpy(d, s) cp(d, s); cp(d, s); cp(d, s); cp(d, s); \ + cp(d, s) +#define mix(d, s) mx(d, s); mx(d, s); mx(d, s); mx(d, s); \ + mx(d, s) +#elif BLOCK_SIZE == 24 +#define cpy(d, s) cp(d, s); cp(d, s); cp(d, s); cp(d, s); \ + cp(d, s); cp(d, s) +#define mix(d, s) mx(d, s); mx(d, s); mx(d, s); mx(d, s); \ + mx(d, s); mx(d, s) +#elif BLOCK_SIZE == 28 +#define cpy(d, s) cp(d, s); cp(d, s); cp(d, s); cp(d, s); \ + cp(d, s); cp(d, s); cp(d, s) +#define mix(d, s) mx(d, s); mx(d, s); mx(d, s); mx(d, s); \ + mx(d, s); mx(d, s); mx(d, s) +#elif BLOCK_SIZE == 32 +#define cpy(d, s) cp(d, s); cp(d, s); cp(d, s); cp(d, s); \ + cp(d, s); cp(d, s); cp(d, s); cp(d, s) +#define mix(d, s) mx(d, s); mx(d, s); mx(d, s); mx(d, s); \ + mx(d, s); mx(d, s); mx(d, s); mx(d, s) +#else + +#define cpy(d, s) \ + switch (nc) \ + { case 8: cp(d, s); \ + case 7: cp(d, s); \ + case 6: cp(d, s); \ + case 5: cp(d, s); \ + case 4: cp(d, s); cp(d, s); \ + cp(d, s); cp(d, s); \ + } + +#define mix(d, s) \ + switch (nc) \ + { case 8: mx(d, s); \ + case 7: mx(d, s); \ + case 6: mx(d, s); \ + case 5: mx(d, s); \ + case 4: mx(d, s); mx(d, s); \ + mx(d, s); mx(d, s); \ + } + +#endif + +/* The following macros implement a single cycle in the key + * schedule generation process. The number of cycles needed + * for each cx->n_blk and nk value is: + * + * nk = 4 5 6 7 8 + * ----------------------- + * cx->n_blk = 4 10 9 8 7 7 + * cx->n_blk = 5 14 11 10 9 9 + * cx->n_blk = 6 19 15 12 11 11 + * cx->n_blk = 7 21 19 16 13 14 + * cx->n_blk = 8 29 23 19 17 14 + */ + +#define ks4(i) \ + { p ^= ls_box(s, 3) ^ rcon_tab[i]; q ^= p; r ^= q; s ^= r; \ + cx->k_sch[4 * (i) + 4] = p; \ + cx->k_sch[4 * (i) + 5] = q; \ + cx->k_sch[4 * (i) + 6] = r; \ + cx->k_sch[4 * (i) + 7] = s; \ + } + +#define ks5(i) \ + { p ^= ls_box(t, 3) ^ rcon_tab[i]; q ^= p; \ + r ^= q; s ^= r; t ^= s; \ + cx->k_sch[5 * (i) + 5] = p; \ + cx->k_sch[5 * (i) + 6] = q; \ + cx->k_sch[5 * (i) + 7] = r; \ + cx->k_sch[5 * (i) + 8] = s; \ + cx->k_sch[5 * (i) + 9] = t; \ + } + +#define ks6(i) \ + { p ^= ls_box(u, 3) ^ rcon_tab[i]; q ^= p; \ + r ^= q; s ^= r; t ^= s; u ^= t; \ + cx->k_sch[6 * (i) + 6] = p; \ + cx->k_sch[6 * (i) + 7] = q; \ + cx->k_sch[6 * (i) + 8] = r; \ + cx->k_sch[6 * (i) + 9] = s; \ + cx->k_sch[6 * (i) + 10] = t; \ + cx->k_sch[6 * (i) + 11] = u; \ + } + +#define ks7(i) \ + { p ^= ls_box(v, 3) ^ rcon_tab[i]; q ^= p; r ^= q; s ^= r; \ + t ^= ls_box(s, 0); u ^= t; v ^= u; \ + cx->k_sch[7 * (i) + 7] = p; \ + cx->k_sch[7 * (i) + 8] = q; \ + cx->k_sch[7 * (i) + 9] = r; \ + cx->k_sch[7 * (i) + 10] = s; \ + cx->k_sch[7 * (i) + 11] = t; \ + cx->k_sch[7 * (i) + 12] = u; \ + cx->k_sch[7 * (i) + 13] = v; \ + } + +#define ks8(i) \ + { p ^= ls_box(w, 3) ^ rcon_tab[i]; q ^= p; r ^= q; s ^= r; \ + t ^= ls_box(s, 0); u ^= t; v ^= u; w ^= v; \ + cx->k_sch[8 * (i) + 8] = p; \ + cx->k_sch[8 * (i) + 9] = q; \ + cx->k_sch[8 * (i) + 10] = r; \ + cx->k_sch[8 * (i) + 11] = s; \ + cx->k_sch[8 * (i) + 12] = t; \ + cx->k_sch[8 * (i) + 13] = u; \ + cx->k_sch[8 * (i) + 14] = v; \ + cx->k_sch[8 * (i) + 15] = w; \ + } + +#if defined(ENCRYPTION_KEY_SCHEDULE) + +aes_rval aes_enc_key(const unsigned char in_key[], unsigned int klen, aes_ctx cx[1]) +{ + aes_32t i, p, q, r, s, t, u, v, w; + +#if !defined(FIXED_TABLES) + if (!tab_init) { + gen_tabs(); + } +#endif + +#if !defined(BLOCK_SIZE) + if (!cx->n_blk) { + cx->n_blk = 16; + } +#else + cx->n_blk = BLOCK_SIZE; +#endif + + cx->n_blk = (cx->n_blk & ~3) | 1; + cx->n_rnd = ((klen >> 2) > nc ? (klen >> 2) : nc) + 6; + + cx->k_sch[0] = p = word_in(in_key ); + cx->k_sch[1] = q = word_in(in_key + 4); + cx->k_sch[2] = r = word_in(in_key + 8); + cx->k_sch[3] = s = word_in(in_key + 12); + +#if BLOCK_SIZE == 16 && defined(UNROLL) + + switch (klen >> 2) { + case 4: ks4(0); + ks4(1); + ks4(2); + ks4(3); + ks4(4); + ks4(5); + ks4(6); + ks4(7); + ks4(8); + ks4(9); + cx->n_rnd = 10; + break; + case 5: cx->k_sch[4] = t = word_in(in_key + 16); + ks5(0); + ks5(1); + ks5(2); + ks5(3); + ks5(4); + ks5(5); + ks5(6); + ks5(7); + ks5(8); + cx->n_rnd = 11; + break; + case 6: cx->k_sch[4] = t = word_in(in_key + 16); + cx->k_sch[5] = u = word_in(in_key + 20); + ks6(0); + ks6(1); + ks6(2); + ks6(3); + ks6(4); + ks6(5); + ks6(6); + ks6(7); + cx->n_rnd = 12; + break; + case 7: cx->k_sch[4] = t = word_in(in_key + 16); + cx->k_sch[5] = u = word_in(in_key + 20); + cx->k_sch[6] = v = word_in(in_key + 24); + ks7(0); + ks7(1); + ks7(2); + ks7(3); + ks7(4); + ks7(5); + ks7(6); + cx->n_rnd = 13; + break; + case 8: cx->k_sch[4] = t = word_in(in_key + 16); + cx->k_sch[5] = u = word_in(in_key + 20); + cx->k_sch[6] = v = word_in(in_key + 24); + cx->k_sch[7] = w = word_in(in_key + 28); + ks8(0); + ks8(1); + ks8(2); + ks8(3); + ks8(4); + ks8(5); + ks8(6); + cx->n_rnd = 14; + break; + default: cx->n_rnd = 0; + return aes_bad; + } +#else + cx->n_rnd = ((klen >> 2) > nc ? (klen >> 2) : nc) + 6; + { + aes_32t l = (nc * (cx->n_rnd + 1) - 1) / (klen >> 2); + switch (klen >> 2) { + case 4: for (i = 0; i < l; ++i) { + ks4(i); + } + break; + case 5: cx->k_sch[4] = t = word_in(in_key + 16); + for (i = 0; i < l; ++i) { + ks5(i); + } + break; + case 6: cx->k_sch[4] = t = word_in(in_key + 16); + cx->k_sch[5] = u = word_in(in_key + 20); + for (i = 0; i < l; ++i) { + ks6(i); + } + break; + case 7: cx->k_sch[4] = t = word_in(in_key + 16); + cx->k_sch[5] = u = word_in(in_key + 20); + cx->k_sch[6] = v = word_in(in_key + 24); + for (i = 0; i < l; ++i) { + ks7(i); + } + break; + case 8: cx->k_sch[4] = t = word_in(in_key + 16); + cx->k_sch[5] = u = word_in(in_key + 20); + cx->k_sch[6] = v = word_in(in_key + 24); + cx->k_sch[7] = w = word_in(in_key + 28); + for (i = 0; i < l; ++i) { + ks8(i); + } + break; + } + } +#endif + + return aes_good; +} + +#endif + +#if defined(DECRYPTION_KEY_SCHEDULE) + +aes_rval aes_dec_key(const unsigned char in_key[], unsigned int klen, aes_ctx cx[1]) +{ + aes_32t i, p, q, r, s, t, u, v, w; + dec_imvars + +#if !defined(FIXED_TABLES) + if (!tab_init) { + gen_tabs(); + } +#endif + +#if !defined(BLOCK_SIZE) + if (!cx->n_blk) { + cx->n_blk = 16; + } +#else + cx->n_blk = BLOCK_SIZE; +#endif + + cx->n_blk = (cx->n_blk & ~3) | 2; + cx->n_rnd = ((klen >> 2) > nc ? (klen >> 2) : nc) + 6; + + cx->k_sch[0] = p = word_in(in_key ); + cx->k_sch[1] = q = word_in(in_key + 4); + cx->k_sch[2] = r = word_in(in_key + 8); + cx->k_sch[3] = s = word_in(in_key + 12); + +#if BLOCK_SIZE == 16 && defined(UNROLL) + + switch (klen >> 2) { + case 4: ks4(0); + ks4(1); + ks4(2); + ks4(3); + ks4(4); + ks4(5); + ks4(6); + ks4(7); + ks4(8); + ks4(9); + cx->n_rnd = 10; + break; + case 5: cx->k_sch[4] = t = word_in(in_key + 16); + ks5(0); + ks5(1); + ks5(2); + ks5(3); + ks5(4); + ks5(5); + ks5(6); + ks5(7); + ks5(8); + cx->n_rnd = 11; + break; + case 6: cx->k_sch[4] = t = word_in(in_key + 16); + cx->k_sch[5] = u = word_in(in_key + 20); + ks6(0); + ks6(1); + ks6(2); + ks6(3); + ks6(4); + ks6(5); + ks6(6); + ks6(7); + cx->n_rnd = 12; + break; + case 7: cx->k_sch[4] = t = word_in(in_key + 16); + cx->k_sch[5] = u = word_in(in_key + 20); + cx->k_sch[6] = v = word_in(in_key + 24); + ks7(0); + ks7(1); + ks7(2); + ks7(3); + ks7(4); + ks7(5); + ks7(6); + cx->n_rnd = 13; + break; + case 8: cx->k_sch[4] = t = word_in(in_key + 16); + cx->k_sch[5] = u = word_in(in_key + 20); + cx->k_sch[6] = v = word_in(in_key + 24); + cx->k_sch[7] = w = word_in(in_key + 28); + ks8(0); + ks8(1); + ks8(2); + ks8(3); + ks8(4); + ks8(5); + ks8(6); + cx->n_rnd = 14; + break; + default: cx->n_rnd = 0; + return aes_bad; + } +#else + cx->n_rnd = ((klen >> 2) > nc ? (klen >> 2) : nc) + 6; + { + aes_32t l = (nc * (cx->n_rnd + 1) - 1) / (klen >> 2); + switch (klen >> 2) { + case 4: for (i = 0; i < l; ++i) { + ks4(i); + } + break; + case 5: cx->k_sch[4] = t = word_in(in_key + 16); + for (i = 0; i < l; ++i) { + ks5(i); + } + break; + case 6: cx->k_sch[4] = t = word_in(in_key + 16); + cx->k_sch[5] = u = word_in(in_key + 20); + for (i = 0; i < l; ++i) { + ks6(i); + } + break; + case 7: cx->k_sch[4] = t = word_in(in_key + 16); + cx->k_sch[5] = u = word_in(in_key + 20); + cx->k_sch[6] = v = word_in(in_key + 24); + for (i = 0; i < l; ++i) { + ks7(i); + } + break; + case 8: cx->k_sch[4] = t = word_in(in_key + 16); + cx->k_sch[5] = u = word_in(in_key + 20); + cx->k_sch[6] = v = word_in(in_key + 24); + cx->k_sch[7] = w = word_in(in_key + 28); + for (i = 0; i < l; ++i) { + ks8(i); + } + break; + } + } +#endif + +#if (DEC_ROUND != NO_TABLES) + for (i = nc; i < nc * cx->n_rnd; ++i) { + cx->k_sch[i] = inv_mcol(cx->k_sch[i]); + } +#endif + + return aes_good; +} + +#endif === modified file 'i3/aeshash/aesopt.h' --- i3/aeshash/aesopt.h 2010-02-10 00:01:34 +0000 +++ i3/aeshash/aesopt.h 2010-02-11 11:49:47 +0000 @@ -1,841 +1,841 @@ -/* - ------------------------------------------------------------------------- - Copyright (c) 2001, Dr Brian Gladman <brg@xxxxxxxxxxxxx>, Worcester, UK. - All rights reserved. - - LICENSE TERMS - - The free distribution and use of this software in both source and binary - form is allowed (with or without changes) provided that: - - 1. distributions of this source code include the above copyright - notice, this list of conditions and the following disclaimer; - - 2. distributions in binary form include the above copyright - notice, this list of conditions and the following disclaimer - in the documentation and/or other associated materials; - - 3. the copyright holder's name is not used to endorse products - built using this software without specific written permission. - - DISCLAIMER - - This software is provided 'as is' with no explicit or implied warranties - in respect of its properties, including, but not limited to, correctness - and fitness for purpose. - ------------------------------------------------------------------------- - Issue Date: 29/07/2002 - - This file contains the compilation options for AES (Rijndael) and code - that is common across encryption, key scheduling and table generation. - - OPERATION - - These source code files implement the AES algorithm Rijndael designed by - Joan Daemen and Vincent Rijmen. The version in aes.c is designed for - block and key sizes of 128, 192 and 256 bits (16, 24 and 32 bytes) while - that in aespp.c provides for block and keys sizes of 128, 160, 192, 224 - and 256 bits (16, 20, 24, 28 and 32 bytes). This file is a common header - file for these two implementations and for aesref.c, which is a reference - implementation. - - This version is designed for flexibility and speed using operations on - 32-bit words rather than operations on bytes. It provides aes_both fixed - and dynamic block and key lengths and can also run with either big or - little endian internal byte order (see aes.h). It inputs block and key - lengths in bytes with the legal values being 16, 24 and 32 for aes.c and - 16, 20, 24, 28 and 32 for aespp.c - - THE CIPHER INTERFACE - - aes_08t (an unsigned 8-bit type) - aes_32t (an unsigned 32-bit type) - aes_fret (a signed 16 bit type for function return values) - aes_good (value != 0, a good return) - aes_bad (value == 0, an error return) - struct aes_ctx (structure for the cipher encryption context) - struct aes_ctx (structure for the cipher decryption context) - aes_rval the function return type (aes_fret if not DLL) - - C subroutine calls: - - aes_rval aes_blk_len(unsigned int blen, aes_ctx cx[1]); - aes_rval aes_enc_key(const unsigned char in_key[], unsigned int klen, aes_ctx cx[1]); - aes_rval aes_enc_blk(const unsigned char in_blk[], unsigned char out_blk[], const aes_ctx cx[1]); - - aes_rval aes_dec_len(unsigned int blen, aes_ctx cx[1]); - aes_rval aes_dec_key(const unsigned char in_key[], unsigned int klen, aes_ctx cx[1]); - aes_rval aes_dec_blk(const unsigned char in_blk[], unsigned char out_blk[], const aes_ctx cx[1]); - - IMPORTANT NOTE: If you are using this C interface and your compiler does - not set the memory used for objects to zero before use, you will need to - ensure that cx.s_flg is set to zero before using these subroutine calls. - - C++ aes class subroutines: - - class AESclass for encryption - class AESclass for decryption - - aes_rval len(unsigned int blen = 16); - aes_rval key(const unsigned char in_key[], unsigned int klen); - aes_rval blk(const unsigned char in_blk[], unsigned char out_blk[]); - - aes_rval len(unsigned int blen = 16); - aes_rval key(const unsigned char in_key[], unsigned int klen); - aes_rval blk(const unsigned char in_blk[], unsigned char out_blk[]); - - The block length inputs to set_block and set_key are in numbers of - BYTES, not bits. The calls to subroutines must be made in the above - order but multiple calls can be made without repeating earlier calls - if their parameters have not changed. If the cipher block length is - variable but set_blk has not been called before cipher operations a - value of 16 is assumed (that is, the AES block size). In contrast to - earlier versions the block and key length parameters are now checked - for correctness and the encryption and decryption routines check to - ensure that an appropriate key has been set before they are called. - - COMPILATION - - The files used to provide AES (Rijndael) are - - a. aes.h for the definitions needed for use in C. - b. aescpp.h for the definitions needed for use in C++. - c. aesopt.h for setting compilation options (also includes common - code). - d. aescrypt.c for encryption and decrytpion, or - e. aescrypt.asm for encryption and decryption using assembler code. - f. aeskey.c for key scheduling. - g. aestab.c for table loading or generation. - - The assembler code uses the NASM assembler. The above files provice - block and key lengths of 16, 24 and 32 bytes (128, 192 and 256 bits). - If aescrypp.c and aeskeypp.c are used instead of aescrypt.c and - aeskey.c respectively, the block and key lengths can then be 16, 20, - 24, 28 or 32 bytes. However this code has not been optimised to the - same extent and is hence slower (esepcially for the AES block size - of 16 bytes). - - To compile AES (Rijndael) for use in C code use aes.h and exclude - the AES_DLL define in aes.h - - To compile AES (Rijndael) for use in in C++ code use aescpp.h and - exclude the AES_DLL define in aes.h - - To compile AES (Rijndael) in C as a Dynamic Link Library DLL) use - aes.h, include the AES_DLL define and compile the DLL. If using - the test files to test the DLL, exclude aes.c from the test build - project and compile it with the same defines as used for the DLL - (ensure that the DLL path is correct) - - CONFIGURATION OPTIONS (here and in aes.h) - - a. define BLOCK_SIZE in aes.h to set the cipher block size (16, 24 - or 32 for the standard code, or 16, 20, 24, 28 or 32 for the - extended code) or leave this undefined for dynamically variable - block size (this will result in much slower code). - b. set AES_DLL in aes.h if AES (Rijndael) is to be compiled as a DLL - c. You may need to set PLATFORM_BYTE_ORDER to define the byte order. - d. If you want the code to run in a specific internal byte order, then - INTERNAL_BYTE_ORDER must be set accordingly. - e. set other configuration options decribed below. -*/ - -#ifndef _AESOPT_H -#define _AESOPT_H - -/* START OF CONFIGURATION OPTIONS - - USE OF DEFINES - - Later in this section there are a number of defines that control the - operation of the code. In each section, the purpose of each define is - explained so that the relevant form can be included or excluded by - setting either 1's or 0's respectively on the branches of the related - #if clauses. -*/ - -/* 1. PLATFORM SPECIFIC INCLUDES */ - -#if defined( __CRYPTLIB__ ) && !defined( INC_ALL ) && !defined( INC_CHILD ) -#include "crypt/aes.h" -#else - #include "aes.h" -#endif - -#if (defined(__GNUC__) || defined(__GNU_LIBRARY__)) && !defined(__CYGWIN__) -# if defined(__APPLE__) -# include <machine/endian.h> -# else -# include <endian.h> -# endif -//# include <machine/byteswap.h> -#elif defined(__CRYPTLIB__) -# if defined( INC_ALL ) -# include "crypt.h" -# elif defined( INC_CHILD ) -# include "../crypt.h" -# else -# include "crypt.h" -# endif -# if defined(DATA_LITTLEENDIAN) -# define PLATFORM_BYTE_ORDER AES_LITTLE_ENDIAN -# else -# define PLATFORM_BYTE_ORDER AES_BIG_ENDIAN -# endif -#elif defined(_MSC_VER) -# include <stdlib.h> -#elif !defined(WIN32) -# include <stdlib.h> -# if !defined (_ENDIAN_H) -# include <sys/param.h> -# else -# include _ENDIAN_H -# endif -#endif - -/* 2. BYTE ORDER IN 32-BIT WORDS - - To obtain the highest speed on processors with 32-bit words, this code - needs to determine the order in which bytes are packed into such words. - The following block of code is an attempt to capture the most obvious - ways in which various environemnts define byte order. It may well fail, - in which case the definitions will need to be set by editing at the - points marked **** EDIT HERE IF NECESSARY **** below. -*/ -#define AES_LITTLE_ENDIAN 1234 /* byte 0 is least significant (i386) */ -#define AES_BIG_ENDIAN 4321 /* byte 0 is most significant (mc68k) */ - -#if !defined(PLATFORM_BYTE_ORDER) -#if defined(LITTLE_ENDIAN) || defined(BIG_ENDIAN) -# if defined(LITTLE_ENDIAN) && defined(BIG_ENDIAN) -# if defined(BYTE_ORDER) -# if (BYTE_ORDER == LITTLE_ENDIAN) -# define PLATFORM_BYTE_ORDER AES_LITTLE_ENDIAN -# elif (BYTE_ORDER == BIG_ENDIAN) -# define PLATFORM_BYTE_ORDER AES_BIG_ENDIAN -# endif -# endif -# elif defined(LITTLE_ENDIAN) && !defined(BIG_ENDIAN) -# define PLATFORM_BYTE_ORDER AES_LITTLE_ENDIAN -# elif !defined(LITTLE_ENDIAN) && defined(BIG_ENDIAN) -# define PLATFORM_BYTE_ORDER AES_BIG_ENDIAN -# endif -#elif defined(_LITTLE_ENDIAN) || defined(_BIG_ENDIAN) -# if defined(_LITTLE_ENDIAN) && defined(_BIG_ENDIAN) -# if defined(_BYTE_ORDER) -# if (_BYTE_ORDER == _LITTLE_ENDIAN) -# define PLATFORM_BYTE_ORDER AES_LITTLE_ENDIAN -# elif (_BYTE_ORDER == _BIG_ENDIAN) -# define PLATFORM_BYTE_ORDER AES_BIG_ENDIAN -# endif -# endif -# elif defined(_LITTLE_ENDIAN) && !defined(_BIG_ENDIAN) -# define PLATFORM_BYTE_ORDER AES_LITTLE_ENDIAN -# elif !defined(_LITTLE_ENDIAN) && defined(_BIG_ENDIAN) -# define PLATFORM_BYTE_ORDER AES_BIG_ENDIAN -# endif -#elif defined(__BYTE_ORDER) -# if (__BYTE_ORDER == __LITTLE_ENDIAN) -# define PLATFORM_BYTE_ORDER AES_LITTLE_ENDIAN -# elif (__BYTE_ORDER == __BIG_ENDIAN) -# define PLATFORM_BYTE_ORDER AES_BIG_ENDIAN -# endif -#elif 0 /* **** EDIT HERE IF NECESSARY **** */ -#define PLATFORM_BYTE_ORDER AES_LITTLE_ENDIAN -#elif 1 /* **** EDIT HERE IF NECESSARY **** */ -XX_FIXME -/*#define PLATFORM_BYTE_ORDER AES_BIG_ENDIAN -#elif (('1234' >> 24) == '1') -# define PLATFORM_BYTE_ORDER AES_LITTLE_ENDIAN -#elif (('4321' >> 24) == '1') -# define PLATFORM_BYTE_ORDER AES_BIG_ENDIAN */ -#endif -#endif - -#if !defined(PLATFORM_BYTE_ORDER) -# error Please set undetermined byte order (lines 233 or 235 of aesopt.h). -#endif - -/* 3. ASSEMBLER SUPPORT - - If the assembler code is used for encryption and decryption this file only - provides key scheduling so the following defines are used -*/ -#ifdef AES_ASM -#define ENCRYPTION_KEY_SCHEDULE -#define DECRYPTION_KEY_SCHEDULE -#else - -/* 4. FUNCTIONS REQUIRED - - This implementation provides five main subroutines which provide for - setting block length, setting encryption and decryption keys and for - encryption and decryption. When the assembler code is not being used - the following definition blocks allow the selection of the routines - that are to be included in the compilation. -*/ -#if 1 -#define ENCRYPTION_KEY_SCHEDULE -#endif - -#if 1 -#define DECRYPTION_KEY_SCHEDULE -#endif - -#if 1 -#define ENCRYPTION -#endif - -#if 1 -#define DECRYPTION -#endif - -#endif - -/* 5. BYTE ORDER WITHIN 32 BIT WORDS - - The fundamental data processing units in Rijndael are 8-bit bytes. The - input, output and key input are all enumerated arrays of bytes in which - bytes are numbered starting at zero and increasing to one less than the - number of bytes in the array in question. This enumeration is only used - for naming bytes and does not imply any adjacency or order relationship - from one byte to another. When these inputs and outputs are considered - as bit sequences, bits 8*n to 8*n+7 of the bit sequence are mapped to - byte[n] with bit 8n+i in the sequence mapped to bit 7-i within the byte. - In this implementation bits are numbered from 0 to 7 starting at the - numerically least significant end of each byte (bit n represents 2^n). - - However, Rijndael can be implemented more efficiently using 32-bit - words by packing bytes into words so that bytes 4*n to 4*n+3 are placed - into word[n]. While in principle these bytes can be assembled into words - in any positions, this implementation only supports the two formats in - which bytes in adjacent positions within words also have adjacent byte - numbers. This order is called big-endian if the lowest numbered bytes - in words have the highest numeric significance and little-endian if the - opposite applies. - - This code can work in either order irrespective of the order used by the - machine on which it runs. Normally the internal byte order will be set - to the order of the processor on which the code is to be run but this - define can be used to reverse this in special situations -*/ -#if 1 -#define INTERNAL_BYTE_ORDER PLATFORM_BYTE_ORDER -#elif defined(AES_LITTLE_ENDIAN) -#define INTERNAL_BYTE_ORDER AES_LITTLE_ENDIAN -#elif defined(AES_BIG_ENDIAN) -#define INTERNAL_BYTE_ORDER AES_BIG_ENDIAN -#endif - -/* 6. FAST INPUT/OUTPUT OPERATIONS. - - On some machines it is possible to improve speed by transferring the - bytes in the input and output arrays to and from the internal 32-bit - variables by addressing these arrays as if they are arrays of 32-bit - words. On some machines this will always be possible but there may - be a large performance penalty if the byte arrays are not aligned on - the normal word boundaries. On other machines this technique will - lead to memory access errors when such 32-bit word accesses are not - properly aligned. The option SAFE_IO avoids such problems but will - often be slower on those machines that support misaligned access - (especially so if care is taken to align the input and output byte - arrays on 32-bit word boundaries). If SAFE_IO is not defined it is - assumed that access to byte arrays as if they are arrays of 32-bit - words will not cause problems when such accesses are misaligned. -*/ -#if 0 -#define SAFE_IO -#endif - -/* 7. LOOP UNROLLING - - The code for encryption and decrytpion cycles through a number of rounds - that can be implemented either in a loop or by expanding the code into a - long sequence of instructions, the latter producing a larger program but - one that will often be much faster. The latter is called loop unrolling. - There are also potential speed advantages in expanding two iterations in - a loop with half the number of iterations, which is called partial loop - unrolling. The following options allow partial or full loop unrolling - to be set independently for encryption and decryption -*/ -#if 1 -#define ENC_UNROLL FULL -#elif 0 -#define ENC_UNROLL PARTIAL -#else -#define ENC_UNROLL NONE -#endif - -#if 1 -#define DEC_UNROLL FULL -#elif 0 -#define DEC_UNROLL PARTIAL -#else -#define DEC_UNROLL NONE -#endif - -/* 8. FIXED OR DYNAMIC TABLES - - When this section is included the tables used by the code are comipled - statically into the binary file. Otherwise they are computed once when - the code is first used. -*/ -#if 1 -#define FIXED_TABLES -#endif - -/* 9. FAST FINITE FIELD OPERATIONS - - If this section is included, tables are used to provide faster finite - field arithmetic (this has no effect if FIXED_TABLES is defined). -*/ -#if 1 -#define FF_TABLES -#endif - -/* 10. INTERNAL STATE VARIABLE FORMAT - - The internal state of Rijndael is stored in a number of local 32-bit - word varaibles which can be defined either as an array or as individual - names variables. Include this section if you want to store these local - varaibles in arrays. Otherwise individual local variables will be used. -*/ -#if 1 -#define ARRAYS -#endif - -/* In this implementation the columns of the state array are each held in - 32-bit words. The state array can be held in various ways: in an array - of words, in a number of individual word variables or in a number of - processor registers. The following define maps a variable name x and - a column number c to the way the state array variable is to be held. - The first define below maps the state into an array x[c] whereas the - second form maps the state into a number of individual variables x0, - x1, etc. Another form could map individual state colums to machine - register names. -*/ - -#if defined(ARRAYS) -#define s(x,c) x[c] -#else -#define s(x,c) x##c -#endif - -/* 11. VARIABLE BLOCK SIZE SPEED - - This section is only relevant if you wish to use the variable block - length feature of the code. Include this section if you place more - emphasis on speed rather than code size. -*/ -#if 1 -#define FAST_VARIABLE -#endif - -/* 12. INTERNAL TABLE CONFIGURATION - - This cipher proceeds by repeating in a number of cycles known as 'rounds' - which are implemented by a round function which can optionally be speeded - up using tables. The basic tables are each 256 32-bit words, with either - one or four tables being required for each round function depending on - how much speed is required. The encryption and decryption round functions - are different and the last encryption and decrytpion round functions are - different again making four different round functions in all. - - This means that: - 1. Normal encryption and decryption rounds can each use either 0, 1 - or 4 tables and table spaces of 0, 1024 or 4096 bytes each. - 2. The last encryption and decryption rounds can also use either 0, 1 - or 4 tables and table spaces of 0, 1024 or 4096 bytes each. - - Include or exclude the appropriate definitions below to set the number - of tables used by this implementation. -*/ - -#if 1 /* set tables for the normal encryption round */ -#define ENC_ROUND FOUR_TABLES -#elif 0 -#define ENC_ROUND ONE_TABLE -#else -#define ENC_ROUND NO_TABLES -#endif - -#if 1 /* set tables for the last encryption round */ -#define LAST_ENC_ROUND FOUR_TABLES -#elif 0 -#define LAST_ENC_ROUND ONE_TABLE -#else -#define LAST_ENC_ROUND NO_TABLES -#endif - -#if 1 /* set tables for the normal decryption round */ -#define DEC_ROUND FOUR_TABLES -#elif 0 -#define DEC_ROUND ONE_TABLE -#else -#define DEC_ROUND NO_TABLES -#endif - -#if 1 /* set tables for the last decryption round */ -#define LAST_DEC_ROUND FOUR_TABLES -#elif 0 -#define LAST_DEC_ROUND ONE_TABLE -#else -#define LAST_DEC_ROUND NO_TABLES -#endif - -/* The decryption key schedule can be speeded up with tables in the same - way that the round functions can. Include or exclude the following - defines to set this requirement. -*/ -#if 1 -#define KEY_SCHED FOUR_TABLES -#elif 0 -#define KEY_SCHED ONE_TABLE -#else -#define KEY_SCHED NO_TABLES -#endif - -/* END OF CONFIGURATION OPTIONS */ - -#define NO_TABLES 0 /* DO NOT CHANGE */ -#define ONE_TABLE 1 /* DO NOT CHANGE */ -#define FOUR_TABLES 4 /* DO NOT CHANGE */ -#define NONE 0 /* DO NOT CHANGE */ -#define PARTIAL 1 /* DO NOT CHANGE */ -#define FULL 2 /* DO NOT CHANGE */ - -#if defined(BLOCK_SIZE) && ((BLOCK_SIZE & 3) || BLOCK_SIZE < 16 || BLOCK_SIZE > 32) -#error An illegal block size has been specified. -#endif - -#if !defined(BLOCK_SIZE) -#define RC_LENGTH 29 -#else -#define RC_LENGTH 5 * BLOCK_SIZE / 4 - (BLOCK_SIZE == 16 ? 10 : 11) -#endif - -/* Disable at least some poor combinations of options */ - -#if ENC_ROUND == NO_TABLES && LAST_ENC_ROUND != NO_TABLES -#undef LAST_ENC_ROUND -#define LAST_ENC_ROUND NO_TABLES -#elif ENC_ROUND == ONE_TABLE && LAST_ENC_ROUND == FOUR_TABLES -#undef LAST_ENC_ROUND -#define LAST_ENC_ROUND ONE_TABLE -#endif - -#if ENC_ROUND == NO_TABLES && ENC_UNROLL != NONE -#undef ENC_UNROLL -#define ENC_UNROLL NONE -#endif - -#if DEC_ROUND == NO_TABLES && LAST_DEC_ROUND != NO_TABLES -#undef LAST_DEC_ROUND -#define LAST_DEC_ROUND NO_TABLES -#elif DEC_ROUND == ONE_TABLE && LAST_DEC_ROUND == FOUR_TABLES -#undef LAST_DEC_ROUND -#define LAST_DEC_ROUND ONE_TABLE -#endif - -#if DEC_ROUND == NO_TABLES && DEC_UNROLL != NONE -#undef DEC_UNROLL -#define DEC_UNROLL NONE -#endif - -/* upr(x,n): rotates bytes within words by n positions, moving bytes to - higher index positions with wrap around into low positions - ups(x,n): moves bytes by n positions to higher index positions in - words but without wrap around - bval(x,n): extracts a byte from a word - - NOTE: The definitions given here are intended only for use with - unsigned variables and with shift counts that are compile - time constants -*/ - -#if (INTERNAL_BYTE_ORDER == AES_LITTLE_ENDIAN) -#if defined(_MSC_VER) -#define upr(x,n) _lrotl((aes_32t)(x), 8 * (n)) -#else -#define upr(x,n) ((aes_32t)(x) << 8 * (n) | (aes_32t)(x) >> 32 - 8 * (n)) -#endif -#define ups(x,n) ((aes_32t)(x) << 8 * (n)) -#define bval(x,n) ((aes_08t)((x) >> 8 * (n))) -#define bytes2word(b0, b1, b2, b3) \ - (((aes_32t)(b3) << 24) | ((aes_32t)(b2) << 16) | ((aes_32t)(b1) << 8) | (b0)) -#endif - -#if (INTERNAL_BYTE_ORDER == AES_BIG_ENDIAN) -#define upr(x,n) ((aes_32t)(x) >> 8 * (n) | (aes_32t)(x) << 32 - 8 * (n)) -#define ups(x,n) ((aes_32t)(x) >> 8 * (n))) -#define bval(x,n) ((aes_08t)((x) >> 24 - 8 * (n))) -#define bytes2word(b0, b1, b2, b3) \ - (((aes_32t)(b0) << 24) | ((aes_32t)(b1) << 16) | ((aes_32t)(b2) << 8) | (b3)) -#endif - -#if defined(SAFE_IO) - -#define word_in(x) bytes2word((x)[0], (x)[1], (x)[2], (x)[3]) -#define word_out(x,v) { (x)[0] ^= bval(v,0); (x)[1] ^= bval(v,1); \ - (x)[2] ^= bval(v,2); (x)[3] ^= bval(v,3); } - -#elif (INTERNAL_BYTE_ORDER == PLATFORM_BYTE_ORDER) - -#define word_in(x) *(aes_32t*)(x) -#define word_out(x,v) *(aes_32t*)(x) ^= (v) - -#else - -#if !defined(bswap_32) -#if !defined(_MSC_VER) -#define _lrotl(x,n) ((aes_32t)(x) << n | (aes_32t)(x) >> 32 - n) -#endif -#define bswap_32(x) ((_lrotl((x),8) & 0x00ff00ff) | (_lrotl((x),24) & 0xff00ff00)) -#endif - -#warn using slow bswap -#define word_in(x) bswap_32(*(aes_32t*)(x)) -#define word_out(x,v) *(aes_32t*)(x) ^= bswap_32(v) - -#endif - -/* the finite field modular polynomial and elements */ - -#define WPOLY 0x011b -#define BPOLY 0x1b - -/* multiply four bytes in GF(2^8) by 'x' {02} in parallel */ - -#define m1 0x80808080 -#define m2 0x7f7f7f7f -#define FFmulX(x) ((((x) & m2) << 1) ^ ((((x) & m1) >> 7) * BPOLY)) - -/* The following defines provide alternative definitions of FFmulX that might - give improved performance if a fast 32-bit multiply is not available. Note - that a temporary variable u needs to be defined where FFmulX is used. - -#define FFmulX(x) (u = (x) & m1, u |= (u >> 1), ((x) & m2) << 1) ^ ((u >> 3) | (u >> 6)) -#define m4 (0x01010101 * BPOLY) -#define FFmulX(x) (u = (x) & m1, ((x) & m2) << 1) ^ ((u - (u >> 7)) & m4) -*/ - -/* Work out which tables are needed for the different options */ - -#ifdef AES_ASM -#ifdef ENC_ROUND -#undef ENC_ROUND -#endif -#define ENC_ROUND FOUR_TABLES -#ifdef LAST_ENC_ROUND -#undef LAST_ENC_ROUND -#endif -#define LAST_ENC_ROUND FOUR_TABLES -#ifdef DEC_ROUND -#undef DEC_ROUND -#endif -#define DEC_ROUND FOUR_TABLES -#ifdef LAST_DEC_ROUND -#undef LAST_DEC_ROUND -#endif -#define LAST_DEC_ROUND FOUR_TABLES -#ifdef KEY_SCHED -#undef KEY_SCHED -#define KEY_SCHED FOUR_TABLES -#endif -#endif - -#if defined(ENCRYPTION) || defined(AES_ASM) -#if ENC_ROUND == ONE_TABLE -#define FT1_SET -#elif ENC_ROUND == FOUR_TABLES -#define FT4_SET -#else -#define SBX_SET -#endif -#if LAST_ENC_ROUND == ONE_TABLE -#define FL1_SET -#elif LAST_ENC_ROUND == FOUR_TABLES -#define FL4_SET -#elif !defined(SBX_SET) -#define SBX_SET -#endif -#endif - -#if defined(DECRYPTION) || defined(AES_ASM) -#if DEC_ROUND == ONE_TABLE -#define IT1_SET -#elif DEC_ROUND == FOUR_TABLES -#define IT4_SET -#else -#define ISB_SET -#endif -#if LAST_DEC_ROUND == ONE_TABLE -#define IL1_SET -#elif LAST_DEC_ROUND == FOUR_TABLES -#define IL4_SET -#elif !defined(ISB_SET) -#define ISB_SET -#endif -#endif - -#if defined(ENCRYPTION_KEY_SCHEDULE) || defined(DECRYPTION_KEY_SCHEDULE) -#if KEY_SCHED == ONE_TABLE -#define LS1_SET -#define IM1_SET -#elif KEY_SCHED == FOUR_TABLES -#define LS4_SET -#define IM4_SET -#elif !defined(SBX_SET) -#define SBX_SET -#endif -#endif - -#ifdef FIXED_TABLES -#define prefx extern const -#else -#define prefx extern -extern aes_08t tab_init; -void gen_tabs(void); -#endif - -prefx aes_32t rcon_tab[29]; - -#ifdef SBX_SET -prefx aes_08t s_box[256]; -#endif - -#ifdef ISB_SET -prefx aes_08t inv_s_box[256]; -#endif - -#ifdef FT1_SET -prefx aes_32t ft_tab[256]; -#endif - -#ifdef FT4_SET -prefx aes_32t ft_tab[4][256]; -#endif - -#ifdef FL1_SET -prefx aes_32t fl_tab[256]; -#endif - -#ifdef FL4_SET -prefx aes_32t fl_tab[4][256]; -#endif - -#ifdef IT1_SET -prefx aes_32t it_tab[256]; -#endif - -#ifdef IT4_SET -prefx aes_32t it_tab[4][256]; -#endif - -#ifdef IL1_SET -prefx aes_32t il_tab[256]; -#endif - -#ifdef IL4_SET -prefx aes_32t il_tab[4][256]; -#endif - -#ifdef LS1_SET -#ifdef FL1_SET -#undef LS1_SET -#else -prefx aes_32t ls_tab[256]; -#endif -#endif - -#ifdef LS4_SET -#ifdef FL4_SET -#undef LS4_SET -#else -prefx aes_32t ls_tab[4][256]; -#endif -#endif - -#ifdef IM1_SET -prefx aes_32t im_tab[256]; -#endif - -#ifdef IM4_SET -prefx aes_32t im_tab[4][256]; -#endif - -/* Set the number of columns in nc. Note that it is important - that nc is a constant which is known at compile time if the - highest speed version of the code is needed. -*/ - -#if defined(BLOCK_SIZE) -#define nc (BLOCK_SIZE >> 2) -#else -#define nc (cx->n_blk >> 2) -#endif - -/* generic definitions of Rijndael macros that use tables */ - -#define no_table(x,box,vf,rf,c) bytes2word( \ - box[bval(vf(x,0,c),rf(0,c))], \ - box[bval(vf(x,1,c),rf(1,c))], \ - box[bval(vf(x,2,c),rf(2,c))], \ - box[bval(vf(x,3,c),rf(3,c))]) - -#define one_table(x,op,tab,vf,rf,c) \ - ( tab[bval(vf(x,0,c),rf(0,c))] \ - ^ op(tab[bval(vf(x,1,c),rf(1,c))],1) \ - ^ op(tab[bval(vf(x,2,c),rf(2,c))],2) \ - ^ op(tab[bval(vf(x,3,c),rf(3,c))],3)) - -#define four_tables(x,tab,vf,rf,c) \ - ( tab[0][bval(vf(x,0,c),rf(0,c))] \ - ^ tab[1][bval(vf(x,1,c),rf(1,c))] \ - ^ tab[2][bval(vf(x,2,c),rf(2,c))] \ - ^ tab[3][bval(vf(x,3,c),rf(3,c))]) - -#define vf1(x,r,c) (x) -#define rf1(r,c) (r) -#define rf2(r,c) ((r-c)&3) - -/* perform forward and inverse column mix operation on four bytes in long word x in */ -/* parallel. NOTE: x must be a simple variable, NOT an expression in these macros. */ - -#define dec_fmvars -#if defined(FM4_SET) /* not currently used */ -#define fwd_mcol(x) four_tables(x,fm_tab,vf1,rf1,0) -#elif defined(FM1_SET) /* not currently used */ -#define fwd_mcol(x) one_table(x,upr,fm_tab,vf1,rf1,0) -#else -#undef dec_fmvars -#define dec_fmvars aes_32t f1, f2; -#define fwd_mcol(x) (f1 = (x), f2 = FFmulX(f1), f2 ^ upr(f1 ^ f2, 3) ^ upr(f1, 2) ^ upr(f1, 1)) -#endif - -#define dec_imvars -#if defined(IM4_SET) -#define inv_mcol(x) four_tables(x,im_tab,vf1,rf1,0) -#elif defined(IM1_SET) -#define inv_mcol(x) one_table(x,upr,im_tab,vf1,rf1,0) -#else -#undef dec_imvars -#define dec_imvars aes_32t f2, f4, f8, f9; -#define inv_mcol(x) \ - (f9 = (x), f2 = FFmulX(f9), f4 = FFmulX(f2), f8 = FFmulX(f4), f9 ^= f8, \ - f2 ^= f4 ^ f8 ^ upr(f2 ^ f9,3) ^ upr(f4 ^ f9,2) ^ upr(f9,1)) -#endif - -#if defined(FL4_SET) -#define ls_box(x,c) four_tables(x,fl_tab,vf1,rf2,c) -#elif defined(LS4_SET) -#define ls_box(x,c) four_tables(x,ls_tab,vf1,rf2,c) -#elif defined(FL1_SET) -#define ls_box(x,c) one_table(x,upr,fl_tab,vf1,rf2,c) -#elif defined(LS1_SET) -#define ls_box(x,c) one_table(x,upr,ls_tab,vf1,rf2,c) -#else -#define ls_box(x,c) no_table(x,s_box,vf1,rf2,c) -#endif - -#endif +/* + * ------------------------------------------------------------------------- + * Copyright (c) 2001, Dr Brian Gladman <brg@xxxxxxxxxxxxx>, Worcester, UK. + * All rights reserved. + * + * LICENSE TERMS + * + * The free distribution and use of this software in both source and binary + * form is allowed (with or without changes) provided that: + * + * 1. distributions of this source code include the above copyright + * notice, this list of conditions and the following disclaimer; + * + * 2. distributions in binary form include the above copyright + * notice, this list of conditions and the following disclaimer + * in the documentation and/or other associated materials; + * + * 3. the copyright holder's name is not used to endorse products + * built using this software without specific written permission. + * + * DISCLAIMER + * + * This software is provided 'as is' with no explicit or implied warranties + * in respect of its properties, including, but not limited to, correctness + * and fitness for purpose. + * ------------------------------------------------------------------------- + * Issue Date: 29/07/2002 + * + * This file contains the compilation options for AES (Rijndael) and code + * that is common across encryption, key scheduling and table generation. + * + * OPERATION + * + * These source code files implement the AES algorithm Rijndael designed by + * Joan Daemen and Vincent Rijmen. The version in aes.c is designed for + * block and key sizes of 128, 192 and 256 bits (16, 24 and 32 bytes) while + * that in aespp.c provides for block and keys sizes of 128, 160, 192, 224 + * and 256 bits (16, 20, 24, 28 and 32 bytes). This file is a common header + * file for these two implementations and for aesref.c, which is a reference + * implementation. + * + * This version is designed for flexibility and speed using operations on + * 32-bit words rather than operations on bytes. It provides aes_both fixed + * and dynamic block and key lengths and can also run with either big or + * little endian internal byte order (see aes.h). It inputs block and key + * lengths in bytes with the legal values being 16, 24 and 32 for aes.c and + * 16, 20, 24, 28 and 32 for aespp.c + * + * THE CIPHER INTERFACE + * + * aes_08t (an unsigned 8-bit type) + * aes_32t (an unsigned 32-bit type) + * aes_fret (a signed 16 bit type for function return values) + * aes_good (value != 0, a good return) + * aes_bad (value == 0, an error return) + * struct aes_ctx (structure for the cipher encryption context) + * struct aes_ctx (structure for the cipher decryption context) + * aes_rval the function return type (aes_fret if not DLL) + * + * C subroutine calls: + * + * aes_rval aes_blk_len(unsigned int blen, aes_ctx cx[1]); + * aes_rval aes_enc_key(const unsigned char in_key[], unsigned int klen, aes_ctx cx[1]); + * aes_rval aes_enc_blk(const unsigned char in_blk[], unsigned char out_blk[], const aes_ctx cx[1]); + * + * aes_rval aes_dec_len(unsigned int blen, aes_ctx cx[1]); + * aes_rval aes_dec_key(const unsigned char in_key[], unsigned int klen, aes_ctx cx[1]); + * aes_rval aes_dec_blk(const unsigned char in_blk[], unsigned char out_blk[], const aes_ctx cx[1]); + * + * IMPORTANT NOTE: If you are using this C interface and your compiler does + * not set the memory used for objects to zero before use, you will need to + * ensure that cx.s_flg is set to zero before using these subroutine calls. + * + * C++ aes class subroutines: + * + * class AESclass for encryption + * class AESclass for decryption + * + * aes_rval len(unsigned int blen = 16); + * aes_rval key(const unsigned char in_key[], unsigned int klen); + * aes_rval blk(const unsigned char in_blk[], unsigned char out_blk[]); + * + * aes_rval len(unsigned int blen = 16); + * aes_rval key(const unsigned char in_key[], unsigned int klen); + * aes_rval blk(const unsigned char in_blk[], unsigned char out_blk[]); + * + * The block length inputs to set_block and set_key are in numbers of + * BYTES, not bits. The calls to subroutines must be made in the above + * order but multiple calls can be made without repeating earlier calls + * if their parameters have not changed. If the cipher block length is + * variable but set_blk has not been called before cipher operations a + * value of 16 is assumed (that is, the AES block size). In contrast to + * earlier versions the block and key length parameters are now checked + * for correctness and the encryption and decryption routines check to + * ensure that an appropriate key has been set before they are called. + * + * COMPILATION + * + * The files used to provide AES (Rijndael) are + * + * a. aes.h for the definitions needed for use in C. + * b. aescpp.h for the definitions needed for use in C++. + * c. aesopt.h for setting compilation options (also includes common + * code). + * d. aescrypt.c for encryption and decrytpion, or + * e. aescrypt.asm for encryption and decryption using assembler code. + * f. aeskey.c for key scheduling. + * g. aestab.c for table loading or generation. + * + * The assembler code uses the NASM assembler. The above files provice + * block and key lengths of 16, 24 and 32 bytes (128, 192 and 256 bits). + * If aescrypp.c and aeskeypp.c are used instead of aescrypt.c and + * aeskey.c respectively, the block and key lengths can then be 16, 20, + * 24, 28 or 32 bytes. However this code has not been optimised to the + * same extent and is hence slower (esepcially for the AES block size + * of 16 bytes). + * + * To compile AES (Rijndael) for use in C code use aes.h and exclude + * the AES_DLL define in aes.h + * + * To compile AES (Rijndael) for use in in C++ code use aescpp.h and + * exclude the AES_DLL define in aes.h + * + * To compile AES (Rijndael) in C as a Dynamic Link Library DLL) use + * aes.h, include the AES_DLL define and compile the DLL. If using + * the test files to test the DLL, exclude aes.c from the test build + * project and compile it with the same defines as used for the DLL + * (ensure that the DLL path is correct) + * + * CONFIGURATION OPTIONS (here and in aes.h) + * + * a. define BLOCK_SIZE in aes.h to set the cipher block size (16, 24 + * or 32 for the standard code, or 16, 20, 24, 28 or 32 for the + * extended code) or leave this undefined for dynamically variable + * block size (this will result in much slower code). + * b. set AES_DLL in aes.h if AES (Rijndael) is to be compiled as a DLL + * c. You may need to set PLATFORM_BYTE_ORDER to define the byte order. + * d. If you want the code to run in a specific internal byte order, then + * INTERNAL_BYTE_ORDER must be set accordingly. + * e. set other configuration options decribed below. + */ + +#ifndef _AESOPT_H +#define _AESOPT_H + +/* START OF CONFIGURATION OPTIONS + * + * USE OF DEFINES + * + * Later in this section there are a number of defines that control the + * operation of the code. In each section, the purpose of each define is + * explained so that the relevant form can be included or excluded by + * setting either 1's or 0's respectively on the branches of the related + * #if clauses. + */ + +/* 1. PLATFORM SPECIFIC INCLUDES */ + +#if defined(__CRYPTLIB__) && !defined(INC_ALL) && !defined(INC_CHILD) +#include "crypt/aes.h" +#else + #include "aes.h" +#endif + +#if (defined(__GNUC__) || defined(__GNU_LIBRARY__)) && !defined(__CYGWIN__) +# if defined(__APPLE__) +# include <machine/endian.h> +# else +# include <endian.h> +# endif +//# include <machine/byteswap.h> +#elif defined(__CRYPTLIB__) +# if defined(INC_ALL) +# include "crypt.h" +# elif defined(INC_CHILD) +# include "../crypt.h" +# else +# include "crypt.h" +# endif +# if defined(DATA_LITTLEENDIAN) +# define PLATFORM_BYTE_ORDER AES_LITTLE_ENDIAN +# else +# define PLATFORM_BYTE_ORDER AES_BIG_ENDIAN +# endif +#elif defined(_MSC_VER) +# include <stdlib.h> +#elif !defined(WIN32) +# include <stdlib.h> +# if !defined (_ENDIAN_H) +# include <sys/param.h> +# else +# include _ENDIAN_H +# endif +#endif + +/* 2. BYTE ORDER IN 32-BIT WORDS + * + * To obtain the highest speed on processors with 32-bit words, this code + * needs to determine the order in which bytes are packed into such words. + * The following block of code is an attempt to capture the most obvious + * ways in which various environemnts define byte order. It may well fail, + * in which case the definitions will need to be set by editing at the + * points marked **** EDIT HERE IF NECESSARY **** below. + */ +#define AES_LITTLE_ENDIAN 1234 /* byte 0 is least significant (i386) */ +#define AES_BIG_ENDIAN 4321 /* byte 0 is most significant (mc68k) */ + +#if !defined(PLATFORM_BYTE_ORDER) +#if defined(LITTLE_ENDIAN) || defined(BIG_ENDIAN) +# if defined(LITTLE_ENDIAN) && defined(BIG_ENDIAN) +# if defined(BYTE_ORDER) +# if (BYTE_ORDER == LITTLE_ENDIAN) +# define PLATFORM_BYTE_ORDER AES_LITTLE_ENDIAN +# elif (BYTE_ORDER == BIG_ENDIAN) +# define PLATFORM_BYTE_ORDER AES_BIG_ENDIAN +# endif +# endif +# elif defined(LITTLE_ENDIAN) && !defined(BIG_ENDIAN) +# define PLATFORM_BYTE_ORDER AES_LITTLE_ENDIAN +# elif !defined(LITTLE_ENDIAN) && defined(BIG_ENDIAN) +# define PLATFORM_BYTE_ORDER AES_BIG_ENDIAN +# endif +#elif defined(_LITTLE_ENDIAN) || defined(_BIG_ENDIAN) +# if defined(_LITTLE_ENDIAN) && defined(_BIG_ENDIAN) +# if defined(_BYTE_ORDER) +# if (_BYTE_ORDER == _LITTLE_ENDIAN) +# define PLATFORM_BYTE_ORDER AES_LITTLE_ENDIAN +# elif (_BYTE_ORDER == _BIG_ENDIAN) +# define PLATFORM_BYTE_ORDER AES_BIG_ENDIAN +# endif +# endif +# elif defined(_LITTLE_ENDIAN) && !defined(_BIG_ENDIAN) +# define PLATFORM_BYTE_ORDER AES_LITTLE_ENDIAN +# elif !defined(_LITTLE_ENDIAN) && defined(_BIG_ENDIAN) +# define PLATFORM_BYTE_ORDER AES_BIG_ENDIAN +# endif +#elif defined(__BYTE_ORDER) +# if (__BYTE_ORDER == __LITTLE_ENDIAN) +# define PLATFORM_BYTE_ORDER AES_LITTLE_ENDIAN +# elif (__BYTE_ORDER == __BIG_ENDIAN) +# define PLATFORM_BYTE_ORDER AES_BIG_ENDIAN +# endif +#elif 0 /* **** EDIT HERE IF NECESSARY **** */ +#define PLATFORM_BYTE_ORDER AES_LITTLE_ENDIAN +#elif 1 /* **** EDIT HERE IF NECESSARY **** */ +XX_FIXME +/*#define PLATFORM_BYTE_ORDER AES_BIG_ENDIAN + * #elif (('1234' >> 24) == '1') + # define PLATFORM_BYTE_ORDER AES_LITTLE_ENDIAN + ##elif (('4321' >> 24) == '1') + # define PLATFORM_BYTE_ORDER AES_BIG_ENDIAN */ +#endif +#endif + +#if !defined(PLATFORM_BYTE_ORDER) +# error Please set undetermined byte order (lines 233 or 235 of aesopt.h). +#endif + +/* 3. ASSEMBLER SUPPORT + * + * If the assembler code is used for encryption and decryption this file only + * provides key scheduling so the following defines are used + */ +#ifdef AES_ASM +#define ENCRYPTION_KEY_SCHEDULE +#define DECRYPTION_KEY_SCHEDULE +#else + +/* 4. FUNCTIONS REQUIRED + * + * This implementation provides five main subroutines which provide for + * setting block length, setting encryption and decryption keys and for + * encryption and decryption. When the assembler code is not being used + * the following definition blocks allow the selection of the routines + * that are to be included in the compilation. + */ +#if 1 +#define ENCRYPTION_KEY_SCHEDULE +#endif + +#if 1 +#define DECRYPTION_KEY_SCHEDULE +#endif + +#if 1 +#define ENCRYPTION +#endif + +#if 1 +#define DECRYPTION +#endif + +#endif + +/* 5. BYTE ORDER WITHIN 32 BIT WORDS + * + * The fundamental data processing units in Rijndael are 8-bit bytes. The + * input, output and key input are all enumerated arrays of bytes in which + * bytes are numbered starting at zero and increasing to one less than the + * number of bytes in the array in question. This enumeration is only used + * for naming bytes and does not imply any adjacency or order relationship + * from one byte to another. When these inputs and outputs are considered + * as bit sequences, bits 8*n to 8*n+7 of the bit sequence are mapped to + * byte[n] with bit 8n+i in the sequence mapped to bit 7-i within the byte. + * In this implementation bits are numbered from 0 to 7 starting at the + * numerically least significant end of each byte (bit n represents 2^n). + * + * However, Rijndael can be implemented more efficiently using 32-bit + * words by packing bytes into words so that bytes 4*n to 4*n+3 are placed + * into word[n]. While in principle these bytes can be assembled into words + * in any positions, this implementation only supports the two formats in + * which bytes in adjacent positions within words also have adjacent byte + * numbers. This order is called big-endian if the lowest numbered bytes + * in words have the highest numeric significance and little-endian if the + * opposite applies. + * + * This code can work in either order irrespective of the order used by the + * machine on which it runs. Normally the internal byte order will be set + * to the order of the processor on which the code is to be run but this + * define can be used to reverse this in special situations + */ +#if 1 +#define INTERNAL_BYTE_ORDER PLATFORM_BYTE_ORDER +#elif defined(AES_LITTLE_ENDIAN) +#define INTERNAL_BYTE_ORDER AES_LITTLE_ENDIAN +#elif defined(AES_BIG_ENDIAN) +#define INTERNAL_BYTE_ORDER AES_BIG_ENDIAN +#endif + +/* 6. FAST INPUT/OUTPUT OPERATIONS. + * + * On some machines it is possible to improve speed by transferring the + * bytes in the input and output arrays to and from the internal 32-bit + * variables by addressing these arrays as if they are arrays of 32-bit + * words. On some machines this will always be possible but there may + * be a large performance penalty if the byte arrays are not aligned on + * the normal word boundaries. On other machines this technique will + * lead to memory access errors when such 32-bit word accesses are not + * properly aligned. The option SAFE_IO avoids such problems but will + * often be slower on those machines that support misaligned access + * (especially so if care is taken to align the input and output byte + * arrays on 32-bit word boundaries). If SAFE_IO is not defined it is + * assumed that access to byte arrays as if they are arrays of 32-bit + * words will not cause problems when such accesses are misaligned. + */ +#if 0 +#define SAFE_IO +#endif + +/* 7. LOOP UNROLLING + * + * The code for encryption and decrytpion cycles through a number of rounds + * that can be implemented either in a loop or by expanding the code into a + * long sequence of instructions, the latter producing a larger program but + * one that will often be much faster. The latter is called loop unrolling. + * There are also potential speed advantages in expanding two iterations in + * a loop with half the number of iterations, which is called partial loop + * unrolling. The following options allow partial or full loop unrolling + * to be set independently for encryption and decryption + */ +#if 1 +#define ENC_UNROLL FULL +#elif 0 +#define ENC_UNROLL PARTIAL +#else +#define ENC_UNROLL NONE +#endif + +#if 1 +#define DEC_UNROLL FULL +#elif 0 +#define DEC_UNROLL PARTIAL +#else +#define DEC_UNROLL NONE +#endif + +/* 8. FIXED OR DYNAMIC TABLES + * + * When this section is included the tables used by the code are comipled + * statically into the binary file. Otherwise they are computed once when + * the code is first used. + */ +#if 1 +#define FIXED_TABLES +#endif + +/* 9. FAST FINITE FIELD OPERATIONS + * + * If this section is included, tables are used to provide faster finite + * field arithmetic (this has no effect if FIXED_TABLES is defined). + */ +#if 1 +#define FF_TABLES +#endif + +/* 10. INTERNAL STATE VARIABLE FORMAT + * + * The internal state of Rijndael is stored in a number of local 32-bit + * word varaibles which can be defined either as an array or as individual + * names variables. Include this section if you want to store these local + * varaibles in arrays. Otherwise individual local variables will be used. + */ +#if 1 +#define ARRAYS +#endif + +/* In this implementation the columns of the state array are each held in + * 32-bit words. The state array can be held in various ways: in an array + * of words, in a number of individual word variables or in a number of + * processor registers. The following define maps a variable name x and + * a column number c to the way the state array variable is to be held. + * The first define below maps the state into an array x[c] whereas the + * second form maps the state into a number of individual variables x0, + * x1, etc. Another form could map individual state colums to machine + * register names. + */ + +#if defined(ARRAYS) +#define s(x, c) x[c] +#else +#define s(x, c) x ## c +#endif + +/* 11. VARIABLE BLOCK SIZE SPEED + * + * This section is only relevant if you wish to use the variable block + * length feature of the code. Include this section if you place more + * emphasis on speed rather than code size. + */ +#if 1 +#define FAST_VARIABLE +#endif + +/* 12. INTERNAL TABLE CONFIGURATION + * + * This cipher proceeds by repeating in a number of cycles known as 'rounds' + * which are implemented by a round function which can optionally be speeded + * up using tables. The basic tables are each 256 32-bit words, with either + * one or four tables being required for each round function depending on + * how much speed is required. The encryption and decryption round functions + * are different and the last encryption and decrytpion round functions are + * different again making four different round functions in all. + * + * This means that: + * 1. Normal encryption and decryption rounds can each use either 0, 1 + * or 4 tables and table spaces of 0, 1024 or 4096 bytes each. + * 2. The last encryption and decryption rounds can also use either 0, 1 + * or 4 tables and table spaces of 0, 1024 or 4096 bytes each. + * + * Include or exclude the appropriate definitions below to set the number + * of tables used by this implementation. + */ + +#if 1 /* set tables for the normal encryption round */ +#define ENC_ROUND FOUR_TABLES +#elif 0 +#define ENC_ROUND ONE_TABLE +#else +#define ENC_ROUND NO_TABLES +#endif + +#if 1 /* set tables for the last encryption round */ +#define LAST_ENC_ROUND FOUR_TABLES +#elif 0 +#define LAST_ENC_ROUND ONE_TABLE +#else +#define LAST_ENC_ROUND NO_TABLES +#endif + +#if 1 /* set tables for the normal decryption round */ +#define DEC_ROUND FOUR_TABLES +#elif 0 +#define DEC_ROUND ONE_TABLE +#else +#define DEC_ROUND NO_TABLES +#endif + +#if 1 /* set tables for the last decryption round */ +#define LAST_DEC_ROUND FOUR_TABLES +#elif 0 +#define LAST_DEC_ROUND ONE_TABLE +#else +#define LAST_DEC_ROUND NO_TABLES +#endif + +/* The decryption key schedule can be speeded up with tables in the same + * way that the round functions can. Include or exclude the following + * defines to set this requirement. + */ +#if 1 +#define KEY_SCHED FOUR_TABLES +#elif 0 +#define KEY_SCHED ONE_TABLE +#else +#define KEY_SCHED NO_TABLES +#endif + +/* END OF CONFIGURATION OPTIONS */ + +#define NO_TABLES 0 /* DO NOT CHANGE */ +#define ONE_TABLE 1 /* DO NOT CHANGE */ +#define FOUR_TABLES 4 /* DO NOT CHANGE */ +#define NONE 0 /* DO NOT CHANGE */ +#define PARTIAL 1 /* DO NOT CHANGE */ +#define FULL 2 /* DO NOT CHANGE */ + +#if defined(BLOCK_SIZE) && ((BLOCK_SIZE & 3) || BLOCK_SIZE < 16 || BLOCK_SIZE > 32) +#error An illegal block size has been specified. +#endif + +#if !defined(BLOCK_SIZE) +#define RC_LENGTH 29 +#else +#define RC_LENGTH 5 * BLOCK_SIZE / 4 - (BLOCK_SIZE == 16 ? 10 : 11) +#endif + +/* Disable at least some poor combinations of options */ + +#if ENC_ROUND == NO_TABLES && LAST_ENC_ROUND != NO_TABLES +#undef LAST_ENC_ROUND +#define LAST_ENC_ROUND NO_TABLES +#elif ENC_ROUND == ONE_TABLE && LAST_ENC_ROUND == FOUR_TABLES +#undef LAST_ENC_ROUND +#define LAST_ENC_ROUND ONE_TABLE +#endif + +#if ENC_ROUND == NO_TABLES && ENC_UNROLL != NONE +#undef ENC_UNROLL +#define ENC_UNROLL NONE +#endif + +#if DEC_ROUND == NO_TABLES && LAST_DEC_ROUND != NO_TABLES +#undef LAST_DEC_ROUND +#define LAST_DEC_ROUND NO_TABLES +#elif DEC_ROUND == ONE_TABLE && LAST_DEC_ROUND == FOUR_TABLES +#undef LAST_DEC_ROUND +#define LAST_DEC_ROUND ONE_TABLE +#endif + +#if DEC_ROUND == NO_TABLES && DEC_UNROLL != NONE +#undef DEC_UNROLL +#define DEC_UNROLL NONE +#endif + +/* upr(x,n): rotates bytes within words by n positions, moving bytes to + * higher index positions with wrap around into low positions + * ups(x,n): moves bytes by n positions to higher index positions in + * words but without wrap around + * bval(x,n): extracts a byte from a word + * + * NOTE: The definitions given here are intended only for use with + * unsigned variables and with shift counts that are compile + * time constants + */ + +#if (INTERNAL_BYTE_ORDER == AES_LITTLE_ENDIAN) +#if defined(_MSC_VER) +#define upr(x, n) _lrotl((aes_32t) (x), 8 * (n)) +#else +#define upr(x, n) ((aes_32t) (x) << 8 * (n) | (aes_32t) (x) >> 32 - 8 * (n)) +#endif +#define ups(x, n) ((aes_32t) (x) << 8 * (n)) +#define bval(x, n) ((aes_08t) ((x) >> 8 * (n))) +#define bytes2word(b0, b1, b2, b3) \ + (((aes_32t) (b3) << 24) | ((aes_32t) (b2) << 16) | ((aes_32t) (b1) << 8) | (b0)) +#endif + +#if (INTERNAL_BYTE_ORDER == AES_BIG_ENDIAN) +#define upr(x, n) ((aes_32t) (x) >> 8 * (n) | (aes_32t) (x) << 32 - 8 * (n)) +#define ups(x, n) ((aes_32t) (x) >> 8 * (n))) +#define bval(x, n) ((aes_08t) ((x) >> 24 - 8 * (n))) +#define bytes2word(b0, b1, b2, b3) \ + (((aes_32t) (b0) << 24) | ((aes_32t) (b1) << 16) | ((aes_32t) (b2) << 8) | (b3)) +#endif + +#if defined(SAFE_IO) + +#define word_in(x) bytes2word((x)[0], (x)[1], (x)[2], (x)[3]) +#define word_out(x, v) { (x)[0] ^= bval(v, 0); (x)[1] ^= bval(v, 1); \ + (x)[2] ^= bval(v, 2); (x)[3] ^= bval(v, 3); } + +#elif (INTERNAL_BYTE_ORDER == PLATFORM_BYTE_ORDER) + +#define word_in(x) *(aes_32t *) (x) +#define word_out(x, v) *(aes_32t *) (x) ^= (v) + +#else + +#if !defined(bswap_32) +#if !defined(_MSC_VER) +#define _lrotl(x, n) ((aes_32t) (x) << n | (aes_32t) (x) >> 32 - n) +#endif +#define bswap_32(x) ((_lrotl((x), 8) & 0x00ff00ff) | (_lrotl((x), 24) & 0xff00ff00)) +#endif + +#warn using slow bswap +#define word_in(x) bswap_32(*(aes_32t *) (x)) +#define word_out(x, v) *(aes_32t *) (x) ^= bswap_32(v) + +#endif + +/* the finite field modular polynomial and elements */ + +#define WPOLY 0x011b +#define BPOLY 0x1b + +/* multiply four bytes in GF(2^8) by 'x' {02} in parallel */ + +#define m1 0x80808080 +#define m2 0x7f7f7f7f +#define FFmulX(x) ((((x) & m2) << 1) ^ ((((x) & m1) >> 7) * BPOLY)) + +/* The following defines provide alternative definitions of FFmulX that might + * give improved performance if a fast 32-bit multiply is not available. Note + * that a temporary variable u needs to be defined where FFmulX is used. + * + * #define FFmulX(x) (u = (x) & m1, u |= (u >> 1), ((x) & m2) << 1) ^ ((u >> 3) | (u >> 6)) + * #define m4 (0x01010101 * BPOLY) + * #define FFmulX(x) (u = (x) & m1, ((x) & m2) << 1) ^ ((u - (u >> 7)) & m4) + */ + +/* Work out which tables are needed for the different options */ + +#ifdef AES_ASM +#ifdef ENC_ROUND +#undef ENC_ROUND +#endif +#define ENC_ROUND FOUR_TABLES +#ifdef LAST_ENC_ROUND +#undef LAST_ENC_ROUND +#endif +#define LAST_ENC_ROUND FOUR_TABLES +#ifdef DEC_ROUND +#undef DEC_ROUND +#endif +#define DEC_ROUND FOUR_TABLES +#ifdef LAST_DEC_ROUND +#undef LAST_DEC_ROUND +#endif +#define LAST_DEC_ROUND FOUR_TABLES +#ifdef KEY_SCHED +#undef KEY_SCHED +#define KEY_SCHED FOUR_TABLES +#endif +#endif + +#if defined(ENCRYPTION) || defined(AES_ASM) +#if ENC_ROUND == ONE_TABLE +#define FT1_SET +#elif ENC_ROUND == FOUR_TABLES +#define FT4_SET +#else +#define SBX_SET +#endif +#if LAST_ENC_ROUND == ONE_TABLE +#define FL1_SET +#elif LAST_ENC_ROUND == FOUR_TABLES +#define FL4_SET +#elif !defined(SBX_SET) +#define SBX_SET +#endif +#endif + +#if defined(DECRYPTION) || defined(AES_ASM) +#if DEC_ROUND == ONE_TABLE +#define IT1_SET +#elif DEC_ROUND == FOUR_TABLES +#define IT4_SET +#else +#define ISB_SET +#endif +#if LAST_DEC_ROUND == ONE_TABLE +#define IL1_SET +#elif LAST_DEC_ROUND == FOUR_TABLES +#define IL4_SET +#elif !defined(ISB_SET) +#define ISB_SET +#endif +#endif + +#if defined(ENCRYPTION_KEY_SCHEDULE) || defined(DECRYPTION_KEY_SCHEDULE) +#if KEY_SCHED == ONE_TABLE +#define LS1_SET +#define IM1_SET +#elif KEY_SCHED == FOUR_TABLES +#define LS4_SET +#define IM4_SET +#elif !defined(SBX_SET) +#define SBX_SET +#endif +#endif + +#ifdef FIXED_TABLES +#define prefx extern const +#else +#define prefx extern +extern aes_08t tab_init; +void gen_tabs(void); +#endif + +prefx aes_32t rcon_tab[29]; + +#ifdef SBX_SET +prefx aes_08t s_box[256]; +#endif + +#ifdef ISB_SET +prefx aes_08t inv_s_box[256]; +#endif + +#ifdef FT1_SET +prefx aes_32t ft_tab[256]; +#endif + +#ifdef FT4_SET +prefx aes_32t ft_tab[4][256]; +#endif + +#ifdef FL1_SET +prefx aes_32t fl_tab[256]; +#endif + +#ifdef FL4_SET +prefx aes_32t fl_tab[4][256]; +#endif + +#ifdef IT1_SET +prefx aes_32t it_tab[256]; +#endif + +#ifdef IT4_SET +prefx aes_32t it_tab[4][256]; +#endif + +#ifdef IL1_SET +prefx aes_32t il_tab[256]; +#endif + +#ifdef IL4_SET +prefx aes_32t il_tab[4][256]; +#endif + +#ifdef LS1_SET +#ifdef FL1_SET +#undef LS1_SET +#else +prefx aes_32t ls_tab[256]; +#endif +#endif + +#ifdef LS4_SET +#ifdef FL4_SET +#undef LS4_SET +#else +prefx aes_32t ls_tab[4][256]; +#endif +#endif + +#ifdef IM1_SET +prefx aes_32t im_tab[256]; +#endif + +#ifdef IM4_SET +prefx aes_32t im_tab[4][256]; +#endif + +/* Set the number of columns in nc. Note that it is important + * that nc is a constant which is known at compile time if the + * highest speed version of the code is needed. + */ + +#if defined(BLOCK_SIZE) +#define nc (BLOCK_SIZE >> 2) +#else +#define nc (cx->n_blk >> 2) +#endif + +/* generic definitions of Rijndael macros that use tables */ + +#define no_table(x, box, vf, rf, c) bytes2word( \ + box[bval(vf(x, 0, c), rf(0, c))], \ + box[bval(vf(x, 1, c), rf(1, c))], \ + box[bval(vf(x, 2, c), rf(2, c))], \ + box[bval(vf(x, 3, c), rf(3, c))]) + +#define one_table(x, op, tab, vf, rf, c) \ + (tab[bval(vf(x, 0, c), rf(0, c))] \ + ^ op(tab[bval(vf(x, 1, c), rf(1, c))], 1) \ + ^ op(tab[bval(vf(x, 2, c), rf(2, c))], 2) \ + ^ op(tab[bval(vf(x, 3, c), rf(3, c))], 3)) + +#define four_tables(x, tab, vf, rf, c) \ + (tab[0][bval(vf(x, 0, c), rf(0, c))] \ + ^ tab[1][bval(vf(x, 1, c), rf(1, c))] \ + ^ tab[2][bval(vf(x, 2, c), rf(2, c))] \ + ^ tab[3][bval(vf(x, 3, c), rf(3, c))]) + +#define vf1(x, r, c) (x) +#define rf1(r, c) (r) +#define rf2(r, c) ((r - c) & 3) + +/* perform forward and inverse column mix operation on four bytes in long word x in */ +/* parallel. NOTE: x must be a simple variable, NOT an expression in these macros. */ + +#define dec_fmvars +#if defined(FM4_SET) /* not currently used */ +#define fwd_mcol(x) four_tables(x, fm_tab, vf1, rf1, 0) +#elif defined(FM1_SET) /* not currently used */ +#define fwd_mcol(x) one_table(x, upr, fm_tab, vf1, rf1, 0) +#else +#undef dec_fmvars +#define dec_fmvars aes_32t f1, f2; +#define fwd_mcol(x) (f1 = (x), f2 = FFmulX(f1), f2 ^ upr(f1 ^ f2, 3) ^ upr(f1, 2) ^ upr(f1, 1)) +#endif + +#define dec_imvars +#if defined(IM4_SET) +#define inv_mcol(x) four_tables(x, im_tab, vf1, rf1, 0) +#elif defined(IM1_SET) +#define inv_mcol(x) one_table(x, upr, im_tab, vf1, rf1, 0) +#else +#undef dec_imvars +#define dec_imvars aes_32t f2, f4, f8, f9; +#define inv_mcol(x) \ + (f9 = (x), f2 = FFmulX(f9), f4 = FFmulX(f2), f8 = FFmulX(f4), f9 ^= f8, \ + f2 ^= f4 ^ f8 ^ upr(f2 ^ f9, 3) ^ upr(f4 ^ f9, 2) ^ upr(f9, 1)) +#endif + +#if defined(FL4_SET) +#define ls_box(x, c) four_tables(x, fl_tab, vf1, rf2, c) +#elif defined(LS4_SET) +#define ls_box(x, c) four_tables(x, ls_tab, vf1, rf2, c) +#elif defined(FL1_SET) +#define ls_box(x, c) one_table(x, upr, fl_tab, vf1, rf2, c) +#elif defined(LS1_SET) +#define ls_box(x, c) one_table(x, upr, ls_tab, vf1, rf2, c) +#else +#define ls_box(x, c) no_table(x, s_box, vf1, rf2, c) +#endif + +#endif === modified file 'i3/aeshash/aestab.c' --- i3/aeshash/aestab.c 2009-12-11 22:49:11 +0000 +++ i3/aeshash/aestab.c 2010-02-11 11:49:47 +0000 @@ -1,494 +1,504 @@ -/* - ------------------------------------------------------------------------- - Copyright (c) 2001, Dr Brian Gladman <brg@xxxxxxxxxxxxx>, Worcester, UK. - All rights reserved. - - LICENSE TERMS - - The free distribution and use of this software in both source and binary - form is allowed (with or without changes) provided that: - - 1. distributions of this source code include the above copyright - notice, this list of conditions and the following disclaimer; - - 2. distributions in binary form include the above copyright - notice, this list of conditions and the following disclaimer - in the documentation and/or other associated materials; - - 3. the copyright holder's name is not used to endorse products - built using this software without specific written permission. - - DISCLAIMER - - This software is provided 'as is' with no explicit or implied warranties - in respect of its properties, including, but not limited to, correctness - and fitness for purpose. - ------------------------------------------------------------------------- - Issue Date: 29/07/2002 -*/ - -#include "aesopt.h" - -#if defined(FIXED_TABLES) || !defined(FF_TABLES) - -/* finite field arithmetic operations */ - -#define f2(x) ((x<<1) ^ (((x>>7) & 1) * WPOLY)) -#define f4(x) ((x<<2) ^ (((x>>6) & 1) * WPOLY) ^ (((x>>6) & 2) * WPOLY)) -#define f8(x) ((x<<3) ^ (((x>>5) & 1) * WPOLY) ^ (((x>>5) & 2) * WPOLY) \ - ^ (((x>>5) & 4) * WPOLY)) -#define f3(x) (f2(x) ^ x) -#define f9(x) (f8(x) ^ x) -#define fb(x) (f8(x) ^ f2(x) ^ x) -#define fd(x) (f8(x) ^ f4(x) ^ x) -#define fe(x) (f8(x) ^ f4(x) ^ f2(x)) - -#endif - -#if defined(FIXED_TABLES) - -#define sb_data(w) \ - w(0x63), w(0x7c), w(0x77), w(0x7b), w(0xf2), w(0x6b), w(0x6f), w(0xc5),\ - w(0x30), w(0x01), w(0x67), w(0x2b), w(0xfe), w(0xd7), w(0xab), w(0x76),\ - w(0xca), w(0x82), w(0xc9), w(0x7d), w(0xfa), w(0x59), w(0x47), w(0xf0),\ - w(0xad), w(0xd4), w(0xa2), w(0xaf), w(0x9c), w(0xa4), w(0x72), w(0xc0),\ - w(0xb7), w(0xfd), w(0x93), w(0x26), w(0x36), w(0x3f), w(0xf7), w(0xcc),\ - w(0x34), w(0xa5), w(0xe5), w(0xf1), w(0x71), w(0xd8), w(0x31), w(0x15),\ - w(0x04), w(0xc7), w(0x23), w(0xc3), w(0x18), w(0x96), w(0x05), w(0x9a),\ - w(0x07), w(0x12), w(0x80), w(0xe2), w(0xeb), w(0x27), w(0xb2), w(0x75),\ - w(0x09), w(0x83), w(0x2c), w(0x1a), w(0x1b), w(0x6e), w(0x5a), w(0xa0),\ - w(0x52), w(0x3b), w(0xd6), w(0xb3), w(0x29), w(0xe3), w(0x2f), w(0x84),\ - w(0x53), w(0xd1), w(0x00), w(0xed), w(0x20), w(0xfc), w(0xb1), w(0x5b),\ - w(0x6a), w(0xcb), w(0xbe), w(0x39), w(0x4a), w(0x4c), w(0x58), w(0xcf),\ - w(0xd0), w(0xef), w(0xaa), w(0xfb), w(0x43), w(0x4d), w(0x33), w(0x85),\ - w(0x45), w(0xf9), w(0x02), w(0x7f), w(0x50), w(0x3c), w(0x9f), w(0xa8),\ - w(0x51), w(0xa3), w(0x40), w(0x8f), w(0x92), w(0x9d), w(0x38), w(0xf5),\ - w(0xbc), w(0xb6), w(0xda), w(0x21), w(0x10), w(0xff), w(0xf3), w(0xd2),\ - w(0xcd), w(0x0c), w(0x13), w(0xec), w(0x5f), w(0x97), w(0x44), w(0x17),\ - w(0xc4), w(0xa7), w(0x7e), w(0x3d), w(0x64), w(0x5d), w(0x19), w(0x73),\ - w(0x60), w(0x81), w(0x4f), w(0xdc), w(0x22), w(0x2a), w(0x90), w(0x88),\ - w(0x46), w(0xee), w(0xb8), w(0x14), w(0xde), w(0x5e), w(0x0b), w(0xdb),\ - w(0xe0), w(0x32), w(0x3a), w(0x0a), w(0x49), w(0x06), w(0x24), w(0x5c),\ - w(0xc2), w(0xd3), w(0xac), w(0x62), w(0x91), w(0x95), w(0xe4), w(0x79),\ - w(0xe7), w(0xc8), w(0x37), w(0x6d), w(0x8d), w(0xd5), w(0x4e), w(0xa9),\ - w(0x6c), w(0x56), w(0xf4), w(0xea), w(0x65), w(0x7a), w(0xae), w(0x08),\ - w(0xba), w(0x78), w(0x25), w(0x2e), w(0x1c), w(0xa6), w(0xb4), w(0xc6),\ - w(0xe8), w(0xdd), w(0x74), w(0x1f), w(0x4b), w(0xbd), w(0x8b), w(0x8a),\ - w(0x70), w(0x3e), w(0xb5), w(0x66), w(0x48), w(0x03), w(0xf6), w(0x0e),\ - w(0x61), w(0x35), w(0x57), w(0xb9), w(0x86), w(0xc1), w(0x1d), w(0x9e),\ - w(0xe1), w(0xf8), w(0x98), w(0x11), w(0x69), w(0xd9), w(0x8e), w(0x94),\ - w(0x9b), w(0x1e), w(0x87), w(0xe9), w(0xce), w(0x55), w(0x28), w(0xdf),\ - w(0x8c), w(0xa1), w(0x89), w(0x0d), w(0xbf), w(0xe6), w(0x42), w(0x68),\ - w(0x41), w(0x99), w(0x2d), w(0x0f), w(0xb0), w(0x54), w(0xbb), w(0x16) - -#define isb_data(w) \ - w(0x52), w(0x09), w(0x6a), w(0xd5), w(0x30), w(0x36), w(0xa5), w(0x38),\ - w(0xbf), w(0x40), w(0xa3), w(0x9e), w(0x81), w(0xf3), w(0xd7), w(0xfb),\ - w(0x7c), w(0xe3), w(0x39), w(0x82), w(0x9b), w(0x2f), w(0xff), w(0x87),\ - w(0x34), w(0x8e), w(0x43), w(0x44), w(0xc4), w(0xde), w(0xe9), w(0xcb),\ - w(0x54), w(0x7b), w(0x94), w(0x32), w(0xa6), w(0xc2), w(0x23), w(0x3d),\ - w(0xee), w(0x4c), w(0x95), w(0x0b), w(0x42), w(0xfa), w(0xc3), w(0x4e),\ - w(0x08), w(0x2e), w(0xa1), w(0x66), w(0x28), w(0xd9), w(0x24), w(0xb2),\ - w(0x76), w(0x5b), w(0xa2), w(0x49), w(0x6d), w(0x8b), w(0xd1), w(0x25),\ - w(0x72), w(0xf8), w(0xf6), w(0x64), w(0x86), w(0x68), w(0x98), w(0x16),\ - w(0xd4), w(0xa4), w(0x5c), w(0xcc), w(0x5d), w(0x65), w(0xb6), w(0x92),\ - w(0x6c), w(0x70), w(0x48), w(0x50), w(0xfd), w(0xed), w(0xb9), w(0xda),\ - w(0x5e), w(0x15), w(0x46), w(0x57), w(0xa7), w(0x8d), w(0x9d), w(0x84),\ - w(0x90), w(0xd8), w(0xab), w(0x00), w(0x8c), w(0xbc), w(0xd3), w(0x0a),\ - w(0xf7), w(0xe4), w(0x58), w(0x05), w(0xb8), w(0xb3), w(0x45), w(0x06),\ - w(0xd0), w(0x2c), w(0x1e), w(0x8f), w(0xca), w(0x3f), w(0x0f), w(0x02),\ - w(0xc1), w(0xaf), w(0xbd), w(0x03), w(0x01), w(0x13), w(0x8a), w(0x6b),\ - w(0x3a), w(0x91), w(0x11), w(0x41), w(0x4f), w(0x67), w(0xdc), w(0xea),\ - w(0x97), w(0xf2), w(0xcf), w(0xce), w(0xf0), w(0xb4), w(0xe6), w(0x73),\ - w(0x96), w(0xac), w(0x74), w(0x22), w(0xe7), w(0xad), w(0x35), w(0x85),\ - w(0xe2), w(0xf9), w(0x37), w(0xe8), w(0x1c), w(0x75), w(0xdf), w(0x6e),\ - w(0x47), w(0xf1), w(0x1a), w(0x71), w(0x1d), w(0x29), w(0xc5), w(0x89),\ - w(0x6f), w(0xb7), w(0x62), w(0x0e), w(0xaa), w(0x18), w(0xbe), w(0x1b),\ - w(0xfc), w(0x56), w(0x3e), w(0x4b), w(0xc6), w(0xd2), w(0x79), w(0x20),\ - w(0x9a), w(0xdb), w(0xc0), w(0xfe), w(0x78), w(0xcd), w(0x5a), w(0xf4),\ - w(0x1f), w(0xdd), w(0xa8), w(0x33), w(0x88), w(0x07), w(0xc7), w(0x31),\ - w(0xb1), w(0x12), w(0x10), w(0x59), w(0x27), w(0x80), w(0xec), w(0x5f),\ - w(0x60), w(0x51), w(0x7f), w(0xa9), w(0x19), w(0xb5), w(0x4a), w(0x0d),\ - w(0x2d), w(0xe5), w(0x7a), w(0x9f), w(0x93), w(0xc9), w(0x9c), w(0xef),\ - w(0xa0), w(0xe0), w(0x3b), w(0x4d), w(0xae), w(0x2a), w(0xf5), w(0xb0),\ - w(0xc8), w(0xeb), w(0xbb), w(0x3c), w(0x83), w(0x53), w(0x99), w(0x61),\ - w(0x17), w(0x2b), w(0x04), w(0x7e), w(0xba), w(0x77), w(0xd6), w(0x26),\ - w(0xe1), w(0x69), w(0x14), w(0x63), w(0x55), w(0x21), w(0x0c), w(0x7d), - -#define mm_data(w) \ - w(0x00), w(0x01), w(0x02), w(0x03), w(0x04), w(0x05), w(0x06), w(0x07),\ - w(0x08), w(0x09), w(0x0a), w(0x0b), w(0x0c), w(0x0d), w(0x0e), w(0x0f),\ - w(0x10), w(0x11), w(0x12), w(0x13), w(0x14), w(0x15), w(0x16), w(0x17),\ - w(0x18), w(0x19), w(0x1a), w(0x1b), w(0x1c), w(0x1d), w(0x1e), w(0x1f),\ - w(0x20), w(0x21), w(0x22), w(0x23), w(0x24), w(0x25), w(0x26), w(0x27),\ - w(0x28), w(0x29), w(0x2a), w(0x2b), w(0x2c), w(0x2d), w(0x2e), w(0x2f),\ - w(0x30), w(0x31), w(0x32), w(0x33), w(0x34), w(0x35), w(0x36), w(0x37),\ - w(0x38), w(0x39), w(0x3a), w(0x3b), w(0x3c), w(0x3d), w(0x3e), w(0x3f),\ - w(0x40), w(0x41), w(0x42), w(0x43), w(0x44), w(0x45), w(0x46), w(0x47),\ - w(0x48), w(0x49), w(0x4a), w(0x4b), w(0x4c), w(0x4d), w(0x4e), w(0x4f),\ - w(0x50), w(0x51), w(0x52), w(0x53), w(0x54), w(0x55), w(0x56), w(0x57),\ - w(0x58), w(0x59), w(0x5a), w(0x5b), w(0x5c), w(0x5d), w(0x5e), w(0x5f),\ - w(0x60), w(0x61), w(0x62), w(0x63), w(0x64), w(0x65), w(0x66), w(0x67),\ - w(0x68), w(0x69), w(0x6a), w(0x6b), w(0x6c), w(0x6d), w(0x6e), w(0x6f),\ - w(0x70), w(0x71), w(0x72), w(0x73), w(0x74), w(0x75), w(0x76), w(0x77),\ - w(0x78), w(0x79), w(0x7a), w(0x7b), w(0x7c), w(0x7d), w(0x7e), w(0x7f),\ - w(0x80), w(0x81), w(0x82), w(0x83), w(0x84), w(0x85), w(0x86), w(0x87),\ - w(0x88), w(0x89), w(0x8a), w(0x8b), w(0x8c), w(0x8d), w(0x8e), w(0x8f),\ - w(0x90), w(0x91), w(0x92), w(0x93), w(0x94), w(0x95), w(0x96), w(0x97),\ - w(0x98), w(0x99), w(0x9a), w(0x9b), w(0x9c), w(0x9d), w(0x9e), w(0x9f),\ - w(0xa0), w(0xa1), w(0xa2), w(0xa3), w(0xa4), w(0xa5), w(0xa6), w(0xa7),\ - w(0xa8), w(0xa9), w(0xaa), w(0xab), w(0xac), w(0xad), w(0xae), w(0xaf),\ - w(0xb0), w(0xb1), w(0xb2), w(0xb3), w(0xb4), w(0xb5), w(0xb6), w(0xb7),\ - w(0xb8), w(0xb9), w(0xba), w(0xbb), w(0xbc), w(0xbd), w(0xbe), w(0xbf),\ - w(0xc0), w(0xc1), w(0xc2), w(0xc3), w(0xc4), w(0xc5), w(0xc6), w(0xc7),\ - w(0xc8), w(0xc9), w(0xca), w(0xcb), w(0xcc), w(0xcd), w(0xce), w(0xcf),\ - w(0xd0), w(0xd1), w(0xd2), w(0xd3), w(0xd4), w(0xd5), w(0xd6), w(0xd7),\ - w(0xd8), w(0xd9), w(0xda), w(0xdb), w(0xdc), w(0xdd), w(0xde), w(0xdf),\ - w(0xe0), w(0xe1), w(0xe2), w(0xe3), w(0xe4), w(0xe5), w(0xe6), w(0xe7),\ - w(0xe8), w(0xe9), w(0xea), w(0xeb), w(0xec), w(0xed), w(0xee), w(0xef),\ - w(0xf0), w(0xf1), w(0xf2), w(0xf3), w(0xf4), w(0xf5), w(0xf6), w(0xf7),\ - w(0xf8), w(0xf9), w(0xfa), w(0xfb), w(0xfc), w(0xfd), w(0xfe), w(0xff) - -#define h0(x) (x) - -/* These defines are used to ensure tables are generated in the - right format depending on the internal byte order required -*/ - -#define w0(p) bytes2word(p, 0, 0, 0) -#define w1(p) bytes2word(0, p, 0, 0) -#define w2(p) bytes2word(0, 0, p, 0) -#define w3(p) bytes2word(0, 0, 0, p) - -/* Number of elements required in this table for different - block and key lengths is: - - Rcon Table key length (bytes) - Length 16 20 24 28 32 - --------------------- - block 16 | 10 9 8 7 7 - length 20 | 14 11 10 9 9 - (bytes) 24 | 19 15 12 11 11 - 28 | 24 19 16 13 13 - 32 | 29 23 19 17 14 - - this table can be a table of bytes if the key schedule - code is adjusted accordingly -*/ - -#define u0(p) bytes2word(f2(p), p, p, f3(p)) -#define u1(p) bytes2word(f3(p), f2(p), p, p) -#define u2(p) bytes2word(p, f3(p), f2(p), p) -#define u3(p) bytes2word(p, p, f3(p), f2(p)) - -#define v0(p) bytes2word(fe(p), f9(p), fd(p), fb(p)) -#define v1(p) bytes2word(fb(p), fe(p), f9(p), fd(p)) -#define v2(p) bytes2word(fd(p), fb(p), fe(p), f9(p)) -#define v3(p) bytes2word(f9(p), fd(p), fb(p), fe(p)) - -const aes_32t rcon_tab[29] = -{ - w0(0x01), w0(0x02), w0(0x04), w0(0x08), - w0(0x10), w0(0x20), w0(0x40), w0(0x80), - w0(0x1b), w0(0x36), w0(0x6c), w0(0xd8), - w0(0xab), w0(0x4d), w0(0x9a), w0(0x2f), - w0(0x5e), w0(0xbc), w0(0x63), w0(0xc6), - w0(0x97), w0(0x35), w0(0x6a), w0(0xd4), - w0(0xb3), w0(0x7d), w0(0xfa), w0(0xef), - w0(0xc5) -}; - -#ifdef SBX_SET -const aes_08t s_box[256] = { sb_data(h0) }; -#endif -#ifdef ISB_SET -const aes_08t inv_s_box[256] = { isb_data(h0) }; -#endif - -#ifdef FT1_SET -const aes_32t ft_tab[256] = { sb_data(u0) }; -#endif -#ifdef FT4_SET -const aes_32t ft_tab[4][256] = - { { sb_data(u0) }, { sb_data(u1) }, { sb_data(u2) }, { sb_data(u3) } }; -#endif - -#ifdef FL1_SET -const aes_32t fl_tab[256] = { sb_data(w0) }; -#endif -#ifdef FL4_SET -const aes_32t fl_tab[4][256] = - { { sb_data(w0) }, { sb_data(w1) }, { sb_data(w2) }, { sb_data(w3) } }; -#endif - -#ifdef IT1_SET -const aes_32t it_tab[256] = { isb_data(v0) }; -#endif -#ifdef IT4_SET -const aes_32t it_tab[4][256] = - { { isb_data(v0) }, { isb_data(v1) }, { isb_data(v2) }, { isb_data(v3) } }; -#endif - -#ifdef IL1_SET -const aes_32t il_tab[256] = { isb_data(w0) }; -#endif -#ifdef IL4_SET -const aes_32t il_tab[4][256] = - { { isb_data(w0) }, { isb_data(w1) }, { isb_data(w2) }, { isb_data(w3) } }; -#endif - -#ifdef LS1_SET -const aes_32t ls_tab[256] = { sb_data(w0) }; -#endif -#ifdef LS4_SET -const aes_32t ls_tab[4][256] = - { { sb_data(w0) }, { sb_data(w1) }, { sb_data(w2) }, { sb_data(w3) } }; -#endif - -#ifdef IM1_SET -const aes_32t im_tab[256] = { mm_data(v0) }; -#endif -#ifdef IM4_SET -const aes_32t im_tab[4][256] = - { { mm_data(v0) }, { mm_data(v1) }, { mm_data(v2) }, { mm_data(v3) } }; -#endif - -#else /* dynamic table generation */ - -aes_08t tab_init = 0; - -#define const - -aes_32t rcon_tab[RC_LENGTH]; - -#ifdef SBX_SET -aes_08t s_box[256]; -#endif -#ifdef ISB_SET -aes_08t inv_s_box[256]; -#endif - -#ifdef FT1_SET -aes_32t ft_tab[256]; -#endif -#ifdef FT4_SET -aes_32t ft_tab[4][256]; -#endif - -#ifdef FL1_SET -aes_32t fl_tab[256]; -#endif -#ifdef FL4_SET -aes_32t fl_tab[4][256]; -#endif - -#ifdef IT1_SET -aes_32t it_tab[256]; -#endif -#ifdef IT4_SET -aes_32t it_tab[4][256]; -#endif - -#ifdef IL1_SET -aes_32t il_tab[256]; -#endif -#ifdef IL4_SET -aes_32t il_tab[4][256]; -#endif - -#ifdef LS1_SET -aes_32t ls_tab[256]; -#endif -#ifdef LS4_SET -aes_32t ls_tab[4][256]; -#endif - -#ifdef IM1_SET -aes_32t im_tab[256]; -#endif -#ifdef IM4_SET -aes_32t im_tab[4][256]; -#endif - -#if !defined(FF_TABLES) - -/* Generate the tables for the dynamic table option - - It will generally be sensible to use tables to compute finite - field multiplies and inverses but where memory is scarse this - code might sometimes be better. But it only has effect during - initialisation so its pretty unimportant in overall terms. -*/ - -/* return 2 ^ (n - 1) where n is the bit number of the highest bit - set in x with x in the range 1 < x < 0x00000200. This form is - used so that locals within fi can be bytes rather than words -*/ - -static aes_08t hibit(const aes_32t x) -{ aes_08t r = (aes_08t)((x >> 1) | (x >> 2)); - - r |= (r >> 2); - r |= (r >> 4); - return (r + 1) >> 1; -} - -/* return the inverse of the finite field element x */ - -static aes_08t fi(const aes_08t x) -{ aes_08t p1 = x, p2 = BPOLY, n1 = hibit(x), n2 = 0x80, v1 = 1, v2 = 0; - - if(x < 2) return x; - - for(;;) - { - if(!n1) return v1; - - while(n2 >= n1) - { - n2 /= n1; p2 ^= p1 * n2; v2 ^= v1 * n2; n2 = hibit(p2); - } - - if(!n2) return v2; - - while(n1 >= n2) - { - n1 /= n2; p1 ^= p2 * n1; v1 ^= v2 * n1; n1 = hibit(p1); - } - } -} - -#else - -/* define the finite field multiplies required for Rijndael */ - -#define f2(x) ((x) ? pow[log[x] + 0x19] : 0) -#define f3(x) ((x) ? pow[log[x] + 0x01] : 0) -#define f9(x) ((x) ? pow[log[x] + 0xc7] : 0) -#define fb(x) ((x) ? pow[log[x] + 0x68] : 0) -#define fd(x) ((x) ? pow[log[x] + 0xee] : 0) -#define fe(x) ((x) ? pow[log[x] + 0xdf] : 0) -#define fi(x) ((x) ? pow[255 - log[x]]: 0) - -#endif - -/* The forward and inverse affine transformations used in the S-box */ - -#define fwd_affine(x) \ - (w = (aes_32t)x, w ^= (w<<1)^(w<<2)^(w<<3)^(w<<4), 0x63^(aes_08t)(w^(w>>8))) - -#define inv_affine(x) \ - (w = (aes_32t)x, w = (w<<1)^(w<<3)^(w<<6), 0x05^(aes_08t)(w^(w>>8))) - -void gen_tabs(void) -{ aes_32t i, w; - -#if defined(FF_TABLES) - - aes_08t pow[512], log[256]; - - /* log and power tables for GF(2^8) finite field with - WPOLY as modular polynomial - the simplest primitive - root is 0x03, used here to generate the tables - */ - - i = 0; w = 1; - do - { - pow[i] = (aes_08t)w; - pow[i + 255] = (aes_08t)w; - log[w] = (aes_08t)i++; - w ^= (w << 1) ^ (w & 0x80 ? WPOLY : 0); - } - while (w != 1); - -#endif - - for(i = 0, w = 1; i < RC_LENGTH; ++i) - { - rcon_tab[i] = bytes2word(w, 0, 0, 0); - w = f2(w); - } - - for(i = 0; i < 256; ++i) - { aes_08t b; - - b = fwd_affine(fi((aes_08t)i)); - w = bytes2word(f2(b), b, b, f3(b)); - -#ifdef SBX_SET - s_box[i] = b; -#endif - -#ifdef FT1_SET /* tables for a normal encryption round */ - ft_tab[i] = w; -#endif -#ifdef FT4_SET - ft_tab[0][i] = w; - ft_tab[1][i] = upr(w,1); - ft_tab[2][i] = upr(w,2); - ft_tab[3][i] = upr(w,3); -#endif - w = bytes2word(b, 0, 0, 0); - -#ifdef FL1_SET /* tables for last encryption round (may also */ - fl_tab[i] = w; /* be used in the key schedule) */ -#endif -#ifdef FL4_SET - fl_tab[0][i] = w; - fl_tab[1][i] = upr(w,1); - fl_tab[2][i] = upr(w,2); - fl_tab[3][i] = upr(w,3); -#endif - -#ifdef LS1_SET /* table for key schedule if fl_tab above is */ - ls_tab[i] = w; /* not of the required form */ -#endif -#ifdef LS4_SET - ls_tab[0][i] = w; - ls_tab[1][i] = upr(w,1); - ls_tab[2][i] = upr(w,2); - ls_tab[3][i] = upr(w,3); -#endif - - b = fi(inv_affine((aes_08t)i)); - w = bytes2word(fe(b), f9(b), fd(b), fb(b)); - -#ifdef IM1_SET /* tables for the inverse mix column operation */ - im_tab[b] = w; -#endif -#ifdef IM4_SET - im_tab[0][b] = w; - im_tab[1][b] = upr(w,1); - im_tab[2][b] = upr(w,2); - im_tab[3][b] = upr(w,3); -#endif - -#ifdef ISB_SET - inv_s_box[i] = b; -#endif -#ifdef IT1_SET /* tables for a normal decryption round */ - it_tab[i] = w; -#endif -#ifdef IT4_SET - it_tab[0][i] = w; - it_tab[1][i] = upr(w,1); - it_tab[2][i] = upr(w,2); - it_tab[3][i] = upr(w,3); -#endif - w = bytes2word(b, 0, 0, 0); -#ifdef IL1_SET /* tables for last decryption round */ - il_tab[i] = w; -#endif -#ifdef IL4_SET - il_tab[0][i] = w; - il_tab[1][i] = upr(w,1); - il_tab[2][i] = upr(w,2); - il_tab[3][i] = upr(w,3); -#endif - } - - tab_init = 1; -} - -#endif +/* + * ------------------------------------------------------------------------- + * Copyright (c) 2001, Dr Brian Gladman <brg@xxxxxxxxxxxxx>, Worcester, UK. + * All rights reserved. + * + * LICENSE TERMS + * + * The free distribution and use of this software in both source and binary + * form is allowed (with or without changes) provided that: + * + * 1. distributions of this source code include the above copyright + * notice, this list of conditions and the following disclaimer; + * + * 2. distributions in binary form include the above copyright + * notice, this list of conditions and the following disclaimer + * in the documentation and/or other associated materials; + * + * 3. the copyright holder's name is not used to endorse products + * built using this software without specific written permission. + * + * DISCLAIMER + * + * This software is provided 'as is' with no explicit or implied warranties + * in respect of its properties, including, but not limited to, correctness + * and fitness for purpose. + * ------------------------------------------------------------------------- + * Issue Date: 29/07/2002 + */ + +#include "aesopt.h" + +#if defined(FIXED_TABLES) || !defined(FF_TABLES) + +/* finite field arithmetic operations */ + +#define f2(x) ((x << 1) ^ (((x >> 7) & 1) * WPOLY)) +#define f4(x) ((x << 2) ^ (((x >> 6) & 1) * WPOLY) ^ (((x >> 6) & 2) * WPOLY)) +#define f8(x) ((x << 3) ^ (((x >> 5) & 1) * WPOLY) ^ (((x >> 5) & 2) * WPOLY) \ + ^ (((x >> 5) & 4) * WPOLY)) +#define f3(x) (f2(x) ^ x) +#define f9(x) (f8(x) ^ x) +#define fb(x) (f8(x) ^ f2(x) ^ x) +#define fd(x) (f8(x) ^ f4(x) ^ x) +#define fe(x) (f8(x) ^ f4(x) ^ f2(x)) + +#endif + +#if defined(FIXED_TABLES) + +#define sb_data(w) \ + w(0x63), w(0x7c), w(0x77), w(0x7b), w(0xf2), w(0x6b), w(0x6f), w(0xc5), \ + w(0x30), w(0x01), w(0x67), w(0x2b), w(0xfe), w(0xd7), w(0xab), w(0x76), \ + w(0xca), w(0x82), w(0xc9), w(0x7d), w(0xfa), w(0x59), w(0x47), w(0xf0), \ + w(0xad), w(0xd4), w(0xa2), w(0xaf), w(0x9c), w(0xa4), w(0x72), w(0xc0), \ + w(0xb7), w(0xfd), w(0x93), w(0x26), w(0x36), w(0x3f), w(0xf7), w(0xcc), \ + w(0x34), w(0xa5), w(0xe5), w(0xf1), w(0x71), w(0xd8), w(0x31), w(0x15), \ + w(0x04), w(0xc7), w(0x23), w(0xc3), w(0x18), w(0x96), w(0x05), w(0x9a), \ + w(0x07), w(0x12), w(0x80), w(0xe2), w(0xeb), w(0x27), w(0xb2), w(0x75), \ + w(0x09), w(0x83), w(0x2c), w(0x1a), w(0x1b), w(0x6e), w(0x5a), w(0xa0), \ + w(0x52), w(0x3b), w(0xd6), w(0xb3), w(0x29), w(0xe3), w(0x2f), w(0x84), \ + w(0x53), w(0xd1), w(0x00), w(0xed), w(0x20), w(0xfc), w(0xb1), w(0x5b), \ + w(0x6a), w(0xcb), w(0xbe), w(0x39), w(0x4a), w(0x4c), w(0x58), w(0xcf), \ + w(0xd0), w(0xef), w(0xaa), w(0xfb), w(0x43), w(0x4d), w(0x33), w(0x85), \ + w(0x45), w(0xf9), w(0x02), w(0x7f), w(0x50), w(0x3c), w(0x9f), w(0xa8), \ + w(0x51), w(0xa3), w(0x40), w(0x8f), w(0x92), w(0x9d), w(0x38), w(0xf5), \ + w(0xbc), w(0xb6), w(0xda), w(0x21), w(0x10), w(0xff), w(0xf3), w(0xd2), \ + w(0xcd), w(0x0c), w(0x13), w(0xec), w(0x5f), w(0x97), w(0x44), w(0x17), \ + w(0xc4), w(0xa7), w(0x7e), w(0x3d), w(0x64), w(0x5d), w(0x19), w(0x73), \ + w(0x60), w(0x81), w(0x4f), w(0xdc), w(0x22), w(0x2a), w(0x90), w(0x88), \ + w(0x46), w(0xee), w(0xb8), w(0x14), w(0xde), w(0x5e), w(0x0b), w(0xdb), \ + w(0xe0), w(0x32), w(0x3a), w(0x0a), w(0x49), w(0x06), w(0x24), w(0x5c), \ + w(0xc2), w(0xd3), w(0xac), w(0x62), w(0x91), w(0x95), w(0xe4), w(0x79), \ + w(0xe7), w(0xc8), w(0x37), w(0x6d), w(0x8d), w(0xd5), w(0x4e), w(0xa9), \ + w(0x6c), w(0x56), w(0xf4), w(0xea), w(0x65), w(0x7a), w(0xae), w(0x08), \ + w(0xba), w(0x78), w(0x25), w(0x2e), w(0x1c), w(0xa6), w(0xb4), w(0xc6), \ + w(0xe8), w(0xdd), w(0x74), w(0x1f), w(0x4b), w(0xbd), w(0x8b), w(0x8a), \ + w(0x70), w(0x3e), w(0xb5), w(0x66), w(0x48), w(0x03), w(0xf6), w(0x0e), \ + w(0x61), w(0x35), w(0x57), w(0xb9), w(0x86), w(0xc1), w(0x1d), w(0x9e), \ + w(0xe1), w(0xf8), w(0x98), w(0x11), w(0x69), w(0xd9), w(0x8e), w(0x94), \ + w(0x9b), w(0x1e), w(0x87), w(0xe9), w(0xce), w(0x55), w(0x28), w(0xdf), \ + w(0x8c), w(0xa1), w(0x89), w(0x0d), w(0xbf), w(0xe6), w(0x42), w(0x68), \ + w(0x41), w(0x99), w(0x2d), w(0x0f), w(0xb0), w(0x54), w(0xbb), w(0x16) + +#define isb_data(w) \ + w(0x52), w(0x09), w(0x6a), w(0xd5), w(0x30), w(0x36), w(0xa5), w(0x38), \ + w(0xbf), w(0x40), w(0xa3), w(0x9e), w(0x81), w(0xf3), w(0xd7), w(0xfb), \ + w(0x7c), w(0xe3), w(0x39), w(0x82), w(0x9b), w(0x2f), w(0xff), w(0x87), \ + w(0x34), w(0x8e), w(0x43), w(0x44), w(0xc4), w(0xde), w(0xe9), w(0xcb), \ + w(0x54), w(0x7b), w(0x94), w(0x32), w(0xa6), w(0xc2), w(0x23), w(0x3d), \ + w(0xee), w(0x4c), w(0x95), w(0x0b), w(0x42), w(0xfa), w(0xc3), w(0x4e), \ + w(0x08), w(0x2e), w(0xa1), w(0x66), w(0x28), w(0xd9), w(0x24), w(0xb2), \ + w(0x76), w(0x5b), w(0xa2), w(0x49), w(0x6d), w(0x8b), w(0xd1), w(0x25), \ + w(0x72), w(0xf8), w(0xf6), w(0x64), w(0x86), w(0x68), w(0x98), w(0x16), \ + w(0xd4), w(0xa4), w(0x5c), w(0xcc), w(0x5d), w(0x65), w(0xb6), w(0x92), \ + w(0x6c), w(0x70), w(0x48), w(0x50), w(0xfd), w(0xed), w(0xb9), w(0xda), \ + w(0x5e), w(0x15), w(0x46), w(0x57), w(0xa7), w(0x8d), w(0x9d), w(0x84), \ + w(0x90), w(0xd8), w(0xab), w(0x00), w(0x8c), w(0xbc), w(0xd3), w(0x0a), \ + w(0xf7), w(0xe4), w(0x58), w(0x05), w(0xb8), w(0xb3), w(0x45), w(0x06), \ + w(0xd0), w(0x2c), w(0x1e), w(0x8f), w(0xca), w(0x3f), w(0x0f), w(0x02), \ + w(0xc1), w(0xaf), w(0xbd), w(0x03), w(0x01), w(0x13), w(0x8a), w(0x6b), \ + w(0x3a), w(0x91), w(0x11), w(0x41), w(0x4f), w(0x67), w(0xdc), w(0xea), \ + w(0x97), w(0xf2), w(0xcf), w(0xce), w(0xf0), w(0xb4), w(0xe6), w(0x73), \ + w(0x96), w(0xac), w(0x74), w(0x22), w(0xe7), w(0xad), w(0x35), w(0x85), \ + w(0xe2), w(0xf9), w(0x37), w(0xe8), w(0x1c), w(0x75), w(0xdf), w(0x6e), \ + w(0x47), w(0xf1), w(0x1a), w(0x71), w(0x1d), w(0x29), w(0xc5), w(0x89), \ + w(0x6f), w(0xb7), w(0x62), w(0x0e), w(0xaa), w(0x18), w(0xbe), w(0x1b), \ + w(0xfc), w(0x56), w(0x3e), w(0x4b), w(0xc6), w(0xd2), w(0x79), w(0x20), \ + w(0x9a), w(0xdb), w(0xc0), w(0xfe), w(0x78), w(0xcd), w(0x5a), w(0xf4), \ + w(0x1f), w(0xdd), w(0xa8), w(0x33), w(0x88), w(0x07), w(0xc7), w(0x31), \ + w(0xb1), w(0x12), w(0x10), w(0x59), w(0x27), w(0x80), w(0xec), w(0x5f), \ + w(0x60), w(0x51), w(0x7f), w(0xa9), w(0x19), w(0xb5), w(0x4a), w(0x0d), \ + w(0x2d), w(0xe5), w(0x7a), w(0x9f), w(0x93), w(0xc9), w(0x9c), w(0xef), \ + w(0xa0), w(0xe0), w(0x3b), w(0x4d), w(0xae), w(0x2a), w(0xf5), w(0xb0), \ + w(0xc8), w(0xeb), w(0xbb), w(0x3c), w(0x83), w(0x53), w(0x99), w(0x61), \ + w(0x17), w(0x2b), w(0x04), w(0x7e), w(0xba), w(0x77), w(0xd6), w(0x26), \ + w(0xe1), w(0x69), w(0x14), w(0x63), w(0x55), w(0x21), w(0x0c), w(0x7d), + +#define mm_data(w) \ + w(0x00), w(0x01), w(0x02), w(0x03), w(0x04), w(0x05), w(0x06), w(0x07), \ + w(0x08), w(0x09), w(0x0a), w(0x0b), w(0x0c), w(0x0d), w(0x0e), w(0x0f), \ + w(0x10), w(0x11), w(0x12), w(0x13), w(0x14), w(0x15), w(0x16), w(0x17), \ + w(0x18), w(0x19), w(0x1a), w(0x1b), w(0x1c), w(0x1d), w(0x1e), w(0x1f), \ + w(0x20), w(0x21), w(0x22), w(0x23), w(0x24), w(0x25), w(0x26), w(0x27), \ + w(0x28), w(0x29), w(0x2a), w(0x2b), w(0x2c), w(0x2d), w(0x2e), w(0x2f), \ + w(0x30), w(0x31), w(0x32), w(0x33), w(0x34), w(0x35), w(0x36), w(0x37), \ + w(0x38), w(0x39), w(0x3a), w(0x3b), w(0x3c), w(0x3d), w(0x3e), w(0x3f), \ + w(0x40), w(0x41), w(0x42), w(0x43), w(0x44), w(0x45), w(0x46), w(0x47), \ + w(0x48), w(0x49), w(0x4a), w(0x4b), w(0x4c), w(0x4d), w(0x4e), w(0x4f), \ + w(0x50), w(0x51), w(0x52), w(0x53), w(0x54), w(0x55), w(0x56), w(0x57), \ + w(0x58), w(0x59), w(0x5a), w(0x5b), w(0x5c), w(0x5d), w(0x5e), w(0x5f), \ + w(0x60), w(0x61), w(0x62), w(0x63), w(0x64), w(0x65), w(0x66), w(0x67), \ + w(0x68), w(0x69), w(0x6a), w(0x6b), w(0x6c), w(0x6d), w(0x6e), w(0x6f), \ + w(0x70), w(0x71), w(0x72), w(0x73), w(0x74), w(0x75), w(0x76), w(0x77), \ + w(0x78), w(0x79), w(0x7a), w(0x7b), w(0x7c), w(0x7d), w(0x7e), w(0x7f), \ + w(0x80), w(0x81), w(0x82), w(0x83), w(0x84), w(0x85), w(0x86), w(0x87), \ + w(0x88), w(0x89), w(0x8a), w(0x8b), w(0x8c), w(0x8d), w(0x8e), w(0x8f), \ + w(0x90), w(0x91), w(0x92), w(0x93), w(0x94), w(0x95), w(0x96), w(0x97), \ + w(0x98), w(0x99), w(0x9a), w(0x9b), w(0x9c), w(0x9d), w(0x9e), w(0x9f), \ + w(0xa0), w(0xa1), w(0xa2), w(0xa3), w(0xa4), w(0xa5), w(0xa6), w(0xa7), \ + w(0xa8), w(0xa9), w(0xaa), w(0xab), w(0xac), w(0xad), w(0xae), w(0xaf), \ + w(0xb0), w(0xb1), w(0xb2), w(0xb3), w(0xb4), w(0xb5), w(0xb6), w(0xb7), \ + w(0xb8), w(0xb9), w(0xba), w(0xbb), w(0xbc), w(0xbd), w(0xbe), w(0xbf), \ + w(0xc0), w(0xc1), w(0xc2), w(0xc3), w(0xc4), w(0xc5), w(0xc6), w(0xc7), \ + w(0xc8), w(0xc9), w(0xca), w(0xcb), w(0xcc), w(0xcd), w(0xce), w(0xcf), \ + w(0xd0), w(0xd1), w(0xd2), w(0xd3), w(0xd4), w(0xd5), w(0xd6), w(0xd7), \ + w(0xd8), w(0xd9), w(0xda), w(0xdb), w(0xdc), w(0xdd), w(0xde), w(0xdf), \ + w(0xe0), w(0xe1), w(0xe2), w(0xe3), w(0xe4), w(0xe5), w(0xe6), w(0xe7), \ + w(0xe8), w(0xe9), w(0xea), w(0xeb), w(0xec), w(0xed), w(0xee), w(0xef), \ + w(0xf0), w(0xf1), w(0xf2), w(0xf3), w(0xf4), w(0xf5), w(0xf6), w(0xf7), \ + w(0xf8), w(0xf9), w(0xfa), w(0xfb), w(0xfc), w(0xfd), w(0xfe), w(0xff) + +#define h0(x) (x) + +/* These defines are used to ensure tables are generated in the + * right format depending on the internal byte order required + */ + +#define w0(p) bytes2word(p, 0, 0, 0) +#define w1(p) bytes2word(0, p, 0, 0) +#define w2(p) bytes2word(0, 0, p, 0) +#define w3(p) bytes2word(0, 0, 0, p) + +/* Number of elements required in this table for different + * block and key lengths is: + * + * Rcon Table key length (bytes) + * Length 16 20 24 28 32 + * --------------------- + * block 16 | 10 9 8 7 7 + * length 20 | 14 11 10 9 9 + * (bytes) 24 | 19 15 12 11 11 + * 28 | 24 19 16 13 13 + * 32 | 29 23 19 17 14 + * + * this table can be a table of bytes if the key schedule + * code is adjusted accordingly + */ + +#define u0(p) bytes2word(f2(p), p, p, f3(p)) +#define u1(p) bytes2word(f3(p), f2(p), p, p) +#define u2(p) bytes2word(p, f3(p), f2(p), p) +#define u3(p) bytes2word(p, p, f3(p), f2(p)) + +#define v0(p) bytes2word(fe(p), f9(p), fd(p), fb(p)) +#define v1(p) bytes2word(fb(p), fe(p), f9(p), fd(p)) +#define v2(p) bytes2word(fd(p), fb(p), fe(p), f9(p)) +#define v3(p) bytes2word(f9(p), fd(p), fb(p), fe(p)) + +const aes_32t rcon_tab[29] = +{ + w0(0x01), w0(0x02), w0(0x04), w0(0x08), + w0(0x10), w0(0x20), w0(0x40), w0(0x80), + w0(0x1b), w0(0x36), w0(0x6c), w0(0xd8), + w0(0xab), w0(0x4d), w0(0x9a), w0(0x2f), + w0(0x5e), w0(0xbc), w0(0x63), w0(0xc6), + w0(0x97), w0(0x35), w0(0x6a), w0(0xd4), + w0(0xb3), w0(0x7d), w0(0xfa), w0(0xef), + w0(0xc5) +}; + +#ifdef SBX_SET +const aes_08t s_box[256] = { sb_data(h0) }; +#endif +#ifdef ISB_SET +const aes_08t inv_s_box[256] = { isb_data(h0) }; +#endif + +#ifdef FT1_SET +const aes_32t ft_tab[256] = { sb_data(u0) }; +#endif +#ifdef FT4_SET +const aes_32t ft_tab[4][256] = +{ { sb_data(u0) }, { sb_data(u1) }, { sb_data(u2) }, { sb_data(u3) } }; +#endif + +#ifdef FL1_SET +const aes_32t fl_tab[256] = { sb_data(w0) }; +#endif +#ifdef FL4_SET +const aes_32t fl_tab[4][256] = +{ { sb_data(w0) }, { sb_data(w1) }, { sb_data(w2) }, { sb_data(w3) } }; +#endif + +#ifdef IT1_SET +const aes_32t it_tab[256] = { isb_data(v0) }; +#endif +#ifdef IT4_SET +const aes_32t it_tab[4][256] = +{ { isb_data(v0) }, { isb_data(v1) }, { isb_data(v2) }, { isb_data(v3) } }; +#endif + +#ifdef IL1_SET +const aes_32t il_tab[256] = { isb_data(w0) }; +#endif +#ifdef IL4_SET +const aes_32t il_tab[4][256] = +{ { isb_data(w0) }, { isb_data(w1) }, { isb_data(w2) }, { isb_data(w3) } }; +#endif + +#ifdef LS1_SET +const aes_32t ls_tab[256] = { sb_data(w0) }; +#endif +#ifdef LS4_SET +const aes_32t ls_tab[4][256] = +{ { sb_data(w0) }, { sb_data(w1) }, { sb_data(w2) }, { sb_data(w3) } }; +#endif + +#ifdef IM1_SET +const aes_32t im_tab[256] = { mm_data(v0) }; +#endif +#ifdef IM4_SET +const aes_32t im_tab[4][256] = +{ { mm_data(v0) }, { mm_data(v1) }, { mm_data(v2) }, { mm_data(v3) } }; +#endif + +#else /* dynamic table generation */ + +aes_08t tab_init = 0; + +#define const + +aes_32t rcon_tab[RC_LENGTH]; + +#ifdef SBX_SET +aes_08t s_box[256]; +#endif +#ifdef ISB_SET +aes_08t inv_s_box[256]; +#endif + +#ifdef FT1_SET +aes_32t ft_tab[256]; +#endif +#ifdef FT4_SET +aes_32t ft_tab[4][256]; +#endif + +#ifdef FL1_SET +aes_32t fl_tab[256]; +#endif +#ifdef FL4_SET +aes_32t fl_tab[4][256]; +#endif + +#ifdef IT1_SET +aes_32t it_tab[256]; +#endif +#ifdef IT4_SET +aes_32t it_tab[4][256]; +#endif + +#ifdef IL1_SET +aes_32t il_tab[256]; +#endif +#ifdef IL4_SET +aes_32t il_tab[4][256]; +#endif + +#ifdef LS1_SET +aes_32t ls_tab[256]; +#endif +#ifdef LS4_SET +aes_32t ls_tab[4][256]; +#endif + +#ifdef IM1_SET +aes_32t im_tab[256]; +#endif +#ifdef IM4_SET +aes_32t im_tab[4][256]; +#endif + +#if !defined(FF_TABLES) + +/* Generate the tables for the dynamic table option + * + * It will generally be sensible to use tables to compute finite + * field multiplies and inverses but where memory is scarse this + * code might sometimes be better. But it only has effect during + * initialisation so its pretty unimportant in overall terms. + */ + +/* return 2 ^ (n - 1) where n is the bit number of the highest bit + * set in x with x in the range 1 < x < 0x00000200. This form is + * used so that locals within fi can be bytes rather than words + */ + +static aes_08t hibit(const aes_32t x) +{ + aes_08t r = (aes_08t) ((x >> 1) | (x >> 2)); + + r |= (r >> 2); + r |= (r >> 4); + return (r + 1) >> 1; +} + +/* return the inverse of the finite field element x */ + +static aes_08t fi(const aes_08t x) +{ + aes_08t p1 = x, p2 = BPOLY, n1 = hibit(x), n2 = 0x80, v1 = 1, v2 = 0; + + if (x < 2) { + return x; + } + + for (;; ) { + if (!n1) { + return v1; + } + + while (n2 >= n1) { + n2 /= n1; + p2 ^= p1 * n2; + v2 ^= v1 * n2; + n2 = hibit(p2); + } + + if (!n2) { + return v2; + } + + while (n1 >= n2) { + n1 /= n2; + p1 ^= p2 * n1; + v1 ^= v2 * n1; + n1 = hibit(p1); + } + } +} + +#else + +/* define the finite field multiplies required for Rijndael */ + +#define f2(x) ((x) ? pow[log[x] + 0x19] : 0) +#define f3(x) ((x) ? pow[log[x] + 0x01] : 0) +#define f9(x) ((x) ? pow[log[x] + 0xc7] : 0) +#define fb(x) ((x) ? pow[log[x] + 0x68] : 0) +#define fd(x) ((x) ? pow[log[x] + 0xee] : 0) +#define fe(x) ((x) ? pow[log[x] + 0xdf] : 0) +#define fi(x) ((x) ? pow[255 - log[x]] : 0) + +#endif + +/* The forward and inverse affine transformations used in the S-box */ + +#define fwd_affine(x) \ + (w = (aes_32t) x, w ^= (w << 1) ^ (w << 2) ^ (w << 3) ^ (w << 4), 0x63 ^ (aes_08t) (w ^ (w >> 8))) + +#define inv_affine(x) \ + (w = (aes_32t) x, w = (w << 1) ^ (w << 3) ^ (w << 6), 0x05 ^ (aes_08t) (w ^ (w >> 8))) + +void gen_tabs(void) +{ + aes_32t i, w; + +#if defined(FF_TABLES) + + aes_08t pow[512], log[256]; + + /* log and power tables for GF(2^8) finite field with + * WPOLY as modular polynomial - the simplest primitive + * root is 0x03, used here to generate the tables + */ + + i = 0; + w = 1; + do { + pow[i] = (aes_08t) w; + pow[i + 255] = (aes_08t) w; + log[w] = (aes_08t) i++; + w ^= (w << 1) ^ (w & 0x80 ? WPOLY : 0); + } while (w != 1); + +#endif + + for (i = 0, w = 1; i < RC_LENGTH; ++i) { + rcon_tab[i] = bytes2word(w, 0, 0, 0); + w = f2(w); + } + + for (i = 0; i < 256; ++i) { + aes_08t b; + + b = fwd_affine(fi((aes_08t) i)); + w = bytes2word(f2(b), b, b, f3(b)); + +#ifdef SBX_SET + s_box[i] = b; +#endif + +#ifdef FT1_SET /* tables for a normal encryption round */ + ft_tab[i] = w; +#endif +#ifdef FT4_SET + ft_tab[0][i] = w; + ft_tab[1][i] = upr(w, 1); + ft_tab[2][i] = upr(w, 2); + ft_tab[3][i] = upr(w, 3); +#endif + w = bytes2word(b, 0, 0, 0); + +#ifdef FL1_SET /* tables for last encryption round (may also */ + fl_tab[i] = w; /* be used in the key schedule) */ +#endif +#ifdef FL4_SET + fl_tab[0][i] = w; + fl_tab[1][i] = upr(w, 1); + fl_tab[2][i] = upr(w, 2); + fl_tab[3][i] = upr(w, 3); +#endif + +#ifdef LS1_SET /* table for key schedule if fl_tab above is */ + ls_tab[i] = w; /* not of the required form */ +#endif +#ifdef LS4_SET + ls_tab[0][i] = w; + ls_tab[1][i] = upr(w, 1); + ls_tab[2][i] = upr(w, 2); + ls_tab[3][i] = upr(w, 3); +#endif + + b = fi(inv_affine((aes_08t) i)); + w = bytes2word(fe(b), f9(b), fd(b), fb(b)); + +#ifdef IM1_SET /* tables for the inverse mix column operation */ + im_tab[b] = w; +#endif +#ifdef IM4_SET + im_tab[0][b] = w; + im_tab[1][b] = upr(w, 1); + im_tab[2][b] = upr(w, 2); + im_tab[3][b] = upr(w, 3); +#endif + +#ifdef ISB_SET + inv_s_box[i] = b; +#endif +#ifdef IT1_SET /* tables for a normal decryption round */ + it_tab[i] = w; +#endif +#ifdef IT4_SET + it_tab[0][i] = w; + it_tab[1][i] = upr(w, 1); + it_tab[2][i] = upr(w, 2); + it_tab[3][i] = upr(w, 3); +#endif + w = bytes2word(b, 0, 0, 0); +#ifdef IL1_SET /* tables for last decryption round */ + il_tab[i] = w; +#endif +#ifdef IL4_SET + il_tab[0][i] = w; + il_tab[1][i] = upr(w, 1); + il_tab[2][i] = upr(w, 2); + il_tab[3][i] = upr(w, 3); +#endif + } + + tab_init = 1; +} + +#endif === modified file 'i3/chord/api.c' --- i3/chord/api.c 2009-12-11 22:49:11 +0000 +++ i3/chord/api.c 2010-02-11 11:49:47 +0000 @@ -1,171 +1,173 @@ -/* Common API functions */ - -#include <sys/types.h> -#include <sys/socket.h> -#include <sys/ipc.h> -#include <sys/shm.h> -#include <unistd.h> -#include <signal.h> -#include <string.h> -#include <stdlib.h> -#include <sys/stat.h> -#include "chord.h" - -#define RUNTIME_DIR "/var/run/chord" -#ifndef PATH_MAX -#define PATH_MAX 256 -#endif -static char shmid_filename[PATH_MAX]; - -#ifndef SIM_CHORD -static int sp[2]; /* Socket pair for communication between the two layers */ -static chordID *shared_data; -static int shmid; -#else -static chordID LeftId, RightId; -#endif - -#ifndef SIM_CHORD - -/* route: forward message M towards the root of key K. */ -void chord_route(chordID *k, char *data, int len) -{ - byte buf[BUFSIZE]; - - if (send(sp[0], buf, pack_data(buf, CHORD_ROUTE, - DEF_TTL, k, len, (unsigned char*)data), 0) < 0) - weprintf("send failed:"); /* ignore errors */ -} - -/**********************************************************************/ - -/* init: initialize chord server, return socket descriptor */ -int chord_init(char *conf_file) -{ - FILE *fp; - struct stat stat_buf; - - if (socketpair(AF_UNIX, SOCK_DGRAM, 0, sp) < 0) - eprintf("socket_pair failed:"); - - if ((shmid = shmget(IPC_PRIVATE, 1024, 0644 | IPC_CREAT)) == -1) - eprintf("shmget failed:"); - -#ifndef CCURED - shared_data = (chordID *) shmat(shmid, (void *) 0, 0); - if ((char *) shared_data == (char *) -1) - eprintf("shmate failed:"); -#else - { - void * shared_data_ret = shmat(shmid, (void *) 0, 0); - if ((ulong) shared_data_ret == (ulong) -1) - eprintf("shmate failed:"); - shared_data = (chordID *)__trusted_cast(__mkptr_size(shared_data_ret, - 1024)); - } -#endif - - /* Write out PID, shmid for monitor */ - memset( &stat_buf, 0, sizeof(struct stat) ); - if( stat( RUNTIME_DIR, &stat_buf ) || !S_ISDIR(stat_buf.st_mode) ) { - weprintf( "Could not open %s; not writing shmid\n", RUNTIME_DIR ); - - } else { - sprintf( shmid_filename, "%s/chord.%u.shmid", RUNTIME_DIR, - getpid() ); - fp = fopen( shmid_filename, "w"); - if (fp == NULL) { - weprintf("Could not write %s\n", shmid_filename); - } else { - if( (fprintf( fp, "%d\n", shmid ) <= 0) || - fflush( fp ) || fclose( fp ) ) { - eprintf("Could not write %s\n", shmid_filename ); - } - } - } - - /* Catch all crashes/kills and cleanup */ - signal(SIGHUP, chord_cleanup); - signal(SIGINT, chord_cleanup); - signal(SIGILL, chord_cleanup); - signal(SIGABRT, chord_cleanup); - signal(SIGALRM, chord_cleanup); - signal(SIGFPE, chord_cleanup); - signal(SIGSEGV, chord_cleanup); - signal(SIGPIPE, chord_cleanup); - signal(SIGTERM, chord_cleanup); - signal(SIGCHLD, chord_cleanup); /* If Chord process dies, exit */ - signal(SIGBUS, chord_cleanup); - - if (!fork()) { /* child */ - chord_main(conf_file, sp[1]); - } - - return sp[0]; -} - -/**********************************************************************/ - -void chord_cleanup(int signum) -{ - shmdt(shared_data); - shmctl(shmid, IPC_RMID, NULL); - unlink(shmid_filename); - signal(SIGABRT, SIG_DFL); - abort(); -} - -/**********************************************************************/ - -/* deliver: upcall */ -void chord_deliver(int n, uchar *data) -{ - /* Convert to I3 format... by stripping off the Chord header */ - send(sp[1], data, n, 0); -} - -#endif - -/**********************************************************************/ - -/* get_range: returns the range (l,r] that this node is responsible for */ -void chord_get_range(chordID *l, chordID *r) -{ -#ifndef SIM_CHORD - *l = shared_data[0]; - *r = shared_data[1]; -#else - *l = LeftId; - *r = RightId; -#endif -} - - - -/**********************************************************************/ - -void chord_update_range(chordID *l, chordID *r) -{ - //printf("update_range("); - //print_chordID(l); - //printf(" - "); - //print_chordID(r); - //printf(")\n"); -#ifndef SIM_CHORD - shared_data[0] = *l; - shared_data[1] = *r; -#else - LeftId = *l; - RightId = *r; -#endif -} - -/**********************************************************************/ - -int chord_is_local(chordID *x) -{ - chordID l, r; - - chord_get_range(&l, &r); - return equals(x, &r) || is_between(x, &l, &r); -} +/* Common API functions */ + +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/ipc.h> +#include <sys/shm.h> +#include <unistd.h> +#include <signal.h> +#include <string.h> +#include <stdlib.h> +#include <sys/stat.h> +#include "chord.h" + +#define RUNTIME_DIR "/var/run/chord" +#ifndef PATH_MAX +#define PATH_MAX 256 +#endif +static char shmid_filename[PATH_MAX]; + +#ifndef SIM_CHORD +static int sp[2]; /* Socket pair for communication between the two layers */ +static chordID *shared_data; +static int shmid; +#else +static chordID LeftId, RightId; +#endif + +#ifndef SIM_CHORD + +/* route: forward message M towards the root of key K. */ +void chord_route(chordID *k, char *data, int len) +{ + byte buf[BUFSIZE]; + + if (send(sp[0], buf, pack_data(buf, CHORD_ROUTE, + DEF_TTL, k, len, (unsigned char *) data), 0) < 0) { + weprintf("send failed:"); /* ignore errors */ + } +} + +/**********************************************************************/ + +/* init: initialize chord server, return socket descriptor */ +int chord_init(char *conf_file) +{ + FILE *fp; + struct stat stat_buf; + + if (socketpair(AF_UNIX, SOCK_DGRAM, 0, sp) < 0) { + eprintf("socket_pair failed:"); + } + + if ((shmid = shmget(IPC_PRIVATE, 1024, 0644 | IPC_CREAT)) == -1) { + eprintf("shmget failed:"); + } + +#ifndef CCURED + shared_data = (chordID *) shmat(shmid, (void *) 0, 0); + if ((char *) shared_data == (char *) -1) { + eprintf("shmate failed:"); + } +#else + { + void *shared_data_ret = shmat(shmid, (void *) 0, 0); + if ((ulong) shared_data_ret == (ulong) - 1) { + eprintf("shmate failed:"); + } + shared_data = (chordID *) __trusted_cast(__mkptr_size(shared_data_ret, + 1024)); + } +#endif + + /* Write out PID, shmid for monitor */ + memset( &stat_buf, 0, sizeof(struct stat)); + if (stat( RUNTIME_DIR, &stat_buf ) || !S_ISDIR(stat_buf.st_mode)) { + weprintf( "Could not open %s; not writing shmid\n", RUNTIME_DIR ); + } else { + sprintf( shmid_filename, "%s/chord.%u.shmid", RUNTIME_DIR, + getpid()); + fp = fopen( shmid_filename, "w"); + if (fp == NULL) { + weprintf("Could not write %s\n", shmid_filename); + } else { + if ((fprintf( fp, "%d\n", shmid ) <= 0) || + fflush( fp ) || fclose( fp )) { + eprintf("Could not write %s\n", shmid_filename ); + } + } + } + + /* Catch all crashes/kills and cleanup */ + signal(SIGHUP, chord_cleanup); + signal(SIGINT, chord_cleanup); + signal(SIGILL, chord_cleanup); + signal(SIGABRT, chord_cleanup); + signal(SIGALRM, chord_cleanup); + signal(SIGFPE, chord_cleanup); + signal(SIGSEGV, chord_cleanup); + signal(SIGPIPE, chord_cleanup); + signal(SIGTERM, chord_cleanup); + signal(SIGCHLD, chord_cleanup); /* If Chord process dies, exit */ + signal(SIGBUS, chord_cleanup); + + if (!fork()) { /* child */ + chord_main(conf_file, sp[1]); + } + + return sp[0]; +} + +/**********************************************************************/ + +void chord_cleanup(int signum) +{ + shmdt(shared_data); + shmctl(shmid, IPC_RMID, NULL); + unlink(shmid_filename); + signal(SIGABRT, SIG_DFL); + abort(); +} + +/**********************************************************************/ + +/* deliver: upcall */ +void chord_deliver(int n, uchar *data) +{ + /* Convert to I3 format... by stripping off the Chord header */ + send(sp[1], data, n, 0); +} + +#endif + +/**********************************************************************/ + +/* get_range: returns the range (l,r] that this node is responsible for */ +void chord_get_range(chordID *l, chordID *r) +{ +#ifndef SIM_CHORD + *l = shared_data[0]; + *r = shared_data[1]; +#else + *l = LeftId; + *r = RightId; +#endif +} + +/**********************************************************************/ + +void chord_update_range(chordID *l, chordID *r) +{ + //printf("update_range("); + //print_chordID(l); + //printf(" - "); + //print_chordID(r); + //printf(")\n"); +#ifndef SIM_CHORD + shared_data[0] = *l; + shared_data[1] = *r; +#else + LeftId = *l; + RightId = *r; +#endif +} + +/**********************************************************************/ + +int chord_is_local(chordID *x) +{ + chordID l, r; + + chord_get_range(&l, &r); + return equals(x, &r) || is_between(x, &l, &r); +} === modified file 'i3/chord/chord.c' --- i3/chord/chord.c 2010-01-12 12:35:31 +0000 +++ i3/chord/chord.c 2010-02-11 11:49:47 +0000 @@ -1,203 +1,204 @@ -/* Chord server loop */ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <time.h> -#include <assert.h> -#include <unistd.h> -#include <fcntl.h> -#include <errno.h> -#include <sys/types.h> -#include <sys/socket.h> -#include <sys/utsname.h> -#include <netinet/in.h> -#include <arpa/inet.h> -#include <netdb.h> -#include <sys/time.h> -#include "chord.h" -#include "../utils/gen_utils.h" - -/* globals */ -extern Server *srv_ref; /* For use in stabilize() */ -Server srv; -Node well_known[MAX_WELLKNOWN]; -int nknown; -Key KeyArray[MAX_KEY_NUM]; -int NumKeys; - - -/**********************************************************************/ - -void -chord_main(char *conf_file, int parent_sock) -{ - fd_set interesting, readable; - int nfound, nfds; - struct in_addr ia; - char id[4*ID_LEN]; - FILE *fp; - int64_t stabilize_wait; - struct timeval timeout; - - setprogname("chord"); - srandom(getpid() ^ time(0)); - memset(&srv, 0, sizeof(Server)); - srv.to_fix_finger = NFINGERS-1; - - fp = fopen(conf_file, "r"); - if (fp == NULL) - eprintf("fopen(%s,\"r\") failed:", conf_file); - if (fscanf(fp, "%hd", (short*)&srv.node.port) != 1) - eprintf("Didn't find port in \"%s\"", conf_file); - if (fscanf(fp, " %s\n", id) != 1) - eprintf("Didn't find id in \"%s\"", conf_file); - srv.node.id = atoid(id); - - /* Figure out one's own address somehow */ - srv.node.addr = ntohl(get_addr()); - - ia.s_addr = htonl(srv.node.addr); - fprintf(stderr, "Chord started.\n"); - fprintf(stderr, "id="); print_id(stderr, &srv.node.id); - fprintf(stderr, "\n"); - fprintf(stderr, "ip=%s\n", inet_ntoa(ia)); - fprintf(stderr, "port=%d\n", srv.node.port); - - initialize(&srv); - srv_ref = &srv; - join(&srv, fp); - fclose(fp); - - FD_ZERO(&interesting); - FD_SET(srv.in_sock, &interesting); - FD_SET(parent_sock, &interesting); - nfds = MAX(srv.in_sock, parent_sock) + 1; - - NumKeys = read_keys(ACCLIST_FILE, KeyArray, MAX_KEY_NUM); - if (NumKeys == -1) { - printf("Error opening file: %s\n", ACCLIST_FILE); - } - if (NumKeys == 0) { - printf("No key found in %s\n", ACCLIST_FILE); - } - - /* Loop on input */ - for (;;) { - readable = interesting; - stabilize_wait = (int64_t)(srv.next_stabilize_us - wall_time()); - stabilize_wait = MAX(stabilize_wait,0); - timeout.tv_sec = stabilize_wait / 1000000UL; - timeout.tv_usec = stabilize_wait % 1000000UL; - nfound = select(nfds, &readable, NULL, NULL, &timeout); - if (nfound < 0 && errno == EINTR) { - continue; - } - if (nfound == 0) { - stabilize_wait = (int64_t)(srv.next_stabilize_us - wall_time()); - if( stabilize_wait <= 0 ) { - stabilize( &srv ); - } - continue; - } - if (FD_ISSET(srv.in_sock, &readable)) { - handle_packet(srv.in_sock); - } - else if (FD_ISSET(parent_sock, &readable)) { - handle_packet(parent_sock); - } - else { - assert(0); - } - } -} - -/**********************************************************************/ - -/* initialize: set up sockets and such <yawn> */ -void -initialize(Server *srv) -{ - int flags; - struct sockaddr_in sin, sout; - - setservent(1); - - memset(&sin, 0, sizeof(sin)); - sin.sin_family = AF_INET; - sin.sin_port = htons(srv->node.port); - sin.sin_addr.s_addr = htonl(INADDR_ANY); - - srv->in_sock = socket(AF_INET, SOCK_DGRAM, 0); - if (srv->in_sock < 0) - eprintf("socket failed:"); - - if (bind(srv->in_sock, (struct sockaddr *) &sin, sizeof(sin)) < 0) - eprintf("bind failed:"); - - /* non-blocking i/o */ - flags = fcntl(srv->in_sock, F_GETFL); - flags |= O_NONBLOCK; - fcntl(srv->in_sock, F_SETFL, flags); - - /* outgoing socket */ - memset(&sout, 0, sizeof(sout)); - sout.sin_family = AF_INET; - sout.sin_port = htons(0); - sout.sin_addr.s_addr = htonl(INADDR_ANY); - - srv->out_sock = socket(AF_INET, SOCK_DGRAM, 0); - if (srv->out_sock < 0) - eprintf("socket failed:"); - - if (bind(srv->out_sock, (struct sockaddr *) &sout, sizeof(sout)) < 0) - eprintf("bind failed:"); -} - -/**********************************************************************/ - -/* handle_packet: snarf packet from network and dispatch */ -void -handle_packet(int network) -{ - int packet_len, from_len; - struct sockaddr_in from; - byte buf[BUFSIZE]; - - from_len = sizeof(from); - packet_len = recvfrom(network, buf, sizeof(buf), 0, - (struct sockaddr *) &from, (unsigned int*)&from_len); - if (packet_len < 0) { - if (errno != EAGAIN) { - weprintf("recvfrom failed:"); /* ignore errors for now */ - return; - } - weprintf("handle_packet: EAGAIN"); - return; /* pick up this packet later */ - } - dispatch(&srv, packet_len, buf); -} - - -/**********************************************************************/ - -int -read_keys(char *file, Key *keyarray, int max_num_keys) -{ - int i; - FILE *fp; - - fp = fopen(file, "r"); - if (fp == NULL) - return -1; - - for (i = 0; i < max_num_keys; i++) { - if (fscanf(fp, "%20c\n", (char *)&keyarray[i]) != 1) - break; - } - return i; - - fclose(fp); -} - - +/* Chord server loop */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <assert.h> +#include <unistd.h> +#include <fcntl.h> +#include <errno.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/utsname.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <netdb.h> +#include <sys/time.h> +#include "chord.h" +#include "../utils/gen_utils.h" + +/* globals */ +extern Server *srv_ref; /* For use in stabilize() */ +Server srv; +Node well_known[MAX_WELLKNOWN]; +int nknown; +Key KeyArray[MAX_KEY_NUM]; +int NumKeys; + + +/**********************************************************************/ + +void chord_main(char *conf_file, int parent_sock) +{ + fd_set interesting, readable; + int nfound, nfds; + struct in_addr ia; + char id[4 * ID_LEN]; + FILE *fp; + int64_t stabilize_wait; + struct timeval timeout; + + setprogname("chord"); + srandom(getpid() ^ time(0)); + memset(&srv, 0, sizeof(Server)); + srv.to_fix_finger = NFINGERS - 1; + + fp = fopen(conf_file, "r"); + if (fp == NULL) { + eprintf("fopen(%s,\"r\") failed:", conf_file); + } + if (fscanf(fp, "%hd", (short *) &srv.node.port) != 1) { + eprintf("Didn't find port in \"%s\"", conf_file); + } + if (fscanf(fp, " %s\n", id) != 1) { + eprintf("Didn't find id in \"%s\"", conf_file); + } + srv.node.id = atoid(id); + + /* Figure out one's own address somehow */ + srv.node.addr = ntohl(get_addr()); + + ia.s_addr = htonl(srv.node.addr); + fprintf(stderr, "Chord started.\n"); + fprintf(stderr, "id="); + print_id(stderr, &srv.node.id); + fprintf(stderr, "\n"); + fprintf(stderr, "ip=%s\n", inet_ntoa(ia)); + fprintf(stderr, "port=%d\n", srv.node.port); + + initialize(&srv); + srv_ref = &srv; + join(&srv, fp); + fclose(fp); + + FD_ZERO(&interesting); + FD_SET(srv.in_sock, &interesting); + FD_SET(parent_sock, &interesting); + nfds = MAX(srv.in_sock, parent_sock) + 1; + + NumKeys = read_keys(ACCLIST_FILE, KeyArray, MAX_KEY_NUM); + if (NumKeys == -1) { + printf("Error opening file: %s\n", ACCLIST_FILE); + } + if (NumKeys == 0) { + printf("No key found in %s\n", ACCLIST_FILE); + } + + /* Loop on input */ + for (;; ) { + readable = interesting; + stabilize_wait = (int64_t) (srv.next_stabilize_us - wall_time()); + stabilize_wait = MAX(stabilize_wait, 0); + timeout.tv_sec = stabilize_wait / 1000000UL; + timeout.tv_usec = stabilize_wait % 1000000UL; + nfound = select(nfds, &readable, NULL, NULL, &timeout); + if (nfound < 0 && errno == EINTR) { + continue; + } + if (nfound == 0) { + stabilize_wait = (int64_t) (srv.next_stabilize_us - wall_time()); + if (stabilize_wait <= 0) { + stabilize( &srv ); + } + continue; + } + if (FD_ISSET(srv.in_sock, &readable)) { + handle_packet(srv.in_sock); + } else if (FD_ISSET(parent_sock, &readable)) { + handle_packet(parent_sock); + } else { + assert(0); + } + } +} + +/**********************************************************************/ + +/* initialize: set up sockets and such <yawn> */ +void initialize(Server *srv) +{ + int flags; + struct sockaddr_in sin, sout; + + setservent(1); + + memset(&sin, 0, sizeof(sin)); + sin.sin_family = AF_INET; + sin.sin_port = htons(srv->node.port); + sin.sin_addr.s_addr = htonl(INADDR_ANY); + + srv->in_sock = socket(AF_INET, SOCK_DGRAM, 0); + if (srv->in_sock < 0) { + eprintf("socket failed:"); + } + + if (bind(srv->in_sock, (struct sockaddr *) &sin, sizeof(sin)) < 0) { + eprintf("bind failed:"); + } + + /* non-blocking i/o */ + flags = fcntl(srv->in_sock, F_GETFL); + flags |= O_NONBLOCK; + fcntl(srv->in_sock, F_SETFL, flags); + + /* outgoing socket */ + memset(&sout, 0, sizeof(sout)); + sout.sin_family = AF_INET; + sout.sin_port = htons(0); + sout.sin_addr.s_addr = htonl(INADDR_ANY); + + srv->out_sock = socket(AF_INET, SOCK_DGRAM, 0); + if (srv->out_sock < 0) { + eprintf("socket failed:"); + } + + if (bind(srv->out_sock, (struct sockaddr *) &sout, sizeof(sout)) < 0) { + eprintf("bind failed:"); + } +} + +/**********************************************************************/ + +/* handle_packet: snarf packet from network and dispatch */ +void handle_packet(int network) +{ + int packet_len, from_len; + struct sockaddr_in from; + byte buf[BUFSIZE]; + + from_len = sizeof(from); + packet_len = recvfrom(network, buf, sizeof(buf), 0, + (struct sockaddr *) &from, (unsigned int *) &from_len); + if (packet_len < 0) { + if (errno != EAGAIN) { + weprintf("recvfrom failed:"); /* ignore errors for now */ + return; + } + weprintf("handle_packet: EAGAIN"); + return; /* pick up this packet later */ + } + dispatch(&srv, packet_len, buf); +} + +/**********************************************************************/ + +int read_keys(char *file, Key *keyarray, int max_num_keys) +{ + int i; + FILE *fp; + + fp = fopen(file, "r"); + if (fp == NULL) { + return -1; + } + + for (i = 0; i < max_num_keys; i++) { + if (fscanf(fp, "%20c\n", (char *) &keyarray[i]) != 1) { + break; + } + } + return i; + + fclose(fp); +} === modified file 'i3/chord/chord.h' --- i3/chord/chord.h 2010-01-12 12:35:31 +0000 +++ i3/chord/chord.h 2010-02-11 11:49:47 +0000 @@ -1,351 +1,348 @@ -#include <sys/types.h> -#include <netinet/in.h> -#ifdef __APPLE__ -#include <inttypes.h> // Need uint64_t -#endif -#include <stdio.h> -#include "debug.h" - -#ifndef INCL_CHORD_H -#define INCL_CHORD_H - -typedef struct Finger Finger; -typedef struct Node Node; -typedef struct Server Server; - - -#define NELEMS(a) (sizeof(a) / sizeof(a[0])) -#ifndef FALSE -#define FALSE 0 -#define TRUE 1 -#endif - -/* whether a finger is passive or active */ -#define F_PASSIVE 0 -#define F_ACTIVE 1 - -//#define SIM_CHORD - -#ifdef SIM_CHORD -enum { - NBITS = 16, /* # bits of an ID */ - ID_LEN = NBITS/8, /* bytes per ID */ - NFINGERS = NBITS, /* # fingers per node */ - NSUCCESSORS = 3, /* # successors kept */ - NPREDECESSORS = 3, /* # predecessors kep */ - BUFSIZE = 65535, /* buffer for packets */ - STABILIZE_PERIOD = 1*1000000, /* in usec */ - MAX_WELLKNOWN = 4, /* maximum number of "seed" servers */ - MAX_SIMJOIN = 4, /* maximum number of servers - * contacted simultaneously when joining - */ - PING_THRESH = 3, /* this many unanswered pings are allowed */ - DEF_TTL = 64, /* default TTL for multi-hop packets */ -}; -#else -enum { - NBITS = 160, /* # bits per ID, same as SHA-1 output */ - ID_LEN = NBITS/8, /* bytes per ID */ - NFINGERS = NBITS, /* # fingers per node */ - NSUCCESSORS = 8, /* # successors kept */ - NPREDECESSORS = 3, /* # predecessors kept */ - STABILIZE_PERIOD = 1*1000000, /* in usec */ - BUFSIZE = 65535, /* buffer for packets */ - MAX_WELLKNOWN = 50, /* maximum number of other known servers - * (read from configuration file) - */ - MAX_SIMJOIN = 4, /* maximum number of servers - * contacted simultaneously when joining - */ - PING_THRESH = 5, /* this many unanswered pings are allowed */ - DEF_TTL = 64, /* default TTL for multi-hop packets */ -}; -#endif /* SIM_CHORD */ - -/* packet types */ -enum { - CHORD_ROUTE = 0, /* data packet */ - CHORD_ROUTE_LAST, - CHORD_FS, /* find_successor */ - CHORD_FS_REPL, /* find_successor reply */ - CHORD_STAB, /* get predecessor */ - CHORD_STAB_REPL, /* ... response */ - CHORD_NOTIFY, /* notify (predecessor) */ - CHORD_PING, /* are you alive? */ - CHORD_PONG, /* yes, I am */ - CHORD_FINGERS_GET, /* get your finger list */ - CHORD_FINGERS_REPL,/* .. here is my finger list */ - CHORD_TRACEROUTE, /* traceroute */ - CHORD_TRACEROUTE_LAST, - CHORD_TRACEROUTE_REPL,/* traceroute repl */ -}; - -/* XXX: warning: portability bugs */ -typedef uint8_t byte; -typedef unsigned char uchar; -#ifdef __APPLE__ -typedef u_long ulong; -#endif - -typedef struct { - byte x[ID_LEN]; -} chordID; - -#define KEY_LEN 20 -typedef struct { - char x[KEY_LEN]; -} Key; - -struct Node -{ - chordID id; - in_addr_t addr; - in_port_t port; -}; - -struct Finger -{ - Node node; /* ID and address of finger */ - int status; /* specifies whether this finger has been - * pinged; possible values: F_PASSIVE (the node - * has not been pinged) and F_ACTIVE (the node - * has been pinged) - */ - int npings; /* # of unanswered pings */ - long rtt_avg; /* average rtt to finger (ms in simulator, - * usec in the implementation) - */ - long rtt_dev; /* rtt's mean deviation (ms in simulator, - * usec in the implementation) - */ - /* rtt_avg, rtt_dev can be used to implement - * proximity routing or set up RTO for ping - */ - struct Finger *next; - struct Finger *prev; -}; - -/* Finger table contains NFINGERS fingers, then predecessor, then - the successor list */ - -struct Server -{ - Node node; /* addr and ID */ - Finger *head_flist; /* head and tail of finger */ - Finger *tail_flist; /* table + pred + successors - */ - int to_fix_finger; /* next finger to be fixed */ - int to_fix_backup; /* next successor/predecessor to be fixed */ - int to_ping; /* next node in finger list to be refreshed */ - uint64_t next_stabilize_us; /* value of wall_time() at next stabilize */ - - int in_sock; /* incoming socket */ - int out_sock; /* outgoing socket */ -}; - -#define PRED(srv) (srv->tail_flist) -#define SUCC(srv) (srv->head_flist) - -/* GLOBALS */ -extern Node well_known[MAX_WELLKNOWN]; -extern int nknown; -#define MAX_KEY_NUM 20 -/* the keys in KeyArray are read from file acclist.txt, - * and are used to authenticate users sending control - * messages such as CHORD_FINGERS_GET. - * This mechanism is intended to prevent trivial DDoS attacks. - * - * (For now the keyes are sent and stored in clear so - * the security provided by this mechanism is quite weak) - */ -#define ACCLIST_FILE "acclist.txt" -extern Key KeyArray[MAX_KEY_NUM]; -extern int NumKeys; - -/* chord.c */ -extern void chord_main(char *conf_file, int parent_sock); -extern void initialize(Server *srv); -extern void handle_packet(int network); -extern int read_keys(char *file, Key *keyarray, int max_num_keys); - -/* finger.c */ -extern Finger *new_finger(Node *node); -extern Finger *succ_finger(Server *srv); -extern Finger *pred_finger(Server *srv); -extern Finger *closest_preceding_finger(Server *srv, chordID *id, int fall); -extern Node *closest_preceding_node(Server *srv, chordID *id, int fall); -extern void remove_finger(Server *srv, Finger *f); -extern Finger *get_finger(Server *srv, chordID *id); -extern Finger *insert_finger(Server *srv, chordID *id, - in_addr_t addr, in_port_t port, int *fnew); -void free_finger_list(Finger *flist); - -/* hosts.c */ -extern in_addr_t get_addr(void); /* get_addr: get IP address of server */ - -/* join.c */ -extern void join(Server *srv, FILE *fp); - -/* pack.c */ -extern int dispatch(Server *srv, int n, uchar *buf); - -extern int pack(uchar *buf, char *fmt, ...); -extern int unpack(uchar *buf, char *fmt, ...); -extern int sizeof_fmt(char *fmt); - -#ifdef CCURED -// These are the kinds of arguments that we pass to pack -struct pack_args { - int f1; - chordID * f2; -}; -#pragma ccuredvararg("pack", sizeof(struct pack_args)) -struct unpack_args { - ushort * f1; - uchar * f2; - ulong * f3; - chordID *id; -}; -#pragma ccuredvararg("unpack", sizeof(struct unpack_args)) -#endif - -extern int pack_data(uchar *buf, uchar type, byte ttl, - chordID *id, ushort len, uchar *data); -extern int unpack_data(Server *srv, int n, uchar *buf); -extern int pack_fs(uchar *buf, byte ttl, chordID *id, ulong addr, ushort port); -extern int unpack_fs(Server *srv, int n, uchar *buf); -extern int pack_fs_repl(uchar *buf, chordID *id, ulong addr, ushort port); -extern int unpack_fs_repl(Server *srv, int n, uchar *buf); -extern int pack_stab(uchar *buf, chordID *id, ulong addr, ushort port); -extern int unpack_stab(Server *srv, int n, uchar *buf); -extern int pack_stab_repl(uchar *buf, chordID *id, ulong addr, ushort port); -extern int unpack_stab_repl(Server *srv, int n, uchar *buf); -extern int pack_notify(uchar *buf, chordID *id, ulong addr, ushort port); -extern int unpack_notify(Server *srv, int n, uchar *buf); -int pack_ping(uchar *buf, chordID *id, ulong addr, ushort port, ulong time); -extern int unpack_ping(Server *srv, int n, uchar *buf); -extern int pack_pong(uchar *buf, chordID *id, - ulong addr, ushort port, ulong time); -extern int unpack_pong(Server *srv, int n, uchar *buf); -extern int pack_fingers_get(uchar *buf, ulong addr, ushort port, Key *key); -extern int unpack_fingers_get(Server *srv, int n, uchar *buf); -extern int pack_fingers_repl(uchar *buf, Server *srv); -extern int unpack_fingers_repl(Server *null, int n, uchar *buf); - -extern int pack_traceroute(uchar *buf, Server *srv, Finger *f, - uchar type, byte ttl, byte hops); -extern int unpack_traceroute(Server *srv, int n, uchar *buf); -extern int pack_traceroute_repl(uchar *buf, Server *srv, byte ttl, byte hops, - ulong *paddr, ushort *pport, int one_hop); -extern int unpack_traceroute_repl(Server *srv, int n, uchar *buf); - -/* process.c */ -extern int process_data(Server *srv, uchar type, byte ttl, chordID *id, - ushort len, uchar *data); -extern int process_fs(Server *srv, byte ttl, - chordID *id, ulong addr, ushort port); -extern int process_fs_repl(Server *srv, chordID *id, ulong addr, ushort port); -extern int process_stab(Server *srv, chordID *id, ulong addr, ushort port); -extern int process_stab_repl(Server *srv, chordID *id, - ulong addr, ushort port); -extern int process_notify(Server *srv, chordID *id, ulong addr, ushort port); -extern int process_ping(Server *srv, chordID *id, - ulong addr, ushort port, ulong time); -extern int process_pong(Server *srv, chordID *id, - ulong addr, ushort port, ulong time); -extern int process_fingers_get(Server *srv, ulong addr, ushort port, Key *key); -extern int process_fingers_repl(Server *srv, uchar ret_code); -extern int process_traceroute(Server *srv, chordID *id, char *buf, - uchar type, byte ttl, byte hops); -extern int process_traceroute_repl(Server *srv, char *buf, - byte ttl, byte hops); - -/* sendpkt.c */ -extern void send_raw(Server *srv, in_addr_t addr, in_port_t port, - int n, uchar *buf); -extern void send_data(Server *srv, uchar type, byte ttl, Node *np, - chordID *id, ushort n, uchar *data); -extern void send_fs(Server *srv, byte ttl, ulong to_addr, ushort to_port, - chordID *id, ulong addr, ushort port); -extern void send_fs_repl(Server *srv, ulong to_addr, ushort to_port, - chordID *id, ulong addr, ushort port); -extern void send_stab(Server *srv, ulong to_addr, ushort to_port, - chordID *id, ulong addr, ushort port); -extern void send_stab_repl(Server *srv, ulong to_addr, ushort to_port, - chordID *id, ulong addr, ushort port); -extern void send_notify(Server *srv, ulong to_addr, ushort to_port, - chordID *id, ulong addr, ushort port); -extern void send_ping(Server *srv, ulong to_addr, ushort to_port, - ulong addr, ushort port, ulong time); -extern void send_pong(Server *srv, ulong to_addr, ushort to_port, ulong time); -extern void send_fingers_get(Server *srv, ulong to_addr, ushort to_port, - ulong addr, ushort port, Key *key); -extern void send_fingers_repl(Server *srv, ulong to_addr, ushort to_port); -extern void send_traceroute(Server *srv, Finger *f, uchar *buf, - uchar type, byte ttl, byte hops); -extern void send_traceroute_repl(Server *srv, uchar *buf, int ttl, - int hops, int one_hop); - -/* stabilize.c */ -extern void stabilize(Server *srv); -extern void set_stabilize_timer(void); - -/* api.c */ -extern int chord_init(char *conf_file); -extern void chord_cleanup(int signum); -extern void chord_route(chordID *k, char *data, int len); -extern void chord_deliver(int n, uchar *data); -extern void chord_get_range(chordID *l, chordID *r); -void chord_update_range(chordID *l, chordID *r); -int chord_is_local(chordID *x); - -/* util.c */ -extern ulong get_current_time(void); -extern void update_rtt(long *rtt_avg, long *rtt_std, long new_rtt); -extern chordID rand_ID(void); -extern chordID successor(chordID id, int n); -extern chordID predecessor(chordID id, int n); -extern void add(chordID *a, chordID *b, chordID *res); -extern void subtract(chordID *a, chordID *b, chordID *res); -extern void random_between(chordID *a, chordID *b, chordID *res); -extern int msb(chordID *x); -extern int equals(chordID *a, chordID *b); -extern int equals_id_str(chordID *a, char *b); -extern int is_zero(chordID *x); -extern int is_between(chordID *x, chordID *a, chordID *b); -extern int copy_id( chordID *a, chordID *b); -extern void print_id(FILE *f, chordID *id); -extern chordID atoid(const char *str); -extern unsigned hash(chordID *id, unsigned n); -extern void print_chordID(chordID *id); -extern void print_two_chordIDs(char *preffix, chordID *id1, - char *middle, chordID *id2, - char *suffix); -extern void print_three_chordIDs(char *preffix, chordID *id1, - char *middle1, chordID *id2, - char *middle2, chordID *id3, - char *suffix); -extern void print_node(Node *node, char *prefix, char *suffix); -extern void print_finger(Finger *f, char *prefix, char *suffix); -extern void print_finger_list(Finger *fhead, char *prefix, char *suffix); -extern void print_server(Server *s, char *prefix, char *suffix); -extern void print_process(Server *srv, char *process_type, chordID *id, - ulong addr, ushort port); -extern void print_send(Server *srv, char *send_type, chordID *id, - ulong addr, ushort port); -extern void print_fun(Server *srv, char *fun_name, chordID *id); -void print_current_time(char *prefix, char *suffix); -extern int match_key(Key *key); - -#ifdef SIM_CHORD -void sim_send_raw(Server *srv, - in_addr_t addr, in_port_t port, int n, uchar *buf); -void sim_deliver_data(Server *srv, chordID *id, int n, uchar *data); -Server *get_random_server(int no_idx, int status); -int sim_chord_is_local(Server *srv, chordID *x); -double sim_get_time(void); -#endif - -#include "eprintf.h" - -#endif /* INCL_CHORD_H */ +#include <sys/types.h> +#include <netinet/in.h> +#ifdef __APPLE__ +#include <inttypes.h> // Need uint64_t +#endif +#include <stdio.h> +#include "debug.h" + +#ifndef INCL_CHORD_H +#define INCL_CHORD_H + +typedef struct Finger Finger; +typedef struct Node Node; +typedef struct Server Server; + + +#define NELEMS(a) (sizeof(a) / sizeof(a[0])) +#ifndef FALSE +#define FALSE 0 +#define TRUE 1 +#endif + +/* whether a finger is passive or active */ +#define F_PASSIVE 0 +#define F_ACTIVE 1 + +//#define SIM_CHORD + +#ifdef SIM_CHORD +enum { + NBITS = 16, /* # bits of an ID */ + ID_LEN = NBITS / 8, /* bytes per ID */ + NFINGERS = NBITS, /* # fingers per node */ + NSUCCESSORS = 3, /* # successors kept */ + NPREDECESSORS = 3, /* # predecessors kep */ + BUFSIZE = 65535, /* buffer for packets */ + STABILIZE_PERIOD = 1 * 1000000, /* in usec */ + MAX_WELLKNOWN = 4, /* maximum number of "seed" servers */ + MAX_SIMJOIN = 4, /* maximum number of servers + * contacted simultaneously when joining + */ + PING_THRESH = 3, /* this many unanswered pings are allowed */ + DEF_TTL = 64, /* default TTL for multi-hop packets */ +}; +#else +enum { + NBITS = 160, /* # bits per ID, same as SHA-1 output */ + ID_LEN = NBITS / 8, /* bytes per ID */ + NFINGERS = NBITS, /* # fingers per node */ + NSUCCESSORS = 8, /* # successors kept */ + NPREDECESSORS = 3, /* # predecessors kept */ + STABILIZE_PERIOD = 1 * 1000000, /* in usec */ + BUFSIZE = 65535, /* buffer for packets */ + MAX_WELLKNOWN = 50, /* maximum number of other known servers + * (read from configuration file) + */ + MAX_SIMJOIN = 4, /* maximum number of servers + * contacted simultaneously when joining + */ + PING_THRESH = 5, /* this many unanswered pings are allowed */ + DEF_TTL = 64, /* default TTL for multi-hop packets */ +}; +#endif /* SIM_CHORD */ + +/* packet types */ +enum { + CHORD_ROUTE = 0, /* data packet */ + CHORD_ROUTE_LAST, + CHORD_FS, /* find_successor */ + CHORD_FS_REPL, /* find_successor reply */ + CHORD_STAB, /* get predecessor */ + CHORD_STAB_REPL, /* ... response */ + CHORD_NOTIFY, /* notify (predecessor) */ + CHORD_PING, /* are you alive? */ + CHORD_PONG, /* yes, I am */ + CHORD_FINGERS_GET, /* get your finger list */ + CHORD_FINGERS_REPL, /* .. here is my finger list */ + CHORD_TRACEROUTE, /* traceroute */ + CHORD_TRACEROUTE_LAST, + CHORD_TRACEROUTE_REPL, /* traceroute repl */ +}; + +/* XXX: warning: portability bugs */ +typedef uint8_t byte; +typedef unsigned char uchar; +#ifdef __APPLE__ +typedef u_long ulong; +#endif + +typedef struct { + byte x[ID_LEN]; +} chordID; + +#define KEY_LEN 20 +typedef struct { + char x[KEY_LEN]; +} Key; + +struct Node { + chordID id; + in_addr_t addr; + in_port_t port; +}; + +struct Finger { + Node node; /* ID and address of finger */ + int status; /* specifies whether this finger has been + * pinged; possible values: F_PASSIVE (the node + * has not been pinged) and F_ACTIVE (the node + * has been pinged) + */ + int npings; /* # of unanswered pings */ + long rtt_avg; /* average rtt to finger (ms in simulator, + * usec in the implementation) + */ + long rtt_dev; /* rtt's mean deviation (ms in simulator, + * usec in the implementation) + */ + /* rtt_avg, rtt_dev can be used to implement + * proximity routing or set up RTO for ping + */ + struct Finger *next; + struct Finger *prev; +}; + +/* Finger table contains NFINGERS fingers, then predecessor, then + * the successor list */ + +struct Server { + Node node; /* addr and ID */ + Finger * head_flist; /* head and tail of finger */ + Finger * tail_flist; /* table + pred + successors + */ + int to_fix_finger; /* next finger to be fixed */ + int to_fix_backup; /* next successor/predecessor to be fixed */ + int to_ping; /* next node in finger list to be refreshed */ + uint64_t next_stabilize_us; /* value of wall_time() at next stabilize */ + + int in_sock; /* incoming socket */ + int out_sock; /* outgoing socket */ +}; + +#define PRED(srv) (srv->tail_flist) +#define SUCC(srv) (srv->head_flist) + +/* GLOBALS */ +extern Node well_known[MAX_WELLKNOWN]; +extern int nknown; +#define MAX_KEY_NUM 20 +/* the keys in KeyArray are read from file acclist.txt, + * and are used to authenticate users sending control + * messages such as CHORD_FINGERS_GET. + * This mechanism is intended to prevent trivial DDoS attacks. + * + * (For now the keyes are sent and stored in clear so + * the security provided by this mechanism is quite weak) + */ +#define ACCLIST_FILE "acclist.txt" +extern Key KeyArray[MAX_KEY_NUM]; +extern int NumKeys; + +/* chord.c */ +extern void chord_main(char *conf_file, int parent_sock); +extern void initialize(Server *srv); +extern void handle_packet(int network); +extern int read_keys(char *file, Key *keyarray, int max_num_keys); + +/* finger.c */ +extern Finger *new_finger(Node *node); +extern Finger *succ_finger(Server *srv); +extern Finger *pred_finger(Server *srv); +extern Finger *closest_preceding_finger(Server *srv, chordID *id, int fall); +extern Node *closest_preceding_node(Server *srv, chordID *id, int fall); +extern void remove_finger(Server *srv, Finger *f); +extern Finger *get_finger(Server *srv, chordID *id); +extern Finger *insert_finger(Server *srv, chordID *id, + in_addr_t addr, in_port_t port, int *fnew); +void free_finger_list(Finger *flist); + +/* hosts.c */ +extern in_addr_t get_addr(void); /* get_addr: get IP address of server */ + +/* join.c */ +extern void join(Server *srv, FILE *fp); + +/* pack.c */ +extern int dispatch(Server *srv, int n, uchar *buf); + +extern int pack(uchar *buf, char *fmt, ...); +extern int unpack(uchar *buf, char *fmt, ...); +extern int sizeof_fmt(char *fmt); + +#ifdef CCURED +// These are the kinds of arguments that we pass to pack +struct pack_args { + int f1; + chordID *f2; +}; +#pragma ccuredvararg("pack", sizeof(struct pack_args)) +struct unpack_args { + ushort * f1; + uchar * f2; + ulong * f3; + chordID *id; +}; +#pragma ccuredvararg("unpack", sizeof(struct unpack_args)) +#endif + +extern int pack_data(uchar *buf, uchar type, byte ttl, + chordID *id, ushort len, uchar *data); +extern int unpack_data(Server *srv, int n, uchar *buf); +extern int pack_fs(uchar *buf, byte ttl, chordID *id, ulong addr, ushort port); +extern int unpack_fs(Server *srv, int n, uchar *buf); +extern int pack_fs_repl(uchar *buf, chordID *id, ulong addr, ushort port); +extern int unpack_fs_repl(Server *srv, int n, uchar *buf); +extern int pack_stab(uchar *buf, chordID *id, ulong addr, ushort port); +extern int unpack_stab(Server *srv, int n, uchar *buf); +extern int pack_stab_repl(uchar *buf, chordID *id, ulong addr, ushort port); +extern int unpack_stab_repl(Server *srv, int n, uchar *buf); +extern int pack_notify(uchar *buf, chordID *id, ulong addr, ushort port); +extern int unpack_notify(Server *srv, int n, uchar *buf); +int pack_ping(uchar *buf, chordID *id, ulong addr, ushort port, ulong time); +extern int unpack_ping(Server *srv, int n, uchar *buf); +extern int pack_pong(uchar *buf, chordID *id, + ulong addr, ushort port, ulong time); +extern int unpack_pong(Server *srv, int n, uchar *buf); +extern int pack_fingers_get(uchar *buf, ulong addr, ushort port, Key *key); +extern int unpack_fingers_get(Server *srv, int n, uchar *buf); +extern int pack_fingers_repl(uchar *buf, Server *srv); +extern int unpack_fingers_repl(Server *null, int n, uchar *buf); + +extern int pack_traceroute(uchar *buf, Server *srv, Finger *f, + uchar type, byte ttl, byte hops); +extern int unpack_traceroute(Server *srv, int n, uchar *buf); +extern int pack_traceroute_repl(uchar *buf, Server *srv, byte ttl, byte hops, + ulong *paddr, ushort *pport, int one_hop); +extern int unpack_traceroute_repl(Server *srv, int n, uchar *buf); + +/* process.c */ +extern int process_data(Server *srv, uchar type, byte ttl, chordID *id, + ushort len, uchar *data); +extern int process_fs(Server *srv, byte ttl, + chordID *id, ulong addr, ushort port); +extern int process_fs_repl(Server *srv, chordID *id, ulong addr, ushort port); +extern int process_stab(Server *srv, chordID *id, ulong addr, ushort port); +extern int process_stab_repl(Server *srv, chordID *id, + ulong addr, ushort port); +extern int process_notify(Server *srv, chordID *id, ulong addr, ushort port); +extern int process_ping(Server *srv, chordID *id, + ulong addr, ushort port, ulong time); +extern int process_pong(Server *srv, chordID *id, + ulong addr, ushort port, ulong time); +extern int process_fingers_get(Server *srv, ulong addr, ushort port, Key *key); +extern int process_fingers_repl(Server *srv, uchar ret_code); +extern int process_traceroute(Server *srv, chordID *id, char *buf, + uchar type, byte ttl, byte hops); +extern int process_traceroute_repl(Server *srv, char *buf, + byte ttl, byte hops); + +/* sendpkt.c */ +extern void send_raw(Server *srv, in_addr_t addr, in_port_t port, + int n, uchar *buf); +extern void send_data(Server *srv, uchar type, byte ttl, Node *np, + chordID *id, ushort n, uchar *data); +extern void send_fs(Server *srv, byte ttl, ulong to_addr, ushort to_port, + chordID *id, ulong addr, ushort port); +extern void send_fs_repl(Server *srv, ulong to_addr, ushort to_port, + chordID *id, ulong addr, ushort port); +extern void send_stab(Server *srv, ulong to_addr, ushort to_port, + chordID *id, ulong addr, ushort port); +extern void send_stab_repl(Server *srv, ulong to_addr, ushort to_port, + chordID *id, ulong addr, ushort port); +extern void send_notify(Server *srv, ulong to_addr, ushort to_port, + chordID *id, ulong addr, ushort port); +extern void send_ping(Server *srv, ulong to_addr, ushort to_port, + ulong addr, ushort port, ulong time); +extern void send_pong(Server *srv, ulong to_addr, ushort to_port, ulong time); +extern void send_fingers_get(Server *srv, ulong to_addr, ushort to_port, + ulong addr, ushort port, Key *key); +extern void send_fingers_repl(Server *srv, ulong to_addr, ushort to_port); +extern void send_traceroute(Server *srv, Finger *f, uchar *buf, + uchar type, byte ttl, byte hops); +extern void send_traceroute_repl(Server *srv, uchar *buf, int ttl, + int hops, int one_hop); + +/* stabilize.c */ +extern void stabilize(Server *srv); +extern void set_stabilize_timer(void); + +/* api.c */ +extern int chord_init(char *conf_file); +extern void chord_cleanup(int signum); +extern void chord_route(chordID *k, char *data, int len); +extern void chord_deliver(int n, uchar *data); +extern void chord_get_range(chordID *l, chordID *r); +void chord_update_range(chordID *l, chordID *r); +int chord_is_local(chordID *x); + +/* util.c */ +extern ulong get_current_time(void); +extern void update_rtt(long *rtt_avg, long *rtt_std, long new_rtt); +extern chordID rand_ID(void); +extern chordID successor(chordID id, int n); +extern chordID predecessor(chordID id, int n); +extern void add(chordID *a, chordID *b, chordID *res); +extern void subtract(chordID *a, chordID *b, chordID *res); +extern void random_between(chordID *a, chordID *b, chordID *res); +extern int msb(chordID *x); +extern int equals(chordID *a, chordID *b); +extern int equals_id_str(chordID *a, char *b); +extern int is_zero(chordID *x); +extern int is_between(chordID *x, chordID *a, chordID *b); +extern int copy_id( chordID *a, chordID *b); +extern void print_id(FILE *f, chordID *id); +extern chordID atoid(const char *str); +extern unsigned hash(chordID *id, unsigned n); +extern void print_chordID(chordID *id); +extern void print_two_chordIDs(char *preffix, chordID *id1, + char *middle, chordID *id2, + char *suffix); +extern void print_three_chordIDs(char *preffix, chordID *id1, + char *middle1, chordID *id2, + char *middle2, chordID *id3, + char *suffix); +extern void print_node(Node *node, char *prefix, char *suffix); +extern void print_finger(Finger *f, char *prefix, char *suffix); +extern void print_finger_list(Finger *fhead, char *prefix, char *suffix); +extern void print_server(Server *s, char *prefix, char *suffix); +extern void print_process(Server *srv, char *process_type, chordID *id, + ulong addr, ushort port); +extern void print_send(Server *srv, char *send_type, chordID *id, + ulong addr, ushort port); +extern void print_fun(Server *srv, char *fun_name, chordID *id); +void print_current_time(char *prefix, char *suffix); +extern int match_key(Key *key); + +#ifdef SIM_CHORD +void sim_send_raw(Server *srv, + in_addr_t addr, in_port_t port, int n, uchar *buf); +void sim_deliver_data(Server *srv, chordID *id, int n, uchar *data); +Server *get_random_server(int no_idx, int status); +int sim_chord_is_local(Server *srv, chordID *x); +double sim_get_time(void); +#endif + +#include "eprintf.h" + +#endif /* INCL_CHORD_H */ === modified file 'i3/chord/chord_api.h' --- i3/chord/chord_api.h 2009-12-11 22:49:11 +0000 +++ i3/chord/chord_api.h 2010-02-11 11:49:47 +0000 @@ -1,26 +1,26 @@ -#ifndef _CHORD_API_H -#define _CHORD_API_H - -typedef unsigned char byte; - -enum { - CHORD_ID_BITS = 160, -}; - -typedef struct { - byte x[CHORD_ID_BITS/8]; -} chordID; - -/* init: initialize chord server, provide configuration file */ -int chord_init(char *conf_file); - -/* route: forward message M towards the root of key K. */ -void chord_route(chordID *k, char *data, int len); - -/* get_range: returns the range (l,r] that this node is responsible for */ -void chord_get_range(chordID *l, chordID *r); - -/* is_local: Does this ID belong to this server? */ -int chord_is_local(chordID *x); - -#endif +#ifndef _CHORD_API_H +#define _CHORD_API_H + +typedef unsigned char byte; + +enum { + CHORD_ID_BITS = 160, +}; + +typedef struct { + byte x[CHORD_ID_BITS / 8]; +} chordID; + +/* init: initialize chord server, provide configuration file */ +int chord_init(char *conf_file); + +/* route: forward message M towards the root of key K. */ +void chord_route(chordID *k, char *data, int len); + +/* get_range: returns the range (l,r] that this node is responsible for */ +void chord_get_range(chordID *l, chordID *r); + +/* is_local: Does this ID belong to this server? */ +int chord_is_local(chordID *x); + +#endif === modified file 'i3/chord/chord_getfingers.c' --- i3/chord/chord_getfingers.c 2009-12-11 22:49:11 +0000 +++ i3/chord/chord_getfingers.c 2010-02-11 11:49:47 +0000 @@ -5,11 +5,11 @@ * node_IP_addr, port - IP address and the port number of a Chord node * -all - if this parameter is specified, the command displays * the information about each node in the system. Otherwise, it - * displays only the information about the Chord node whose + * displays only the information about the Chord node whose * address and port number are specified in the command line. * - * The node-related information includes its finger list. Associated - * to each finger, the command displays the mean value and standard + * The node-related information includes its finger list. Associated + * to each finger, the command displays the mean value and standard * deviation of the round-trip-time. * * Note: This command doesn't work behind NATs and firewalls. @@ -39,158 +39,168 @@ typedef struct iditem_ { - chordID id; - struct iditem_ *next; + chordID id; + struct iditem_ *next; } IDitem; -static int unpack_print_getnext(char *buf, int n, ulong *succ_addr, - ushort *succ_port); +static int unpack_print_getnext(char *buf, int n, ulong *succ_addr, + ushort *succ_port); static IDitem *add_chordID(IDitem *head, chordID *id); static int find_chordID(IDitem *head, chordID *id); -static int recv_packet(int in_sock, fd_set fdset, int nfds, - char *buf, int buf_len, - ulong chordsrv_addr, ulong chordsrv_port); +static int recv_packet(int in_sock, fd_set fdset, int nfds, + char *buf, int buf_len, + ulong chordsrv_addr, ulong chordsrv_port); -int main(int argc, char *argv[]) +int main(int argc, char *argv[]) { - Key key; - int in_sock, out_sock, len, rc; - int argc_idx = 0, flag_all = FALSE; - ulong chordsrv_addr, client_addr; - ushort chordsrv_port, client_port; - struct sockaddr_in chordsrv; - struct sockaddr_in sin, sout; - struct hostent *h; - fd_set fdset; - int nfds; - int retries = 0; - byte buf[BUFSIZE]; + Key key; + int in_sock, out_sock, len, rc; + int argc_idx = 0, flag_all = FALSE; + ulong chordsrv_addr, client_addr; + ushort chordsrv_port, client_port; + struct sockaddr_in chordsrv; + struct sockaddr_in sin, sout; + struct hostent *h; + fd_set fdset; + int nfds; + int retries = 0; + byte buf[BUFSIZE]; // chordID id; - /* check command line args */ - if(argc < 3) - eprintf("usage: %s [-all] <node_IP_addr> <port>\n", argv[0]); - - if (argc == 4) { - if (strcmp(argv[1], "-all")) { - eprintf("usage: %s [-all] <node_IP_addr> <port>\n", argv[0]); - } else { - argc_idx++; - flag_all = TRUE; - } - } - - /* i3 server address and port number */ - h = gethostbyname(argv[argc_idx+1]); - if(h==NULL) { - printf("%s: unknown host '%s' \n", argv[0], argv[argc_idx+1]); - exit(1); - } - assert(h->h_length == sizeof(long)); - memcpy((char *) &chordsrv_addr, h->h_addr_list[0], h->h_length); - chordsrv_addr = ntohl(chordsrv_addr); - chordsrv_port = (ushort)atoi(argv[argc_idx+2]); - - /* get client's address */ - client_addr = ntohl(get_addr()); - client_port = CLIENT_PORT; - - /* create socket to receieve packets */ - memset(&sin, 0, sizeof(sin)); - sin.sin_family = AF_INET; - sin.sin_port = htons(client_port); - sin.sin_addr.s_addr = htonl(INADDR_ANY); - - in_sock = socket(AF_INET, SOCK_DGRAM, 0); - if (in_sock < 0) - eprintf("incoming socket failed:"); - if (bind(in_sock, (struct sockaddr *) &sin, sizeof(sin)) < 0) - eprintf("bind to incoming socket failed:"); - - /* create outgoing socket */ // struct in_addr ia; - - memset(&sout, 0, sizeof(sout)); - sout.sin_family = AF_INET; - sout.sin_port = htons(0); - sout.sin_addr.s_addr = htonl(INADDR_ANY); - out_sock = socket(AF_INET, SOCK_DGRAM, 0); - if (out_sock < 0) - eprintf("outgoing socket failed:"); - if (bind(out_sock, (struct sockaddr *) &sout, sizeof(sout)) < 0) - eprintf("bind to outgoing socket failed:"); - - /* create CHORD_FINGERS_GET message */ - rc = read_keys(KEY_FILE, &key, 1); - if (rc < 1) { - close(in_sock);; + /* check command line args */ + if (argc < 3) { + eprintf("usage: %s [-all] <node_IP_addr> <port>\n", argv[0]); + } + + if (argc == 4) { + if (strcmp(argv[1], "-all")) { + eprintf("usage: %s [-all] <node_IP_addr> <port>\n", argv[0]); + } else { + argc_idx++; + flag_all = TRUE; + } + } + + /* i3 server address and port number */ + h = gethostbyname(argv[argc_idx + 1]); + if (h == NULL) { + printf("%s: unknown host '%s' \n", argv[0], argv[argc_idx + 1]); + exit(1); + } + assert(h->h_length == sizeof(long)); + memcpy((char *) &chordsrv_addr, h->h_addr_list[0], h->h_length); + chordsrv_addr = ntohl(chordsrv_addr); + chordsrv_port = (ushort) atoi(argv[argc_idx + 2]); + + /* get client's address */ + client_addr = ntohl(get_addr()); + client_port = CLIENT_PORT; + + /* create socket to receieve packets */ + memset(&sin, 0, sizeof(sin)); + sin.sin_family = AF_INET; + sin.sin_port = htons(client_port); + sin.sin_addr.s_addr = htonl(INADDR_ANY); + + in_sock = socket(AF_INET, SOCK_DGRAM, 0); + if (in_sock < 0) { + eprintf("incoming socket failed:"); + } + if (bind(in_sock, (struct sockaddr *) &sin, sizeof(sin)) < 0) { + eprintf("bind to incoming socket failed:"); + } + + /* create outgoing socket */ // struct in_addr ia; + + memset(&sout, 0, sizeof(sout)); + sout.sin_family = AF_INET; + sout.sin_port = htons(0); + sout.sin_addr.s_addr = htonl(INADDR_ANY); + out_sock = socket(AF_INET, SOCK_DGRAM, 0); + if (out_sock < 0) { + eprintf("outgoing socket failed:"); + } + if (bind(out_sock, (struct sockaddr *) &sout, sizeof(sout)) < 0) { + eprintf("bind to outgoing socket failed:"); + } + + /* create CHORD_FINGERS_GET message */ + rc = read_keys(KEY_FILE, &key, 1); + if (rc < 1) { + close(in_sock); + ; + close(out_sock); + if (rc == -1) { + eprintf("Error opening file: %s\n", KEY_FILE); + } + if (rc == 0) { + eprintf("No key found in %s\n", KEY_FILE); + } + } + + len = pack_fingers_get(buf, client_addr, client_port, &key); + + chordsrv.sin_family = h->h_addrtype; + chordsrv.sin_addr.s_addr = htonl(chordsrv_addr); + chordsrv.sin_port = htons(chordsrv_port); + + FD_ZERO(&fdset); + FD_SET(in_sock, &fdset); + nfds = in_sock + 1; + + for (;; ) { + /* send CHORD_FINGERS_GET request */ + len = pack_fingers_get(buf, client_addr, client_port, &key); + rc = sendto(out_sock, buf, len, 0, + (struct sockaddr *) &chordsrv, sizeof(chordsrv)); + if (rc < 0) { + eprintf("cannot send data, errno: %d \n", errno); + break; + } + len = recv_packet(in_sock, fdset, nfds, (char *) buf, sizeof(buf), + chordsrv_addr, chordsrv_port); + + /* len == -1 -> no answer; the chord node is either done, or + * the message has been lost, or the acclist.txt is missing + * at the chord node or it doesn't contain the proper key + */ + if (len == -1 && retries < MAX_RETRIES) { + retries++; + continue; + } + if (len == -1) { + /* no answer has been received from the chord node + * after MAX_RETRIES retries + */ + printf("... giving up...\n"); + printf("\nAlso, check whether file %s exists at the chord node,\n", + ACCLIST_FILE); + printf("and if does, check whether it contains the key in %s\n", + KEY_FILE); + printf("(see README for details).\n"); + break; + } + if (unpack_print_getnext((char *) buf, len, &chordsrv_addr, &chordsrv_port)) { + chordsrv.sin_addr.s_addr = htonl(chordsrv_addr); + chordsrv.sin_port = htons(chordsrv_port); + retries = 0; + if (flag_all == FALSE) { + break; + } + } else { + break; + } + } + + close(in_sock); + ; close(out_sock); - if (rc == -1) - eprintf("Error opening file: %s\n", KEY_FILE); - if (rc == 0) - eprintf("No key found in %s\n", KEY_FILE); - } - - len = pack_fingers_get(buf, client_addr, client_port, &key); - - chordsrv.sin_family = h->h_addrtype; - chordsrv.sin_addr.s_addr = htonl(chordsrv_addr); - chordsrv.sin_port = htons(chordsrv_port); - - FD_ZERO(&fdset); - FD_SET(in_sock, &fdset); - nfds = in_sock + 1; - - for (;;) { - /* send CHORD_FINGERS_GET request */ - len = pack_fingers_get(buf, client_addr, client_port, &key); - rc = sendto(out_sock, buf, len, 0, - (struct sockaddr *)&chordsrv, sizeof(chordsrv)); - if(rc < 0) { - eprintf("cannot send data, errno: %d \n", errno); - break; - } - len = recv_packet(in_sock, fdset, nfds, (char *)buf, sizeof(buf), - chordsrv_addr, chordsrv_port); - - /* len == -1 -> no answer; the chord node is either done, or - * the message has been lost, or the acclist.txt is missing - * at the chord node or it doesn't contain the proper key - */ - if (len == -1 && retries < MAX_RETRIES) { - retries++; - continue; - } - if (len == -1) { - /* no answer has been received from the chord node - * after MAX_RETRIES retries - */ - printf("... giving up...\n"); - printf("\nAlso, check whether file %s exists at the chord node,\n", - ACCLIST_FILE); - printf("and if does, check whether it contains the key in %s\n", - KEY_FILE); - printf("(see README for details).\n"); - break; - } - if (unpack_print_getnext((char *)buf, len, &chordsrv_addr, &chordsrv_port)) { - chordsrv.sin_addr.s_addr = htonl(chordsrv_addr); - chordsrv.sin_port = htons(chordsrv_port); - retries = 0; - if (flag_all == FALSE) - break; - } else - break; - } - - close(in_sock);; - close(out_sock); - printf("\n"); - - return 1; + printf("\n"); + + return 1; } - -/* this function unpacks the CHORD_FINGERS_REPL message +/* this function unpacks the CHORD_FINGERS_REPL message * and prints its content * * the function returns TRUE if the successor of the Chord node @@ -198,125 +208,128 @@ * the functions also returns the successor address and port * number in succ_addr and succ_port variables */ -static int unpack_print_getnext(char *buf, int n, - ulong *succ_addr, ushort *succ_port) +static int unpack_print_getnext(char *buf, int n, + ulong *succ_addr, ushort *succ_port) { - chordID id; - char type; - ulong addr, rtt_avg, rtt_dev; - ushort port, npings; - int len, i, ret_code; - struct in_addr ia; - static IDitem *head_list = NULL; - - len = unpack((uchar *)buf, "cxls", &type, &id, (ulong*)&addr, (ushort*)&port); - assert(type == CHORD_FINGERS_REPL); - - if (find_chordID(head_list, &id) == TRUE) { - return FALSE; - } else { - head_list = add_chordID(head_list, &id); - } - printf("\nID=("); print_chordID(&id); - ia.s_addr = htonl(addr); - printf("), addr=(%s:%d)\n", inet_ntoa(ia), port); - - if (len >= n-1) - return FALSE; - - i = 0; - do { - len += unpack((uchar*)(buf + len), "xlslls", &id, &addr, &port, - &rtt_avg, &rtt_dev, &npings); - - *succ_addr = addr; - *succ_port = port; - - printf(" F[%d]: ID=(", i++); print_chordID(&id); + chordID id; + char type; + ulong addr, rtt_avg, rtt_dev; + ushort port, npings; + int len, i, ret_code; + struct in_addr ia; + static IDitem *head_list = NULL; + + len = unpack((uchar *) buf, "cxls", &type, &id, (ulong *) &addr, (ushort *) &port); + assert(type == CHORD_FINGERS_REPL); + + if (find_chordID(head_list, &id) == TRUE) { + return FALSE; + } else { + head_list = add_chordID(head_list, &id); + } + printf("\nID=("); + print_chordID(&id); ia.s_addr = htonl(addr); printf("), addr=(%s:%d)\n", inet_ntoa(ia), port); - printf(" rtt_avg = %5.2f ms, rtt_stdev = %5.2f ms\n", - (float)rtt_avg/1000., (float)rtt_dev/1000.); - - } while (len + 1 < n); - - if (len+1 > n) - return FALSE; - - unpack((uchar*)(buf + len), "c", &ret_code); - return TRUE; + + if (len >= n - 1) { + return FALSE; + } + + i = 0; + do { + len += unpack((uchar *) (buf + len), "xlslls", &id, &addr, &port, + &rtt_avg, &rtt_dev, &npings); + + *succ_addr = addr; + *succ_port = port; + + printf(" F[%d]: ID=(", i++); + print_chordID(&id); + ia.s_addr = htonl(addr); + printf("), addr=(%s:%d)\n", inet_ntoa(ia), port); + printf(" rtt_avg = %5.2f ms, rtt_stdev = %5.2f ms\n", + (float) rtt_avg / 1000., (float) rtt_dev / 1000.); + } while (len + 1 < n); + + if (len + 1 > n) { + return FALSE; + } + + unpack((uchar *) (buf + len), "c", &ret_code); + return TRUE; } static IDitem *add_chordID(IDitem *head, chordID *id) { - IDitem *item; - - if ((item = calloc(1, sizeof(IDitem))) == NULL) { - eprintf("memory allocation error\n"); - } else - copy_id(&item->id, id); - - item->next = head; - return item; + IDitem *item; + + if ((item = calloc(1, sizeof(IDitem))) == NULL) { + eprintf("memory allocation error\n"); + } else { + copy_id(&item->id, id); + } + + item->next = head; + return item; } - -/* search a chord ID in the list; use linear search +/* search a chord ID in the list; use linear search * for now--should change it later... */ static int find_chordID(IDitem *head, chordID *id) { - IDitem *item = head; + IDitem *item = head; - for (; item; item = item->next) { - if (equals(&item->id, id)) - return TRUE; - } - return FALSE; + for (; item; item = item->next) { + if (equals(&item->id, id)) { + return TRUE; + } + } + return FALSE; } - -static int recv_packet(int in_sock, fd_set fdset, int nfds, - char *buf, int buf_len, - ulong chordsrv_addr, ulong chordsrv_port) +static int recv_packet(int in_sock, fd_set fdset, int nfds, + char *buf, int buf_len, + ulong chordsrv_addr, ulong chordsrv_port) { - fd_set readset; - int nfound, from_len, len; - struct timeval timeout; - struct sockaddr_in from; - - for (;;) { - readset = fdset; - /* set a timeout in case we cannot contact the Chord node */ - timeout.tv_sec = SELECT_TIMEOUT; - timeout.tv_usec = 0; - nfound = select(nfds, &readset, NULL, NULL, &timeout); - - if (nfound < 0 && errno == EINTR) { - continue; - } - if (nfound == 0) { - /* timeout expired */ - struct in_addr ia; - ia.s_addr = htonl(chordsrv_addr); - printf("\nCouldn't contact node (%s:%d), try again...\n", - inet_ntoa(ia), (int)chordsrv_port); - return -1; - } - if (FD_ISSET(in_sock, &readset)) { - /* this is the reply from the Chord node */ - from_len = sizeof(from); - len = recvfrom(in_sock, buf, buf_len, 0, - (struct sockaddr *)&from, (uint*)&from_len); - if (len < 0) { - if (errno != EAGAIN) { - printf("recvfrom failed."); - continue; - } - weprintf("try again..."); - continue; - } - return len; - } - } + fd_set readset; + int nfound, from_len, len; + struct timeval timeout; + struct sockaddr_in from; + + for (;; ) { + readset = fdset; + /* set a timeout in case we cannot contact the Chord node */ + timeout.tv_sec = SELECT_TIMEOUT; + timeout.tv_usec = 0; + nfound = select(nfds, &readset, NULL, NULL, &timeout); + + if (nfound < 0 && errno == EINTR) { + continue; + } + if (nfound == 0) { + /* timeout expired */ + struct in_addr ia; + ia.s_addr = htonl(chordsrv_addr); + printf("\nCouldn't contact node (%s:%d), try again...\n", + inet_ntoa(ia), (int) chordsrv_port); + return -1; + } + if (FD_ISSET(in_sock, &readset)) { + /* this is the reply from the Chord node */ + from_len = sizeof(from); + len = recvfrom(in_sock, buf, buf_len, 0, + (struct sockaddr *) &from, (uint *) &from_len); + if (len < 0) { + if (errno != EAGAIN) { + printf("recvfrom failed."); + continue; + } + weprintf("try again..."); + continue; + } + return len; + } + } } === modified file 'i3/chord/chord_traceroute.c' --- i3/chord/chord_traceroute.c 2009-12-11 22:49:11 +0000 +++ i3/chord/chord_traceroute.c 2010-02-11 11:49:47 +0000 @@ -6,9 +6,9 @@ * node_IP_addr, port - IP address and the port number of a Chord node * from where we originate the traceroute * - * This command dispalys the chord route to the node that is + * This command dispalys the chord route to the node that is * responsibe for target ID (id) starting from the originator node. - * + * * Note: This command doesn't work behind NATs and firewalls. */ @@ -36,158 +36,165 @@ typedef struct iditem_ { - chordID id; - struct iditem_ *next; + chordID id; + struct iditem_ *next; } IDitem; -/*static int unpack_print_getnext(char *buf, int n, ulong *succ_addr, - ushort *succ_port);*/ +/*static int unpack_print_getnext(char *buf, int n, ulong *succ_addr, + * ushort *succ_port);*/ /*static IDitem *add_chordID(IDitem *head, chordID *id);*/ /*static int find_chordID(IDitem *head, chordID *id);*/ -static int recv_packet(int in_sock, fd_set fdset, int nfds, - char *buf, int buf_len, - ulong chordsrv_addr, ulong chordsrv_port); -static int pack_client_traceroute(uchar *buf, byte ttl, chordID *id, - ulong client_addr, ushort client_port); +static int recv_packet(int in_sock, fd_set fdset, int nfds, + char *buf, int buf_len, + ulong chordsrv_addr, ulong chordsrv_port); +static int pack_client_traceroute(uchar *buf, byte ttl, chordID *id, + ulong client_addr, ushort client_port); static int unpack_client_traceroute_repl(char *buf, int n, int orig_ttl, - ulong chordsrv_addr, - ushort chordsrv_port); + ulong chordsrv_addr, + ushort chordsrv_port); -int main(int argc, char *argv[]) +int main(int argc, char *argv[]) { - Key key; - int in_sock, out_sock, len, rc; - ulong chordsrv_addr, client_addr; - ushort chordsrv_port, client_port; - struct sockaddr_in chordsrv; - struct sockaddr_in sin, sout; - struct hostent *h; - uchar ttl = 1; - fd_set fdset; - int nfds, i; - int retries = 0; - byte buf[BUFSIZE]; - chordID id; - - /* check command line args */ - if (argc != 4) - eprintf("usage: %s <id> <node_IP_addr> <port>\n", argv[0]); - - for (i = 0; i < ID_LEN; i++) { - char tmp[3]; + Key key; + int in_sock, out_sock, len, rc; + ulong chordsrv_addr, client_addr; + ushort chordsrv_port, client_port; + struct sockaddr_in chordsrv; + struct sockaddr_in sin, sout; + struct hostent *h; + uchar ttl = 1; + fd_set fdset; + int nfds, i; + int retries = 0; + byte buf[BUFSIZE]; + chordID id; + + /* check command line args */ + if (argc != 4) { + eprintf("usage: %s <id> <node_IP_addr> <port>\n", argv[0]); + } + + for (i = 0; i < ID_LEN; i++) { + char tmp[3]; // char t; - tmp[0] = argv[1][2*i]; - tmp[1] = argv[1][2*i+1]; - tmp[2] = 0; - sscanf(tmp, "%x", (uint *)&id.x[i]); - } - - /* chord server address and port number */ - h = gethostbyname(argv[2]); - if(h==NULL) { - printf("%s: unknown host '%s' \n", argv[0], argv[2]); - exit(1); - } - assert(h->h_length == sizeof(long)); - memcpy((char *) &chordsrv_addr, h->h_addr_list[0], h->h_length); - chordsrv_addr = ntohl(chordsrv_addr); - chordsrv_port = (ushort)atoi(argv[3]); - - /* get client's address */ - client_addr = ntohl(get_addr()); - client_port = CLIENT_PORT; - - /* create socket to receieve packets */ - memset(&sin, 0, sizeof(sin)); - sin.sin_family = AF_INET; - sin.sin_port = htons(client_port); - sin.sin_addr.s_addr = htonl(INADDR_ANY); - - in_sock = socket(AF_INET, SOCK_DGRAM, 0); - if (in_sock < 0) - eprintf("incoming socket failed:"); - if (bind(in_sock, (struct sockaddr *) &sin, sizeof(sin)) < 0) - eprintf("bind to incoming socket failed:"); - - /* create outgoing socket */ // struct in_addr ia; - - memset(&sout, 0, sizeof(sout)); - sout.sin_family = AF_INET; - sout.sin_port = htons(0); - sout.sin_addr.s_addr = htonl(INADDR_ANY); - out_sock = socket(AF_INET, SOCK_DGRAM, 0); - if (out_sock < 0) - eprintf("outgoing socket failed:"); - if (bind(out_sock, (struct sockaddr *) &sout, sizeof(sout)) < 0) - eprintf("bind to outgoing socket failed:"); - - - /* create CHORD_FINGERS_GET message */ - rc = read_keys(KEY_FILE, &key, 1); - if (rc < 1) { - close(in_sock);; + tmp[0] = argv[1][2 * i]; + tmp[1] = argv[1][2 * i + 1]; + tmp[2] = 0; + sscanf(tmp, "%x", (uint *) &id.x[i]); + } + + /* chord server address and port number */ + h = gethostbyname(argv[2]); + if (h == NULL) { + printf("%s: unknown host '%s' \n", argv[0], argv[2]); + exit(1); + } + assert(h->h_length == sizeof(long)); + memcpy((char *) &chordsrv_addr, h->h_addr_list[0], h->h_length); + chordsrv_addr = ntohl(chordsrv_addr); + chordsrv_port = (ushort) atoi(argv[3]); + + /* get client's address */ + client_addr = ntohl(get_addr()); + client_port = CLIENT_PORT; + + /* create socket to receieve packets */ + memset(&sin, 0, sizeof(sin)); + sin.sin_family = AF_INET; + sin.sin_port = htons(client_port); + sin.sin_addr.s_addr = htonl(INADDR_ANY); + + in_sock = socket(AF_INET, SOCK_DGRAM, 0); + if (in_sock < 0) { + eprintf("incoming socket failed:"); + } + if (bind(in_sock, (struct sockaddr *) &sin, sizeof(sin)) < 0) { + eprintf("bind to incoming socket failed:"); + } + + /* create outgoing socket */ // struct in_addr ia; + + memset(&sout, 0, sizeof(sout)); + sout.sin_family = AF_INET; + sout.sin_port = htons(0); + sout.sin_addr.s_addr = htonl(INADDR_ANY); + out_sock = socket(AF_INET, SOCK_DGRAM, 0); + if (out_sock < 0) { + eprintf("outgoing socket failed:"); + } + if (bind(out_sock, (struct sockaddr *) &sout, sizeof(sout)) < 0) { + eprintf("bind to outgoing socket failed:"); + } + + + /* create CHORD_FINGERS_GET message */ + rc = read_keys(KEY_FILE, &key, 1); + if (rc < 1) { + close(in_sock); + ; + close(out_sock); + if (rc == -1) { + eprintf("Error opening file: %s\n", KEY_FILE); + } + if (rc == 0) { + eprintf("No key found in %s\n", KEY_FILE); + } + } + len = pack_fingers_get(buf, client_addr, client_port, &key); + + chordsrv.sin_family = h->h_addrtype; + chordsrv.sin_addr.s_addr = htonl(chordsrv_addr); + chordsrv.sin_port = htons(chordsrv_port); + + FD_ZERO(&fdset); + FD_SET(in_sock, &fdset); + nfds = in_sock + 1; + + for (;; ) { + /* send CHORD_FINGERS_GET request */ + len = pack_client_traceroute(buf, ttl, &id, client_addr, client_port); + rc = sendto(out_sock, buf, len, 0, + (struct sockaddr *) &chordsrv, sizeof(chordsrv)); + if (rc < 0) { + printf("cannot send data, errno: %d \n", errno); + return -1; + } + + len = recv_packet(in_sock, fdset, nfds, (char *) buf, sizeof(buf), + chordsrv_addr, chordsrv_port); + + if (len == -1 && retries < MAX_RETRIES) { + retries++; + continue; + } + if (len == -1 || + (!unpack_client_traceroute_repl((char *) buf, len, ttl, + chordsrv_addr, chordsrv_port))) { + if (len == -1) { + printf("... giving up...\n"); + printf("\nAlso, check whether file %s exists at the chord node,\n", + ACCLIST_FILE); + printf("and if does, check whether it contains the key in %s\n", + KEY_FILE); + printf("(see README for details).\n"); + } + break; + } else { + retries = 0; + ttl++; + } + } + + close(in_sock); + ; close(out_sock); - if (rc == -1) - eprintf("Error opening file: %s\n", KEY_FILE); - if (rc == 0) - eprintf("No key found in %s\n", KEY_FILE); - } - len = pack_fingers_get(buf, client_addr, client_port, &key); - - chordsrv.sin_family = h->h_addrtype; - chordsrv.sin_addr.s_addr = htonl(chordsrv_addr); - chordsrv.sin_port = htons(chordsrv_port); - - FD_ZERO(&fdset); - FD_SET(in_sock, &fdset); - nfds = in_sock + 1; - - for (;;) { - /* send CHORD_FINGERS_GET request */ - len = pack_client_traceroute(buf, ttl, &id, client_addr, client_port); - rc = sendto(out_sock, buf, len, 0, - (struct sockaddr *)&chordsrv, sizeof(chordsrv)); - if(rc < 0) { - printf("cannot send data, errno: %d \n", errno); - return -1; - } - - len = recv_packet(in_sock, fdset, nfds, (char*)buf, sizeof(buf), - chordsrv_addr, chordsrv_port); - - if (len == -1 && retries < MAX_RETRIES) { - retries++; - continue; - } - if (len == -1 || - (!unpack_client_traceroute_repl((char*)buf, len, ttl, - chordsrv_addr, chordsrv_port))) { - if (len == -1) { - printf("... giving up...\n"); - printf("\nAlso, check whether file %s exists at the chord node,\n", - ACCLIST_FILE); - printf("and if does, check whether it contains the key in %s\n", - KEY_FILE); - printf("(see README for details).\n"); - } - break; - } - else { - retries = 0; - ttl++; - } - } - - close(in_sock);; - close(out_sock); - printf("\n"); - - return 1; + printf("\n"); + + return 1; } - -/* this function unpacks the CHORD_FINGERS_REPL message +/* this function unpacks the CHORD_FINGERS_REPL message * and prints its content * * the function returns TRUE if the successor of the Chord node @@ -196,137 +203,137 @@ * number in succ_addr and succ_port variables */ static int unpack_client_traceroute_repl(char *buf, int n, int orig_ttl, - ulong chordsrv_addr, - ushort chordsrv_port) + ulong chordsrv_addr, + ushort chordsrv_port) { - chordID id; - char type; - ulong addr; - ushort port; - ulong rtt_avg, rtt_dev; - int len; - uchar ttl, hops; - struct in_addr ia; - - len = unpack((uchar*)buf, "cccx", &type, &ttl, &hops, &id); - - assert(type == CHORD_TRACEROUTE_REPL); - - if (orig_ttl == 1) { + chordID id; + char type; + ulong addr; + ushort port; + ulong rtt_avg, rtt_dev; + int len; + uchar ttl, hops; + struct in_addr ia; + + len = unpack((uchar *) buf, "cccx", &type, &ttl, &hops, &id); + + assert(type == CHORD_TRACEROUTE_REPL); + + if (orig_ttl == 1) { + /* print the last link of the traceroute path */ + len += unpack((uchar *) (buf + len), "xls", &id, &addr, &port); + + printf("First hop: ("); + print_chordID(&id); + ia.s_addr = htonl(addr); + printf("), (%s:%d))\n", inet_ntoa(ia), port); + return TRUE; + } + + if (ttl) { + /* the last hop has been already returned in the previous call */ + return FALSE; + } + /* print the last link of the traceroute path */ - len += unpack((uchar *)(buf + len), "xls", &id, &addr, &port); - - printf("First hop: ("); + len += unpack((uchar *) (buf + len), "xlsll", &id, &addr, &port, &rtt_avg, &rtt_dev); + + printf("\n("); + print_chordID(&id); + ia.s_addr = htonl(addr); + printf("), (%s:%d)) --> \n", inet_ntoa(ia), port); + + len += unpack((uchar *) (buf + len), "xls", &id, &addr, &port); + printf(" ("); print_chordID(&id); ia.s_addr = htonl(addr); printf("), (%s:%d))\n", inet_ntoa(ia), port); + + printf(" rtt_avg = %5.2f ms, rtt_stdev = %5.2f ms\n", + (float) rtt_avg / 1000., (float) rtt_dev / 1000.); return TRUE; - } - - if (ttl) - /* the last hop has been already returned in the previous call */ - return FALSE; - - /* print the last link of the traceroute path */ - len += unpack((uchar*)(buf + len), "xlsll", &id, &addr, &port, &rtt_avg, &rtt_dev); - - printf("\n("); - print_chordID(&id); - ia.s_addr = htonl(addr); - printf("), (%s:%d)) --> \n", inet_ntoa(ia), port); - - len += unpack((uchar*)(buf + len), "xls", &id, &addr, &port); - printf(" ("); - print_chordID(&id); - ia.s_addr = htonl(addr); - printf("), (%s:%d))\n", inet_ntoa(ia), port); - - printf(" rtt_avg = %5.2f ms, rtt_stdev = %5.2f ms\n", - (float)rtt_avg/1000., (float)rtt_dev/1000.); - return TRUE; } -static int recv_packet(int in_sock, fd_set fdset, int nfds, - char *buf, int buf_len, - ulong chordsrv_addr, ulong chordsrv_port) +static int recv_packet(int in_sock, fd_set fdset, int nfds, + char *buf, int buf_len, + ulong chordsrv_addr, ulong chordsrv_port) { - fd_set readset; - int nfound, from_len, len; - struct timeval timeout; - struct sockaddr_in from; - - for (;;) { - readset = fdset; - /* set a timeout in case we cannot contact the Chord node */ - timeout.tv_sec = SELECT_TIMEOUT; - timeout.tv_usec = 0; - nfound = select(nfds, &readset, NULL, NULL, &timeout); - - if (nfound < 0 && errno == EINTR) { - continue; - } - if (nfound == 0) { - /* timeout expired */ - struct in_addr ia; - ia.s_addr = htonl(chordsrv_addr); - printf("\nCouldn't contact node (%s:%d), try again...\n", - inet_ntoa(ia), (int)chordsrv_port); - return -1; - } - if (FD_ISSET(in_sock, &readset)) { - /* this is the reply from the Chord node */ - from_len = sizeof(from); - len = recvfrom(in_sock, buf, buf_len, 0, - (struct sockaddr *)&from, (uint*)&from_len); - if (len < 0) { - if (errno != EAGAIN) { - printf("recvfrom failed; "); - continue; - } - weprintf("try again..."); - continue; - } - return len; - } - } + fd_set readset; + int nfound, from_len, len; + struct timeval timeout; + struct sockaddr_in from; + + for (;; ) { + readset = fdset; + /* set a timeout in case we cannot contact the Chord node */ + timeout.tv_sec = SELECT_TIMEOUT; + timeout.tv_usec = 0; + nfound = select(nfds, &readset, NULL, NULL, &timeout); + + if (nfound < 0 && errno == EINTR) { + continue; + } + if (nfound == 0) { + /* timeout expired */ + struct in_addr ia; + ia.s_addr = htonl(chordsrv_addr); + printf("\nCouldn't contact node (%s:%d), try again...\n", + inet_ntoa(ia), (int) chordsrv_port); + return -1; + } + if (FD_ISSET(in_sock, &readset)) { + /* this is the reply from the Chord node */ + from_len = sizeof(from); + len = recvfrom(in_sock, buf, buf_len, 0, + (struct sockaddr *) &from, (uint *) &from_len); + if (len < 0) { + if (errno != EAGAIN) { + printf("recvfrom failed; "); + continue; + } + weprintf("try again..."); + continue; + } + return len; + } + } } - /**********************************************************************/ /* pack_client_traceroute: pack traceroute packet */ -/* +/* * traceroute packet format: - * char pkt_type; - * char ttl; time to live, decremented at every hop. + * char pkt_type; + * char ttl; time to live, decremented at every hop. * When ttl reaches 0, a traceroute_repl packet is returned. * char hops; number of hops up to the current node (not including the - * client). hops is inceremented at every hop along the - * forward path. hops should be initialized to 0 by the clients. + * client). hops is inceremented at every hop along the + * forward path. hops should be initialized to 0 by the clients. * ID target_id; target ID for traceroute. - * Node prev_node; previous node (ie., the node which forwarded the packet) + * Node prev_node; previous node (ie., the node which forwarded the packet) * ulong rtt; rtt... - * ulong dev; ... and std dev frm previous node to this node (in usec) + * ulong dev; ... and std dev frm previous node to this node (in usec) * Node crt_node; this node - * (list of addresses/ports of the nodes along the traceroute path + * (list of addresses/ports of the nodes along the traceroute path * up to this node) - * ulong addr; address... + * ulong addr; address... * ushort port; ... and port number of the client * .... */ -static int pack_client_traceroute(uchar *buf, uchar ttl, chordID *id, - ulong client_addr, ushort client_port) +static int pack_client_traceroute(uchar *buf, uchar ttl, chordID *id, + ulong client_addr, ushort client_port) { - int n = 0; - - /* pack type, ttl, hops, and target id fields */ - n = pack(buf+n, "cccx", CHORD_TRACEROUTE, ttl, 0, id); - - /* skip prev node and next node fields */ - n += sizeof_fmt("xlsllxls"); - - /* add client's address to the list of addresses .. */ - n += pack(buf+n, "ls", client_addr, client_port); - - return n; + int n = 0; + + /* pack type, ttl, hops, and target id fields */ + n = pack(buf + n, "cccx", CHORD_TRACEROUTE, ttl, 0, id); + + /* skip prev node and next node fields */ + n += sizeof_fmt("xlsllxls"); + + /* add client's address to the list of addresses .. */ + n += pack(buf + n, "ls", client_addr, client_port); + + return n; } === modified file 'i3/chord/debug.h' --- i3/chord/debug.h 2009-12-11 22:49:11 +0000 +++ i3/chord/debug.h 2010-02-11 11:49:47 +0000 @@ -1,16 +1,16 @@ -/*************************************************************************** - debug.h - description - ------------------- - begin : Mon Oct 2 2003 - copyright : (C) 2003 by ion - email : istoica@xxxxxxxxxxxxxxx - ***************************************************************************/ - -#ifndef CHORD_DEBUG_H -#define CHORD_DEBUG_H - -#define CHORD_DEBUG_LEVEL 3 - -#define CHORD_DEBUG(level, x) if (level <= CHORD_DEBUG_LEVEL) x; - -#endif +/*************************************************************************** +* debug.h - description +* ------------------- +* begin : Mon Oct 2 2003 +* copyright : (C) 2003 by ion +* email : istoica@xxxxxxxxxxxxxxx +***************************************************************************/ + +#ifndef CHORD_DEBUG_H +#define CHORD_DEBUG_H + +#define CHORD_DEBUG_LEVEL 3 + +#define CHORD_DEBUG(level, x) if (level <= CHORD_DEBUG_LEVEL) {x; } + +#endif === modified file 'i3/chord/eprintf.c' --- i3/chord/eprintf.c 2009-12-11 22:49:11 +0000 +++ i3/chord/eprintf.c 2010-02-11 11:49:47 +0000 @@ -1,108 +1,117 @@ -/* Copyright (C) 1999 Lucent Technologies */ -/* Excerpted from 'The Practice of Programming' */ -/* by Brian W. Kernighan and Rob Pike */ - -#include <stdio.h> -#include <stdlib.h> -#include <stdarg.h> -#include <string.h> -#include <errno.h> -#include "eprintf.h" - -/* eprintf: print error message and exit */ -void eprintf(char *fmt, ...) -{ - va_list args; - - fflush(stdout); - if (getprogname() != NULL) - fprintf(stderr, "%s: ", getprogname()); - - va_start(args, fmt); - vfprintf(stderr, fmt, args); - va_end(args); - - if (fmt[0] != '\0' && fmt[strlen(fmt)-1] == ':') - fprintf(stderr, " %s", strerror(errno)); - fprintf(stderr, "\n"); - exit(2); /* conventional value for failed execution */ -} - -/* weprintf: print warning message */ -void weprintf(char *fmt, ...) -{ - va_list args; - - fflush(stdout); - fprintf(stderr, "warning: "); - if (getprogname() != NULL) - fprintf(stderr, "%s: ", getprogname()); - va_start(args, fmt); - vfprintf(stderr, fmt, args); - va_end(args); - if (fmt[0] != '\0' && fmt[strlen(fmt)-1] == ':') - fprintf(stderr, " %s\n", strerror(errno)); - else - fprintf(stderr, "\n"); -} - -/* emalloc: malloc and report if error */ -void *emalloc(size_t n) -{ - void *p; - - p = malloc(n); - if (p == NULL) - eprintf("malloc of %u bytes failed:", n); - return p; -} - -/* erealloc: realloc and report if error */ -void *erealloc(void *vp, size_t n) -{ - void *p; - - p = realloc(vp, n); - if (p == NULL) - eprintf("realloc of %u bytes failed:", n); - return p; -} - -/* ecalloc: calloc and report if error */ -void *ecalloc(size_t n, size_t w) -{ - void *p; - - p = calloc(n, w); - if (p == NULL) - eprintf("calloc of %u x %u bytes failed:", n, w); - return p; -} - -/* estrdup: duplicate a string, report if error */ -char *estrdup(char *s) -{ - char *t; - - t = (char *) malloc(strlen(s)+1); - if (t == NULL) - eprintf("estrdup(\"%.20s\") failed:", s); - strcpy(t, s); - return t; -} - -#ifndef __APPLE__ -static const char *progname; - -/* setprogname: set name of program */ -void setprogname(const char *name) -{ - progname = name; -} - -/* getprogname: return name of program */ -const char *getprogname(void) -{ - return progname; -} -#endif +/* Copyright (C) 1999 Lucent Technologies */ +/* Excerpted from 'The Practice of Programming' */ +/* by Brian W. Kernighan and Rob Pike */ + +#include <stdio.h> +#include <stdlib.h> +#include <stdarg.h> +#include <string.h> +#include <errno.h> +#include "eprintf.h" + +/* eprintf: print error message and exit */ +void eprintf(char *fmt, ...) +{ + va_list args; + + fflush(stdout); + if (getprogname() != NULL) { + fprintf(stderr, "%s: ", getprogname()); + } + + va_start(args, fmt); + vfprintf(stderr, fmt, args); + va_end(args); + + if (fmt[0] != '\0' && fmt[strlen(fmt) - 1] == ':') { + fprintf(stderr, " %s", strerror(errno)); + } + fprintf(stderr, "\n"); + exit(2); /* conventional value for failed execution */ +} + +/* weprintf: print warning message */ +void weprintf(char *fmt, ...) +{ + va_list args; + + fflush(stdout); + fprintf(stderr, "warning: "); + if (getprogname() != NULL) { + fprintf(stderr, "%s: ", getprogname()); + } + va_start(args, fmt); + vfprintf(stderr, fmt, args); + va_end(args); + if (fmt[0] != '\0' && fmt[strlen(fmt) - 1] == ':') { + fprintf(stderr, " %s\n", strerror(errno)); + } else { + fprintf(stderr, "\n"); + } +} + +/* emalloc: malloc and report if error */ +void *emalloc(size_t n) +{ + void *p; + + p = malloc(n); + if (p == NULL) { + eprintf("malloc of %u bytes failed:", n); + } + return p; +} + +/* erealloc: realloc and report if error */ +void *erealloc(void *vp, size_t n) +{ + void *p; + + p = realloc(vp, n); + if (p == NULL) { + eprintf("realloc of %u bytes failed:", n); + } + return p; +} + +/* ecalloc: calloc and report if error */ +void *ecalloc(size_t n, size_t w) +{ + void *p; + + p = calloc(n, w); + if (p == NULL) { + eprintf("calloc of %u x %u bytes failed:", n, w); + } + return p; +} + +/* estrdup: duplicate a string, report if error */ +char *estrdup(char *s) +{ + char *t; + + t = (char *) malloc(strlen(s) + 1); + if (t == NULL) { + eprintf("estrdup(\"%.20s\") failed:", s); + } + strcpy(t, s); + return t; +} + +#ifndef __APPLE__ +static const char *progname; + +/* setprogname: set name of program */ +void setprogname(const char *name) +{ + progname = name; +} + +/* getprogname: return name of program */ +const char *getprogname(void) +{ + return progname; +} + +#endif === modified file 'i3/chord/eprintf.h' --- i3/chord/eprintf.h 2009-12-11 22:49:11 +0000 +++ i3/chord/eprintf.h 2010-02-11 11:49:47 +0000 @@ -1,17 +1,17 @@ -/* Copyright (C) 1999 Lucent Technologies */ -/* Excerpted from 'The Practice of Programming' */ -/* by Brian W. Kernighan and Rob Pike */ - -/* eprintf.h: error wrapper functions */ -extern void eprintf(char *, ...); -extern void weprintf(char *, ...); -#ifdef CCURED -#pragma ccuredvararg("eprintf", printf(1)) -#pragma ccuredvararg("weprintf", printf(1)) -#endif -extern char *estrdup(char *); -extern void *emalloc(size_t); -extern void *erealloc(void *, size_t); -extern void *ecalloc(size_t, size_t); -extern void setprogname(const char *); -extern const char* getprogname(void); +/* Copyright (C) 1999 Lucent Technologies */ +/* Excerpted from 'The Practice of Programming' */ +/* by Brian W. Kernighan and Rob Pike */ + +/* eprintf.h: error wrapper functions */ +extern void eprintf(char *, ...); +extern void weprintf(char *, ...); +#ifdef CCURED +#pragma ccuredvararg("eprintf", printf(1)) +#pragma ccuredvararg("weprintf", printf(1)) +#endif +extern char *estrdup(char *); +extern void *emalloc(size_t); +extern void *erealloc(void *, size_t); +extern void *ecalloc(size_t, size_t); +extern void setprogname(const char *); +extern const char *getprogname(void); === modified file 'i3/chord/finger.c' --- i3/chord/finger.c 2009-12-11 22:49:11 +0000 +++ i3/chord/finger.c 2010-02-11 11:49:47 +0000 @@ -1,202 +1,211 @@ -#include <stdlib.h> -#include <assert.h> -#include "chord.h" - -/* new_finger: allocate and initialize finger structure */ -Finger *new_finger(Node *node) -{ - Finger *fp; - - /* allocate space for new finger */ - fp = emalloc(sizeof(Finger)); - fp->node = *node; - fp->status = F_PASSIVE; - fp->npings = 0; - fp->next = fp->prev = NULL; - fp->rtt_avg = fp->rtt_dev = 0; - return fp; -} - -/**********************************************************************/ - -Finger *succ_finger(Server *srv) -{ - Finger *f; - - for (f = srv->head_flist; f; f = f->next) { - if (f->status == F_ACTIVE) - return f; - } - return NULL; -} - -/**********************************************************************/ - -Finger *pred_finger(Server *srv) -{ - Finger *f; - - for (f = srv->tail_flist; f; f = f->prev) { - if (f->status == F_ACTIVE) - return f; - } - - return NULL; -} - -/**********************************************************************/ - -/* closest_preceding_node: search table for highest predecessor of id */ -/* closest_preceding_finger: search table for highest predecessor of id */ - -Finger *closest_preceding_finger(Server *srv, chordID *id, int fall) -{ - Finger *f; - - for (f = srv->tail_flist; f; f = f->prev) { - /* look only for active fingers; we do not know if we can - * reach the passive fingers - */ - if ((fall == TRUE) || (f->status == F_ACTIVE)) { - if (is_between(&f->node.id, &srv->node.id, id)) - return f; - } - } - - return NULL; -} - -Node *closest_preceding_node(Server *srv, chordID *id, int fall) -{ - Finger *f = closest_preceding_finger(srv, id, fall); - - if (f == NULL) - return &(srv->node); - else - return &(f->node); -} - -/**********************************************************************/ - -Finger *get_finger(Server *srv, chordID *id) -{ - Finger *f; - - for (f = srv->head_flist; f; f = f->next) - if (equals(id, &f->node.id)) - return f; - return NULL; -} - -/**********************************************************************/ - -Finger *insert_finger(Server *srv, chordID *id, - in_addr_t addr, in_port_t port, int *fnew) -{ - Finger *f, *new_f, *pred; - Node n; - - assert((srv->node.addr != addr) || (srv->node.port != port)); - pred = PRED(srv); - - f = get_finger(srv, id); - - if (f) { - if (f->node.addr != addr) { - f->node.addr = addr; - f->node.port = port; - f->rtt_avg = f->rtt_dev = 0; - f->npings = 0; - } - /* f is already in the list. In this case, - * f is not refreshed, i.e., f->npings is not set to 0. - * Refreshing f here might preclude the ping procedeure from removing - * f when it dies. - */ - CHORD_DEBUG(5, print_server(srv, "[insert_finger(1)]", "end")); - *fnew = FALSE; - return f; - } - - n.id = *id; n.addr = addr; n.port = port; - new_f = new_finger(&n); - - f = srv->head_flist; - if (f == NULL) { - /* this is the first finger */ - srv->head_flist = srv->tail_flist = new_f; - } else { - - f = closest_preceding_finger(srv, id, TRUE); - if (f == NULL) { - new_f->next = srv->head_flist; - new_f->prev = NULL; - srv->head_flist->prev = new_f; - srv->head_flist = new_f; - } else { - new_f->next = f->next; - if (f->next) - f->next->prev = new_f; - else - srv->tail_flist = new_f; - new_f->prev = f; - f->next = new_f; - } - } - - CHORD_DEBUG(5, print_server(srv, "[insert_finger(2)]", "")); - - *fnew = TRUE; - return new_f; -} - - -/**********************************************************************/ - -void remove_finger(Server *srv, Finger *f) -{ - Finger *pred, *pf; - - pred = pred_finger(srv); /* remeber to check whether pred changes */ - - if ((srv->tail_flist != f) && (srv->head_flist != f)) { - f->prev->next = f->next; - f->next->prev = f->prev; - } else { - if (srv->head_flist == f) { - srv->head_flist = f->next; - if (f->next) f->next->prev = NULL; - } - if (srv->tail_flist == f) { - srv->tail_flist = f->prev; - if (f->prev) f->prev->next = NULL; - } - } - - pf = pred_finger(srv); - if (pred != pf) { - if (pf == NULL) - chord_update_range(&srv->node.id, &srv->node.id); - else - chord_update_range(&pf->node.id, &srv->node.id); - } - - CHORD_DEBUG(5, print_server(srv, "[remove_finger]", "")); - free(f); -} - -/**********************************************************************/ - -void free_finger_list(Finger *flist) -{ - Finger *f; - - while (flist) { - f = flist; - flist = flist->next; - free(f); - } -} - - - +#include <stdlib.h> +#include <assert.h> +#include "chord.h" + +/* new_finger: allocate and initialize finger structure */ +Finger *new_finger(Node *node) +{ + Finger *fp; + + /* allocate space for new finger */ + fp = emalloc(sizeof(Finger)); + fp->node = *node; + fp->status = F_PASSIVE; + fp->npings = 0; + fp->next = fp->prev = NULL; + fp->rtt_avg = fp->rtt_dev = 0; + return fp; +} + +/**********************************************************************/ + +Finger *succ_finger(Server *srv) +{ + Finger *f; + + for (f = srv->head_flist; f; f = f->next) { + if (f->status == F_ACTIVE) { + return f; + } + } + return NULL; +} + +/**********************************************************************/ + +Finger *pred_finger(Server *srv) +{ + Finger *f; + + for (f = srv->tail_flist; f; f = f->prev) { + if (f->status == F_ACTIVE) { + return f; + } + } + + return NULL; +} + +/**********************************************************************/ + +/* closest_preceding_node: search table for highest predecessor of id */ +/* closest_preceding_finger: search table for highest predecessor of id */ + +Finger *closest_preceding_finger(Server *srv, chordID *id, int fall) +{ + Finger *f; + + for (f = srv->tail_flist; f; f = f->prev) { + /* look only for active fingers; we do not know if we can + * reach the passive fingers + */ + if ((fall == TRUE) || (f->status == F_ACTIVE)) { + if (is_between(&f->node.id, &srv->node.id, id)) { + return f; + } + } + } + + return NULL; +} + +Node *closest_preceding_node(Server *srv, chordID *id, int fall) +{ + Finger *f = closest_preceding_finger(srv, id, fall); + + if (f == NULL) { + return &(srv->node); + } else { + return &(f->node); + } +} + +/**********************************************************************/ + +Finger *get_finger(Server *srv, chordID *id) +{ + Finger *f; + + for (f = srv->head_flist; f; f = f->next) { + if (equals(id, &f->node.id)) { + return f; + } + } + return NULL; +} + +/**********************************************************************/ + +Finger *insert_finger(Server *srv, chordID *id, + in_addr_t addr, in_port_t port, int *fnew) +{ + Finger *f, *new_f, *pred; + Node n; + + assert((srv->node.addr != addr) || (srv->node.port != port)); + pred = PRED(srv); + + f = get_finger(srv, id); + + if (f) { + if (f->node.addr != addr) { + f->node.addr = addr; + f->node.port = port; + f->rtt_avg = f->rtt_dev = 0; + f->npings = 0; + } + /* f is already in the list. In this case, + * f is not refreshed, i.e., f->npings is not set to 0. + * Refreshing f here might preclude the ping procedeure from removing + * f when it dies. + */ + CHORD_DEBUG(5, print_server(srv, "[insert_finger(1)]", "end")); + *fnew = FALSE; + return f; + } + + n.id = *id; + n.addr = addr; + n.port = port; + new_f = new_finger(&n); + + f = srv->head_flist; + if (f == NULL) { + /* this is the first finger */ + srv->head_flist = srv->tail_flist = new_f; + } else { + f = closest_preceding_finger(srv, id, TRUE); + if (f == NULL) { + new_f->next = srv->head_flist; + new_f->prev = NULL; + srv->head_flist->prev = new_f; + srv->head_flist = new_f; + } else { + new_f->next = f->next; + if (f->next) { + f->next->prev = new_f; + } else { + srv->tail_flist = new_f; + } + new_f->prev = f; + f->next = new_f; + } + } + + CHORD_DEBUG(5, print_server(srv, "[insert_finger(2)]", "")); + + *fnew = TRUE; + return new_f; +} + +/**********************************************************************/ + +void remove_finger(Server *srv, Finger *f) +{ + Finger *pred, *pf; + + pred = pred_finger(srv); /* remeber to check whether pred changes */ + + if ((srv->tail_flist != f) && (srv->head_flist != f)) { + f->prev->next = f->next; + f->next->prev = f->prev; + } else { + if (srv->head_flist == f) { + srv->head_flist = f->next; + if (f->next) { + f->next->prev = NULL; + } + } + if (srv->tail_flist == f) { + srv->tail_flist = f->prev; + if (f->prev) { + f->prev->next = NULL; + } + } + } + + pf = pred_finger(srv); + if (pred != pf) { + if (pf == NULL) { + chord_update_range(&srv->node.id, &srv->node.id); + } else { + chord_update_range(&pf->node.id, &srv->node.id); + } + } + + CHORD_DEBUG(5, print_server(srv, "[remove_finger]", "")); + free(f); +} + +/**********************************************************************/ + +void free_finger_list(Finger *flist) +{ + Finger *f; + + while (flist) { + f = flist; + flist = flist->next; + free(f); + } +} === modified file 'i3/chord/gen_conf.c' --- i3/chord/gen_conf.c 2009-12-29 15:10:11 +0000 +++ i3/chord/gen_conf.c 2010-02-11 11:49:47 +0000 @@ -1,201 +1,205 @@ -#include <stdlib.h> -#include <stdio.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <netinet/in.h> -#include <arpa/inet.h> -#include <time.h> -#include <unistd.h> -#ifdef __APPLE__ -#include <sys/socket.h> -#endif -#include <net/if.h> -#include <netdb.h> -#include <sys/utsname.h> -#include <sys/sysctl.h> -#include <sys/ioctl.h> -#include <string.h> - -#include "chord.h" - -#define IFNAME_LEN 256 -#define MAX_NUM_IFS 16 - -#define NEWS - -/* get_addr: get IP address of server */ -ulong get_addr1(char *name, int* ok_flag) -{ - int i, tempfd, ret; - struct sockaddr_in tmp_addr; - char ifname[IFNAME_LEN]; - struct ifreq ifr; - - struct hostent *hptr; - struct utsname myname; - - *ok_flag = 1; - - if (name == NULL) { - if (uname(&myname) < 0) { - printf("uname failed:"); - *ok_flag = 0; - return 0; - } - name = myname.nodename; - } - - hptr = gethostbyname(name); - if (!hptr) { - printf("gethostbyname(%s) failed", name); - *ok_flag =0; - return 0; - } - for (i = 0; i < hptr->h_length/sizeof(ulong); i++) { - struct in_addr ia; - ulong *addrptr; - - addrptr = (ulong *) hptr->h_addr_list[i]; - - ia.s_addr = *addrptr; - //printf("Addr %d = %s; ", i, inet_ntoa(ia)); - } - - if (*((ulong *) hptr->h_addr) != inet_addr("127.0.0.1")) - return *((ulong *) hptr->h_addr); - - // if not, ioctl on ethernet interface. - for (i = 0; i < MAX_NUM_IFS; i++) { - sprintf(ifname, "eth%d", i); - strcpy(ifr.ifr_name, ifname); - - tempfd = socket(AF_INET, SOCK_DGRAM, 0); - - if (((ret = ioctl(tempfd, SIOCGIFFLAGS, (char *)&ifr)) != -1)) { - if ((ifr.ifr_flags & IFF_UP) != 0) { - if ((ret = ioctl(tempfd, SIOCGIFADDR, (char *)&ifr)) != -1) { - tmp_addr = *((struct sockaddr_in *) &ifr.ifr_addr); - return tmp_addr.sin_addr.s_addr; - } - } - } - } - - return inet_addr("127.0.0.1"); -} - - -void set_loworder_bits(chordID *id) -{ - int i; -#define ID_SERVER_LEN 6 - for (i = ID_SERVER_LEN; i < ID_LEN; i++) - id->x[i] = 0xff; -} - -int main(int argc, char **argv) -{ - - /** Port offset is used when you want to start multiple sets of i3 servers - * on the same set of planetlab nodes. The port numbers of the different - * i3 servers running on the same planetlab node should not clash. - * So we specificy an offset. - */ - int port_offset = 0; - - int get_addr_ok_flag = 0; - - int i, j, k, i3_port, validate_port; - Node *nodes; - char filename[100], name[100]; - FILE *fp, *fd, *i3clientconf_fd; -#ifdef NEWS - FILE *newsconf_fd; -#endif - struct in_addr ia; -#define MAX_NUM_NODES 1000 - - if (argc < 3) { - fprintf(stderr, "usage: %s server_list cfg_file_prefix [port_offset]\n", argv[0]); - exit(-1); - } - - if (argc > 3) { - //Read the optional port offset which has been specified. - port_offset = atoi(argv[3]); - } else { - port_offset = 0; - } - - srandom(getpid() ^ time(0)); - - nodes = (Node *) malloc(MAX_NUM_NODES * sizeof(Node)); - - fd = fopen(argv[1], "r"); - k = 0; - while (!feof(fd)) { - if (k == MAX_NUM_NODES) - break; - - if( fscanf(fd, "%s\n", name) == EOF ){ - perror("scanf error"); - }; - nodes[k].id = rand_ID(); - //set_loworder_bits(&(nodes[k].id)); - nodes[k].addr = ntohl(get_addr1(name, &get_addr_ok_flag)); - nodes[k].port = (4710 + port_offset) + k; - if (get_addr_ok_flag) { - //advance counter only if we were able to successfully lookup the address - //This is equivalent to ignoring this node. - k++; - } - } - fclose(fd); - - //create a directory to hold the configuration files - mkdir (argv[2], S_IRUSR|S_IWUSR|S_IEXEC); - - sprintf(filename, "%s/%s_i3client.conf", argv[2], argv[2]); - i3clientconf_fd = fopen(filename, "w"); -#ifdef NEWS - sprintf(filename, "%s/%s_i3news.conf", argv[2], argv[2]); - newsconf_fd = fopen(filename, "w"); -#endif - - for (i = 0; i < k; i++) { - i3_port = nodes[i].port - (4710 + port_offset) + (5610 + port_offset); - validate_port = nodes[i].port - (4710 + port_offset) + (7810 + port_offset); - ia.s_addr = htonl(nodes[i].addr); - fprintf(i3clientconf_fd, "%s %d\n", inet_ntoa(ia), i3_port); -#ifdef NEWS - fprintf(newsconf_fd, "%s %d %d ", inet_ntoa(ia), i3_port, validate_port); - print_id(newsconf_fd, &nodes[i].id); - fprintf(newsconf_fd, "\n"); -#endif - -#ifdef NEWS - sprintf(filename, "%s/%s_%s_%d_%d_%d.cfg", - argv[2], argv[2], inet_ntoa(ia), i3_port, validate_port, nodes[i].port); -#else - sprintf(filename, "%s/%s_%s_%d_%d.cfg", - argv[2], argv[2], inet_ntoa(ia), i3_port, nodes[i].port); -#endif - fp = fopen(filename, "w"); - fprintf(fp, "%d ", nodes[i].port); - print_id(fp, &nodes[i].id); - fprintf(fp, "\n"); - for (j = 0; j < k; j++) { - if (j == i) continue; - ia.s_addr = htonl(nodes[j].addr); - fprintf(fp, "%s:%d ", inet_ntoa(ia), nodes[j].port); - fprintf(fp, "\n"); - } - fclose(fp); - } - - fclose(i3clientconf_fd); -#ifdef NEWS - fclose(newsconf_fd); -#endif - return 0; -} +#include <stdlib.h> +#include <stdio.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <time.h> +#include <unistd.h> +#ifdef __APPLE__ +#include <sys/socket.h> +#endif +#include <net/if.h> +#include <netdb.h> +#include <sys/utsname.h> +#include <sys/sysctl.h> +#include <sys/ioctl.h> +#include <string.h> + +#include "chord.h" + +#define IFNAME_LEN 256 +#define MAX_NUM_IFS 16 + +#define NEWS + +/* get_addr: get IP address of server */ +ulong get_addr1(char *name, int *ok_flag) +{ + int i, tempfd, ret; + struct sockaddr_in tmp_addr; + char ifname[IFNAME_LEN]; + struct ifreq ifr; + + struct hostent *hptr; + struct utsname myname; + + *ok_flag = 1; + + if (name == NULL) { + if (uname(&myname) < 0) { + printf("uname failed:"); + *ok_flag = 0; + return 0; + } + name = myname.nodename; + } + + hptr = gethostbyname(name); + if (!hptr) { + printf("gethostbyname(%s) failed", name); + *ok_flag = 0; + return 0; + } + for (i = 0; i < hptr->h_length / sizeof(ulong); i++) { + struct in_addr ia; + ulong *addrptr; + + addrptr = (ulong *) hptr->h_addr_list[i]; + + ia.s_addr = *addrptr; + //printf("Addr %d = %s; ", i, inet_ntoa(ia)); + } + + if (*((ulong *) hptr->h_addr) != inet_addr("127.0.0.1")) { + return *((ulong *) hptr->h_addr); + } + + // if not, ioctl on ethernet interface. + for (i = 0; i < MAX_NUM_IFS; i++) { + sprintf(ifname, "eth%d", i); + strcpy(ifr.ifr_name, ifname); + + tempfd = socket(AF_INET, SOCK_DGRAM, 0); + + if (((ret = ioctl(tempfd, SIOCGIFFLAGS, (char *) &ifr)) != -1)) { + if ((ifr.ifr_flags & IFF_UP) != 0) { + if ((ret = ioctl(tempfd, SIOCGIFADDR, (char *) &ifr)) != -1) { + tmp_addr = *((struct sockaddr_in *) &ifr.ifr_addr); + return tmp_addr.sin_addr.s_addr; + } + } + } + } + + return inet_addr("127.0.0.1"); +} + +void set_loworder_bits(chordID *id) +{ + int i; +#define ID_SERVER_LEN 6 + for (i = ID_SERVER_LEN; i < ID_LEN; i++) { + id->x[i] = 0xff; + } +} + +int main(int argc, char **argv) +{ + /** Port offset is used when you want to start multiple sets of i3 servers + * on the same set of planetlab nodes. The port numbers of the different + * i3 servers running on the same planetlab node should not clash. + * So we specificy an offset. + */ + int port_offset = 0; + + int get_addr_ok_flag = 0; + + int i, j, k, i3_port, validate_port; + Node *nodes; + char filename[100], name[100]; + FILE *fp, *fd, *i3clientconf_fd; +#ifdef NEWS + FILE *newsconf_fd; +#endif + struct in_addr ia; +#define MAX_NUM_NODES 1000 + + if (argc < 3) { + fprintf(stderr, "usage: %s server_list cfg_file_prefix [port_offset]\n", argv[0]); + exit(-1); + } + + if (argc > 3) { + //Read the optional port offset which has been specified. + port_offset = atoi(argv[3]); + } else { + port_offset = 0; + } + + srandom(getpid() ^ time(0)); + + nodes = (Node *) malloc(MAX_NUM_NODES * sizeof(Node)); + + fd = fopen(argv[1], "r"); + k = 0; + while (!feof(fd)) { + if (k == MAX_NUM_NODES) { + break; + } + + if (fscanf(fd, "%s\n", name) == EOF) { + perror("scanf error"); + } + ; + nodes[k].id = rand_ID(); + //set_loworder_bits(&(nodes[k].id)); + nodes[k].addr = ntohl(get_addr1(name, &get_addr_ok_flag)); + nodes[k].port = (4710 + port_offset) + k; + if (get_addr_ok_flag) { + //advance counter only if we were able to successfully lookup the address + //This is equivalent to ignoring this node. + k++; + } + } + fclose(fd); + + //create a directory to hold the configuration files + mkdir(argv[2], S_IRUSR | S_IWUSR | S_IEXEC); + + sprintf(filename, "%s/%s_i3client.conf", argv[2], argv[2]); + i3clientconf_fd = fopen(filename, "w"); +#ifdef NEWS + sprintf(filename, "%s/%s_i3news.conf", argv[2], argv[2]); + newsconf_fd = fopen(filename, "w"); +#endif + + for (i = 0; i < k; i++) { + i3_port = nodes[i].port - (4710 + port_offset) + (5610 + port_offset); + validate_port = nodes[i].port - (4710 + port_offset) + (7810 + port_offset); + ia.s_addr = htonl(nodes[i].addr); + fprintf(i3clientconf_fd, "%s %d\n", inet_ntoa(ia), i3_port); +#ifdef NEWS + fprintf(newsconf_fd, "%s %d %d ", inet_ntoa(ia), i3_port, validate_port); + print_id(newsconf_fd, &nodes[i].id); + fprintf(newsconf_fd, "\n"); +#endif + +#ifdef NEWS + sprintf(filename, "%s/%s_%s_%d_%d_%d.cfg", + argv[2], argv[2], inet_ntoa(ia), i3_port, validate_port, nodes[i].port); +#else + sprintf(filename, "%s/%s_%s_%d_%d.cfg", + argv[2], argv[2], inet_ntoa(ia), i3_port, nodes[i].port); +#endif + fp = fopen(filename, "w"); + fprintf(fp, "%d ", nodes[i].port); + print_id(fp, &nodes[i].id); + fprintf(fp, "\n"); + for (j = 0; j < k; j++) { + if (j == i) { + continue; + } + ia.s_addr = htonl(nodes[j].addr); + fprintf(fp, "%s:%d ", inet_ntoa(ia), nodes[j].port); + fprintf(fp, "\n"); + } + fclose(fp); + } + + fclose(i3clientconf_fd); +#ifdef NEWS + fclose(newsconf_fd); +#endif + return 0; +} === modified file 'i3/chord/gen_conf_same.c' --- i3/chord/gen_conf_same.c 2009-12-11 22:49:11 +0000 +++ i3/chord/gen_conf_same.c 2010-02-11 11:49:47 +0000 @@ -1,49 +1,51 @@ -#include <stdlib.h> -#include <stdio.h> -#include <netinet/in.h> -#include <arpa/inet.h> -#include <time.h> -#include <unistd.h> -#include "chord.h" - -int main(int argc, char **argv) -{ - int i, j, n; - Node *nodes; - in_addr_t addr; - char filename[100]; - FILE *fp; - struct in_addr ia; - - if (argc != 2) { - fprintf(stderr, "ussage: %s num_servers\n", argv[0]); - exit(-1); - } - n = atoi(argv[1]); - srandom(getpid() ^ time(0)); - - addr = ntohl(get_addr()); - - nodes = (Node *) malloc(n * sizeof(Node)); - for (i = 0; i < n; i++) { - nodes[i].id = rand_ID(); - nodes[i].addr = addr; - nodes[i].port = 6500 + i; - } - - for (i = 0; i < n; i++) { - sprintf(filename, "conf.%d", i); - fp = fopen(filename, "w"); - fprintf(fp, "%d ", nodes[i].port); - print_id(fp, &nodes[i].id); - fprintf(fp, "\n"); - for (j = 0; j < n; j++) { - if (j == i) continue; - ia.s_addr = htonl(nodes[j].addr); - fprintf(fp, "%s:%d\n", inet_ntoa(ia), nodes[j].port); - } - fclose(fp); - } - - return 0; -} +#include <stdlib.h> +#include <stdio.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <time.h> +#include <unistd.h> +#include "chord.h" + +int main(int argc, char **argv) +{ + int i, j, n; + Node *nodes; + in_addr_t addr; + char filename[100]; + FILE *fp; + struct in_addr ia; + + if (argc != 2) { + fprintf(stderr, "ussage: %s num_servers\n", argv[0]); + exit(-1); + } + n = atoi(argv[1]); + srandom(getpid() ^ time(0)); + + addr = ntohl(get_addr()); + + nodes = (Node *) malloc(n * sizeof(Node)); + for (i = 0; i < n; i++) { + nodes[i].id = rand_ID(); + nodes[i].addr = addr; + nodes[i].port = 6500 + i; + } + + for (i = 0; i < n; i++) { + sprintf(filename, "conf.%d", i); + fp = fopen(filename, "w"); + fprintf(fp, "%d ", nodes[i].port); + print_id(fp, &nodes[i].id); + fprintf(fp, "\n"); + for (j = 0; j < n; j++) { + if (j == i) { + continue; + } + ia.s_addr = htonl(nodes[j].addr); + fprintf(fp, "%s:%d\n", inet_ntoa(ia), nodes[j].port); + } + fclose(fp); + } + + return 0; +} === modified file 'i3/chord/hosts.c' --- i3/chord/hosts.c 2010-01-06 22:17:32 +0000 +++ i3/chord/hosts.c 2010-02-11 11:49:47 +0000 @@ -1,135 +1,136 @@ -/* host registration (mainly for testing) */ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <errno.h> -#include <assert.h> -#include <sys/types.h> -#include <unistd.h> -#include <netinet/in.h> -#include <arpa/inet.h> -#include <sys/utsname.h> -#include <sys/ioctl.h> -#include <sys/sysctl.h> -#include <netdb.h> -#include <net/if.h> -#include "chord.h" - -#define TRIVIAL_LOCAL_ADDR "127.0.0.1" -#define MAX_NUM_INTERFACES 3 -#define IFNAME_LEN 256 - -/*************************************************************************** - * - * Purpose: Get IP address of local machine by ioctl on eth0-ethk - * - * Return: As an unsigned long in network byte order - * - **************************************************************************/ -static uint32_t get_local_addr_eth(void) -{ - int i, tempfd; - struct sockaddr_in addr; - char ifname[IFNAME_LEN]; - struct ifreq ifr; - - for (i = 0; i < MAX_NUM_INTERFACES; i++) { - sprintf(ifname, "eth%d", i); - strcpy(ifr.ifr_name, ifname); - tempfd = socket(AF_INET, SOCK_DGRAM, 0); - - if (-1 != ioctl(tempfd, SIOCGIFFLAGS, (char *)&ifr)) { - if (0 != (ifr.ifr_flags & IFF_UP)) { - if (-1 != ioctl(tempfd, SIOCGIFADDR, (char *)&ifr)) { - addr = *((struct sockaddr_in *) &ifr.ifr_addr); - close(tempfd); - return addr.sin_addr.s_addr; - } - } - } - close(tempfd); - } - - return inet_addr(TRIVIAL_LOCAL_ADDR); -} - -/*************************************************************************** - * - * Purpose: Get the IP address of an arbitrary machine - * given the name of the machine - * - * Return: As an unsigned long in network byte order - * - **************************************************************************/ -static uint32_t name_to_addr(const char *name) -{ - int i; - struct hostent *hptr = gethostbyname(name); - if (!hptr) { - weprintf("gethostbyname(%s) failed", name); - } - else { - for (i = 0; i < hptr->h_length/sizeof(uint32_t); i++) { - uint32_t addr = *((uint32_t *) hptr->h_addr_list[i]); - if (inet_addr(TRIVIAL_LOCAL_ADDR) != addr) - return addr; - } - } - return 0; -} - - -/*************************************************************************** - * - * Purpose: Get IP address of local machine by uname/gethostbyname - * - * Return: As an unsigned long in network byte order - * - **************************************************************************/ -static uint32_t get_local_addr_uname(void) -{ - struct utsname myname; - uint32_t addr = 0; - - if (uname(&myname) < 0) { - weprintf("uname failed:"); - } else { - addr = name_to_addr(myname.nodename); - } - - if (addr == 0) - return inet_addr(TRIVIAL_LOCAL_ADDR); - else - return addr; -} - -/*************************************************************************** - * - * Purpose: Get IP address of local machine - * - * Return: As an unsigned long in network byte order - * - **************************************************************************/ -static uint32_t get_local_addr(void) -{ - uint32_t addr; - - /* First try uname/gethostbyname */ - if ((addr = get_local_addr_uname()) != inet_addr(TRIVIAL_LOCAL_ADDR)) - return addr; - /* If that is unsuccessful, try ioctl on eth interfaces */ - if ((addr = get_local_addr_eth()) != inet_addr(TRIVIAL_LOCAL_ADDR)) - return addr; - - /* This is hopeless, return TRIVIAL_IP */ - return(inet_addr(TRIVIAL_LOCAL_ADDR)); -} - -/***********************************************************************/ -/* get_addr: get IP address of server */ -in_addr_t -get_addr(void) -{ - return (in_addr_t) get_local_addr(); -} +/* host registration (mainly for testing) */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <assert.h> +#include <sys/types.h> +#include <unistd.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <sys/utsname.h> +#include <sys/ioctl.h> +#include <sys/sysctl.h> +#include <netdb.h> +#include <net/if.h> +#include "chord.h" + +#define TRIVIAL_LOCAL_ADDR "127.0.0.1" +#define MAX_NUM_INTERFACES 3 +#define IFNAME_LEN 256 + +/*************************************************************************** + * + * Purpose: Get IP address of local machine by ioctl on eth0-ethk + * + * Return: As an unsigned long in network byte order + * + **************************************************************************/ +static uint32_t get_local_addr_eth(void) +{ + int i, tempfd; + struct sockaddr_in addr; + char ifname[IFNAME_LEN]; + struct ifreq ifr; + + for (i = 0; i < MAX_NUM_INTERFACES; i++) { + sprintf(ifname, "eth%d", i); + strcpy(ifr.ifr_name, ifname); + tempfd = socket(AF_INET, SOCK_DGRAM, 0); + + if (-1 != ioctl(tempfd, SIOCGIFFLAGS, (char *) &ifr)) { + if (0 != (ifr.ifr_flags & IFF_UP)) { + if (-1 != ioctl(tempfd, SIOCGIFADDR, (char *) &ifr)) { + addr = *((struct sockaddr_in *) &ifr.ifr_addr); + close(tempfd); + return addr.sin_addr.s_addr; + } + } + } + close(tempfd); + } + + return inet_addr(TRIVIAL_LOCAL_ADDR); +} + +/*************************************************************************** + * + * Purpose: Get the IP address of an arbitrary machine + * given the name of the machine + * + * Return: As an unsigned long in network byte order + * + **************************************************************************/ +static uint32_t name_to_addr(const char *name) +{ + int i; + struct hostent *hptr = gethostbyname(name); + if (!hptr) { + weprintf("gethostbyname(%s) failed", name); + } else { + for (i = 0; i < hptr->h_length / sizeof(uint32_t); i++) { + uint32_t addr = *((uint32_t *) hptr->h_addr_list[i]); + if (inet_addr(TRIVIAL_LOCAL_ADDR) != addr) { + return addr; + } + } + } + return 0; +} + +/*************************************************************************** + * + * Purpose: Get IP address of local machine by uname/gethostbyname + * + * Return: As an unsigned long in network byte order + * + **************************************************************************/ +static uint32_t get_local_addr_uname(void) +{ + struct utsname myname; + uint32_t addr = 0; + + if (uname(&myname) < 0) { + weprintf("uname failed:"); + } else { + addr = name_to_addr(myname.nodename); + } + + if (addr == 0) { + return inet_addr(TRIVIAL_LOCAL_ADDR); + } else { + return addr; + } +} + +/*************************************************************************** + * + * Purpose: Get IP address of local machine + * + * Return: As an unsigned long in network byte order + * + **************************************************************************/ +static uint32_t get_local_addr(void) +{ + uint32_t addr; + + /* First try uname/gethostbyname */ + if ((addr = get_local_addr_uname()) != inet_addr(TRIVIAL_LOCAL_ADDR)) { + return addr; + } + /* If that is unsuccessful, try ioctl on eth interfaces */ + if ((addr = get_local_addr_eth()) != inet_addr(TRIVIAL_LOCAL_ADDR)) { + return addr; + } + + /* This is hopeless, return TRIVIAL_IP */ + return inet_addr(TRIVIAL_LOCAL_ADDR); +} + +/***********************************************************************/ +/* get_addr: get IP address of server */ +in_addr_t get_addr(void) +{ + return (in_addr_t) get_local_addr(); +} === modified file 'i3/chord/join.c' --- i3/chord/join.c 2009-12-11 22:49:11 +0000 +++ i3/chord/join.c 2010-02-11 11:49:47 +0000 @@ -1,42 +1,44 @@ -#include <stdio.h> -#include <string.h> -#include <stdlib.h> -#include <assert.h> -#include <netdb.h> -#include <sys/types.h> -#include <netinet/in.h> -#include <arpa/inet.h> -#include <sys/utsname.h> -#include "chord.h" - -/* join: Send join messages to hosts in file */ -void join(Server *srv, FILE *fp) -{ - char addr[100], *p; - struct hostent *hp; - - // printf("join\n"); - while (nknown < MAX_WELLKNOWN && fscanf(fp, " %s\n", addr) == 1) { - p = strchr(addr, ':'); - printf("addr=%s\n", addr); - assert(p != NULL); - *(p++) = '\0'; - - /* resolve address */ - hp = gethostbyname(addr); - if (hp == NULL) - eprintf("gethostbyname(%s) failed:", addr); - - well_known[nknown].addr = ntohl(*((in_addr_t *) hp->h_addr)); - well_known[nknown].port = (in_port_t) atoi(p); - nknown++; - } - - if (nknown == 0) - printf("Didn't find any known hosts."); - // eprintf("Didn't find any known hosts."); xxxx - - chord_update_range(&srv->node.id, &srv->node.id); - set_stabilize_timer(); - stabilize(srv); -} +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <assert.h> +#include <netdb.h> +#include <sys/types.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <sys/utsname.h> +#include "chord.h" + +/* join: Send join messages to hosts in file */ +void join(Server *srv, FILE *fp) +{ + char addr[100], *p; + struct hostent *hp; + + // printf("join\n"); + while (nknown < MAX_WELLKNOWN && fscanf(fp, " %s\n", addr) == 1) { + p = strchr(addr, ':'); + printf("addr=%s\n", addr); + assert(p != NULL); + *(p++) = '\0'; + + /* resolve address */ + hp = gethostbyname(addr); + if (hp == NULL) { + eprintf("gethostbyname(%s) failed:", addr); + } + + well_known[nknown].addr = ntohl(*((in_addr_t *) hp->h_addr)); + well_known[nknown].port = (in_port_t) atoi(p); + nknown++; + } + + if (nknown == 0) { + printf("Didn't find any known hosts."); + } + // eprintf("Didn't find any known hosts."); xxxx + + chord_update_range(&srv->node.id, &srv->node.id); + set_stabilize_timer(); + stabilize(srv); +} === modified file 'i3/chord/pack.c' --- i3/chord/pack.c 2009-12-11 22:49:11 +0000 +++ i3/chord/pack.c 2010-02-11 11:49:47 +0000 @@ -1,584 +1,593 @@ -#include <stdarg.h> -#include <string.h> -#include <assert.h> -#include "chord.h" - -/* pack: pack binary items into buf, return length */ - -int pack(uchar *buf, char *fmt, ...) -{ - va_list args; - char *p; - uchar *bp; - chordID *id; - ushort s; - ulong l; - - bp = buf; - va_start(args, fmt); - for (p = fmt; *p != '\0'; p++) { - switch (*p) { - case 'c': /* char */ - *bp++ = va_arg(args, int); - break; - case 's': /* short */ - s = va_arg(args, int); - s = htons(s); - memmove(bp, (char *)&s, sizeof(ushort)); - bp += sizeof(ushort); - break; - case 'l': /* long */ - l = va_arg(args, ulong); - l = htonl(l); - memmove(bp, (char *)&l, sizeof(ulong)); - bp += sizeof(ulong); - break; - case 'x': /* id */ - id = va_arg(args, chordID *); - memmove(bp, id->x, ID_LEN); - bp += ID_LEN; - break; - default: /* illegal type character */ - va_end(args); - return -1; - } - } - va_end(args); - return bp - buf; -} - -/**********************************************************************/ - -/* unpack: unpack binary items from buf, return length */ -int unpack(uchar *buf, char *fmt, ...) -{ - va_list args; - char *p; - uchar *bp, *pc; - chordID *id; - ushort *ps; - ulong *pl; - - bp = buf; - va_start(args, fmt); - for (p = fmt; *p != '\0'; p++) { - switch (*p) { - case 'c': /* char */ - pc = va_arg(args, uchar*); - *pc = *bp++; - break; - case 's': /* short */ - ps = va_arg(args, ushort*); - *ps = ntohs(*(ushort*)bp); - bp += sizeof(ushort); - break; - case 'l': /* long */ - pl = va_arg(args, ulong*); - *pl = ntohl(*(ulong*)bp); - bp += sizeof(ulong); - break; - case 'x': /* id */ - id = va_arg(args, chordID *); - memmove(id->x, bp, ID_LEN); - bp += ID_LEN; - break; - default: /* illegal type character */ - va_end(args); - return -1; - } - } - va_end(args); - return bp - buf; -} - -/**********************************************************************/ - -int sizeof_fmt(char *fmt) -{ - int len = 0; - int i; - - for (i = 0; i < strlen(fmt); i++) { - switch (fmt[i]) { - case 'c': /* char */ - len += sizeof(char); - break; - case 's': /* short */ - len += sizeof(ushort); - break; - case 'l': /* long */ - len += sizeof(ulong); - break; - case 'x': /* id */ - len += ID_LEN; - break; - default: /* illegal type character */ - eprintf("fmt_len: illegal type character.\n"); - return -1; - } - } - return len; -} - -/**********************************************************************/ - -static int (*unpackfn[])(Server *, int, uchar *) = { - unpack_data, - unpack_data, - unpack_fs, - unpack_fs_repl, - unpack_stab, - unpack_stab_repl, - unpack_notify, - unpack_ping, - unpack_pong, - unpack_fingers_get, - unpack_fingers_repl, - unpack_traceroute, - unpack_traceroute, - unpack_traceroute_repl, -}; - -/* dispatch: unpack and process packet */ -int dispatch(Server *srv, int n, uchar *buf) -{ - uchar type; - int res; - - type = buf[0]; - - if (type >= NELEMS(unpackfn)) { - printf("bad packet type 0x%x\n", type); - return -1; - } - res = (*unpackfn[type])(srv, n, buf); - if (res == -1) - printf("protocol error, type %x length %d\n", type, n); - return res; -} - -/**********************************************************************/ - -/* pack_data: pack data packet */ -int pack_data(uchar *buf, uchar type, byte ttl, chordID *id, - ushort len, uchar *data) -{ - int n; - - n = pack(buf, "ccxs", type, ttl, id, len); - if (n >= 0) { - memmove(buf + n, data, len); - n += len; - } - return n; -} - -/**********************************************************************/ - -/* unpack_data: unpack and process data packet */ -int unpack_data(Server *srv, int n, uchar *buf) -{ - uchar type; - byte ttl; - int len; - chordID id; - ushort pkt_len; - - len = unpack(buf, "ccxs", &type, &ttl, id.x, &pkt_len); - if (len < 0 || len + pkt_len != n) - return -1; - if (--ttl == 0) { - print_two_chordIDs("TTL expired: data packet ", &id, - " dropped at node ", &srv->node.id, "\n"); - return -2; - } - assert(type == CHORD_ROUTE || type == CHORD_ROUTE_LAST); - return process_data(srv, type, ttl, &id, pkt_len, buf + len); -} - -/**********************************************************************/ - -/* pack_fs: pack find_successor packet */ -int pack_fs(uchar *buf, byte ttl, chordID *id, ulong addr, ushort port) -{ - return pack(buf, "ccxls", CHORD_FS, ttl, id, addr, port); -} - -/**********************************************************************/ - -/* unpack_fs: unpack and process find_successor packet */ -int unpack_fs(Server *srv, int n, uchar *buf) -{ - uchar type; - byte ttl; - ulong addr; - ushort port; - chordID id; - - if (unpack(buf, "ccxls", &type, &ttl, &id, &addr, &port) != n) - return -1; - if (--ttl == 0) { - print_two_chordIDs("TTL expired: fix_finger packet ", &id, - " dropped at node ", &srv->node.id, "\n"); - return -2; - } - assert(type == CHORD_FS); - return process_fs(srv, ttl, &id, addr, port); -} - -/**********************************************************************/ - -/* pack_fs_repl: pack find_successor reply packet */ -int pack_fs_repl(uchar *buf, chordID *id, ulong addr, ushort port) -{ - return pack(buf, "cxls", CHORD_FS_REPL, id, addr, port); -} - -/**********************************************************************/ - -/* unpack_fs_repl: unpack and process find_successor reply packet */ -int unpack_fs_repl(Server *srv, int n, uchar *buf) -{ - uchar type; - ulong addr; - ushort port; - chordID id; - - if (unpack(buf, "cxls", &type, &id, &addr, &port) != n) - return -1; - assert(type == CHORD_FS_REPL); - return process_fs_repl(srv, &id, addr, port); -} - -/**********************************************************************/ - -/* pack_stab: pack stabilize packet */ -int pack_stab(uchar *buf, chordID *id, ulong addr, ushort port) -{ - return pack(buf, "cxls", CHORD_STAB, id, addr, port); -} - -/**********************************************************************/ - -/* unpack_stab: unpack and process stabilize packet */ -int unpack_stab(Server *srv, int n, uchar *buf) -{ - uchar type; - ulong addr; - ushort port; - chordID id; - - if (unpack(buf, "cxls", &type, &id, &addr, &port) != n) - return -1; - assert(type == CHORD_STAB); - return process_stab(srv, &id, addr, port); -} - -/**********************************************************************/ - -/* pack_stab_repl: pack stabilize reply packet */ -int pack_stab_repl(uchar *buf, chordID *id, ulong addr, ushort port) -{ - return pack(buf, "cxls", CHORD_STAB_REPL, id, addr, port); -} - -/**********************************************************************/ - -/* unpack_stab_repl: unpack and process stabilize reply packet */ -int unpack_stab_repl(Server *srv, int n, uchar *buf) -{ - uchar type; - ulong addr; - ushort port; - chordID id; - - if (unpack(buf, "cxls", &type, &id, &addr, &port) != n) - return -1; - assert(type == CHORD_STAB_REPL); - return process_stab_repl(srv, &id, addr, port); -} - -/**********************************************************************/ - -/* pack_notify: pack notify packet */ -int pack_notify(uchar *buf, chordID *id, ulong addr, ushort port) -{ - return pack(buf, "cxls", CHORD_NOTIFY, id, addr, port); -} - -/**********************************************************************/ - -/* unpack_notify: unpack notify packet */ -int unpack_notify(Server *srv, int n, uchar *buf) -{ - uchar type; - ulong addr; - ushort port; - chordID id; - - if (unpack(buf, "cxls", &type, &id, &addr, &port) != n) - return -1; - assert(type == CHORD_NOTIFY); - return process_notify(srv, &id, addr, port); -} - -/**********************************************************************/ - -/* pack_ping: pack ping packet */ -int pack_ping(uchar *buf, chordID *id, ulong addr, ushort port, ulong time) -{ - return pack(buf, "cxlsl", CHORD_PING, id, addr, port, time); -} - -/**********************************************************************/ - -/* unpack_ping: unpack and process ping packet */ -int unpack_ping(Server *srv, int n, uchar *buf) -{ - uchar type; - chordID id; - ulong addr; - ushort port; - ulong time; - - if (unpack(buf, "cxlsl", &type, &id, &addr, &port, &time) != n) - return -1; - assert(type == CHORD_PING); - return process_ping(srv, &id, addr, port, time); -} - -/**********************************************************************/ - -/* pack_pong: pack pong packet */ -int pack_pong(uchar *buf, chordID *id, ulong addr, ushort port, ulong time) -{ - return pack(buf, "cxlsl", CHORD_PONG, id, addr, port, time); -} - -/**********************************************************************/ - -/* unpack_pong: unpack pong packet */ -int unpack_pong(Server *srv, int n, uchar *buf) -{ - uchar type; - ulong addr; - ushort port; - chordID id; - ulong time; - - if (unpack(buf, "cxlsl", &type, &id, &addr, &port, &time) != n) - return -1; - assert(type == CHORD_PONG); - return process_pong(srv, &id, addr, port, time); -} - -/**********************************************************************/ -/**********************************************************************/ - -/* pack_fingers_get: pack get fingers packet */ -int pack_fingers_get(uchar *buf, ulong addr, ushort port, Key *key) -{ - return pack(buf, "cxls", CHORD_FINGERS_GET, key, addr, port); -} - -/**********************************************************************/ - -/* unpack_fingers_get: unpack and process fingers_get packet */ -int unpack_fingers_get(Server *srv, int n, uchar *buf) -{ - uchar type; - Key key; - ulong addr; - ushort port; - - if (unpack(buf, "cxls", &type, &key, &addr, &port) != n) - return -1; - assert(type == CHORD_FINGERS_GET); - return process_fingers_get(srv, addr, port, &key); -} - -#define INCOMPLETE_FINGER_LIST -1 -#define END_FINGER_LIST 0 - -/* pack_fingers_repl: pack repl fingers packet */ -int pack_fingers_repl(uchar *buf, Server *srv) -{ - Finger *f; - int len, l; - - assert(srv); - len = pack(buf, "cxls", CHORD_FINGERS_REPL, &srv->node.id, - srv->node.addr, srv->node.port); - - /* pack fingers */ - for (f = srv->head_flist; f; f = f->next) { - l = pack(buf + len, "xlslls", - &f->node.id, f->node.addr, f->node.port, - f->rtt_avg, f->rtt_dev, (short)f->npings); - len += l; - if (len + l + 1 > BUFSIZE) { - len += pack(buf + len, "c", INCOMPLETE_FINGER_LIST); - return len; - } - } - len += pack(buf + len, "c", END_FINGER_LIST); - return len; -} - - -/* unpack_fingers_repl: unpack and process fingers_repl packet */ -int unpack_fingers_repl(Server *srv, int n, uchar *buf) -{ - /* this message is received by a client; - * it shouldn't be received by an i3 server - */ - return process_fingers_repl(srv, 0); -} - - -/**********************************************************************/ - -/* pack_traceroute: pack/update traceroute packet */ -/* - * traceroute packet format: - * char pkt_type; - * char ttl; time to live, decremented at every hop. - * When ttl reaches 0, a traceroute_repl packet is returned. - * char hops; number of hops up to the current node (not including the - * client). hops is inceremented at every hop along the - * forward path. hops should be initialized to 0 by the clients. - * ID target_id; target ID for traceroute. - * Node prev_node; previous node (ie., the node which forwarded the packet) - * ulong rtt; rtt... - * ulong dev; ... and std dev frm previous node to this node (in usec) - * Node crt_node; this node - * (list of addresses/ports of the nodes along the traceroute path - * up to this node) - * ulong addr; address... - * ushort port; ... and port number of the client - * .... - */ -int pack_traceroute(uchar *buf, Server *srv, Finger *f, - uchar type, byte ttl, byte hops) -{ - int n = 0; - - /* pack type, ttl and hops fields */ - n = pack(buf+n, "ccc", type, ttl, hops); - - /* skip target ID field */ - n += sizeof_fmt("x"); - - /* pack prev node (for the next node, this is the current node!) */ - n += pack(buf+n, "xlsll", &srv->node.id, srv->node.addr, srv->node.port, - f->rtt_avg, f->rtt_dev); - - /* pack this node field (for next node this is the node itself!) */ - n += pack(buf+n, "xls", &f->node.id, f->node.addr, f->node.port); - - /* skip current list of addresses .. */ - n += sizeof_fmt("ls")*hops; - - /* add current node to the list */ - n += pack(buf+n, "ls", srv->node.addr, srv->node.port); - - return n; -} - -/**********************************************************************/ - -/* unpack_traceroute: unpack and process trace_route packet - * (see pack_traceroute for packet format) - */ -int unpack_traceroute(Server *srv, int n, uchar *buf) -{ - chordID id; - byte type; - byte ttl; - byte hops; - - /* unpack following fields: type, ttl, hops, and target id */ - if (unpack(buf, "cccx", &type, &ttl, &hops, &id) >= n) - return -1; - assert(type == CHORD_TRACEROUTE || type == CHORD_TRACEROUTE_LAST); - return process_traceroute(srv, &id, (char *)buf, type, ttl, hops); -} - -/**********************************************************************/ - -/* pack_traceroute_repl: pack/update traceroute packet */ -/* - * traceroute packet_repl format: - * char pkt_type; - * char ttl; time to live, incremented at every hop (remember, this message - * travls on the reverse path) - * char hops; number of hops from client, decremented at every - * hop along the forward path. When hops reaches 0, - * the packet is dropped. - * ID target_id; target ID for traceroute. - * Node nl_node; next-to-last hop on traceroute path - * ulong rtt; rtt... - * ulong dev; ... and std dev from next-to-last hop to the last hop - * Node l_node; last node of traceroute path - * (list of addresses/ports of the nodes along the traceroute path - * up to this node, starting with the client) - * ulong addr; address... - * ushort port; ... and port number of the client - * .... - */ -int pack_traceroute_repl(uchar *buf, Server *srv, byte ttl, byte hops, - ulong *paddr, ushort *pport, int one_hop) -{ - int n = 0; - - /* pack ttl and hops fields */ - n += pack(buf+n, "ccc", CHORD_TRACEROUTE_REPL, (char)ttl, (char)hops); - - /* skip target ID field */ - n += sizeof_fmt("x"); - - if (one_hop) { - /* one hop path */ - n += pack(buf+n, "xls", &srv->node.id, srv->node.addr, srv->node.port); - /* skip mean rtt, and std dev rtt fields */ - n += sizeof_fmt("ll"); - } else { - /* skip next-to-last node field, and the mean and std dev. to last - * node fields - */ - n += sizeof_fmt("xlsll"); - } - - /* skip last node field */ - n += sizeof_fmt("xls"); - - /* compute source list size -- this is the number of hops plus client */ - n += sizeof_fmt("ls")*hops; - - /* get address and port number of previous node on reverse path - * yes, it's ugly to unpack in a pack function, but... - */ - unpack(buf+n, "ls", paddr, pport); - - return n; -} - -/**********************************************************************/ - -/* unpack_traceroute: unpack and process trace_route packet - * (see pack_traceroute for packet format) - */ -int unpack_traceroute_repl(Server *srv, int n, uchar *buf) -{ - byte type; - byte ttl; - byte hops; - - /* unpack following fields: type, ttl, and hops */ - if (unpack(buf, "ccc", &type, &ttl, &hops) >= n) - return -1; - assert(type == CHORD_TRACEROUTE_REPL); - - return process_traceroute_repl(srv, (char *)buf, ttl, hops); -} - +#include <stdarg.h> +#include <string.h> +#include <assert.h> +#include "chord.h" + +/* pack: pack binary items into buf, return length */ + +int pack(uchar *buf, char *fmt, ...) +{ + va_list args; + char *p; + uchar *bp; + chordID *id; + ushort s; + ulong l; + + bp = buf; + va_start(args, fmt); + for (p = fmt; *p != '\0'; p++) { + switch (*p) { + case 'c': /* char */ + *bp++ = va_arg(args, int); + break; + case 's': /* short */ + s = va_arg(args, int); + s = htons(s); + memmove(bp, (char *) &s, sizeof(ushort)); + bp += sizeof(ushort); + break; + case 'l': /* long */ + l = va_arg(args, ulong); + l = htonl(l); + memmove(bp, (char *) &l, sizeof(ulong)); + bp += sizeof(ulong); + break; + case 'x': /* id */ + id = va_arg(args, chordID *); + memmove(bp, id->x, ID_LEN); + bp += ID_LEN; + break; + default: /* illegal type character */ + va_end(args); + return -1; + } + } + va_end(args); + return bp - buf; +} + +/**********************************************************************/ + +/* unpack: unpack binary items from buf, return length */ +int unpack(uchar *buf, char *fmt, ...) +{ + va_list args; + char *p; + uchar *bp, *pc; + chordID *id; + ushort *ps; + ulong *pl; + + bp = buf; + va_start(args, fmt); + for (p = fmt; *p != '\0'; p++) { + switch (*p) { + case 'c': /* char */ + pc = va_arg(args, uchar *); + *pc = *bp++; + break; + case 's': /* short */ + ps = va_arg(args, ushort *); + *ps = ntohs(*(ushort *) bp); + bp += sizeof(ushort); + break; + case 'l': /* long */ + pl = va_arg(args, ulong *); + *pl = ntohl(*(ulong *) bp); + bp += sizeof(ulong); + break; + case 'x': /* id */ + id = va_arg(args, chordID *); + memmove(id->x, bp, ID_LEN); + bp += ID_LEN; + break; + default: /* illegal type character */ + va_end(args); + return -1; + } + } + va_end(args); + return bp - buf; +} + +/**********************************************************************/ + +int sizeof_fmt(char *fmt) +{ + int len = 0; + int i; + + for (i = 0; i < strlen(fmt); i++) { + switch (fmt[i]) { + case 'c': /* char */ + len += sizeof(char); + break; + case 's': /* short */ + len += sizeof(ushort); + break; + case 'l': /* long */ + len += sizeof(ulong); + break; + case 'x': /* id */ + len += ID_LEN; + break; + default: /* illegal type character */ + eprintf("fmt_len: illegal type character.\n"); + return -1; + } + } + return len; +} + +/**********************************************************************/ + +static int (*unpackfn[])(Server *, int, uchar *) = { + unpack_data, + unpack_data, + unpack_fs, + unpack_fs_repl, + unpack_stab, + unpack_stab_repl, + unpack_notify, + unpack_ping, + unpack_pong, + unpack_fingers_get, + unpack_fingers_repl, + unpack_traceroute, + unpack_traceroute, + unpack_traceroute_repl, +}; + +/* dispatch: unpack and process packet */ +int dispatch(Server *srv, int n, uchar *buf) +{ + uchar type; + int res; + + type = buf[0]; + + if (type >= NELEMS(unpackfn)) { + printf("bad packet type 0x%x\n", type); + return -1; + } + res = (*unpackfn[type])(srv, n, buf); + if (res == -1) { + printf("protocol error, type %x length %d\n", type, n); + } + return res; +} + +/**********************************************************************/ + +/* pack_data: pack data packet */ +int pack_data(uchar *buf, uchar type, byte ttl, chordID *id, + ushort len, uchar *data) +{ + int n; + + n = pack(buf, "ccxs", type, ttl, id, len); + if (n >= 0) { + memmove(buf + n, data, len); + n += len; + } + return n; +} + +/**********************************************************************/ + +/* unpack_data: unpack and process data packet */ +int unpack_data(Server *srv, int n, uchar *buf) +{ + uchar type; + byte ttl; + int len; + chordID id; + ushort pkt_len; + + len = unpack(buf, "ccxs", &type, &ttl, id.x, &pkt_len); + if (len < 0 || len + pkt_len != n) { + return -1; + } + if (--ttl == 0) { + print_two_chordIDs("TTL expired: data packet ", &id, + " dropped at node ", &srv->node.id, "\n"); + return -2; + } + assert(type == CHORD_ROUTE || type == CHORD_ROUTE_LAST); + return process_data(srv, type, ttl, &id, pkt_len, buf + len); +} + +/**********************************************************************/ + +/* pack_fs: pack find_successor packet */ +int pack_fs(uchar *buf, byte ttl, chordID *id, ulong addr, ushort port) +{ + return pack(buf, "ccxls", CHORD_FS, ttl, id, addr, port); +} + +/**********************************************************************/ + +/* unpack_fs: unpack and process find_successor packet */ +int unpack_fs(Server *srv, int n, uchar *buf) +{ + uchar type; + byte ttl; + ulong addr; + ushort port; + chordID id; + + if (unpack(buf, "ccxls", &type, &ttl, &id, &addr, &port) != n) { + return -1; + } + if (--ttl == 0) { + print_two_chordIDs("TTL expired: fix_finger packet ", &id, + " dropped at node ", &srv->node.id, "\n"); + return -2; + } + assert(type == CHORD_FS); + return process_fs(srv, ttl, &id, addr, port); +} + +/**********************************************************************/ + +/* pack_fs_repl: pack find_successor reply packet */ +int pack_fs_repl(uchar *buf, chordID *id, ulong addr, ushort port) +{ + return pack(buf, "cxls", CHORD_FS_REPL, id, addr, port); +} + +/**********************************************************************/ + +/* unpack_fs_repl: unpack and process find_successor reply packet */ +int unpack_fs_repl(Server *srv, int n, uchar *buf) +{ + uchar type; + ulong addr; + ushort port; + chordID id; + + if (unpack(buf, "cxls", &type, &id, &addr, &port) != n) { + return -1; + } + assert(type == CHORD_FS_REPL); + return process_fs_repl(srv, &id, addr, port); +} + +/**********************************************************************/ + +/* pack_stab: pack stabilize packet */ +int pack_stab(uchar *buf, chordID *id, ulong addr, ushort port) +{ + return pack(buf, "cxls", CHORD_STAB, id, addr, port); +} + +/**********************************************************************/ + +/* unpack_stab: unpack and process stabilize packet */ +int unpack_stab(Server *srv, int n, uchar *buf) +{ + uchar type; + ulong addr; + ushort port; + chordID id; + + if (unpack(buf, "cxls", &type, &id, &addr, &port) != n) { + return -1; + } + assert(type == CHORD_STAB); + return process_stab(srv, &id, addr, port); +} + +/**********************************************************************/ + +/* pack_stab_repl: pack stabilize reply packet */ +int pack_stab_repl(uchar *buf, chordID *id, ulong addr, ushort port) +{ + return pack(buf, "cxls", CHORD_STAB_REPL, id, addr, port); +} + +/**********************************************************************/ + +/* unpack_stab_repl: unpack and process stabilize reply packet */ +int unpack_stab_repl(Server *srv, int n, uchar *buf) +{ + uchar type; + ulong addr; + ushort port; + chordID id; + + if (unpack(buf, "cxls", &type, &id, &addr, &port) != n) { + return -1; + } + assert(type == CHORD_STAB_REPL); + return process_stab_repl(srv, &id, addr, port); +} + +/**********************************************************************/ + +/* pack_notify: pack notify packet */ +int pack_notify(uchar *buf, chordID *id, ulong addr, ushort port) +{ + return pack(buf, "cxls", CHORD_NOTIFY, id, addr, port); +} + +/**********************************************************************/ + +/* unpack_notify: unpack notify packet */ +int unpack_notify(Server *srv, int n, uchar *buf) +{ + uchar type; + ulong addr; + ushort port; + chordID id; + + if (unpack(buf, "cxls", &type, &id, &addr, &port) != n) { + return -1; + } + assert(type == CHORD_NOTIFY); + return process_notify(srv, &id, addr, port); +} + +/**********************************************************************/ + +/* pack_ping: pack ping packet */ +int pack_ping(uchar *buf, chordID *id, ulong addr, ushort port, ulong time) +{ + return pack(buf, "cxlsl", CHORD_PING, id, addr, port, time); +} + +/**********************************************************************/ + +/* unpack_ping: unpack and process ping packet */ +int unpack_ping(Server *srv, int n, uchar *buf) +{ + uchar type; + chordID id; + ulong addr; + ushort port; + ulong time; + + if (unpack(buf, "cxlsl", &type, &id, &addr, &port, &time) != n) { + return -1; + } + assert(type == CHORD_PING); + return process_ping(srv, &id, addr, port, time); +} + +/**********************************************************************/ + +/* pack_pong: pack pong packet */ +int pack_pong(uchar *buf, chordID *id, ulong addr, ushort port, ulong time) +{ + return pack(buf, "cxlsl", CHORD_PONG, id, addr, port, time); +} + +/**********************************************************************/ + +/* unpack_pong: unpack pong packet */ +int unpack_pong(Server *srv, int n, uchar *buf) +{ + uchar type; + ulong addr; + ushort port; + chordID id; + ulong time; + + if (unpack(buf, "cxlsl", &type, &id, &addr, &port, &time) != n) { + return -1; + } + assert(type == CHORD_PONG); + return process_pong(srv, &id, addr, port, time); +} + +/**********************************************************************/ +/**********************************************************************/ + +/* pack_fingers_get: pack get fingers packet */ +int pack_fingers_get(uchar *buf, ulong addr, ushort port, Key *key) +{ + return pack(buf, "cxls", CHORD_FINGERS_GET, key, addr, port); +} + +/**********************************************************************/ + +/* unpack_fingers_get: unpack and process fingers_get packet */ +int unpack_fingers_get(Server *srv, int n, uchar *buf) +{ + uchar type; + Key key; + ulong addr; + ushort port; + + if (unpack(buf, "cxls", &type, &key, &addr, &port) != n) { + return -1; + } + assert(type == CHORD_FINGERS_GET); + return process_fingers_get(srv, addr, port, &key); +} + +#define INCOMPLETE_FINGER_LIST -1 +#define END_FINGER_LIST 0 + +/* pack_fingers_repl: pack repl fingers packet */ +int pack_fingers_repl(uchar *buf, Server *srv) +{ + Finger *f; + int len, l; + + assert(srv); + len = pack(buf, "cxls", CHORD_FINGERS_REPL, &srv->node.id, + srv->node.addr, srv->node.port); + + /* pack fingers */ + for (f = srv->head_flist; f; f = f->next) { + l = pack(buf + len, "xlslls", + &f->node.id, f->node.addr, f->node.port, + f->rtt_avg, f->rtt_dev, (short) f->npings); + len += l; + if (len + l + 1 > BUFSIZE) { + len += pack(buf + len, "c", INCOMPLETE_FINGER_LIST); + return len; + } + } + len += pack(buf + len, "c", END_FINGER_LIST); + return len; +} + +/* unpack_fingers_repl: unpack and process fingers_repl packet */ +int unpack_fingers_repl(Server *srv, int n, uchar *buf) +{ + /* this message is received by a client; + * it shouldn't be received by an i3 server + */ + return process_fingers_repl(srv, 0); +} + +/**********************************************************************/ + +/* pack_traceroute: pack/update traceroute packet */ +/* + * traceroute packet format: + * char pkt_type; + * char ttl; time to live, decremented at every hop. + * When ttl reaches 0, a traceroute_repl packet is returned. + * char hops; number of hops up to the current node (not including the + * client). hops is inceremented at every hop along the + * forward path. hops should be initialized to 0 by the clients. + * ID target_id; target ID for traceroute. + * Node prev_node; previous node (ie., the node which forwarded the packet) + * ulong rtt; rtt... + * ulong dev; ... and std dev frm previous node to this node (in usec) + * Node crt_node; this node + * (list of addresses/ports of the nodes along the traceroute path + * up to this node) + * ulong addr; address... + * ushort port; ... and port number of the client + * .... + */ +int pack_traceroute(uchar *buf, Server *srv, Finger *f, + uchar type, byte ttl, byte hops) +{ + int n = 0; + + /* pack type, ttl and hops fields */ + n = pack(buf + n, "ccc", type, ttl, hops); + + /* skip target ID field */ + n += sizeof_fmt("x"); + + /* pack prev node (for the next node, this is the current node!) */ + n += pack(buf + n, "xlsll", &srv->node.id, srv->node.addr, srv->node.port, + f->rtt_avg, f->rtt_dev); + + /* pack this node field (for next node this is the node itself!) */ + n += pack(buf + n, "xls", &f->node.id, f->node.addr, f->node.port); + + /* skip current list of addresses .. */ + n += sizeof_fmt("ls") * hops; + + /* add current node to the list */ + n += pack(buf + n, "ls", srv->node.addr, srv->node.port); + + return n; +} + +/**********************************************************************/ + +/* unpack_traceroute: unpack and process trace_route packet + * (see pack_traceroute for packet format) + */ +int unpack_traceroute(Server *srv, int n, uchar *buf) +{ + chordID id; + byte type; + byte ttl; + byte hops; + + /* unpack following fields: type, ttl, hops, and target id */ + if (unpack(buf, "cccx", &type, &ttl, &hops, &id) >= n) { + return -1; + } + assert(type == CHORD_TRACEROUTE || type == CHORD_TRACEROUTE_LAST); + return process_traceroute(srv, &id, (char *) buf, type, ttl, hops); +} + +/**********************************************************************/ + +/* pack_traceroute_repl: pack/update traceroute packet */ +/* + * traceroute packet_repl format: + * char pkt_type; + * char ttl; time to live, incremented at every hop (remember, this message + * travls on the reverse path) + * char hops; number of hops from client, decremented at every + * hop along the forward path. When hops reaches 0, + * the packet is dropped. + * ID target_id; target ID for traceroute. + * Node nl_node; next-to-last hop on traceroute path + * ulong rtt; rtt... + * ulong dev; ... and std dev from next-to-last hop to the last hop + * Node l_node; last node of traceroute path + * (list of addresses/ports of the nodes along the traceroute path + * up to this node, starting with the client) + * ulong addr; address... + * ushort port; ... and port number of the client + * .... + */ +int pack_traceroute_repl(uchar *buf, Server *srv, byte ttl, byte hops, + ulong *paddr, ushort *pport, int one_hop) +{ + int n = 0; + + /* pack ttl and hops fields */ + n += pack(buf + n, "ccc", CHORD_TRACEROUTE_REPL, (char) ttl, (char) hops); + + /* skip target ID field */ + n += sizeof_fmt("x"); + + if (one_hop) { + /* one hop path */ + n += pack(buf + n, "xls", &srv->node.id, srv->node.addr, srv->node.port); + /* skip mean rtt, and std dev rtt fields */ + n += sizeof_fmt("ll"); + } else { + /* skip next-to-last node field, and the mean and std dev. to last + * node fields + */ + n += sizeof_fmt("xlsll"); + } + + /* skip last node field */ + n += sizeof_fmt("xls"); + + /* compute source list size -- this is the number of hops plus client */ + n += sizeof_fmt("ls") * hops; + + /* get address and port number of previous node on reverse path + * yes, it's ugly to unpack in a pack function, but... + */ + unpack(buf + n, "ls", paddr, pport); + + return n; +} + +/**********************************************************************/ + +/* unpack_traceroute: unpack and process trace_route packet + * (see pack_traceroute for packet format) + */ +int unpack_traceroute_repl(Server *srv, int n, uchar *buf) +{ + byte type; + byte ttl; + byte hops; + + /* unpack following fields: type, ttl, and hops */ + if (unpack(buf, "ccc", &type, &ttl, &hops) >= n) { + return -1; + } + assert(type == CHORD_TRACEROUTE_REPL); + + return process_traceroute_repl(srv, (char *) buf, ttl, hops); +} === modified file 'i3/chord/process.c' --- i3/chord/process.c 2009-12-11 22:49:11 +0000 +++ i3/chord/process.c 2010-02-11 11:49:47 +0000 @@ -1,284 +1,287 @@ -#include <stdlib.h> -#include <stdio.h> -#include <assert.h> -#include "chord.h" - -int process_data(Server *srv, uchar type, - byte ttl, chordID *id, ushort len, uchar *data) -{ - Node *np; - Finger *pf, *sf; - - CHORD_DEBUG(5, print_process(srv, "process_data", id, -1, -1)); - - /* handle request locally? */ -#ifdef SIM_CHORD - if (sim_chord_is_local(srv, id)) { - /* Upcall goes here... */ - sim_deliver_data(srv, id, len, data); -#else - if (chord_is_local(id)) { - /* Upcall goes here... */ - chord_deliver(len, data); -#endif - return 1; - } - if ((type == CHORD_ROUTE_LAST) && ((pf = pred_finger(srv)) != NULL)) { - /* the previous hop N believes we are responsible for id, - * but we aren't. This means that our predecessor is - * a better successor for N. Just pass the packet to our - * predecessor. Note that ttl takes care of loops! - */ - send_data(srv, CHORD_ROUTE_LAST, ttl, &pf->node, id, len, data); - return 1; - } - if ((sf = succ_finger(srv)) != NULL) { - if (is_between(id, &srv->node.id, &sf->node.id) || - equals(id, &sf->node.id)) { - /* according to our info the successor should be responsible - * for id; send the packet to the successor. - */ - send_data(srv, CHORD_ROUTE_LAST, ttl, &sf->node, id, len, data); - return 1; - } - } - /* send packet to the closest active predecessor (that we know about) */ - np = closest_preceding_node(srv, id, FALSE); - send_data(srv, CHORD_ROUTE, ttl, np, id, len, data); - return 1; -} - -/**********************************************************************/ - -int process_fs(Server *srv, byte ttl, chordID *id, ulong addr, ushort port) -{ - Node *succ, *np; - - if (srv->node.addr == addr && srv->node.port == port) - return 1; - - CHORD_DEBUG(5, print_process(srv, "process_fs", id, addr, port)); - - if (succ_finger(srv) == NULL) { - send_fs_repl(srv, addr, port, - &srv->node.id, srv->node.addr, srv->node.port); - return 0; - } - succ = &(succ_finger(srv)->node); - if (is_between(id, &srv->node.id, &succ->id) || equals(id, &succ->id)) { - send_fs_repl(srv, addr, port, &succ->id, succ->addr, succ->port); - } else { - np = closest_preceding_node(srv, id, FALSE); - send_fs(srv, ttl, np->addr, np->port, id, addr, port); - } - return 1; -} - -/**********************************************************************/ - -int process_fs_repl(Server *srv, chordID *id, ulong addr, ushort port) -{ - int fnew; - - if (srv->node.addr == addr && srv->node.port == port) - return 1; - - CHORD_DEBUG(5, print_process(srv, "process_fs_repl", id, -1, -1)); - insert_finger(srv, id, addr, port, &fnew); - if (fnew == TRUE) { - send_ping(srv, addr, port, - srv->node.addr, srv->node.port, get_current_time()); - } - - return 1; -} - -/**********************************************************************/ - -int process_stab(Server *srv, chordID *id, ulong addr, ushort port) -{ - Finger *pred = pred_finger(srv); - int fnew; - - CHORD_DEBUG(5, print_process(srv, "process_stab", id, addr, port)); - - insert_finger(srv, id, addr, port, &fnew); - if (pred) { - send_stab_repl(srv, addr, port, - &pred->node.id, pred->node.addr, pred->node.port); - } - return 1; -} - -/**********************************************************************/ - -int process_stab_repl(Server *srv, chordID *id, ulong addr, ushort port) -{ - Finger *succ; - int fnew; - - CHORD_DEBUG(5, print_process(srv, "process_stab_repl", id, -1, -1)); - - if ((srv->node.addr == addr) && (srv->node.port == port)) - return 1; - insert_finger(srv, id, addr, port, &fnew); - succ = succ_finger(srv); - send_notify(srv, succ->node.addr, succ->node.port, - &srv->node.id, srv->node.addr, srv->node.port); - if (fnew == TRUE) { - send_ping(srv, addr, port, - srv->node.addr, srv->node.port, get_current_time()); - } - return 1; -} - -/**********************************************************************/ - -int process_notify(Server *srv, chordID *id, ulong addr, ushort port) -{ - int fnew; - - CHORD_DEBUG(5, print_process(srv, "process_notify", id, addr, port)); - insert_finger(srv, id, addr, port, &fnew); - if (fnew == TRUE) { - send_ping(srv, addr, port, - srv->node.addr, srv->node.port, get_current_time()); - } - return 1; -} - -/**********************************************************************/ - -int process_ping(Server *srv, chordID *id, ulong addr, ushort port, ulong time) -{ - int fnew; - Finger *pred; - - CHORD_DEBUG(5, print_process(srv, "process_ping", id, addr, port)); - insert_finger(srv, id, addr, port, &fnew); - pred = pred_finger(srv); - if (fnew == TRUE && ((pred == NULL) || - (pred && is_between(id, &pred->node.id, - &srv->node.id)))) { - send_ping(srv, addr, port, - srv->node.addr, srv->node.port, get_current_time()); - } - - send_pong(srv, addr, port, time); - - return 1; -} - -/**********************************************************************/ - -int process_pong(Server *srv, chordID *id, ulong addr, ushort port, ulong time) -{ - Finger *f, *pred, *newpred; - ulong new_rtt; - int fnew; - - CHORD_DEBUG(5, print_process(srv, "process_pong", id, addr, port)); - f = insert_finger(srv, id, addr, port, &fnew); - f->npings = 0; - new_rtt = get_current_time() - time; /* takes care of overlow */ - update_rtt(&f->rtt_avg, &f->rtt_dev, (long)new_rtt); - - pred = pred_finger(srv); - f->status = F_ACTIVE; /* there is a two-way connectivity to this node */ - newpred = pred_finger(srv); /* check whether pred has changed, i.e., - * f has became the new pred - */ - assert(newpred || (pred == newpred)); - - if (pred != newpred) - chord_update_range(&newpred->node.id, &srv->node.id); - - return 1; -} - -/**********************************************************************/ - -int process_fingers_get(Server *srv, ulong addr, ushort port, Key *key) -{ - CHORD_DEBUG(5, print_process(srv, "process_fingers_get", NULL, addr, port)); - if (match_key(key) == 0) - print_server(srv, "[process_fingers_get: invalid key]", ""); - else - send_fingers_repl(srv, addr, port); - - return 1; -} - -/**********************************************************************/ - -int process_fingers_repl(Server *srv, uchar ret_code) -{ - /* this process should be never invoked by the i3 server, - * as CHORD_FINGERS_REPL is always sent to the client - */ - CHORD_DEBUG(5, print_process(srv, "process_fingers_repl", NULL, 0, 0)); - return 1; -} - -/**********************************************************************/ - -int process_traceroute(Server *srv, chordID *id, char *buf, - uchar type, byte ttl, byte hops) -{ - Finger *f; - - CHORD_DEBUG(5, print_process(srv, "process_traceroute", id, -1, -1)); - - assert(ttl); - ttl--; - - /* handle request locally? */ -#ifdef SIM_CHORD - if (sim_chord_is_local(srv, id) || (ttl == 0)) { - send_traceroute_repl(srv, buf, ttl, hops, (hops ? FALSE : TRUE)); -#else - if (chord_is_local(id) || (ttl == 0)) { - send_traceroute_repl(srv, (uchar *)buf, ttl, hops, (hops ? FALSE : TRUE)); -#endif - return 1; - } - hops++; - if ((type == CHORD_TRACEROUTE_LAST) && (f = pred_finger(srv))) { - /* the previous hop N believes we are responsible for id, - * but we aren't. This means that our predecessor is - * a better successor for N. Just pass the packet to our - * predecessor. Note that ttl takes care of loops. - */ - send_traceroute(srv, f, (uchar *)buf, CHORD_TRACEROUTE_LAST, ttl, hops); - return 1; - } - if ((f = succ_finger(srv)) != NULL) { - if (is_between(id, &srv->node.id, &f->node.id) || - equals(id, &f->node.id)) { - send_traceroute(srv, f, (uchar *)buf, CHORD_TRACEROUTE_LAST, ttl, hops); - return 1; - } - } - - /* send to the closest predecessor (that we know about) */ - f = closest_preceding_finger(srv, id, FALSE); - send_traceroute(srv, f, (uchar *)buf, CHORD_TRACEROUTE, ttl, hops); - return 1; -} - -/**********************************************************************/ - -int process_traceroute_repl(Server *srv, char *buf, - byte ttl, byte hops) -{ - CHORD_DEBUG(5, print_process(srv, "process_traceroute_repl", - &srv->node.id, -1, -1)); - if (hops == 0) - return -1; - hops--; - send_traceroute_repl(srv, (uchar *)buf, ttl, hops, FALSE); - return 1; -} - - - +#include <stdlib.h> +#include <stdio.h> +#include <assert.h> +#include "chord.h" + +int process_data(Server *srv, uchar type, + byte ttl, chordID *id, ushort len, uchar *data) +{ + Node *np; + Finger *pf, *sf; + + CHORD_DEBUG(5, print_process(srv, "process_data", id, -1, -1)); + + /* handle request locally? */ +#ifdef SIM_CHORD + if (sim_chord_is_local(srv, id)) { + /* Upcall goes here... */ + sim_deliver_data(srv, id, len, data); +#else + if (chord_is_local(id)) { + /* Upcall goes here... */ + chord_deliver(len, data); +#endif + return 1; + } + if ((type == CHORD_ROUTE_LAST) && ((pf = pred_finger(srv)) != NULL)) { + /* the previous hop N believes we are responsible for id, + * but we aren't. This means that our predecessor is + * a better successor for N. Just pass the packet to our + * predecessor. Note that ttl takes care of loops! + */ + send_data(srv, CHORD_ROUTE_LAST, ttl, &pf->node, id, len, data); + return 1; + } + if ((sf = succ_finger(srv)) != NULL) { + if (is_between(id, &srv->node.id, &sf->node.id) || + equals(id, &sf->node.id)) { + /* according to our info the successor should be responsible + * for id; send the packet to the successor. + */ + send_data(srv, CHORD_ROUTE_LAST, ttl, &sf->node, id, len, data); + return 1; + } + } + /* send packet to the closest active predecessor (that we know about) */ + np = closest_preceding_node(srv, id, FALSE); + send_data(srv, CHORD_ROUTE, ttl, np, id, len, data); + return 1; +} + +/**********************************************************************/ + +int process_fs(Server *srv, byte ttl, chordID *id, ulong addr, ushort port) +{ + Node *succ, *np; + + if (srv->node.addr == addr && srv->node.port == port) { + return 1; + } + + CHORD_DEBUG(5, print_process(srv, "process_fs", id, addr, port)); + + if (succ_finger(srv) == NULL) { + send_fs_repl(srv, addr, port, + &srv->node.id, srv->node.addr, srv->node.port); + return 0; + } + succ = &(succ_finger(srv)->node); + if (is_between(id, &srv->node.id, &succ->id) || equals(id, &succ->id)) { + send_fs_repl(srv, addr, port, &succ->id, succ->addr, succ->port); + } else { + np = closest_preceding_node(srv, id, FALSE); + send_fs(srv, ttl, np->addr, np->port, id, addr, port); + } + return 1; +} + +/**********************************************************************/ + +int process_fs_repl(Server *srv, chordID *id, ulong addr, ushort port) +{ + int fnew; + + if (srv->node.addr == addr && srv->node.port == port) { + return 1; + } + + CHORD_DEBUG(5, print_process(srv, "process_fs_repl", id, -1, -1)); + insert_finger(srv, id, addr, port, &fnew); + if (fnew == TRUE) { + send_ping(srv, addr, port, + srv->node.addr, srv->node.port, get_current_time()); + } + + return 1; +} + +/**********************************************************************/ + +int process_stab(Server *srv, chordID *id, ulong addr, ushort port) +{ + Finger *pred = pred_finger(srv); + int fnew; + + CHORD_DEBUG(5, print_process(srv, "process_stab", id, addr, port)); + + insert_finger(srv, id, addr, port, &fnew); + if (pred) { + send_stab_repl(srv, addr, port, + &pred->node.id, pred->node.addr, pred->node.port); + } + return 1; +} + +/**********************************************************************/ + +int process_stab_repl(Server *srv, chordID *id, ulong addr, ushort port) +{ + Finger *succ; + int fnew; + + CHORD_DEBUG(5, print_process(srv, "process_stab_repl", id, -1, -1)); + + if ((srv->node.addr == addr) && (srv->node.port == port)) { + return 1; + } + insert_finger(srv, id, addr, port, &fnew); + succ = succ_finger(srv); + send_notify(srv, succ->node.addr, succ->node.port, + &srv->node.id, srv->node.addr, srv->node.port); + if (fnew == TRUE) { + send_ping(srv, addr, port, + srv->node.addr, srv->node.port, get_current_time()); + } + return 1; +} + +/**********************************************************************/ + +int process_notify(Server *srv, chordID *id, ulong addr, ushort port) +{ + int fnew; + + CHORD_DEBUG(5, print_process(srv, "process_notify", id, addr, port)); + insert_finger(srv, id, addr, port, &fnew); + if (fnew == TRUE) { + send_ping(srv, addr, port, + srv->node.addr, srv->node.port, get_current_time()); + } + return 1; +} + +/**********************************************************************/ + +int process_ping(Server *srv, chordID *id, ulong addr, ushort port, ulong time) +{ + int fnew; + Finger *pred; + + CHORD_DEBUG(5, print_process(srv, "process_ping", id, addr, port)); + insert_finger(srv, id, addr, port, &fnew); + pred = pred_finger(srv); + if (fnew == TRUE && ((pred == NULL) || + (pred && is_between(id, &pred->node.id, + &srv->node.id)))) { + send_ping(srv, addr, port, + srv->node.addr, srv->node.port, get_current_time()); + } + + send_pong(srv, addr, port, time); + + return 1; +} + +/**********************************************************************/ + +int process_pong(Server *srv, chordID *id, ulong addr, ushort port, ulong time) +{ + Finger *f, *pred, *newpred; + ulong new_rtt; + int fnew; + + CHORD_DEBUG(5, print_process(srv, "process_pong", id, addr, port)); + f = insert_finger(srv, id, addr, port, &fnew); + f->npings = 0; + new_rtt = get_current_time() - time; /* takes care of overlow */ + update_rtt(&f->rtt_avg, &f->rtt_dev, (long) new_rtt); + + pred = pred_finger(srv); + f->status = F_ACTIVE; /* there is a two-way connectivity to this node */ + newpred = pred_finger(srv); /* check whether pred has changed, i.e., + * f has became the new pred + */ + assert(newpred || (pred == newpred)); + + if (pred != newpred) { + chord_update_range(&newpred->node.id, &srv->node.id); + } + + return 1; +} + +/**********************************************************************/ + +int process_fingers_get(Server *srv, ulong addr, ushort port, Key *key) +{ + CHORD_DEBUG(5, print_process(srv, "process_fingers_get", NULL, addr, port)); + if (match_key(key) == 0) { + print_server(srv, "[process_fingers_get: invalid key]", ""); + } else { + send_fingers_repl(srv, addr, port); + } + + return 1; +} + +/**********************************************************************/ + +int process_fingers_repl(Server *srv, uchar ret_code) +{ + /* this process should be never invoked by the i3 server, + * as CHORD_FINGERS_REPL is always sent to the client + */ + CHORD_DEBUG(5, print_process(srv, "process_fingers_repl", NULL, 0, 0)); + return 1; +} + +/**********************************************************************/ + +int process_traceroute(Server *srv, chordID *id, char *buf, + uchar type, byte ttl, byte hops) +{ + Finger *f; + + CHORD_DEBUG(5, print_process(srv, "process_traceroute", id, -1, -1)); + + assert(ttl); + ttl--; + + /* handle request locally? */ +#ifdef SIM_CHORD + if (sim_chord_is_local(srv, id) || (ttl == 0)) { + send_traceroute_repl(srv, buf, ttl, hops, (hops ? FALSE : TRUE)); +#else + if (chord_is_local(id) || (ttl == 0)) { + send_traceroute_repl(srv, (uchar *) buf, ttl, hops, (hops ? FALSE : TRUE)); +#endif + return 1; + } + hops++; + if ((type == CHORD_TRACEROUTE_LAST) && (f = pred_finger(srv))) { + /* the previous hop N believes we are responsible for id, + * but we aren't. This means that our predecessor is + * a better successor for N. Just pass the packet to our + * predecessor. Note that ttl takes care of loops. + */ + send_traceroute(srv, f, (uchar *) buf, CHORD_TRACEROUTE_LAST, ttl, hops); + return 1; + } + if ((f = succ_finger(srv)) != NULL) { + if (is_between(id, &srv->node.id, &f->node.id) || + equals(id, &f->node.id)) { + send_traceroute(srv, f, (uchar *) buf, CHORD_TRACEROUTE_LAST, ttl, hops); + return 1; + } + } + + /* send to the closest predecessor (that we know about) */ + f = closest_preceding_finger(srv, id, FALSE); + send_traceroute(srv, f, (uchar *) buf, CHORD_TRACEROUTE, ttl, hops); + return 1; +} + +/**********************************************************************/ + +int process_traceroute_repl(Server *srv, char *buf, + byte ttl, byte hops) +{ + CHORD_DEBUG(5, print_process(srv, "process_traceroute_repl", + &srv->node.id, -1, -1)); + if (hops == 0) { + return -1; + } + hops--; + send_traceroute_repl(srv, (uchar *) buf, ttl, hops, FALSE); + return 1; +} === modified file 'i3/chord/sendpkt.c' --- i3/chord/sendpkt.c 2009-12-11 22:49:11 +0000 +++ i3/chord/sendpkt.c 2010-02-11 11:49:47 +0000 @@ -1,194 +1,189 @@ -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <time.h> -#include <assert.h> -#include <unistd.h> -#include <fcntl.h> -#include <errno.h> -#include <sys/types.h> -#include <sys/socket.h> -#include <netinet/in.h> -#include <arpa/inet.h> -#include <netdb.h> -#include "chord.h" - -void send_data(Server *srv, uchar type, byte ttl, Node *np, chordID *id, - ushort n, uchar *data) -{ - byte buf[BUFSIZE]; - - CHORD_DEBUG(5, print_send(srv, "send_data", id, np->addr, np->port)); - send_raw(srv, np->addr, np->port, pack_data(buf, type, - ttl, id, n, data), buf); -} - -/**********************************************************************/ - -void send_fs(Server *srv, byte ttl, ulong to_addr, ushort to_port, - chordID *id, ulong addr, ushort port) -{ - byte buf[BUFSIZE]; - - CHORD_DEBUG(5, print_send(srv, "send_fs", id, to_addr, to_port)); - send_raw(srv, to_addr, to_port, pack_fs(buf, ttl, id, addr, port), buf); -} - -/**********************************************************************/ - -void send_fs_repl(Server *srv, ulong to_addr, ushort to_port, - chordID *id, ulong addr, ushort port) -{ - byte buf[BUFSIZE]; - - CHORD_DEBUG(5, print_send(srv, "send_fs_repl", id, to_addr, to_port)); - send_raw(srv, to_addr, to_port, pack_fs_repl(buf, id, addr, port), buf); -} - -/**********************************************************************/ - -void send_stab(Server *srv, ulong to_addr, ushort to_port, - chordID *id, ulong addr, ushort port) -{ - byte buf[BUFSIZE]; - - CHORD_DEBUG(5, print_send(srv, "send_stab", id, to_addr, to_port)); - send_raw(srv, to_addr, to_port, pack_stab(buf, id, addr, port), buf); -} - -/**********************************************************************/ - -void send_stab_repl(Server *srv, ulong to_addr, ushort to_port, - chordID *id, ulong addr, ushort port) -{ - byte buf[BUFSIZE]; - - CHORD_DEBUG(5, print_send(srv, "send_stab_repl", id, to_addr, to_port)); - send_raw(srv, to_addr, to_port, pack_stab_repl(buf, id, addr, port), buf); -} - -/**********************************************************************/ - -void send_notify(Server *srv, ulong to_addr, ushort to_port, - chordID *id, ulong addr, ushort port) -{ - byte buf[BUFSIZE]; - - CHORD_DEBUG(5, print_send(srv, "send_notify", id, to_addr, to_port)); - send_raw(srv, to_addr, to_port, pack_notify(buf, id, addr, port), buf); -} - -/**********************************************************************/ - -void send_ping(Server *srv, ulong to_addr, ushort to_port, - ulong addr, ushort port, ulong time) -{ - byte buf[BUFSIZE]; - - CHORD_DEBUG(5, print_send(srv, "send_ping", - &srv->node.id, to_addr, to_port)); - send_raw(srv, to_addr, to_port, - pack_ping(buf, &srv->node.id, addr, port, time), buf); -} - -/**********************************************************************/ - -void send_pong(Server *srv, ulong to_addr, ushort to_port, ulong time) -{ - byte buf[BUFSIZE]; - - CHORD_DEBUG(5, print_send(srv, "send_pong", - &srv->node.id, to_addr, to_port)); - send_raw(srv, to_addr, to_port, - pack_pong(buf, &srv->node.id, - srv->node.addr, srv->node.port, time), buf); -} - - -/**********************************************************************/ - -void send_fingers_get(Server *srv, ulong to_addr, ushort to_port, - ulong addr, ushort port, Key *key) -{ - byte buf[BUFSIZE]; - - CHORD_DEBUG(5, print_send(srv, "send_fingers_get", NULL, to_addr, to_port)); - send_raw(srv, to_addr, to_port, - pack_fingers_get(buf, addr, port, key), buf); -} - -/**********************************************************************/ - -void send_fingers_repl(Server *srv, ulong to_addr, ushort to_port) -{ - byte buf[BUFSIZE]; - - CHORD_DEBUG(5, print_send(srv, "send_fingers_repl", - &srv->node.id, to_addr, to_port)); - send_raw(srv, to_addr, to_port, - pack_fingers_repl(buf, srv), buf); -} - - - -/**********************************************************************/ - -void send_traceroute(Server *srv, Finger *f, uchar *buf, uchar type, - byte ttl, byte hops) -{ - CHORD_DEBUG(5, print_send(srv, "send_traceroute", &srv->node.id, -1, -1)); - send_raw(srv, f->node.addr, f->node.port, - pack_traceroute(buf, srv, f, type, ttl, hops), buf); -} - - -/**********************************************************************/ - -void send_traceroute_repl(Server *srv, uchar *buf, int ttl, - int hops, int one_hop) -{ - ulong to_addr; - ushort to_port; - int n; - - CHORD_DEBUG(5, print_send(srv, "send_traceroute_repl", - &srv->node.id, -1, -1)); - n = pack_traceroute_repl(buf, srv, ttl, hops, &to_addr, &to_port, one_hop); - send_raw(srv, to_addr, to_port, n, buf); -} - - - -/**********************************************************************/ - -#ifdef SIM_CHORD - -/* send_raw: send datagram to remote addr:port */ -void send_raw(Server *srv, in_addr_t addr, in_port_t port, int n, uchar *buf) -{ - /* XXX */ - //if ((srv->node.addr + addr) % 9 == 1) - // return; - /* XXX */ - - sim_send_raw(srv, addr, port, n, buf); -} - -#else - -/* send_raw: send datagram to remote addr:port */ -void send_raw(Server *srv, in_addr_t addr, in_port_t port, int n, uchar *buf) -{ - struct sockaddr_in dest; - - memset(&dest, 0, sizeof(dest)); - dest.sin_family = AF_INET; - dest.sin_port = htons(port); - dest.sin_addr.s_addr = htonl(addr); - - if (sendto(srv->out_sock, buf, n, 0, (struct sockaddr *) &dest, - sizeof(dest)) < 0) - weprintf("sendto failed:"); /* ignore errors for now */ -} - -#endif +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <assert.h> +#include <unistd.h> +#include <fcntl.h> +#include <errno.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <netdb.h> +#include "chord.h" + +void send_data(Server *srv, uchar type, byte ttl, Node *np, chordID *id, + ushort n, uchar *data) +{ + byte buf[BUFSIZE]; + + CHORD_DEBUG(5, print_send(srv, "send_data", id, np->addr, np->port)); + send_raw(srv, np->addr, np->port, pack_data(buf, type, + ttl, id, n, data), buf); +} + +/**********************************************************************/ + +void send_fs(Server *srv, byte ttl, ulong to_addr, ushort to_port, + chordID *id, ulong addr, ushort port) +{ + byte buf[BUFSIZE]; + + CHORD_DEBUG(5, print_send(srv, "send_fs", id, to_addr, to_port)); + send_raw(srv, to_addr, to_port, pack_fs(buf, ttl, id, addr, port), buf); +} + +/**********************************************************************/ + +void send_fs_repl(Server *srv, ulong to_addr, ushort to_port, + chordID *id, ulong addr, ushort port) +{ + byte buf[BUFSIZE]; + + CHORD_DEBUG(5, print_send(srv, "send_fs_repl", id, to_addr, to_port)); + send_raw(srv, to_addr, to_port, pack_fs_repl(buf, id, addr, port), buf); +} + +/**********************************************************************/ + +void send_stab(Server *srv, ulong to_addr, ushort to_port, + chordID *id, ulong addr, ushort port) +{ + byte buf[BUFSIZE]; + + CHORD_DEBUG(5, print_send(srv, "send_stab", id, to_addr, to_port)); + send_raw(srv, to_addr, to_port, pack_stab(buf, id, addr, port), buf); +} + +/**********************************************************************/ + +void send_stab_repl(Server *srv, ulong to_addr, ushort to_port, + chordID *id, ulong addr, ushort port) +{ + byte buf[BUFSIZE]; + + CHORD_DEBUG(5, print_send(srv, "send_stab_repl", id, to_addr, to_port)); + send_raw(srv, to_addr, to_port, pack_stab_repl(buf, id, addr, port), buf); +} + +/**********************************************************************/ + +void send_notify(Server *srv, ulong to_addr, ushort to_port, + chordID *id, ulong addr, ushort port) +{ + byte buf[BUFSIZE]; + + CHORD_DEBUG(5, print_send(srv, "send_notify", id, to_addr, to_port)); + send_raw(srv, to_addr, to_port, pack_notify(buf, id, addr, port), buf); +} + +/**********************************************************************/ + +void send_ping(Server *srv, ulong to_addr, ushort to_port, + ulong addr, ushort port, ulong time) +{ + byte buf[BUFSIZE]; + + CHORD_DEBUG(5, print_send(srv, "send_ping", + &srv->node.id, to_addr, to_port)); + send_raw(srv, to_addr, to_port, + pack_ping(buf, &srv->node.id, addr, port, time), buf); +} + +/**********************************************************************/ + +void send_pong(Server *srv, ulong to_addr, ushort to_port, ulong time) +{ + byte buf[BUFSIZE]; + + CHORD_DEBUG(5, print_send(srv, "send_pong", + &srv->node.id, to_addr, to_port)); + send_raw(srv, to_addr, to_port, + pack_pong(buf, &srv->node.id, + srv->node.addr, srv->node.port, time), buf); +} + +/**********************************************************************/ + +void send_fingers_get(Server *srv, ulong to_addr, ushort to_port, + ulong addr, ushort port, Key *key) +{ + byte buf[BUFSIZE]; + + CHORD_DEBUG(5, print_send(srv, "send_fingers_get", NULL, to_addr, to_port)); + send_raw(srv, to_addr, to_port, + pack_fingers_get(buf, addr, port, key), buf); +} + +/**********************************************************************/ + +void send_fingers_repl(Server *srv, ulong to_addr, ushort to_port) +{ + byte buf[BUFSIZE]; + + CHORD_DEBUG(5, print_send(srv, "send_fingers_repl", + &srv->node.id, to_addr, to_port)); + send_raw(srv, to_addr, to_port, + pack_fingers_repl(buf, srv), buf); +} + +/**********************************************************************/ + +void send_traceroute(Server *srv, Finger *f, uchar *buf, uchar type, + byte ttl, byte hops) +{ + CHORD_DEBUG(5, print_send(srv, "send_traceroute", &srv->node.id, -1, -1)); + send_raw(srv, f->node.addr, f->node.port, + pack_traceroute(buf, srv, f, type, ttl, hops), buf); +} + +/**********************************************************************/ + +void send_traceroute_repl(Server *srv, uchar *buf, int ttl, + int hops, int one_hop) +{ + ulong to_addr; + ushort to_port; + int n; + + CHORD_DEBUG(5, print_send(srv, "send_traceroute_repl", + &srv->node.id, -1, -1)); + n = pack_traceroute_repl(buf, srv, ttl, hops, &to_addr, &to_port, one_hop); + send_raw(srv, to_addr, to_port, n, buf); +} + +/**********************************************************************/ + +#ifdef SIM_CHORD + +/* send_raw: send datagram to remote addr:port */ +void send_raw(Server *srv, in_addr_t addr, in_port_t port, int n, uchar *buf) +{ + /* XXX */ + //if ((srv->node.addr + addr) % 9 == 1) + // return; + /* XXX */ + + sim_send_raw(srv, addr, port, n, buf); +} + +#else + +/* send_raw: send datagram to remote addr:port */ +void send_raw(Server *srv, in_addr_t addr, in_port_t port, int n, uchar *buf) +{ + struct sockaddr_in dest; + + memset(&dest, 0, sizeof(dest)); + dest.sin_family = AF_INET; + dest.sin_port = htons(port); + dest.sin_addr.s_addr = htonl(addr); + + if (sendto(srv->out_sock, buf, n, 0, (struct sockaddr *) &dest, + sizeof(dest)) < 0) { + weprintf("sendto failed:"); /* ignore errors for now */ + } +} + +#endif === modified file 'i3/chord/stabilize.c' --- i3/chord/stabilize.c 2010-01-12 12:35:31 +0000 +++ i3/chord/stabilize.c 2010-02-11 11:49:47 +0000 @@ -1,387 +1,399 @@ -#include <stdlib.h> -#include <sys/time.h> -#include <string.h> -#include <signal.h> -#include <assert.h> -#include <sys/socket.h> -#include <netinet/in.h> -#include <arpa/inet.h> - -#include "chord.h" -#include "../utils/gen_utils.h" - -/* Global variable that is a pointer to srv in chord main */ -Server *srv_ref; - -/* local functions */ -static void fix_fingers(Server *srv); -static void fix_succs_preds(Server *srv); -static void ping(Server *srv); -static void clean_finger_list(Server *srv); - -/* stabilize: the following things are done periodically - * - stabilize successor by asking for its predecessor - * - fix one backup successor - * - fix one proper finger - * - ping one node in the finger list (the finger list includes - * the backup successors, the proper fingers and the predecessor) - * - ping any node in the finger list that has not replied to the - * previous ping - */ - -#define CHORD_CLEAN_PERIOD 60 - -void stabilize(Server *srv) -{ - static int idx = 0, i; - Finger *succ, *pred; - - /* Hack to get around the fact that parameters - * cannot be passed when setting signal timers - */ -#ifndef SIM_CHORD - srv = srv_ref; - /* Set next stabilize time */ - do { - srv->next_stabilize_us += STABILIZE_PERIOD; - } while(srv->next_stabilize_us <= wall_time()); -#endif - - /* While there is no successor, we fix that! */ - if (srv->head_flist == NULL) { -#ifndef SIM_CHORD - for (i = 0; ((i < nknown) && (i < MAX_SIMJOIN)); i++) { - send_fs(srv, DEF_TTL, well_known[i].addr, well_known[i].port, - &srv->node.id, srv->node.addr, srv->node.port); - send_ping(srv, well_known[i].addr, well_known[i].port, - srv->node.addr, srv->node.port, get_current_time()); - } -#else - { - Server *s; -#define SRV_PRESENT 2 - /* join by contacting two nodes, already in the system */ - for (i = 0; i < 2; i++) { - s = get_random_server(srv->node.addr, SRV_PRESENT); - if (s != NULL) { - send_fs(srv, DEF_TTL, s->node.addr, s->node.port, - &srv->node.id, srv->node.addr, srv->node.port); - send_ping(srv, s->node.addr, s->node.port, - srv->node.addr, srv->node.port, get_current_time()); - } - } - } -#endif - return; - } - - /* ping one node in the finger list; these nodes are - * pinged in a round robin fashion. - * In ddition, ping all nodes which have not replyed to previous pings - */ - ping(srv); - - /* stabilize successor */ - if ((succ = succ_finger(srv)) == NULL) - return; - send_stab(srv, succ->node.addr, succ->node.port, - &srv->node.id, srv->node.addr, srv->node.port); - - /* ping predecessor. Normally we should hear from our - * predecessor via the stabilize message. However, if we - * cannot communicate with our true predecessor, our predecessor - * will be another node, so we need to ping it... - */ -#define PERIOD_PING_PRED 5 - if (idx % PERIOD_PING_PRED == 0) { - pred = pred_finger(srv); - assert(pred); - send_ping(srv, pred->node.addr, pred->node.port, - srv->node.addr, srv->node.port, get_current_time()); - } - - /* fix one backup successor and predessors in a round-robin fashion */ - fix_succs_preds(srv); - - /* fix one proper finger that is not a backup successor; - * backup successors are fixed in a round-robin fashion - */ - fix_fingers(srv); - - if ((idx++) % CHORD_CLEAN_PERIOD == 0) { - /* remove all nodes in the finger list that are neither (1) - * backup successors, nor (2) proper fingers, and nor (3) backup - * predecessors - */ - clean_finger_list(srv); - } -} - - -/**********************************************************************/ - -void fix_fingers(Server *srv) -{ - Finger *f, *succ = succ_finger(srv); - chordID id = successor(srv->node.id, srv->to_fix_finger); - chordID to_id = successor(srv->node.id, NFINGERS-1); - - CHORD_DEBUG(5, print_fun(srv, "fix_finger", &id)); - - /* Only loop across most significant fingers */ - if (is_between(&id, &srv->node.id, &succ->node.id) || - (srv->to_fix_finger == 0)) { - /* the problem we are trying to solve here is the one of - * loopy graphs, i.e., graphs that are locally consistent - * but globally inconsistent (see the Chord TR). Loopy - * graphs are quite common in the Internet where the - * communication is not necessary symmetric or transitive - * (i.e., A can reach B and C, but B cannot reach C). - * Loopy graphs cause in lookup failures, as two loops - * that originate in different parts of the ring can reach - * different targets. - * To alleviate loopy graph we ask a random node to resolve - * a query to a random id between us and our successor. - */ - random_between(&srv->node.id, &succ->node.id, &id); -#ifdef SIM_CHORD - Server *s; - s = get_random_server(srv->node.addr, SRV_PRESENT); - if (s) { - send_fs(srv, DEF_TTL, s->node.addr, s->node.port, - &id, srv->node.addr, srv->node.port); - } -#else - Node *n; - n = &well_known[random() % nknown]; - if (nknown) - send_fs(srv, DEF_TTL, n->addr, n->port, - &id, srv->node.addr, srv->node.port); -#endif // SIM_CHORD - srv->to_fix_finger = NFINGERS-1; - } else - srv->to_fix_finger--; - - /* ask one of our fingers to find the proper finger corresponding to id. - * preferable this is a far away finger, that share as little routing - * information as possible with us - */ - if ((f = closest_preceding_finger(srv, &to_id, FALSE)) == NULL) - /* settle for successor... */ - f = succ; - if (f) { - send_fs(srv, DEF_TTL, f->node.addr, f->node.port, - &id, srv->node.addr, srv->node.port); - - /* once in a while try to get a better predecessor, as well */ - if (srv->to_fix_finger == NFINGERS-1) { - if (PRED(srv)) { - random_between(&(PRED(srv)->node.id), &srv->node.id, &id); - send_fs(srv, DEF_TTL, f->node.addr, f->node.port, - &id, srv->node.addr, srv->node.port); - } - } - } -} - - -/**********************************************************************/ -/* fix backup successors and predecessors in a round-robin fashion */ -/**********************************************************************/ - -void fix_succs_preds(Server *srv) -{ - int k; - Finger *f, *succ; - chordID id; - - CHORD_DEBUG(5, print_fun(srv, "fix_successors", &f->node.id)); - - if (succ_finger(srv) == NULL) - return; - - /* find the next successor to be fixed... */ - for (f = succ_finger(srv), k = 0; - (k < srv->to_fix_backup) && f->next; - k++, f = f->next); - /* ... no more successors to be fixed; restart */ - if (f->next == NULL) { - srv->to_fix_backup = 0; - return; - } - - /* find f's successor */ - id = successor(f->node.id, 0); - send_fs(srv, DEF_TTL, f->node.addr, f->node.port, - &id, srv->node.addr, srv->node.port); - succ = f; - - /* now fix predecessors; this is not part of the Chord protocol, - * but in pactice having more than one predecessor is more robust - * - * use same index (to_fix_backup) to fix predecessor, as well. Note - * that here we assume that NPREDECESSORS <= NSUCCESSORS - */ - for (f = pred_finger(srv), k = 0; (k < NPREDECESSORS) && f->prev; - k++, f = f->prev) { - if (f->next == NULL) - /* f is our known predecessor; if there is a node between our - * predecessor and us, we'll get it during the next stabilization - * round - */ - continue; - if (f == succ) - /* f is both a successor and predecessor */ - break; - if (k == srv->to_fix_backup) { - /* fix predecessor */ - random_between(&f->node.id, &f->next->node.id, &id); - send_fs(srv, DEF_TTL, f->node.addr, f->node.port, - &id, srv->node.addr, srv->node.port); - break; - } - } - - srv->to_fix_backup++; - if (srv->to_fix_backup >= NSUCCESSORS) - srv->to_fix_backup = 0; -} - -/************************************************************************/ - -void ping(Server *srv) -{ - int i; - struct in_addr ia; - Finger *f, *f_next, *f_pinged = NULL; - - /* ping every finger who is still waiting for reply to a previous ping, - * and the to_ping-th finger in the list - */ - for (f = srv->head_flist, i = 0; f; i++) { - - if (f->npings >= PING_THRESH) { -#define ADDR_STR_LEN 16 - char srv_addr[ADDR_STR_LEN+1]; - char dropped_addr[ADDR_STR_LEN+1]; - ia.s_addr = htonl(srv->node.addr); - strncpy( srv_addr, inet_ntoa(ia), ADDR_STR_LEN ); - ia.s_addr = htonl(f->node.addr); - strncpy( dropped_addr, inet_ntoa(ia), ADDR_STR_LEN ); - -#ifdef SIM_CHORD - // print_fun(srv, "dropping finger", &f->node.id); -#else - weprintf("dropping finger[%d] %s:%d (at %s:%d)\n", - i, dropped_addr, f->node.port, - srv_addr, srv->node.port); -#endif - f_next = f->next; - remove_finger(srv, f); - } else { - if (f->npings || (srv->to_ping == i)) { - f->npings++; - send_ping(srv, f->node.addr, f->node.port, - srv->node.addr, srv->node.port, get_current_time()); - if (srv->to_ping == i) - f_pinged = f; - } - f_next = f->next; - } - f = f_next; - } - - if (!f_pinged || !(f_pinged->next)) - srv->to_ping = 0; - else - srv->to_ping++; -} - -/********************************************************************** - * keep only (1) backup successors, (2) proper fingers, and (3) predecessor; - * remove anything else from finger list - ***********************************************************************/ - -void clean_finger_list(Server *srv) -{ - Finger *f, *f_lastsucc, *f_lastpred, *f_tmp; - int k; - chordID id; - - /* skip successor list */ - for (f = srv->head_flist, k = 0; f && (k < NSUCCESSORS-1); f = f->next, k++); - if (f == NULL || f->next == NULL) - return; - f_lastsucc = f; - - /* start from the tail and skip predecessors */ - for (f = srv->tail_flist, k = 0; k < NPREDECESSORS-1; f = f->prev, k++) { - if (f == f_lastsucc) - /* finger list contains only of backup successors and predecesor */ - return; - } - f_lastpred = f; - f = f_lastpred->prev; /* First disposable finger */ - - /* keep only unique (proper) fingers */ - for (k = NFINGERS - 1; k >= 0; k--) { - - if (f == f_lastsucc) - return; - - /* compute srv.id + 2^k */ - id = successor(srv->node.id, k); - - if (is_between(&id, &f_lastpred->node.id, &srv->node.id) || - equals(&id, &f_lastpred->node.id)) { - /* proper finger for id is one of the (backup) predecessors */ - continue; - } - - if (is_between(&id, &srv->node.id, &f_lastsucc->node.id) || - equals(&id, &srv->node.id)) - /* proper finger for id is one of the (backup) successors */ - break; - - if (is_between(&f->node.id, &srv->node.id, &id)) { - /* f cannot be a proper finger for id, because it - * is between current node and id; try next finger - */ - continue; - } - - /* f is a possible proper finger for id */ - while (1) { - if (f->prev == NULL || f == f_lastsucc) - return; - if (is_between(&f->prev->node.id, &id, &f->node.id) || - equals(&f->prev->node.id, &id)) { - /* this is not a proper finger (i.e., f's predecessor - * is between id and f), so remove f - */ - f_tmp = f; - f = f->prev; - remove_finger(srv, f_tmp); - } else { - /* f is a proper finger */ - f = f->prev; - break; - } - } - } -} - - - -/**********************************************************************/ -/* set_stabilize_timer: Set first stabilize time (to now). */ -/**********************************************************************/ - -void set_stabilize_timer(void) -{ - /* do not use get_current_time(), because we need the - * resolution of uint64_t - */ - srv_ref->next_stabilize_us = wall_time(); -} - +#include <stdlib.h> +#include <sys/time.h> +#include <string.h> +#include <signal.h> +#include <assert.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> + +#include "chord.h" +#include "../utils/gen_utils.h" + +/* Global variable that is a pointer to srv in chord main */ +Server *srv_ref; + +/* local functions */ +static void fix_fingers(Server *srv); +static void fix_succs_preds(Server *srv); +static void ping(Server *srv); +static void clean_finger_list(Server *srv); + +/* stabilize: the following things are done periodically + * - stabilize successor by asking for its predecessor + * - fix one backup successor + * - fix one proper finger + * - ping one node in the finger list (the finger list includes + * the backup successors, the proper fingers and the predecessor) + * - ping any node in the finger list that has not replied to the + * previous ping + */ + +#define CHORD_CLEAN_PERIOD 60 + +void stabilize(Server *srv) +{ + static int idx = 0, i; + Finger *succ, *pred; + + /* Hack to get around the fact that parameters + * cannot be passed when setting signal timers + */ +#ifndef SIM_CHORD + srv = srv_ref; + /* Set next stabilize time */ + do { + srv->next_stabilize_us += STABILIZE_PERIOD; + } while (srv->next_stabilize_us <= wall_time()); +#endif + + /* While there is no successor, we fix that! */ + if (srv->head_flist == NULL) { +#ifndef SIM_CHORD + for (i = 0; ((i < nknown) && (i < MAX_SIMJOIN)); i++) { + send_fs(srv, DEF_TTL, well_known[i].addr, well_known[i].port, + &srv->node.id, srv->node.addr, srv->node.port); + send_ping(srv, well_known[i].addr, well_known[i].port, + srv->node.addr, srv->node.port, get_current_time()); + } +#else + { + Server *s; +#define SRV_PRESENT 2 + /* join by contacting two nodes, already in the system */ + for (i = 0; i < 2; i++) { + s = get_random_server(srv->node.addr, SRV_PRESENT); + if (s != NULL) { + send_fs(srv, DEF_TTL, s->node.addr, s->node.port, + &srv->node.id, srv->node.addr, srv->node.port); + send_ping(srv, s->node.addr, s->node.port, + srv->node.addr, srv->node.port, get_current_time()); + } + } + } +#endif + return; + } + + /* ping one node in the finger list; these nodes are + * pinged in a round robin fashion. + * In ddition, ping all nodes which have not replyed to previous pings + */ + ping(srv); + + /* stabilize successor */ + if ((succ = succ_finger(srv)) == NULL) { + return; + } + send_stab(srv, succ->node.addr, succ->node.port, + &srv->node.id, srv->node.addr, srv->node.port); + + /* ping predecessor. Normally we should hear from our + * predecessor via the stabilize message. However, if we + * cannot communicate with our true predecessor, our predecessor + * will be another node, so we need to ping it... + */ +#define PERIOD_PING_PRED 5 + if (idx % PERIOD_PING_PRED == 0) { + pred = pred_finger(srv); + assert(pred); + send_ping(srv, pred->node.addr, pred->node.port, + srv->node.addr, srv->node.port, get_current_time()); + } + + /* fix one backup successor and predessors in a round-robin fashion */ + fix_succs_preds(srv); + + /* fix one proper finger that is not a backup successor; + * backup successors are fixed in a round-robin fashion + */ + fix_fingers(srv); + + if ((idx++) % CHORD_CLEAN_PERIOD == 0) { + /* remove all nodes in the finger list that are neither (1) + * backup successors, nor (2) proper fingers, and nor (3) backup + * predecessors + */ + clean_finger_list(srv); + } +} + +/**********************************************************************/ + +void fix_fingers(Server *srv) +{ + Finger *f, *succ = succ_finger(srv); + chordID id = successor(srv->node.id, srv->to_fix_finger); + chordID to_id = successor(srv->node.id, NFINGERS - 1); + + CHORD_DEBUG(5, print_fun(srv, "fix_finger", &id)); + + /* Only loop across most significant fingers */ + if (is_between(&id, &srv->node.id, &succ->node.id) || + (srv->to_fix_finger == 0)) { + /* the problem we are trying to solve here is the one of + * loopy graphs, i.e., graphs that are locally consistent + * but globally inconsistent (see the Chord TR). Loopy + * graphs are quite common in the Internet where the + * communication is not necessary symmetric or transitive + * (i.e., A can reach B and C, but B cannot reach C). + * Loopy graphs cause in lookup failures, as two loops + * that originate in different parts of the ring can reach + * different targets. + * To alleviate loopy graph we ask a random node to resolve + * a query to a random id between us and our successor. + */ + random_between(&srv->node.id, &succ->node.id, &id); +#ifdef SIM_CHORD + Server *s; + s = get_random_server(srv->node.addr, SRV_PRESENT); + if (s) { + send_fs(srv, DEF_TTL, s->node.addr, s->node.port, + &id, srv->node.addr, srv->node.port); + } +#else + Node *n; + n = &well_known[random() % nknown]; + if (nknown) { + send_fs(srv, DEF_TTL, n->addr, n->port, + &id, srv->node.addr, srv->node.port); + } +#endif // SIM_CHORD + srv->to_fix_finger = NFINGERS - 1; + } else { + srv->to_fix_finger--; + } + + /* ask one of our fingers to find the proper finger corresponding to id. + * preferable this is a far away finger, that share as little routing + * information as possible with us + */ + if ((f = closest_preceding_finger(srv, &to_id, FALSE)) == NULL) { + /* settle for successor... */ + f = succ; + } + if (f) { + send_fs(srv, DEF_TTL, f->node.addr, f->node.port, + &id, srv->node.addr, srv->node.port); + + /* once in a while try to get a better predecessor, as well */ + if (srv->to_fix_finger == NFINGERS - 1) { + if (PRED(srv)) { + random_between(&(PRED(srv)->node.id), &srv->node.id, &id); + send_fs(srv, DEF_TTL, f->node.addr, f->node.port, + &id, srv->node.addr, srv->node.port); + } + } + } +} + +/**********************************************************************/ +/* fix backup successors and predecessors in a round-robin fashion */ +/**********************************************************************/ + +void fix_succs_preds(Server *srv) +{ + int k; + Finger *f, *succ; + chordID id; + + CHORD_DEBUG(5, print_fun(srv, "fix_successors", &f->node.id)); + + if (succ_finger(srv) == NULL) { + return; + } + + /* find the next successor to be fixed... */ + for (f = succ_finger(srv), k = 0; + (k < srv->to_fix_backup) && f->next; + k++, f = f->next) { + ; + } + /* ... no more successors to be fixed; restart */ + if (f->next == NULL) { + srv->to_fix_backup = 0; + return; + } + + /* find f's successor */ + id = successor(f->node.id, 0); + send_fs(srv, DEF_TTL, f->node.addr, f->node.port, + &id, srv->node.addr, srv->node.port); + succ = f; + + /* now fix predecessors; this is not part of the Chord protocol, + * but in pactice having more than one predecessor is more robust + * + * use same index (to_fix_backup) to fix predecessor, as well. Note + * that here we assume that NPREDECESSORS <= NSUCCESSORS + */ + for (f = pred_finger(srv), k = 0; (k < NPREDECESSORS) && f->prev; + k++, f = f->prev) { + if (f->next == NULL) { + /* f is our known predecessor; if there is a node between our + * predecessor and us, we'll get it during the next stabilization + * round + */ + continue; + } + if (f == succ) { + /* f is both a successor and predecessor */ + break; + } + if (k == srv->to_fix_backup) { + /* fix predecessor */ + random_between(&f->node.id, &f->next->node.id, &id); + send_fs(srv, DEF_TTL, f->node.addr, f->node.port, + &id, srv->node.addr, srv->node.port); + break; + } + } + + srv->to_fix_backup++; + if (srv->to_fix_backup >= NSUCCESSORS) { + srv->to_fix_backup = 0; + } +} + +/************************************************************************/ + +void ping(Server *srv) +{ + int i; + struct in_addr ia; + Finger *f, *f_next, *f_pinged = NULL; + + /* ping every finger who is still waiting for reply to a previous ping, + * and the to_ping-th finger in the list + */ + for (f = srv->head_flist, i = 0; f; i++) { + if (f->npings >= PING_THRESH) { +#define ADDR_STR_LEN 16 + char srv_addr[ADDR_STR_LEN + 1]; + char dropped_addr[ADDR_STR_LEN + 1]; + ia.s_addr = htonl(srv->node.addr); + strncpy( srv_addr, inet_ntoa(ia), ADDR_STR_LEN ); + ia.s_addr = htonl(f->node.addr); + strncpy( dropped_addr, inet_ntoa(ia), ADDR_STR_LEN ); + +#ifdef SIM_CHORD + // print_fun(srv, "dropping finger", &f->node.id); +#else + weprintf("dropping finger[%d] %s:%d (at %s:%d)\n", + i, dropped_addr, f->node.port, + srv_addr, srv->node.port); +#endif + f_next = f->next; + remove_finger(srv, f); + } else { + if (f->npings || (srv->to_ping == i)) { + f->npings++; + send_ping(srv, f->node.addr, f->node.port, + srv->node.addr, srv->node.port, get_current_time()); + if (srv->to_ping == i) { + f_pinged = f; + } + } + f_next = f->next; + } + f = f_next; + } + + if (!f_pinged || !(f_pinged->next)) { + srv->to_ping = 0; + } else { + srv->to_ping++; + } +} + +/********************************************************************** + * keep only (1) backup successors, (2) proper fingers, and (3) predecessor; + * remove anything else from finger list + ***********************************************************************/ + +void clean_finger_list(Server *srv) +{ + Finger *f, *f_lastsucc, *f_lastpred, *f_tmp; + int k; + chordID id; + + /* skip successor list */ + for (f = srv->head_flist, k = 0; f && (k < NSUCCESSORS - 1); f = f->next, k++) { + ; + } + if (f == NULL || f->next == NULL) { + return; + } + f_lastsucc = f; + + /* start from the tail and skip predecessors */ + for (f = srv->tail_flist, k = 0; k < NPREDECESSORS - 1; f = f->prev, k++) { + if (f == f_lastsucc) { + /* finger list contains only of backup successors and predecesor */ + return; + } + } + f_lastpred = f; + f = f_lastpred->prev; /* First disposable finger */ + + /* keep only unique (proper) fingers */ + for (k = NFINGERS - 1; k >= 0; k--) { + if (f == f_lastsucc) { + return; + } + + /* compute srv.id + 2^k */ + id = successor(srv->node.id, k); + + if (is_between(&id, &f_lastpred->node.id, &srv->node.id) || + equals(&id, &f_lastpred->node.id)) { + /* proper finger for id is one of the (backup) predecessors */ + continue; + } + + if (is_between(&id, &srv->node.id, &f_lastsucc->node.id) || + equals(&id, &srv->node.id)) { + /* proper finger for id is one of the (backup) successors */ + break; + } + + if (is_between(&f->node.id, &srv->node.id, &id)) { + /* f cannot be a proper finger for id, because it + * is between current node and id; try next finger + */ + continue; + } + + /* f is a possible proper finger for id */ + while (1) { + if (f->prev == NULL || f == f_lastsucc) { + return; + } + if (is_between(&f->prev->node.id, &id, &f->node.id) || + equals(&f->prev->node.id, &id)) { + /* this is not a proper finger (i.e., f's predecessor + * is between id and f), so remove f + */ + f_tmp = f; + f = f->prev; + remove_finger(srv, f_tmp); + } else { + /* f is a proper finger */ + f = f->prev; + break; + } + } + } +} + +/**********************************************************************/ +/* set_stabilize_timer: Set first stabilize time (to now). */ +/**********************************************************************/ + +void set_stabilize_timer(void) +{ + /* do not use get_current_time(), because we need the + * resolution of uint64_t + */ + srv_ref->next_stabilize_us = wall_time(); +} === modified file 'i3/chord/test.c' --- i3/chord/test.c 2009-12-11 22:49:11 +0000 +++ i3/chord/test.c 2010-02-11 11:49:47 +0000 @@ -1,10 +1,10 @@ -#include <sys/wait.h> -#include "chord_api.h" - -int main(int argc, char **argv) -{ - chord_init(argv[1]); - wait(0); - - return 0; -} +#include <sys/wait.h> +#include "chord_api.h" + +int main(int argc, char **argv) +{ + chord_init(argv[1]); + wait(0); + + return 0; +} === modified file 'i3/chord/util.c' --- i3/chord/util.c 2009-12-11 22:49:11 +0000 +++ i3/chord/util.c 2010-02-11 11:49:47 +0000 @@ -1,522 +1,546 @@ -#include <assert.h> -#include <ctype.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <time.h> -#include <errno.h> -#include <sys/socket.h> -#include <netinet/in.h> -#include <arpa/inet.h> -#include "chord.h" -#include "../utils/gen_utils.h" - -#if 0 -/* f_rand: return a random double between 0.0 and 1.0 */ -double f_rand(void) -{ - int64_t l, r; - - l = (int64_t) (random() & ((1 << 26) - 1)); - r = (int64_t) (random() & ((1 << 27) - 1)); - return ((l << 27) + r) / (double)(1LL << 53); -} - -/**********************************************************************/ - -/* funif_rand: Return a random number between a and b */ -double funif_rand(double a, double b) -{ - return a + (b - a) * f_rand(); -} - -/**********************************************************************/ - -/* n_rand: return a random integer in [0, n), - borrowed from Java Random class */ -int n_rand(int n) -{ - int bits, val; - - assert(n > 0); /* n must be positive */ - - /* Special case: power of 2 */ - if ((n & -n) == n) - return random() & (n - 1); - - do { - bits = random(); - val = bits % n; - } while (bits - val + (n - 1) < 0); - return val; -} - -/**********************************************************************/ - -/* unif_rand: return a random integer number in the interval [a, b) */ -int unif_rand(int a, int b) -{ - return a + n_rand(b - a); -} - -/**********************************************************************/ - -/* getusec: return wall time in usec */ -uint64_t wall_time(void) -{ - struct timeval tv; - gettimeofday(&tv, NULL); - return tv.tv_sec * 1000000ULL + tv.tv_usec; -} - -/**********************************************************************/ -#endif -void update_rtt(long *rtt_avg, long *rtt_dev, long new_rtt) -{ - long err; - - if (*rtt_avg == 0) { - *rtt_avg = new_rtt; - *rtt_dev = 0; - return; - } - - /* use TCP's rtt estimation algorithm */ - err = new_rtt - *rtt_avg; - *rtt_avg += err >> 3; - if (err < 0) err = -err; - *rtt_dev += (err - *rtt_dev) >> 2; -} - - -/**********************************************************************/ - -/* randID: return a random ID */ -chordID rand_ID(void) -{ - chordID id; - int i; - - for (i = 0; i < ID_LEN; i++) - id.x[i] = (byte)(random() & 0xff); - return id; -} - -/**********************************************************************/ - -/* successorID: id + (1 << n) */ -chordID successor(chordID id, int n) -{ - byte old; - int i, start; - - assert(n >= 0 && n < NBITS); - /* Note id.x[0] is most significant bit */ - start = ID_LEN-1 - n/8; - old = id.x[start]; - id.x[start] += 1 << (n%8); - if (id.x[start] < old) - for (i = start-1; i >= 0; i--) { - id.x[i]++; - if (id.x[i]) break; - } - return id; -} - -/**********************************************************************/ - -/* predecessorID: id - (1 << n) */ -chordID predecessor(chordID id, int n) -{ - byte old; - int i, start; - - assert(n >= 0 && n < NBITS); - start = ID_LEN-1 - n/8; - old = id.x[start]; - id.x[start] -= 1 << (n%8); - if (id.x[start] > old) - for (i = start-1; i >= 0; i--) { - if (id.x[i]) { - id.x[i]--; - break; - } else - id.x[i]--; - } - return id; -} - -/**********************************************************************/ - -/* add: res = a + b (mod 2^n) */ -void add(chordID *a, chordID *b, chordID *res) -{ - int carry, i; - - carry = 0; - for (i = ID_LEN - 1; i >= 0; i--) { - res->x[i] = (a->x[i] + b->x[i] + carry) & 0xff; - carry = (a->x[i] + b->x[i] + carry) >> 8; - } -} - -/**********************************************************************/ - -/* subtract: res = a - b (mod 2^n) */ -void subtract(chordID *a, chordID *b, chordID *res) -{ - int borrow, i; - - borrow = 0; - for (i = ID_LEN - 1; i >= 0; i--) { - if (a->x[i] - borrow < b->x[i]) { - res->x[i] = 256 + a->x[i] - borrow - b->x[i]; - borrow = 1; - } else { - res->x[i] = a->x[i] - borrow - b->x[i]; - borrow = 0; - } - } -} - -/**********************************************************************/ - -chordID random_from(chordID *a) -{ - chordID b; - int i, m = random()%10 + 1; - - for (i = 0; i < ID_LEN; i++) { - b.x[i] = a->x[i]*m/11; - } - return b; -} - -/**********************************************************************/ - -void random_between(chordID *a, chordID *b, chordID *res) -{ - chordID r; - - subtract(b, a, res); - - r = random_from(res); - - add(a, &r, res); -} - -/**********************************************************************/ - -static int msb_tab[256] = { - 0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, - 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, - 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, - 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, - 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, - 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7 -}; - -/* msb: most significant bit */ -int -msb(chordID *x) -{ - int i; - - for (i = 0; i < ID_LEN; i++) - if (x->x[i]) - return 8 * i + msb_tab[x->x[i]]; - return 0; -} - -/**********************************************************************/ - -/* equals: a == b? */ -int equals(chordID *a, chordID *b) -{ - return memcmp(a->x, b->x, sizeof(chordID)) == 0; -} - -/* equals: a == b? */ -int equals_id_str(chordID *a, char *b) -{ - chordID idb = atoid(b); - - return memcmp(a->x, idb.x, sizeof(chordID)) == 0; -} - -/**********************************************************************/ - -int is_zero(chordID *x) -{ - static chordID zero; - return memcmp(x->x, zero.x, sizeof(chordID)) == 0; -} - -/**********************************************************************/ - -/* greater: a>b? */ -/* -static int is_greater(chordID *a, chordID *b) -{ - return memcmp(a->x, b->x, sizeof(chordID)) > 0; -} -*/ - -/* less: a<b? */ -static int is_less(chordID *a, chordID *b) -{ - return memcmp(a->x, b->x, sizeof(chordID)) < 0; -} - -/* between: is x in (a,b) on circle? */ -int is_between(chordID *x, chordID *a, chordID *b) -{ - if (equals(a, b)) - return !equals(x, a); /* x is only node not in (x,x) */ - else if (is_less(a, b)) - return is_less(a, x) && is_less(x, b); - else - return is_less(a, x) || is_less(x, b); -} - -/***********************************************/ -int copy_id( chordID *a, chordID *b) -{ - int i = 0; - - assert(a); - assert(b); - for (i = 0; i < sizeof(chordID); i++) - a->x[i] = b->x[i]; - return 1; -} - -/**********************************************************************/ - -void print_id(FILE *f, chordID *id) -{ - int i; - - for (i = 0; i < ID_LEN; i++) - fprintf(f, "%02x", id->x[i]); -} - -/**********************************************************************/ - - -/**********************************************************************/ - -static unsigned char todigit(char ch) -{ - if (isdigit((int) ch)) - return (ch - '0'); - else - return (10 + ch - 'a'); -} - -chordID atoid(const char *str) -{ - chordID id; - int i; - - assert(strlen(str) == 2*ID_LEN); - for (i = 0; i < ID_LEN; i++) - id.x[ i ] = (todigit(str[2*i]) << 4) | todigit(str[2*i+1]); - return id; -} - -/**********************************************************************/ - -enum { - MULTIPLIER = 31 /* for hash() */ -}; - -/* hash: compute hash value for ID */ -unsigned hash(chordID *id, unsigned n) -{ - unsigned h; - int i; - - h = 0; - for (i = 0; i < ID_LEN; i++) - h = MULTIPLIER * h + id->x[ i ]; - - return h % n; -} - - -/* hash: compute hash value for ID */ -int match_key(Key *key) -{ - int i; - - for (i = 0; i < NumKeys; i++) { - if (memcmp((char *)&key->x[0], (char *)&KeyArray[i].x[0], KEY_LEN) == 0) { - return 1; - } - } - return 0; -} - -/***********************************************************************/ - -void print_chordID(chordID *id) -{ - int i; - - for (i = 0; i < ID_LEN; i++) - printf("%02x", id->x[i]); -} - -/***********************************************************************/ - -void print_two_chordIDs(char *preffix, chordID *id1, char *middle, - chordID *id2, char *suffix) -{ - assert(preffix && id1 && middle && id2 && suffix); - printf("%s", preffix); - print_chordID(id1); - printf("%s", middle); - print_chordID(id2); - printf("%s", suffix); -} - -/***********************************************************************/ - -void print_three_chordIDs(char *preffix, chordID *id1, - char *middle1, chordID *id2, - char *middle2, chordID *id3, - char *suffix) -{ - assert(preffix && id1 && middle1 && id2 && middle2 && id3 && suffix); - printf("%s", preffix); - print_chordID(id1); - printf("%s", middle1); - print_chordID(id2); - printf("%s", middle2); - print_chordID(id3); - printf("%s", suffix); -} - - -/***********************************************************************/ - -void print_node(Node *node, char *prefix, char *suffix) -{ - struct in_addr ia; - - printf("%s", prefix); - print_chordID(&node->id); - ia.s_addr = htonl(node->addr); - printf(", %s, %d%s", inet_ntoa(ia), node->port, suffix); -} - -void print_finger(Finger *f, char *prefix, char *suffix) -{ - printf("%sFinger:", prefix); - print_node(&f->node, "<", ">"); -#ifndef CIL - printf(" (status = %d, npings = %d, rtt = %ld/%ld) %s", - f->status, f->npings, f->rtt_avg, f->rtt_dev, suffix); -#else - printf(" (status = %d, npings = %d, rtt = %ld/%ld)%s", - f->status, f->npings, f->rtt_avg, f->rtt_dev, suffix); -#endif -} - - -void print_finger_list(Finger *fhead, char *prefix, char *suffix) -{ - int i; - Finger *f; - - printf("%s", prefix); - for (f = fhead, i = 0; f; f = f->next, i++) { - printf(" [%d] ", i); - print_finger(f, "", "\n"); - } - printf("%s", suffix); -} - -void print_server(Server *s, char *prefix, char *suffix) -{ - printf("---------------%s---------------\n", prefix); - print_node(&s->node, "[", "]\n"); - print_finger_list(s->head_flist, " Finger list:\n", "\n"); - printf("---------------%s---------------\n", suffix); -} - - -void print_process(Server *srv, char *process_type, chordID *id, - ulong addr, ushort port) -{ -#define TYPE_LEN 16 - int i = TYPE_LEN - strlen(process_type); - - printf("[%s]", process_type); - if (i > 0) for (; i; i--) printf(" "); - - printf(" ("); - if (id) - print_chordID(id); - else - printf("null"); - printf(") "); - print_node(&srv->node, " <", ">"); - if (addr == -1) - printf(" <----- <,>"); - else - printf(" <----- <%ld, %d>", addr, port); - print_current_time(" Time:", "\n"); -} - -void print_send(Server *srv, char *send_type, chordID *id, - ulong addr, ushort port) -{ - int i = TYPE_LEN - strlen(send_type); - - printf("[%s]", send_type); - if (i > 0) for (; i; i--) printf(" "); - - printf(" ("); - if (id) - print_chordID(id); - else - printf("null"); - printf(") "); - print_node(&srv->node, " <", ">"); - if (addr == -1) - printf(" -----> <,>"); - else - printf(" -----> <%ld, %d>", addr, port); - print_current_time(" Time:", "\n"); -} - -void print_fun(Server *srv, char *fun_name, chordID *id) -{ - printf("%s: ", fun_name); - print_chordID(&srv->node.id); - printf(" > "); - print_chordID(id); - print_current_time(" @ ", "\n"); -} - -ulong get_current_time() -{ -#ifdef SIM_CHORD - return (ulong)sim_get_time(); -#else - return (ulong)wall_time(); -#endif -} - -void print_current_time(char *prefix, char *suffix) -{ -#ifdef SIM_CHORD - printf("%s%f%s", prefix, sim_get_time(), suffix); -#else - printf("%s%lld%s", prefix, (long long int)wall_time(), suffix); -#endif -} +#include <assert.h> +#include <ctype.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <errno.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include "chord.h" +#include "../utils/gen_utils.h" + +#if 0 +/* f_rand: return a random double between 0.0 and 1.0 */ +double f_rand(void) +{ + int64_t l, r; + + l = (int64_t) (random() & ((1 << 26) - 1)); + r = (int64_t) (random() & ((1 << 27) - 1)); + return ((l << 27) + r) / (double) (1LL << 53); +} + +/**********************************************************************/ + +/* funif_rand: Return a random number between a and b */ +double funif_rand(double a, double b) +{ + return a + (b - a) * f_rand(); +} + +/**********************************************************************/ + +/* n_rand: return a random integer in [0, n), + * borrowed from Java Random class */ +int n_rand(int n) +{ + int bits, val; + + assert(n > 0); /* n must be positive */ + + /* Special case: power of 2 */ + if ((n & - n) == n) { + return random() & (n - 1); + } + + do { + bits = random(); + val = bits % n; + } while (bits - val + (n - 1) < 0); + return val; +} + +/**********************************************************************/ + +/* unif_rand: return a random integer number in the interval [a, b) */ +int unif_rand(int a, int b) +{ + return a + n_rand(b - a); +} + +/**********************************************************************/ + +/* getusec: return wall time in usec */ +uint64_t wall_time(void) +{ + struct timeval tv; + gettimeofday(&tv, NULL); + return tv.tv_sec * 1000000ULL + tv.tv_usec; +} + +/**********************************************************************/ +#endif +void update_rtt(long *rtt_avg, long *rtt_dev, long new_rtt) +{ + long err; + + if (*rtt_avg == 0) { + *rtt_avg = new_rtt; + *rtt_dev = 0; + return; + } + + /* use TCP's rtt estimation algorithm */ + err = new_rtt - *rtt_avg; + *rtt_avg += err >> 3; + if (err < 0) { + err = -err; + } + *rtt_dev += (err - *rtt_dev) >> 2; +} + +/**********************************************************************/ + +/* randID: return a random ID */ +chordID rand_ID(void) +{ + chordID id; + int i; + + for (i = 0; i < ID_LEN; i++) { + id.x[i] = (byte) (random() & 0xff); + } + return id; +} + +/**********************************************************************/ + +/* successorID: id + (1 << n) */ +chordID successor(chordID id, int n) +{ + byte old; + int i, start; + + assert(n >= 0 && n < NBITS); + /* Note id.x[0] is most significant bit */ + start = ID_LEN - 1 - n / 8; + old = id.x[start]; + id.x[start] += 1 << (n % 8); + if (id.x[start] < old) { + for (i = start - 1; i >= 0; i--) { + id.x[i]++; + if (id.x[i]) { + break; + } + } + } + return id; +} + +/**********************************************************************/ + +/* predecessorID: id - (1 << n) */ +chordID predecessor(chordID id, int n) +{ + byte old; + int i, start; + + assert(n >= 0 && n < NBITS); + start = ID_LEN - 1 - n / 8; + old = id.x[start]; + id.x[start] -= 1 << (n % 8); + if (id.x[start] > old) { + for (i = start - 1; i >= 0; i--) { + if (id.x[i]) { + id.x[i]--; + break; + } else { + id.x[i]--; + } + } + } + return id; +} + +/**********************************************************************/ + +/* add: res = a + b (mod 2^n) */ +void add(chordID *a, chordID *b, chordID *res) +{ + int carry, i; + + carry = 0; + for (i = ID_LEN - 1; i >= 0; i--) { + res->x[i] = (a->x[i] + b->x[i] + carry) & 0xff; + carry = (a->x[i] + b->x[i] + carry) >> 8; + } +} + +/**********************************************************************/ + +/* subtract: res = a - b (mod 2^n) */ +void subtract(chordID *a, chordID *b, chordID *res) +{ + int borrow, i; + + borrow = 0; + for (i = ID_LEN - 1; i >= 0; i--) { + if (a->x[i] - borrow < b->x[i]) { + res->x[i] = 256 + a->x[i] - borrow - b->x[i]; + borrow = 1; + } else { + res->x[i] = a->x[i] - borrow - b->x[i]; + borrow = 0; + } + } +} + +/**********************************************************************/ + +chordID random_from(chordID *a) +{ + chordID b; + int i, m = random() % 10 + 1; + + for (i = 0; i < ID_LEN; i++) { + b.x[i] = a->x[i] * m / 11; + } + return b; +} + +/**********************************************************************/ + +void random_between(chordID *a, chordID *b, chordID *res) +{ + chordID r; + + subtract(b, a, res); + + r = random_from(res); + + add(a, &r, res); +} + +/**********************************************************************/ + +static int msb_tab[256] = { + 0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 +}; + +/* msb: most significant bit */ +int msb(chordID *x) +{ + int i; + + for (i = 0; i < ID_LEN; i++) { + if (x->x[i]) { + return 8 * i + msb_tab[x->x[i]]; + } + } + return 0; +} + +/**********************************************************************/ + +/* equals: a == b? */ +int equals(chordID *a, chordID *b) +{ + return memcmp(a->x, b->x, sizeof(chordID)) == 0; +} + +/* equals: a == b? */ +int equals_id_str(chordID *a, char *b) +{ + chordID idb = atoid(b); + + return memcmp(a->x, idb.x, sizeof(chordID)) == 0; +} + +/**********************************************************************/ + +int is_zero(chordID *x) +{ + static chordID zero; + return memcmp(x->x, zero.x, sizeof(chordID)) == 0; +} + +/**********************************************************************/ + +/* greater: a>b? */ +/* + * static int is_greater(chordID *a, chordID *b) + * { + * return memcmp(a->x, b->x, sizeof(chordID)) > 0; + * } + */ + +/* less: a<b? */ +static int is_less(chordID *a, chordID *b) +{ + return memcmp(a->x, b->x, sizeof(chordID)) < 0; +} + +/* between: is x in (a,b) on circle? */ +int is_between(chordID *x, chordID *a, chordID *b) +{ + if (equals(a, b)) { + return !equals(x, a); /* x is only node not in (x,x) */ + } else if (is_less(a, b)) { + return is_less(a, x) && is_less(x, b); + } else { + return is_less(a, x) || is_less(x, b); + } +} + +/***********************************************/ +int copy_id( chordID *a, chordID *b) +{ + int i = 0; + + assert(a); + assert(b); + for (i = 0; i < sizeof(chordID); i++) { + a->x[i] = b->x[i]; + } + return 1; +} + +/**********************************************************************/ + +void print_id(FILE *f, chordID *id) +{ + int i; + + for (i = 0; i < ID_LEN; i++) { + fprintf(f, "%02x", id->x[i]); + } +} + +/**********************************************************************/ + + +/**********************************************************************/ + +static unsigned char todigit(char ch) +{ + if (isdigit((int) ch)) { + return ch - '0'; + } else { + return 10 + ch - 'a'; + } +} + +chordID atoid(const char *str) +{ + chordID id; + int i; + + assert(strlen(str) == 2 * ID_LEN); + for (i = 0; i < ID_LEN; i++) { + id.x[ i ] = (todigit(str[2 * i]) << 4) | todigit(str[2 * i + 1]); + } + return id; +} + +/**********************************************************************/ + +enum { + MULTIPLIER = 31 /* for hash() */ +}; + +/* hash: compute hash value for ID */ +unsigned hash(chordID *id, unsigned n) +{ + unsigned h; + int i; + + h = 0; + for (i = 0; i < ID_LEN; i++) { + h = MULTIPLIER * h + id->x[ i ]; + } + + return h % n; +} + +/* hash: compute hash value for ID */ +int match_key(Key *key) +{ + int i; + + for (i = 0; i < NumKeys; i++) { + if (memcmp((char *) &key->x[0], (char *) &KeyArray[i].x[0], KEY_LEN) == 0) { + return 1; + } + } + return 0; +} + +/***********************************************************************/ + +void print_chordID(chordID *id) +{ + int i; + + for (i = 0; i < ID_LEN; i++) { + printf("%02x", id->x[i]); + } +} + +/***********************************************************************/ + +void print_two_chordIDs(char *preffix, chordID *id1, char *middle, + chordID *id2, char *suffix) +{ + assert(preffix && id1 && middle && id2 && suffix); + printf("%s", preffix); + print_chordID(id1); + printf("%s", middle); + print_chordID(id2); + printf("%s", suffix); +} + +/***********************************************************************/ + +void print_three_chordIDs(char *preffix, chordID *id1, + char *middle1, chordID *id2, + char *middle2, chordID *id3, + char *suffix) +{ + assert(preffix && id1 && middle1 && id2 && middle2 && id3 && suffix); + printf("%s", preffix); + print_chordID(id1); + printf("%s", middle1); + print_chordID(id2); + printf("%s", middle2); + print_chordID(id3); + printf("%s", suffix); +} + +/***********************************************************************/ + +void print_node(Node *node, char *prefix, char *suffix) +{ + struct in_addr ia; + + printf("%s", prefix); + print_chordID(&node->id); + ia.s_addr = htonl(node->addr); + printf(", %s, %d%s", inet_ntoa(ia), node->port, suffix); +} + +void print_finger(Finger *f, char *prefix, char *suffix) +{ + printf("%sFinger:", prefix); + print_node(&f->node, "<", ">"); +#ifndef CIL + printf(" (status = %d, npings = %d, rtt = %ld/%ld) %s", + f->status, f->npings, f->rtt_avg, f->rtt_dev, suffix); +#else + printf(" (status = %d, npings = %d, rtt = %ld/%ld)%s", + f->status, f->npings, f->rtt_avg, f->rtt_dev, suffix); +#endif +} + +void print_finger_list(Finger *fhead, char *prefix, char *suffix) +{ + int i; + Finger *f; + + printf("%s", prefix); + for (f = fhead, i = 0; f; f = f->next, i++) { + printf(" [%d] ", i); + print_finger(f, "", "\n"); + } + printf("%s", suffix); +} + +void print_server(Server *s, char *prefix, char *suffix) +{ + printf("---------------%s---------------\n", prefix); + print_node(&s->node, "[", "]\n"); + print_finger_list(s->head_flist, " Finger list:\n", "\n"); + printf("---------------%s---------------\n", suffix); +} + +void print_process(Server *srv, char *process_type, chordID *id, + ulong addr, ushort port) +{ +#define TYPE_LEN 16 + int i = TYPE_LEN - strlen(process_type); + + printf("[%s]", process_type); + if (i > 0) { + for (; i; i--) { + printf(" "); + } + } + + printf(" ("); + if (id) { + print_chordID(id); + } else { + printf("null"); + } + printf(") "); + print_node(&srv->node, " <", ">"); + if (addr == -1) { + printf(" <----- <,>"); + } else { + printf(" <----- <%ld, %d>", addr, port); + } + print_current_time(" Time:", "\n"); +} + +void print_send(Server *srv, char *send_type, chordID *id, + ulong addr, ushort port) +{ + int i = TYPE_LEN - strlen(send_type); + + printf("[%s]", send_type); + if (i > 0) { + for (; i; i--) { + printf(" "); + } + } + + printf(" ("); + if (id) { + print_chordID(id); + } else { + printf("null"); + } + printf(") "); + print_node(&srv->node, " <", ">"); + if (addr == -1) { + printf(" -----> <,>"); + } else { + printf(" -----> <%ld, %d>", addr, port); + } + print_current_time(" Time:", "\n"); +} + +void print_fun(Server *srv, char *fun_name, chordID *id) +{ + printf("%s: ", fun_name); + print_chordID(&srv->node.id); + printf(" > "); + print_chordID(id); + print_current_time(" @ ", "\n"); +} + +ulong get_current_time() +{ +#ifdef SIM_CHORD + return (ulong) sim_get_time(); +#else + return (ulong) wall_time(); +#endif +} + +void print_current_time(char *prefix, char *suffix) +{ +#ifdef SIM_CHORD + printf("%s%f%s", prefix, sim_get_time(), suffix); +#else + printf("%s%lld%s", prefix, (long long int) wall_time(), suffix); +#endif +} === modified file 'i3/i3/debug_fns.h' --- i3/i3/debug_fns.h 2010-01-19 09:28:42 +0000 +++ i3/i3/debug_fns.h 2010-02-11 11:49:47 +0000 @@ -13,50 +13,53 @@ #ifndef I3_PRINT_DEBUG - /** - * This macro is used to print debugging information. - * The message is printed only if the current debugging level is - * greater than that of the level specified in the macro call. - */ +/** + * This macro is used to print debugging information. + * The message is printed only if the current debugging level is + * greater than that of the level specified in the macro call. + */ #if 0 // We turn off the i3 debuging instead we will use HIP_DEBUG - #define I3_PRINT_DEBUG(debugLevel, msg, ... ) if(debugLevel <= I3_CURRENT_DEBUG_LEVEL) { printf("[Line:%d in file:%s] ", __LINE__, __FILE__); printf(msg, ##__VA_ARGS__);} - #endif - - #define I3_PRINT_DEBUG(debugLevel, ... ) if(debugLevel <= I3_CURRENT_DEBUG_LEVEL) HIP_DEBUG(__VA_ARGS__) - - - #define I3_PRINT_DEBUG0 I3_PRINT_DEBUG - #define I3_PRINT_DEBUG1 I3_PRINT_DEBUG - #define I3_PRINT_DEBUG2 I3_PRINT_DEBUG - #define I3_PRINT_DEBUG3 I3_PRINT_DEBUG - #define I3_PRINT_DEBUG4 I3_PRINT_DEBUG - #define I3_PRINT_DEBUG5 I3_PRINT_DEBUG - #define I3_PRINT_DEBUG6 I3_PRINT_DEBUG - #define I3_PRINT_DEBUG7 I3_PRINT_DEBUG + #define I3_PRINT_DEBUG(debugLevel, msg, ... ) if (debugLevel <= I3_CURRENT_DEBUG_LEVEL) { printf("[Line:%d in file:%s] ", __LINE__, __FILE__); printf(msg, ## __VA_ARGS__); } + #endif + + #define I3_PRINT_DEBUG(debugLevel, ... ) if (debugLevel <= I3_CURRENT_DEBUG_LEVEL) \ + HIP_DEBUG(__VA_ARGS__) + + + #define I3_PRINT_DEBUG0 I3_PRINT_DEBUG + #define I3_PRINT_DEBUG1 I3_PRINT_DEBUG + #define I3_PRINT_DEBUG2 I3_PRINT_DEBUG + #define I3_PRINT_DEBUG3 I3_PRINT_DEBUG + #define I3_PRINT_DEBUG4 I3_PRINT_DEBUG + #define I3_PRINT_DEBUG5 I3_PRINT_DEBUG + #define I3_PRINT_DEBUG6 I3_PRINT_DEBUG + #define I3_PRINT_DEBUG7 I3_PRINT_DEBUG #endif //I3_PRINT_DEBUG /** - * This macro is used to print messages irrespective of debug level. - * These are messages are not for debugging, but for giving information - * to the user. - */ + * This macro is used to print messages irrespective of debug level. + * These are messages are not for debugging, but for giving information + * to the user. + */ #ifndef I3_PRINT_INFO #if 0 - #define I3_PRINT_INFO(infoLevel, msg, ...) if(infoLevel <= I3_CURRENT_INFO_LEVEL) printf(msg, ##__VA_ARGS__) + #define I3_PRINT_INFO(infoLevel, msg, ...) if (infoLevel <= I3_CURRENT_INFO_LEVEL) \ + printf(msg, ## __VA_ARGS__) #endif - #define I3_PRINT_INFO(infoLevel, ... ) if(infoLevel <= I3_CURRENT_INFO_LEVEL) HIP_INFO(__VA_ARGS__) + #define I3_PRINT_INFO(infoLevel, ... ) if (infoLevel <= I3_CURRENT_INFO_LEVEL) \ + HIP_INFO(__VA_ARGS__) #define I3_PRINT_INFO0 I3_PRINT_INFO - #define I3_PRINT_INFO1 I3_PRINT_INFO - #define I3_PRINT_INFO2 I3_PRINT_INFO - #define I3_PRINT_INFO3 I3_PRINT_INFO - #define I3_PRINT_INFO4 I3_PRINT_INFO - #define I3_PRINT_INFO5 I3_PRINT_INFO - #define I3_PRINT_INFO6 I3_PRINT_INFO - #define I3_PRINT_INFO7 I3_PRINT_INFO + #define I3_PRINT_INFO1 I3_PRINT_INFO + #define I3_PRINT_INFO2 I3_PRINT_INFO + #define I3_PRINT_INFO3 I3_PRINT_INFO + #define I3_PRINT_INFO4 I3_PRINT_INFO + #define I3_PRINT_INFO5 I3_PRINT_INFO + #define I3_PRINT_INFO6 I3_PRINT_INFO + #define I3_PRINT_INFO7 I3_PRINT_INFO #endif //I3_PRINT_INFO === modified file 'i3/i3/i3.h' --- i3/i3/i3.h 2009-12-11 22:49:11 +0000 +++ i3/i3/i3.h 2010-02-11 11:49:47 +0000 @@ -1,456 +1,447 @@ -/*************************************************************************** - i3.h - description - ------------------- - begin : Son Nov 17 2002 - email : wehrle@xxxxxxxxxxxxxxxxx - ***************************************************************************/ - -#ifndef I3_H -#define I3_H - -#include <sys/types.h> -#ifdef _WIN32 - #include "../utils/fwint.h" -#endif -#include "../utils/netwrap.h" -#ifdef __APPLE__ -#include <inttypes.h> // Need uint8_t -#include <sys/time.h> // Need timeval -#endif -#include <assert.h> - -/* CLIENT_API_DEPRECIATED specifies whether the old client api is used */ -//#define CLIENT_API_DEPRECIATED - -#ifndef TRUE -#define TRUE 1 -#define FALSE 0 -#endif - -#define CHAR_BITS 8 - -// first byte in a packet sent to an i3 server -// - normal i3 packet --> version number -// - i3 ping packet --> I3_PING_PACKET - -// note that i3 ping packets are not i3 packets; ping responses -// should be from a different process, but for fatesharing reasons -// implemented together -#define I3_v01 0x10 -#define I3_PING_PKT 0x01 - -#define I3_DATA 0x10 -#define I3_OPTION_LIST 0x20 -#define I3_FIRST_HOP 0x40 - -#define I3_ADDR_TYPE_STACK 0x10 -#define I3_ADDR_TYPE_IPv4 0x20 -#define I3_ADDR_TYPE_IPv6 0x30 -#define I3_ADDR_TYPE_IPv4_NAT 0x40 - -#define I3_ID_TYPE_PUBLIC 0x10 -#define I3_ID_TYPE_PRIVATE 0x20 -//#define I3_ID_TYPE_UNCONSTRAINED 0x30 -#define I3_ID_TYPE_UNKNOWN 0x40 - -#define I3_OPT_SENDER 0x01 -#define I3_OPT_TRIGGER_INSERT 0x02 -#define I3_OPT_TRIGGER_CHALLENGE 0x03 -#define I3_OPT_TRIGGER_ACK 0x04 -#define I3_OPT_TRIGGER_REMOVE 0x05 -#define I3_OPT_TRIGGER_NOT_PRESENT 0x06 -#define I3_OPT_REQUEST_FOR_CACHE 0x07 -#define I3_OPT_CACHE_ADDR 0x08 -#define I3_OPT_FORCE_CACHE_ADDR 0x09 -#define I3_OPT_CONSTRAINT_FAILED 0x10 -#define I3_OPT_ROUTE_BROKEN 0x11 -#define I3_OPT_REQUEST_FOR_CACHE_SHORTCUT 0x12 -#define I3_OPT_CACHE_SHORTCUT_ADDR 0x13 -#define I3_OPT_CACHE_DEST_ADDR 0x14 -#define I3_OPT_REQUEST_FOR_CACHE_SHORTCUT_INDIR 0x15 -#define I3_OPT_DESTINATION 0x20 -#define I3_OPT_TRIGGER_RATELIMIT 0x30 - -/* flags associated to trigger */ -#define I3_TRIGGER_FLAG_ALLOW_SHORTCUT 0x1 -#define I3_TRIGGER_FLAG_RATE_LIMIT 0x2 - -#define I3_ERR_INVALID_VER -1 -#define I3_ERR_INVALID_FLAGS -2 -#define I3_ERR_PKT_LEN_TOO_SHORT -3 -#define I3_ERR_INVALID_STACK -4 -#define I3_ERR_INVALID_ADDR -5 -#define I3_ERR_INVALID_OPTLIST -6 -#define I3_ERR_INVALID_OPTION -7 - -#define L_CONSTRAINT 0 -#define R_CONSTRAINT 1 - -#define NEWS_INSTRUMENT 1 - -#if NEWS_INSTRUMENT -// 2 options for instrumenting i3 servers -// maybe modified later for cleanliness -#define I3_OPT_LOG_PACKET 0x0A -#define I3_OPT_APPEND_TS 0x0B -#define MAX_NEWS_OPTS 2 -#endif - -#define OK 1 -#define ERROR 0 - -#define INDENT_CONST 2 /* just for printing data nice for debugging */ -#define INDENT_BUF_LEN 100 /* just for printing data nice for debugging */ - - -/****************************** - ** Type of an i3-id ** - ******************************/ - -#define ID_LEN 32 /* in bytes */ -#define ID_LEN_BITS 256 /* in bits, i.e., ID_LEN_BITS = ID_LEN*8 */ -#define MIN_PREFIX_LEN 192 /* minimum prefix length that has to match */ - -#define PREFIX_LEN 8 -#define KEY_LEN 16 /* length of key in bytes */ - -#define PREFIX_ID(id) (id.x) -#define KEY_ID(id) (id.x + PREFIX_LEN) -#define KEY_ID_PTR(id) (id->x + PREFIX_LEN) -#define SUFFIX_ID(id) (id.x + SUFFIX_LEN) -typedef struct -{ - uint8_t x[ID_LEN]; -} ID; - -typedef struct -{ - uint8_t x[KEY_LEN]; -} Key; - -/****************************** - ** structure of an i3-stack ** - ******************************/ - -#define I3_MAX_STACK_LEN 15 -typedef struct i3_stack { - int len; /* # of IDs in the stack */ - ID *ids; -} i3_stack; - - -/******************************** - ** structure of an i3 address ** - ********************************/ -#ifndef CCURED - #define __SELECTEDWHEN(x) - #define __SELECTOR(x) - #define __RTTI -#endif -typedef struct i3_addr { - char type; - union - { - /* I3_ADDR_TYPE_STACK */ - i3_stack *stack __SELECTEDWHEN("type" == I3_ADDR_TYPE_STACK); - - struct /* I3_ADDR_TYPE_IPv4 */ - { - struct in_addr addr; - uint16_t port; - } v4 __SELECTEDWHEN("type" == I3_ADDR_TYPE_IPv4); - - /* v4_nat is used to store all the information required to support - * NAT hosts: - * - (host_addr, host_port) is the address of the host, which - * can be behind NAT - * - (nat_addr, nat_port) is the address assigned by the NAT to the host - * - (i3srv_addr, i3srv_port) is the address of the first i3 server - * to which the host sends packets - */ - struct - { - struct in_addr host_addr; - uint16_t host_port; - struct in_addr nat_addr; - uint16_t nat_port; - struct in_addr i3srv_addr; - uint16_t i3srv_port; - - } v4_nat __SELECTEDWHEN("type" == I3_ADDR_TYPE_IPv4_NAT); - - -#ifndef __CYGWIN__ - struct /* I3_ADDR_TYPE_IPv6 */ - { - struct in6_addr addr; - uint16_t port; - } v6 __SELECTEDWHEN("type" == I3_ADDR_TYPE_IPv6); -#endif - } t; -} i3_addr; - - -typedef struct token_bucket { -#define TOKEN_BUCKET_PACKET 0 -#define TOKEN_BUCKET_BYTE 1 - char type; /* specifies whether units are "packets" or "bytes" */ - uint32_t depth; /* token depth (bytes or packets) */ - uint32_t r; /* long term rate (Bps or pps) */ - uint32_t R; /* maximum rate (Bps or pps) */ - /* only the first three fields are packed in packet; - * the following two fields are temporar variables - * used to implement the token bucket functionality - */ - uint32_t tokens; /* actual number of tokens in the bucket (bytes or packets) - * Note: "tokens" is never larger than "depth" - */ - uint64_t last_time; /* time since the previous packet has been - * received (usec) - */ -} token_bucket; - -#define NONCE_LEN 16 -typedef struct i3_trigger { - ID id; - uint8_t flags; /* possible flags:I3_TRIGGER_FLAG_ALLOW_SHORTCUT (0x1) - * I3_TRIGGER_FLAG_RATE_LIMIT (0x2) - */ - uint16_t prefix_len; /* packet ID should match trigID in the first - max(prefix_len, MIN_PREFIX_LEN) bits or more */ - char nonce[NONCE_LEN]; - i3_addr *to; - Key key; - token_bucket *tb; /* this is set only if I3_TRIGGER_FLAG_RATE_LIMIT is set*/ -} i3_trigger; - - -/************************************ - ** i3_option_entry data structure ** - ************************************/ - -typedef struct i3_option -{ - char type; - union - { - /* sender address where to send a reply (type = I3_OPT_SENDER) - */ - i3_addr *ret_addr __SELECTEDWHEN("type" == I3_OPT_SENDER); - - /* sender address where to send a reply (type = I3_OPT_SENDER) - */ - i3_addr *dst_addr __SELECTEDWHEN("type" == I3_OPT_DESTINATION); - - /* trigger insertion and challenge - * (type = I3_OPT_TRIGGER_INSERT, I3_OPT_TRIGGER_CHALLENGE, - * I3_OPT_TRIGGER_ACK, I3_OPT_TRIGGER_REMOVE, - * I3_OPT_CACHE_ADDR, I3_OPT_CACHE_SHORTCUT_ADDR, - * I3_OPT_CACHE_DEST_ADDR, - * I3_OPT_CONSTRAINT_FAILED, I3_OPT_ROUTE_BROKEN) - * - * When I3_OPT_CACHE_ADDR is used, trigger->to represents the - * the address suggested by the i3 server (e.g., its own address) - * where client should send data and control messages addressed to - * any identifier that shares MIN_PREFIX_LEN bits with trigger->id. - * Thus, this option allows the client to cache the address of a server - * responsible for a certain identifier. - * When I3_OPT_CACHE_SHORTCUT_ADDR is used, trigger->to represents the - * the address of the end host. This option is sent directly to the - * receiver. The receiver can see whether the sender is behind a NAT - * by comparing the IP source address of the packet and the IP address - * in trigger->to. - */ - i3_trigger *trigger __SELECTEDWHEN("type" == I3_OPT_TRIGGER_INSERT || \ - "type" == I3_OPT_TRIGGER_CHALLENGE || \ - "type" == I3_OPT_TRIGGER_ACK || \ - "type" == I3_OPT_TRIGGER_REMOVE || \ - "type" == I3_OPT_CACHE_ADDR || \ - "type" == I3_OPT_CACHE_DEST_ADDR || \ - "type" == I3_OPT_CACHE_SHORTCUT_ADDR ||\ - "type" == I3_OPT_CONSTRAINT_FAILED\ - "type" == I3_OPT_ROUTE_BROKEN); - - /* id to which the reply refers to (type = I3_OPT_TRIGGER_NOT_PRESENT, - * I3_OPT_REQUEST_FOR_CACHE, I3_OPT_TRIGGER_RATELIMIT) - */ - ID *id __SELECTEDWHEN("type" == I3_OPT_TRIGGER_NOT_PRESENT ||\ - "type" == I3_OPT_TRIGGER_RATELIMIT); - - /* the cache request is for the first ID in the stack - * (type = I3_OPT_REQUEST_FOR_CACHE, I3_OPT_REQUEST_FOR_CACHE_SHORTCUT) - */ - void *nothing __SELECTEDWHEN("type" == I3_OPT_REQUEST_FOR_CACHE || \ - "type" == I3_OPT_REQUEST_FOR_CACHE_SHORTCUT || \ - "type" == I3_OPT_REQUEST_FOR_CACHE_SHORTCUT_INDIR); - } entry; - struct i3_option *next; -} i3_option; - - -/********************************* - ** structure of i3 option list ** - *********************************/ - -typedef struct i3_option_list -{ - i3_option *head; - i3_option *tail; -} i3_option_list; - - -/**************************** - ** structure of i3-header ** - ****************************/ - -typedef struct i3_header -{ - uint8_t ver; /* version */ - uint8_t flags; - struct i3_stack *stack; /* stack of IDs */ - i3_option_list *option_list; /* option list */ -} i3_header; - -#define get_hdr_options(p) (p + ID_LEN*((p)[2] & 0xf) + 3*sizeof(char)) -#define get_hdr_stack(p) ((p) + 3*sizeof(char)) -#define get_flags(p) ((p)[1]) -#define get_stack_len(p) ( (p)[2] & 0xf) -#define get_first_hop(p) ( get_flags(p) & I3_FIRST_HOP ) -#define set_first_hop(p) ( (p)[1] = (p)[1] | I3_FIRST_HOP ) -#define clear_first_hop(p) ( (p)[1] = (p)[1] & (~I3_FIRST_HOP) ) - - -/***************************************************************** - * - * i3_header: - * - * 7 0 - * ---------------- - * | version | - * ---------------- - * | flags | - * ---------------- - * | stacklen | - * ---------------- - * | | - * | i3_stack | - * | (var size) | - * | ... | - * ---------------- - * | option_list_len| - * | | - * ---------------- - * | | - * | i3_option_list | - * | (var size) | - * | ... | - * ---------------- - * - * - * i3_stack: list of i3 IDs (number of IDs < 16) - * ---------------- - * | ID #1 | - * | | - * ---------------- - * | ... | - * | | - * ---------------- - * | ID #n | - * | | - * ---------------- - * - * i3_option_list: list of i3_option's - * ---------------- - * | option list | - * | size | - * | (in bytes) | - * | | - * ---------------- - * | i3 option | - * | (var size) | - * | | - * ---------------- - * | | - * | ... | - * | | - * ---------------- - * | i3 option | - * | (var size) | - * | | - * ---------------- - * - * i3 options: - * - * return address - * --------------- - * | opt type | - * --------------- - * | data type | - * --------------- - * | i3 stack or | - * | IPv4 addr or | - * | IPv6 add | - * ---------------- - * - * trigger - * --------------- - * | opt type | - * --------------- - * | flags | - * --------------- - * | | - * | i3 id (32B) | - * | ... | - * --------------- - * |prefix len (2B)| - * --------------- - * | | - * | Nonce (16B) | - * | ... | - * --------------- - * | i3 address | - * --------------- - * - * i3_addr - * --------------- - * | type | - * --------------- - * | IPv4 addr or | - * | IPv6 addr or | - * | i3_stack | - * ---------------- - * - * IPv4 addr - * --------------- - * | | - * | IP address | - * | | - * | | - * --------------- - * | port # | - * | | - * --------------- - * - * IPv6 addr - * --------------- - * | | - * | IPv6 addr | - * | (16 B) | - * | ... | - * --------------- - * | port # | - * | | - * --------------- - * - * I3 id - * --------------- - * | | - * | | - * | (32 B) | - * | ... | - * --------------- - * - *****************************************************************/ - - -#endif /* I3_H */ +/*************************************************************************** +* i3.h - description +* ------------------- +* begin : Son Nov 17 2002 +* email : wehrle@xxxxxxxxxxxxxxxxx +***************************************************************************/ + +#ifndef I3_H +#define I3_H + +#include <sys/types.h> +#ifdef _WIN32 + #include "../utils/fwint.h" +#endif +#include "../utils/netwrap.h" +#ifdef __APPLE__ +#include <inttypes.h> // Need uint8_t +#include <sys/time.h> // Need timeval +#endif +#include <assert.h> + +/* CLIENT_API_DEPRECIATED specifies whether the old client api is used */ +//#define CLIENT_API_DEPRECIATED + +#ifndef TRUE +#define TRUE 1 +#define FALSE 0 +#endif + +#define CHAR_BITS 8 + +// first byte in a packet sent to an i3 server +// - normal i3 packet --> version number +// - i3 ping packet --> I3_PING_PACKET + +// note that i3 ping packets are not i3 packets; ping responses +// should be from a different process, but for fatesharing reasons +// implemented together +#define I3_v01 0x10 +#define I3_PING_PKT 0x01 + +#define I3_DATA 0x10 +#define I3_OPTION_LIST 0x20 +#define I3_FIRST_HOP 0x40 + +#define I3_ADDR_TYPE_STACK 0x10 +#define I3_ADDR_TYPE_IPv4 0x20 +#define I3_ADDR_TYPE_IPv6 0x30 +#define I3_ADDR_TYPE_IPv4_NAT 0x40 + +#define I3_ID_TYPE_PUBLIC 0x10 +#define I3_ID_TYPE_PRIVATE 0x20 +//#define I3_ID_TYPE_UNCONSTRAINED 0x30 +#define I3_ID_TYPE_UNKNOWN 0x40 + +#define I3_OPT_SENDER 0x01 +#define I3_OPT_TRIGGER_INSERT 0x02 +#define I3_OPT_TRIGGER_CHALLENGE 0x03 +#define I3_OPT_TRIGGER_ACK 0x04 +#define I3_OPT_TRIGGER_REMOVE 0x05 +#define I3_OPT_TRIGGER_NOT_PRESENT 0x06 +#define I3_OPT_REQUEST_FOR_CACHE 0x07 +#define I3_OPT_CACHE_ADDR 0x08 +#define I3_OPT_FORCE_CACHE_ADDR 0x09 +#define I3_OPT_CONSTRAINT_FAILED 0x10 +#define I3_OPT_ROUTE_BROKEN 0x11 +#define I3_OPT_REQUEST_FOR_CACHE_SHORTCUT 0x12 +#define I3_OPT_CACHE_SHORTCUT_ADDR 0x13 +#define I3_OPT_CACHE_DEST_ADDR 0x14 +#define I3_OPT_REQUEST_FOR_CACHE_SHORTCUT_INDIR 0x15 +#define I3_OPT_DESTINATION 0x20 +#define I3_OPT_TRIGGER_RATELIMIT 0x30 + +/* flags associated to trigger */ +#define I3_TRIGGER_FLAG_ALLOW_SHORTCUT 0x1 +#define I3_TRIGGER_FLAG_RATE_LIMIT 0x2 + +#define I3_ERR_INVALID_VER -1 +#define I3_ERR_INVALID_FLAGS -2 +#define I3_ERR_PKT_LEN_TOO_SHORT -3 +#define I3_ERR_INVALID_STACK -4 +#define I3_ERR_INVALID_ADDR -5 +#define I3_ERR_INVALID_OPTLIST -6 +#define I3_ERR_INVALID_OPTION -7 + +#define L_CONSTRAINT 0 +#define R_CONSTRAINT 1 + +#define NEWS_INSTRUMENT 1 + +#if NEWS_INSTRUMENT +// 2 options for instrumenting i3 servers +// maybe modified later for cleanliness +#define I3_OPT_LOG_PACKET 0x0A +#define I3_OPT_APPEND_TS 0x0B +#define MAX_NEWS_OPTS 2 +#endif + +#define OK 1 +#define ERROR 0 + +#define INDENT_CONST 2 /* just for printing data nice for debugging */ +#define INDENT_BUF_LEN 100 /* just for printing data nice for debugging */ + + +/****************************** +** Type of an i3-id ** +******************************/ + +#define ID_LEN 32 /* in bytes */ +#define ID_LEN_BITS 256 /* in bits, i.e., ID_LEN_BITS = ID_LEN*8 */ +#define MIN_PREFIX_LEN 192 /* minimum prefix length that has to match */ + +#define PREFIX_LEN 8 +#define KEY_LEN 16 /* length of key in bytes */ + +#define PREFIX_ID(id) (id.x) +#define KEY_ID(id) (id.x + PREFIX_LEN) +#define KEY_ID_PTR(id) (id->x + PREFIX_LEN) +#define SUFFIX_ID(id) (id.x + SUFFIX_LEN) +typedef struct { + uint8_t x[ID_LEN]; +} ID; + +typedef struct { + uint8_t x[KEY_LEN]; +} Key; + +/****************************** +** structure of an i3-stack ** +******************************/ + +#define I3_MAX_STACK_LEN 15 +typedef struct i3_stack { + int len; /* # of IDs in the stack */ + ID *ids; +} i3_stack; + + +/******************************** +** structure of an i3 address ** +********************************/ +#ifndef CCURED + #define __SELECTEDWHEN(x) + #define __SELECTOR(x) + #define __RTTI +#endif +typedef struct i3_addr { + char type; + union { + /* I3_ADDR_TYPE_STACK */ + i3_stack *stack __SELECTEDWHEN("type" == I3_ADDR_TYPE_STACK); + + struct /* I3_ADDR_TYPE_IPv4 */ + { + struct in_addr addr; + uint16_t port; + } v4 __SELECTEDWHEN("type" == I3_ADDR_TYPE_IPv4); + + /* v4_nat is used to store all the information required to support + * NAT hosts: + * - (host_addr, host_port) is the address of the host, which + * can be behind NAT + * - (nat_addr, nat_port) is the address assigned by the NAT to the host + * - (i3srv_addr, i3srv_port) is the address of the first i3 server + * to which the host sends packets + */ + struct { + struct in_addr host_addr; + uint16_t host_port; + struct in_addr nat_addr; + uint16_t nat_port; + struct in_addr i3srv_addr; + uint16_t i3srv_port; + } v4_nat __SELECTEDWHEN("type" == I3_ADDR_TYPE_IPv4_NAT); + + +#ifndef __CYGWIN__ + struct /* I3_ADDR_TYPE_IPv6 */ + { + struct in6_addr addr; + uint16_t port; + } v6 __SELECTEDWHEN("type" == I3_ADDR_TYPE_IPv6); +#endif + } t; +} i3_addr; + + +typedef struct token_bucket { +#define TOKEN_BUCKET_PACKET 0 +#define TOKEN_BUCKET_BYTE 1 + char type; /* specifies whether units are "packets" or "bytes" */ + uint32_t depth; /* token depth (bytes or packets) */ + uint32_t r; /* long term rate (Bps or pps) */ + uint32_t R; /* maximum rate (Bps or pps) */ + /* only the first three fields are packed in packet; + * the following two fields are temporar variables + * used to implement the token bucket functionality + */ + uint32_t tokens; /* actual number of tokens in the bucket (bytes or packets) + * Note: "tokens" is never larger than "depth" + */ + uint64_t last_time; /* time since the previous packet has been + * received (usec) + */ +} token_bucket; + +#define NONCE_LEN 16 +typedef struct i3_trigger { + ID id; + uint8_t flags; /* possible flags:I3_TRIGGER_FLAG_ALLOW_SHORTCUT (0x1) + * I3_TRIGGER_FLAG_RATE_LIMIT (0x2) + */ + uint16_t prefix_len; /* packet ID should match trigID in the first + * max(prefix_len, MIN_PREFIX_LEN) bits or more */ + char nonce[NONCE_LEN]; + i3_addr * to; + Key key; + token_bucket *tb; /* this is set only if I3_TRIGGER_FLAG_RATE_LIMIT is set*/ +} i3_trigger; + + +/************************************ +** i3_option_entry data structure ** +************************************/ + +typedef struct i3_option { + char type; + union { + /* sender address where to send a reply (type = I3_OPT_SENDER) + */ + i3_addr *ret_addr __SELECTEDWHEN("type" == I3_OPT_SENDER); + + /* sender address where to send a reply (type = I3_OPT_SENDER) + */ + i3_addr *dst_addr __SELECTEDWHEN("type" == I3_OPT_DESTINATION); + + /* trigger insertion and challenge + * (type = I3_OPT_TRIGGER_INSERT, I3_OPT_TRIGGER_CHALLENGE, + * I3_OPT_TRIGGER_ACK, I3_OPT_TRIGGER_REMOVE, + * I3_OPT_CACHE_ADDR, I3_OPT_CACHE_SHORTCUT_ADDR, + * I3_OPT_CACHE_DEST_ADDR, + * I3_OPT_CONSTRAINT_FAILED, I3_OPT_ROUTE_BROKEN) + * + * When I3_OPT_CACHE_ADDR is used, trigger->to represents the + * the address suggested by the i3 server (e.g., its own address) + * where client should send data and control messages addressed to + * any identifier that shares MIN_PREFIX_LEN bits with trigger->id. + * Thus, this option allows the client to cache the address of a server + * responsible for a certain identifier. + * When I3_OPT_CACHE_SHORTCUT_ADDR is used, trigger->to represents the + * the address of the end host. This option is sent directly to the + * receiver. The receiver can see whether the sender is behind a NAT + * by comparing the IP source address of the packet and the IP address + * in trigger->to. + */ + i3_trigger *trigger __SELECTEDWHEN("type" == I3_OPT_TRIGGER_INSERT || \ + "type" == I3_OPT_TRIGGER_CHALLENGE || \ + "type" == I3_OPT_TRIGGER_ACK || \ + "type" == I3_OPT_TRIGGER_REMOVE || \ + "type" == I3_OPT_CACHE_ADDR || \ + "type" == I3_OPT_CACHE_DEST_ADDR || \ + "type" == I3_OPT_CACHE_SHORTCUT_ADDR || \ + "type" == I3_OPT_CONSTRAINT_FAILED \ + "type" == I3_OPT_ROUTE_BROKEN); + + /* id to which the reply refers to (type = I3_OPT_TRIGGER_NOT_PRESENT, + * I3_OPT_REQUEST_FOR_CACHE, I3_OPT_TRIGGER_RATELIMIT) + */ + ID *id __SELECTEDWHEN("type" == I3_OPT_TRIGGER_NOT_PRESENT || \ + "type" == I3_OPT_TRIGGER_RATELIMIT); + + /* the cache request is for the first ID in the stack + * (type = I3_OPT_REQUEST_FOR_CACHE, I3_OPT_REQUEST_FOR_CACHE_SHORTCUT) + */ + void *nothing __SELECTEDWHEN("type" == I3_OPT_REQUEST_FOR_CACHE || \ + "type" == I3_OPT_REQUEST_FOR_CACHE_SHORTCUT || \ + "type" == I3_OPT_REQUEST_FOR_CACHE_SHORTCUT_INDIR); + } entry; + struct i3_option *next; +} i3_option; + + +/********************************* +** structure of i3 option list ** +*********************************/ + +typedef struct i3_option_list { + i3_option *head; + i3_option *tail; +} i3_option_list; + + +/**************************** +** structure of i3-header ** +****************************/ + +typedef struct i3_header { + uint8_t ver; /* version */ + uint8_t flags; + struct i3_stack *stack; /* stack of IDs */ + i3_option_list * option_list; /* option list */ +} i3_header; + +#define get_hdr_options(p) (p + ID_LEN * ((p)[2] & 0xf) + 3 * sizeof(char)) +#define get_hdr_stack(p) ((p) + 3 * sizeof(char)) +#define get_flags(p) ((p)[1]) +#define get_stack_len(p) ((p)[2] & 0xf) +#define get_first_hop(p) (get_flags(p) & I3_FIRST_HOP) +#define set_first_hop(p) ((p)[1] = (p)[1] | I3_FIRST_HOP) +#define clear_first_hop(p) ((p)[1] = (p)[1] & (~I3_FIRST_HOP)) + + +/***************************************************************** +* +* i3_header: +* +* 7 0 +* ---------------- +* | version | +* ---------------- +* | flags | +* ---------------- +* | stacklen | +* ---------------- +* | | +* | i3_stack | +* | (var size) | +* | ... | +* ---------------- +* | option_list_len| +* | | +* ---------------- +* | | +* | i3_option_list | +* | (var size) | +* | ... | +* ---------------- +* +* +* i3_stack: list of i3 IDs (number of IDs < 16) +* ---------------- +* | ID #1 | +* | | +* ---------------- +* | ... | +* | | +* ---------------- +* | ID #n | +* | | +* ---------------- +* +* i3_option_list: list of i3_option's +* ---------------- +* | option list | +* | size | +* | (in bytes) | +* | | +* ---------------- +* | i3 option | +* | (var size) | +* | | +* ---------------- +* | | +* | ... | +* | | +* ---------------- +* | i3 option | +* | (var size) | +* | | +* ---------------- +* +* i3 options: +* +* return address +* --------------- +* | opt type | +* --------------- +* | data type | +* --------------- +* | i3 stack or | +* | IPv4 addr or | +* | IPv6 add | +* ---------------- +* +* trigger +* --------------- +* | opt type | +* --------------- +* | flags | +* --------------- +* | | +* | i3 id (32B) | +* | ... | +* --------------- +* |prefix len (2B)| +* --------------- +* | | +* | Nonce (16B) | +* | ... | +* --------------- +* | i3 address | +* --------------- +* +* i3_addr +* --------------- +* | type | +* --------------- +* | IPv4 addr or | +* | IPv6 addr or | +* | i3_stack | +* ---------------- +* +* IPv4 addr +* --------------- +* | | +* | IP address | +* | | +* | | +* --------------- +* | port # | +* | | +* --------------- +* +* IPv6 addr +* --------------- +* | | +* | IPv6 addr | +* | (16 B) | +* | ... | +* --------------- +* | port # | +* | | +* --------------- +* +* I3 id +* --------------- +* | | +* | | +* | (32 B) | +* | ... | +* --------------- +* +*****************************************************************/ + + +#endif /* I3_H */ === modified file 'i3/i3/i3_addr.c' --- i3/i3/i3_addr.c 2010-01-06 17:03:26 +0000 +++ i3/i3/i3_addr.c 2010-02-11 11:49:47 +0000 @@ -1,677 +1,683 @@ -/*************************************************************************** - i3_addr.c - description - ------------------- - begin : Nov 18 2002 - email : istoica@xxxxxxxxxxxxxxx - ***************************************************************************/ - -#include "i3.h" -#include "i3_fun.h" -#include <stdlib.h> -#include <stdio.h> -#include <string.h> - -#ifndef _WIN32 -# include <sys/types.h> -# include <sys/socket.h> -# include <netinet/in.h> -# include <arpa/inet.h> -#endif - -#include "i3_debug.h" - - -#include "../utils/gen_utils.h" - -/*************************************************************************** - * alloc_i3_addr - allocate address data structure - * - * return: - * pointer to the allocated data structure - ***************************************************************************/ -i3_addr *alloc_i3_addr() -{ - i3_addr *addr; - - /* TODO: just simply call alloc for now; - * preallocate a pool of buffers in the future */ - addr = (i3_addr *)malloc(sizeof(i3_addr)); - if (addr) - return addr; - - I3_PRINT_INFO0( - I3_INFO_LEVEL_FATAL_ERROR, - "FATAL ERROR: memory allocation error in alloc_i3_addr\n" - ); - return NULL; -} - - -/*************************************************************************** - * init_i3_addr_ipv4, init_i3_addr_ipv6, init_i3_addr_stack - - * initailize the fields of address data structure - * - * input: - * addr, port: IPv4/IPv6 address and port numbres - * - or - - * stack: pointer to stack (this data structure is not copied; don't - * free it after calling the function) - * - ***************************************************************************/ -void init_i3_addr_ipv4(i3_addr *a, struct in_addr addr, uint16_t port) -{ - a->type = I3_ADDR_TYPE_IPv4; - a->t.v4.addr.s_addr = addr.s_addr; - a->t.v4.port = port; -} - -void init_i3_addr_ipv4_nat(i3_addr *a, - struct in_addr host_addr, uint16_t host_port, - struct in_addr nat_addr, uint16_t nat_port, - struct in_addr i3srv_addr, uint16_t i3srv_port) -{ - a->type = I3_ADDR_TYPE_IPv4_NAT; - a->t.v4_nat.host_addr.s_addr = host_addr.s_addr; - a->t.v4_nat.host_port = host_port; - a->t.v4_nat.nat_addr.s_addr = nat_addr.s_addr; - a->t.v4_nat.nat_port = nat_port; - a->t.v4_nat.i3srv_addr.s_addr = i3srv_addr.s_addr; - a->t.v4_nat.i3srv_port = i3srv_port; -} -#ifndef __CYGWIN__ -void init_i3_addr_ipv6(i3_addr *a, struct in6_addr addr, uint16_t port) -{ - a->type = I3_ADDR_TYPE_IPv6; -#ifndef CCURED - memcpy((char *)&a->t.v6.addr.s6_addr, (char *)&addr.s6_addr, - sizeof(struct in6_addr)); -#else - a->t.v6.addr = addr; -#endif - a->t.v6.port = port; -} -#endif -void init_i3_addr_stack(i3_addr *a, i3_stack *s) -{ - a->type = I3_ADDR_TYPE_STACK; - a->t.stack = s; -} - - -/*************************************************************************** - * free_i3_trigger - free address data structure - * - * input: - * i3 address to be freed - * - ***************************************************************************/ - -void free_i3_addr(i3_addr *addr) -{ - if (addr->type == I3_ADDR_TYPE_STACK) - free_i3_stack(addr->t.stack); - free(addr); -} - -/*************************************************************************** - * duplicate_i3_addr - duplicate a given address - * - * input: - * a - address to be duplicated - * - * return: - * a's replica - ***************************************************************************/ - -i3_addr *duplicate_i3_addr(i3_addr *a) -{ - i3_addr *anew; - - if (NULL == a) - return NULL; - else - anew = alloc_i3_addr(); - - anew->type = a->type; - switch (a->type) { - case I3_ADDR_TYPE_IPv4: - anew->t.v4.addr.s_addr = a->t.v4.addr.s_addr; - anew->t.v4.port = a->t.v4.port; - break; - case I3_ADDR_TYPE_IPv4_NAT: - anew->t.v4_nat.host_addr.s_addr = a->t.v4_nat.host_addr.s_addr; - anew->t.v4_nat.host_port = a->t.v4_nat.host_port; - anew->t.v4_nat.nat_addr.s_addr = a->t.v4_nat.nat_addr.s_addr; - anew->t.v4_nat.nat_port = a->t.v4_nat.nat_port; - anew->t.v4_nat.i3srv_addr.s_addr = a->t.v4_nat.i3srv_addr.s_addr; - anew->t.v4_nat.i3srv_port = a->t.v4_nat.i3srv_port; - break; -#ifndef __CYGWIN__ - case I3_ADDR_TYPE_IPv6: -#ifndef CCURED - memcpy((char *)&anew->t.v6.addr.s6_addr, (char *)&a->t.v6.addr.s6_addr, - sizeof(struct in6_addr)); -#else - // Cleaner and faster - anew->t.v6.addr = a->t.v6.addr; -#endif - anew->t.v6.port = a->t.v6.port; - break; -#endif - case I3_ADDR_TYPE_STACK: - anew->t.stack = duplicate_i3_stack(a->t.stack); - break; - default: - I3_PRINT_DEBUG1(I3_DEBUG_LEVEL_MINIMAL, "duplicate_i3_id: invalid address type %d.\n", a->type); - } - - return anew; -} - - - -/*************************************************************************** - * pack_i3_addr - convert an i3 address data structure in packet format - * - * input: - * p - address of the buffer where the address is to be stored in - * packet format (pre-allocated) - * addr - trigger to be converted in packet format - * - * output: - * length - length of the address in packet format - * - ***************************************************************************/ - -void pack_i3_addr(char *p, i3_addr *addr, unsigned short *length) -{ - unsigned short len = 0, l; - long long_temp; - short short_temp; - - p[0] = addr->type; - p++; len++; - - switch (addr->type) { - case I3_ADDR_TYPE_STACK: - pack_i3_stack(p, addr->t.stack, &l); - len += l; - break; - - case I3_ADDR_TYPE_IPv4: - long_temp = htonl(addr->t.v4.addr.s_addr); - memcpy(p, (char *)&long_temp, sizeof(long)); - p += sizeof(long); - len += sizeof(long); - - short_temp = htons(addr->t.v4.port); - memcpy(p, &short_temp, sizeof(short)); - p += sizeof(short); - len += sizeof(short); - - break; - - case I3_ADDR_TYPE_IPv4_NAT: - long_temp = htonl(addr->t.v4_nat.host_addr.s_addr); - memcpy(p, (char *)&long_temp, sizeof(long)); - p += sizeof(long); - len += sizeof(long); - short_temp = htons(addr->t.v4_nat.host_port); - memcpy(p, &short_temp, sizeof(short)); - p += sizeof(short); - len += sizeof(short); - - long_temp = htonl(addr->t.v4_nat.nat_addr.s_addr); - memcpy(p, (char *)&long_temp, sizeof(long)); - p += sizeof(long); - len += sizeof(long); - short_temp = htons(addr->t.v4_nat.nat_port); - memcpy(p, &short_temp, sizeof(short)); - p += sizeof(short); - len += sizeof(short); - - long_temp = htonl(addr->t.v4_nat.i3srv_addr.s_addr); - memcpy(p, (char *)&long_temp, sizeof(long)); - p += sizeof(long); - len += sizeof(long); - short_temp = htons(addr->t.v4_nat.i3srv_port); - memcpy(p, &short_temp, sizeof(short)); - p += sizeof(short); - len += sizeof(short); - break; - -#ifndef _WIN32 - case I3_ADDR_TYPE_IPv6: -#ifndef CCURED - memcpy(p, (char *)&addr->t.v6.addr.s6_addr, sizeof(struct in6_addr)); -#else - * (struct in6_addr *)p = addr->t.v6.addr; -#endif - p += sizeof(struct in6_addr); - len += sizeof(struct in6_addr); - - short_temp = htons(addr->t.v6.port); - memcpy(p, &short_temp, sizeof(short)); - len += sizeof(short); - p += sizeof(short); - - break; -#endif - - default: - printf("pack_i3_addr: invalid address type %d\n", addr->type); - } - - *length = len; -} - -unsigned short get_i3_addr_len(i3_addr *addr) -{ - unsigned short length; - - length = sizeof(char); /* type */ - - switch (addr->type) { - case I3_ADDR_TYPE_STACK: - length += get_i3_stack_len(addr->t.stack); - break; - case I3_ADDR_TYPE_IPv4: - length += sizeof(long) + sizeof(short); - break; - case I3_ADDR_TYPE_IPv4_NAT: - length += 3*(sizeof(long) + sizeof(short)); - break; -#ifndef __CYGWIN__ - case I3_ADDR_TYPE_IPv6: - length += sizeof(struct in6_addr) + sizeof(short); - break; -#endif - default: - I3_PRINT_DEBUG1(I3_DEBUG_LEVEL_MINIMAL, "pack_i3_addr: invalid address type %d\n", addr->type); - } - - return length; -} - - -/*************************************************************************** - * unpack_i3_addr - copy address info from packet to a trigger - * data structure - * - * input: - * p - address where address is stored in packet format - * - * return: - * address data structure initialized with the info from buffer "p" - * - * output: - * length - length of the address info in packet format - * - ***************************************************************************/ - -i3_addr *unpack_i3_addr(char *p, unsigned short *length) -{ - unsigned short len; - i3_addr *addr = alloc_i3_addr(); - - addr->type = p[0]; - p++; *length = 1; - - switch (addr->type) { - case I3_ADDR_TYPE_STACK: - addr->t.stack = unpack_i3_stack(p, &len); - *length += len; - break; - - case I3_ADDR_TYPE_IPv4: - addr->t.v4.addr.s_addr = ntohl(*((long *)p)); - p += sizeof(long); - *length += sizeof(long); - - addr->t.v4.port = ntohs(*((short *)p)); - *length += sizeof(short); - p += sizeof(short); - - break; - - case I3_ADDR_TYPE_IPv4_NAT: - addr->t.v4_nat.host_addr.s_addr = ntohl(*((long *)p)); - p += sizeof(long); - *length += sizeof(long); - addr->t.v4_nat.host_port = ntohs(*((short *)p)); - *length += sizeof(short); - p += sizeof(short); - - addr->t.v4_nat.nat_addr.s_addr = ntohl(*((long *)p)); - p += sizeof(long); - *length += sizeof(long); - addr->t.v4_nat.nat_port = ntohs(*((short *)p)); - *length += sizeof(short); - p += sizeof(short); - - addr->t.v4_nat.i3srv_addr.s_addr = ntohl(*((long *)p)); - p += sizeof(long); - *length += sizeof(long); - addr->t.v4_nat.i3srv_port = ntohs(*((short *)p)); - *length += sizeof(short); - p += sizeof(short); - break; - -#ifndef __CYGWIN__ - case I3_ADDR_TYPE_IPv6: -#ifndef CCURED - memcpy((char *)&addr->t.v6.addr.s6_addr, p, sizeof(struct in6_addr)); -#else - addr->t.v6.addr = * (struct in6_addr *)p; -#endif - - p += sizeof(struct in6_addr); - *length += sizeof(struct in6_addr); - - addr->t.v6.port = ntohs(*((short *)p)); - *length += sizeof(short); - p += sizeof(short); - - break; -#endif - - default: - I3_PRINT_DEBUG1(I3_DEBUG_LEVEL_MINIMAL,"unpack_i3_addr: invalid address type %d\n", addr->type); - } - return addr; -} - -/*************************************************************************** - * check_i3_addr - check address whether is well-formed - * - * input: - * p - address where i3_addr is stored in packet format - * - * return: - * error code; FALSE if no error - * - * output: - * length - length of the address info in packet format - * - ***************************************************************************/ - -int check_i3_addr(char *p, unsigned short *length, char *type) -{ - *type = p[0]; - - p++; /* skip address type field */ - - switch (*type) { - case I3_ADDR_TYPE_STACK: - check_i3_stack(p, length); - break; - case I3_ADDR_TYPE_IPv4: - *length = sizeof(long)/*IP address*/ + sizeof(short)/*port*/; - break; - case I3_ADDR_TYPE_IPv4_NAT: - *length = 3*(sizeof(long)/*IP address*/ + sizeof(short)/*port*/); - break; -#ifndef __CYGWIN__ - case I3_ADDR_TYPE_IPv6: - *length = sizeof(struct in6_addr)/*IP address*/ + sizeof(short)/*port*/; - break; -#endif - default: - return I3_ERR_INVALID_ADDR; - - } - - *length += 1; /* account for address type */ - - return FALSE; -} - - -/** - * This function understands natted addresses. - * If an address is natted, the nat_address and nat_port number - * are used in the comparison. - * @author Dilip - */ -int addr_nat_equal(i3_addr *a1, i3_addr *a2) -{ - - struct in_addr cmp_addr_A, cmp_addr_B; - int cmp_port_A = 0, cmp_port_B = 0; - - memset(&cmp_addr_A, 0, sizeof(struct in_addr)); - memset(&cmp_addr_B, 0, sizeof(struct in_addr)); - - if (a1->type == I3_ADDR_TYPE_IPv4) { - memcpy(&cmp_addr_A, &a1->t.v4.addr, sizeof(struct in_addr)); - cmp_port_A = a1->t.v4.port; - } else if (a1->type == I3_ADDR_TYPE_IPv4_NAT) { - memcpy(&cmp_addr_A, &a1->t.v4_nat.host_addr, sizeof(struct in_addr)); - cmp_port_A = a1->t.v4_nat.host_port; - } - - if (a2->type == I3_ADDR_TYPE_IPv4) { - memcpy(&cmp_addr_B, &a2->t.v4.addr, sizeof(struct in_addr)); - cmp_port_B = a2->t.v4.port; - } else if (a2->type == I3_ADDR_TYPE_IPv4_NAT) { - memcpy(&cmp_addr_B, &a2->t.v4_nat.host_addr, sizeof(struct in_addr)); - cmp_port_B = a2->t.v4_nat.host_port; - } - - if (cmp_addr_A.s_addr != cmp_addr_B.s_addr || cmp_port_A != cmp_port_B) { - return FALSE; - } else { - return TRUE; - } - -} - - -/*************************************************************************** - * addr_equal - compare two addresses - * - * input: - * t1, t2 - addresses to be compared - * - * return: - * TRUE, if the addresses are identical; FALSE, otherwise - * - ***************************************************************************/ - -int addr_equal(i3_addr *a1, i3_addr *a2) -{ -#ifndef __CYGWIN__ - uint i; -#endif - - if (a1->type != a2->type) - return FALSE; - - switch (a1->type) { - case I3_ADDR_TYPE_IPv4: - if ((a1->t.v4.addr.s_addr != a2->t.v4.addr.s_addr) || - (a1->t.v4.port != a2->t.v4.port)) - return FALSE; - break; - case I3_ADDR_TYPE_IPv4_NAT: - if ((a1->t.v4_nat.host_addr.s_addr != a2->t.v4_nat.host_addr.s_addr) || - (a1->t.v4_nat.host_port != a2->t.v4_nat.host_port) || - (a1->t.v4_nat.nat_addr.s_addr != a2->t.v4_nat.nat_addr.s_addr) || - (a1->t.v4_nat.nat_port != a2->t.v4_nat.nat_port) || - (a1->t.v4_nat.i3srv_addr.s_addr != a2->t.v4_nat.i3srv_addr.s_addr) || - (a1->t.v4_nat.i3srv_port != a2->t.v4_nat.i3srv_port)) - return FALSE; - break; -#ifndef __CYGWIN__ - case I3_ADDR_TYPE_IPv6: - for (i = 0; i < sizeof(struct in6_addr); i++) - if (a1->t.v6.addr.s6_addr[i] != a2->t.v6.addr.s6_addr[i]) - return FALSE; - if (a1->t.v6.port == a2->t.v6.port) - return FALSE; - break; -#endif - case I3_ADDR_TYPE_STACK: - if (a1->t.stack->len != a2->t.stack->len) - return FALSE; - if (memcmp((char *)a1->t.stack->ids, (char *)a2->t.stack->ids, - a1->t.stack->len*sizeof(ID))) - return FALSE; - } - return TRUE; -} - - -/*************************************************************************** - * sizeof_addr - return the length of the address data structure - * - * input: - * a - given address - * - * return: - * length in bytes of the address - * - ***************************************************************************/ - -int sizeof_addr(i3_addr *a) -{ - switch (a->type) { - case I3_ADDR_TYPE_IPv4: - return (sizeof(struct in_addr) + sizeof(uint16_t) + sizeof(a->type) + - KEY_LEN); - case I3_ADDR_TYPE_IPv4_NAT: - return (3*(sizeof(struct in_addr) + sizeof(uint16_t)) + sizeof(a->type) + - KEY_LEN); -#ifndef __CYGWIN__ - case I3_ADDR_TYPE_IPv6: - return (sizeof(struct in6_addr) + sizeof(uint16_t) + sizeof(a->type) + - KEY_LEN); -#endif - case I3_ADDR_TYPE_STACK: - return (a->t.stack->len*sizeof(ID) + sizeof(a->type)); - } - I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, "addr_len: Invalid trigger type"); - return -1; -} - -/*************************************************************************** - * printf_id - print i3-id with an indentation of "indent" - **************************************************************************/ - -void printf_id(ID *id, int indent) -{ - uint i; - char buf[INDENT_BUF_LEN]; - - memset(buf, ' ', indent); - buf[indent] = 0; - - printf("%s i3-id = ", buf); - for (i = 0; i < sizeof(ID); i++) - printf("%02x", id->x[i]); - printf("\n"); -} - -/*************************************************************************** - * printf_i3_addr - print i3-addr with an indentation of "indent" - **************************************************************************/ - -void printf_i3_addr(i3_addr *addr, int indent) -{ -#ifndef __CYGWIN__ - uint i; -#endif - char buf[INDENT_BUF_LEN]; - struct in_addr ia; - - memset(buf, ' ', indent); - buf[indent] = 0; - - printf("%s addr type = %d\n", buf, addr->type); - - switch (addr->type) { - case I3_ADDR_TYPE_STACK: - printf_i3_stack(addr->t.stack, indent); - break; - case I3_ADDR_TYPE_IPv4: - ia.s_addr = htonl(addr->t.v4.addr.s_addr); - printf("%s IPv4 (address, port) = (%s, %d)", - buf, inet_ntoa(ia), addr->t.v4.port); - break; - case I3_ADDR_TYPE_IPv4_NAT: - ia.s_addr = htonl(addr->t.v4_nat.host_addr.s_addr); - printf("%s NAT_IPv4 (host_addr, host_port) = (%s, %d)\n", - buf, inet_ntoa(ia), addr->t.v4_nat.host_port); - ia.s_addr = htonl(addr->t.v4_nat.nat_addr.s_addr); - printf("%s (nat_addr, nat_port) = (%s, %d)\n", - buf, inet_ntoa(ia), addr->t.v4_nat.nat_port); - ia.s_addr = htonl(addr->t.v4_nat.i3srv_addr.s_addr); - printf("%s (i3srv_addr, i3srv_port) = (%s, %d)\n", - buf, inet_ntoa(ia), addr->t.v4_nat.i3srv_port); - break; -#ifndef __CYGWIN__ - case I3_ADDR_TYPE_IPv6: - printf("%s IPv6 (address, port) = (", buf); - for (i = 0; i < sizeof(struct in6_addr); i++) - printf("%d.", addr->t.v6.addr.s6_addr[i]); - printf(", %d)", addr->t.v6.port); - break; -#endif - default: - printf("Unknown addr type\n"); - } - printf("\n"); -} - -/*************************************************************************** - * compute_nonce - compute the nonce for challenging trigger insertion - **************************************************************************/ - -void compute_nonce(char *nonce, i3_addr *a) -{ - memset(nonce, 0, NONCE_LEN); - - switch (a->type) { - case I3_ADDR_TYPE_IPv4: -#ifndef CCURED - memcpy(nonce, (char *)&a->t.v4.addr.s_addr, sizeof(struct in_addr)); -#else - * (struct in_addr *)nonce = a->t.v4.addr; -#endif -#ifndef CCURED - memcpy(nonce + sizeof(struct in_addr), - (char *)&a->t.v4.port, sizeof(a->t.v4.port)); -#else - * (uint16_t *)(nonce + sizeof(struct in_addr)) = a->t.v4.port; -#endif - break; - case I3_ADDR_TYPE_IPv4_NAT: - /* the 2nd address in the two-hop route represents the - * the Internet-routable address of the destination - */ - memcpy(nonce, (char *)&a->t.v4_nat.nat_addr.s_addr, - sizeof(struct in_addr)); - memcpy(nonce + sizeof(struct in_addr), - (char *)&a->t.v4_nat.host_port, sizeof(a->t.v4_nat.nat_port)); - break; -#ifndef __CYGWIN__ - case I3_ADDR_TYPE_IPv6: -#ifndef CCURED - memcpy(nonce, (char *)&a->t.v6.addr.s6_addr, - MIN(sizeof(struct in6_addr), NONCE_LEN)); -#else - { - struct in6_addr tmp = a->t.v6.addr; - memcpy(nonce, (char*)&tmp, MIN(sizeof(struct in6_addr), NONCE_LEN)); - } -#endif - break; -#endif - case I3_ADDR_TYPE_STACK: - memcpy(nonce, a->t.stack->ids, NONCE_LEN); - break; - default: - I3_PRINT_DEBUG1(I3_DEBUG_LEVEL_MINIMAL,"compute_nonce: invalid address type %d\n", a->type); - printf_i3_addr(a, 2); - } -} +/*************************************************************************** +* i3_addr.c - description +* ------------------- +* begin : Nov 18 2002 +* email : istoica@xxxxxxxxxxxxxxx +***************************************************************************/ + +#include "i3.h" +#include "i3_fun.h" +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#ifndef _WIN32 +# include <sys/types.h> +# include <sys/socket.h> +# include <netinet/in.h> +# include <arpa/inet.h> +#endif + +#include "i3_debug.h" + + +#include "../utils/gen_utils.h" + +/*************************************************************************** +* alloc_i3_addr - allocate address data structure +* +* return: +* pointer to the allocated data structure +***************************************************************************/ +i3_addr *alloc_i3_addr() +{ + i3_addr *addr; + + /* TODO: just simply call alloc for now; + * preallocate a pool of buffers in the future */ + addr = (i3_addr *) malloc(sizeof(i3_addr)); + if (addr) { + return addr; + } + + I3_PRINT_INFO0( + I3_INFO_LEVEL_FATAL_ERROR, + "FATAL ERROR: memory allocation error in alloc_i3_addr\n" + ); + return NULL; +} + +/*************************************************************************** +* init_i3_addr_ipv4, init_i3_addr_ipv6, init_i3_addr_stack - +* initailize the fields of address data structure +* +* input: +* addr, port: IPv4/IPv6 address and port numbres +* - or - +* stack: pointer to stack (this data structure is not copied; don't +* free it after calling the function) +* +***************************************************************************/ +void init_i3_addr_ipv4(i3_addr *a, struct in_addr addr, uint16_t port) +{ + a->type = I3_ADDR_TYPE_IPv4; + a->t.v4.addr.s_addr = addr.s_addr; + a->t.v4.port = port; +} + +void init_i3_addr_ipv4_nat(i3_addr *a, + struct in_addr host_addr, uint16_t host_port, + struct in_addr nat_addr, uint16_t nat_port, + struct in_addr i3srv_addr, uint16_t i3srv_port) +{ + a->type = I3_ADDR_TYPE_IPv4_NAT; + a->t.v4_nat.host_addr.s_addr = host_addr.s_addr; + a->t.v4_nat.host_port = host_port; + a->t.v4_nat.nat_addr.s_addr = nat_addr.s_addr; + a->t.v4_nat.nat_port = nat_port; + a->t.v4_nat.i3srv_addr.s_addr = i3srv_addr.s_addr; + a->t.v4_nat.i3srv_port = i3srv_port; +} + +#ifndef __CYGWIN__ +void init_i3_addr_ipv6(i3_addr *a, struct in6_addr addr, uint16_t port) +{ + a->type = I3_ADDR_TYPE_IPv6; +#ifndef CCURED + memcpy((char *) &a->t.v6.addr.s6_addr, (char *) &addr.s6_addr, + sizeof(struct in6_addr)); +#else + a->t.v6.addr = addr; +#endif + a->t.v6.port = port; +} + +#endif +void init_i3_addr_stack(i3_addr *a, i3_stack *s) +{ + a->type = I3_ADDR_TYPE_STACK; + a->t.stack = s; +} + +/*************************************************************************** +* free_i3_trigger - free address data structure +* +* input: +* i3 address to be freed +* +***************************************************************************/ + +void free_i3_addr(i3_addr *addr) +{ + if (addr->type == I3_ADDR_TYPE_STACK) { + free_i3_stack(addr->t.stack); + } + free(addr); +} + +/*************************************************************************** +* duplicate_i3_addr - duplicate a given address +* +* input: +* a - address to be duplicated +* +* return: +* a's replica +***************************************************************************/ + +i3_addr *duplicate_i3_addr(i3_addr *a) +{ + i3_addr *anew; + + if (NULL == a) { + return NULL; + } else { + anew = alloc_i3_addr(); + } + + anew->type = a->type; + switch (a->type) { + case I3_ADDR_TYPE_IPv4: + anew->t.v4.addr.s_addr = a->t.v4.addr.s_addr; + anew->t.v4.port = a->t.v4.port; + break; + case I3_ADDR_TYPE_IPv4_NAT: + anew->t.v4_nat.host_addr.s_addr = a->t.v4_nat.host_addr.s_addr; + anew->t.v4_nat.host_port = a->t.v4_nat.host_port; + anew->t.v4_nat.nat_addr.s_addr = a->t.v4_nat.nat_addr.s_addr; + anew->t.v4_nat.nat_port = a->t.v4_nat.nat_port; + anew->t.v4_nat.i3srv_addr.s_addr = a->t.v4_nat.i3srv_addr.s_addr; + anew->t.v4_nat.i3srv_port = a->t.v4_nat.i3srv_port; + break; +#ifndef __CYGWIN__ + case I3_ADDR_TYPE_IPv6: +#ifndef CCURED + memcpy((char *) &anew->t.v6.addr.s6_addr, (char *) &a->t.v6.addr.s6_addr, + sizeof(struct in6_addr)); +#else + // Cleaner and faster + anew->t.v6.addr = a->t.v6.addr; +#endif + anew->t.v6.port = a->t.v6.port; + break; +#endif + case I3_ADDR_TYPE_STACK: + anew->t.stack = duplicate_i3_stack(a->t.stack); + break; + default: + I3_PRINT_DEBUG1(I3_DEBUG_LEVEL_MINIMAL, "duplicate_i3_id: invalid address type %d.\n", a->type); + } + + return anew; +} + +/*************************************************************************** +* pack_i3_addr - convert an i3 address data structure in packet format +* +* input: +* p - address of the buffer where the address is to be stored in +* packet format (pre-allocated) +* addr - trigger to be converted in packet format +* +* output: +* length - length of the address in packet format +* +***************************************************************************/ + +void pack_i3_addr(char *p, i3_addr *addr, unsigned short *length) +{ + unsigned short len = 0, l; + long long_temp; + short short_temp; + + p[0] = addr->type; + p++; + len++; + + switch (addr->type) { + case I3_ADDR_TYPE_STACK: + pack_i3_stack(p, addr->t.stack, &l); + len += l; + break; + + case I3_ADDR_TYPE_IPv4: + long_temp = htonl(addr->t.v4.addr.s_addr); + memcpy(p, (char *) &long_temp, sizeof(long)); + p += sizeof(long); + len += sizeof(long); + + short_temp = htons(addr->t.v4.port); + memcpy(p, &short_temp, sizeof(short)); + p += sizeof(short); + len += sizeof(short); + + break; + + case I3_ADDR_TYPE_IPv4_NAT: + long_temp = htonl(addr->t.v4_nat.host_addr.s_addr); + memcpy(p, (char *) &long_temp, sizeof(long)); + p += sizeof(long); + len += sizeof(long); + short_temp = htons(addr->t.v4_nat.host_port); + memcpy(p, &short_temp, sizeof(short)); + p += sizeof(short); + len += sizeof(short); + + long_temp = htonl(addr->t.v4_nat.nat_addr.s_addr); + memcpy(p, (char *) &long_temp, sizeof(long)); + p += sizeof(long); + len += sizeof(long); + short_temp = htons(addr->t.v4_nat.nat_port); + memcpy(p, &short_temp, sizeof(short)); + p += sizeof(short); + len += sizeof(short); + + long_temp = htonl(addr->t.v4_nat.i3srv_addr.s_addr); + memcpy(p, (char *) &long_temp, sizeof(long)); + p += sizeof(long); + len += sizeof(long); + short_temp = htons(addr->t.v4_nat.i3srv_port); + memcpy(p, &short_temp, sizeof(short)); + p += sizeof(short); + len += sizeof(short); + break; + +#ifndef _WIN32 + case I3_ADDR_TYPE_IPv6: +#ifndef CCURED + memcpy(p, (char *) &addr->t.v6.addr.s6_addr, sizeof(struct in6_addr)); +#else + *(struct in6_addr *) p = addr->t.v6.addr; +#endif + p += sizeof(struct in6_addr); + len += sizeof(struct in6_addr); + + short_temp = htons(addr->t.v6.port); + memcpy(p, &short_temp, sizeof(short)); + len += sizeof(short); + p += sizeof(short); + + break; +#endif + + default: + printf("pack_i3_addr: invalid address type %d\n", addr->type); + } + + *length = len; +} + +unsigned short get_i3_addr_len(i3_addr *addr) +{ + unsigned short length; + + length = sizeof(char); /* type */ + + switch (addr->type) { + case I3_ADDR_TYPE_STACK: + length += get_i3_stack_len(addr->t.stack); + break; + case I3_ADDR_TYPE_IPv4: + length += sizeof(long) + sizeof(short); + break; + case I3_ADDR_TYPE_IPv4_NAT: + length += 3 * (sizeof(long) + sizeof(short)); + break; +#ifndef __CYGWIN__ + case I3_ADDR_TYPE_IPv6: + length += sizeof(struct in6_addr) + sizeof(short); + break; +#endif + default: + I3_PRINT_DEBUG1(I3_DEBUG_LEVEL_MINIMAL, "pack_i3_addr: invalid address type %d\n", addr->type); + } + + return length; +} + +/*************************************************************************** +* unpack_i3_addr - copy address info from packet to a trigger +* data structure +* +* input: +* p - address where address is stored in packet format +* +* return: +* address data structure initialized with the info from buffer "p" +* +* output: +* length - length of the address info in packet format +* +***************************************************************************/ + +i3_addr *unpack_i3_addr(char *p, unsigned short *length) +{ + unsigned short len; + i3_addr *addr = alloc_i3_addr(); + + addr->type = p[0]; + p++; + *length = 1; + + switch (addr->type) { + case I3_ADDR_TYPE_STACK: + addr->t.stack = unpack_i3_stack(p, &len); + *length += len; + break; + + case I3_ADDR_TYPE_IPv4: + addr->t.v4.addr.s_addr = ntohl(*((long *) p)); + p += sizeof(long); + *length += sizeof(long); + + addr->t.v4.port = ntohs(*((short *) p)); + *length += sizeof(short); + p += sizeof(short); + + break; + + case I3_ADDR_TYPE_IPv4_NAT: + addr->t.v4_nat.host_addr.s_addr = ntohl(*((long *) p)); + p += sizeof(long); + *length += sizeof(long); + addr->t.v4_nat.host_port = ntohs(*((short *) p)); + *length += sizeof(short); + p += sizeof(short); + + addr->t.v4_nat.nat_addr.s_addr = ntohl(*((long *) p)); + p += sizeof(long); + *length += sizeof(long); + addr->t.v4_nat.nat_port = ntohs(*((short *) p)); + *length += sizeof(short); + p += sizeof(short); + + addr->t.v4_nat.i3srv_addr.s_addr = ntohl(*((long *) p)); + p += sizeof(long); + *length += sizeof(long); + addr->t.v4_nat.i3srv_port = ntohs(*((short *) p)); + *length += sizeof(short); + p += sizeof(short); + break; + +#ifndef __CYGWIN__ + case I3_ADDR_TYPE_IPv6: +#ifndef CCURED + memcpy((char *) &addr->t.v6.addr.s6_addr, p, sizeof(struct in6_addr)); +#else + addr->t.v6.addr = *(struct in6_addr *) p; +#endif + + p += sizeof(struct in6_addr); + *length += sizeof(struct in6_addr); + + addr->t.v6.port = ntohs(*((short *) p)); + *length += sizeof(short); + p += sizeof(short); + + break; +#endif + + default: + I3_PRINT_DEBUG1(I3_DEBUG_LEVEL_MINIMAL, "unpack_i3_addr: invalid address type %d\n", addr->type); + } + return addr; +} + +/*************************************************************************** +* check_i3_addr - check address whether is well-formed +* +* input: +* p - address where i3_addr is stored in packet format +* +* return: +* error code; FALSE if no error +* +* output: +* length - length of the address info in packet format +* +***************************************************************************/ + +int check_i3_addr(char *p, unsigned short *length, char *type) +{ + *type = p[0]; + + p++; /* skip address type field */ + + switch (*type) { + case I3_ADDR_TYPE_STACK: + check_i3_stack(p, length); + break; + case I3_ADDR_TYPE_IPv4: + *length = sizeof(long) /*IP address*/ + sizeof(short) /*port*/; + break; + case I3_ADDR_TYPE_IPv4_NAT: + *length = 3 * (sizeof(long) /*IP address*/ + sizeof(short) /*port*/); + break; +#ifndef __CYGWIN__ + case I3_ADDR_TYPE_IPv6: + *length = sizeof(struct in6_addr) /*IP address*/ + sizeof(short) /*port*/; + break; +#endif + default: + return I3_ERR_INVALID_ADDR; + } + + *length += 1; /* account for address type */ + + return FALSE; +} + +/** + * This function understands natted addresses. + * If an address is natted, the nat_address and nat_port number + * are used in the comparison. + * @author Dilip + */ +int addr_nat_equal(i3_addr *a1, i3_addr *a2) +{ + struct in_addr cmp_addr_A, cmp_addr_B; + int cmp_port_A = 0, cmp_port_B = 0; + + memset(&cmp_addr_A, 0, sizeof(struct in_addr)); + memset(&cmp_addr_B, 0, sizeof(struct in_addr)); + + if (a1->type == I3_ADDR_TYPE_IPv4) { + memcpy(&cmp_addr_A, &a1->t.v4.addr, sizeof(struct in_addr)); + cmp_port_A = a1->t.v4.port; + } else if (a1->type == I3_ADDR_TYPE_IPv4_NAT) { + memcpy(&cmp_addr_A, &a1->t.v4_nat.host_addr, sizeof(struct in_addr)); + cmp_port_A = a1->t.v4_nat.host_port; + } + + if (a2->type == I3_ADDR_TYPE_IPv4) { + memcpy(&cmp_addr_B, &a2->t.v4.addr, sizeof(struct in_addr)); + cmp_port_B = a2->t.v4.port; + } else if (a2->type == I3_ADDR_TYPE_IPv4_NAT) { + memcpy(&cmp_addr_B, &a2->t.v4_nat.host_addr, sizeof(struct in_addr)); + cmp_port_B = a2->t.v4_nat.host_port; + } + + if (cmp_addr_A.s_addr != cmp_addr_B.s_addr || cmp_port_A != cmp_port_B) { + return FALSE; + } else { + return TRUE; + } +} + +/*************************************************************************** +* addr_equal - compare two addresses +* +* input: +* t1, t2 - addresses to be compared +* +* return: +* TRUE, if the addresses are identical; FALSE, otherwise +* +***************************************************************************/ + +int addr_equal(i3_addr *a1, i3_addr *a2) +{ +#ifndef __CYGWIN__ + uint i; +#endif + + if (a1->type != a2->type) { + return FALSE; + } + + switch (a1->type) { + case I3_ADDR_TYPE_IPv4: + if ((a1->t.v4.addr.s_addr != a2->t.v4.addr.s_addr) || + (a1->t.v4.port != a2->t.v4.port)) { + return FALSE; + } + break; + case I3_ADDR_TYPE_IPv4_NAT: + if ((a1->t.v4_nat.host_addr.s_addr != a2->t.v4_nat.host_addr.s_addr) || + (a1->t.v4_nat.host_port != a2->t.v4_nat.host_port) || + (a1->t.v4_nat.nat_addr.s_addr != a2->t.v4_nat.nat_addr.s_addr) || + (a1->t.v4_nat.nat_port != a2->t.v4_nat.nat_port) || + (a1->t.v4_nat.i3srv_addr.s_addr != a2->t.v4_nat.i3srv_addr.s_addr) || + (a1->t.v4_nat.i3srv_port != a2->t.v4_nat.i3srv_port)) { + return FALSE; + } + break; +#ifndef __CYGWIN__ + case I3_ADDR_TYPE_IPv6: + for (i = 0; i < sizeof(struct in6_addr); i++) { + if (a1->t.v6.addr.s6_addr[i] != a2->t.v6.addr.s6_addr[i]) { + return FALSE; + } + } + if (a1->t.v6.port == a2->t.v6.port) { + return FALSE; + } + break; +#endif + case I3_ADDR_TYPE_STACK: + if (a1->t.stack->len != a2->t.stack->len) { + return FALSE; + } + if (memcmp((char *) a1->t.stack->ids, (char *) a2->t.stack->ids, + a1->t.stack->len * sizeof(ID))) { + return FALSE; + } + } + return TRUE; +} + +/*************************************************************************** +* sizeof_addr - return the length of the address data structure +* +* input: +* a - given address +* +* return: +* length in bytes of the address +* +***************************************************************************/ + +int sizeof_addr(i3_addr *a) +{ + switch (a->type) { + case I3_ADDR_TYPE_IPv4: + return sizeof(struct in_addr) + sizeof(uint16_t) + sizeof(a->type) + + KEY_LEN; + case I3_ADDR_TYPE_IPv4_NAT: + return 3 * (sizeof(struct in_addr) + sizeof(uint16_t)) + sizeof(a->type) + + KEY_LEN; +#ifndef __CYGWIN__ + case I3_ADDR_TYPE_IPv6: + return sizeof(struct in6_addr) + sizeof(uint16_t) + sizeof(a->type) + + KEY_LEN; +#endif + case I3_ADDR_TYPE_STACK: + return a->t.stack->len * sizeof(ID) + sizeof(a->type); + } + I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, "addr_len: Invalid trigger type"); + return -1; +} + +/*************************************************************************** + * printf_id - print i3-id with an indentation of "indent" + **************************************************************************/ + +void printf_id(ID *id, int indent) +{ + uint i; + char buf[INDENT_BUF_LEN]; + + memset(buf, ' ', indent); + buf[indent] = 0; + + printf("%s i3-id = ", buf); + for (i = 0; i < sizeof(ID); i++) { + printf("%02x", id->x[i]); + } + printf("\n"); +} + +/*************************************************************************** + * printf_i3_addr - print i3-addr with an indentation of "indent" + **************************************************************************/ + +void printf_i3_addr(i3_addr *addr, int indent) +{ +#ifndef __CYGWIN__ + uint i; +#endif + char buf[INDENT_BUF_LEN]; + struct in_addr ia; + + memset(buf, ' ', indent); + buf[indent] = 0; + + printf("%s addr type = %d\n", buf, addr->type); + + switch (addr->type) { + case I3_ADDR_TYPE_STACK: + printf_i3_stack(addr->t.stack, indent); + break; + case I3_ADDR_TYPE_IPv4: + ia.s_addr = htonl(addr->t.v4.addr.s_addr); + printf("%s IPv4 (address, port) = (%s, %d)", + buf, inet_ntoa(ia), addr->t.v4.port); + break; + case I3_ADDR_TYPE_IPv4_NAT: + ia.s_addr = htonl(addr->t.v4_nat.host_addr.s_addr); + printf("%s NAT_IPv4 (host_addr, host_port) = (%s, %d)\n", + buf, inet_ntoa(ia), addr->t.v4_nat.host_port); + ia.s_addr = htonl(addr->t.v4_nat.nat_addr.s_addr); + printf("%s (nat_addr, nat_port) = (%s, %d)\n", + buf, inet_ntoa(ia), addr->t.v4_nat.nat_port); + ia.s_addr = htonl(addr->t.v4_nat.i3srv_addr.s_addr); + printf("%s (i3srv_addr, i3srv_port) = (%s, %d)\n", + buf, inet_ntoa(ia), addr->t.v4_nat.i3srv_port); + break; +#ifndef __CYGWIN__ + case I3_ADDR_TYPE_IPv6: + printf("%s IPv6 (address, port) = (", buf); + for (i = 0; i < sizeof(struct in6_addr); i++) { + printf("%d.", addr->t.v6.addr.s6_addr[i]); + } + printf(", %d)", addr->t.v6.port); + break; +#endif + default: + printf("Unknown addr type\n"); + } + printf("\n"); +} + +/*************************************************************************** + * compute_nonce - compute the nonce for challenging trigger insertion + **************************************************************************/ + +void compute_nonce(char *nonce, i3_addr *a) +{ + memset(nonce, 0, NONCE_LEN); + + switch (a->type) { + case I3_ADDR_TYPE_IPv4: +#ifndef CCURED + memcpy(nonce, (char *) &a->t.v4.addr.s_addr, sizeof(struct in_addr)); +#else + *(struct in_addr *) nonce = a->t.v4.addr; +#endif +#ifndef CCURED + memcpy(nonce + sizeof(struct in_addr), + (char *) &a->t.v4.port, sizeof(a->t.v4.port)); +#else + *(uint16_t *) (nonce + sizeof(struct in_addr)) = a->t.v4.port; +#endif + break; + case I3_ADDR_TYPE_IPv4_NAT: + /* the 2nd address in the two-hop route represents the + * the Internet-routable address of the destination + */ + memcpy(nonce, (char *) &a->t.v4_nat.nat_addr.s_addr, + sizeof(struct in_addr)); + memcpy(nonce + sizeof(struct in_addr), + (char *) &a->t.v4_nat.host_port, sizeof(a->t.v4_nat.nat_port)); + break; +#ifndef __CYGWIN__ + case I3_ADDR_TYPE_IPv6: +#ifndef CCURED + memcpy(nonce, (char *) &a->t.v6.addr.s6_addr, + MIN(sizeof(struct in6_addr), NONCE_LEN)); +#else + { + struct in6_addr tmp = a->t.v6.addr; + memcpy(nonce, (char *) &tmp, MIN(sizeof(struct in6_addr), NONCE_LEN)); + } +#endif + break; +#endif + case I3_ADDR_TYPE_STACK: + memcpy(nonce, a->t.stack->ids, NONCE_LEN); + break; + default: + I3_PRINT_DEBUG1(I3_DEBUG_LEVEL_MINIMAL, "compute_nonce: invalid address type %d\n", a->type); + printf_i3_addr(a, 2); + } +} === modified file 'i3/i3/i3_addr.h' --- i3/i3/i3_addr.h 2010-01-06 22:17:32 +0000 +++ i3/i3/i3_addr.h 2010-02-11 11:49:47 +0000 @@ -1,38 +1,37 @@ -/*************************************************************************** - i3_addr.h - description - ------------------- - begin : Fre Jun 20 2003 - copyright : (C) 2003 by klaus - email : wehrle@xxxxxxxxxxxxxxxxx - ***************************************************************************/ - -#ifndef I3_ADDR_H -#define I3_ADDR_H - -/* functions implemented in i3_addr.c */ -i3_addr *alloc_i3_addr(void); - -void init_i3_addr_ipv4(i3_addr *a, struct in_addr addr, uint16_t port); -void init_i3_addr_ipv4_nat(i3_addr *a, - struct in_addr host_addr, uint16_t host_port, - struct in_addr nat_addr, uint16_t nat_port, - struct in_addr i3srv_addr, uint16_t i3srv_port); -#ifndef __CYGWIN__ -void init_i3_addr_ipv6(i3_addr *a, struct in6_addr addr, uint16_t port); -#endif -void init_i3_addr_stack(i3_addr *a, i3_stack *s); -i3_addr *duplicate_i3_addr(i3_addr *a); -void free_i3_addr(i3_addr *addr); -void pack_i3_addr(char *p, i3_addr *addr, unsigned short *length); -unsigned short get_i3_addr_len(i3_addr *addr); -i3_addr *unpack_i3_addr(char *p, unsigned short *length); -int check_i3_addr(char *p, unsigned short *length, char *type); -int addr_equal(i3_addr *a1, i3_addr *a2); -int addr_nat_equal(i3_addr *a1, i3_addr *a2); -int sizeof_addr(i3_addr *a); -void printf_i3_addr(i3_addr *addr, int intend); -void printf_id(ID *id, int indent); -void compute_nonce(char *nonce, i3_addr *a); - -#endif - +/*************************************************************************** +* i3_addr.h - description +* ------------------- +* begin : Fre Jun 20 2003 +* copyright : (C) 2003 by klaus +* email : wehrle@xxxxxxxxxxxxxxxxx +***************************************************************************/ + +#ifndef I3_ADDR_H +#define I3_ADDR_H + +/* functions implemented in i3_addr.c */ +i3_addr *alloc_i3_addr(void); + +void init_i3_addr_ipv4(i3_addr *a, struct in_addr addr, uint16_t port); +void init_i3_addr_ipv4_nat(i3_addr *a, + struct in_addr host_addr, uint16_t host_port, + struct in_addr nat_addr, uint16_t nat_port, + struct in_addr i3srv_addr, uint16_t i3srv_port); +#ifndef __CYGWIN__ +void init_i3_addr_ipv6(i3_addr *a, struct in6_addr addr, uint16_t port); +#endif +void init_i3_addr_stack(i3_addr *a, i3_stack *s); +i3_addr *duplicate_i3_addr(i3_addr *a); +void free_i3_addr(i3_addr *addr); +void pack_i3_addr(char *p, i3_addr *addr, unsigned short *length); +unsigned short get_i3_addr_len(i3_addr *addr); +i3_addr *unpack_i3_addr(char *p, unsigned short *length); +int check_i3_addr(char *p, unsigned short *length, char *type); +int addr_equal(i3_addr *a1, i3_addr *a2); +int addr_nat_equal(i3_addr *a1, i3_addr *a2); +int sizeof_addr(i3_addr *a); +void printf_i3_addr(i3_addr *addr, int intend); +void printf_id(ID *id, int indent); +void compute_nonce(char *nonce, i3_addr *a); + +#endif === modified file 'i3/i3/i3_api.c' --- i3/i3/i3_api.c 2009-12-11 22:49:11 +0000 +++ i3/i3/i3_api.c 2010-02-11 11:49:47 +0000 @@ -1,53 +1,52 @@ -/** @file - * - * @note: HIPU: libinet6 requires LD_PRELOAD which is "dylib" on BSD. - */ - -#include <stdio.h> -#include <stdarg.h> -#include <string.h> -#include <sys/types.h> /* basic system data types */ - -#include <errno.h> -#include "../utils/netwrap.h" - -#include "i3.h" -#include "i3_fun.h" -#include "i3_debug.h" - -int id_local(char *id) -{ - // to be changed when more than one server - return TRUE; -} - -void send_packet_ipv4(char *pkt, int len, struct in_addr *dst_addr, - uint16_t dst_port, nw_skt_t dst_fd) -{ - struct sockaddr_in dstaddr; - - memset(&dstaddr, 0, sizeof(dstaddr)); - dstaddr.sin_family = AF_INET; - dstaddr.sin_addr.s_addr = htonl(dst_addr->s_addr); - dstaddr.sin_port = htons(dst_port); - - if (sendto(dst_fd, pkt, len, 0, - (struct sockaddr *)&dstaddr, sizeof(dstaddr)) < 0) - I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, "send_ipv4: sendto error\n"); -} - -#ifndef __CYGWIN__ -void send_packet_ipv6(char *p, int len, - struct in6_addr *ip6_addr, uint16_t port, nw_skt_t rfd) -{ - I3_PRINT_INFO0(I3_INFO_LEVEL_WARNING, "send_packet_ipv6: not implemented yet!\n"); -} -#endif - -void send_packet_i3(char *p, int len) -{ - I3_PRINT_INFO0(I3_INFO_LEVEL_WARNING, "send_i3: not implemented yet!\n"); -} - - - +/** @file + * + * @note: HIPU: libinet6 requires LD_PRELOAD which is "dylib" on BSD. + */ + +#include <stdio.h> +#include <stdarg.h> +#include <string.h> +#include <sys/types.h> /* basic system data types */ + +#include <errno.h> +#include "../utils/netwrap.h" + +#include "i3.h" +#include "i3_fun.h" +#include "i3_debug.h" + +int id_local(char *id) +{ + // to be changed when more than one server + return TRUE; +} + +void send_packet_ipv4(char *pkt, int len, struct in_addr *dst_addr, + uint16_t dst_port, nw_skt_t dst_fd) +{ + struct sockaddr_in dstaddr; + + memset(&dstaddr, 0, sizeof(dstaddr)); + dstaddr.sin_family = AF_INET; + dstaddr.sin_addr.s_addr = htonl(dst_addr->s_addr); + dstaddr.sin_port = htons(dst_port); + + if (sendto(dst_fd, pkt, len, 0, + (struct sockaddr *) &dstaddr, sizeof(dstaddr)) < 0) { + I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, "send_ipv4: sendto error\n"); + } +} + +#ifndef __CYGWIN__ +void send_packet_ipv6(char *p, int len, + struct in6_addr *ip6_addr, uint16_t port, nw_skt_t rfd) +{ + I3_PRINT_INFO0(I3_INFO_LEVEL_WARNING, "send_packet_ipv6: not implemented yet!\n"); +} + +#endif + +void send_packet_i3(char *p, int len) +{ + I3_PRINT_INFO0(I3_INFO_LEVEL_WARNING, "send_i3: not implemented yet!\n"); +} === modified file 'i3/i3/i3_api.h' --- i3/i3/i3_api.h 2009-12-11 22:49:11 +0000 +++ i3/i3/i3_api.h 2010-02-11 11:49:47 +0000 @@ -1,18 +1,18 @@ -/*************************************************************************** - * i3_addr.h - description - **************************************************************************/ - -#ifndef I3_API_H -#define I3_API_H -#include "../utils/netwrap.h" - -int id_local(char *id); -void send_packet_ipv4(char *pkt, int len, struct in_addr *dst_addr, - uint16_t dst_port, nw_skt_t dst_fd); -#ifndef __CYGWIN__ -void send_packet_ipv6(char *p, int len, - struct in6_addr *ip6_addr, uint16_t port, nw_skt_t rfd); -#endif -void send_packet_i3(char *p, int len); - -#endif //I3_API_H +/*************************************************************************** + * i3_addr.h - description + **************************************************************************/ + +#ifndef I3_API_H +#define I3_API_H +#include "../utils/netwrap.h" + +int id_local(char *id); +void send_packet_ipv4(char *pkt, int len, struct in_addr *dst_addr, + uint16_t dst_port, nw_skt_t dst_fd); +#ifndef __CYGWIN__ +void send_packet_ipv6(char *p, int len, + struct in6_addr *ip6_addr, uint16_t port, nw_skt_t rfd); +#endif +void send_packet_i3(char *p, int len); + +#endif //I3_API_H === modified file 'i3/i3/i3_config.c' --- i3/i3/i3_config.c 2010-01-06 22:17:32 +0000 +++ i3/i3/i3_config.c 2010-02-11 11:49:47 +0000 @@ -1,300 +1,291 @@ -#include <stdio.h> -#include <string.h> -#include <stdlib.h> -#include <libxml2/libxml/xmlmemory.h> -#include <libxml2/libxml/parser.h> -#include <libxml2/libxml/tree.h> -#include <libxml2/libxml/xpath.h> -#include <ctype.h> -#include "i3_debug.h" -#include "i3_config.h" - -static xmlDocPtr i3_config_doc; -char cfilename[200]=""; - -void read_parameters(const char* filename) -{ - char version[200]; - xmlNodePtr root; - strcpy(cfilename,filename); - - i3_config_doc = xmlParseFile(filename); - - if (i3_config_doc == NULL ) - { - I3_PRINT_INFO1( - I3_INFO_LEVEL_FATAL_ERROR, - "%s: XML configuration in not parsed successfully" - "check whether all tags are terminated etc). \n", - filename - ); - exit(-1); - } - - root = xmlDocGetRootElement(i3_config_doc); - - if (root == NULL) - { - I3_PRINT_INFO1( - I3_INFO_LEVEL_FATAL_ERROR, - "%s: Empty XML configuration file\n", - filename - ); - exit(-1); - } - - if (xmlStrcmp(root->name, (const xmlChar *) "I3ConfigFile")) { - I3_PRINT_INFO1( - I3_INFO_LEVEL_FATAL_ERROR, - "%s: Document of the wrong type, root node != I3ConfigFile\n", - filename - ); - exit(-1); - } - - read_string_attribute("//I3ConfigFile", "version",version,1); - - if ( strcmp(version,VER_CONFIG)) - { - I3_PRINT_INFO3( - I3_INFO_LEVEL_FATAL_ERROR, - "%s: Incorrect version of configuration file. " - "This code uses version %s configuration file, your configuration " - "file has version %s, please update.\n", - filename,VER_CONFIG,version - ); - exit(-1); - } - -} - -void release_params() -{ - xmlFreeDoc(i3_config_doc); - //xmlCleanupParser(); -} - -xmlXPathObjectPtr getnodeset(xmlChar *xpath) -{ - xmlXPathContextPtr context; - xmlXPathObjectPtr result; - - context = xmlXPathNewContext(i3_config_doc); - result = xmlXPathEvalExpression(xpath, context); - - if(xmlXPathNodeSetIsEmpty(result->nodesetval)) { - xmlXPathFreeObject(result); - xmlXPathFreeContext(context); - return NULL; - } - - xmlXPathFreeContext(context); - return result; -} - -void strip_ws(char* str) -{ - char tstr[200]; - int lindex = 0; - int rindex = 0; - - while ( str[lindex] != 0 && isspace(str[lindex])) - lindex++; - - rindex = ((int) strlen(str)) -1; - while ( rindex >= 0 && isspace(str[rindex]) ) - rindex--; - - if ( lindex == strlen(str)) - { - strcpy(str,""); - return; - } - - str[rindex+1] = 0; - strcpy(tstr,str+lindex); - strcpy(str,tstr); -} - - -void read_string_attribute(char* elementPath, char *attribName, char* str, int required) -{ - xmlChar *xpath; - xmlXPathObjectPtr result; - xmlNodeSetPtr nodeset; - xmlChar* resultstr; - char tmpBuf[1000]; - sprintf(tmpBuf, "%s[@%s]", elementPath, attribName); - - xpath = xmlCharStrdup(tmpBuf); - result = getnodeset(xpath); - xmlFree(xpath); - - required=1; - - if ( required && result == NULL ) - { - printf("%s: %s required in configuration file\n",cfilename, elementPath); - exit(-1); - } - - if ( result == NULL ) - return; - nodeset = result->nodesetval; - - if ( nodeset->nodeNr >= 2 ) - { - I3_PRINT_INFO2( - I3_INFO_LEVEL_FATAL_ERROR, - "%s: %s should appear atmost once in configuration file\n", - cfilename, elementPath - ); - exit(-1); - } - - resultstr = xmlGetProp(nodeset->nodeTab[0], (xmlChar*)attribName); - strcpy(str,(char*)resultstr); - strip_ws(str); - xmlFree(resultstr); - xmlXPathFreeObject(result); -} - -void read_string_par(char* path,char* str,int required) -{ - xmlNodeSetPtr nodeset; - xmlChar* resultstr; - xmlChar *xpath = xmlCharStrdup(path); - xmlXPathObjectPtr result = getnodeset(xpath); - xmlFree(xpath); - - required=1; - - if ( required && result == NULL ) - { - printf("%s: %s required in configuration file\n",cfilename,path); - exit(-1); - } - - if ( result == NULL ) - return; - - nodeset = result->nodesetval; - - if ( nodeset->nodeNr >= 2 ) - { - I3_PRINT_INFO2( - I3_INFO_LEVEL_FATAL_ERROR, - "%s: %s should appear atmost once in configuration file\n", - cfilename,path - ); - exit(-1); - } - - resultstr = xmlNodeListGetString(i3_config_doc, nodeset->nodeTab[0]->xmlChildrenNode, 1); - strcpy(str,(char*)resultstr); - strip_ws(str); - xmlFree(resultstr); - xmlXPathFreeObject(result); -} - -void read_ushort_attribute(char* elementPath, char *attribName,unsigned short* us,int required) -{ - char str[200]; - read_string_attribute(elementPath, attribName, str,required); - *us = (unsigned short) atoi(str); -} - -void read_ushort_par(char* path,unsigned short* us,int required) -{ - char str[200]; - read_string_par(path,str,required); - *us = (unsigned short) atoi(str); -} - -char **read_i3server_list(int* num) -{ - xmlNodeSetPtr nodeset; - char** toret; - int i; - xmlChar *xpath = xmlCharStrdup("//I3Server"); - xmlXPathObjectPtr result = getnodeset(xpath); - xmlFree(xpath); - - if ( result == NULL ) - { - *num=0; - return NULL; - } - - nodeset = result->nodesetval; - toret = (char**) malloc(nodeset->nodeNr * sizeof(char*)); - *num=nodeset->nodeNr; - - for(i=0;i<nodeset->nodeNr;i++) - { - xmlChar* ipStr = xmlGetProp(nodeset->nodeTab[i], (xmlChar*) "IPAddress"); - xmlChar* portStr = xmlGetProp(nodeset->nodeTab[i], (xmlChar*) "PortNum"); - xmlChar* i3IdStr = xmlGetProp(nodeset->nodeTab[i], (xmlChar*) "I3Id"); - - toret[i] = (char *) malloc(1000); /* TODO */ - sprintf(toret[i], "%s %s %s\n", (char *) ipStr, (char *) portStr, (char *) i3IdStr); - - strip_ws(toret[i]); - xmlFree(ipStr); - xmlFree(portStr); - xmlFree(i3IdStr); - } - - xmlXPathFreeObject (result); - return toret; -} - -char **read_strings_par(char* path,int* num) -{ - xmlNodeSetPtr nodeset; - char** toret; - int i; - xmlChar *xpath = xmlCharStrdup(path); - xmlXPathObjectPtr result = getnodeset(xpath); - xmlFree(xpath); - - if ( result == NULL ) - { - *num=0; - return NULL; - } - - nodeset = result->nodesetval; - toret = (char**) malloc(nodeset->nodeNr * sizeof(char*)); - *num=nodeset->nodeNr; - - for(i=0;i<nodeset->nodeNr;i++) - { - xmlChar* resultstr = xmlNodeListGetString(i3_config_doc, nodeset->nodeTab[i]->xmlChildrenNode, 1); - toret[i] = strdup((char*)resultstr); - strip_ws(toret[i]); - xmlFree(resultstr); - } - - xmlXPathFreeObject (result); - return toret; -} - -int test_main(void) -{ - char fake[200]; - char** fakes; - int num; - int i; - - read_parameters("i3-proxy.xml"); - read_string_par("/parameters/proxy/server_proxy_trigger/server_proxy[@name='sp1']",fake,1); - printf("%s\n",fake); - - fakes = read_strings_par("/parameters/proxy/public_triggers/trigger",&num); - printf("Num: %d\n",num); - for(i=0;i<num;i++) - printf("%s\n",fakes[i]); - - return 0; -} +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <libxml2/libxml/xmlmemory.h> +#include <libxml2/libxml/parser.h> +#include <libxml2/libxml/tree.h> +#include <libxml2/libxml/xpath.h> +#include <ctype.h> +#include "i3_debug.h" +#include "i3_config.h" + +static xmlDocPtr i3_config_doc; +char cfilename[200] = ""; + +void read_parameters(const char *filename) +{ + char version[200]; + xmlNodePtr root; + strcpy(cfilename, filename); + + i3_config_doc = xmlParseFile(filename); + + if (i3_config_doc == NULL) { + I3_PRINT_INFO1( + I3_INFO_LEVEL_FATAL_ERROR, + "%s: XML configuration in not parsed successfully" + "check whether all tags are terminated etc). \n", + filename + ); + exit(-1); + } + + root = xmlDocGetRootElement(i3_config_doc); + + if (root == NULL) { + I3_PRINT_INFO1( + I3_INFO_LEVEL_FATAL_ERROR, + "%s: Empty XML configuration file\n", + filename + ); + exit(-1); + } + + if (xmlStrcmp(root->name, (const xmlChar *) "I3ConfigFile")) { + I3_PRINT_INFO1( + I3_INFO_LEVEL_FATAL_ERROR, + "%s: Document of the wrong type, root node != I3ConfigFile\n", + filename + ); + exit(-1); + } + + read_string_attribute("//I3ConfigFile", "version", version, 1); + + if (strcmp(version, VER_CONFIG)) { + I3_PRINT_INFO3( + I3_INFO_LEVEL_FATAL_ERROR, + "%s: Incorrect version of configuration file. " + "This code uses version %s configuration file, your configuration " + "file has version %s, please update.\n", + filename, VER_CONFIG, version + ); + exit(-1); + } +} + +void release_params() +{ + xmlFreeDoc(i3_config_doc); + //xmlCleanupParser(); +} + +xmlXPathObjectPtr getnodeset(xmlChar *xpath) +{ + xmlXPathContextPtr context; + xmlXPathObjectPtr result; + + context = xmlXPathNewContext(i3_config_doc); + result = xmlXPathEvalExpression(xpath, context); + + if (xmlXPathNodeSetIsEmpty(result->nodesetval)) { + xmlXPathFreeObject(result); + xmlXPathFreeContext(context); + return NULL; + } + + xmlXPathFreeContext(context); + return result; +} + +void strip_ws(char *str) +{ + char tstr[200]; + int lindex = 0; + int rindex = 0; + + while (str[lindex] != 0 && isspace(str[lindex])) { + lindex++; + } + + rindex = ((int) strlen(str)) - 1; + while (rindex >= 0 && isspace(str[rindex])) { + rindex--; + } + + if (lindex == strlen(str)) { + strcpy(str, ""); + return; + } + + str[rindex + 1] = 0; + strcpy(tstr, str + lindex); + strcpy(str, tstr); +} + +void read_string_attribute(char *elementPath, char *attribName, char *str, int required) +{ + xmlChar *xpath; + xmlXPathObjectPtr result; + xmlNodeSetPtr nodeset; + xmlChar *resultstr; + char tmpBuf[1000]; + sprintf(tmpBuf, "%s[@%s]", elementPath, attribName); + + xpath = xmlCharStrdup(tmpBuf); + result = getnodeset(xpath); + xmlFree(xpath); + + required = 1; + + if (required && result == NULL) { + printf("%s: %s required in configuration file\n", cfilename, elementPath); + exit(-1); + } + + if (result == NULL) { + return; + } + nodeset = result->nodesetval; + + if (nodeset->nodeNr >= 2) { + I3_PRINT_INFO2( + I3_INFO_LEVEL_FATAL_ERROR, + "%s: %s should appear atmost once in configuration file\n", + cfilename, elementPath + ); + exit(-1); + } + + resultstr = xmlGetProp(nodeset->nodeTab[0], (xmlChar *) attribName); + strcpy(str, (char *) resultstr); + strip_ws(str); + xmlFree(resultstr); + xmlXPathFreeObject(result); +} + +void read_string_par(char *path, char *str, int required) +{ + xmlNodeSetPtr nodeset; + xmlChar *resultstr; + xmlChar *xpath = xmlCharStrdup(path); + xmlXPathObjectPtr result = getnodeset(xpath); + xmlFree(xpath); + + required = 1; + + if (required && result == NULL) { + printf("%s: %s required in configuration file\n", cfilename, path); + exit(-1); + } + + if (result == NULL) { + return; + } + + nodeset = result->nodesetval; + + if (nodeset->nodeNr >= 2) { + I3_PRINT_INFO2( + I3_INFO_LEVEL_FATAL_ERROR, + "%s: %s should appear atmost once in configuration file\n", + cfilename, path + ); + exit(-1); + } + + resultstr = xmlNodeListGetString(i3_config_doc, nodeset->nodeTab[0]->xmlChildrenNode, 1); + strcpy(str, (char *) resultstr); + strip_ws(str); + xmlFree(resultstr); + xmlXPathFreeObject(result); +} + +void read_ushort_attribute(char *elementPath, char *attribName, unsigned short *us, int required) +{ + char str[200]; + read_string_attribute(elementPath, attribName, str, required); + *us = (unsigned short) atoi(str); +} + +void read_ushort_par(char *path, unsigned short *us, int required) +{ + char str[200]; + read_string_par(path, str, required); + *us = (unsigned short) atoi(str); +} + +char **read_i3server_list(int *num) +{ + xmlNodeSetPtr nodeset; + char **toret; + int i; + xmlChar *xpath = xmlCharStrdup("//I3Server"); + xmlXPathObjectPtr result = getnodeset(xpath); + xmlFree(xpath); + + if (result == NULL) { + *num = 0; + return NULL; + } + + nodeset = result->nodesetval; + toret = (char **) malloc(nodeset->nodeNr * sizeof(char *)); + *num = nodeset->nodeNr; + + for (i = 0; i < nodeset->nodeNr; i++) { + xmlChar *ipStr = xmlGetProp(nodeset->nodeTab[i], (xmlChar *) "IPAddress"); + xmlChar *portStr = xmlGetProp(nodeset->nodeTab[i], (xmlChar *) "PortNum"); + xmlChar *i3IdStr = xmlGetProp(nodeset->nodeTab[i], (xmlChar *) "I3Id"); + + toret[i] = (char *) malloc(1000); /* TODO */ + sprintf(toret[i], "%s %s %s\n", (char *) ipStr, (char *) portStr, (char *) i3IdStr); + + strip_ws(toret[i]); + xmlFree(ipStr); + xmlFree(portStr); + xmlFree(i3IdStr); + } + + xmlXPathFreeObject(result); + return toret; +} + +char **read_strings_par(char *path, int *num) +{ + xmlNodeSetPtr nodeset; + char **toret; + int i; + xmlChar *xpath = xmlCharStrdup(path); + xmlXPathObjectPtr result = getnodeset(xpath); + xmlFree(xpath); + + if (result == NULL) { + *num = 0; + return NULL; + } + + nodeset = result->nodesetval; + toret = (char **) malloc(nodeset->nodeNr * sizeof(char *)); + *num = nodeset->nodeNr; + + for (i = 0; i < nodeset->nodeNr; i++) { + xmlChar *resultstr = xmlNodeListGetString(i3_config_doc, nodeset->nodeTab[i]->xmlChildrenNode, 1); + toret[i] = strdup((char *) resultstr); + strip_ws(toret[i]); + xmlFree(resultstr); + } + + xmlXPathFreeObject(result); + return toret; +} + +int test_main(void) +{ + char fake[200]; + char **fakes; + int num; + int i; + + read_parameters("i3-proxy.xml"); + read_string_par("/parameters/proxy/server_proxy_trigger/server_proxy[@name='sp1']", fake, 1); + printf("%s\n", fake); + + fakes = read_strings_par("/parameters/proxy/public_triggers/trigger", &num); + printf("Num: %d\n", num); + for (i = 0; i < num; i++) { + printf("%s\n", fakes[i]); + } + + return 0; +} === modified file 'i3/i3/i3_config.h' --- i3/i3/i3_config.h 2010-01-06 22:17:32 +0000 +++ i3/i3/i3_config.h 2010-02-11 11:49:47 +0000 @@ -1,27 +1,27 @@ -#ifndef I3_CONFIG - -#define I3_CONFIG - -#define MAX_CONFIG_PARM_LEN 200 -#define VER_CONFIG "0.1" - -void read_parameters(const char* filename); -void release_params(void); -/* You need to preallocate str */ -void read_string_par(char* path,char* str,int required); -/* You need to preallocate us */ -void read_ushort_par(char* path,unsigned short* us,int required); -/* You need to deallocate the returned char** by first deallocating #num char* pointers, and then char** */ -char **read_strings_par(char* path,int* num); - -/** Read the (string) value of the attribute (attribName) of the element specificed by elementPath */ -void read_string_attribute(char* elementPath, char *attribName, char* str, int required); - -/** Read the (unsigned short) value of the attribute (attribName) of the element specificed by elementPath */ -void read_ushort_attribute(char* elementPath, char *attribName,unsigned short* us,int required); - -/** Read the list of i3 servers. The number of servers is returned in the parameter num. - */ -char **read_i3server_list(int* num); - -#endif +#ifndef I3_CONFIG + +#define I3_CONFIG + +#define MAX_CONFIG_PARM_LEN 200 +#define VER_CONFIG "0.1" + +void read_parameters(const char *filename); +void release_params(void); +/* You need to preallocate str */ +void read_string_par(char *path, char *str, int required); +/* You need to preallocate us */ +void read_ushort_par(char *path, unsigned short *us, int required); +/* You need to deallocate the returned char** by first deallocating #num char* pointers, and then char** */ +char **read_strings_par(char *path, int *num); + +/** Read the (string) value of the attribute (attribName) of the element specificed by elementPath */ +void read_string_attribute(char *elementPath, char *attribName, char *str, int required); + +/** Read the (unsigned short) value of the attribute (attribName) of the element specificed by elementPath */ +void read_ushort_attribute(char *elementPath, char *attribName, unsigned short *us, int required); + +/** Read the list of i3 servers. The number of servers is returned in the parameter num. + */ +char **read_i3server_list(int *num); + +#endif === modified file 'i3/i3/i3_debug.c' --- i3/i3/i3_debug.c 2009-12-11 22:49:11 +0000 +++ i3/i3/i3_debug.c 2010-02-11 11:49:47 +0000 @@ -1,10 +1,10 @@ -#ifdef _WIN32 - - -// All the i3 debug and info messages go into this file. -# include <stdio.h> - // NOTE: the i3DebugFD should NOT be called debugFD. - // This causes a weird conflict with the debugging messages - // associated with the proxy - FILE* i3DebugFD = NULL; -#endif +#ifdef _WIN32 + + +// All the i3 debug and info messages go into this file. +# include <stdio.h> +// NOTE: the i3DebugFD should NOT be called debugFD. +// This causes a weird conflict with the debugging messages +// associated with the proxy +FILE *i3DebugFD = NULL; +#endif === modified file 'i3/i3/i3_debug.h' --- i3/i3/i3_debug.h 2009-12-11 22:49:11 +0000 +++ i3/i3/i3_debug.h 2010-02-11 11:49:47 +0000 @@ -1,89 +1,88 @@ -#ifndef I3_DEBUG_H -#define I3_DEBUG_H 1 - -#ifdef _WIN32 -#include <stdio.h> -# ifdef __cplusplus - extern "C" FILE* i3DebugFD; -# else - extern FILE* i3DebugFD; -# endif -#endif - - -/** - * The current debug level. - * Only debug messages with level less than or equal to this value will - * be printed. - */ -#define I3_CURRENT_DEBUG_LEVEL 100 - -/** - * The current info level. This is used to restrict the amount of - * informational messages displayed to the user. - * Only those messages whose level is less than or equal to the - * CURRENT_INFO_LEVEL will be displayed. - */ -#define I3_CURRENT_INFO_LEVEL 100 - - -/** - * This file defines the constants used as debugging levels - * in the i3 specific code. - */ - -/** - * This info level is used for displaying fatal error messages. - * Always displayed. - */ -#define I3_INFO_LEVEL_FATAL_ERROR 0 - -/** - * This info level is used for messages which are very essential. - * Messages at this level will always be displayed. - */ -#define I3_INFO_LEVEL_MINIMAL 50 - -/** - * This info level is used for warning messages. - */ -#define I3_INFO_LEVEL_WARNING 60 - -/** - * The messages at this level are not critical. So they may not be - * displayed (depends on CURRENT_INFO_LEVEL). - */ -#define I3_INFO_LEVEL_VERBOSE 70 - -/** - * This is used for error messages which are probably caused due to bugs in the - * code. i.e. they are not INFO_LEVEL_WARNINGs - */ -#define I3_DEBUG_LEVEL_WARNING 20 - -/** - * This level is used temporarily while debugging to emphasize - * certain parts of the code. - */ -#define I3_DEBUG_LEVEL_SUPER -1 - -/** - * This is used for messages describing fatal errors. - */ -#define I3_DEBUG_LEVEL_FATAL 0 - -/** - * This is used for messages that are not fatal, but quite important - * or high level. - */ -#define I3_DEBUG_LEVEL_MINIMAL 30 - -/** - * This is used for messages that are not very important. - */ -#define I3_DEBUG_LEVEL_VERBOSE 90 - -#include "debug_fns.h" - -#endif - +#ifndef I3_DEBUG_H +#define I3_DEBUG_H 1 + +#ifdef _WIN32 +#include <stdio.h> +# ifdef __cplusplus +extern "C" FILE * i3DebugFD; +# else +extern FILE *i3DebugFD; +# endif +#endif + + +/** + * The current debug level. + * Only debug messages with level less than or equal to this value will + * be printed. + */ +#define I3_CURRENT_DEBUG_LEVEL 100 + +/** + * The current info level. This is used to restrict the amount of + * informational messages displayed to the user. + * Only those messages whose level is less than or equal to the + * CURRENT_INFO_LEVEL will be displayed. + */ +#define I3_CURRENT_INFO_LEVEL 100 + + +/** + * This file defines the constants used as debugging levels + * in the i3 specific code. + */ + +/** + * This info level is used for displaying fatal error messages. + * Always displayed. + */ +#define I3_INFO_LEVEL_FATAL_ERROR 0 + +/** + * This info level is used for messages which are very essential. + * Messages at this level will always be displayed. + */ +#define I3_INFO_LEVEL_MINIMAL 50 + +/** + * This info level is used for warning messages. + */ +#define I3_INFO_LEVEL_WARNING 60 + +/** + * The messages at this level are not critical. So they may not be + * displayed (depends on CURRENT_INFO_LEVEL). + */ +#define I3_INFO_LEVEL_VERBOSE 70 + +/** + * This is used for error messages which are probably caused due to bugs in the + * code. i.e. they are not INFO_LEVEL_WARNINGs + */ +#define I3_DEBUG_LEVEL_WARNING 20 + +/** + * This level is used temporarily while debugging to emphasize + * certain parts of the code. + */ +#define I3_DEBUG_LEVEL_SUPER -1 + +/** + * This is used for messages describing fatal errors. + */ +#define I3_DEBUG_LEVEL_FATAL 0 + +/** + * This is used for messages that are not fatal, but quite important + * or high level. + */ +#define I3_DEBUG_LEVEL_MINIMAL 30 + +/** + * This is used for messages that are not very important. + */ +#define I3_DEBUG_LEVEL_VERBOSE 90 + +#include "debug_fns.h" + +#endif === modified file 'i3/i3/i3_fun.h' --- i3/i3/i3_fun.h 2009-12-11 22:49:11 +0000 +++ i3/i3/i3_fun.h 2010-02-11 11:49:47 +0000 @@ -1,15 +1,15 @@ -#ifndef INCL_I3_FUN -#define INCL_I3_FUN - -#include "i3_id.h" -#include "i3_addr.h" -#include "i3_header.h" -#include "i3_misc.h" -#include "i3_options.h" -#include "i3_stack.h" -#include "i3_trigger.h" -#include "i3_api.h" -#include "i3_utils.h" -#include "token_bucket.h" - -#endif /* INCL_I3_FUN */ +#ifndef INCL_I3_FUN +#define INCL_I3_FUN + +#include "i3_id.h" +#include "i3_addr.h" +#include "i3_header.h" +#include "i3_misc.h" +#include "i3_options.h" +#include "i3_stack.h" +#include "i3_trigger.h" +#include "i3_api.h" +#include "i3_utils.h" +#include "token_bucket.h" + +#endif /* INCL_I3_FUN */ === modified file 'i3/i3/i3_header.c' --- i3/i3/i3_header.c 2009-12-11 22:49:11 +0000 +++ i3/i3/i3_header.c 2010-02-11 11:49:47 +0000 @@ -1,297 +1,315 @@ -/*************************************************************************** - i3_header.c - description - ------------------- - begin : Nov 27 2002 - email : istoica@xxxxxxxxxxxxxxx - ***************************************************************************/ - -#include "i3.h" -#include "i3_fun.h" -#include "i3_debug.h" -#include <stdlib.h> -#include <stdio.h> -#include <string.h> - - -/*************************************************************************** - * alloc_i3_header - allocate i3 header data structure - * - * return: - * pointer to the allocated data structure - ***************************************************************************/ - -i3_header *alloc_i3_header() -{ - struct i3_header *hdr; - - /* XXX: just simply call alloc for now; preallocate a pool of buffers - in the future */ - hdr = (i3_header *)calloc(1, sizeof(i3_header)); - if (hdr) - return hdr; - - I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, "FATAL ERROR: memory allocation error in alloc_i3_header\n"); - return NULL; -} - - -/*************************************************************************** - * init_i3_header - initialize i3 header data structure - * - * input: - * hdr - header data structure to be initialized - * data - specifies whether the packet contains data payload - * stack - stack of IDs used to route the packet - * option_list - list of options - ***************************************************************************/ - -void init_i3_header(i3_header *hdr, char data, - i3_stack *stack, i3_option_list *option_list) -{ - hdr->ver = I3_v01; - hdr->flags = (data ? I3_DATA : 0); - hdr->stack = stack; - if (option_list) { - hdr->flags |= I3_OPTION_LIST; - hdr->option_list = option_list; - } -} - -/*************************************************************************** - * duplicate_i3_header - duplicate the entire header - **************************************************************************/ -i3_header *duplicate_i3_header(i3_header *h) -{ - i3_header *new_h; - - new_h = alloc_i3_header(); - new_h->ver = h->ver; - new_h->flags = h->flags; - new_h->stack = duplicate_i3_stack(h->stack); - new_h->option_list = duplicate_i3_option_list(h->option_list); - - return new_h; -} - - -/*************************************************************************** - * free_i3_header - free header data structure - * - * input: - * header to be freed - * - ***************************************************************************/ - -void free_i3_header(i3_header *hdr) -{ - if (hdr->stack) - free_i3_stack(hdr->stack); - if (hdr->option_list) - free_i3_option_list(hdr->option_list); - free(hdr); -} - - -/*************************************************************************** - * pack_i3_header - convert a header data structure in packet format - * - * input: - * p - address of the buffer where the header is to be stored in - * packet format (pre-allocated) - * hdr - header to be converted in packet format - * - * output: - * length - length of the header in packet format (bytes) - ***************************************************************************/ - -void pack_i3_header(char *p, i3_header *hdr, unsigned short *length) -{ - unsigned short len; - - *p = hdr->ver; - // printf("%d %d\n",p[0],*length); - - p += sizeof(char); *length = sizeof(char); - - *p = hdr->flags; - // printf("%d %d\n",p[0],*length); - - if (!hdr->option_list) - *p = *p & (~I3_OPTION_LIST); - else - *p = *p | I3_OPTION_LIST; - p += sizeof(char); *length += sizeof(char); - - *p = 0; - pack_i3_stack(p, hdr->stack, &len); - - *length += len; p += len; - - if (hdr->option_list) { - pack_i3_option_list(p, hdr->option_list, &len); - *length += len; - } -} - - -unsigned short get_i3_header_len(i3_header *hdr) -{ - unsigned short length; - - length = 2 * sizeof(char); /* version + flags*/ - - length += get_i3_stack_len(hdr->stack); - - if (hdr->option_list) { - length += get_i3_option_list_len(hdr->option_list); - } - - return length; -} - - -/*************************************************************************** - * unpack_i3_header - allocate an i3_header data structure - * and copy info from packet into it - * - * input: - * p - address where header is stored in packet format - * - * output: - * length - length of the header info in packet format (bytes) - * - ***************************************************************************/ - -i3_header *unpack_i3_header(char *p, unsigned short *length) -{ - unsigned short len; - i3_header *hdr = alloc_i3_header(); - - // printf("%d %d\n",p[0],*length); - hdr->ver = p[0]; - p += sizeof(char); *length = sizeof(char); - - // printf("%d %d\n",p[0],*length); - hdr->flags = p[0]; - p += sizeof(char); *length += sizeof(char); - - // printf("%d %d\n",p[0],*length); - hdr->stack = unpack_i3_stack(p, &len); - p += len; *length += len; - // printf("%d %d\n",p[0],*length); - - if (hdr->flags & I3_OPTION_LIST) { - // printf("OPTIIONS: %d %d\n",p[0],*length); - hdr->option_list = unpack_i3_option_list(p, &len); - *length += len; - p += len; - } - - return hdr; -} - - -/*************************************************************************** - * check_i3_header - check whether this is a legal header (should be - * called when an i3 packet is received) - * - * input: - * p - address where header is stored in packet format - * - * return: - * error if any; FALSE otherwise - * - ***************************************************************************/ - -int check_i3_header(char *p, int pkt_len) -{ - unsigned short len; - int rc; - char flags; - - /* check packet length */ - if (pkt_len < 3) - return I3_ERR_PKT_LEN_TOO_SHORT; - - /* check version */ - if (p[0] != I3_v01) - return I3_ERR_INVALID_VER; - p += sizeof(char); pkt_len -= sizeof(char); /* account for version */ - - /* check flags */ - flags = p[0] & 0xf0; - if (flags & ~(I3_DATA | I3_OPTION_LIST | I3_FIRST_HOP)) - return I3_ERR_INVALID_FLAGS; - p += sizeof(char); pkt_len -= sizeof(char); /* account for flags */ - - /* check ID stack */ - if (*p > (char) I3_MAX_STACK_LEN) - return I3_ERR_INVALID_STACK; - if ((rc = check_i3_stack(p, &len)) != FALSE) - return rc; - /* account for stack length */ - p += len; pkt_len -= len; - - /* check option list */ - if (flags & I3_OPTION_LIST) { - if ((rc = check_i3_option_list(p, &len)) != FALSE) - return rc; - } else - len = 0; - - pkt_len -= len; - if (pkt_len < 0) - return I3_ERR_PKT_LEN_TOO_SHORT; - - return 0; -} - - -/*************************************************************************** - * get_first_id - return the address of the first character - * in the stack - * - * input: - * p - i3 packet - * - * return: - * pointer to the first ID in the stack - * - ***************************************************************************/ - -char *get_first_id(char *p) -{ - /* stack follows after version and "flags" and "stack_length" fields */ - return p + 3*sizeof(char); -} - -/********************* - ** print i3_header ** - *********************/ - -void printf_i3_header(struct i3_header *hdr, int indent) -{ - char buf[INDENT_BUF_LEN]; - - memset(buf, ' ', indent); - buf[indent] = 0; - - printf("%s header (version = %x, flags = %x (", - buf, hdr->ver, hdr->flags); - if (hdr->flags & I3_DATA) - printf("I3_DATA| "); - if (hdr->flags & I3_OPTION_LIST) - printf("I3_OPTION_LIST| "); - if (hdr->flags & I3_FIRST_HOP) - printf("I3_FIRST_HOP| "); - if (hdr->flags & I3_TRIGGER_FLAG_ALLOW_SHORTCUT) - printf("I3_TRIGGER_FLAG_ALLOW_SHORTCUT | "); - printf(")\n"); - - printf_i3_stack(hdr->stack, indent + INDENT_CONST); - if (hdr->option_list) - printf_i3_option_list(hdr->option_list, indent + INDENT_CONST); - - fflush(stdout); -} - +/*************************************************************************** +* i3_header.c - description +* ------------------- +* begin : Nov 27 2002 +* email : istoica@xxxxxxxxxxxxxxx +***************************************************************************/ + +#include "i3.h" +#include "i3_fun.h" +#include "i3_debug.h" +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + + +/*************************************************************************** +* alloc_i3_header - allocate i3 header data structure +* +* return: +* pointer to the allocated data structure +***************************************************************************/ + +i3_header *alloc_i3_header() +{ + struct i3_header *hdr; + + /* XXX: just simply call alloc for now; preallocate a pool of buffers + * in the future */ + hdr = (i3_header *) calloc(1, sizeof(i3_header)); + if (hdr) { + return hdr; + } + + I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, "FATAL ERROR: memory allocation error in alloc_i3_header\n"); + return NULL; +} + +/*************************************************************************** +* init_i3_header - initialize i3 header data structure +* +* input: +* hdr - header data structure to be initialized +* data - specifies whether the packet contains data payload +* stack - stack of IDs used to route the packet +* option_list - list of options +***************************************************************************/ + +void init_i3_header(i3_header *hdr, char data, + i3_stack *stack, i3_option_list *option_list) +{ + hdr->ver = I3_v01; + hdr->flags = (data ? I3_DATA : 0); + hdr->stack = stack; + if (option_list) { + hdr->flags |= I3_OPTION_LIST; + hdr->option_list = option_list; + } +} + +/*************************************************************************** + * duplicate_i3_header - duplicate the entire header + **************************************************************************/ +i3_header *duplicate_i3_header(i3_header *h) +{ + i3_header *new_h; + + new_h = alloc_i3_header(); + new_h->ver = h->ver; + new_h->flags = h->flags; + new_h->stack = duplicate_i3_stack(h->stack); + new_h->option_list = duplicate_i3_option_list(h->option_list); + + return new_h; +} + +/*************************************************************************** +* free_i3_header - free header data structure +* +* input: +* header to be freed +* +***************************************************************************/ + +void free_i3_header(i3_header *hdr) +{ + if (hdr->stack) { + free_i3_stack(hdr->stack); + } + if (hdr->option_list) { + free_i3_option_list(hdr->option_list); + } + free(hdr); +} + +/*************************************************************************** +* pack_i3_header - convert a header data structure in packet format +* +* input: +* p - address of the buffer where the header is to be stored in +* packet format (pre-allocated) +* hdr - header to be converted in packet format +* +* output: +* length - length of the header in packet format (bytes) +***************************************************************************/ + +void pack_i3_header(char *p, i3_header *hdr, unsigned short *length) +{ + unsigned short len; + + *p = hdr->ver; + // printf("%d %d\n",p[0],*length); + + p += sizeof(char); + *length = sizeof(char); + + *p = hdr->flags; + // printf("%d %d\n",p[0],*length); + + if (!hdr->option_list) { + *p = *p & (~I3_OPTION_LIST); + } else { + *p = *p | I3_OPTION_LIST; + } + p += sizeof(char); + *length += sizeof(char); + + *p = 0; + pack_i3_stack(p, hdr->stack, &len); + + *length += len; + p += len; + + if (hdr->option_list) { + pack_i3_option_list(p, hdr->option_list, &len); + *length += len; + } +} + +unsigned short get_i3_header_len(i3_header *hdr) +{ + unsigned short length; + + length = 2 * sizeof(char); /* version + flags*/ + + length += get_i3_stack_len(hdr->stack); + + if (hdr->option_list) { + length += get_i3_option_list_len(hdr->option_list); + } + + return length; +} + +/*************************************************************************** +* unpack_i3_header - allocate an i3_header data structure +* and copy info from packet into it +* +* input: +* p - address where header is stored in packet format +* +* output: +* length - length of the header info in packet format (bytes) +* +***************************************************************************/ + +i3_header *unpack_i3_header(char *p, unsigned short *length) +{ + unsigned short len; + i3_header *hdr = alloc_i3_header(); + + // printf("%d %d\n",p[0],*length); + hdr->ver = p[0]; + p += sizeof(char); + *length = sizeof(char); + + // printf("%d %d\n",p[0],*length); + hdr->flags = p[0]; + p += sizeof(char); + *length += sizeof(char); + + // printf("%d %d\n",p[0],*length); + hdr->stack = unpack_i3_stack(p, &len); + p += len; + *length += len; + // printf("%d %d\n",p[0],*length); + + if (hdr->flags & I3_OPTION_LIST) { + // printf("OPTIIONS: %d %d\n",p[0],*length); + hdr->option_list = unpack_i3_option_list(p, &len); + *length += len; + p += len; + } + + return hdr; +} + +/*************************************************************************** +* check_i3_header - check whether this is a legal header (should be +* called when an i3 packet is received) +* +* input: +* p - address where header is stored in packet format +* +* return: +* error if any; FALSE otherwise +* +***************************************************************************/ + +int check_i3_header(char *p, int pkt_len) +{ + unsigned short len; + int rc; + char flags; + + /* check packet length */ + if (pkt_len < 3) { + return I3_ERR_PKT_LEN_TOO_SHORT; + } + + /* check version */ + if (p[0] != I3_v01) { + return I3_ERR_INVALID_VER; + } + p += sizeof(char); + pkt_len -= sizeof(char); /* account for version */ + + /* check flags */ + flags = p[0] & 0xf0; + if (flags & ~(I3_DATA | I3_OPTION_LIST | I3_FIRST_HOP)) { + return I3_ERR_INVALID_FLAGS; + } + p += sizeof(char); + pkt_len -= sizeof(char); /* account for flags */ + + /* check ID stack */ + if (*p > (char) I3_MAX_STACK_LEN) { + return I3_ERR_INVALID_STACK; + } + if ((rc = check_i3_stack(p, &len)) != FALSE) { + return rc; + } + /* account for stack length */ + p += len; + pkt_len -= len; + + /* check option list */ + if (flags & I3_OPTION_LIST) { + if ((rc = check_i3_option_list(p, &len)) != FALSE) { + return rc; + } + } else { + len = 0; + } + + pkt_len -= len; + if (pkt_len < 0) { + return I3_ERR_PKT_LEN_TOO_SHORT; + } + + return 0; +} + +/*************************************************************************** +* get_first_id - return the address of the first character +* in the stack +* +* input: +* p - i3 packet +* +* return: +* pointer to the first ID in the stack +* +***************************************************************************/ + +char *get_first_id(char *p) +{ + /* stack follows after version and "flags" and "stack_length" fields */ + return p + 3 * sizeof(char); +} + +/********************* +** print i3_header ** +*********************/ + +void printf_i3_header(struct i3_header *hdr, int indent) +{ + char buf[INDENT_BUF_LEN]; + + memset(buf, ' ', indent); + buf[indent] = 0; + + printf("%s header (version = %x, flags = %x (", + buf, hdr->ver, hdr->flags); + if (hdr->flags & I3_DATA) { + printf("I3_DATA| "); + } + if (hdr->flags & I3_OPTION_LIST) { + printf("I3_OPTION_LIST| "); + } + if (hdr->flags & I3_FIRST_HOP) { + printf("I3_FIRST_HOP| "); + } + if (hdr->flags & I3_TRIGGER_FLAG_ALLOW_SHORTCUT) { + printf("I3_TRIGGER_FLAG_ALLOW_SHORTCUT | "); + } + printf(")\n"); + + printf_i3_stack(hdr->stack, indent + INDENT_CONST); + if (hdr->option_list) { + printf_i3_option_list(hdr->option_list, indent + INDENT_CONST); + } + + fflush(stdout); +} === modified file 'i3/i3/i3_header.h' --- i3/i3/i3_header.h 2010-01-06 22:17:32 +0000 +++ i3/i3/i3_header.h 2010-02-11 11:49:47 +0000 @@ -1,27 +1,27 @@ -/*************************************************************************** - i3_header.h - description - ------------------- - begin : Fre Jun 20 2003 - copyright : (C) 2003 by klaus - email : wehrle@xxxxxxxxxxxxxxxxx - ***************************************************************************/ - -#ifndef I3_HEADER_H -#define I3_HEADER_H - - -/* functions implemented in i3_header.c */ -i3_header *alloc_i3_header(void); -void init_i3_header(i3_header *hdr, char data, - i3_stack *stack, i3_option_list *option_list); -i3_header *duplicate_i3_header(i3_header *h); -void free_i3_header(i3_header *hdr); -void pack_i3_header(char *packedhdr, i3_header *hdr, - unsigned short *length); -unsigned short get_i3_header_len(i3_header *hdr); -i3_header *unpack_i3_header(char *packedhdr, unsigned short *length); -int check_i3_header(char *p, int pkt_len); -char *get_first_id(char *packet); -void printf_i3_header(struct i3_header *hdr, int indent); - -#endif +/*************************************************************************** +* i3_header.h - description +* ------------------- +* begin : Fre Jun 20 2003 +* copyright : (C) 2003 by klaus +* email : wehrle@xxxxxxxxxxxxxxxxx +***************************************************************************/ + +#ifndef I3_HEADER_H +#define I3_HEADER_H + + +/* functions implemented in i3_header.c */ +i3_header *alloc_i3_header(void); +void init_i3_header(i3_header *hdr, char data, + i3_stack *stack, i3_option_list *option_list); +i3_header *duplicate_i3_header(i3_header *h); +void free_i3_header(i3_header *hdr); +void pack_i3_header(char *packedhdr, i3_header *hdr, + unsigned short *length); +unsigned short get_i3_header_len(i3_header *hdr); +i3_header *unpack_i3_header(char *packedhdr, unsigned short *length); +int check_i3_header(char *p, int pkt_len); +char *get_first_id(char *packet); +void printf_i3_header(struct i3_header *hdr, int indent); + +#endif === modified file 'i3/i3/i3_id.c' --- i3/i3/i3_id.c 2009-12-11 22:49:11 +0000 +++ i3/i3/i3_id.c 2010-02-11 11:49:47 +0000 @@ -1,337 +1,333 @@ -/*************************************************************************** - i3_id.c - description - ------------------- - begin : Nov 20 2002 - email : istoica@xxxxxxxxxxxxxxx - ***************************************************************************/ - -#include "i3.h" -#include "i3_fun.h" -#include "i3_debug.h" -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <assert.h> -#include <ctype.h> -/*************************************************************************** - * alloc_i3_id - allocate a indientifie data structure - * - * return: - * allocated identifier - ***************************************************************************/ - -ID *alloc_i3_id() -{ - ID *id; - - if ((id = (ID *)malloc(sizeof(ID))) == NULL) - I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, "alloc_i3_id: memory allocation error.\n"); - return id; -} - - -/*************************************************************************** - * init_i3_id - initialized identifier - * - * input - * id, id1 - set id to id1 - * - ***************************************************************************/ - -void init_i3_id(ID *id, const ID *id1) -{ - memcpy(id->x, id1->x, sizeof(ID)); -} - - -/*************************************************************************** - * free_i3_id - free identifier - * - * input: - * id to be freed - ***************************************************************************/ - -void free_i3_id(ID *id) -{ - free(id); -} - - -/*************************************************************************** - * duplicate_i3_id - create a replica of identifier id - * - * input: - * id - identifier to be duplicated - * - * return: - * replica of id - ***************************************************************************/ - -ID *duplicate_i3_id(ID *id) -{ - ID *idnew = alloc_i3_id(); - - init_i3_id(idnew, id); - return idnew; -} - -/*************************************************************************** - * pack_i3_id - convert identifier in packet format - * - * input: - * p - address of the buffer where the id is to be stored in - * packet format (the buffer is pre-allocated) - * id - id to be converted in packet format - * - * output: - * length - length of the identifier in packet format - ***************************************************************************/ - -void pack_i3_id(char *p, ID *id, unsigned short *length) -{ - memcpy(p, id->x, sizeof(ID)); - *length = sizeof(ID); -} - - - -/*************************************************************************** - * unpack_i3_id - copy identifier info from packet to an identifier - * data structure - * - * input: - * p - address where identifier is stored in packet format - * - * return: - * id - identifier data structure - * - * output: - * length - length of the id info in packet format - * - ***************************************************************************/ - -ID *unpack_i3_id(char *p, unsigned short *length) -{ - ID *id = alloc_i3_id(); - - memcpy(id->x, p, sizeof(ID)); - *length = sizeof(ID); - - return id; -} - -// Assume: s has enough space -/** - * This function prints the ID specified by <code>id</code> - * in the character pointed to by <code>s</code>. - * It is assumed that enough space has already been allocated - * for the character array. - * @param s the character array into which the id should be printed. - * @param id the ID to be printed. - * @return Returns the same pointer as that passed in parameter <code>s</code>. - * This is useful when you want to use sprintf_i3_id as part of some other - * printf statement. - */ -char* sprintf_i3_id(char* s, const ID *id) -{ - uint i; - - *s = 0; - for (i = 0; i < sizeof(ID); i++) - { - char ts[20]; - sprintf(ts, "%02x", (int)(id->x[i])); - strcat(s,ts); - } - - return s; -} - -/** - * This function can read back the ID from the - * string printed by sprintf_i3_id. - */ -ID* sscanf_i3_id(char *id_str, ID* id) { - uint i; - int c; - for (i = 0; i < sizeof(ID); i++) { - sscanf(id_str, "%02x", &c); - id->x[i] = (uint8_t)c; - id_str += 2; - } - return id; -} - -char* sprintf_i3_key(char* s, const Key *key) -{ - uint i; - - *s = 0; - for (i = 0; i < sizeof(Key); i++) - { - char ts[20]; - sprintf(ts, "%02x", (int)(key->x[i])); - strcat(s,ts); - } - - return s; -} - - -/** - * This function can read back the Key from the - * string printed by sprintf_i3_key. - */ -Key* sscanf_i3_key(char *id_str, Key *key) { - uint i; - int c; - for (i = 0; i < sizeof(Key); i++) { - sscanf(id_str, "%02x", &c); - key->x[i] = (uint8_t) c; - id_str += 2; - } - - return key; -} -/************************************* - ** print i3_id; just for test ** - *************************************/ - -void fprintf_i3_id(FILE *fp, ID *id, int indent) -{ - char buf[INDENT_BUF_LEN]; - uint i; - - memset(buf, ' ', INDENT_BUF_LEN); - buf[indent] = 0; - - fprintf(fp, "%s id: ", buf); - for (i = 0; i < sizeof(ID); i++) - fprintf(fp, "%02x", (int)(id->x[i])); - fprintf(fp, "\n"); -} - -void printf_i3_id(ID *id, int indent) -{ - char buf[INDENT_BUF_LEN]; - uint i; - - memset(buf, ' ', INDENT_BUF_LEN); - buf[indent] = 0; - - printf("%s id: ", buf); - for (i = 0; i < sizeof(ID); i++) - printf("%02x", (int)(id->x[i])); - printf("\n"); -} - -/************************************************************************ - * Compare two ids and return an integer less than, equal to, or - * greater than zero if id1 is found, respectively, to be less than, - * to match, or be greater than s2. - ***********************************************************************/ -int compare_ids(ID *id1, ID *id2) -{ - assert(NULL != id1 && NULL != id2); - return memcmp(id1->x, id2->x, ID_LEN); -} - -/************************************************************************ - * Purpose: Convert a string to i3 id eg. read from file - * XXX Check where this should be included ... may be in some other - * file -- To check for bugs also - ***********************************************************************/ -static unsigned char todigit(char ch) -{ - if (isdigit((int) ch)) - return (ch - '0'); - else - return (10 + ch - 'a'); -} - -ID atoi3id(char *str) -{ - ID id; - int i, len; - - len = (int) strlen(str); - assert(len <= 2*ID_LEN); - memset(id.x, 0, ID_LEN); - - if (len % 2 != 0) { - str[len] = '0'; - len++; - } - - for (i = 0; i < len/2; i++) - id.x[ i ] = (todigit(str[2*i]) << 4) | todigit(str[2*i+1]); - - str[len--] = 0; // to restore old str - return id; -} - -/************************************************************************ - * Purpose: Public ID constraint - * Public IDs (ie. IDs that need to be protected from - * impersonation) need to have "public_id" bit set. The public_id - * bit is the last bit in the prefix. - ***********************************************************************/ -void set_id_type(ID *id, char type) -{ - uint8_t mask = 1; - - if (I3_ID_TYPE_PUBLIC == type) { - - // last two bits 01 if UNCONSTRAINED type exists - id->x[PREFIX_LEN-1] |= mask; - //id->x[PREFIX_LEN - 2] &= ~mask; - - } else if (I3_ID_TYPE_PRIVATE == type) { - - // last two bits 00 if UNCONSTRAINED ID type exists - id->x[PREFIX_LEN-1] &= ~mask; - //id->x[PREFIX_LEN - 2] &= ~mask; - - /** - } else if (I3_ID_TYPE_UNCONSTRAINED == type) { - - // last two bits 10 - id->x[PREFIX_LEN - 2] |= mask; - id->x[PREFIX_LEN - 1] &= ~mask; - */ - - } else { - I3_PRINT_DEBUG1(I3_DEBUG_LEVEL_MINIMAL, "set_id_type: Unknown type: %d\n", type); - } -} - -char get_id_type(ID *id) -{ - uint8_t mask = 1; - - /* Only if UNCONSTRAINED id type exists - if ((id->x[PREFIX_LEN - 2] & mask) == 1) { - //second last bit 1 - if ((id->x[PREFIX_LEN - 1] & mask) == 1) { - //last bit 1 - return I3_ID_TYPE_UNKNOWN; - } else { - // last bit 0 - return I3_ID_TYPE_UNCONSTRAINED; - } - } else { - //second last bit 0 - - */ - if ((id->x[PREFIX_LEN-1] & mask) == 1) { - //last bit 1 - return I3_ID_TYPE_PUBLIC; - } else { - //last bit 0 - return I3_ID_TYPE_PRIVATE; - } - - /* Only if UNCONSTRAINED id type exists - } - */ -} +/*************************************************************************** +* i3_id.c - description +* ------------------- +* begin : Nov 20 2002 +* email : istoica@xxxxxxxxxxxxxxx +***************************************************************************/ + +#include "i3.h" +#include "i3_fun.h" +#include "i3_debug.h" +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <assert.h> +#include <ctype.h> +/*************************************************************************** +* alloc_i3_id - allocate a indientifie data structure +* +* return: +* allocated identifier +***************************************************************************/ + +ID *alloc_i3_id() +{ + ID *id; + + if ((id = (ID *) malloc(sizeof(ID))) == NULL) { + I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, "alloc_i3_id: memory allocation error.\n"); + } + return id; +} + +/*************************************************************************** +* init_i3_id - initialized identifier +* +* input +* id, id1 - set id to id1 +* +***************************************************************************/ + +void init_i3_id(ID *id, const ID *id1) +{ + memcpy(id->x, id1->x, sizeof(ID)); +} + +/*************************************************************************** +* free_i3_id - free identifier +* +* input: +* id to be freed +***************************************************************************/ + +void free_i3_id(ID *id) +{ + free(id); +} + +/*************************************************************************** +* duplicate_i3_id - create a replica of identifier id +* +* input: +* id - identifier to be duplicated +* +* return: +* replica of id +***************************************************************************/ + +ID *duplicate_i3_id(ID *id) +{ + ID *idnew = alloc_i3_id(); + + init_i3_id(idnew, id); + return idnew; +} + +/*************************************************************************** +* pack_i3_id - convert identifier in packet format +* +* input: +* p - address of the buffer where the id is to be stored in +* packet format (the buffer is pre-allocated) +* id - id to be converted in packet format +* +* output: +* length - length of the identifier in packet format +***************************************************************************/ + +void pack_i3_id(char *p, ID *id, unsigned short *length) +{ + memcpy(p, id->x, sizeof(ID)); + *length = sizeof(ID); +} + +/*************************************************************************** +* unpack_i3_id - copy identifier info from packet to an identifier +* data structure +* +* input: +* p - address where identifier is stored in packet format +* +* return: +* id - identifier data structure +* +* output: +* length - length of the id info in packet format +* +***************************************************************************/ + +ID *unpack_i3_id(char *p, unsigned short *length) +{ + ID *id = alloc_i3_id(); + + memcpy(id->x, p, sizeof(ID)); + *length = sizeof(ID); + + return id; +} + +// Assume: s has enough space +/** + * This function prints the ID specified by <code>id</code> + * in the character pointed to by <code>s</code>. + * It is assumed that enough space has already been allocated + * for the character array. + * @param s the character array into which the id should be printed. + * @param id the ID to be printed. + * @return Returns the same pointer as that passed in parameter <code>s</code>. + * This is useful when you want to use sprintf_i3_id as part of some other + * printf statement. + */ +char *sprintf_i3_id(char *s, const ID *id) +{ + uint i; + + *s = 0; + for (i = 0; i < sizeof(ID); i++) { + char ts[20]; + sprintf(ts, "%02x", (int) (id->x[i])); + strcat(s, ts); + } + + return s; +} + +/** + * This function can read back the ID from the + * string printed by sprintf_i3_id. + */ +ID *sscanf_i3_id(char *id_str, ID *id) +{ + uint i; + int c; + for (i = 0; i < sizeof(ID); i++) { + sscanf(id_str, "%02x", &c); + id->x[i] = (uint8_t) c; + id_str += 2; + } + return id; +} + +char *sprintf_i3_key(char *s, const Key *key) +{ + uint i; + + *s = 0; + for (i = 0; i < sizeof(Key); i++) { + char ts[20]; + sprintf(ts, "%02x", (int) (key->x[i])); + strcat(s, ts); + } + + return s; +} + +/** + * This function can read back the Key from the + * string printed by sprintf_i3_key. + */ +Key *sscanf_i3_key(char *id_str, Key *key) +{ + uint i; + int c; + for (i = 0; i < sizeof(Key); i++) { + sscanf(id_str, "%02x", &c); + key->x[i] = (uint8_t) c; + id_str += 2; + } + + return key; +} + +/************************************* +** print i3_id; just for test ** +*************************************/ + +void fprintf_i3_id(FILE *fp, ID *id, int indent) +{ + char buf[INDENT_BUF_LEN]; + uint i; + + memset(buf, ' ', INDENT_BUF_LEN); + buf[indent] = 0; + + fprintf(fp, "%s id: ", buf); + for (i = 0; i < sizeof(ID); i++) { + fprintf(fp, "%02x", (int) (id->x[i])); + } + fprintf(fp, "\n"); +} + +void printf_i3_id(ID *id, int indent) +{ + char buf[INDENT_BUF_LEN]; + uint i; + + memset(buf, ' ', INDENT_BUF_LEN); + buf[indent] = 0; + + printf("%s id: ", buf); + for (i = 0; i < sizeof(ID); i++) { + printf("%02x", (int) (id->x[i])); + } + printf("\n"); +} + +/************************************************************************ + * Compare two ids and return an integer less than, equal to, or + * greater than zero if id1 is found, respectively, to be less than, + * to match, or be greater than s2. + ***********************************************************************/ +int compare_ids(ID *id1, ID *id2) +{ + assert(NULL != id1 && NULL != id2); + return memcmp(id1->x, id2->x, ID_LEN); +} + +/************************************************************************ + * Purpose: Convert a string to i3 id eg. read from file + * XXX Check where this should be included ... may be in some other + * file -- To check for bugs also + ***********************************************************************/ +static unsigned char todigit(char ch) +{ + if (isdigit((int) ch)) { + return ch - '0'; + } else { + return 10 + ch - 'a'; + } +} + +ID atoi3id(char *str) +{ + ID id; + int i, len; + + len = (int) strlen(str); + assert(len <= 2 * ID_LEN); + memset(id.x, 0, ID_LEN); + + if (len % 2 != 0) { + str[len] = '0'; + len++; + } + + for (i = 0; i < len / 2; i++) { + id.x[ i ] = (todigit(str[2 * i]) << 4) | todigit(str[2 * i + 1]); + } + + str[len--] = 0; // to restore old str + return id; +} + +/************************************************************************ + * Purpose: Public ID constraint + * Public IDs (ie. IDs that need to be protected from + * impersonation) need to have "public_id" bit set. The public_id + * bit is the last bit in the prefix. + ***********************************************************************/ +void set_id_type(ID *id, char type) +{ + uint8_t mask = 1; + + if (I3_ID_TYPE_PUBLIC == type) { + // last two bits 01 if UNCONSTRAINED type exists + id->x[PREFIX_LEN - 1] |= mask; + //id->x[PREFIX_LEN - 2] &= ~mask; + } else if (I3_ID_TYPE_PRIVATE == type) { + // last two bits 00 if UNCONSTRAINED ID type exists + id->x[PREFIX_LEN - 1] &= ~mask; + //id->x[PREFIX_LEN - 2] &= ~mask; + + /** + * } else if (I3_ID_TYPE_UNCONSTRAINED == type) { + * + * // last two bits 10 + * id->x[PREFIX_LEN - 2] |= mask; + * id->x[PREFIX_LEN - 1] &= ~mask; + */ + } else { + I3_PRINT_DEBUG1(I3_DEBUG_LEVEL_MINIMAL, "set_id_type: Unknown type: %d\n", type); + } +} + +char get_id_type(ID *id) +{ + uint8_t mask = 1; + + /* Only if UNCONSTRAINED id type exists + * if ((id->x[PREFIX_LEN - 2] & mask) == 1) { + * //second last bit 1 + * if ((id->x[PREFIX_LEN - 1] & mask) == 1) { + * //last bit 1 + * return I3_ID_TYPE_UNKNOWN; + * } else { + * // last bit 0 + * return I3_ID_TYPE_UNCONSTRAINED; + * } + * } else { + * //second last bit 0 + * + */ + if ((id->x[PREFIX_LEN - 1] & mask) == 1) { + //last bit 1 + return I3_ID_TYPE_PUBLIC; + } else { + //last bit 0 + return I3_ID_TYPE_PRIVATE; + } + + /* Only if UNCONSTRAINED id type exists + * } + */ +} === modified file 'i3/i3/i3_id.h' --- i3/i3/i3_id.h 2010-01-06 22:17:32 +0000 +++ i3/i3/i3_id.h 2010-02-11 11:49:47 +0000 @@ -1,39 +1,39 @@ -/*************************************************************************** - i3_id.h - description - ------------------- - begin : Fre Jun 20 2003 - copyright : (C) 2003 by Ion - email : istoica@xxxxxxxxxxxxxxx - ***************************************************************************/ - -#ifndef I3_ID_H -#define I3_ID_H - -#include <stdio.h> -#include "i3.h" - -/* functions implemented in i3_id.c */ -ID *alloc_i3_id(void); -void init_i3_id(ID *id, const ID *id1); -void free_i3_id(ID *id); -void pack_i3_id(char *packedid, ID *id, unsigned short *length); -ID *unpack_i3_id(char *p, unsigned short *length); -void printf_i3_id(ID *id, int intend); -void fprintf_i3_id(FILE *fp, ID *id, int intend); - -char* sprintf_i3_id(char* s, const ID *id); -char* sprintf_i3_key(char* s, const Key *key); -ID* sscanf_i3_id(char *s, ID *id); -Key* sscanf_i3_key(char *s, Key *key); - -ID *duplicate_i3_id(ID *id); -int compare_ids(ID *id1, ID *id2); -ID atoi3id(char *str); - -/* for public ID constraints */ -char get_id_type(ID *id); -void set_id_type(ID *id, char type); -#define set_public_id(id) set_id_type(id, I3_ID_TYPE_PUBLIC) -#define set_private_id(id) set_id_type(id, I3_ID_TYPE_PRIVATE) - -#endif +/*************************************************************************** +* i3_id.h - description +* ------------------- +* begin : Fre Jun 20 2003 +* copyright : (C) 2003 by Ion +* email : istoica@xxxxxxxxxxxxxxx +***************************************************************************/ + +#ifndef I3_ID_H +#define I3_ID_H + +#include <stdio.h> +#include "i3.h" + +/* functions implemented in i3_id.c */ +ID *alloc_i3_id(void); +void init_i3_id(ID *id, const ID *id1); +void free_i3_id(ID *id); +void pack_i3_id(char *packedid, ID *id, unsigned short *length); +ID *unpack_i3_id(char *p, unsigned short *length); +void printf_i3_id(ID *id, int intend); +void fprintf_i3_id(FILE *fp, ID *id, int intend); + +char *sprintf_i3_id(char *s, const ID *id); +char *sprintf_i3_key(char *s, const Key *key); +ID *sscanf_i3_id(char *s, ID *id); +Key *sscanf_i3_key(char *s, Key *key); + +ID *duplicate_i3_id(ID *id); +int compare_ids(ID *id1, ID *id2); +ID atoi3id(char *str); + +/* for public ID constraints */ +char get_id_type(ID *id); +void set_id_type(ID *id, char type); +#define set_public_id(id) set_id_type(id, I3_ID_TYPE_PUBLIC) +#define set_private_id(id) set_id_type(id, I3_ID_TYPE_PRIVATE) + +#endif === modified file 'i3/i3/i3_misc.c' --- i3/i3/i3_misc.c 2009-12-11 22:49:11 +0000 +++ i3/i3/i3_misc.c 2010-02-11 11:49:47 +0000 @@ -1,31 +1,32 @@ -/*************************************************************************** - i3_misc.c - description - ------------------- - begin : Nov 20 2002 - email : istoica@xxxxxxxxxxxxxxx - ***************************************************************************/ - -#include <stdio.h> -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <stdarg.h> -#include <errno.h> - -void panic(char *fmt, ...) -{ - va_list args; - - fflush(stdout); - fprintf(stderr, "FATAL ERROR: "); - - va_start(args, fmt); - vfprintf(stderr, fmt, args); - va_end(args); - - if (fmt[0] != '\0' && fmt[strlen(fmt)-1] == ':') - fprintf(stderr, " %s", strerror(errno)); - fprintf(stderr, "\n"); - - exit(2); /* conventional value for failed execution */ -} +/*************************************************************************** +* i3_misc.c - description +* ------------------- +* begin : Nov 20 2002 +* email : istoica@xxxxxxxxxxxxxxx +***************************************************************************/ + +#include <stdio.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <stdarg.h> +#include <errno.h> + +void panic(char *fmt, ...) +{ + va_list args; + + fflush(stdout); + fprintf(stderr, "FATAL ERROR: "); + + va_start(args, fmt); + vfprintf(stderr, fmt, args); + va_end(args); + + if (fmt[0] != '\0' && fmt[strlen(fmt) - 1] == ':') { + fprintf(stderr, " %s", strerror(errno)); + } + fprintf(stderr, "\n"); + + exit(2); /* conventional value for failed execution */ +} === modified file 'i3/i3/i3_misc.h' --- i3/i3/i3_misc.h 2009-12-11 22:49:11 +0000 +++ i3/i3/i3_misc.h 2010-02-11 11:49:47 +0000 @@ -1,15 +1,15 @@ -/*************************************************************************** - i3_misc.h - description - ------------------- - begin : Fre Jun 20 2003 - copyright : (C) 2003 by klaus - email : wehrle@xxxxxxxxxxxxxxxxx - ***************************************************************************/ - -#ifndef I3_MISC_H -#define I3_MISC_H - -/* functions implemented in i3_misc.c */ -void panic(char *fmt, ...); - -#endif +/*************************************************************************** +* i3_misc.h - description +* ------------------- +* begin : Fre Jun 20 2003 +* copyright : (C) 2003 by klaus +* email : wehrle@xxxxxxxxxxxxxxxxx +***************************************************************************/ + +#ifndef I3_MISC_H +#define I3_MISC_H + +/* functions implemented in i3_misc.c */ +void panic(char *fmt, ...); + +#endif === modified file 'i3/i3/i3_options.c' --- i3/i3/i3_options.c 2009-12-11 22:49:11 +0000 +++ i3/i3/i3_options.c 2010-02-11 11:49:47 +0000 @@ -1,863 +1,867 @@ -/*************************************************************************** - i3_options.c - description - ------------------- - begin : Nov 21 2002 - email : istoica@xxxxxxxxxxxxxxx - ***************************************************************************/ - -#include "i3.h" -#include "i3_fun.h" -#include "i3_debug.h" -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <assert.h> - - -/*************************************************************************** - * alloc_i3_option - allocate i3 option data structure - * - * return: - * pointer to the allocated data structure - ***************************************************************************/ -struct i3_option *alloc_i3_option() -{ - struct i3_option *option; - - option = (i3_option *)calloc(1, sizeof(i3_option)); - if (option) - return option; - - I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL,"FATAL ERROR: memory allocation error in alloc_i3_option\n"); - return NULL; -} - - -/*************************************************************************** - * init_i3_option - initialize i3 option data structure - * - * input: - * option - data structure to be initialized - * type - option type - * entry - option entry, e.g., ret_addr, trigger (pre-allocated) - * - ***************************************************************************/ -void init_i3_option(i3_option *option, char type, void * __RTTI entry) -{ - option->type = type; - /* all are pointers; just use one type for assigment */ - if (type == I3_OPT_REQUEST_FOR_CACHE - || type == I3_OPT_REQUEST_FOR_CACHE_SHORTCUT - || type == I3_OPT_REQUEST_FOR_CACHE_SHORTCUT_INDIR -#if NEWS_INSTRUMENT - || type == I3_OPT_LOG_PACKET || type == I3_OPT_APPEND_TS -#endif - ) - option->entry.nothing = (void *)NULL; - else - option->entry.trigger = (i3_trigger *)entry; -} - -static void * __RTTI duplicate_i3_option_entry(char type, void * __RTTI entry) -{ - if (NULL == entry) - return NULL; - - if (I3_OPT_SENDER == type || I3_OPT_DESTINATION == type) - return duplicate_i3_addr((i3_addr *) entry); - else if (I3_OPT_TRIGGER_INSERT == type || - I3_OPT_TRIGGER_CHALLENGE == type || - I3_OPT_CONSTRAINT_FAILED == type || - I3_OPT_TRIGGER_ACK == type || - I3_OPT_TRIGGER_REMOVE == type || - I3_OPT_CACHE_ADDR == type || - I3_OPT_CACHE_DEST_ADDR == type || - I3_OPT_CACHE_SHORTCUT_ADDR == type || - I3_OPT_FORCE_CACHE_ADDR == type || - I3_OPT_ROUTE_BROKEN == type) - return duplicate_i3_trigger((i3_trigger *) entry); - else if (I3_OPT_TRIGGER_NOT_PRESENT == type || - I3_OPT_TRIGGER_RATELIMIT == type) - return duplicate_i3_id((ID *) entry); - else { - I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, "duplicate_i3_option: invalid option type\n"); - return NULL; - } -} - -i3_option *duplicate_i3_option(i3_option *option) -{ - i3_option *new_option = alloc_i3_option(); - - new_option->type = option->type; - new_option->entry.trigger = (i3_trigger *) - duplicate_i3_option_entry(option->type, (void *)option->entry.trigger); - - return new_option; -} - -/*************************************************************************** - * free_i3_option - free option data structure - * - * input: - * data structure to be freed - * - ***************************************************************************/ -void free_i3_option(i3_option *option) -{ - switch (option->type) { - case I3_OPT_SENDER: - if (option->entry.ret_addr) - free_i3_addr(option->entry.ret_addr); - break; - case I3_OPT_DESTINATION: - if (option->entry.dst_addr) - free_i3_addr(option->entry.dst_addr); - break; - case I3_OPT_TRIGGER_INSERT: - case I3_OPT_TRIGGER_CHALLENGE: - case I3_OPT_CONSTRAINT_FAILED: - case I3_OPT_TRIGGER_ACK: - case I3_OPT_TRIGGER_REMOVE: - case I3_OPT_CACHE_ADDR: - case I3_OPT_CACHE_DEST_ADDR: - case I3_OPT_CACHE_SHORTCUT_ADDR: - case I3_OPT_FORCE_CACHE_ADDR: - case I3_OPT_ROUTE_BROKEN: - if (option->entry.trigger) - free_i3_trigger(option->entry.trigger); - break; - case I3_OPT_TRIGGER_NOT_PRESENT: - case I3_OPT_TRIGGER_RATELIMIT: - if (option->entry.id) - free_i3_id(option->entry.id); - break; - case I3_OPT_REQUEST_FOR_CACHE: - case I3_OPT_REQUEST_FOR_CACHE_SHORTCUT: - case I3_OPT_REQUEST_FOR_CACHE_SHORTCUT_INDIR: -#if NEWS_INSTRUMENT - case I3_OPT_LOG_PACKET: - case I3_OPT_APPEND_TS: -#endif - break; - default: - I3_PRINT_DEBUG1(I3_DEBUG_LEVEL_MINIMAL, "free_i3_option: invalid option type: %d\n", option->type); - } - free(option); -} - - -i3_option_list *alloc_i3_option_list() -{ - i3_option_list *option_list; - - option_list = (i3_option_list *)malloc(sizeof(i3_option_list)); - if (option_list) { - option_list->head = option_list->tail = NULL; - return option_list; - } - - I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, "alloc_i3_option_list: memory allocation error.\n"); - return NULL; -} - - -void free_i3_option_list(i3_option_list *option_list) -{ - i3_option *option; - - while (option_list->head) { - option = option_list->head; - option_list->head = option_list->head->next; - free_i3_option(option); - } - - free(option_list); -} - - - -/*************************************************************************** - * Purpose: To check if an option is "local" to an i3 node - * or needs to be forwarded along a path - * - * Example: I3_OPT_LOG_PACKET (ie. instrumenting to log packets) - * needs to be forwarded along an i3 path, whereas I3_OPT_SENDER - * is just for this i3 node in case any control mesg is returned - * - ***************************************************************************/ -int is_local_option(i3_option *option) -{ -#ifdef NEWS_INSTRUMENT - if (option->type == I3_OPT_LOG_PACKET || - option->type == I3_OPT_APPEND_TS || - option->type == I3_OPT_REQUEST_FOR_CACHE_SHORTCUT || - option->type == I3_OPT_REQUEST_FOR_CACHE_SHORTCUT_INDIR) { - return FALSE; - } else { - return TRUE; - } -#else - if (option->type == I3_OPT_REQUEST_FOR_CACHE_SHORTCUT || - option->type == I3_OPT_REQUEST_FOR_CACHE_SHORTCUT_INDIR) { - /* this might be associated to another non-local option */ - return FALSE; - } else { - return TRUE; - } -#endif -} - - - -/*************************************************************************** - * Purpose: Returns true if the type of the option is valid - * - **************************************************************************/ -int is_valid_option(i3_option *option) -{ - char type = option->type; - - if (type == I3_OPT_SENDER || - type == I3_OPT_TRIGGER_INSERT || - type == I3_OPT_TRIGGER_CHALLENGE || - type == I3_OPT_CONSTRAINT_FAILED || - type == I3_OPT_TRIGGER_ACK || - type == I3_OPT_TRIGGER_REMOVE || - type == I3_OPT_TRIGGER_NOT_PRESENT || - type == I3_OPT_TRIGGER_RATELIMIT || - type == I3_OPT_REQUEST_FOR_CACHE || - type == I3_OPT_REQUEST_FOR_CACHE_SHORTCUT || - type == I3_OPT_REQUEST_FOR_CACHE_SHORTCUT_INDIR || - type == I3_OPT_ROUTE_BROKEN || - type == I3_OPT_DESTINATION || -#if NEWS_INSTRUMENT - type == I3_OPT_LOG_PACKET || - type == I3_OPT_APPEND_TS || -#endif - type == I3_OPT_CACHE_ADDR || - type == I3_OPT_CACHE_DEST_ADDR || - type == I3_OPT_CACHE_SHORTCUT_ADDR || - type == I3_OPT_FORCE_CACHE_ADDR) - { - return TRUE; - } else { - return FALSE; - } -} - - -/*************************************************************************** - * Purpose: Find an option of a given type in the option list - * - * Return: pointer to option, if option found; NULL otherwise - * - ***************************************************************************/ -i3_option *get_i3_option_from_list(i3_option_list *option_list, int type) -{ - i3_option *o; - - if (option_list == NULL) - return NULL; - - for (o = option_list->head; o; o = o->next) - if (o->type == type) - return o; - return NULL; -} - - -/*************************************************************************** - * Purpose: Remove all the options that should not be forwarded in - * the path, ie. all opts such that is_local_option(opt) is true - * - * Return: 0 if there is nothing left in the option list, 1 otherwise - * - ***************************************************************************/ -int remove_local_i3_options(i3_option_list *option_list) -{ - i3_option *curr, *next, *prev; - - for (prev = 0, curr = option_list->head; curr != 0;) { - next = curr->next; - /* save I3_OPT_SENDER option just in case a non-local option needs it */ - if (is_local_option(curr) && (curr->type != I3_OPT_SENDER)) { - free_i3_option(curr); - - if (NULL == prev) - option_list->head = next; - else - prev->next = next; - } else - prev = curr; - - curr = next; - } - option_list->tail = prev; - - /* check whether there is any non-local option needing I3_OPT_SENDER - * option; if not remove it - * XXX - now check only if I3_OPT_SENDER is the only option; - * need to be changed when more non-local options are added - */ - if ( - option_list && //FIX by Andrei - option_list->head == option_list->tail && - option_list->head && //FIX by Andrei - option_list->head->type == I3_OPT_SENDER - ) { - free_i3_option(option_list->head); - option_list->head = option_list->tail = NULL; - } - - return (NULL != option_list->tail); -} - - -/*************************************************************************** - * Purpose: Remove a option from the option list - * - * Return: 0 if there is nothing left in the option list, 1 otherwise - * - ***************************************************************************/ - -int remove_i3_option_from_list(i3_option_list *option_list, i3_option *opt) -{ - i3_option *o; - - assert(option_list); - - if (option_list->head == opt) { - if (option_list->head == option_list->tail) - /* only option "opt" in the list */ - option_list->tail = NULL; - option_list->head = option_list->head->next; - free_i3_option(opt); - return (NULL != option_list->tail); - } - - for (o = option_list->head; o; o = o->next) { - if (o->next == opt) { - if (opt == option_list->tail) - /* "opt" is the last option in the list */ - option_list->tail = o; - o->next = o->next->next; - free_i3_option(opt); - } - } - - return (NULL != option_list->tail); -} - - -/*************************************************************************** - * append_i3_option - append a new option to the option list - * - * input: - * option_list - option list - * option - option to be added to the option_list - ***************************************************************************/ -void append_i3_option(i3_option_list *option_list, - i3_option *option) -{ - if (!option_list->head) - option_list->head = option_list->tail = option; - else { - option_list->tail->next = option; - option_list->tail = option; - } -} - - -/*************************************************************************** - * pack_i3_option - convert an option data structure in packet format - * - * input: - * p - address of the buffer where the option is to be stored in - * packet format (pre-allocated) - * option - option data structure to be converted in packet format - * - * output: - * length - length of the option in packet format (bytes) - ***************************************************************************/ -void pack_i3_option(char *p, i3_option *option, - unsigned short *length) -{ - unsigned short len; - - p[0] = option->type; - p++; *length = 1; /* skip option's type */ - - switch (option->type) { - case I3_OPT_SENDER: - pack_i3_addr(p, option->entry.ret_addr, &len); - *length += len; - break; - case I3_OPT_DESTINATION: - pack_i3_addr(p, option->entry.dst_addr, &len); - *length += len; - break; - case I3_OPT_TRIGGER_INSERT: - case I3_OPT_TRIGGER_CHALLENGE: - case I3_OPT_CONSTRAINT_FAILED: - case I3_OPT_TRIGGER_ACK: - case I3_OPT_TRIGGER_REMOVE: - case I3_OPT_CACHE_ADDR: - case I3_OPT_CACHE_DEST_ADDR: - case I3_OPT_CACHE_SHORTCUT_ADDR: - case I3_OPT_FORCE_CACHE_ADDR: - case I3_OPT_ROUTE_BROKEN: - pack_i3_trigger(p, option->entry.trigger, &len); - *length += len; - break; - case I3_OPT_TRIGGER_NOT_PRESENT: - case I3_OPT_TRIGGER_RATELIMIT: - pack_i3_id(p, option->entry.id, &len); - *length += len; - break; - case I3_OPT_REQUEST_FOR_CACHE: - case I3_OPT_REQUEST_FOR_CACHE_SHORTCUT: - case I3_OPT_REQUEST_FOR_CACHE_SHORTCUT_INDIR: -#if NEWS_INSTRUMENT - case I3_OPT_LOG_PACKET: - case I3_OPT_APPEND_TS: -#endif - break; - default: - I3_PRINT_DEBUG1(I3_DEBUG_LEVEL_MINIMAL, - "pack_i3_option: invalid address type %d\n", option->type); - } -} - -unsigned short get_i3_option_len(i3_option *option) -{ - unsigned short length; - - length = sizeof(char); /* option type */ - - switch (option->type) { - case I3_OPT_SENDER: - length += get_i3_addr_len(option->entry.ret_addr); - break; - case I3_OPT_DESTINATION: - length += get_i3_addr_len(option->entry.dst_addr); - break; - case I3_OPT_TRIGGER_INSERT: - case I3_OPT_TRIGGER_CHALLENGE: - case I3_OPT_CONSTRAINT_FAILED: - case I3_OPT_TRIGGER_ACK: - case I3_OPT_TRIGGER_REMOVE: - case I3_OPT_CACHE_ADDR: - case I3_OPT_CACHE_DEST_ADDR: - case I3_OPT_CACHE_SHORTCUT_ADDR: - case I3_OPT_FORCE_CACHE_ADDR: - case I3_OPT_ROUTE_BROKEN: - length += get_i3_trigger_len(option->entry.trigger); - break; - case I3_OPT_TRIGGER_NOT_PRESENT: - case I3_OPT_TRIGGER_RATELIMIT: - length += sizeof(ID); - break; - case I3_OPT_REQUEST_FOR_CACHE: - case I3_OPT_REQUEST_FOR_CACHE_SHORTCUT: - case I3_OPT_REQUEST_FOR_CACHE_SHORTCUT_INDIR: -#if NEWS_INSTRUMENT - case I3_OPT_LOG_PACKET: - case I3_OPT_APPEND_TS: -#endif - break; - default: - I3_PRINT_DEBUG1(I3_DEBUG_LEVEL_MINIMAL, "pack_i3_option: invalid address type %d\n",option->type); - } - return length; -} - - -/*************************************************************************** - * unpack_i3_option - allocate an i3 option data structure - * and copy info from packet into it - * - * input: - * p - address where option is stored in packet format - * - * output: - * length - length of the option in packet format (bytes) - * - ***************************************************************************/ -i3_option *unpack_i3_option(char *p, unsigned short *length) -{ - i3_option *option = alloc_i3_option(); - unsigned short len = 0; - - option->type = p[0]; - p++; *length = 1; - - switch (option->type) { - case I3_OPT_SENDER: - option->entry.ret_addr = unpack_i3_addr(p, &len); - p += len; - *length += len; - break; - case I3_OPT_DESTINATION: - option->entry.dst_addr = unpack_i3_addr(p, &len); - p += len; - *length += len; - break; - case I3_OPT_TRIGGER_INSERT: - case I3_OPT_TRIGGER_CHALLENGE: - case I3_OPT_CONSTRAINT_FAILED: - case I3_OPT_TRIGGER_ACK: - case I3_OPT_TRIGGER_REMOVE: - case I3_OPT_CACHE_ADDR: - case I3_OPT_CACHE_DEST_ADDR: - case I3_OPT_CACHE_SHORTCUT_ADDR: - case I3_OPT_FORCE_CACHE_ADDR: - case I3_OPT_ROUTE_BROKEN: - option->entry.trigger = unpack_i3_trigger(p, &len); - *length += len; - break; - case I3_OPT_TRIGGER_NOT_PRESENT: - case I3_OPT_TRIGGER_RATELIMIT: - option->entry.id = unpack_i3_id(p, &len); - *length += len; - break; - case I3_OPT_REQUEST_FOR_CACHE: - case I3_OPT_REQUEST_FOR_CACHE_SHORTCUT: - case I3_OPT_REQUEST_FOR_CACHE_SHORTCUT_INDIR: -#if NEWS_INSTRUMENT - case I3_OPT_LOG_PACKET: - case I3_OPT_APPEND_TS: -#endif - option->entry.nothing = (void *)NULL; - break; - default: - I3_PRINT_DEBUG1(I3_DEBUG_LEVEL_MINIMAL, "unpack_i3_option: invalid address type %d\n", option->type); - } - return option; -} - -/*************************************************************************** - * check_i3_option - check whether i3 option is well-formed - * - * input: - * p - address where option is stored in packet format - * - * return: - * error code; FALSE if no error - - * output: - * length - length of the option in packet format (bytes) - * - ***************************************************************************/ - -int check_i3_option(char *p, unsigned short *length) -{ - unsigned short len = 0; - char option_type = p[0], type; - int rc; - - p++; *length = 1; /* account for option's type */ - - switch (option_type) { - case I3_OPT_SENDER: - case I3_OPT_DESTINATION: - if ((rc = check_i3_addr(p, &len, &type)) != FALSE) - return rc; - *length += len; - break; - case I3_OPT_TRIGGER_INSERT: - case I3_OPT_TRIGGER_CHALLENGE: - case I3_OPT_CONSTRAINT_FAILED: - case I3_OPT_TRIGGER_ACK: - case I3_OPT_TRIGGER_REMOVE: - case I3_OPT_CACHE_ADDR: - case I3_OPT_CACHE_DEST_ADDR: - case I3_OPT_CACHE_SHORTCUT_ADDR: - case I3_OPT_FORCE_CACHE_ADDR: - case I3_OPT_ROUTE_BROKEN: - if ((rc = check_i3_trigger(p, &len)) != FALSE) - return rc; - *length += len; - break; - case I3_OPT_TRIGGER_NOT_PRESENT: - case I3_OPT_TRIGGER_RATELIMIT: - *length += sizeof(ID); - break; - case I3_OPT_REQUEST_FOR_CACHE: - case I3_OPT_REQUEST_FOR_CACHE_SHORTCUT: - case I3_OPT_REQUEST_FOR_CACHE_SHORTCUT_INDIR: -#if NEWS_INSTRUMENT - case I3_OPT_LOG_PACKET: - case I3_OPT_APPEND_TS: -#endif - break; - default: - return I3_ERR_INVALID_OPTION; - } - - return FALSE; -} - - -/*************************************************************************** - * pack_i3_option_list - store a list of options in packet format - * - * input: - * packedbuff - address of the buffer where the option_list is to - * be stored in packet format (pre-allocated) - * option_list - list of options to be stored in packet format - * - * output: - * length - length of the entire list of option in packet format (bytes) - ***************************************************************************/ -void pack_i3_option_list(char *packedbuff, - i3_option_list *option_list, - unsigned short *length) -{ - unsigned short len; - char *p = packedbuff; - i3_option *option; - - p += sizeof(unsigned short); /* skip option list's length field */ - *length = sizeof(unsigned short); /* account for length field */ - - for (option = option_list->head; option; option = option->next) { - len = 0; - pack_i3_option(p, option, &len); - /* set the link flag */ - p += len; - *length += len; - } - len = htons(*length); - memcpy(packedbuff, (char *)&len, sizeof(unsigned short)); -} - -unsigned short get_i3_option_list_len(i3_option_list *option_list) -{ - unsigned short length; - i3_option *option; - - length = sizeof(unsigned short); /* account for option list's length field */ - - for (option = option_list->head; option; option = option->next) { - length += get_i3_option_len(option); - } - - return length; -} - - -/*************************************************************************** - * unpack_i3_option_list - allocate an option list data structure - * and copy info from packet into it - * - * input: - * p - address where the option list is stored in packet format - * - * output: - * length - length of the option list info in packet format (bytes) - * - ***************************************************************************/ -i3_option_list *unpack_i3_option_list(char *p, unsigned short *length) -{ - unsigned short len, len1; - i3_option *option; - i3_option_list *option_list = alloc_i3_option_list(); - - *length = len1 = ntohs(*(unsigned short *)p); /* get option list's length */ - len1 -= sizeof(unsigned short); /* skip option list's length field */ - p += sizeof(unsigned short); - - while (len1) { - option = unpack_i3_option(p, &len); - append_i3_option(option_list, option); - p += len; - len1 -= len; - } - - return option_list; -} - -/*************************************************************************** - * check_i3_option_list - check whether the option list is well formatted - * - * input: - * p - address where the option list is stored in packet format - * - * return: - * error code; FALSE, if no error - * - * output: - * length - length of the option list info in packet format (bytes) - * - ***************************************************************************/ -int check_i3_option_list(char *p, unsigned short *length) -{ - unsigned short len; - int ol_len; - int rc; - - ol_len = ntohs(*(unsigned short *)p); /* get option list's length */ - p += sizeof(unsigned short); - *length = sizeof(unsigned short); - ol_len -= sizeof(unsigned short); /* account for option length */ - - while (ol_len) { - rc = check_i3_option(p, &len); - if (rc != FALSE) - return rc; - p += len; - ol_len -= len; - if (ol_len < 0) - return I3_ERR_INVALID_OPTLIST; - } - - if (ol_len) /* ol_len should be zero */ - return I3_ERR_INVALID_OPTLIST; - - return FALSE; -} - - -/*************************************************************************** - * duplicate_i3_option_list - perform a deep copy - **************************************************************************/ -i3_option_list *duplicate_i3_option_list(i3_option_list *option_list) -{ - i3_option *option, *new_option; - i3_option_list *new_option_list = alloc_i3_option_list(); - - for (option = option_list->head; option; option = option->next) { - new_option = duplicate_i3_option(option); - append_i3_option(new_option_list, new_option); - } - - return new_option_list; -} - - -/******************************************* - ** print i3_option; just for debbuging ** - *******************************************/ -void printf_i3_option(i3_option *option, int indent) -{ - char buf[INDENT_BUF_LEN]; - - memset(buf, ' ', INDENT_BUF_LEN); - buf[indent] = 0; - - printf("%s option type = ", buf); - printf_i3_option_type(option->type); printf("\n"); - - switch (option->type) { - case I3_OPT_SENDER: - printf_i3_addr(option->entry.ret_addr, indent + INDENT_CONST); - break; - case I3_OPT_DESTINATION: - printf_i3_addr(option->entry.dst_addr, indent + INDENT_CONST); - break; - case I3_OPT_TRIGGER_INSERT: - case I3_OPT_TRIGGER_CHALLENGE: - case I3_OPT_CONSTRAINT_FAILED: - case I3_OPT_TRIGGER_ACK: - case I3_OPT_TRIGGER_REMOVE: - case I3_OPT_CACHE_ADDR: - case I3_OPT_CACHE_DEST_ADDR: - case I3_OPT_CACHE_SHORTCUT_ADDR: - case I3_OPT_FORCE_CACHE_ADDR: - case I3_OPT_ROUTE_BROKEN: - printf_i3_trigger(option->entry.trigger, indent + INDENT_CONST); - break; - case I3_OPT_TRIGGER_NOT_PRESENT: - case I3_OPT_TRIGGER_RATELIMIT: - printf_i3_id(option->entry.id, indent + INDENT_CONST); - break; - case I3_OPT_REQUEST_FOR_CACHE: - case I3_OPT_REQUEST_FOR_CACHE_SHORTCUT: - case I3_OPT_REQUEST_FOR_CACHE_SHORTCUT_INDIR: -#if NEWS_INSTRUMENT - case I3_OPT_LOG_PACKET: - case I3_OPT_APPEND_TS: -#endif - break; - default: - I3_PRINT_DEBUG1(I3_DEBUG_LEVEL_MINIMAL, "printf_i3_option: invalid address type %d\n", option->type); - } -} - - -/************************** - ** print i3_option_list ** - **************************/ -void printf_i3_option_list(i3_option_list *option_list, int indent) -{ - i3_option *option; - char buf[INDENT_BUF_LEN]; - - memset(buf, ' ', INDENT_BUF_LEN); - buf[indent] = 0; - - printf("%s option list:\n", buf); - - for (option = option_list->head; option; option = option->next) - printf_i3_option(option, indent + INDENT_CONST); -} - - -void printf_i3_option_type(int option_type) -{ - switch (option_type) { - case I3_OPT_SENDER: - I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, "I3_OPT_SENDER\n"); - break; - case I3_OPT_DESTINATION: - I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, "I3_OPT_DESTINATION"); - break; - case I3_OPT_TRIGGER_INSERT: - I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, "I3_OPT_TRIGGER_INSERT"); - break; - case I3_OPT_TRIGGER_CHALLENGE: - I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, "I3_OPT_TRIGGER_CHALLENG"); - break; - case I3_OPT_CONSTRAINT_FAILED: - I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, "I3_OPT_CONSTRAINT_FAILED"); - break; - case I3_OPT_TRIGGER_ACK: - I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, "I3_OPT_TRIGGER_ACK"); - break; - case I3_OPT_TRIGGER_REMOVE: - I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, "I3_OPT_TRIGGER_REMOVE"); - break; - case I3_OPT_CACHE_ADDR: - I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, "I3_OPT_CACHE_ADDR"); - break; - case I3_OPT_CACHE_DEST_ADDR: - I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, "I3_OPT_CACHE_DEST_ADDR"); - break; - case I3_OPT_CACHE_SHORTCUT_ADDR: - I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, "I3_OPT_CACHE_SHORTCUT_ADDR"); - break; - case I3_OPT_FORCE_CACHE_ADDR: - I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, "I3_OPT_FORCE_CACHE_ADDR"); - break; - case I3_OPT_ROUTE_BROKEN: - I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, "I3_OPT_ROUTE_BROKEN"); - break; - case I3_OPT_TRIGGER_NOT_PRESENT: - I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, "I3_OPT_TRIGGER_NOT_PRESENT"); - break; - case I3_OPT_TRIGGER_RATELIMIT: - I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, "I3_OPT_TRIGGER_RATELIMIT"); - case I3_OPT_REQUEST_FOR_CACHE: - I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, "I3_OPT_REQUEST_FOR_CACHE"); - break; - case I3_OPT_REQUEST_FOR_CACHE_SHORTCUT: - I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, "I3_OPT_REQUEST_FOR_CACHE_SHORTCUT"); - break; - case I3_OPT_REQUEST_FOR_CACHE_SHORTCUT_INDIR: - I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, "I3_OPT_REQUEST_FOR_CACHE_SHORTCUT_INDIR"); - break; - default: - I3_PRINT_DEBUG1(I3_DEBUG_LEVEL_MINIMAL, "%d", option_type); - } -} +/*************************************************************************** +* i3_options.c - description +* ------------------- +* begin : Nov 21 2002 +* email : istoica@xxxxxxxxxxxxxxx +***************************************************************************/ + +#include "i3.h" +#include "i3_fun.h" +#include "i3_debug.h" +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <assert.h> + + +/*************************************************************************** +* alloc_i3_option - allocate i3 option data structure +* +* return: +* pointer to the allocated data structure +***************************************************************************/ +struct i3_option *alloc_i3_option() +{ + struct i3_option *option; + + option = (i3_option *) calloc(1, sizeof(i3_option)); + if (option) { + return option; + } + + I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, "FATAL ERROR: memory allocation error in alloc_i3_option\n"); + return NULL; +} + +/*************************************************************************** +* init_i3_option - initialize i3 option data structure +* +* input: +* option - data structure to be initialized +* type - option type +* entry - option entry, e.g., ret_addr, trigger (pre-allocated) +* +***************************************************************************/ +void init_i3_option(i3_option *option, char type, void *__RTTI entry) +{ + option->type = type; + /* all are pointers; just use one type for assigment */ + if (type == I3_OPT_REQUEST_FOR_CACHE + || type == I3_OPT_REQUEST_FOR_CACHE_SHORTCUT + || type == I3_OPT_REQUEST_FOR_CACHE_SHORTCUT_INDIR +#if NEWS_INSTRUMENT + || type == I3_OPT_LOG_PACKET || type == I3_OPT_APPEND_TS +#endif + ) { + option->entry.nothing = (void *) NULL; + } else { + option->entry.trigger = (i3_trigger *) entry; + } +} + +static void *__RTTI duplicate_i3_option_entry(char type, void *__RTTI entry) +{ + if (NULL == entry) { + return NULL; + } + + if (I3_OPT_SENDER == type || I3_OPT_DESTINATION == type) { + return duplicate_i3_addr((i3_addr *) entry); + } else if (I3_OPT_TRIGGER_INSERT == type || + I3_OPT_TRIGGER_CHALLENGE == type || + I3_OPT_CONSTRAINT_FAILED == type || + I3_OPT_TRIGGER_ACK == type || + I3_OPT_TRIGGER_REMOVE == type || + I3_OPT_CACHE_ADDR == type || + I3_OPT_CACHE_DEST_ADDR == type || + I3_OPT_CACHE_SHORTCUT_ADDR == type || + I3_OPT_FORCE_CACHE_ADDR == type || + I3_OPT_ROUTE_BROKEN == type) { + return duplicate_i3_trigger((i3_trigger *) entry); + } else if (I3_OPT_TRIGGER_NOT_PRESENT == type || + I3_OPT_TRIGGER_RATELIMIT == type) { + return duplicate_i3_id((ID *) entry); + } else { + I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, "duplicate_i3_option: invalid option type\n"); + return NULL; + } +} + +i3_option *duplicate_i3_option(i3_option *option) +{ + i3_option *new_option = alloc_i3_option(); + + new_option->type = option->type; + new_option->entry.trigger = (i3_trigger *) + duplicate_i3_option_entry(option->type, (void *) option->entry.trigger); + + return new_option; +} + +/*************************************************************************** +* free_i3_option - free option data structure +* +* input: +* data structure to be freed +* +***************************************************************************/ +void free_i3_option(i3_option *option) +{ + switch (option->type) { + case I3_OPT_SENDER: + if (option->entry.ret_addr) { + free_i3_addr(option->entry.ret_addr); + } + break; + case I3_OPT_DESTINATION: + if (option->entry.dst_addr) { + free_i3_addr(option->entry.dst_addr); + } + break; + case I3_OPT_TRIGGER_INSERT: + case I3_OPT_TRIGGER_CHALLENGE: + case I3_OPT_CONSTRAINT_FAILED: + case I3_OPT_TRIGGER_ACK: + case I3_OPT_TRIGGER_REMOVE: + case I3_OPT_CACHE_ADDR: + case I3_OPT_CACHE_DEST_ADDR: + case I3_OPT_CACHE_SHORTCUT_ADDR: + case I3_OPT_FORCE_CACHE_ADDR: + case I3_OPT_ROUTE_BROKEN: + if (option->entry.trigger) { + free_i3_trigger(option->entry.trigger); + } + break; + case I3_OPT_TRIGGER_NOT_PRESENT: + case I3_OPT_TRIGGER_RATELIMIT: + if (option->entry.id) { + free_i3_id(option->entry.id); + } + break; + case I3_OPT_REQUEST_FOR_CACHE: + case I3_OPT_REQUEST_FOR_CACHE_SHORTCUT: + case I3_OPT_REQUEST_FOR_CACHE_SHORTCUT_INDIR: +#if NEWS_INSTRUMENT + case I3_OPT_LOG_PACKET: + case I3_OPT_APPEND_TS: +#endif + break; + default: + I3_PRINT_DEBUG1(I3_DEBUG_LEVEL_MINIMAL, "free_i3_option: invalid option type: %d\n", option->type); + } + free(option); +} + +i3_option_list *alloc_i3_option_list() +{ + i3_option_list *option_list; + + option_list = (i3_option_list *) malloc(sizeof(i3_option_list)); + if (option_list) { + option_list->head = option_list->tail = NULL; + return option_list; + } + + I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, "alloc_i3_option_list: memory allocation error.\n"); + return NULL; +} + +void free_i3_option_list(i3_option_list *option_list) +{ + i3_option *option; + + while (option_list->head) { + option = option_list->head; + option_list->head = option_list->head->next; + free_i3_option(option); + } + + free(option_list); +} + +/*************************************************************************** +* Purpose: To check if an option is "local" to an i3 node +* or needs to be forwarded along a path +* +* Example: I3_OPT_LOG_PACKET (ie. instrumenting to log packets) +* needs to be forwarded along an i3 path, whereas I3_OPT_SENDER +* is just for this i3 node in case any control mesg is returned +* +***************************************************************************/ +int is_local_option(i3_option *option) +{ +#ifdef NEWS_INSTRUMENT + if (option->type == I3_OPT_LOG_PACKET || + option->type == I3_OPT_APPEND_TS || + option->type == I3_OPT_REQUEST_FOR_CACHE_SHORTCUT || + option->type == I3_OPT_REQUEST_FOR_CACHE_SHORTCUT_INDIR) { + return FALSE; + } else { + return TRUE; + } +#else + if (option->type == I3_OPT_REQUEST_FOR_CACHE_SHORTCUT || + option->type == I3_OPT_REQUEST_FOR_CACHE_SHORTCUT_INDIR) { + /* this might be associated to another non-local option */ + return FALSE; + } else { + return TRUE; + } +#endif +} + +/*************************************************************************** + * Purpose: Returns true if the type of the option is valid + * + **************************************************************************/ +int is_valid_option(i3_option *option) +{ + char type = option->type; + + if (type == I3_OPT_SENDER || + type == I3_OPT_TRIGGER_INSERT || + type == I3_OPT_TRIGGER_CHALLENGE || + type == I3_OPT_CONSTRAINT_FAILED || + type == I3_OPT_TRIGGER_ACK || + type == I3_OPT_TRIGGER_REMOVE || + type == I3_OPT_TRIGGER_NOT_PRESENT || + type == I3_OPT_TRIGGER_RATELIMIT || + type == I3_OPT_REQUEST_FOR_CACHE || + type == I3_OPT_REQUEST_FOR_CACHE_SHORTCUT || + type == I3_OPT_REQUEST_FOR_CACHE_SHORTCUT_INDIR || + type == I3_OPT_ROUTE_BROKEN || + type == I3_OPT_DESTINATION || +#if NEWS_INSTRUMENT + type == I3_OPT_LOG_PACKET || + type == I3_OPT_APPEND_TS || +#endif + type == I3_OPT_CACHE_ADDR || + type == I3_OPT_CACHE_DEST_ADDR || + type == I3_OPT_CACHE_SHORTCUT_ADDR || + type == I3_OPT_FORCE_CACHE_ADDR) { + return TRUE; + } else { + return FALSE; + } +} + +/*************************************************************************** +* Purpose: Find an option of a given type in the option list +* +* Return: pointer to option, if option found; NULL otherwise +* +***************************************************************************/ +i3_option *get_i3_option_from_list(i3_option_list *option_list, int type) +{ + i3_option *o; + + if (option_list == NULL) { + return NULL; + } + + for (o = option_list->head; o; o = o->next) { + if (o->type == type) { + return o; + } + } + return NULL; +} + +/*************************************************************************** +* Purpose: Remove all the options that should not be forwarded in +* the path, ie. all opts such that is_local_option(opt) is true +* +* Return: 0 if there is nothing left in the option list, 1 otherwise +* +***************************************************************************/ +int remove_local_i3_options(i3_option_list *option_list) +{ + i3_option *curr, *next, *prev; + + for (prev = 0, curr = option_list->head; curr != 0; ) { + next = curr->next; + /* save I3_OPT_SENDER option just in case a non-local option needs it */ + if (is_local_option(curr) && (curr->type != I3_OPT_SENDER)) { + free_i3_option(curr); + + if (NULL == prev) { + option_list->head = next; + } else { + prev->next = next; + } + } else { + prev = curr; + } + + curr = next; + } + option_list->tail = prev; + + /* check whether there is any non-local option needing I3_OPT_SENDER + * option; if not remove it + * XXX - now check only if I3_OPT_SENDER is the only option; + * need to be changed when more non-local options are added + */ + if ( + option_list && //FIX by Andrei + option_list->head == option_list->tail && + option_list->head && //FIX by Andrei + option_list->head->type == I3_OPT_SENDER + ) { + free_i3_option(option_list->head); + option_list->head = option_list->tail = NULL; + } + + return NULL != option_list->tail; +} + +/*************************************************************************** +* Purpose: Remove a option from the option list +* +* Return: 0 if there is nothing left in the option list, 1 otherwise +* +***************************************************************************/ + +int remove_i3_option_from_list(i3_option_list *option_list, i3_option *opt) +{ + i3_option *o; + + assert(option_list); + + if (option_list->head == opt) { + if (option_list->head == option_list->tail) { + /* only option "opt" in the list */ + option_list->tail = NULL; + } + option_list->head = option_list->head->next; + free_i3_option(opt); + return NULL != option_list->tail; + } + + for (o = option_list->head; o; o = o->next) { + if (o->next == opt) { + if (opt == option_list->tail) { + /* "opt" is the last option in the list */ + option_list->tail = o; + } + o->next = o->next->next; + free_i3_option(opt); + } + } + + return NULL != option_list->tail; +} + +/*************************************************************************** +* append_i3_option - append a new option to the option list +* +* input: +* option_list - option list +* option - option to be added to the option_list +***************************************************************************/ +void append_i3_option(i3_option_list *option_list, + i3_option *option) +{ + if (!option_list->head) { + option_list->head = option_list->tail = option; + } else { + option_list->tail->next = option; + option_list->tail = option; + } +} + +/*************************************************************************** +* pack_i3_option - convert an option data structure in packet format +* +* input: +* p - address of the buffer where the option is to be stored in +* packet format (pre-allocated) +* option - option data structure to be converted in packet format +* +* output: +* length - length of the option in packet format (bytes) +***************************************************************************/ +void pack_i3_option(char *p, i3_option *option, + unsigned short *length) +{ + unsigned short len; + + p[0] = option->type; + p++; + *length = 1; /* skip option's type */ + + switch (option->type) { + case I3_OPT_SENDER: + pack_i3_addr(p, option->entry.ret_addr, &len); + *length += len; + break; + case I3_OPT_DESTINATION: + pack_i3_addr(p, option->entry.dst_addr, &len); + *length += len; + break; + case I3_OPT_TRIGGER_INSERT: + case I3_OPT_TRIGGER_CHALLENGE: + case I3_OPT_CONSTRAINT_FAILED: + case I3_OPT_TRIGGER_ACK: + case I3_OPT_TRIGGER_REMOVE: + case I3_OPT_CACHE_ADDR: + case I3_OPT_CACHE_DEST_ADDR: + case I3_OPT_CACHE_SHORTCUT_ADDR: + case I3_OPT_FORCE_CACHE_ADDR: + case I3_OPT_ROUTE_BROKEN: + pack_i3_trigger(p, option->entry.trigger, &len); + *length += len; + break; + case I3_OPT_TRIGGER_NOT_PRESENT: + case I3_OPT_TRIGGER_RATELIMIT: + pack_i3_id(p, option->entry.id, &len); + *length += len; + break; + case I3_OPT_REQUEST_FOR_CACHE: + case I3_OPT_REQUEST_FOR_CACHE_SHORTCUT: + case I3_OPT_REQUEST_FOR_CACHE_SHORTCUT_INDIR: +#if NEWS_INSTRUMENT + case I3_OPT_LOG_PACKET: + case I3_OPT_APPEND_TS: +#endif + break; + default: + I3_PRINT_DEBUG1(I3_DEBUG_LEVEL_MINIMAL, + "pack_i3_option: invalid address type %d\n", option->type); + } +} + +unsigned short get_i3_option_len(i3_option *option) +{ + unsigned short length; + + length = sizeof(char); /* option type */ + + switch (option->type) { + case I3_OPT_SENDER: + length += get_i3_addr_len(option->entry.ret_addr); + break; + case I3_OPT_DESTINATION: + length += get_i3_addr_len(option->entry.dst_addr); + break; + case I3_OPT_TRIGGER_INSERT: + case I3_OPT_TRIGGER_CHALLENGE: + case I3_OPT_CONSTRAINT_FAILED: + case I3_OPT_TRIGGER_ACK: + case I3_OPT_TRIGGER_REMOVE: + case I3_OPT_CACHE_ADDR: + case I3_OPT_CACHE_DEST_ADDR: + case I3_OPT_CACHE_SHORTCUT_ADDR: + case I3_OPT_FORCE_CACHE_ADDR: + case I3_OPT_ROUTE_BROKEN: + length += get_i3_trigger_len(option->entry.trigger); + break; + case I3_OPT_TRIGGER_NOT_PRESENT: + case I3_OPT_TRIGGER_RATELIMIT: + length += sizeof(ID); + break; + case I3_OPT_REQUEST_FOR_CACHE: + case I3_OPT_REQUEST_FOR_CACHE_SHORTCUT: + case I3_OPT_REQUEST_FOR_CACHE_SHORTCUT_INDIR: +#if NEWS_INSTRUMENT + case I3_OPT_LOG_PACKET: + case I3_OPT_APPEND_TS: +#endif + break; + default: + I3_PRINT_DEBUG1(I3_DEBUG_LEVEL_MINIMAL, "pack_i3_option: invalid address type %d\n", option->type); + } + return length; +} + +/*************************************************************************** +* unpack_i3_option - allocate an i3 option data structure +* and copy info from packet into it +* +* input: +* p - address where option is stored in packet format +* +* output: +* length - length of the option in packet format (bytes) +* +***************************************************************************/ +i3_option *unpack_i3_option(char *p, unsigned short *length) +{ + i3_option *option = alloc_i3_option(); + unsigned short len = 0; + + option->type = p[0]; + p++; + *length = 1; + + switch (option->type) { + case I3_OPT_SENDER: + option->entry.ret_addr = unpack_i3_addr(p, &len); + p += len; + *length += len; + break; + case I3_OPT_DESTINATION: + option->entry.dst_addr = unpack_i3_addr(p, &len); + p += len; + *length += len; + break; + case I3_OPT_TRIGGER_INSERT: + case I3_OPT_TRIGGER_CHALLENGE: + case I3_OPT_CONSTRAINT_FAILED: + case I3_OPT_TRIGGER_ACK: + case I3_OPT_TRIGGER_REMOVE: + case I3_OPT_CACHE_ADDR: + case I3_OPT_CACHE_DEST_ADDR: + case I3_OPT_CACHE_SHORTCUT_ADDR: + case I3_OPT_FORCE_CACHE_ADDR: + case I3_OPT_ROUTE_BROKEN: + option->entry.trigger = unpack_i3_trigger(p, &len); + *length += len; + break; + case I3_OPT_TRIGGER_NOT_PRESENT: + case I3_OPT_TRIGGER_RATELIMIT: + option->entry.id = unpack_i3_id(p, &len); + *length += len; + break; + case I3_OPT_REQUEST_FOR_CACHE: + case I3_OPT_REQUEST_FOR_CACHE_SHORTCUT: + case I3_OPT_REQUEST_FOR_CACHE_SHORTCUT_INDIR: +#if NEWS_INSTRUMENT + case I3_OPT_LOG_PACKET: + case I3_OPT_APPEND_TS: +#endif + option->entry.nothing = (void *) NULL; + break; + default: + I3_PRINT_DEBUG1(I3_DEBUG_LEVEL_MINIMAL, "unpack_i3_option: invalid address type %d\n", option->type); + } + return option; +} + +/*************************************************************************** +* check_i3_option - check whether i3 option is well-formed +* +* input: +* p - address where option is stored in packet format +* +* return: +* error code; FALSE if no error +* +* output: +* length - length of the option in packet format (bytes) +* +***************************************************************************/ + +int check_i3_option(char *p, unsigned short *length) +{ + unsigned short len = 0; + char option_type = p[0], type; + int rc; + + p++; + *length = 1; /* account for option's type */ + + switch (option_type) { + case I3_OPT_SENDER: + case I3_OPT_DESTINATION: + if ((rc = check_i3_addr(p, &len, &type)) != FALSE) { + return rc; + } + *length += len; + break; + case I3_OPT_TRIGGER_INSERT: + case I3_OPT_TRIGGER_CHALLENGE: + case I3_OPT_CONSTRAINT_FAILED: + case I3_OPT_TRIGGER_ACK: + case I3_OPT_TRIGGER_REMOVE: + case I3_OPT_CACHE_ADDR: + case I3_OPT_CACHE_DEST_ADDR: + case I3_OPT_CACHE_SHORTCUT_ADDR: + case I3_OPT_FORCE_CACHE_ADDR: + case I3_OPT_ROUTE_BROKEN: + if ((rc = check_i3_trigger(p, &len)) != FALSE) { + return rc; + } + *length += len; + break; + case I3_OPT_TRIGGER_NOT_PRESENT: + case I3_OPT_TRIGGER_RATELIMIT: + *length += sizeof(ID); + break; + case I3_OPT_REQUEST_FOR_CACHE: + case I3_OPT_REQUEST_FOR_CACHE_SHORTCUT: + case I3_OPT_REQUEST_FOR_CACHE_SHORTCUT_INDIR: +#if NEWS_INSTRUMENT + case I3_OPT_LOG_PACKET: + case I3_OPT_APPEND_TS: +#endif + break; + default: + return I3_ERR_INVALID_OPTION; + } + + return FALSE; +} + +/*************************************************************************** +* pack_i3_option_list - store a list of options in packet format +* +* input: +* packedbuff - address of the buffer where the option_list is to +* be stored in packet format (pre-allocated) +* option_list - list of options to be stored in packet format +* +* output: +* length - length of the entire list of option in packet format (bytes) +***************************************************************************/ +void pack_i3_option_list(char *packedbuff, + i3_option_list *option_list, + unsigned short *length) +{ + unsigned short len; + char *p = packedbuff; + i3_option *option; + + p += sizeof(unsigned short); /* skip option list's length field */ + *length = sizeof(unsigned short); /* account for length field */ + + for (option = option_list->head; option; option = option->next) { + len = 0; + pack_i3_option(p, option, &len); + /* set the link flag */ + p += len; + *length += len; + } + len = htons(*length); + memcpy(packedbuff, (char *) &len, sizeof(unsigned short)); +} + +unsigned short get_i3_option_list_len(i3_option_list *option_list) +{ + unsigned short length; + i3_option *option; + + length = sizeof(unsigned short); /* account for option list's length field */ + + for (option = option_list->head; option; option = option->next) { + length += get_i3_option_len(option); + } + + return length; +} + +/*************************************************************************** +* unpack_i3_option_list - allocate an option list data structure +* and copy info from packet into it +* +* input: +* p - address where the option list is stored in packet format +* +* output: +* length - length of the option list info in packet format (bytes) +* +***************************************************************************/ +i3_option_list *unpack_i3_option_list(char *p, unsigned short *length) +{ + unsigned short len, len1; + i3_option *option; + i3_option_list *option_list = alloc_i3_option_list(); + + *length = len1 = ntohs(*(unsigned short *) p); /* get option list's length */ + len1 -= sizeof(unsigned short); /* skip option list's length field */ + p += sizeof(unsigned short); + + while (len1) { + option = unpack_i3_option(p, &len); + append_i3_option(option_list, option); + p += len; + len1 -= len; + } + + return option_list; +} + +/*************************************************************************** +* check_i3_option_list - check whether the option list is well formatted +* +* input: +* p - address where the option list is stored in packet format +* +* return: +* error code; FALSE, if no error +* +* output: +* length - length of the option list info in packet format (bytes) +* +***************************************************************************/ +int check_i3_option_list(char *p, unsigned short *length) +{ + unsigned short len; + int ol_len; + int rc; + + ol_len = ntohs(*(unsigned short *) p); /* get option list's length */ + p += sizeof(unsigned short); + *length = sizeof(unsigned short); + ol_len -= sizeof(unsigned short); /* account for option length */ + + while (ol_len) { + rc = check_i3_option(p, &len); + if (rc != FALSE) { + return rc; + } + p += len; + ol_len -= len; + if (ol_len < 0) { + return I3_ERR_INVALID_OPTLIST; + } + } + + if (ol_len) { /* ol_len should be zero */ + return I3_ERR_INVALID_OPTLIST; + } + + return FALSE; +} + +/*************************************************************************** + * duplicate_i3_option_list - perform a deep copy + **************************************************************************/ +i3_option_list *duplicate_i3_option_list(i3_option_list *option_list) +{ + i3_option *option, *new_option; + i3_option_list *new_option_list = alloc_i3_option_list(); + + for (option = option_list->head; option; option = option->next) { + new_option = duplicate_i3_option(option); + append_i3_option(new_option_list, new_option); + } + + return new_option_list; +} + +/******************************************* +** print i3_option; just for debbuging ** +*******************************************/ +void printf_i3_option(i3_option *option, int indent) +{ + char buf[INDENT_BUF_LEN]; + + memset(buf, ' ', INDENT_BUF_LEN); + buf[indent] = 0; + + printf("%s option type = ", buf); + printf_i3_option_type(option->type); + printf("\n"); + + switch (option->type) { + case I3_OPT_SENDER: + printf_i3_addr(option->entry.ret_addr, indent + INDENT_CONST); + break; + case I3_OPT_DESTINATION: + printf_i3_addr(option->entry.dst_addr, indent + INDENT_CONST); + break; + case I3_OPT_TRIGGER_INSERT: + case I3_OPT_TRIGGER_CHALLENGE: + case I3_OPT_CONSTRAINT_FAILED: + case I3_OPT_TRIGGER_ACK: + case I3_OPT_TRIGGER_REMOVE: + case I3_OPT_CACHE_ADDR: + case I3_OPT_CACHE_DEST_ADDR: + case I3_OPT_CACHE_SHORTCUT_ADDR: + case I3_OPT_FORCE_CACHE_ADDR: + case I3_OPT_ROUTE_BROKEN: + printf_i3_trigger(option->entry.trigger, indent + INDENT_CONST); + break; + case I3_OPT_TRIGGER_NOT_PRESENT: + case I3_OPT_TRIGGER_RATELIMIT: + printf_i3_id(option->entry.id, indent + INDENT_CONST); + break; + case I3_OPT_REQUEST_FOR_CACHE: + case I3_OPT_REQUEST_FOR_CACHE_SHORTCUT: + case I3_OPT_REQUEST_FOR_CACHE_SHORTCUT_INDIR: +#if NEWS_INSTRUMENT + case I3_OPT_LOG_PACKET: + case I3_OPT_APPEND_TS: +#endif + break; + default: + I3_PRINT_DEBUG1(I3_DEBUG_LEVEL_MINIMAL, "printf_i3_option: invalid address type %d\n", option->type); + } +} + +/************************** +** print i3_option_list ** +**************************/ +void printf_i3_option_list(i3_option_list *option_list, int indent) +{ + i3_option *option; + char buf[INDENT_BUF_LEN]; + + memset(buf, ' ', INDENT_BUF_LEN); + buf[indent] = 0; + + printf("%s option list:\n", buf); + + for (option = option_list->head; option; option = option->next) { + printf_i3_option(option, indent + INDENT_CONST); + } +} + +void printf_i3_option_type(int option_type) +{ + switch (option_type) { + case I3_OPT_SENDER: + I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, "I3_OPT_SENDER\n"); + break; + case I3_OPT_DESTINATION: + I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, "I3_OPT_DESTINATION"); + break; + case I3_OPT_TRIGGER_INSERT: + I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, "I3_OPT_TRIGGER_INSERT"); + break; + case I3_OPT_TRIGGER_CHALLENGE: + I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, "I3_OPT_TRIGGER_CHALLENG"); + break; + case I3_OPT_CONSTRAINT_FAILED: + I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, "I3_OPT_CONSTRAINT_FAILED"); + break; + case I3_OPT_TRIGGER_ACK: + I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, "I3_OPT_TRIGGER_ACK"); + break; + case I3_OPT_TRIGGER_REMOVE: + I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, "I3_OPT_TRIGGER_REMOVE"); + break; + case I3_OPT_CACHE_ADDR: + I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, "I3_OPT_CACHE_ADDR"); + break; + case I3_OPT_CACHE_DEST_ADDR: + I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, "I3_OPT_CACHE_DEST_ADDR"); + break; + case I3_OPT_CACHE_SHORTCUT_ADDR: + I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, "I3_OPT_CACHE_SHORTCUT_ADDR"); + break; + case I3_OPT_FORCE_CACHE_ADDR: + I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, "I3_OPT_FORCE_CACHE_ADDR"); + break; + case I3_OPT_ROUTE_BROKEN: + I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, "I3_OPT_ROUTE_BROKEN"); + break; + case I3_OPT_TRIGGER_NOT_PRESENT: + I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, "I3_OPT_TRIGGER_NOT_PRESENT"); + break; + case I3_OPT_TRIGGER_RATELIMIT: + I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, "I3_OPT_TRIGGER_RATELIMIT"); + case I3_OPT_REQUEST_FOR_CACHE: + I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, "I3_OPT_REQUEST_FOR_CACHE"); + break; + case I3_OPT_REQUEST_FOR_CACHE_SHORTCUT: + I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, "I3_OPT_REQUEST_FOR_CACHE_SHORTCUT"); + break; + case I3_OPT_REQUEST_FOR_CACHE_SHORTCUT_INDIR: + I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, "I3_OPT_REQUEST_FOR_CACHE_SHORTCUT_INDIR"); + break; + default: + I3_PRINT_DEBUG1(I3_DEBUG_LEVEL_MINIMAL, "%d", option_type); + } +} === modified file 'i3/i3/i3_options.h' --- i3/i3/i3_options.h 2010-01-06 22:17:32 +0000 +++ i3/i3/i3_options.h 2010-02-11 11:49:47 +0000 @@ -1,41 +1,41 @@ -/*************************************************************************** - i3_options.h - description - ------------------- - begin : Fre Jun 20 2003 - copyright : (C) 2003 by klaus - email : wehrle@xxxxxxxxxxxxxxxxx - ***************************************************************************/ - -#ifndef I3_OPTIONS_H -#define I3_OPTIONS_H - -/* functions implemented in i3_options.c */ -i3_option *alloc_i3_option(void); -void init_i3_option(i3_option *option, char type, void *entry); -void free_i3_option(i3_option *option); -int is_local_option(i3_option *option); -int is_valid_option(i3_option *option); -i3_option_list *alloc_i3_option_list(void); -void free_i3_option_list(i3_option_list *option_list); -i3_option *get_i3_option_from_list(i3_option_list *option_list, int type); -int remove_local_i3_options(i3_option_list *option_list); -int remove_i3_option_from_list(i3_option_list *option_list, i3_option *opt); - -void append_i3_option(i3_option_list *option_list, - i3_option *option); -void pack_i3_option(char *packedbuff, i3_option *option, - unsigned short *length); -unsigned short get_i3_option_len(i3_option *option); -i3_option *unpack_i3_option(char *p, unsigned short *length); -int check_i3_option(char *p, unsigned short *length); -int sizeof_i3_option(char *p); -void pack_i3_option_list(char *p, i3_option_list *option_list, - unsigned short *length); -unsigned short get_i3_option_list_len(i3_option_list *option_list); -i3_option_list *unpack_i3_option_list(char *p, unsigned short *length); -int check_i3_option_list(char *p, unsigned short *length); -i3_option_list *duplicate_i3_option_list(i3_option_list *opt_list); -void printf_i3_option(i3_option *option, int intend); -void printf_i3_option_list(i3_option_list *option_list, int intend); -void printf_i3_option_type(int option_type); -#endif +/*************************************************************************** +* i3_options.h - description +* ------------------- +* begin : Fre Jun 20 2003 +* copyright : (C) 2003 by klaus +* email : wehrle@xxxxxxxxxxxxxxxxx +***************************************************************************/ + +#ifndef I3_OPTIONS_H +#define I3_OPTIONS_H + +/* functions implemented in i3_options.c */ +i3_option *alloc_i3_option(void); +void init_i3_option(i3_option *option, char type, void *entry); +void free_i3_option(i3_option *option); +int is_local_option(i3_option *option); +int is_valid_option(i3_option *option); +i3_option_list *alloc_i3_option_list(void); +void free_i3_option_list(i3_option_list *option_list); +i3_option *get_i3_option_from_list(i3_option_list *option_list, int type); +int remove_local_i3_options(i3_option_list *option_list); +int remove_i3_option_from_list(i3_option_list *option_list, i3_option *opt); + +void append_i3_option(i3_option_list *option_list, + i3_option *option); +void pack_i3_option(char *packedbuff, i3_option *option, + unsigned short *length); +unsigned short get_i3_option_len(i3_option *option); +i3_option *unpack_i3_option(char *p, unsigned short *length); +int check_i3_option(char *p, unsigned short *length); +int sizeof_i3_option(char *p); +void pack_i3_option_list(char *p, i3_option_list *option_list, + unsigned short *length); +unsigned short get_i3_option_list_len(i3_option_list *option_list); +i3_option_list *unpack_i3_option_list(char *p, unsigned short *length); +int check_i3_option_list(char *p, unsigned short *length); +i3_option_list *duplicate_i3_option_list(i3_option_list *opt_list); +void printf_i3_option(i3_option *option, int intend); +void printf_i3_option_list(i3_option_list *option_list, int intend); +void printf_i3_option_type(int option_type); +#endif === modified file 'i3/i3/i3_ping.c' --- i3/i3/i3_ping.c 2009-12-11 22:49:11 +0000 +++ i3/i3/i3_ping.c 2010-02-11 11:49:47 +0000 @@ -12,79 +12,77 @@ #define MAX_PACKET_SIZE 2000 /* packet offsets for seq and time */ -#define i3_ping_pkt_seq_offset(p) ((p)+1) -#define i3_ping_pkt_time_offset(p) ((p)+3) +#define i3_ping_pkt_seq_offset(p) ((p) + 1) +#define i3_ping_pkt_time_offset(p) ((p) + 3) /* True if the packet is a request to the i3 server to echo the pkt */ char is_i3_echo_request(char *p) { - return (((*p) & I3_PING_PKT) == 1); + return ((*p) & I3_PING_PKT) == 1; } - /* Echo request to an i3 server with addr and port */ void i3_echo_request(nw_skt_t fd, uint32_t addr, uint16_t port, uint16_t seq) { struct sockaddr_in to_addr; int rc; char p[ECHO_PACKET_SIZE]; - + memset((void *) &to_addr, 0, sizeof(struct sockaddr_in)); - to_addr.sin_family = AF_INET; + to_addr.sin_family = AF_INET; to_addr.sin_addr.s_addr = htonl(addr); - to_addr.sin_port = htons(port); + to_addr.sin_port = htons(port); - p[0] = I3_PING_PKT; // ping packet - hnputs(i3_ping_pkt_seq_offset(p), seq); // seq number - hnput64(i3_ping_pkt_time_offset(p), wall_time()); // curr time + p[0] = I3_PING_PKT; // ping packet + hnputs(i3_ping_pkt_seq_offset(p), seq); // seq number + hnput64(i3_ping_pkt_time_offset(p), wall_time()); // curr time // TODO: Possible problem rc = sendto(fd, p, ECHO_PACKET_SIZE, 0, - (struct sockaddr *)&to_addr, sizeof(to_addr)); - if (rc < 0) + (struct sockaddr *) &to_addr, sizeof(to_addr)); + if (rc < 0) { perror("Echo request"); - + } } - /* Echo reply (by i3_server back to monitor) */ void i3_echo_reply(nw_skt_t fd, char *p, int len, struct sockaddr_in *addr) { struct sockaddr_in to_addr; int rc; - + memset((void *) &to_addr, 0, sizeof(struct sockaddr_in)); - to_addr.sin_family = AF_INET; + to_addr.sin_family = AF_INET; to_addr.sin_addr.s_addr = htonl(addr->sin_addr.s_addr); - to_addr.sin_port = htons(addr->sin_port); + to_addr.sin_port = htons(addr->sin_port); - rc = sendto(fd, p, len, 0, (struct sockaddr *)&to_addr, sizeof(to_addr)); - if (rc < 0) - perror("Echo reply"); + rc = sendto(fd, p, len, 0, (struct sockaddr *) &to_addr, sizeof(to_addr)); + if (rc < 0) { + perror("Echo reply"); + } } - /* Receive echo reply */ int recv_i3_echo_reply(nw_skt_t fd, uint32_t *addr, uint16_t *port, - uint16_t *seq, uint64_t *rtt) + uint16_t *seq, uint64_t *rtt) { static char buf[MAX_PACKET_SIZE]; struct sockaddr_in saddr; int len = sizeof(struct sockaddr_in); int rc; - - rc = recvfrom(fd, buf, MAX_PACKET_SIZE, 0, (struct sockaddr *)&saddr, (socklen_t *) &len); + + rc = recvfrom(fd, buf, MAX_PACKET_SIZE, 0, (struct sockaddr *) &saddr, (socklen_t *) &len); if (rc < 0) { - perror("recvfrom"); - return -1; + perror("recvfrom"); + return -1; } if (I3_PING_PKT != buf[0]) { - return -1; + return -1; } *addr = ntohl(saddr.sin_addr.s_addr); *port = ntohs(saddr.sin_port); - *seq = nhgets(i3_ping_pkt_seq_offset(buf)); - *rtt = wall_time() - nhget64(i3_ping_pkt_time_offset(buf)); + *seq = nhgets(i3_ping_pkt_seq_offset(buf)); + *rtt = wall_time() - nhget64(i3_ping_pkt_time_offset(buf)); return 1; } === modified file 'i3/i3/i3_ping.h' --- i3/i3/i3_ping.h 2009-12-11 22:49:11 +0000 +++ i3/i3/i3_ping.h 2010-02-11 11:49:47 +0000 @@ -11,9 +11,9 @@ #endif void i3_echo_reply(nw_skt_t fd, char *p, int len, struct sockaddr_in *addr); -void i3_echo_request(nw_skt_t fd, uint32_t addr, uint16_t port, uint16_t seq); +void i3_echo_request(nw_skt_t fd, uint32_t addr, uint16_t port, uint16_t seq); int recv_i3_echo_reply(nw_skt_t fd, uint32_t *addr, uint16_t *port, - uint16_t *seq, uint64_t *rtt); + uint16_t *seq, uint64_t *rtt); char is_i3_echo_request(char *p); #endif === modified file 'i3/i3/i3_stack.c' --- i3/i3/i3_stack.c 2009-12-11 22:49:11 +0000 +++ i3/i3/i3_stack.c 2010-02-11 11:49:47 +0000 @@ -1,249 +1,248 @@ -/*************************************************************************** - i3_stack.c - description - ------------------- - begin : Nov 20 2002 - email : istoica@xxxxxxxxxxxxxxx - ***************************************************************************/ - -#include "i3.h" -#include "i3_fun.h" -#include "i3_debug.h" -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <assert.h> - -/*************************************************************************** - * alloc_i3_stack - allocate a stack data structure - * - * return: - * pointer to the allocated stack - ***************************************************************************/ - -i3_stack *alloc_i3_stack() -{ - i3_stack *stack; - - stack = (i3_stack *)malloc(sizeof(i3_stack)); - if (stack) { - stack->ids = NULL; - return stack; - } - I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL,"alloc_i3_stack: memory allocation error.\n"); - return NULL; -} - - -/*************************************************************************** - * alloc_i3_stack - allocate a stack data structure, and initialize - * its fields - * - * return: - * pointer to the allocated stack - ***************************************************************************/ - -void init_i3_stack(i3_stack *s, ID *ids, int len) -{ - s->len = len; - s->ids = (ID *)malloc(sizeof(ID)*len); - if (s->ids) { - memcpy((char *)s->ids, ids, sizeof(ID)*len); - return; - } - - I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL,"init_i3_stack: memory allocation error.\n"); -} - -void init_i3_stack2(i3_stack *s, ID **ids, int len) -{ - int i; - - s->len = len; - s->ids = (ID *)malloc(sizeof(ID)*len); - - if (s->ids) { - for (i = 0; i < len; i++) - memcpy((char *)s->ids, ids[i], sizeof(ID)); - return; - } - - I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL,"init_i3_stack2: memory allocation error.\n"); -} - - -/*************************************************************************** - * free_i3_stack - free stack data structure including its list of IDs - * - * input: - * stack to be freed - ***************************************************************************/ - -void free_i3_stack(i3_stack *stack) -{ - if (stack->ids) - free(stack->ids); - free(stack); -} - - -/*************************************************************************** - * duplicate_i3_stack - create a replica of stack s - * - * input: - * s - stack to be duplicated - * - * return: - * replica of s - ***************************************************************************/ - -i3_stack *duplicate_i3_stack(i3_stack *s) -{ - i3_stack *snew = alloc_i3_stack(); - - snew->len = s->len; - if ((snew->ids = (ID *)malloc(sizeof(ID)*s->len))) { - memcpy((char *)snew->ids, (char *)s->ids, sizeof(ID)*s->len); - return snew; - } - - I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL,"init_i3_stack: memory allocation error.\n"); - return NULL; -} - - - - -/*************************************************************************** - * pack_i3_stack - convert a stack data structure in packet format - * - * input: - * p - address of the buffer where the stack is to be stored in - * packet format (the buffer is pre-allocated) - * stack - stack to be converted in packet format - * - * output: - * length - length of the stack in packet format - ***************************************************************************/ - -void pack_i3_stack(char *p, i3_stack *stack, unsigned short *length) -{ - int i; - int num_ids; - - num_ids = (stack ? stack->len : 0); - - *p = (*p & 0xf0) + num_ids; /* init stack length */ - *length = sizeof(char); p += sizeof(char); /* skip stack len */ - - if (!num_ids) return; /* no stack to pack */ - - for (i = 0; i < num_ids; i++) { - memcpy(p, (char *)&stack->ids[i].x, sizeof(ID)); - *length += sizeof(ID); p += sizeof(ID); - } -} - -unsigned short get_i3_stack_len(i3_stack *stack) -{ - int num_ids; - - num_ids = (stack ? stack->len : 0); - - return (unsigned short) (sizeof(char) + num_ids*sizeof(ID)); -} - - -/*************************************************************************** - * unpack_i3_stack - copy stack info from packet to a stack - * data structure - * - * input: - * p - address where stack is stored in packet format - * - * return: - * stack data structure - * - * output: - * length - length of the stack info in packet format - * - ***************************************************************************/ - -i3_stack *unpack_i3_stack(char *p, unsigned short *length) -{ - int i, len; - i3_stack *stack; - - len = *p & 0xf; - - if (!len) { - /* there is no stack */ - *length = sizeof(char); - return NULL; - } - - stack = alloc_i3_stack(); - stack->len = len; - *length = sizeof(char); - p += sizeof(char); /* skip stack len field */ - - if (!(stack->ids = (ID*)malloc(stack->len*sizeof(ID)))) - panic("unpack_i3_stack: memory allocation error!\n"); - - for (i = 0; i < stack->len; i++) { - memcpy((char *)&stack->ids[i].x, p, sizeof(ID)); - *length += sizeof(ID); p += sizeof(ID); - } - - return stack; -} - - -/*************************************************************************** - * check_i3_stack - check i3_stack whether is well-formed - * - * input: - * p - address where stack is stored in packet format - * - * return: - * error code; FALSE if no error - * - * output: - * length - length of the stack info in packet format - * - ***************************************************************************/ - -int check_i3_stack(char *p, unsigned short *length) -{ - int len = *p & 0xf; - - *length = (int) (sizeof(char) + len*sizeof(ID)); - return FALSE; -} - - -/************************************* - ** print i3_stack; just for test ** - *************************************/ - -void printf_i3_stack(i3_stack *stack, int indent) -{ - char buf[INDENT_BUF_LEN]; - int i; - uint k; - - memset(buf, ' ', INDENT_BUF_LEN); - buf[indent] = 0; - - printf("%s stack:\n", buf); - - if (!stack) - return; - - for (i = 0; i < stack->len; i++) { - printf("%s id(%u) = ", buf, i); - for (k = 0; k < sizeof(ID); k++) - printf("%x.", (int)(stack->ids[i].x[k])); - printf("\n"); - } -} - +/*************************************************************************** +* i3_stack.c - description +* ------------------- +* begin : Nov 20 2002 +* email : istoica@xxxxxxxxxxxxxxx +***************************************************************************/ + +#include "i3.h" +#include "i3_fun.h" +#include "i3_debug.h" +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <assert.h> + +/*************************************************************************** +* alloc_i3_stack - allocate a stack data structure +* +* return: +* pointer to the allocated stack +***************************************************************************/ + +i3_stack *alloc_i3_stack() +{ + i3_stack *stack; + + stack = (i3_stack *) malloc(sizeof(i3_stack)); + if (stack) { + stack->ids = NULL; + return stack; + } + I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, "alloc_i3_stack: memory allocation error.\n"); + return NULL; +} + +/*************************************************************************** +* alloc_i3_stack - allocate a stack data structure, and initialize +* its fields +* +* return: +* pointer to the allocated stack +***************************************************************************/ + +void init_i3_stack(i3_stack *s, ID *ids, int len) +{ + s->len = len; + s->ids = (ID *) malloc(sizeof(ID) * len); + if (s->ids) { + memcpy((char *) s->ids, ids, sizeof(ID) * len); + return; + } + + I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, "init_i3_stack: memory allocation error.\n"); +} + +void init_i3_stack2(i3_stack *s, ID **ids, int len) +{ + int i; + + s->len = len; + s->ids = (ID *) malloc(sizeof(ID) * len); + + if (s->ids) { + for (i = 0; i < len; i++) { + memcpy((char *) s->ids, ids[i], sizeof(ID)); + } + return; + } + + I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, "init_i3_stack2: memory allocation error.\n"); +} + +/*************************************************************************** +* free_i3_stack - free stack data structure including its list of IDs +* +* input: +* stack to be freed +***************************************************************************/ + +void free_i3_stack(i3_stack *stack) +{ + if (stack->ids) { + free(stack->ids); + } + free(stack); +} + +/*************************************************************************** +* duplicate_i3_stack - create a replica of stack s +* +* input: +* s - stack to be duplicated +* +* return: +* replica of s +***************************************************************************/ + +i3_stack *duplicate_i3_stack(i3_stack *s) +{ + i3_stack *snew = alloc_i3_stack(); + + snew->len = s->len; + if ((snew->ids = (ID *) malloc(sizeof(ID) * s->len))) { + memcpy((char *) snew->ids, (char *) s->ids, sizeof(ID) * s->len); + return snew; + } + + I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, "init_i3_stack: memory allocation error.\n"); + return NULL; +} + +/*************************************************************************** +* pack_i3_stack - convert a stack data structure in packet format +* +* input: +* p - address of the buffer where the stack is to be stored in +* packet format (the buffer is pre-allocated) +* stack - stack to be converted in packet format +* +* output: +* length - length of the stack in packet format +***************************************************************************/ + +void pack_i3_stack(char *p, i3_stack *stack, unsigned short *length) +{ + int i; + int num_ids; + + num_ids = (stack ? stack->len : 0); + + *p = (*p & 0xf0) + num_ids; /* init stack length */ + *length = sizeof(char); + p += sizeof(char); /* skip stack len */ + + if (!num_ids) { + return; /* no stack to pack */ + } + for (i = 0; i < num_ids; i++) { + memcpy(p, (char *) &stack->ids[i].x, sizeof(ID)); + *length += sizeof(ID); + p += sizeof(ID); + } +} + +unsigned short get_i3_stack_len(i3_stack *stack) +{ + int num_ids; + + num_ids = (stack ? stack->len : 0); + + return (unsigned short) (sizeof(char) + num_ids * sizeof(ID)); +} + +/*************************************************************************** +* unpack_i3_stack - copy stack info from packet to a stack +* data structure +* +* input: +* p - address where stack is stored in packet format +* +* return: +* stack data structure +* +* output: +* length - length of the stack info in packet format +* +***************************************************************************/ + +i3_stack *unpack_i3_stack(char *p, unsigned short *length) +{ + int i, len; + i3_stack *stack; + + len = *p & 0xf; + + if (!len) { + /* there is no stack */ + *length = sizeof(char); + return NULL; + } + + stack = alloc_i3_stack(); + stack->len = len; + *length = sizeof(char); + p += sizeof(char); /* skip stack len field */ + + if (!(stack->ids = (ID *) malloc(stack->len * sizeof(ID)))) { + panic("unpack_i3_stack: memory allocation error!\n"); + } + + for (i = 0; i < stack->len; i++) { + memcpy((char *) &stack->ids[i].x, p, sizeof(ID)); + *length += sizeof(ID); + p += sizeof(ID); + } + + return stack; +} + +/*************************************************************************** +* check_i3_stack - check i3_stack whether is well-formed +* +* input: +* p - address where stack is stored in packet format +* +* return: +* error code; FALSE if no error +* +* output: +* length - length of the stack info in packet format +* +***************************************************************************/ + +int check_i3_stack(char *p, unsigned short *length) +{ + int len = *p & 0xf; + + *length = (int) (sizeof(char) + len * sizeof(ID)); + return FALSE; +} + +/************************************* +** print i3_stack; just for test ** +*************************************/ + +void printf_i3_stack(i3_stack *stack, int indent) +{ + char buf[INDENT_BUF_LEN]; + int i; + uint k; + + memset(buf, ' ', INDENT_BUF_LEN); + buf[indent] = 0; + + printf("%s stack:\n", buf); + + if (!stack) { + return; + } + + for (i = 0; i < stack->len; i++) { + printf("%s id(%u) = ", buf, i); + for (k = 0; k < sizeof(ID); k++) { + printf("%x.", (int) (stack->ids[i].x[k])); + } + printf("\n"); + } +} === modified file 'i3/i3/i3_stack.h' --- i3/i3/i3_stack.h 2010-01-06 22:17:32 +0000 +++ i3/i3/i3_stack.h 2010-02-11 11:49:47 +0000 @@ -1,26 +1,26 @@ -/*************************************************************************** - i3_stack.h - description - ------------------- - begin : Fre Jun 20 2003 - copyright : (C) 2003 by klaus - email : wehrle@xxxxxxxxxxxxxxxxx - ***************************************************************************/ - -#ifndef I3_STACK_H -#define I3_STACK_H - -/* functions implemented in i3_stack.c */ -i3_stack *alloc_i3_stack(void); -void init_i3_stack(i3_stack *s, ID *ids, int len); -void init_i3_stack2(i3_stack *s, ID **ids, int len); -void free_i3_stack(i3_stack *stack); -void pack_i3_stack(char *packedstack, i3_stack *stack, - unsigned short *length); -unsigned short get_i3_stack_len(i3_stack *stack); -i3_stack *unpack_i3_stack(char *p, unsigned short *length); -int check_i3_stack(char *p, unsigned short *length); -void printf_i3_stack(i3_stack *stack, int intend); -i3_stack *duplicate_i3_stack(i3_stack *s); - - -#endif +/*************************************************************************** +* i3_stack.h - description +* ------------------- +* begin : Fre Jun 20 2003 +* copyright : (C) 2003 by klaus +* email : wehrle@xxxxxxxxxxxxxxxxx +***************************************************************************/ + +#ifndef I3_STACK_H +#define I3_STACK_H + +/* functions implemented in i3_stack.c */ +i3_stack *alloc_i3_stack(void); +void init_i3_stack(i3_stack *s, ID *ids, int len); +void init_i3_stack2(i3_stack *s, ID **ids, int len); +void free_i3_stack(i3_stack *stack); +void pack_i3_stack(char *packedstack, i3_stack *stack, + unsigned short *length); +unsigned short get_i3_stack_len(i3_stack *stack); +i3_stack *unpack_i3_stack(char *p, unsigned short *length); +int check_i3_stack(char *p, unsigned short *length); +void printf_i3_stack(i3_stack *stack, int intend); +i3_stack *duplicate_i3_stack(i3_stack *s); + + +#endif === modified file 'i3/i3/i3_tcp_fns.c' --- i3/i3/i3_tcp_fns.c 2009-12-29 15:10:11 +0000 +++ i3/i3/i3_tcp_fns.c 2010-02-11 11:49:47 +0000 @@ -1,87 +1,87 @@ -#include "i3_tcp_fns.h" -#include "../utils/byteorder.h" -#include "i3_debug.h" - -#include <stdio.h> -#include <assert.h> -#include <sys/types.h> -#include "../utils/netwrap.h" - -/* Purpose: Send i3 data on TCP socket - * Note: To avoid copying of packets, the two sends are performed */ -int send_tcp(char *p, int len, nw_skt_t fd) -{ - char header[TCP_I3_HEADER_SIZE]; - - - /* Send header */ - header[0] = TCP_I3_HEADER_MAGIC; - hnputs(header + 1, (uint16_t) len); - - if (send(fd, header, TCP_I3_HEADER_SIZE, 0) != TCP_I3_HEADER_SIZE) { - perror("TCP header send"); - return -1; - } - - /* Send rest of the packet */ - if (send(fd, p, len, 0) < len) { - perror("TCP Send"); - return -1; - } - - return len; -} - -/* Purpose: Recv i3 data on TCP socket */ -#define MAX_ATTEMPTS 10 -int recv_tcp(char *p, int len, nw_skt_t fd) -{ - int recv_len, pkt_size = 0, total_recv_len = 0, num_attempts = 0; - - if (fd < 0) { - //TODO XXX Fix this.. - I3_PRINT_DEBUG1 (I3_DEBUG_LEVEL_VERBOSE, "invalid fd = %d\n",fd); - return -1; - } - - /* recv header */ - recv_len = recv(fd, p, TCP_I3_HEADER_SIZE, 0); - if (recv_len < 0) { - perror("TCP header recv"); - fprintf (stderr, " on fd %d\n\n", fd); - nw_close (fd); - return recv_len; - } - - /* recv rest of the packet */ - if (recv_len > 0) { - if( (TCP_I3_HEADER_MAGIC != p[0]) || // Invalid packet; Not i3? - (recv_len < TCP_I3_HEADER_SIZE) ) { - I3_PRINT_INFO1 (I3_INFO_LEVEL_WARNING, - "Invalid i3 tcp header on fd %d\n", fd); - return -1; - } - pkt_size = nhgets(p + 1); - if (len < pkt_size) { // Invalid size - I3_PRINT_INFO2 (I3_INFO_LEVEL_WARNING, - "Invalid i3 tcp packet size %d (on fd %d)\n", - pkt_size, fd); - return -1; - } - - while (pkt_size > 0 && num_attempts++ < MAX_ATTEMPTS) { - recv_len = recv(fd, p, pkt_size, 0); - total_recv_len += recv_len; - pkt_size -= recv_len; - p += recv_len; - } - } - - /* Hack! */ - if (pkt_size > 0) { - I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, "Still some more bytes to be received, quitting!\n"); - return -1; - } else { - return total_recv_len; - } -} +#include "i3_tcp_fns.h" +#include "../utils/byteorder.h" +#include "i3_debug.h" + +#include <stdio.h> +#include <assert.h> +#include <sys/types.h> +#include "../utils/netwrap.h" + +/* Purpose: Send i3 data on TCP socket + * Note: To avoid copying of packets, the two sends are performed */ +int send_tcp(char *p, int len, nw_skt_t fd) +{ + char header[TCP_I3_HEADER_SIZE]; + + + /* Send header */ + header[0] = TCP_I3_HEADER_MAGIC; + hnputs(header + 1, (uint16_t) len); + + if (send(fd, header, TCP_I3_HEADER_SIZE, 0) != TCP_I3_HEADER_SIZE) { + perror("TCP header send"); + return -1; + } + + /* Send rest of the packet */ + if (send(fd, p, len, 0) < len) { + perror("TCP Send"); + return -1; + } + + return len; +} + +/* Purpose: Recv i3 data on TCP socket */ +#define MAX_ATTEMPTS 10 +int recv_tcp(char *p, int len, nw_skt_t fd) +{ + int recv_len, pkt_size = 0, total_recv_len = 0, num_attempts = 0; + + if (fd < 0) { + //TODO XXX Fix this.. + I3_PRINT_DEBUG1(I3_DEBUG_LEVEL_VERBOSE, "invalid fd = %d\n", fd); + return -1; + } + + /* recv header */ + recv_len = recv(fd, p, TCP_I3_HEADER_SIZE, 0); + if (recv_len < 0) { + perror("TCP header recv"); + fprintf(stderr, " on fd %d\n\n", fd); + nw_close(fd); + return recv_len; + } + + /* recv rest of the packet */ + if (recv_len > 0) { + if ((TCP_I3_HEADER_MAGIC != p[0]) || // Invalid packet; Not i3? + (recv_len < TCP_I3_HEADER_SIZE)) { + I3_PRINT_INFO1(I3_INFO_LEVEL_WARNING, + "Invalid i3 tcp header on fd %d\n", fd); + return -1; + } + pkt_size = nhgets(p + 1); + if (len < pkt_size) { // Invalid size + I3_PRINT_INFO2(I3_INFO_LEVEL_WARNING, + "Invalid i3 tcp packet size %d (on fd %d)\n", + pkt_size, fd); + return -1; + } + + while (pkt_size > 0 && num_attempts++ < MAX_ATTEMPTS) { + recv_len = recv(fd, p, pkt_size, 0); + total_recv_len += recv_len; + pkt_size -= recv_len; + p += recv_len; + } + } + + /* Hack! */ + if (pkt_size > 0) { + I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, "Still some more bytes to be received, quitting!\n"); + return -1; + } else { + return total_recv_len; + } +} === modified file 'i3/i3/i3_tcp_fns.h' --- i3/i3/i3_tcp_fns.h 2009-12-11 22:49:11 +0000 +++ i3/i3/i3_tcp_fns.h 2010-02-11 11:49:47 +0000 @@ -1,14 +1,14 @@ -#ifndef _I3_TCP_FNS_H -#define _I3_TCP_FNS_H -#include "../utils/netwrap.h" - -/************************************************************* - * Packet formats for TCP packets, pack/unpack - ************************************************************/ -/* Header = [ 1 byte: MAGIC | 2 bytes (packet length) ] */ -#define TCP_I3_HEADER_SIZE 3 -#define TCP_I3_HEADER_MAGIC 0x42 -int send_tcp(char *p, int len, nw_skt_t fd); -int recv_tcp(char *p, int len, nw_skt_t fd); - -#endif +#ifndef _I3_TCP_FNS_H +#define _I3_TCP_FNS_H +#include "../utils/netwrap.h" + +/************************************************************* + * Packet formats for TCP packets, pack/unpack + ************************************************************/ +/* Header = [ 1 byte: MAGIC | 2 bytes (packet length) ] */ +#define TCP_I3_HEADER_SIZE 3 +#define TCP_I3_HEADER_MAGIC 0x42 +int send_tcp(char *p, int len, nw_skt_t fd); +int recv_tcp(char *p, int len, nw_skt_t fd); + +#endif === modified file 'i3/i3/i3_trigger.c' --- i3/i3/i3_trigger.c 2009-12-11 22:49:11 +0000 +++ i3/i3/i3_trigger.c 2010-02-11 11:49:47 +0000 @@ -1,577 +1,573 @@ -/*************************************************************************** - i3_trigger.c - description - ------------------- - begin : Nov 18 2002 - email : istoica@xxxxxxxxxxxxxxx - ***************************************************************************/ - -#include "i3.h" -#include "i3_fun.h" -#include "i3_debug.h" -#include <stdlib.h> -#include <stdio.h> -#include <string.h> - -#include "../aeshash/aes.h" - - -/*************************************************************************** - * alloc_i3_trigger - allocate trigger data structure - * - * return: - * pointer to the allocated data structure - ***************************************************************************/ - -i3_trigger *alloc_i3_trigger() -{ - i3_trigger *trigger; - - /* XXX: just simply call alloc for now; preallocate a pool of buffers - in the future */ - trigger = (i3_trigger *)calloc(1, sizeof(i3_trigger)); - trigger->flags = 0; - trigger->tb = NULL; - - if (trigger) - return trigger; - I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL,"alloc_i3_trigger: memory allocation error.\n"); - return NULL; -} - - -/*************************************************************************** - * init_i3_trigger - initialize trigger fields - * - * input: - * t - trigger to be initialized - * prefix_len - prefix length - * id - trigger ID - * to - pointer to the address where packets matching "id" - * are forwarded (this data structure is not copied; don't - * free it after calling the function) - * - * note: - * the nonce field is updated separately; see update_nonce() function - ***************************************************************************/ - -void init_i3_trigger(i3_trigger *t, ID *id, uint16_t prefix_len, - i3_addr *to, Key *key, uint8_t flags) -{ - t->flags = flags; - memcpy((char *)&t->id.x, id->x, sizeof(ID)); - t->prefix_len = prefix_len; - t->to = to; - if (key) { - memcpy(t->key.x, key->x, KEY_LEN); - } -} - -/*************************************************************************** - * free_i3_trigger - free trigger data structure - * - * input: - * trigger to be freed - * - ***************************************************************************/ - -void free_i3_trigger(i3_trigger *trigger) -{ - /* XXX: just simply call free for now ... */ - if (trigger->to) - free_i3_addr(trigger->to); - if (trigger->tb) - free_token_bucket(trigger->tb); - free(trigger); -} - - - -/*************************************************************************** - * duplicate_i3_trigger - create a replica of trigger t - * - * input: - * t - trigger to be duplicated - * - * return: - * t's replica - ***************************************************************************/ - -i3_trigger *duplicate_i3_trigger(i3_trigger *t) -{ - i3_trigger *tnew = alloc_i3_trigger(); - - tnew->flags = t->flags; - memcpy((char *)&tnew->id.x, (char *)&t->id.x, sizeof(ID)); - tnew->prefix_len = t->prefix_len; - memcpy((char *)tnew->nonce, (char *)t->nonce, NONCE_LEN); - tnew->to = duplicate_i3_addr(t->to); - memcpy(tnew->key.x, t->key.x, KEY_LEN); - if (t->flags & I3_TRIGGER_FLAG_RATE_LIMIT) { - assert(t->tb); - tnew->tb = duplicate_token_bucket(t->tb); - } - return tnew; -} - - - - -/*************************************************************************** - * pack_i3_trigger - convert a trigger data structure in packet format - * - * input: - * p - address of the buffer where the trigger is to be stored in - * packet format (pre-allocated) - * trigger - trigger to be converted in packet format - * - * output: - * length - length of the trigger in packet format - ***************************************************************************/ - -void pack_i3_trigger(char *p, i3_trigger *trigger, - unsigned short *length) -{ - unsigned short len = 0, temp; - - *p = trigger->flags; - p += sizeof(char); - *length = sizeof(char); - - memcpy(p, &trigger->id.x, sizeof(ID)); - p += sizeof(ID); - *length += sizeof(ID); - - temp = htons(trigger->prefix_len); - memcpy(p, &temp, sizeof(uint16_t)); - p += sizeof(uint16_t); - *length += sizeof(uint16_t); - - memcpy(p, trigger->nonce, NONCE_LEN); - p += NONCE_LEN; - *length += NONCE_LEN; - - pack_i3_addr(p, trigger->to, &len); - *length += len; - p += len; - - if (I3_ADDR_TYPE_STACK != trigger->to->type) { - memcpy(p, trigger->key.x, KEY_LEN); - *length += KEY_LEN; - p += KEY_LEN; - } - - if (trigger->flags & I3_TRIGGER_FLAG_RATE_LIMIT) { - assert(trigger->tb); - pack_token_bucket(p, trigger->tb, &len); - *length += len; - p += len; - } -} - -unsigned short get_i3_trigger_len(i3_trigger *trigger) -{ - unsigned short length; - - length = sizeof(char) + sizeof(ID); // flags + id - - length += sizeof(uint16_t); /* prefix length */ - - length += NONCE_LEN; - - length += get_i3_addr_len(trigger->to); - - if (I3_ADDR_TYPE_STACK != trigger->to->type) { - length += KEY_LEN; - } - - if (trigger->flags & I3_TRIGGER_FLAG_RATE_LIMIT) { - assert(trigger->tb); - length += get_token_bucket_len(); - } - - return length; -} - - -/*************************************************************************** - * unpack_i3_trigger - allocate an i3_trigger data structure - * and copy info from packet into it - * - * input: - * p - address where trigger is stored in packet format - * - * output: - * length - length of the trigger info in packet format - * - ***************************************************************************/ - -i3_trigger *unpack_i3_trigger(char *p, unsigned short *length) -{ - i3_trigger *trigger = alloc_i3_trigger(); - unsigned short len; - - trigger->flags = *p; - - *length = sizeof(char); - p += sizeof(char); - - memcpy(&trigger->id.x, p, sizeof(ID)); - *length += sizeof(ID); - p += sizeof(ID); - - trigger->prefix_len = ntohs(*((uint16_t *)p)); - *length += sizeof(uint16_t); - p += sizeof(uint16_t); - - memcpy(&trigger->nonce, p, NONCE_LEN); - *length += NONCE_LEN; - p += NONCE_LEN; - - trigger->to = unpack_i3_addr(p, &len); - *length += len; - p += len; - - if (I3_ADDR_TYPE_STACK != trigger->to->type) { - memcpy(trigger->key.x, p, KEY_LEN); - *length += KEY_LEN; - p += KEY_LEN; - } - - if (trigger->flags & I3_TRIGGER_FLAG_RATE_LIMIT) { - trigger->tb = unpack_token_bucket(p, &len); - *length += len; - p += len; - } - - return trigger; -} - - -/*************************************************************************** - * check_i3_trigger - check whether i3 trigger is well-formed - * - * input: - * p - address where trigger is stored in packet format - * - * return: - * error code; FALSE if no error - * - * output: - * length - length of the trigger info in packet format - * - ***************************************************************************/ - -int check_i3_trigger(char *p, unsigned short *length) -{ - unsigned short len; - char type, flags; - int rc; - - flags = p[0]; - *length = sizeof(char); /* Flags */ - p += sizeof(char); - - *length += sizeof(ID); /* ID */ - p += sizeof(ID); - - *length += sizeof(uint16_t); /* prefix len */ - p += sizeof(uint16_t); - - *length += NONCE_LEN; /* nonce */ - p += NONCE_LEN; - - if ((rc = check_i3_addr(p, &len, &type)) != FALSE) - return rc; - - *length += len; - - if (I3_ADDR_TYPE_STACK != type) - *length += KEY_LEN; - - if (flags & I3_TRIGGER_FLAG_RATE_LIMIT) - *length += get_token_bucket_len(); - - return FALSE; -} - - - -/*************************************************************************** - * trigger_equal - compare two triggers - * - * input: - * t1, t2 - triggers to be compared - * - * return: - * TRUE, if triggers are identical; FALSE, if they are not - * - * note: - * ingnore the "id" field since this function is used to compare - * triggers with the same ids; also ignore the "nonce" field as - * the nonce is checked when the trigger is inserted - * - ***************************************************************************/ - -int trigger_equal(i3_trigger *t1, i3_trigger *t2) -{ - if (memcmp(t1->id.x, t2->id.x, ID_LEN)) { - return FALSE; - } -// if (memcmp(t1->key.x, t2->key.x, KEY_LEN)) -// return FALSE; - return addr_equal(t1->to, t2->to); -} - - -/*************************************************************************** - * update_nonce - compute nonce of a given trigger - * - * input: - * t - given trigger - * - * note: - * the algorithm to compute a nonce is trival now; it will be - * modified in the future - ***************************************************************************/ - -void update_nonce(i3_trigger *t) -{ - compute_nonce(t->nonce, t->to); -} - -/*************************************************************************** - * check_nonce - check the nonce of a given trigger - * - * input: - * t - given trigger - * - * note: - * obviously, this function has to implement the same algorithm to - * compute the nonce as "update_nonce"! So if the algorithm is changed - * this needs to be done in both "check_nonce" and "update_nonce" - * functions - * - ***************************************************************************/ - -int check_nonce(i3_trigger *t) -{ - char nonce[NONCE_LEN]; - - compute_nonce(nonce, t->to); - - if (!memcmp(nonce, t->nonce, NONCE_LEN)) - return TRUE; - else - return FALSE; -} - - -/******************************************************* - ** print i3_trigger -- this is for debuging proposes ** - *******************************************************/ - -void printf_i3_trigger(i3_trigger *trigger, int indent) -{ - int i; - char buf[INDENT_BUF_LEN]; - - memset(buf, ' ', indent); - buf[indent] = 0; - - printf("%s flags = %x\n", buf, trigger->flags); - printf_i3_id(&trigger->id, indent + 2); - printf("%s prefix_len: %d\n", buf, trigger->prefix_len); - printf("%s nonce = ", buf); - for (i=0; i < NONCE_LEN; i++) - printf("%d.", trigger->nonce[i]); - printf("\n"); - printf_i3_addr(trigger->to, indent + 2); - if (trigger->flags & I3_TRIGGER_FLAG_RATE_LIMIT) - printf_token_bucket(trigger->tb, indent + 2); -} - -/******************************************************** - * - * Constrained triggers: - * -------------------- - * - * T = (x, y), where {x,y} E I3_Addr - * Also, x = [x.prefix | x.key | x.suffix] - * - * l-constraint: - * if y E ID - * x.key = h_l(y) - * else if y E IP Addr - * x.key = h_l(y.key) - * - * r-constraint: - * y.key = h_r(x) - * - * - * For generating a 256->128 hash fn from a 128->128 hash function, - * foll is done: - * - * x (256 bits) = [x1 | x2] where x1 and x2 are 128 bits long - * - * y1 = First 64 bits of h(x1) - * y2 = Last 64 bits of h(x2) - * - * Y = H(x) = h( y1|y2 ) - * - ********************************************************/ - -/******************************************************** - * Generate constraints - *******************************************************/ -typedef void (*AesHash) (const unsigned char in[], unsigned char out[]); -static const AesHash aeshash[2] = {&aeshash_l, &aeshash_r}; - -void printf_i3_key(uint8_t *t, int indent) -{ - char buf[INDENT_BUF_LEN]; - uint i; - - memset(buf, ' ', INDENT_BUF_LEN); - buf[indent] = 0; - - printf("%s key: ", buf); - for (i = 0; i < KEY_LEN; i++) - printf("%02x", (int)(t[i])); - printf("\n"); -} - -void generate_constraint_id(ID *id, Key *key, int type) -{ - Key k1, k2; - - aeshash[type](id->x, k1.x); - aeshash[type](id->x + ID_LEN/2, k2.x); - - memcpy(k1.x + KEY_LEN/2, k2.x + KEY_LEN/2, KEY_LEN/2); - - aeshash[type](k1.x, key->x); -} - -void generate_l_constraint_addr(Key *rkey, Key *lkey) -{ - aeshash_l(rkey->x, lkey->x); -} - -void generate_r_constraint_addr(Key *lkey, Key *rkey) -{ - aeshash_r(lkey->x, rkey->x); -} - - -void generate_l_constraint(i3_trigger *t, Key *key) -{ - if (I3_ADDR_TYPE_STACK == t->to->type) - generate_l_constraint_id(t->to->t.stack->ids, key); - else { - // printf("l-constr from key: "); - // printf_i3_key(t->key.x, 2); - generate_l_constraint_addr(&t->key, key); - } -} - -int is_constrained(ID *id, Key *key) -{ - int retval; - retval = (0 == memcmp(KEY_ID_PTR(id), key->x, KEY_LEN)); - - // printf("Required key: "); printf_i3_key(key->x, 2); - // printf("Obtained key: "); printf_i3_key(KEY_ID_PTR(id), 2); - - return retval; -} - -/******************************************************* - * Check constraints - * -- called by server when trigger insert is attempted - *******************************************************/ -int check_constraint(i3_trigger *t) -{ - Key key; - char type; - - type = get_id_type (&(t->id)); - - /* - if (I3_ID_TYPE_UNCONSTRAINED == type) { - //Unconstrained ids require no checking. - printf ("\n\nUnconstrained trigger being checked\n\n"); - return 1; - } - - */ - - /* l-constraint is ok for any ID type (ie. public/private) */ - generate_l_constraint(t, &key); - if (is_constrained(&(t->id), &key)) { - return 1; - } - - /* r-constraint is ok only for private IDs */ - type = get_id_type(&(t->id)); - if (I3_ID_TYPE_PRIVATE != type) { - return 0; - } - - /* check for r-constraint */ - generate_r_constraint(&t->id, &key); - if (I3_ADDR_TYPE_STACK == t->to->type) { - I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL,"c1 -- check_constraint\n"); - if (is_constrained(t->to->t.stack->ids, &key)) { - return 1; - } - } else { - if (0 == memcmp(t->key.x, key.x, KEY_LEN)) { - return 1; - } - } - - return 0; -} - -/******************************************************* - * set the key in the client data structures - ******************************************************/ -void set_key_id(ID *id, Key *key) -{ - memcpy(KEY_ID_PTR(id), key->x, KEY_LEN); -} - -void set_key_addr(Key *dst, Key *src) -{ - memcpy(dst, src, KEY_LEN); -} - - -/******************************************************* - * Set key in path - * Parameters: - id array - * - array length - * - key of the first/last ID depending on l/r-constraint - * - return key ie. of the other end of path - ******************************************************/ -void l_constrain_path(ID *id, int path_len) -{ - Key key; - int i; - - for (i = path_len - 1; i > 0; i--) { - generate_l_constraint_id(&(id[i]), &key); - set_key_id(&(id[i-1]), &key); - } -} - -void r_constrain_path(ID *id, int path_len) -{ - Key key; - int i; - - for (i = 0; i < path_len - 1; i++) { - generate_r_constraint_id(&(id[i]), &key); - set_key_id(&(id[i+1]), &key); - } -} +/*************************************************************************** +* i3_trigger.c - description +* ------------------- +* begin : Nov 18 2002 +* email : istoica@xxxxxxxxxxxxxxx +***************************************************************************/ + +#include "i3.h" +#include "i3_fun.h" +#include "i3_debug.h" +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#include "../aeshash/aes.h" + + +/*************************************************************************** +* alloc_i3_trigger - allocate trigger data structure +* +* return: +* pointer to the allocated data structure +***************************************************************************/ + +i3_trigger *alloc_i3_trigger() +{ + i3_trigger *trigger; + + /* XXX: just simply call alloc for now; preallocate a pool of buffers + * in the future */ + trigger = (i3_trigger *) calloc(1, sizeof(i3_trigger)); + trigger->flags = 0; + trigger->tb = NULL; + + if (trigger) { + return trigger; + } + I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, "alloc_i3_trigger: memory allocation error.\n"); + return NULL; +} + +/*************************************************************************** +* init_i3_trigger - initialize trigger fields +* +* input: +* t - trigger to be initialized +* prefix_len - prefix length +* id - trigger ID +* to - pointer to the address where packets matching "id" +* are forwarded (this data structure is not copied; don't +* free it after calling the function) +* +* note: +* the nonce field is updated separately; see update_nonce() function +***************************************************************************/ + +void init_i3_trigger(i3_trigger *t, ID *id, uint16_t prefix_len, + i3_addr *to, Key *key, uint8_t flags) +{ + t->flags = flags; + memcpy((char *) &t->id.x, id->x, sizeof(ID)); + t->prefix_len = prefix_len; + t->to = to; + if (key) { + memcpy(t->key.x, key->x, KEY_LEN); + } +} + +/*************************************************************************** +* free_i3_trigger - free trigger data structure +* +* input: +* trigger to be freed +* +***************************************************************************/ + +void free_i3_trigger(i3_trigger *trigger) +{ + /* XXX: just simply call free for now ... */ + if (trigger->to) { + free_i3_addr(trigger->to); + } + if (trigger->tb) { + free_token_bucket(trigger->tb); + } + free(trigger); +} + +/*************************************************************************** +* duplicate_i3_trigger - create a replica of trigger t +* +* input: +* t - trigger to be duplicated +* +* return: +* t's replica +***************************************************************************/ + +i3_trigger *duplicate_i3_trigger(i3_trigger *t) +{ + i3_trigger *tnew = alloc_i3_trigger(); + + tnew->flags = t->flags; + memcpy((char *) &tnew->id.x, (char *) &t->id.x, sizeof(ID)); + tnew->prefix_len = t->prefix_len; + memcpy((char *) tnew->nonce, (char *) t->nonce, NONCE_LEN); + tnew->to = duplicate_i3_addr(t->to); + memcpy(tnew->key.x, t->key.x, KEY_LEN); + if (t->flags & I3_TRIGGER_FLAG_RATE_LIMIT) { + assert(t->tb); + tnew->tb = duplicate_token_bucket(t->tb); + } + return tnew; +} + +/*************************************************************************** +* pack_i3_trigger - convert a trigger data structure in packet format +* +* input: +* p - address of the buffer where the trigger is to be stored in +* packet format (pre-allocated) +* trigger - trigger to be converted in packet format +* +* output: +* length - length of the trigger in packet format +***************************************************************************/ + +void pack_i3_trigger(char *p, i3_trigger *trigger, + unsigned short *length) +{ + unsigned short len = 0, temp; + + *p = trigger->flags; + p += sizeof(char); + *length = sizeof(char); + + memcpy(p, &trigger->id.x, sizeof(ID)); + p += sizeof(ID); + *length += sizeof(ID); + + temp = htons(trigger->prefix_len); + memcpy(p, &temp, sizeof(uint16_t)); + p += sizeof(uint16_t); + *length += sizeof(uint16_t); + + memcpy(p, trigger->nonce, NONCE_LEN); + p += NONCE_LEN; + *length += NONCE_LEN; + + pack_i3_addr(p, trigger->to, &len); + *length += len; + p += len; + + if (I3_ADDR_TYPE_STACK != trigger->to->type) { + memcpy(p, trigger->key.x, KEY_LEN); + *length += KEY_LEN; + p += KEY_LEN; + } + + if (trigger->flags & I3_TRIGGER_FLAG_RATE_LIMIT) { + assert(trigger->tb); + pack_token_bucket(p, trigger->tb, &len); + *length += len; + p += len; + } +} + +unsigned short get_i3_trigger_len(i3_trigger *trigger) +{ + unsigned short length; + + length = sizeof(char) + sizeof(ID); // flags + id + + length += sizeof(uint16_t); /* prefix length */ + + length += NONCE_LEN; + + length += get_i3_addr_len(trigger->to); + + if (I3_ADDR_TYPE_STACK != trigger->to->type) { + length += KEY_LEN; + } + + if (trigger->flags & I3_TRIGGER_FLAG_RATE_LIMIT) { + assert(trigger->tb); + length += get_token_bucket_len(); + } + + return length; +} + +/*************************************************************************** +* unpack_i3_trigger - allocate an i3_trigger data structure +* and copy info from packet into it +* +* input: +* p - address where trigger is stored in packet format +* +* output: +* length - length of the trigger info in packet format +* +***************************************************************************/ + +i3_trigger *unpack_i3_trigger(char *p, unsigned short *length) +{ + i3_trigger *trigger = alloc_i3_trigger(); + unsigned short len; + + trigger->flags = *p; + + *length = sizeof(char); + p += sizeof(char); + + memcpy(&trigger->id.x, p, sizeof(ID)); + *length += sizeof(ID); + p += sizeof(ID); + + trigger->prefix_len = ntohs(*((uint16_t *) p)); + *length += sizeof(uint16_t); + p += sizeof(uint16_t); + + memcpy(&trigger->nonce, p, NONCE_LEN); + *length += NONCE_LEN; + p += NONCE_LEN; + + trigger->to = unpack_i3_addr(p, &len); + *length += len; + p += len; + + if (I3_ADDR_TYPE_STACK != trigger->to->type) { + memcpy(trigger->key.x, p, KEY_LEN); + *length += KEY_LEN; + p += KEY_LEN; + } + + if (trigger->flags & I3_TRIGGER_FLAG_RATE_LIMIT) { + trigger->tb = unpack_token_bucket(p, &len); + *length += len; + p += len; + } + + return trigger; +} + +/*************************************************************************** +* check_i3_trigger - check whether i3 trigger is well-formed +* +* input: +* p - address where trigger is stored in packet format +* +* return: +* error code; FALSE if no error +* +* output: +* length - length of the trigger info in packet format +* +***************************************************************************/ + +int check_i3_trigger(char *p, unsigned short *length) +{ + unsigned short len; + char type, flags; + int rc; + + flags = p[0]; + *length = sizeof(char); /* Flags */ + p += sizeof(char); + + *length += sizeof(ID); /* ID */ + p += sizeof(ID); + + *length += sizeof(uint16_t); /* prefix len */ + p += sizeof(uint16_t); + + *length += NONCE_LEN; /* nonce */ + p += NONCE_LEN; + + if ((rc = check_i3_addr(p, &len, &type)) != FALSE) { + return rc; + } + + *length += len; + + if (I3_ADDR_TYPE_STACK != type) { + *length += KEY_LEN; + } + + if (flags & I3_TRIGGER_FLAG_RATE_LIMIT) { + *length += get_token_bucket_len(); + } + + return FALSE; +} + +/*************************************************************************** +* trigger_equal - compare two triggers +* +* input: +* t1, t2 - triggers to be compared +* +* return: +* TRUE, if triggers are identical; FALSE, if they are not +* +* note: +* ingnore the "id" field since this function is used to compare +* triggers with the same ids; also ignore the "nonce" field as +* the nonce is checked when the trigger is inserted +* +***************************************************************************/ + +int trigger_equal(i3_trigger *t1, i3_trigger *t2) +{ + if (memcmp(t1->id.x, t2->id.x, ID_LEN)) { + return FALSE; + } +// if (memcmp(t1->key.x, t2->key.x, KEY_LEN)) +// return FALSE; + return addr_equal(t1->to, t2->to); +} + +/*************************************************************************** +* update_nonce - compute nonce of a given trigger +* +* input: +* t - given trigger +* +* note: +* the algorithm to compute a nonce is trival now; it will be +* modified in the future +***************************************************************************/ + +void update_nonce(i3_trigger *t) +{ + compute_nonce(t->nonce, t->to); +} + +/*************************************************************************** +* check_nonce - check the nonce of a given trigger +* +* input: +* t - given trigger +* +* note: +* obviously, this function has to implement the same algorithm to +* compute the nonce as "update_nonce"! So if the algorithm is changed +* this needs to be done in both "check_nonce" and "update_nonce" +* functions +* +***************************************************************************/ + +int check_nonce(i3_trigger *t) +{ + char nonce[NONCE_LEN]; + + compute_nonce(nonce, t->to); + + if (!memcmp(nonce, t->nonce, NONCE_LEN)) { + return TRUE; + } else { + return FALSE; + } +} + +/******************************************************* +** print i3_trigger -- this is for debuging proposes ** +*******************************************************/ + +void printf_i3_trigger(i3_trigger *trigger, int indent) +{ + int i; + char buf[INDENT_BUF_LEN]; + + memset(buf, ' ', indent); + buf[indent] = 0; + + printf("%s flags = %x\n", buf, trigger->flags); + printf_i3_id(&trigger->id, indent + 2); + printf("%s prefix_len: %d\n", buf, trigger->prefix_len); + printf("%s nonce = ", buf); + for (i = 0; i < NONCE_LEN; i++) { + printf("%d.", trigger->nonce[i]); + } + printf("\n"); + printf_i3_addr(trigger->to, indent + 2); + if (trigger->flags & I3_TRIGGER_FLAG_RATE_LIMIT) { + printf_token_bucket(trigger->tb, indent + 2); + } +} + +/******************************************************** +* +* Constrained triggers: +* -------------------- +* +* T = (x, y), where {x,y} E I3_Addr +* Also, x = [x.prefix | x.key | x.suffix] +* +* l-constraint: +* if y E ID +* x.key = h_l(y) +* else if y E IP Addr +* x.key = h_l(y.key) +* +* r-constraint: +* y.key = h_r(x) +* +* +* For generating a 256->128 hash fn from a 128->128 hash function, +* foll is done: +* +* x (256 bits) = [x1 | x2] where x1 and x2 are 128 bits long +* +* y1 = First 64 bits of h(x1) +* y2 = Last 64 bits of h(x2) +* +* Y = H(x) = h( y1|y2 ) +* +********************************************************/ + +/******************************************************** + * Generate constraints + *******************************************************/ +typedef void (*AesHash)(const unsigned char in[], unsigned char out[]); +static const AesHash aeshash[2] = {&aeshash_l, &aeshash_r}; + +void printf_i3_key(uint8_t *t, int indent) +{ + char buf[INDENT_BUF_LEN]; + uint i; + + memset(buf, ' ', INDENT_BUF_LEN); + buf[indent] = 0; + + printf("%s key: ", buf); + for (i = 0; i < KEY_LEN; i++) { + printf("%02x", (int) (t[i])); + } + printf("\n"); +} + +void generate_constraint_id(ID *id, Key *key, int type) +{ + Key k1, k2; + + aeshash[type](id->x, k1.x); + aeshash[type](id->x + ID_LEN / 2, k2.x); + + memcpy(k1.x + KEY_LEN / 2, k2.x + KEY_LEN / 2, KEY_LEN / 2); + + aeshash[type](k1.x, key->x); +} + +void generate_l_constraint_addr(Key *rkey, Key *lkey) +{ + aeshash_l(rkey->x, lkey->x); +} + +void generate_r_constraint_addr(Key *lkey, Key *rkey) +{ + aeshash_r(lkey->x, rkey->x); +} + +void generate_l_constraint(i3_trigger *t, Key *key) +{ + if (I3_ADDR_TYPE_STACK == t->to->type) { + generate_l_constraint_id(t->to->t.stack->ids, key); + } else { + // printf("l-constr from key: "); + // printf_i3_key(t->key.x, 2); + generate_l_constraint_addr(&t->key, key); + } +} + +int is_constrained(ID *id, Key *key) +{ + int retval; + retval = (0 == memcmp(KEY_ID_PTR(id), key->x, KEY_LEN)); + + // printf("Required key: "); printf_i3_key(key->x, 2); + // printf("Obtained key: "); printf_i3_key(KEY_ID_PTR(id), 2); + + return retval; +} + +/******************************************************* +* Check constraints +* -- called by server when trigger insert is attempted +*******************************************************/ +int check_constraint(i3_trigger *t) +{ + Key key; + char type; + + type = get_id_type(&(t->id)); + + /* + * if (I3_ID_TYPE_UNCONSTRAINED == type) { + * //Unconstrained ids require no checking. + * printf ("\n\nUnconstrained trigger being checked\n\n"); + * return 1; + * } + * + */ + + /* l-constraint is ok for any ID type (ie. public/private) */ + generate_l_constraint(t, &key); + if (is_constrained(&(t->id), &key)) { + return 1; + } + + /* r-constraint is ok only for private IDs */ + type = get_id_type(&(t->id)); + if (I3_ID_TYPE_PRIVATE != type) { + return 0; + } + + /* check for r-constraint */ + generate_r_constraint(&t->id, &key); + if (I3_ADDR_TYPE_STACK == t->to->type) { + I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, "c1 -- check_constraint\n"); + if (is_constrained(t->to->t.stack->ids, &key)) { + return 1; + } + } else { + if (0 == memcmp(t->key.x, key.x, KEY_LEN)) { + return 1; + } + } + + return 0; +} + +/******************************************************* + * set the key in the client data structures + ******************************************************/ +void set_key_id(ID *id, Key *key) +{ + memcpy(KEY_ID_PTR(id), key->x, KEY_LEN); +} + +void set_key_addr(Key *dst, Key *src) +{ + memcpy(dst, src, KEY_LEN); +} + +/******************************************************* + * Set key in path + * Parameters: - id array + * - array length + * - key of the first/last ID depending on l/r-constraint + * - return key ie. of the other end of path + ******************************************************/ +void l_constrain_path(ID *id, int path_len) +{ + Key key; + int i; + + for (i = path_len - 1; i > 0; i--) { + generate_l_constraint_id(&(id[i]), &key); + set_key_id(&(id[i - 1]), &key); + } +} + +void r_constrain_path(ID *id, int path_len) +{ + Key key; + int i; + + for (i = 0; i < path_len - 1; i++) { + generate_r_constraint_id(&(id[i]), &key); + set_key_id(&(id[i + 1]), &key); + } +} === modified file 'i3/i3/i3_trigger.h' --- i3/i3/i3_trigger.h 2010-01-06 22:17:32 +0000 +++ i3/i3/i3_trigger.h 2010-02-11 11:49:47 +0000 @@ -1,42 +1,42 @@ -/*************************************************************************** - i3_trigger.h - description - ------------------- - begin : Fre Jun 20 2003 - copyright : (C) 2003 by klaus - email : wehrle@xxxxxxxxxxxxxxxxx - ***************************************************************************/ - -#ifndef I3_TRIGGER_H -#define I3_TRIGGER_H - - -/* functions implemented in i3_trigger.c */ -i3_trigger *alloc_i3_trigger(void); -void init_i3_trigger(i3_trigger *t, ID *id, uint16_t prefix_len, - struct i3_addr *to, Key *key, uint8_t flags); -void free_i3_trigger(i3_trigger *trigger); -void pack_i3_trigger(char *p, i3_trigger *trigger, unsigned short *length); -unsigned short get_i3_trigger_len(i3_trigger *trigger); -i3_trigger *unpack_i3_trigger(char *p, unsigned short *length); -int check_i3_trigger(char *p, unsigned short *length); -int trigger_equal(i3_trigger *t1, i3_trigger *t2); -void printf_i3_trigger(i3_trigger *trigger, int indent); -void update_nonce(i3_trigger *t); -int check_nonce(i3_trigger *t); -i3_trigger *duplicate_i3_trigger(i3_trigger *t); - -void generate_constraint_id(ID *id, Key *key, int type); -#define generate_r_constraint_id(id, key) generate_constraint_id(id, key, R_CONSTRAINT) -#define generate_r_constraint(id, key) generate_constraint_id(id, key, R_CONSTRAINT) -#define generate_l_constraint_id(id, key) generate_constraint_id(id, key, L_CONSTRAINT) -void generate_l_constraint_addr(Key *rkey, Key *lkey); -int check_constraint(i3_trigger *t); -void set_key_id(ID *id, Key *key); -void set_key_addr(Key *dst, Key *src); - -void l_constrain_path(ID *id, int path_len); -void r_constrain_path(ID *id, int path_len); - -void printf_i3_key(uint8_t *k,int indent); - -#endif +/*************************************************************************** +* i3_trigger.h - description +* ------------------- +* begin : Fre Jun 20 2003 +* copyright : (C) 2003 by klaus +* email : wehrle@xxxxxxxxxxxxxxxxx +***************************************************************************/ + +#ifndef I3_TRIGGER_H +#define I3_TRIGGER_H + + +/* functions implemented in i3_trigger.c */ +i3_trigger *alloc_i3_trigger(void); +void init_i3_trigger(i3_trigger *t, ID *id, uint16_t prefix_len, + struct i3_addr *to, Key *key, uint8_t flags); +void free_i3_trigger(i3_trigger *trigger); +void pack_i3_trigger(char *p, i3_trigger *trigger, unsigned short *length); +unsigned short get_i3_trigger_len(i3_trigger *trigger); +i3_trigger *unpack_i3_trigger(char *p, unsigned short *length); +int check_i3_trigger(char *p, unsigned short *length); +int trigger_equal(i3_trigger *t1, i3_trigger *t2); +void printf_i3_trigger(i3_trigger *trigger, int indent); +void update_nonce(i3_trigger *t); +int check_nonce(i3_trigger *t); +i3_trigger *duplicate_i3_trigger(i3_trigger *t); + +void generate_constraint_id(ID *id, Key *key, int type); +#define generate_r_constraint_id(id, key) generate_constraint_id(id, key, R_CONSTRAINT) +#define generate_r_constraint(id, key) generate_constraint_id(id, key, R_CONSTRAINT) +#define generate_l_constraint_id(id, key) generate_constraint_id(id, key, L_CONSTRAINT) +void generate_l_constraint_addr(Key *rkey, Key *lkey); +int check_constraint(i3_trigger *t); +void set_key_id(ID *id, Key *key); +void set_key_addr(Key *dst, Key *src); + +void l_constrain_path(ID *id, int path_len); +void r_constrain_path(ID *id, int path_len); + +void printf_i3_key(uint8_t *k, int indent); + +#endif === modified file 'i3/i3/i3_utils.c' --- i3/i3/i3_utils.c 2009-12-11 22:49:11 +0000 +++ i3/i3/i3_utils.c 2010-02-11 11:49:47 +0000 @@ -1,33 +1,34 @@ -#include <stdio.h> -#include <stdlib.h> -#include <stdarg.h> -#include <string.h> -#include <errno.h> - -#define MAXLINE 4096 - - -/*static*/ void err_doit(int errnoflag, const char *fmt, va_list ap) -{ - int errno_save; - char buf[MAXLINE]; - - errno_save = errno; /* value caller might want printed */ - vsprintf(buf, fmt, ap); - if (errnoflag) - sprintf(buf+strlen(buf), ": %s", strerror(errno_save)); - strcat(buf, "\n"); - fflush(stdout); /* in case stdout and stderr are the same */ - fputs(buf, stderr); - fflush(NULL); /* flushes all stdio output streams */ -} - -void err_sys(const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - err_doit(1, fmt, ap); - va_end(ap); - exit(1); -} +#include <stdio.h> +#include <stdlib.h> +#include <stdarg.h> +#include <string.h> +#include <errno.h> + +#define MAXLINE 4096 + + +/*static*/ void err_doit(int errnoflag, const char *fmt, va_list ap) +{ + int errno_save; + char buf[MAXLINE]; + + errno_save = errno; /* value caller might want printed */ + vsprintf(buf, fmt, ap); + if (errnoflag) { + sprintf(buf + strlen(buf), ": %s", strerror(errno_save)); + } + strcat(buf, "\n"); + fflush(stdout); /* in case stdout and stderr are the same */ + fputs(buf, stderr); + fflush(NULL); /* flushes all stdio output streams */ +} + +void err_sys(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + err_doit(1, fmt, ap); + va_end(ap); + exit(1); +} === modified file 'i3/i3/i3_utils.h' --- i3/i3/i3_utils.h 2009-12-11 22:49:11 +0000 +++ i3/i3/i3_utils.h 2010-02-11 11:49:47 +0000 @@ -1,21 +1,21 @@ -/*************************************************************************** - i3_utils.h - description - ------------------- - begin : Sam Jun 21 2003 - copyright : (C) 2003 by klaus - email : wehrle@xxxxxxxxxxxxxxxxx - ***************************************************************************/ - -#ifndef I3_UTILS_H -#define I3_UTILS_H - -#include <stdio.h> -#include <stdlib.h> -#include <stdarg.h> -#include <string.h> - -/*static*/ void err_doit(int errnoflag, const char *fmt, va_list ap); -void err_sys(const char *fmt, ...); - - -#endif //I3_UTILS_H +/*************************************************************************** +* i3_utils.h - description +* ------------------- +* begin : Sam Jun 21 2003 +* copyright : (C) 2003 by klaus +* email : wehrle@xxxxxxxxxxxxxxxxx +***************************************************************************/ + +#ifndef I3_UTILS_H +#define I3_UTILS_H + +#include <stdio.h> +#include <stdlib.h> +#include <stdarg.h> +#include <string.h> + +/*static*/ void err_doit(int errnoflag, const char *fmt, va_list ap); +void err_sys(const char *fmt, ...); + + +#endif //I3_UTILS_H === modified file 'i3/i3/token_bucket.c' --- i3/i3/token_bucket.c 2009-12-11 22:49:11 +0000 +++ i3/i3/token_bucket.c 2010-02-11 11:49:47 +0000 @@ -1,266 +1,257 @@ -/*************************************************************************** - token_bucket.c - description - ------------------- - begin : Nov 20 2002 - email : istoica@xxxxxxxxxxxxxxx - ***************************************************************************/ - -#include "i3.h" -#include "i3_fun.h" -#include "i3_debug.h" -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <assert.h> - -/*************************************************************************** - * alloc_token_bucket - allocate a token bucket data structure - * - * return: - * pointer to the allocated token bucket - ***************************************************************************/ - -token_bucket *alloc_token_bucket() -{ - token_bucket *tb; - - tb = (token_bucket *)calloc(1, sizeof(token_bucket)); - if (tb) - return tb; - I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, - "alloc_token_bucket: memory allocation error.\n"); - return NULL; -} - - -/*************************************************************************** - * init_token_bucket - initialize token bucket's fields - * - * return: - * pointer to the allocated token bucket - ***************************************************************************/ - -void init_token_bucket(token_bucket *tb, uint8_t type, - uint32_t depth, uint32_t r, uint32_t R) -{ - tb->type = type; - tb->depth = depth; - tb->r = r; - tb->R = R; -} - - -/*************************************************************************** - * free_token_bucket - free tb data structure - * - * input: - * tb to be freed - ***************************************************************************/ - -void free_token_bucket(token_bucket *tb) -{ - free(tb); -} - - -/*************************************************************************** - * duplicate_token_bucket - create a replica of a token bucket - * - * input: - * tb - token bucket to be duplicated - * - * return: - * replica of tb - ***************************************************************************/ - -token_bucket *duplicate_token_bucket(token_bucket *tb) -{ - token_bucket *tbnew = alloc_token_bucket(); - - init_token_bucket(tbnew, tb->type, tb->depth, tb->r, tb->R); - - return tbnew; -} - - - - -/*************************************************************************** - * pack_token_bucket - convert a token bucket data structure in packet format - * - * input: - * p - address of the buffer where the token bucket is to be stored in - * packet format (the buffer is pre-allocated) - * tb - token bucket to be converted in packet format - * - * output: - * length - length of the token bucket in packet format - ***************************************************************************/ - -void pack_token_bucket(char *p, token_bucket *tb, unsigned short *length) -{ - uint32_t temp; - - p[0] = tb->type; - p += sizeof(char); - *length = sizeof(char); - - temp = htons(tb->depth); - memcpy(p, &temp, sizeof(uint32_t)); - p += sizeof(uint32_t); - *length += sizeof(uint32_t); - - temp = htons(tb->r); - memcpy(p, &temp, sizeof(uint32_t)); - p += sizeof(uint32_t); - *length += sizeof(uint32_t); - - temp = htons(tb->R); - memcpy(p, &temp, sizeof(uint32_t)); - p += sizeof(uint32_t); - *length += sizeof(uint32_t); -} - -unsigned short get_token_bucket_len() -{ - return 3*sizeof(uint32_t) + sizeof(uint8_t); -} - - -/*************************************************************************** - * unpack_token_bucket - copy token bucket info from packet to a tb - * data structure - * - * input: - * p - address where token bucket is stored in packet format - * - * return: - * token bucket data structure - * - * output: - * length - length of the token bucket info in packet format - * - ***************************************************************************/ - -token_bucket *unpack_token_bucket(char *p, unsigned short *length) -{ - token_bucket *tb = alloc_token_bucket(); - - tb->type = *p; - *length = sizeof(char); - p += sizeof(char); - - tb->depth = ntohs(*((uint32_t *)p)); - *length += sizeof(uint32_t); - p += sizeof(uint32_t); - - tb->r = ntohs(*((uint32_t *)p)); - *length += sizeof(uint32_t); - p += sizeof(uint32_t); - - tb->R = ntohs(*((uint32_t *)p)); - *length += sizeof(uint32_t); - p += sizeof(uint32_t); - - return tb; -} - - -/*************************************************************************** - * check_token_bucket - check token bucket whether is well-formed - * - * input: - * p - address where token bucket is stored in packet format - * - * return: - * error code; FALSE if no error - * - * output: - * length - length of the token bucket info in packet format - * - ***************************************************************************/ - -int check_token_bucket(char *p, unsigned short *length) -{ - *length = 3*sizeof(uint32_t) + sizeof(uint8_t); - return FALSE; -} - - -/*************************************************************************** - * token_bucket_accept_pkt - check whether token bucket constraints - * allow to send packet - * - * input: - * tb - token bucket - * len - packet length - * - * return: - * 1 - if the packet can be sent, - * 0 - if the packet cannot be sent (in this case, the packet is dropped) - * - * - ***************************************************************************/ - -int token_bucket_accept_pkt(token_bucket *tb, uint32_t len, uint64_t now) -{ - uint64_t tokens; - - assert(tb); - - /* update # of tokens in the bucket */ - tokens = (now - tb->last_time)*tb->r/1000000ULL; - tb->tokens += tokens; - - if (tb->tokens == 0) { - return 0; - } - - if (tb->tokens <= tb->depth) { - tb->last_time += tokens*1000000ULL/tb->r; - } else { - tb->last_time = now; - /* number of tokens cannot exceed bucket's depth */ - tb->tokens = tb->depth; - } - - if (tb->type == TOKEN_BUCKET_BYTE) { - if (tb->tokens < len) { - /* not enough tokens; cannot send the packet */ - return 0; - } - tb->tokens -= len; - return 1; - } else if (tb->type == TOKEN_BUCKET_PACKET) { - if (tb->tokens < 1) { - /* not enough tokens; cannot send the packet */ - return 0; - } - tb->tokens--; - return 1; - } else - panic("token_bucket_accept_pkt: invalid token bucket type!\n"); - - /* we shouldn't get here, but we need to return something - * to make the compiler happy - */ - return 0; -} - - -/**************************************** - ** print token bucket; just for test ** - ****************************************/ - -void printf_token_bucket(token_bucket *tb, int indent) -{ - char buf[INDENT_BUF_LEN]; - - memset(buf, ' ', INDENT_BUF_LEN); - buf[indent] = 0; - - printf("%s type=%d, depth=%u, r=%u, R=%u (tokens=%u, last_time=%llu)\n", - buf, tb->type, tb->depth, tb->r, tb->R, - tb->tokens, (unsigned long long int)tb->last_time); -} - +/*************************************************************************** +* token_bucket.c - description +* ------------------- +* begin : Nov 20 2002 +* email : istoica@xxxxxxxxxxxxxxx +***************************************************************************/ + +#include "i3.h" +#include "i3_fun.h" +#include "i3_debug.h" +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <assert.h> + +/*************************************************************************** +* alloc_token_bucket - allocate a token bucket data structure +* +* return: +* pointer to the allocated token bucket +***************************************************************************/ + +token_bucket *alloc_token_bucket() +{ + token_bucket *tb; + + tb = (token_bucket *) calloc(1, sizeof(token_bucket)); + if (tb) { + return tb; + } + I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, + "alloc_token_bucket: memory allocation error.\n"); + return NULL; +} + +/*************************************************************************** +* init_token_bucket - initialize token bucket's fields +* +* return: +* pointer to the allocated token bucket +***************************************************************************/ + +void init_token_bucket(token_bucket *tb, uint8_t type, + uint32_t depth, uint32_t r, uint32_t R) +{ + tb->type = type; + tb->depth = depth; + tb->r = r; + tb->R = R; +} + +/*************************************************************************** +* free_token_bucket - free tb data structure +* +* input: +* tb to be freed +***************************************************************************/ + +void free_token_bucket(token_bucket *tb) +{ + free(tb); +} + +/*************************************************************************** +* duplicate_token_bucket - create a replica of a token bucket +* +* input: +* tb - token bucket to be duplicated +* +* return: +* replica of tb +***************************************************************************/ + +token_bucket *duplicate_token_bucket(token_bucket *tb) +{ + token_bucket *tbnew = alloc_token_bucket(); + + init_token_bucket(tbnew, tb->type, tb->depth, tb->r, tb->R); + + return tbnew; +} + +/*************************************************************************** +* pack_token_bucket - convert a token bucket data structure in packet format +* +* input: +* p - address of the buffer where the token bucket is to be stored in +* packet format (the buffer is pre-allocated) +* tb - token bucket to be converted in packet format +* +* output: +* length - length of the token bucket in packet format +***************************************************************************/ + +void pack_token_bucket(char *p, token_bucket *tb, unsigned short *length) +{ + uint32_t temp; + + p[0] = tb->type; + p += sizeof(char); + *length = sizeof(char); + + temp = htons(tb->depth); + memcpy(p, &temp, sizeof(uint32_t)); + p += sizeof(uint32_t); + *length += sizeof(uint32_t); + + temp = htons(tb->r); + memcpy(p, &temp, sizeof(uint32_t)); + p += sizeof(uint32_t); + *length += sizeof(uint32_t); + + temp = htons(tb->R); + memcpy(p, &temp, sizeof(uint32_t)); + p += sizeof(uint32_t); + *length += sizeof(uint32_t); +} + +unsigned short get_token_bucket_len() +{ + return 3 * sizeof(uint32_t) + sizeof(uint8_t); +} + +/*************************************************************************** +* unpack_token_bucket - copy token bucket info from packet to a tb +* data structure +* +* input: +* p - address where token bucket is stored in packet format +* +* return: +* token bucket data structure +* +* output: +* length - length of the token bucket info in packet format +* +***************************************************************************/ + +token_bucket *unpack_token_bucket(char *p, unsigned short *length) +{ + token_bucket *tb = alloc_token_bucket(); + + tb->type = *p; + *length = sizeof(char); + p += sizeof(char); + + tb->depth = ntohs(*((uint32_t *) p)); + *length += sizeof(uint32_t); + p += sizeof(uint32_t); + + tb->r = ntohs(*((uint32_t *) p)); + *length += sizeof(uint32_t); + p += sizeof(uint32_t); + + tb->R = ntohs(*((uint32_t *) p)); + *length += sizeof(uint32_t); + p += sizeof(uint32_t); + + return tb; +} + +/*************************************************************************** +* check_token_bucket - check token bucket whether is well-formed +* +* input: +* p - address where token bucket is stored in packet format +* +* return: +* error code; FALSE if no error +* +* output: +* length - length of the token bucket info in packet format +* +***************************************************************************/ + +int check_token_bucket(char *p, unsigned short *length) +{ + *length = 3 * sizeof(uint32_t) + sizeof(uint8_t); + return FALSE; +} + +/*************************************************************************** +* token_bucket_accept_pkt - check whether token bucket constraints +* allow to send packet +* +* input: +* tb - token bucket +* len - packet length +* +* return: +* 1 - if the packet can be sent, +* 0 - if the packet cannot be sent (in this case, the packet is dropped) +* +* +***************************************************************************/ + +int token_bucket_accept_pkt(token_bucket *tb, uint32_t len, uint64_t now) +{ + uint64_t tokens; + + assert(tb); + + /* update # of tokens in the bucket */ + tokens = (now - tb->last_time) * tb->r / 1000000ULL; + tb->tokens += tokens; + + if (tb->tokens == 0) { + return 0; + } + + if (tb->tokens <= tb->depth) { + tb->last_time += tokens * 1000000ULL / tb->r; + } else { + tb->last_time = now; + /* number of tokens cannot exceed bucket's depth */ + tb->tokens = tb->depth; + } + + if (tb->type == TOKEN_BUCKET_BYTE) { + if (tb->tokens < len) { + /* not enough tokens; cannot send the packet */ + return 0; + } + tb->tokens -= len; + return 1; + } else if (tb->type == TOKEN_BUCKET_PACKET) { + if (tb->tokens < 1) { + /* not enough tokens; cannot send the packet */ + return 0; + } + tb->tokens--; + return 1; + } else { + panic("token_bucket_accept_pkt: invalid token bucket type!\n"); + } + + /* we shouldn't get here, but we need to return something + * to make the compiler happy + */ + return 0; +} + +/**************************************** +** print token bucket; just for test ** +****************************************/ + +void printf_token_bucket(token_bucket *tb, int indent) +{ + char buf[INDENT_BUF_LEN]; + + memset(buf, ' ', INDENT_BUF_LEN); + buf[indent] = 0; + + printf("%s type=%d, depth=%u, r=%u, R=%u (tokens=%u, last_time=%llu)\n", + buf, tb->type, tb->depth, tb->r, tb->R, + tb->tokens, (unsigned long long int) tb->last_time); +} === modified file 'i3/i3/token_bucket.h' --- i3/i3/token_bucket.h 2010-01-06 22:17:32 +0000 +++ i3/i3/token_bucket.h 2010-02-11 11:49:47 +0000 @@ -1,25 +1,25 @@ -/*************************************************************************** - token_bucket.h - description - ------------------- - begin : Fre Jun 20 2003 - copyright : (C) 2003 by klaus - email : wehrle@xxxxxxxxxxxxxxxxx - ***************************************************************************/ - -#ifndef TOKEN_BUCKET_H -#define TOKEN_BUCKET_H - -/* functions implemented in token_bucket.c */ -token_bucket *alloc_token_bucket(void); -void free_token_bucket(token_bucket *tb); -void init_token_bucket(token_bucket *tb, uint8_t type, - uint32_t depth, uint32_t r, uint32_t R); -token_bucket *duplicate_token_bucket(token_bucket *tb); -void pack_token_bucket(char *p, token_bucket *tb, unsigned short *length); -unsigned short get_token_bucket_len(void); -token_bucket *unpack_token_bucket(char *p, unsigned short *length); -int check_token_bucket(char *p, unsigned short *length); -int token_bucket_accept_pkt(token_bucket *tb, uint32_t len, uint64_t now); -void printf_token_bucket(token_bucket *tb, int indent); - -#endif // TOKEN_BUCKET_H +/*************************************************************************** +* token_bucket.h - description +* ------------------- +* begin : Fre Jun 20 2003 +* copyright : (C) 2003 by klaus +* email : wehrle@xxxxxxxxxxxxxxxxx +***************************************************************************/ + +#ifndef TOKEN_BUCKET_H +#define TOKEN_BUCKET_H + +/* functions implemented in token_bucket.c */ +token_bucket *alloc_token_bucket(void); +void free_token_bucket(token_bucket *tb); +void init_token_bucket(token_bucket *tb, uint8_t type, + uint32_t depth, uint32_t r, uint32_t R); +token_bucket *duplicate_token_bucket(token_bucket *tb); +void pack_token_bucket(char *p, token_bucket *tb, unsigned short *length); +unsigned short get_token_bucket_len(void); +token_bucket *unpack_token_bucket(char *p, unsigned short *length); +int check_token_bucket(char *p, unsigned short *length); +int token_bucket_accept_pkt(token_bucket *tb, uint32_t len, uint64_t now); +void printf_token_bucket(token_bucket *tb, int indent); + +#endif // TOKEN_BUCKET_H === modified file 'i3/i3_client/coordinates.c' --- i3/i3_client/coordinates.c 2009-12-11 22:49:11 +0000 +++ i3/i3_client/coordinates.c 2010-02-11 11:49:47 +0000 @@ -16,20 +16,20 @@ float objective_function(float dim[], int ndim) { int i; - float sum = 0; + float sum = 0; float l1, l2, temp; - + static int count = 0; ++count; - + // TODO: handle wraparound for longitude assert(curr_num > 0); for (i = 0; i < curr_num; i++) { - l1 = dim[0]-curr_coord_rtt[i].coord.latitude; - l2 = dim[1]-curr_coord_rtt[i].coord.longitude; + l1 = dim[0] - curr_coord_rtt[i].coord.latitude; + l2 = dim[1] - curr_coord_rtt[i].coord.longitude; - temp = (float)(sqrt(l1*l1 + l2*l2) - dim[2]*((float)curr_coord_rtt[i].rtt/1000.0)); - sum += temp*temp; + temp = (float) (sqrt(l1 * l1 + l2 * l2) - dim[2] * ((float) curr_coord_rtt[i].rtt / 1000.0)); + sum += temp * temp; } return sum; @@ -42,51 +42,53 @@ static int firsttime = 1; static float **p; static float *y; - int mean[] = {0, 0, 0, 10}; - int width[] = {0, 180, 360, 20}; - + int mean[] = {0, 0, 0, 10}; + int width[] = {0, 180, 360, 20}; + if (firsttime) { - p = (float **)malloc(sizeof(float *)*(DIM+2)); - y = (float *)malloc(sizeof(float)*(DIM+2)); - for (i = 1; i <= DIM+1; ++i) { - p[i] = (float *)malloc(sizeof(float)*(DIM+1)); - } - firsttime = 0; + p = (float **) malloc(sizeof(float *) * (DIM + 2)); + y = (float *) malloc(sizeof(float) * (DIM + 2)); + for (i = 1; i <= DIM + 1; ++i) { + p[i] = (float *) malloc(sizeof(float) * (DIM + 1)); + } + firsttime = 0; } - - curr_num = num; + + curr_num = num; curr_coord_rtt = coord_rtt; if (curr_num == 0) { - printf("No landmarks specified for coordinate computation. Exiting function...\n"); - return; + printf("No landmarks specified for coordinate computation. Exiting function...\n"); + return; } - + /* choose random numbers, and initializations */ - for (i = 1; i <= DIM+1; ++i) { - for (j = 1; j <= DIM; j++) { - p[i][j] = (float)(mean[j] + rand() % width[j] - width[j]/2); - } - } - for (i = 1; i <= DIM+1; ++i) { - y[i] = objective_function(p[i], DIM); - } - + for (i = 1; i <= DIM + 1; ++i) { + for (j = 1; j <= DIM; j++) { + p[i][j] = (float) (mean[j] + rand() % width[j] - width[j] / 2); + } + } + for (i = 1; i <= DIM + 1; ++i) { + y[i] = objective_function(p[i], DIM); + } + /* multiple runs */ #define NUM_RUNS_DOWNHILL 10 - for (i = 0; i < NUM_RUNS_DOWNHILL; i++) - downhill_simplex(p, y, DIM, FTOL, objective_function, &nfunc); - + for (i = 0; i < NUM_RUNS_DOWNHILL; i++) { + downhill_simplex(p, y, DIM, FTOL, objective_function, &nfunc); + } + printf("%.2f %.2f %.2f\n", p[1][1], p[1][2], p[1][3]); - my_coordinates.latitude = p[1][1]; + my_coordinates.latitude = p[1][1]; my_coordinates.longitude = p[1][2]; } float coordinates_distance(Coordinates coord) { - if (COORD_UNDEFINED == coord.latitude || COORD_UNDEFINED == coord.longitude) - return -1; - - return (float)(sqrt(pow(coord.latitude - my_coordinates.latitude, 2) + - pow(coord.longitude - my_coordinates.longitude, 2))); + if (COORD_UNDEFINED == coord.latitude || COORD_UNDEFINED == coord.longitude) { + return -1; + } + + return (float) (sqrt(pow(coord.latitude - my_coordinates.latitude, 2) + + pow(coord.longitude - my_coordinates.longitude, 2))); } === modified file 'i3/i3_client/coordinates.h' --- i3/i3_client/coordinates.h 2009-12-11 22:49:11 +0000 +++ i3/i3_client/coordinates.h 2010-02-11 11:49:47 +0000 @@ -16,7 +16,7 @@ typedef struct Coordinates_RTT { Coordinates coord; - uint64_t rtt; + uint64_t rtt; } Coordinates_RTT; void compute_coordinates(int num, Coordinates_RTT coord_rtt[]); === modified file 'i3/i3_client/downhill_simplex.c' --- i3/i3_client/downhill_simplex.c 2009-12-11 22:49:11 +0000 +++ i3/i3_client/downhill_simplex.c 2010-02-11 11:49:47 +0000 @@ -1,12 +1,12 @@ /* * This software is a copyright (c) of Carnegie Mellon University, 2002. - * + * * Permission to reproduce, use and prepare derivative works of this * software for use is granted provided the copyright and "No Warranty" * statements are included with all reproductions and derivative works. * This software may also be redistributed provided that the copyright * and "No Warranty" statements are included in all redistributions. - * + * * NO WARRANTY. THIS SOFTWARE IS FURNISHED ON AN "AS IS" BASIS. CARNEGIE * MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY KIND, EITHER EXPRESSED OR * IMPLIED AS TO ANY MATTER INCLUDING, BUT NOT LIMITED TO, WARRANTY OF @@ -29,167 +29,164 @@ #define NMAX 500000 /* - note: all effective array indices are 1..N, not 0..N-1 - - simplex - the initial simplex, must contain d + 1 points - values - the initial function values at the simplex points - d - the number of dimensions - ftol - the tolerate for convergence - obj - the objective function to minimize - num_eval - the number of evaluations of obj - stuff - things that are needed by obj -*/ + * note: all effective array indices are 1..N, not 0..N-1 + * + * simplex - the initial simplex, must contain d + 1 points + * values - the initial function values at the simplex points + * d - the number of dimensions + * ftol - the tolerate for convergence + * obj - the objective function to minimize + * num_eval - the number of evaluations of obj + * stuff - things that are needed by obj + */ void downhill_simplex(float **simplex, float *values, int d, float ftol, - float (*obj)(float *, int), int *num_eval) { - - int i, j, low, high, second_high, ssize; - float rtol, sum, *simplex_sum, *test_point, test_value, mult; - - /* initializations */ - *num_eval = 0; - ssize = d + 1; /* size of the simplex */ - - /* for each dimension, pre-compute the sum of all points */ - /* this is used later to compute the average coordinates */ - simplex_sum = (float*) malloc(sizeof(float)*(d+1)); /* array starts at 1 */ - for (i=1; i<=d; i++) { - sum = 0.0; - for(j=1; j<=ssize; j++) { - sum = sum + simplex[j][i]; - } - simplex_sum[i] = sum; - } - - /* create a test point */ - test_point = (float*) malloc(sizeof(float)*(d+1)); /* array starts at 1 */ - - - /* begin algorithm */ - while (1) { - - /* find the lowest point, the highest point and the second highest - point in the simplex */ - if (values[1] > values[2]) { - low = 2; - high = 1; - second_high = 2; - } else { - low = 1; - high = 2; - second_high = 1; - } - for (i=1; i<=ssize; i++) { - if (values[i] > values[high]) { - second_high = high; - high = i; - } else if (values[i] > values[second_high] && i != high) { - second_high = i; - } else if (values[i] <= values[low]) { - low = i; - } - } - - - /* we will quit if there are too many tries - the tolerance is met, or if the function - value is so low that we really don't care anymore - */ - rtol=2.0*fabs(values[high]-values[low])/ - (fabs(values[high])+fabs(values[low])+TINY); - if (*num_eval >= NMAX || rtol < ftol || values[low] < 1.0e-6) { - values[1] = values[low]; - for (i=1; i<=d; i++) { - simplex[1][i] = simplex[low][i]; - } - break; - } - - - /* first try to reflect the high point across the mean point */ - /* i.e. want (x_mean - x_high) = - (x_mean - x_test) */ - mult = 2.0/d; - for (i=1; i<=d; i++) { - test_point[i] = (simplex_sum[i] - simplex[high][i])*mult - - simplex[high][i]; - } - test_value = (*obj)(&test_point[1], d); - (*num_eval)++; - if (test_value < values[high]) { - /* better point, update the simplex, update also the sum */ - values[high] = test_value; - for (i=1; i<=d; i++) { - simplex_sum[i] = simplex_sum[i] - simplex[high][i] + test_point[i]; - simplex[high][i] = test_point[i]; - } - } - - if (test_value <= values[low]) { - /* the new point is even better than our lowest point, okay, now, - extend the point we just found even further - i.e. want 2*(x_mean - x_high) = (x_mean - x_test) - */ - mult = -1.0/d; - for (i=1; i<=d; i++) { - test_point[i] = (simplex_sum[i] - simplex[high][i])*mult - + 2.0*simplex[high][i]; - } - test_value = (*obj)(&test_point[1], d); - (*num_eval)++; - if (test_value < values[high]) { - /* better point, update the simplex, update also the sum */ - values[high] = test_value; - for (i=1; i<=d; i++) { - simplex_sum[i] = simplex_sum[i] - simplex[high][i] + test_point[i]; - simplex[high][i] = test_point[i]; - } - } - - } else if (test_value >= values[second_high]) { - /* the new point is still the highest, no improvement, - so we are going to shrink the high point towards the mean - i.e. want (x_mean - x_high) = 2*(x_mean - x_test) - */ - mult = 0.5/d; - for (i=1; i<=d; i++) { - test_point[i] = (simplex_sum[i] - simplex[high][i])*mult - + 0.5*simplex[high][i]; - } - test_value = (*obj)(&test_point[1], d); - (*num_eval)++; - if (test_value < values[high]) { - /* better point, update the simplex, update also the sum */ - values[high] = test_value; - for (i=1; i<=d; i++) { - simplex_sum[i] = simplex_sum[i] - simplex[high][i] + test_point[i]; - simplex[high][i] = test_point[i]; - } - } else { - /* no good, we better just contract the whole simplex - toward the low point - */ - for (i=1; i<=ssize; i++) { - if (i != low) { - for (j=1; j<=d; j++) { - simplex[i][j]=test_point[j]=0.5*(simplex[i][j]+simplex[low][j]); - } - values[i]=(*obj)(&test_point[1], d); - } - } - *num_eval = *num_eval + d; - - /* recompute the sums */ - for (i=1; i<=d; i++) { - sum = 0.0; - for(j=1; j<=ssize; j++) { - sum = sum + simplex[j][i]; - } - simplex_sum[i] = sum; - } - } - } - } - - free(simplex_sum); - free(test_point); - + float (*obj)(float *, int), int *num_eval) +{ + int i, j, low, high, second_high, ssize; + float rtol, sum, *simplex_sum, *test_point, test_value, mult; + + /* initializations */ + *num_eval = 0; + ssize = d + 1; /* size of the simplex */ + + /* for each dimension, pre-compute the sum of all points */ + /* this is used later to compute the average coordinates */ + simplex_sum = (float *) malloc(sizeof(float) * (d + 1)); /* array starts at 1 */ + for (i = 1; i <= d; i++) { + sum = 0.0; + for (j = 1; j <= ssize; j++) { + sum = sum + simplex[j][i]; + } + simplex_sum[i] = sum; + } + + /* create a test point */ + test_point = (float *) malloc(sizeof(float) * (d + 1)); /* array starts at 1 */ + + + /* begin algorithm */ + while (1) { + /* find the lowest point, the highest point and the second highest + * point in the simplex */ + if (values[1] > values[2]) { + low = 2; + high = 1; + second_high = 2; + } else { + low = 1; + high = 2; + second_high = 1; + } + for (i = 1; i <= ssize; i++) { + if (values[i] > values[high]) { + second_high = high; + high = i; + } else if (values[i] > values[second_high] && i != high) { + second_high = i; + } else if (values[i] <= values[low]) { + low = i; + } + } + + + /* we will quit if there are too many tries + * the tolerance is met, or if the function + * value is so low that we really don't care anymore + */ + rtol = 2.0 * fabs(values[high] - values[low]) / + (fabs(values[high]) + fabs(values[low]) + TINY); + if (*num_eval >= NMAX || rtol < ftol || values[low] < 1.0e-6) { + values[1] = values[low]; + for (i = 1; i <= d; i++) { + simplex[1][i] = simplex[low][i]; + } + break; + } + + + /* first try to reflect the high point across the mean point */ + /* i.e. want (x_mean - x_high) = - (x_mean - x_test) */ + mult = 2.0 / d; + for (i = 1; i <= d; i++) { + test_point[i] = (simplex_sum[i] - simplex[high][i]) * mult + - simplex[high][i]; + } + test_value = (*obj)(&test_point[1], d); + (*num_eval)++; + if (test_value < values[high]) { + /* better point, update the simplex, update also the sum */ + values[high] = test_value; + for (i = 1; i <= d; i++) { + simplex_sum[i] = simplex_sum[i] - simplex[high][i] + test_point[i]; + simplex[high][i] = test_point[i]; + } + } + + if (test_value <= values[low]) { + /* the new point is even better than our lowest point, okay, now, + * extend the point we just found even further + * i.e. want 2*(x_mean - x_high) = (x_mean - x_test) + */ + mult = -1.0 / d; + for (i = 1; i <= d; i++) { + test_point[i] = (simplex_sum[i] - simplex[high][i]) * mult + + 2.0 * simplex[high][i]; + } + test_value = (*obj)(&test_point[1], d); + (*num_eval)++; + if (test_value < values[high]) { + /* better point, update the simplex, update also the sum */ + values[high] = test_value; + for (i = 1; i <= d; i++) { + simplex_sum[i] = simplex_sum[i] - simplex[high][i] + test_point[i]; + simplex[high][i] = test_point[i]; + } + } + } else if (test_value >= values[second_high]) { + /* the new point is still the highest, no improvement, + * so we are going to shrink the high point towards the mean + * i.e. want (x_mean - x_high) = 2*(x_mean - x_test) + */ + mult = 0.5 / d; + for (i = 1; i <= d; i++) { + test_point[i] = (simplex_sum[i] - simplex[high][i]) * mult + + 0.5 * simplex[high][i]; + } + test_value = (*obj)(&test_point[1], d); + (*num_eval)++; + if (test_value < values[high]) { + /* better point, update the simplex, update also the sum */ + values[high] = test_value; + for (i = 1; i <= d; i++) { + simplex_sum[i] = simplex_sum[i] - simplex[high][i] + test_point[i]; + simplex[high][i] = test_point[i]; + } + } else { + /* no good, we better just contract the whole simplex + * toward the low point + */ + for (i = 1; i <= ssize; i++) { + if (i != low) { + for (j = 1; j <= d; j++) { + simplex[i][j] = test_point[j] = 0.5 * (simplex[i][j] + simplex[low][j]); + } + values[i] = (*obj)(&test_point[1], d); + } + } + *num_eval = *num_eval + d; + + /* recompute the sums */ + for (i = 1; i <= d; i++) { + sum = 0.0; + for (j = 1; j <= ssize; j++) { + sum = sum + simplex[j][i]; + } + simplex_sum[i] = sum; + } + } + } + } + + free(simplex_sum); + free(test_point); } === modified file 'i3/i3_client/downhill_simplex.h' --- i3/i3_client/downhill_simplex.h 2009-12-11 22:49:11 +0000 +++ i3/i3_client/downhill_simplex.h 2010-02-11 11:49:47 +0000 @@ -2,6 +2,6 @@ #define __DOWNHILL_SIMPLEX_H void downhill_simplex(float **simplex, float *values, int dim, float ftol, - float (*obj_func)(float [], int ndim), int *num_eval); - + float (*obj_func)(float [], int ndim), int *num_eval); + #endif === modified file 'i3/i3_client/http.c' --- i3/i3_client/http.c 2009-12-29 21:08:52 +0000 +++ i3/i3_client/http.c 2010-02-11 11:49:47 +0000 @@ -1,7 +1,7 @@ /* webclient.c written by detour@xxxxxxxxxxxxxx * * This code will connect to a host and attempt to download - * the source for an http page. + * the source for an http page. * * run: ./webclient <host> * @@ -15,7 +15,7 @@ #include <string.h> #include <errno.h> #ifndef _WIN32 - #include <unistd.h> + #include <unistd.h> #endif #include "../utils/netwrap.h" @@ -30,7 +30,7 @@ #define STR_ID_LEN 41 /* two chars per real "byte" plus one for end of string */ #define PORT_LEN 10 /* just enough to store a port in ascii */ #define IP_LEN 65 /* just in case, for IPv6 */ -#define BUF_SIZE 65535 +#define BUF_SIZE 65535 #define CHAR_LEN 4 #ifndef TRUE @@ -39,261 +39,275 @@ #endif -/* get host name and format get command from input +/* get host name and format get command from input * example, * input: www.cs.berkeley.edu/~istoica/index.html * host: www.cs.berkeley.edu * get_cmd: GET /~istoica/index.html HTTP/1.0 */ -void get_args(char *input, char *host, char *get_cmd, - int *port, int buf_len) +void get_args(char *input, char *host, char *get_cmd, + int *port, int buf_len) { - char *p1, *p2, *end, *ptemp; - - if (strlen(input) >= buf_len) { - fprintf(stderr, "input string too large: %s\n", input); - return; - } - - /* get host name */ - ptemp = get_cmd; - strcpy(ptemp, "GET "); - ptemp += strlen("GET "); - - end = input + strlen(input); - p1 = strstr(input, "/"); - p2 = strstr(input, ":"); - - if (NULL == p1) p1 = end; - if (NULL == p2) p2 = p1; - - if (p1 != end) { - strcpy(ptemp, p1); - ptemp += strlen(p1); - } else { - strcpy(ptemp, "/ "); - ptemp += strlen("/ "); - } - - if (p2 != p1) { - memcpy(host, p2+1, p1-p2-1); - host[p1-p2-1] = 0; - *port = atoi(host); - } else { - *port = 0; - } - - memcpy(host, input, p2-input); - host[p2-input] = 0; - - strcpy(ptemp, " HTTP/1.0\n\n"); -} - -/* get an entry containing the host IP address, port number, and 20 byte ID */ + char *p1, *p2, *end, *ptemp; + + if (strlen(input) >= buf_len) { + fprintf(stderr, "input string too large: %s\n", input); + return; + } + + /* get host name */ + ptemp = get_cmd; + strcpy(ptemp, "GET "); + ptemp += strlen("GET "); + + end = input + strlen(input); + p1 = strstr(input, "/"); + p2 = strstr(input, ":"); + + if (NULL == p1) { + p1 = end; + } + if (NULL == p2) { + p2 = p1; + } + + if (p1 != end) { + strcpy(ptemp, p1); + ptemp += strlen(p1); + } else { + strcpy(ptemp, "/ "); + ptemp += strlen("/ "); + } + + if (p2 != p1) { + memcpy(host, p2 + 1, p1 - p2 - 1); + host[p1 - p2 - 1] = 0; + *port = atoi(host); + } else { + *port = 0; + } + + memcpy(host, input, p2 - input); + host[p2 - input] = 0; + + strcpy(ptemp, " HTTP/1.0\n\n"); +} + +/* get an entry containing the host IP address, port number, and 20 byte ID */ int get_entry(char *buf, char *end, char *ip_addr, int *port, - char *id, char *status, float *latitude, float *longitude) + char *id, char *status, float *latitude, float *longitude) { - char *ip_start, *port_start, *id_start, *status_start, *coord_start, *temp, *p1, *p2; - char num_str[PORT_LEN]; - int len_id; - *status = FALSE; - - /* split fields */ - ip_start = strstr(buf, " "); - if (ip_start == NULL || ip_start > end) - return 0; - else - ip_start++; - id_start = strstr(ip_start, " "); - if (id_start == NULL || id_start > end) - return 0; - else - id_start++; - status_start = strstr(id_start, " "); - if (status_start == NULL || status_start > end) - return 0; - else - status_start++; - coord_start = strstr(status_start, " "); - if (coord_start == NULL || coord_start > end) - return 0; - else - coord_start++; - - /* lat_start = strstr(status_start, " "); - if (lat_start == NULL || lat_start > end) - return 0; - else - lat_start++; - long_start = strstr(lat_start, " "); - if (long_start == NULL || long_start > end) - return 0; - else - long_start++;*/ - - /* look for delimiter between ip address and port number ":" ... */ - port_start = strstr(ip_start, ":"); - if (port_start == NULL || port_start >= id_start) - return 0; - else - port_start++; - - /* ... make sure that at the left of ":" there is an IP address */ - for (temp = port_start-1; *temp != '.'; temp--) { - if (port_start-1 - temp > CHAR_LEN) { - /* not an IP address return */ - return 0; - } - } - - /* get address */ - if (port_start-1 - ip_start > IP_LEN) - return 0; - memcpy(ip_addr, ip_start, port_start-1 - ip_start); - ip_addr[port_start-1 - ip_start] = 0; - - /* get port */ - if (id_start-1 - port_start > PORT_LEN) - return 0; - memcpy(num_str, port_start, id_start-1 - port_start); - num_str[id_start-1 - port_start] = 0; - *port = atoi(num_str); - - /* get id */ - if (status_start-1 - id_start > STR_ID_LEN) - len_id = STR_ID_LEN; - else - len_id = status_start-1 - id_start; - memcpy(id, id_start, len_id); - id[len_id] = 0; - - /* get coordinates: TODO checks */ - sscanf(coord_start, "%f %f", latitude, longitude); - - /* get status */ - if ((p1 = strstr(status_start, "No")) > end) - p1 = NULL; - if ((p2 = strstr(status_start, "Running")) > end) - p2 = NULL; - - if (p1 && p2) - return 0; - else if (p2) { - *status = TRUE; - return 1; - } - else if (p1) - return 1; - - return 0; + char *ip_start, *port_start, *id_start, *status_start, *coord_start, *temp, *p1, *p2; + char num_str[PORT_LEN]; + int len_id; + *status = FALSE; + + /* split fields */ + ip_start = strstr(buf, " "); + if (ip_start == NULL || ip_start > end) { + return 0; + } else { + ip_start++; + } + id_start = strstr(ip_start, " "); + if (id_start == NULL || id_start > end) { + return 0; + } else { + id_start++; + } + status_start = strstr(id_start, " "); + if (status_start == NULL || status_start > end) { + return 0; + } else { + status_start++; + } + coord_start = strstr(status_start, " "); + if (coord_start == NULL || coord_start > end) { + return 0; + } else { + coord_start++; + } + + /* lat_start = strstr(status_start, " "); + * if (lat_start == NULL || lat_start > end) + * return 0; + * else + * lat_start++; + * long_start = strstr(lat_start, " "); + * if (long_start == NULL || long_start > end) + * return 0; + * else + * long_start++;*/ + + /* look for delimiter between ip address and port number ":" ... */ + port_start = strstr(ip_start, ":"); + if (port_start == NULL || port_start >= id_start) { + return 0; + } else { + port_start++; + } + + /* ... make sure that at the left of ":" there is an IP address */ + for (temp = port_start - 1; *temp != '.'; temp--) { + if (port_start - 1 - temp > CHAR_LEN) { + /* not an IP address return */ + return 0; + } + } + + /* get address */ + if (port_start - 1 - ip_start > IP_LEN) { + return 0; + } + memcpy(ip_addr, ip_start, port_start - 1 - ip_start); + ip_addr[port_start - 1 - ip_start] = 0; + + /* get port */ + if (id_start - 1 - port_start > PORT_LEN) { + return 0; + } + memcpy(num_str, port_start, id_start - 1 - port_start); + num_str[id_start - 1 - port_start] = 0; + *port = atoi(num_str); + + /* get id */ + if (status_start - 1 - id_start > STR_ID_LEN) { + len_id = STR_ID_LEN; + } else { + len_id = status_start - 1 - id_start; + } + memcpy(id, id_start, len_id); + id[len_id] = 0; + + /* get coordinates: TODO checks */ + sscanf(coord_start, "%f %f", latitude, longitude); + + /* get status */ + if ((p1 = strstr(status_start, "No")) > end) { + p1 = NULL; + } + if ((p2 = strstr(status_start, "Running")) > end) { + p2 = NULL; + } + + if (p1 && p2) { + return 0; + } else if (p2) { + *status = TRUE; + return 1; + } else if (p1) { + return 1; + } + + return 0; } int get_address(char *web_url, I3ServerList *list) { - nw_skt_t sockid; - int bufsize; - char host[STR_LEN]; - char get_cmd[STR_LEN]; - char buffer[BUF_SIZE]; - char ip_addr[IP_LEN]; - char id[STR_ID_LEN]; - char status; - int port; - Coordinates coord; - struct sockaddr_in socketaddr; - struct hostent *hostaddr; - struct servent *servaddr; - struct protoent *protocol; - char *p, *next; - int offset = 0; - - /* get host name and format the get command */ - get_args(web_url, host, get_cmd, &port, STR_LEN); - - /* Resolve the host name */ - if (!(hostaddr = gethostbyname(host))) { - fprintf(stderr, "Getting server list: error resolving host %s.", host); - return -1; - } - - /* clear and initialize socketaddr */ - memset(&socketaddr, 0, sizeof(socketaddr)); - socketaddr.sin_family = AF_INET; - - /* setup the servent struct using getservbyname */ - servaddr = getservbyname(SERVICE, PROTOCOL); - if (0 == port) - socketaddr.sin_port = servaddr->s_port; - else - socketaddr.sin_port = htons(port); - - memcpy(&socketaddr.sin_addr, hostaddr->h_addr, hostaddr->h_length); - - /* protocol must be a number when used with socket() - since we are using tcp protocol->p_proto will be 0 */ - protocol = getprotobyname(PROTOCOL); - - sockid = socket(AF_INET, SOCK_STREAM, protocol->p_proto); - if (sockid < 0) { - fprintf(stderr, "get: error creating socket\n"); - return -1; - } - - /* everything is setup, now we connect */ - if(connect(sockid, (struct sockaddr *)&socketaddr, sizeof(socketaddr)) == -1) { - fprintf(stderr, "get: error connecting\n"); - nw_close(sockid); - return -1; - } - - /* send our get request for http */ - if (send(sockid, get_cmd, strlen(get_cmd), 0) == -1) { - fprintf(stderr, "get: error sending data\n"); - nw_close(sockid); - return -1; - } - - //printf ("8888: start get\n"); - /* read the socket until its clear then exit */ - while ( (bufsize = recv(sockid, buffer+offset, sizeof(buffer)-offset-1, 0))) { - - if (bufsize == -1) { - I3_PRINT_DEBUG1 (I3_DEBUG_LEVEL_MINIMAL, - "Error while getting list of i3 servers in get_addr: %s.\n", - strerror (errno) - ); - break; - } - - buffer[offset+bufsize] = 0; - p = buffer; - - while ((next = strstr(p, "\n")) != NULL) { - if (get_entry(p, next, ip_addr, &port, id, &status, - &(coord.latitude), &(coord.longitude))) { - if (status) { - I3_PRINT_DEBUG5(I3_DEBUG_LEVEL_VERBOSE, "GET: %s %d %s %.1f %.1f\n", - ip_addr, port, id, coord.latitude, coord.longitude); - update_i3server(list, ntohl(inet_addr(ip_addr)), - port, atoi3id(id), coord); - } - } - p = next + 1; - } - - memmove(buffer, p, strlen(p)); - offset = strlen(p); - } - //printf ("8888: stop get\n"); - nw_close(sockid); - return 0; + nw_skt_t sockid; + int bufsize; + char host[STR_LEN]; + char get_cmd[STR_LEN]; + char buffer[BUF_SIZE]; + char ip_addr[IP_LEN]; + char id[STR_ID_LEN]; + char status; + int port; + Coordinates coord; + struct sockaddr_in socketaddr; + struct hostent *hostaddr; + struct servent *servaddr; + struct protoent *protocol; + char *p, *next; + int offset = 0; + + /* get host name and format the get command */ + get_args(web_url, host, get_cmd, &port, STR_LEN); + + /* Resolve the host name */ + if (!(hostaddr = gethostbyname(host))) { + fprintf(stderr, "Getting server list: error resolving host %s.", host); + return -1; + } + + /* clear and initialize socketaddr */ + memset(&socketaddr, 0, sizeof(socketaddr)); + socketaddr.sin_family = AF_INET; + + /* setup the servent struct using getservbyname */ + servaddr = getservbyname(SERVICE, PROTOCOL); + if (0 == port) { + socketaddr.sin_port = servaddr->s_port; + } else { + socketaddr.sin_port = htons(port); + } + + memcpy(&socketaddr.sin_addr, hostaddr->h_addr, hostaddr->h_length); + + /* protocol must be a number when used with socket() + * since we are using tcp protocol->p_proto will be 0 */ + protocol = getprotobyname(PROTOCOL); + + sockid = socket(AF_INET, SOCK_STREAM, protocol->p_proto); + if (sockid < 0) { + fprintf(stderr, "get: error creating socket\n"); + return -1; + } + + /* everything is setup, now we connect */ + if (connect(sockid, (struct sockaddr *) &socketaddr, sizeof(socketaddr)) == -1) { + fprintf(stderr, "get: error connecting\n"); + nw_close(sockid); + return -1; + } + + /* send our get request for http */ + if (send(sockid, get_cmd, strlen(get_cmd), 0) == -1) { + fprintf(stderr, "get: error sending data\n"); + nw_close(sockid); + return -1; + } + + //printf ("8888: start get\n"); + /* read the socket until its clear then exit */ + while ((bufsize = recv(sockid, buffer + offset, sizeof(buffer) - offset - 1, 0))) { + if (bufsize == -1) { + I3_PRINT_DEBUG1(I3_DEBUG_LEVEL_MINIMAL, + "Error while getting list of i3 servers in get_addr: %s.\n", + strerror(errno) + ); + break; + } + + buffer[offset + bufsize] = 0; + p = buffer; + + while ((next = strstr(p, "\n")) != NULL) { + if (get_entry(p, next, ip_addr, &port, id, &status, + &(coord.latitude), &(coord.longitude))) { + if (status) { + I3_PRINT_DEBUG5(I3_DEBUG_LEVEL_VERBOSE, "GET: %s %d %s %.1f %.1f\n", + ip_addr, port, id, coord.latitude, coord.longitude); + update_i3server(list, ntohl(inet_addr(ip_addr)), + port, atoi3id(id), coord); + } + } + p = next + 1; + } + + memmove(buffer, p, strlen(p)); + offset = strlen(p); + } + //printf ("8888: stop get\n"); + nw_close(sockid); + return 0; } void update_i3_server_list(char *web_url, I3ServerList *list, - I3ServerListNode **next_ping) + I3ServerListNode **next_ping) { mark_i3servers_dead(list); if (get_address(web_url, list) >= 0) { - delete_dead_i3servers(list); - *next_ping = list->list; + delete_dead_i3servers(list); + *next_ping = list->list; } } === modified file 'i3/i3_client/http.h' --- i3/i3_client/http.h 2009-12-11 22:49:11 +0000 +++ i3/i3_client/http.h 2010-02-11 11:49:47 +0000 @@ -4,6 +4,6 @@ #include "i3server_list.h" void update_i3_server_list(char *web_url, I3ServerList *list, - I3ServerListNode **next_ping); + I3ServerListNode **next_ping); #endif === modified file 'i3/i3_client/i3_client.h' --- i3/i3_client/i3_client.h 2010-01-06 22:17:32 +0000 +++ i3/i3_client/i3_client.h 2010-02-11 11:49:47 +0000 @@ -14,14 +14,14 @@ #include "i3_client_fd.h" #include "../utils/event.h" -#define CL_CBK_TRIGGER_INSERTED 1 -#define CL_CBK_TRIGGER_REFRESH_FAILED 2 +#define CL_CBK_TRIGGER_INSERTED 1 +#define CL_CBK_TRIGGER_REFRESH_FAILED 2 #define CL_CBK_TRIGGER_NOT_FOUND 3 #define CL_CBK_RECEIVE_PACKET 4 #define CL_CBK_RECEIVE_PAYLOAD 5 #define CL_CBK_SERVER_DOWN 6 #define CL_CBK_TRIGGER_CONSTRAINT_FAILED 7 -#define CL_CBK_ROUTE_BROKEN 8 +#define CL_CBK_ROUTE_BROKEN 8 #define CL_CBK_RATELIMIT_EXCEEDED 9 @@ -31,7 +31,7 @@ #define CL_RET_OK 0 #define CL_RET_TRIGGER_ALREADY_CREATED 1 #define CL_RET_TRIGGER_NOT_FOUND 2 -#define CL_RET_IGNORE_CBK_RECEIVE_PAYLOAD 3 +#define CL_RET_IGNORE_CBK_RECEIVE_PAYLOAD 3 #define CL_RET_DUP_CONTEXT 4 #define CL_RET_NO_CONTEXT 5 #define CL_RET_NO_TRIGGER 6 @@ -44,9 +44,9 @@ #define CL_RET_INVALID_CFG_FILE 17 #define CL_RET_INVALID_FLAGS 18 #define CL_RET_INVALID_STACK_LEN 20 -#define CL_RET_NET_ERROR 21 -#define CL_RET_MSG_SIZE 22 -#define CL_RET_NO_SERVERS 23 +#define CL_RET_NET_ERROR 21 +#define CL_RET_MSG_SIZE 22 +#define CL_RET_NO_SERVERS 23 #define CL_TRIGGER_STATUS_IDLE 0 #define CL_TRIGGER_STATUS_PENDING 1 @@ -77,147 +77,146 @@ #define EOL 0xa #define MAX_BUF_SIZE 2048 -#define CL_HTABLE_SIZE 1024*64 +#define CL_HTABLE_SIZE 1024 * 64 #define UMILLION 1000000ULL /**************************************************************************** - * Macro definitions - ****************************************************************************/ - -#define CL_HASH_ID(id) (((*(uint32_t *)&(id)->x[0])^(*(uint32_t *)&(id)->x[4]) ^ (*(uint32_t *)&(id)->x[8]) ^ (*(uint32_t *)&(id)->x[12]))% CL_HTABLE_SIZE) - -#define CL_HASH_TRIG(id) (((*(uint32_t *)&(id)->x[0])^(*(uint32_t *)&(id)->x[4])^ (*(uint32_t *)&(id)->x[8]) ^ (*(uint32_t *)&(id)->x[12]))% CL_HTABLE_SIZE) +* Macro definitions +****************************************************************************/ + +#define CL_HASH_ID(id) (((*(uint32_t *) &(id)->x[0]) ^ (*(uint32_t *) &(id)->x[4]) ^ (*(uint32_t *) &(id)->x[8]) ^ (*(uint32_t *) &(id)->x[12])) % CL_HTABLE_SIZE) + +#define CL_HASH_TRIG(id) (((*(uint32_t *) &(id)->x[0]) ^ (*(uint32_t *) &(id)->x[4]) ^ (*(uint32_t *) &(id)->x[8]) ^ (*(uint32_t *) &(id)->x[12])) % CL_HTABLE_SIZE) /* #define CL_HASH_TRIG(id) (((*(uint32_t *)&(id)->x[0])^(*(uint32_t *)&(id)->x[4])^ (*(uint32_t *)&(id)->x[8]) ^ (*(uint32_t *)&(id)->x[12]) ^ (*(uint32_t *)&(id)->x[16]) ^ (*(uint32_t *)&(id)->x[20]) ^ (*(uint32_t *)&(id)->x[24]) ^ (*(uint32_t *)&(id)->x[28]))% CL_HTABLE_SIZE) */ /**************************************************************************** - * Data structures - ****************************************************************************/ +* Data structures +****************************************************************************/ typedef struct buf_struct { - unsigned short len; - char *p; + unsigned short len; + char * p; } buf_struct; #ifndef CCURED typedef struct cl_cbk { - void (*fun)(void*, void*, void*); /* pointer to callback function */ - void *fun_ctx; /* pointer to the function context information specified while registering the callback */ - + void (*fun)(void *, void *, void *); /* pointer to callback function */ + void *fun_ctx; /* pointer to the function context information specified while registering the callback */ } cl_cbk; #else #ifndef __RTTI #define __RTTI #endif typedef struct cl_cbk { - void (*fun)(i3_trigger*, void * __RTTI); /* pointer to callbcak function */ - void * __RTTI fun_ctx; /* pointer to the function context information specified while registering the callback */ + void (*fun)(i3_trigger *, void *__RTTI); /* pointer to callbcak function */ + void *__RTTI fun_ctx; /* pointer to the function context information specified while registering the callback */ } cl_cbk; #endif typedef struct cl_trigger { - i3_trigger *t; - buf_struct precomputed_pkt; - char type; /* specify whether the trigger is inserted only - * locally (CL_TRIGGER_LOCAL) or is inserted in - * i3 (CL_TRIGGER_I3) + i3_trigger *t; + buf_struct precomputed_pkt; + char type; /* specify whether the trigger is inserted only + * locally (CL_TRIGGER_LOCAL) or is inserted in + * i3 (CL_TRIGGER_I3) */ - char is_queued; /* true when it is inserted in PRIORITY QUEUE. - * the priority queue is used to efficiently + char is_queued; /* true when it is inserted in PRIORITY QUEUE. + * the priority queue is used to efficiently * refresh triggers */ - uint16_t status; /* possible status: CL_TRIGGER_STATUS_PENDING, - * CL_TRIGGER_STATUS_INSERTED - * CL_TRIGGER_STATUS_IDLE + uint16_t status; /* possible status: CL_TRIGGER_STATUS_PENDING, + * CL_TRIGGER_STATUS_INSERTED + * CL_TRIGGER_STATUS_IDLE */ - int retries_cnt; - cl_cbk cbk_trigger_inserted; /* callback confirming that the trigger - * has been inserted - */ - cl_cbk cbk_trigger_refresh_failed;/* trigger cannot be inserted - * or trigger couldn't be refreshed + int retries_cnt; + cl_cbk cbk_trigger_inserted; /* callback confirming that the trigger + * has been inserted + */ + cl_cbk cbk_trigger_refresh_failed; /* trigger cannot be inserted + * or trigger couldn't be refreshed + */ + cl_cbk cbk_trigger_constraint_failed; /* constraint fails at server */ + cl_cbk cbk_receive_packet; /* callback triggered when a packet + * arrives to this trigger */ - cl_cbk cbk_trigger_constraint_failed; /* constraint fails at server */ - cl_cbk cbk_receive_packet; /* callback triggered when a packet - * arrives to this trigger - */ - cl_cbk cbk_receive_payload; /* callback triggered when a packet - * arrives to this trigger - * NOTE 1: cbk_receive_packet has a higher - * precedence than cbk_receive_data; if both - * of these callbacks are specified, only - * cbk_receive_data will called - * NOTE 2: the only difference between - * cbk_receive_data and cbk_receive_packet - * is that cbk_receive_packet returns - * the packet's header (hdr) in addition - */ - cl_cbk cbk_route_broken; /* triggered when an i3_server - * attempting to forward a packet - * along this trigger discovers that - * the i3_server corres to the next - * hop is down - */ - - /** This is an internal hook which is triggered whenever a trigger ack timeout - * needs to be set. This is used only when an external select() statement - * is used (as in the proxy). - */ - cl_cbk internal_hook_ack_timeout; - - /** This is an internal hook which is triggered whenever a trigger refresh timeout - * needs to be set. This is used only when an external select() statement - * is used (as in the proxy). - */ - cl_cbk internal_hook_refresh_timeout; - - void *ctx; /* trigger's context */ - void *timer; /* pointer to the current timeout associated + cl_cbk cbk_receive_payload; /* callback triggered when a packet + * arrives to this trigger + * NOTE 1: cbk_receive_packet has a higher + * precedence than cbk_receive_data; if both + * of these callbacks are specified, only + * cbk_receive_data will called + * NOTE 2: the only difference between + * cbk_receive_data and cbk_receive_packet + * is that cbk_receive_packet returns + * the packet's header (hdr) in addition + */ + cl_cbk cbk_route_broken; /* triggered when an i3_server + * attempting to forward a packet + * along this trigger discovers that + * the i3_server corres to the next + * hop is down + */ + + /** This is an internal hook which is triggered whenever a trigger ack timeout + * needs to be set. This is used only when an external select() statement + * is used (as in the proxy). + */ + cl_cbk internal_hook_ack_timeout; + + /** This is an internal hook which is triggered whenever a trigger refresh timeout + * needs to be set. This is used only when an external select() statement + * is used (as in the proxy). + */ + cl_cbk internal_hook_refresh_timeout; + + void * ctx; /* trigger's context */ + void * timer; /* pointer to the current timeout associated * to the trigger (e.g., timeout) - */ - struct cl_trigger *next; - struct cl_trigger *prev; + */ + struct cl_trigger *next; + struct cl_trigger *prev; } cl_trigger; typedef struct cl_id { - ID id; - struct sockaddr_in cache_addr; /* address where packets with the - * the identifier "id" are sent; - * data is stored in network format - */ - struct sockaddr_in dest_addr; /* destination address. Returned - * by the I3_OPT_CACHE_DEST_ADDR and - * I3_OPT_CACHE_SHORTCUT_ADDR options - */ - int retries_cnt; - struct timeval last_ack; /* time when last request for ack - has been sent */ - cl_cbk cbk_no_trigger; /* callback invoked when no trigger - * matching the "id" filed was found - */ + ID id; + struct sockaddr_in cache_addr; /* address where packets with the + * the identifier "id" are sent; + * data is stored in network format + */ + struct sockaddr_in dest_addr; /* destination address. Returned + * by the I3_OPT_CACHE_DEST_ADDR and + * I3_OPT_CACHE_SHORTCUT_ADDR options + */ + int retries_cnt; + struct timeval last_ack; /* time when last request for ack + * has been sent */ + cl_cbk cbk_no_trigger; /* callback invoked when no trigger + * matching the "id" filed was found + */ #if NEWS_INSTRUMENT - int opt_log_pkt; - int opt_add_ts; + int opt_log_pkt; + int opt_add_ts; #endif - struct cl_id *next; - struct cl_id *prev; + struct cl_id * next; + struct cl_id * prev; } cl_id; /* maintain the list of i3 servers read from the configuration file */ #define MAX_NUM_SRV 20 typedef struct srv_address { - struct in_addr addr; - uint16_t port; - ID id; + struct in_addr addr; + uint16_t port; + ID id; #define ID_EMPTY 0 #define ID_UP 1 #define ID_DOWN 2 - char status; + char status; } srv_address; /* Maintain array of precomputed options */ @@ -228,96 +227,95 @@ #define REFRESH_SHORTCUT_MASK (1 << 3) typedef struct { - nw_skt_t fd; /* file descriptor for i3 packets */ - struct sockaddr_in local; /* local address, used to receive i3 traffic - * (in network format) - */ - struct in_addr local_ip_addr; /* local IP address; this field is - * needed because the IP address in - * "local" data structure is set to - * INADDR_ANY (host format) - */ - uint16_t local_port; /* local port number (host format) */ - struct timeval now; /* updated every time cl_refresh_context - * is invoked */ - - nw_skt_t tcp_fd; /* Filedes for TCP connection */ - char is_tcp; /* 1 if tcp connection is used */ - - cl_cbk cbk_trigger_not_found; /* callback invoked when there is no trigger - * matching the ID of the transmitted - * packet */ - cl_cbk cbk_server_down; /* callback invoked when an i3 server - * couldn't be contacted */ - /* following callbacks are called when the corresponding callbacks - * associated with the trigger are not defined */ - cl_cbk cbk_trigger_inserted; /* callback confirming that the trigger - * has been inserted - */ - cl_cbk cbk_trigger_refresh_failed;/* trigger cannot be inserted - * or trigger couldn't be refreshed */ - cl_cbk cbk_trigger_constraint_failed; /* constraint fails at server */ - - cl_cbk cbk_receive_packet; /* callback triggered when a packet - * arrives to this trigger */ - cl_cbk cbk_receive_payload; /* callback triggered when a packet - * arrives to this trigger - * NOTE 1: cbk_receive_packet has a higher - * precedence than cbk_receive_data; if both - * of these callbacks are specified, only - * cbk_receive_data will called - * NOTE 2: the only difference between - * cbk_receive_data and cbk_receive_packet - * is that cbk_receive_packet returns - * the packet's header (hdr) in addition */ - cl_cbk cbk_route_broken; /* triggered when an i3_server when - attempting to forward a packet - along this trigger discovers that - the i3_server corres to the next - hop is down */ - - cl_cbk cbk_ratelimit_exceeded; /* callback invoked when the token-bucket - * constraints of trigger that matches the - * packet's ID are exceeded - */ - cl_trigger *trigger_htable[CL_HTABLE_SIZE]; - cl_id *id_htable[CL_HTABLE_SIZE]; - srv_address *s_array; - int num_servers; - buf_struct precomputed_opt[MAX_OPTS_MASK_SIZE]; - I3ServerList *list; - EventHeap timer_heap; /* heap managing timers */ + nw_skt_t fd; /* file descriptor for i3 packets */ + struct sockaddr_in local; /* local address, used to receive i3 traffic + * (in network format) + */ + struct in_addr local_ip_addr; /* local IP address; this field is + * needed because the IP address in + * "local" data structure is set to + * INADDR_ANY (host format) + */ + uint16_t local_port; /* local port number (host format) */ + struct timeval now; /* updated every time cl_refresh_context + * is invoked */ + + nw_skt_t tcp_fd; /* Filedes for TCP connection */ + char is_tcp; /* 1 if tcp connection is used */ + + cl_cbk cbk_trigger_not_found; /* callback invoked when there is no trigger + * matching the ID of the transmitted + * packet */ + cl_cbk cbk_server_down; /* callback invoked when an i3 server + * couldn't be contacted */ + /* following callbacks are called when the corresponding callbacks + * associated with the trigger are not defined */ + cl_cbk cbk_trigger_inserted; /* callback confirming that the trigger + * has been inserted + */ + cl_cbk cbk_trigger_refresh_failed; /* trigger cannot be inserted + * or trigger couldn't be refreshed */ + cl_cbk cbk_trigger_constraint_failed; /* constraint fails at server */ + + cl_cbk cbk_receive_packet; /* callback triggered when a packet + * arrives to this trigger */ + cl_cbk cbk_receive_payload; /* callback triggered when a packet + * arrives to this trigger + * NOTE 1: cbk_receive_packet has a higher + * precedence than cbk_receive_data; if both + * of these callbacks are specified, only + * cbk_receive_data will called + * NOTE 2: the only difference between + * cbk_receive_data and cbk_receive_packet + * is that cbk_receive_packet returns + * the packet's header (hdr) in addition */ + cl_cbk cbk_route_broken; /* triggered when an i3_server when + * attempting to forward a packet + * along this trigger discovers that + * the i3_server corres to the next + * hop is down */ + + cl_cbk cbk_ratelimit_exceeded; /* callback invoked when the token-bucket + * constraints of trigger that matches the + * packet's ID are exceeded + */ + cl_trigger * trigger_htable[CL_HTABLE_SIZE]; + cl_id * id_htable[CL_HTABLE_SIZE]; + srv_address * s_array; + int num_servers; + buf_struct precomputed_opt[MAX_OPTS_MASK_SIZE]; + I3ServerList *list; + EventHeap timer_heap; /* heap managing timers */ #define MAX_FDS 1024 - i3_fds *i3fds; /* list of file descriptors */ - uint64_t *ping_start_time; - - /** Is pinging being used to choose the best i3 server - * 0 - no - * 1 - true - */ - unsigned short use_ping; - - /** TCP socket was successfully initialized if this flag is 1. - * Else the flag is 0. - */ - int init_tcp_ctx_flag; - + i3_fds * i3fds; /* list of file descriptors */ + uint64_t * ping_start_time; + + /** Is pinging being used to choose the best i3 server + * 0 - no + * 1 - true + */ + unsigned short use_ping; + + /** TCP socket was successfully initialized if this flag is 1. + * Else the flag is 0. + */ + int init_tcp_ctx_flag; } cl_context; -/* this data structure is used to send/receive data while eliminating +/* this data structure is used to send/receive data while eliminating * an extra memory copy */ typedef struct cl_buf { #define CL_PREFIX_LEN 512 - char *data; /* pointer to the payload */ - unsigned int data_len; /* length of the payload */ - unsigned int max_len; /* maximum length that can be used for payload */ - char *internal_buf; /* pointer to the allocated buffer. the size of - * this buffer is max_len + 2*CL_PREFIX_LEN. - * the "data" pointer is between (internal_buf + - * CL_PREFIX_LEN) and (internal_buf + 2*CL_PREFIX_LEN) - */ + char * data; /* pointer to the payload */ + unsigned int data_len; /* length of the payload */ + unsigned int max_len; /* maximum length that can be used for payload */ + char * internal_buf; /* pointer to the allocated buffer. the size of + * this buffer is max_len + 2*CL_PREFIX_LEN. + * the "data" pointer is between (internal_buf + + * CL_PREFIX_LEN) and (internal_buf + 2*CL_PREFIX_LEN) + */ } cl_buf; === modified file 'i3/i3_client/i3_client_api.c' --- i3/i3_client/i3_client_api.c 2010-01-06 22:17:32 +0000 +++ i3/i3_client/i3_client_api.c 2010-02-11 11:49:47 +0000 @@ -1,9 +1,9 @@ /*************************************************************************** - i3_client_api.c - description - ------------------- - begin : Aug 20 2003 - email : istoica@xxxxxxxxxxxxxxx - ***************************************************************************/ +* i3_client_api.c - description +* ------------------- +* begin : Aug 20 2003 +* email : istoica@xxxxxxxxxxxxxxx +***************************************************************************/ #include <errno.h> @@ -26,12 +26,12 @@ * This structure stores all i3 specific information. * By default, all API functions use g_ctx. Moreover, you can have only one g_ctx * structure in a program as it is static. - * + * * If you wish to use a different instance of the context, rather - * than the one defined here, the functions in i3_client_api_ctx will be + * than the one defined here, the functions in i3_client_api_ctx will be * helpful. Those function explicitly take a cl_context structure as one * of their inputs. - */ + */ static cl_context *g_ctx = NULL; /* context associated with the process */ /************************************************************************ @@ -43,107 +43,106 @@ * calling any other I3 API functions. * * @param cfg_file The i3 configuration file from which parameters are read. - * + * * @return One of the following error codes is returned. - * <ul> + * <ul> * <li><code>CL_RET_OK</code> - Initialization was completed successfully. * <li><code>CL_RET_INVALID_CFG_FILE</code> - There was an error in the supplied configuration file. * <li><code>CL_RE_NO_CONTEXT</code> - Unable to initialize the context. * <li><code>CL_RET_DUP_CONTEXT</code> - I3 was already initialized previously. - * <li><code>CL_RET_NET_ERROR</code> - networking subsystem could not be initialized. - * You shouldn't call this function multiple times. - * </ul> + * <li><code>CL_RET_NET_ERROR</code> - networking subsystem could not be initialized. + * You shouldn't call this function multiple times. + * </ul> */ int cl_init(char *cfg_file) { - int rc; - - init_rand(); - - if (0 != nw_init()) - return CL_RET_NET_ERROR; - - if (g_ctx != NULL) - return CL_RET_DUP_CONTEXT; - - g_ctx = cl_ctx_init(cfg_file, &rc, 0); - - return rc; + int rc; + + init_rand(); + + if (0 != nw_init()) { + return CL_RET_NET_ERROR; + } + + if (g_ctx != NULL) { + return CL_RET_DUP_CONTEXT; + } + + g_ctx = cl_ctx_init(cfg_file, &rc, 0); + + return rc; } - /** * This function is called to free all resources allocated by * cl_init(). This function is usually called when you are exiting the program. - * + * * @return One of the following error codes is returned. - * <ul> - * <li><code>CL_RET_OK</code> - All resources were successfully freed. - * <li><code>CL_RET_NO_CONTEXT</code> - There was no i3 context to free. - * This error usually occurs when a cl_init() was initially omitted. - * </ul> + * <ul> + * <li><code>CL_RET_OK</code> - All resources were successfully freed. + * <li><code>CL_RET_NO_CONTEXT</code> - There was no i3 context to free. + * This error usually occurs when a cl_init() was initially omitted. + * </ul> */ int cl_exit() { - int rc; + int rc; - rc = cl_ctx_exit(g_ctx); - g_ctx = NULL; - return rc; + rc = cl_ctx_exit(g_ctx); + g_ctx = NULL; + return rc; } - /************************************************************************ - * cl_selct - function that replaces the select() function - * (sys/select.h) Either this function or cl_loop() should be - * invoked at the end of every client program since - * cl_select()/cl_loop() are responsibe with the trigger + * cl_selct - function that replaces the select() function + * (sys/select.h) Either this function or cl_loop() should be + * invoked at the end of every client program since + * cl_select()/cl_loop() are responsibe with the trigger * refreshing and processing the options of the received packets. ***********************************************************************/ /** * This function should be called in the client program after all initialization * has been completed. - * This function loops indefinitely and does not return unless there is an - * error. It listens for packets on the i3 socket and other sockets added - * using cl_register_fd_callback(). + * This function loops indefinitely and does not return unless there is an + * error. It listens for packets on the i3 socket and other sockets added + * using cl_register_fd_callback(). */ -int cl_select(int n, fd_set *readfds, fd_set *writefds, - fd_set *exceptfds, struct timeval *cl_to) +int cl_select(int n, fd_set *readfds, fd_set *writefds, + fd_set *exceptfds, struct timeval *cl_to) { - if (g_ctx == NULL) - return CL_RET_NO_CONTEXT; - return cl_ctx_select(g_ctx, n, readfds, writefds, exceptfds, cl_to); /*xxx */ + if (g_ctx == NULL) { + return CL_RET_NO_CONTEXT; + } + return cl_ctx_select(g_ctx, n, readfds, writefds, exceptfds, cl_to); /*xxx */ } - int cl_loop(void) { - return cl_ctx_loop(g_ctx); + return cl_ctx_loop(g_ctx); } - /** * This function is used to create a trigger which points to the client, - * i.e. the machine on which this function is executed. + * i.e. the machine on which this function is executed. * Please note that this function does not insert the trigger into the i3 infrastructure. * <code>cl_insert_trigger</code> is used to insert the trigger into the i3 infrastructure. - * + * * @param id The i3 Id of the trigger to be created. - * + * * @param prefix_len The length of the prefix of the id to be used for matching. - * + * * @param key The key for this trigger. <br> - * The key is equal to h_l(id) if the trigger is left constrained, and<br> + * The key is equal to h_l(id) if the trigger is left constrained, and<br> * h_r(id) if the trigger is right constrained, <br> * where h_l and h_r are two one-way hash functions. - * The key field of the ID is upadted to h_l(key) or h_r(key). - * + * The key field of the ID is upadted to h_l(key) or h_r(key). + * * @param flags Flags are used to specify the properties of the trigger being created. * The following flags can be used individually or ORed together. * <ul> - * <li><code>CL_TRIGGER_CFLAG_R_CONSTRAINT</code> - Make the trigger right constrained. + * <li><code>CL_TRIGGER_CFLAG_R_CONSTRAINT</code> - Make the trigger right constrained. * <li><code>CL_TRIGGER_CFLAG_L_CONSTRAINT</code> - Make the trigger left constrained. - * <li><code>CL_TRIGGER_CFLAG_PUBLIC</code> - Make this a public trigger. If this is flag is + * <li><code>CL_TRIGGER_CFLAG_PUBLIC</code> - Make this a public trigger. If this is flag is * not used, the trigger is private by default. Please note that a public trigger must be left constrained. * This means that you cannot use the flags <code>CL_TRIGGER_CFLAG_R_CONSTRAINT</code> and * CL_TRIGGER_CFLAG_PUBLIC together. @@ -153,135 +152,131 @@ * the id by calling set_public_id before using it. The same applies to CL_TRIGGER_CFLAG_PRIVATE too (Note * that CL_TRIGGER_CFLAG_PRIVATE is assumed by default unless CL_TRIGGER_CLFAG_PUBLIC is specified.) * </ul> - * + * * @return A pointer to the created trigger. */ -cl_trigger *cl_create_trigger(ID *id, uint16_t prefix_len, Key *key, - uint16_t flags) +cl_trigger *cl_create_trigger(ID *id, uint16_t prefix_len, Key *key, + uint16_t flags) { - int rc; - return cl_ctx_create_trigger(g_ctx, id, prefix_len, key, flags, &rc); + int rc; + return cl_ctx_create_trigger(g_ctx, id, prefix_len, key, flags, &rc); } - /** * This function is similar to cl_create_trigger except that the created - * trigger points to the specificed stack of i3 IDs instead of the + * trigger points to the specificed stack of i3 IDs instead of the * client machine. * * Please note that this function does not insert the trigger into the i3 infrastructure. * <code>cl_insert_trigger</code> is used to insert the trigger into the i3 infrastructure. * * @param id The i3 Id of the trigger to be created. - * + * * @param prefix_len The length of the prefix of the id to be used for matching. - * - * @param stack The stack of i3 ids to which this trigger points + * + * @param stack The stack of i3 ids to which this trigger points * @param stack_len The number of i3 ids in the stack. - * + * * @param flags Flags are used to specify the properties of the trigger being created. * The following flags can be used individually or ORed together. * <ul> - * <li><code>CL_TRIGGER_CFLAG_R_CONSTRAINT</code> - Make the trigger right constrained. + * <li><code>CL_TRIGGER_CFLAG_R_CONSTRAINT</code> - Make the trigger right constrained. * <li><code>CL_TRIGGER_CFLAG_L_CONSTRAINT</code> - Make the trigger left constrained. - * <li><code>CL_TRIGGER_CFLAG_PUBLIC</code> - Make this a public trigger. If this is flag is + * <li><code>CL_TRIGGER_CFLAG_PUBLIC</code> - Make this a public trigger. If this is flag is * not used, the trigger is private by default. Please note that a public trigger must be left constrained. * This means that you cannot use the flags <code>CL_TRIGGER_CFLAG_R_CONSTRAINT</code> and * CL_TRIGGER_CFLAG_PUBLIC together. * </ul> - * + * * @return A pointer to the created trigger. */ -cl_trigger *cl_create_trigger_stack(ID *id, uint16_t prefix_len, - ID *stack, int stack_len, - uint16_t flags) +cl_trigger *cl_create_trigger_stack(ID *id, uint16_t prefix_len, + ID *stack, int stack_len, + uint16_t flags) { - int rc; - return cl_ctx_create_trigger_stack(g_ctx, id, prefix_len, stack, - stack_len, flags, &rc); + int rc; + return cl_ctx_create_trigger_stack(g_ctx, id, prefix_len, stack, + stack_len, flags, &rc); } - /** * This function is used to deallocate a trigger created by - * <code>cl_create_trigger. This function not only frees up + * <code>cl_create_trigger. This function not only frees up * the memory used by the trigger in the local system, but also * removes it from the i3 infrastructure. * * @param ctr Pointer to the trigger to be destroyed. * * @return One of the following codes is returned. - * <ul> - * <li><code>CL_RET_OK</code> - The trigger was successfully destroyed. - * <li><code>CL_RET_NO_CONTEXT</code> - No i3 context was available or - * invalid context. Probably cl_init() was not called initially. - * </ul> + * <ul> + * <li><code>CL_RET_OK</code> - The trigger was successfully destroyed. + * <li><code>CL_RET_NO_CONTEXT</code> - No i3 context was available or + * invalid context. Probably cl_init() was not called initially. + * </ul> */ int cl_destroy_trigger(cl_trigger *ctr) { - return cl_ctx_destroy_trigger(g_ctx, ctr); + return cl_ctx_destroy_trigger(g_ctx, ctr); } - /** - * This function inserts the specified trigger into the i3 + * This function inserts the specified trigger into the i3 * infrastructure. * * @param ctr Pointer to the trigger to be inserted. * @param flags The following flags can be specified at trigger insertion. - * <ul> - * <li><code>CL_IFLAGS_TRIGGER_LOCAL</code> - This trigger should be inserted locally, i.e. not - * in the i3 infrastructure. - * <li><code>CL_IFLAGS_TRIGGER_ALLOW_SHORTCUT</code> - This trigger allows shortcuts. - * </ul> + * <ul> + * <li><code>CL_IFLAGS_TRIGGER_LOCAL</code> - This trigger should be inserted locally, i.e. not + * in the i3 infrastructure. + * <li><code>CL_IFLAGS_TRIGGER_ALLOW_SHORTCUT</code> - This trigger allows shortcuts. + * </ul> * @return One of the following codes is returned. - * <ul> - * <li><code>CL_RET_OK</code> - The trigger was successfully submitted for insertion. - * The trigger insertion callbacks (if any were registered) will be executed when - * a confirmation message for trigger insertion is received from the infrastructure. - * - * <li><code>CL_RET_NO_CONTEXT</code> - No i3 context was available or - * invalid context. Probably cl_init() was not called initially. - * - * <li><code>CL_RET_NO_TRIGGER</code> - The trigger to be inserted is NULL. - * </ul> + * <ul> + * <li><code>CL_RET_OK</code> - The trigger was successfully submitted for insertion. + * The trigger insertion callbacks (if any were registered) will be executed when + * a confirmation message for trigger insertion is received from the infrastructure. + * + * <li><code>CL_RET_NO_CONTEXT</code> - No i3 context was available or + * invalid context. Probably cl_init() was not called initially. + * + * <li><code>CL_RET_NO_TRIGGER</code> - The trigger to be inserted is NULL. + * </ul> */ -int cl_insert_trigger(cl_trigger *ctr, uint16_t flags) +int cl_insert_trigger(cl_trigger *ctr, uint16_t flags) { - return cl_ctx_insert_trigger(g_ctx, ctr, flags); + return cl_ctx_insert_trigger(g_ctx, ctr, flags); } /** * This function removes the specified trigger from the i3 infrastructure. * However, it is not destroyed from the local system, i.e. its data structures - * are not deallocated. It can be reinserted at a later point using + * are not deallocated. It can be reinserted at a later point using * <code>cl_insert_trigger</code>. * * @param ctr The trigger to be removed. * * @return One of the following codes is returned. - * <ul> - * <li><code>CL_RET_OK</code> - The trigger was successfully submitted for removal. - * - * <li><code>CL_RET_NO_CONTEXT</code> - No i3 context was available or - * invalid context. Probably cl_init() was not called initially. - * - * <li><code>CL_RET_NO_TRIGGER</code> - The trigger to be removed is NULL. - * </ul> + * <ul> + * <li><code>CL_RET_OK</code> - The trigger was successfully submitted for removal. + * + * <li><code>CL_RET_NO_CONTEXT</code> - No i3 context was available or + * invalid context. Probably cl_init() was not called initially. + * + * <li><code>CL_RET_NO_TRIGGER</code> - The trigger to be removed is NULL. + * </ul> */ int cl_remove_trigger(cl_trigger *ctr) { - return cl_ctx_remove_trigger(g_ctx, ctr); + return cl_ctx_remove_trigger(g_ctx, ctr); } - /** - * This function limits the traffic forwarded by a trigger using - * token-bucket constraints. + * This function limits the traffic forwarded by a trigger using + * token-bucket constraints. * * Note 1: This function takes action only if/when the trigger - * is inserted in the i3 infrastructure. If the trigger is local - * (i.e. it was inserted using the + * is inserted in the i3 infrastructure. If the trigger is local + * (i.e. it was inserted using the * <li><code>CL_IFLAGS_TRIGGER_LOCAL</code></li> flag) this function * has no effect. * @@ -292,9 +287,9 @@ * * @param ctr The trigger to be rate limited using a token bucket. * - * @param type The type of token bucket, specifying data units. - Possible values are TOKEN_BUKET_PACKET and - TOKEN_BUKET_BYTE, respectively. + * @param type The type of token bucket, specifying data units. + * Possible values are TOKEN_BUKET_PACKET and + * TOKEN_BUKET_BYTE, respectively. * * @param depth Token bucket depth (bytes or packets, depending on "type") * @@ -303,224 +298,224 @@ * @param R Token bucket peek rate (Bps or pps) * * @return One of the following codes is returned. - * <ul> - * <li><code>CL_RET_OK</code> - The trigger was successfully submitted for removal. - * - * <li><code>CL_RET_NO_CONTEXT</code> - No i3 context was available or - * invalid context. Probably cl_init() was not called initially. - * - * <li><code>CL_RET_NO_TRIGGER</code> - The trigger does not exist. - * </ul> + * <ul> + * <li><code>CL_RET_OK</code> - The trigger was successfully submitted for removal. + * + * <li><code>CL_RET_NO_CONTEXT</code> - No i3 context was available or + * invalid context. Probably cl_init() was not called initially. + * + * <li><code>CL_RET_NO_TRIGGER</code> - The trigger does not exist. + * </ul> */ int cl_trigger_ratelimit(cl_trigger *ctr, uint8_t type, - uint32_t depth, uint32_t r, uint32_t R) + uint32_t depth, uint32_t r, uint32_t R) { - return cl_ctx_trigger_ratelimit(g_ctx, ctr, type, depth, r, R); + return cl_ctx_trigger_ratelimit(g_ctx, ctr, type, depth, r, R); } /** - This function is used to register a callback associated with the current context. This - is more general than associating a callback with a particular trigger. - - @param cbk_type The callback type. It should be equal to one of the following values: - <ol> - - <li><b>CL_CBK_TRIGGER_INSERTED</b> : This callback is invoked when the client receives the first ack as a result of a trigger insertion. - - <li><b>CL_CBK_TRIGGER_REFRESH_FAILED</b> : This callback is invoked when the refreshing of a trigger fails. A refreshing failure occurs when none of the client's refreshing messages is acked during a refresh period which has a duration of TRIGGER_REFRESH_PERIOD sec. The client refreshes a trigger by sending a refreshing message MAX_NUM_TRIG_RETRIES*ACK_TIMEOUT before the refreshing period expires. If the first refresh message is not acked, the client resends the refresh message approximately every ACK_TIMEOUT sec. A typical response of the client to this callback is to reinsert the trigger. - - <li><b>CL_CBK_TRIGGER_NOT_FOUND</b> : This callback is invoked when the client sends packets to an ID id, and there is no trigger in the network matching this id. - - <li><b>CL_CBK_RATELIMIT_EXCEEDED</b> : This callback is invoked when the client packet (sent to an ID id) is dropped due to the violation of the token-bucket traffic constraints (associated with the trigger whose ID is id). - - is no trigger in the network matching this id. - - <li><b>CL_CBK_TRIGGER_CONSTRAINT_FAILED</b> : This callback invoked when an unconstrained trigger insertion is attempted. - - <li><b>CL_CBK_RECEIVE_PACKET</b> : This callback is invoked on receiving an i3 packet. - - <li><b>CL_CBK_RECEIVE_PAYLOAD</b> : This callback is invoked upon receiving a data packet. This callback is suppressed by the CL_CBK_RECEIVE_PACKET callback. - - <li><b>CL_CBK_SERVER_DOWN</b> : This callback is invoked when the client concludes than an i3 server is down. This happens when the client either receives no acks (in the form of I3_OPT_CACHE_ADDR replies) to sending packets to that server during a refresh period of ID_REFRESH_PERIOD sec, or when the client receives no acks to three consecutive I3_OPT_REQUEST_FOR_CACHE queries. - - <li><b>CL_CBK_ROUTE_BROKEN</b> : This callback is invoked when server indicates that the i3server corresponding to the next hop is dead, and some action is needed to recover. - </ol> - - @param fun The pointer to the function to be executed when the callback is invoked. - This function pointer should point to a function with following signature:<br> - - <center><code>void funName (void *ctx_data, void *data, void *fun_ctx)</code></center> - - The parameters to the callback function are used as follows: - - <ul> - - <li><b>ctx_data</b>: This is parameter is used to pass some context info when the callback is invoked. For example, for a callback of type CL_CBK_TRIGGER_INSERTED, the pointer to the <code>cl_trigger</code> which was inserted is passed via this argument. Please note that the function signature must assign the type <code>void *</code> to this argument. The argument must be appropriately cast before use inside the function body. - - <li><b>data</b>: This parameter is used to pass back some data which is generated at the time of callback invocation. - For example, in the callback of type CL_CBK_RECEIVE_PAYLOAD, the payload of the packet received is passed through this argument. - - <li><b>fun_ctx</b>: This parameter is used to pass back data which was stored at the time of callback registration. - - </ul> - - We now describe the values passed via the arguments of the callback function for the different callback types in the following table. - - <table> - <tr> - <td>CALLBACK TYPE</td> - <td>ctx_data</td> - <td>data</td> - <td>fun_ctx</td> - </tr> - - <tr> - <td>CL_CBK_TRIGGER_INSERTED</td> - <td><code>cl_trigger* t</code>, where t represents the inserted trigger</td> - <td><code>NULL</code> - <td>function context passed at callback registration</td> - </tr> - - <tr> - <td>CL_CBK_TRIGGER_REFRESH_FAILED</td> - <td><code>cl_trigger* t</code>, where t represents the trigger whose refresh failed</td> - <td><code>NULL</code> - <td>function context passed at callback registration</td> - </tr> - - <tr> - <td>CL_CBK_TRIGGER_NOT_FOUND</td> - <td><code>ID *id</code>, the id for which no matching trigger was found.</td> - <td><code>NULL</code></td> - <td>function context passed at callback registration</td> - </tr> - - <tr> - <td>CL_CBK_RATELIMIT_EXCEEDED</td> - <td><code>ID *id</code>, the id whose token-bucket traffic constraints were violated.</td> - <td><code>NULL</code></td> - <td>function context passed at callback registration</td> - </tr> - - <tr> - <td>CL_CBK_TRIGGER_CONSTRAINT_FAILED</td> - <td><code>ID *id</code>, the id for which trigger constraint failed.</td> - <td><code>NULL</code></td> - <td>function context passed at callback registration</td> - </tr> - - <tr> - <td>CL_CBK_RECEIVE_PACKET</td> - <td><code>cl_trigger* t</code>, the trigger matching the packet's ID</td> - <td><code>cbk_packet* pkt</code> encapsulates the header and payload of the received packet. - Please note that the callback function should deallocate the memory pointed to by pkt after - it is no longer needed by using <code>free(pkt)</code>. This frees up only the temporary encapsulating - cbk_packet and not the actual contents of the packet.</td> - <td>function context passed at callback registration</td> - </tr> - - <tr> - <td>CL_CBK_RECEIVE_PAYLOAD</td> - <td><code>cl_trigger* t</code>, the trigger matching the packet's ID</td> - <td><code>cl_buf *b</code>, the payload of the data packet received</td> - <td>function context passed at callback registration</td> - </tr> - - <tr> - <td>CL_CBK_SERVER_DOWN</td> - <td><code>struct in_addr *ip_addr</code>, the IP address of the server which is down</td> - <td><code>uint16_t *portNum</code>, the port on which i3 was supposed to have been running on the down server (TODO: It will better to aggregate the IP address and port info into a single structure as part of the first param.)</td> - <td>function context passed at callback registration</td> - </tr> - - <tr> - <td>CL_CBK_ROUTE_BROKEN</td> - <td><code>cl_trigger *t</code>, the trigger whose route has been broken [[VERIFY: unclear]]</td> - <td><code>NULL</code></td> - <td>function context passed at callback registration</td> - </tr> - </table> - - @return One of the following codes is returned. - <ul> - <li><code>CL_RET_OK</code> - - <li><code>CL_RET_NO_CONTEXT</code> - No i3 context was available or - invalid context. Probably cl_init() was not called initially. - - </ul> + * This function is used to register a callback associated with the current context. This + * is more general than associating a callback with a particular trigger. + * + * @param cbk_type The callback type. It should be equal to one of the following values: + * <ol> + * + * <li><b>CL_CBK_TRIGGER_INSERTED</b> : This callback is invoked when the client receives the first ack as a result of a trigger insertion. + * + * <li><b>CL_CBK_TRIGGER_REFRESH_FAILED</b> : This callback is invoked when the refreshing of a trigger fails. A refreshing failure occurs when none of the client's refreshing messages is acked during a refresh period which has a duration of TRIGGER_REFRESH_PERIOD sec. The client refreshes a trigger by sending a refreshing message MAX_NUM_TRIG_RETRIES*ACK_TIMEOUT before the refreshing period expires. If the first refresh message is not acked, the client resends the refresh message approximately every ACK_TIMEOUT sec. A typical response of the client to this callback is to reinsert the trigger. + * + * <li><b>CL_CBK_TRIGGER_NOT_FOUND</b> : This callback is invoked when the client sends packets to an ID id, and there is no trigger in the network matching this id. + * + * <li><b>CL_CBK_RATELIMIT_EXCEEDED</b> : This callback is invoked when the client packet (sent to an ID id) is dropped due to the violation of the token-bucket traffic constraints (associated with the trigger whose ID is id). + * + * is no trigger in the network matching this id. + * + * <li><b>CL_CBK_TRIGGER_CONSTRAINT_FAILED</b> : This callback invoked when an unconstrained trigger insertion is attempted. + * + * <li><b>CL_CBK_RECEIVE_PACKET</b> : This callback is invoked on receiving an i3 packet. + * + * <li><b>CL_CBK_RECEIVE_PAYLOAD</b> : This callback is invoked upon receiving a data packet. This callback is suppressed by the CL_CBK_RECEIVE_PACKET callback. + * + * <li><b>CL_CBK_SERVER_DOWN</b> : This callback is invoked when the client concludes than an i3 server is down. This happens when the client either receives no acks (in the form of I3_OPT_CACHE_ADDR replies) to sending packets to that server during a refresh period of ID_REFRESH_PERIOD sec, or when the client receives no acks to three consecutive I3_OPT_REQUEST_FOR_CACHE queries. + * + * <li><b>CL_CBK_ROUTE_BROKEN</b> : This callback is invoked when server indicates that the i3server corresponding to the next hop is dead, and some action is needed to recover. + * </ol> + * + * @param fun The pointer to the function to be executed when the callback is invoked. + * This function pointer should point to a function with following signature:<br> + * + * <center><code>void funName (void *ctx_data, void *data, void *fun_ctx)</code></center> + * + * The parameters to the callback function are used as follows: + * + * <ul> + * + * <li><b>ctx_data</b>: This is parameter is used to pass some context info when the callback is invoked. For example, for a callback of type CL_CBK_TRIGGER_INSERTED, the pointer to the <code>cl_trigger</code> which was inserted is passed via this argument. Please note that the function signature must assign the type <code>void *</code> to this argument. The argument must be appropriately cast before use inside the function body. + * + * <li><b>data</b>: This parameter is used to pass back some data which is generated at the time of callback invocation. + * For example, in the callback of type CL_CBK_RECEIVE_PAYLOAD, the payload of the packet received is passed through this argument. + * + * <li><b>fun_ctx</b>: This parameter is used to pass back data which was stored at the time of callback registration. + * + * </ul> + * + * We now describe the values passed via the arguments of the callback function for the different callback types in the following table. + * + * <table> + * <tr> + * <td>CALLBACK TYPE</td> + * <td>ctx_data</td> + * <td>data</td> + * <td>fun_ctx</td> + * </tr> + * + * <tr> + * <td>CL_CBK_TRIGGER_INSERTED</td> + * <td><code>cl_trigger* t</code>, where t represents the inserted trigger</td> + * <td><code>NULL</code> + * <td>function context passed at callback registration</td> + * </tr> + * + * <tr> + * <td>CL_CBK_TRIGGER_REFRESH_FAILED</td> + * <td><code>cl_trigger* t</code>, where t represents the trigger whose refresh failed</td> + * <td><code>NULL</code> + * <td>function context passed at callback registration</td> + * </tr> + * + * <tr> + * <td>CL_CBK_TRIGGER_NOT_FOUND</td> + * <td><code>ID *id</code>, the id for which no matching trigger was found.</td> + * <td><code>NULL</code></td> + * <td>function context passed at callback registration</td> + * </tr> + * + * <tr> + * <td>CL_CBK_RATELIMIT_EXCEEDED</td> + * <td><code>ID *id</code>, the id whose token-bucket traffic constraints were violated.</td> + * <td><code>NULL</code></td> + * <td>function context passed at callback registration</td> + * </tr> + * + * <tr> + * <td>CL_CBK_TRIGGER_CONSTRAINT_FAILED</td> + * <td><code>ID *id</code>, the id for which trigger constraint failed.</td> + * <td><code>NULL</code></td> + * <td>function context passed at callback registration</td> + * </tr> + * + * <tr> + * <td>CL_CBK_RECEIVE_PACKET</td> + * <td><code>cl_trigger* t</code>, the trigger matching the packet's ID</td> + * <td><code>cbk_packet* pkt</code> encapsulates the header and payload of the received packet. + * Please note that the callback function should deallocate the memory pointed to by pkt after + * it is no longer needed by using <code>free(pkt)</code>. This frees up only the temporary encapsulating + * cbk_packet and not the actual contents of the packet.</td> + * <td>function context passed at callback registration</td> + * </tr> + * + * <tr> + * <td>CL_CBK_RECEIVE_PAYLOAD</td> + * <td><code>cl_trigger* t</code>, the trigger matching the packet's ID</td> + * <td><code>cl_buf *b</code>, the payload of the data packet received</td> + * <td>function context passed at callback registration</td> + * </tr> + * + * <tr> + * <td>CL_CBK_SERVER_DOWN</td> + * <td><code>struct in_addr *ip_addr</code>, the IP address of the server which is down</td> + * <td><code>uint16_t *portNum</code>, the port on which i3 was supposed to have been running on the down server (TODO: It will better to aggregate the IP address and port info into a single structure as part of the first param.)</td> + * <td>function context passed at callback registration</td> + * </tr> + * + * <tr> + * <td>CL_CBK_ROUTE_BROKEN</td> + * <td><code>cl_trigger *t</code>, the trigger whose route has been broken [[VERIFY: unclear]]</td> + * <td><code>NULL</code></td> + * <td>function context passed at callback registration</td> + * </tr> + * </table> + * + * @return One of the following codes is returned. + * <ul> + * <li><code>CL_RET_OK</code> + * + * <li><code>CL_RET_NO_CONTEXT</code> - No i3 context was available or + * invalid context. Probably cl_init() was not called initially. + * + * </ul> */ -int cl_register_callback( - uint16_t cbk_type, - void (*fun)(void *ctx_data, void *data, void *fun_ctx), - void *fun_ctx) +int cl_register_callback(uint16_t cbk_type, + void (*fun)(void *ctx_data, void *data, void *fun_ctx), + void *fun_ctx) { - if (g_ctx == NULL) - return CL_RET_NO_CONTEXT; + if (g_ctx == NULL) { + return CL_RET_NO_CONTEXT; + } - return cl_ctx_register_callback(g_ctx, cbk_type, fun, fun_ctx); + return cl_ctx_register_callback(g_ctx, cbk_type, fun, fun_ctx); } /* - * This function is used to register a callback associated with a - * particular trigger. These callbacks are similar to the callbacks + * This function is used to register a callback associated with a + * particular trigger. These callbacks are similar to the callbacks * asssociated with the context (see cl_register_callback). - * A callback associated with a trigger has strict priority over the same + * A callback associated with a trigger has strict priority over the same * callback associated with the context. * * @param t The trigger with which the callback is associated. * @param cbk_type The callback type should be one of the following: - * <ol> - * <li><code>CL_CBK_TRIGGER_INSERTED<code> - * This callback is invoked when the client receives the first ack - * as a result of a trigger insertion. + * <ol> + * <li><code>CL_CBK_TRIGGER_INSERTED<code> + * This callback is invoked when the client receives the first ack + * as a result of a trigger insertion. * - * <li><code>CL_CBK_TRIGGER_REFRESH_FAILED</code> - * This callback is invoked when the refreshing of a trigger fails. - * A refreshing failure occurs when none of the client's refreshing messages - * is acked during a refresh period which has a duration of - * <code>TRIGGER_REFRESH_PERIOD</code> sec. The client refreshes a trigger by - * sending a refreshing message <code>MAX_NUM_TRIG_RETRIES * ACK_TIMEOUT</code> sec - * before the refreshing period expires. If the first refresh message is not - * acked, the client resends the refresh message approximately every + * <li><code>CL_CBK_TRIGGER_REFRESH_FAILED</code> + * This callback is invoked when the refreshing of a trigger fails. + * A refreshing failure occurs when none of the client's refreshing messages + * is acked during a refresh period which has a duration of + * <code>TRIGGER_REFRESH_PERIOD</code> sec. The client refreshes a trigger by + * sending a refreshing message <code>MAX_NUM_TRIG_RETRIES * ACK_TIMEOUT</code> sec + * before the refreshing period expires. If the first refresh message is not + * acked, the client resends the refresh message approximately every * <code>ACK_TIMEOUT</code> sec. * * A typical response of the client to this callback is to reinsert the trigger * using the cl_reinsert_trigger function. - * - * <li><code>CL_CBK_RECEIVE_PACKET</code> - * This callback is invoked upon receiving an i3 packet. - * - * The callback function has the following - * arguments: + * + * <li><code>CL_CBK_RECEIVE_PACKET</code> + * This callback is invoked upon receiving an i3 packet. + * + * The callback function has the following + * arguments: * fun(i3_trigger *t, i3_header *hdr, - * cl_buf *b, void *data), where "t" + * cl_buf *b, void *data), where "t" * represents the trigger matching the - * the packet's ID, "hdr" represents the - * packet's header, "b" contains the + * the packet's ID, "hdr" represents the + * packet's header, "b" contains the * packet's payload, and "data" represents * the client's data. * - * <li><code>CL_CBK_RECEIVE_PAYLOAD</code> - * This callback is invoked upon receiving a data packet. - * This callback is suppressed by the <code>CL_CBK_RECEIVE_PACKET</code> callback. + * <li><code>CL_CBK_RECEIVE_PAYLOAD</code> + * This callback is invoked upon receiving a data packet. + * This callback is suppressed by the <code>CL_CBK_RECEIVE_PACKET</code> callback. * * * @param fun The pointer to the function to be executed when the callback is invoked. * This function pointer should point to a function with following signature:<br> - * + * * <center><code>void funName (cl_trigger *ctr, void *data, void *fun_ctx)</code></center> - * + * * The parameters to the callback function are used as follows: - * + * * <ul> - * + * * <li><b>ctr</b>: This parameter is used to pass a pointer to the trigger on which this * callback was registered. - * + * * <li><b>data</b>: This parameter is used to pass back some data which is generated - * at the time of callback invocation. For example, in the callback of type - * <code>CL_CBK_RECEIVE_PAYLOAD</code>, the payload of the packet received is passed + * at the time of callback invocation. For example, in the callback of type + * <code>CL_CBK_RECEIVE_PAYLOAD</code>, the payload of the packet received is passed * via this argument. * * <li><b>fun_ctx</b>: This parameter is used to pass back data which was stored i @@ -528,7 +523,7 @@ * * </ul> * - * We now describe the values passed via the arguments of the callback function for the + * We now describe the values passed via the arguments of the callback function for the * different callback types in the following table. * * <table> @@ -538,21 +533,21 @@ * <td>data</td> * <td>fun_ctx</td> * </tr> - * + * * <tr> * <td>CL_CBK_TRIGGER_INSERTED</td> * <td>ctr is a pointer to the inserted trigger</td> * <td><code>NULL</code> * <td>function context passed at callback registration</td> * </tr> - * + * * <tr> * <td>CL_CBK_TRIGGER_REFRESH_FAILED</td> * <td>ctr is a pointer to the trigger whose refresh failed</td> * <td><code>NULL</code> * <td>function context passed at callback registration</td> * </tr> - * + * * <tr> * <td>CL_CBK_RECEIVE_PAYLOAD</td> * <td>ctr is a pointer to the trigger matching the packet's ID</td> @@ -561,71 +556,72 @@ * </tr> * </table> * @return One of the following codes is returned. - * <ul> - * <li><code>CL_RET_OK</code> - - * - * <li><code>CL_RET_NO_CONTEXT</code> - No i3 context was available or - * invalid context. Probably cl_init() was not called initially. - * - * <li><code>CL_RET_NO_TRIGGER</code> - The trigger on which the callback - * is to be registered is NULL. - * </ul> + * <ul> + * <li><code>CL_RET_OK</code> - + * + * <li><code>CL_RET_NO_CONTEXT</code> - No i3 context was available or + * invalid context. Probably cl_init() was not called initially. + * + * <li><code>CL_RET_NO_TRIGGER</code> - The trigger on which the callback + * is to be registered is NULL. + * </ul> */ -int cl_register_trigger_callback(cl_trigger *ctr, uint16_t cbk_type, - void (*fun)(void*,void* data, void* fun_ctx), void *fun_ctx) //DILIP +int cl_register_trigger_callback(cl_trigger *ctr, uint16_t cbk_type, + void (*fun)(void *, void *data, void *fun_ctx), void *fun_ctx) //DILIP { - if (g_ctx == NULL) - return CL_RET_NO_CONTEXT; - - if (!ctr) - return CL_RET_NO_TRIGGER; - - return cl_register_trigger_callback1(ctr, cbk_type, fun, fun_ctx); + if (g_ctx == NULL) { + return CL_RET_NO_CONTEXT; + } + + if (!ctr) { + return CL_RET_NO_TRIGGER; + } + + return cl_register_trigger_callback1(ctr, cbk_type, fun, fun_ctx); } /* - * This function is used to register a call back on a file descriptor open + * This function is used to register a call back on a file descriptor open * for reading (e.g., a socket file descriptor). The callback function is * executed whenever there is data available to be read on the file descriptor. - * This callback does NOT read the data from fd on application's behalf; + * This callback does NOT read the data from fd on application's behalf; * the application has to explicitly read data from fd. * The application is also responsible for opening and closing the associated file/socket. * * @param fd The file descriptor on which the callback is to be registered. * @param type The type of the file descriptor can be one of the following: * <ul> - * <li><code>CL_FD_TYPE_READ</code> - * <li><code>CL_FD_TYPE_WRITE</code> - * <li><code>CL_FD_TYPE_EXCEPT</code> + * <li><code>CL_FD_TYPE_READ</code> + * <li><code>CL_FD_TYPE_WRITE</code> + * <li><code>CL_FD_TYPE_EXCEPT</code> * </ul> * * @param fun The function to be called back. The function should have the * following signature:<br> * <center><code>void funName(int fd, void *data)</code></center> * I - * @param data Application data to be passed when the callback is invoked + * @param data Application data to be passed when the callback is invoked */ -int cl_register_fd_callback(int fd, int type, void (*fun)(int, void*), void *data) +int cl_register_fd_callback(int fd, int type, void (*fun)(int, void *), void *data) { - return cl_ctx_register_fd_callback(g_ctx, fd, type, fun, data); + return cl_ctx_register_fd_callback(g_ctx, fd, type, fun, data); } - /** * This function unregisters the callback associated with the specified file * descriptor. This should be done once the file descriptor is closed. * @param fd The file descriptor whose callback is to be removed. * @param type The type of the file descriptor can be one of the following: * <ul> - * <li><code>CL_FD_TYPE_READ</code> - * <li><code>CL_FD_TYPE_WRITE</code> - * <li><code>CL_FD_TYPE_EXCEPT</code> + * <li><code>CL_FD_TYPE_READ</code> + * <li><code>CL_FD_TYPE_WRITE</code> + * <li><code>CL_FD_TYPE_EXCEPT</code> * </ul> * */ int cl_unregister_fd_callback(int fd, int type) { - return cl_ctx_unregister_fd_callback(g_ctx, fd, type); + return cl_ctx_unregister_fd_callback(g_ctx, fd, type); } /** @@ -636,72 +632,72 @@ * @param data Application data passed back to the application when the * callback is invoked. * - * @return A pointer to the created timer. + * @return A pointer to the created timer. */ cl_timer *cl_set_timer(struct timeval *tv, void (*fun)(void *), void *data) { - return cl_ctx_set_timer(g_ctx, tv, fun, data); + return cl_ctx_set_timer(g_ctx, tv, fun, data); } - -/** +/** * This function is used to cancel an existing timer. * @param ct The timer data structure of the timer to be cancelled. * This data structure is returned by <code>cl_set_timer</code>. */ void cl_cancel_timer(cl_timer *ct) { - ct->cancel = TRUE; + ct->cancel = TRUE; } /* - * This function is used to send a packet addressed to a stack + * This function is used to send a packet addressed to a stack * of i3 ids. - * + * * @param stack The stack of i3 ids to which the packet is to be sent. * The stack is represented as an array of IDs; stack[0] * represents the ID where the packet is sent next - * - * @param stack_len The number of IDs in the stack + * + * @param stack_len The number of IDs in the stack * @param clb The packet payload * @param flags The flags associated with sending a packet. It can take on the * following values: * * <ul> - * <li><code>CL_PKT_FLAG_ALLOW_SHORTCUT</code> All this packet to be shortcutted. + * <li><code>CL_PKT_FLAG_ALLOW_SHORTCUT</code> All this packet to be shortcutted. * </ul> * * @return One of the following codes is returned. * - * <ul> - * <li><code>CL_RET_OK</code> - Packet was successfully sent. - * <li><code>CL_RET_NO_CONTEXT</code> - No i3 context was found. - * Probably cl_init() was omitted initially. - * <li><code>CL_RET_INVALID_STACK_LEN</code> - The length of the stack is incorrect. - * <li><code>CL_RET_MSG_SIZE</code> - the packet payload is - * too large to be transferred. - * <li><code>CL_RET_NO_SERVERS</code> - no i3 servers are - * known or reachable. - * <li><code>CL_RET_NET_ERROR</code> - the packet was not - * sent due to a low-level network or socket error. - * </ul> - */ -int cl_send_stack(ID *stack, int stack_len, - cl_buf *clb, uint16_t flags) + * <ul> + * <li><code>CL_RET_OK</code> - Packet was successfully sent. + * <li><code>CL_RET_NO_CONTEXT</code> - No i3 context was found. + * Probably cl_init() was omitted initially. + * <li><code>CL_RET_INVALID_STACK_LEN</code> - The length of the stack is incorrect. + * <li><code>CL_RET_MSG_SIZE</code> - the packet payload is + * too large to be transferred. + * <li><code>CL_RET_NO_SERVERS</code> - no i3 servers are + * known or reachable. + * <li><code>CL_RET_NET_ERROR</code> - the packet was not + * sent due to a low-level network or socket error. + * </ul> + */ +int cl_send_stack(ID *stack, int stack_len, + cl_buf *clb, uint16_t flags) { - return cl_ctx_send_stack(g_ctx, stack, stack_len, clb, flags); + return cl_ctx_send_stack(g_ctx, stack, stack_len, clb, flags); } + /************************************************************************ * Returns RTT of given addr (in host format) ***********************************************************************/ int cl_get_rtt_server(uint32_t addr, uint64_t *rtt) { - return cl_ctx_get_rtt_server (g_ctx, addr, rtt); + return cl_ctx_get_rtt_server(g_ctx, addr, rtt); } int cl_get_rtt_id(ID *id, uint64_t *rtt) -{ - return cl_ctx_get_rtt_id (g_ctx, id, rtt); +{ + return cl_ctx_get_rtt_id(g_ctx, id, rtt); } /************************************************************************ @@ -711,13 +707,12 @@ * returned (may be smaller than requested) ***********************************************************************/ int cl_get_top_k_servers(int *k, uint32_t best_addr[], - uint16_t best_port[], uint64_t best_rtt[]) -{ + uint16_t best_port[], uint64_t best_rtt[]) +{ return cl_ctx_get_top_k_servers(g_ctx, k, best_addr, best_port, best_rtt); } int cl_get_top_k_ids(int *k, ID best_id[], uint64_t best_rtt[]) { - return cl_ctx_get_top_k_ids (g_ctx, k, best_id, best_rtt); + return cl_ctx_get_top_k_ids(g_ctx, k, best_id, best_rtt); } - === modified file 'i3/i3_client/i3_client_api.h' --- i3/i3_client/i3_client_api.h 2010-01-12 12:35:31 +0000 +++ i3/i3_client/i3_client_api.h 2010-02-11 11:49:47 +0000 @@ -1,9 +1,9 @@ /*************************************************************************** - i3_client_api.h - description - ------------------- - begin : Aug 20 2003 - email : istoica@xxxxxxxxxxxxxxx - ***************************************************************************/ +* i3_client_api.h - description +* ------------------- +* begin : Aug 20 2003 +* email : istoica@xxxxxxxxxxxxxxx +***************************************************************************/ #ifndef I3_CLIENT_API_H #define I3_CLIENT_API_H @@ -13,52 +13,52 @@ #define cl_timer Event -/** - * cbk_packet stands for "Callback Packet". - * This structure encapsulates the contents - * of a packet and the stack of IDs and stack len associated with - * its header. It is used in the data arguments of callbacks of type - * CL_CBK_RECEIVE_PACKET. - */ +/** + * cbk_packet stands for "Callback Packet". + * This structure encapsulates the contents + * of a packet and the stack of IDs and stack len associated with + * its header. It is used in the data arguments of callbacks of type + * CL_CBK_RECEIVE_PACKET. + */ typedef struct cbk_packet { - ID *ids; /** Stack of IDs associated with the packet. */ - int stack_len; /** Number of IDs in the stack */ - cl_buf* clb; /** The contents of the packet */ + ID * ids; /** Stack of IDs associated with the packet. */ + int stack_len; /** Number of IDs in the stack */ + cl_buf *clb; /** The contents of the packet */ } cbk_packet; int cl_init(char *cfg_file); int cl_exit(void); -int cl_select(int n, fd_set *readfds, fd_set *writefds, - fd_set *exceptfds, struct timeval *cl_to); +int cl_select(int n, fd_set *readfds, fd_set *writefds, + fd_set *exceptfds, struct timeval *cl_to); int cl_loop(void); -cl_trigger *cl_create_trigger(ID *id, uint16_t prefix_len, Key *key, - uint16_t flags); +cl_trigger *cl_create_trigger(ID *id, uint16_t prefix_len, Key *key, + uint16_t flags); -cl_trigger *cl_create_trigger_stack(ID *id, uint16_t prefix_len, - ID *stack, int stack_len, - uint16_t flags); +cl_trigger *cl_create_trigger_stack(ID *id, uint16_t prefix_len, + ID *stack, int stack_len, + uint16_t flags); /** * This function is used to create a trigger which points to an i3 id. * Please note that this function does not insert the trigger into the i3 infrastructure. * <code>cl_insert_trigger</code> is used to insert the trigger into the i3 infrastructure. - * + * * @param id The i3 Id of the trigger to be created. - * + * * @param prefix_len The length of the prefix of the id to be used for matching. - * + * * @param id_target The i3 Id to which this trigger points. * * @param flags Flags are used to specify the properties of the trigger being created. * The following flags can be used individually or ORed together. * <ul> - * <li><code>CL_TRIGGER_CFLAG_R_CONSTRAINT</code> - Make the trigger right constrained. + * <li><code>CL_TRIGGER_CFLAG_R_CONSTRAINT</code> - Make the trigger right constrained. * <li><code>CL_TRIGGER_CFLAG_L_CONSTRAINT</code> - Make the trigger left constrained. - * <li><code>CL_TRIGGER_CFLAG_PUBLIC</code> - Make this a public trigger. If this is flag is + * <li><code>CL_TRIGGER_CFLAG_PUBLIC</code> - Make this a public trigger. If this is flag is * not used, the trigger is private by default. Please note that a public trigger must be left constrained. * This means that you cannot use the flags <code>CL_TRIGGER_CFLAG_R_CONSTRAINT</code> and * CL_TRIGGER_CFLAG_PUBLIC together. @@ -67,7 +67,7 @@ * @return A pointer to the created trigger. */ #define cl_create_trigger_id(id, prefix_len, id_target, flags) \ - cl_create_trigger_stack(id, prefix_len, id_target, 1, flags) + cl_create_trigger_stack(id, prefix_len, id_target, 1, flags) int cl_destroy_trigger(cl_trigger *ctr); @@ -80,48 +80,48 @@ /* * This function is used to send a packet addressed to an i3 Id. - * - * @param id The i3 id to which this packet is addressed + * + * @param id The i3 id to which this packet is addressed * @param clb The packet payload * @param flags The flags associated with sending a packet. It can take on the * following values: * * <ul> - * <li><code>CL_PKT_FLAG_ALLOW_SHORTCUT</code> All this packet to be shortcutted. + * <li><code>CL_PKT_FLAG_ALLOW_SHORTCUT</code> All this packet to be shortcutted. * </ul> * * @return One of the following codes is returned. * - * <ul> - * <li><code>CL_RET_OK</code> - Packet was successfully sent. - * <li><code>CL_RET_NO_CONTEXT</code> - No i3 context was found. - * Probably cl_init() was omitted initially. - * <li><code>CL_RET_MSG_SIZE</code> - the packet payload is - * too large to be transferred. - * <li><code>CL_RET_NO_SERVERS</code> - no i3 servers are - * known or reachable. - * <li><code>CL_RET_NET_ERROR</code> - the packet was not - * sent due to a low-level network or socket error. - * </ul> - */ + * <ul> + * <li><code>CL_RET_OK</code> - Packet was successfully sent. + * <li><code>CL_RET_NO_CONTEXT</code> - No i3 context was found. + * Probably cl_init() was omitted initially. + * <li><code>CL_RET_MSG_SIZE</code> - the packet payload is + * too large to be transferred. + * <li><code>CL_RET_NO_SERVERS</code> - no i3 servers are + * known or reachable. + * <li><code>CL_RET_NET_ERROR</code> - the packet was not + * sent due to a low-level network or socket error. + * </ul> + */ #define cl_send(id, clb, flags) cl_send_stack(id, 1, clb, flags) -int cl_register_trigger_callback(cl_trigger *ctr, uint16_t cbk_type, - void (*fun)(void*, void* data, void* fun_ctx), void *fun_ctx); +int cl_register_trigger_callback(cl_trigger * ctr, uint16_t cbk_type, + void (*fun)(void *, void *data, void *fun_ctx), void *fun_ctx); int cl_register_callback( - uint16_t cbk_type, - void (*fun)(void *ctx_data, void *data, void *fun_ctx), - void *fun_ctx); + uint16_t cbk_type, + void (*fun)(void *ctx_data, void *data, void *fun_ctx), + void *fun_ctx); -int cl_register_fd_callback(int fd, int type, void (*fun)(int, void*), void *data); +int cl_register_fd_callback(int fd, int type, void (*fun)(int, void *), void *data); int cl_unregister_fd_callback(int fd, int type); cl_timer *cl_set_timer(struct timeval *tv, void (*fun)(void *), void *data); void cl_cancel_timer(cl_timer *ct); -/* +/* * Create a cl_bug data structure which is used for sending and receiving packets. * @param len The size of the buffer to be created. */ @@ -133,8 +133,8 @@ */ void cl_free_buf(cl_buf *clb); -/* - * Get close servers from a list of servers +/* + * Get close servers from a list of servers * - currently uses a combination of latitude-longitude + pings */ int cl_get_rtt_server(uint32_t addr, uint64_t *rtt); === modified file 'i3/i3_client/i3_client_api_ctx.c' --- i3/i3_client/i3_client_api_ctx.c 2010-01-12 12:35:31 +0000 +++ i3/i3_client/i3_client_api_ctx.c 2010-02-11 11:49:47 +0000 @@ -1,6 +1,6 @@ /************************************************************************ - * cl_ctx_init - create and initialize a context data structure - * + * cl_ctx_init - create and initialize a context data structure + * * input: * cfg_file - xml file containing configuration parameters * such as the servers to which the client can connect @@ -9,7 +9,7 @@ * CL_RET_INVALID_CFG_FILE * CL_RE_NO_CONTEXT * error code returned cl_init_ping - * + * * return value: * ctx - pointer to the context * @@ -21,7 +21,7 @@ #include <string.h> // strcasecmp() #include <stdlib.h> // exit() #ifdef _WIN32 - // stg: win does not have strcasecmp(): +// stg: win does not have strcasecmp(): #define strcasecmp _stricmp #endif @@ -42,267 +42,268 @@ -int cl_init_ping(cl_context* ctx, char *url); +int cl_init_ping(cl_context *ctx, char *url); void trigger_set_timer(struct timeval *tv, void (*fun)(void *), cl_trigger *ctr); /** - * @param i3_port_num The port on which i3 should listen. - */ + * @param i3_port_num The port on which i3 should listen. + */ cl_context *cl_ctx_init(const char *cfg_file, int *rc, int i3_port_num) { - char usePingStr[50]; - char useTCPStr[50]; - - cl_context *ctx; - - // Open the debug file to which all debug and info messages related to i3 are sent, - // if it had not be previously opened. - // For eg: if the i3 client api is used as part of the i3OCD, the i3OCD - // sets up i3DebugFD as soon as the i3OCD dll is loaded. + char usePingStr[50]; + char useTCPStr[50]; + + cl_context *ctx; + + // Open the debug file to which all debug and info messages related to i3 are sent, + // if it had not be previously opened. + // For eg: if the i3 client api is used as part of the i3OCD, the i3OCD + // sets up i3DebugFD as soon as the i3OCD dll is loaded. #ifdef _WIN32 - if (i3DebugFD == NULL) { - i3DebugFD = fopen ("debug_i3.txt", "w"); - } + if (i3DebugFD == NULL) { + i3DebugFD = fopen("debug_i3.txt", "w"); + } #endif - if (0 != nw_init()) { - I3_PRINT_INFO0 (I3_INFO_LEVEL_FATAL_ERROR, "Unable to initialize the network.\n"); - EXIT_ON_ERROR; - return NULL; - } - - if (!cfg_file) { - *rc = CL_RET_INVALID_CFG_FILE; - return NULL; - } - - /* read configuration file */ - read_parameters(cfg_file); - - /* create context */ - ctx = cl_create_context(NULL, i3_port_num); - if (ctx) - *rc = CL_RET_OK; - else { - *rc = CL_RET_NO_CONTEXT; + if (0 != nw_init()) { + I3_PRINT_INFO0(I3_INFO_LEVEL_FATAL_ERROR, "Unable to initialize the network.\n"); + EXIT_ON_ERROR; + return NULL; + } + + if (!cfg_file) { + *rc = CL_RET_INVALID_CFG_FILE; + return NULL; + } + + /* read configuration file */ + read_parameters(cfg_file); + + /* create context */ + ctx = cl_create_context(NULL, i3_port_num); + if (ctx) { + *rc = CL_RET_OK; + } else { + *rc = CL_RET_NO_CONTEXT; + return ctx; + } + + /* Should TCP be used to find the first hop i3 server? */ + read_string_attribute("//I3ServerDetails", "UseTCP", useTCPStr, 0); + if (strcasecmp(useTCPStr, "yes") == 0 || strcasecmp(useTCPStr, "true") == 0) { + ctx->is_tcp = 1; + } else { + ctx->is_tcp = 0; + } + + /* check whether ping is used to find a nearby server */ + read_string_attribute("//I3ServerDetails", "UsePing", usePingStr, 0); + if (strcasecmp(usePingStr, "yes") == 0 || strcasecmp(usePingStr, "true") == 0) { + ctx->use_ping = 1; + } else { + ctx->use_ping = 0; + } + + if (ctx->use_ping) { +#define STATUS_URL_LEN 1024 + char status_url[STATUS_URL_LEN]; + + /* read the url containing the list of i3 serevers */ + read_string_attribute("//I3ServerDetails", "ServerListURL", status_url, 0); + + I3_PRINT_DEBUG1(I3_DEBUG_LEVEL_SUPER, "Using ping, server status url = %s\n\n", status_url); + + if (strlen(status_url) >= STATUS_URL_LEN) { + I3_PRINT_INFO1(I3_INFO_LEVEL_WARNING, "cl_ctx_init: status_url file too long in %s\n", cfg_file); + exit(-1); + } + if (strlen(status_url) == 0) { + I3_PRINT_INFO1(I3_INFO_LEVEL_WARNING, "cl_ctx_init: no status_url file in %s\n", cfg_file); + exit(-1); + } + I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_VERBOSE, "Starting ping thread\n"); + *rc = cl_init_ping(ctx, status_url); + } + + // Don't read the configuration file after this point. + release_params(); + + if (ctx->num_servers < 1 && !ctx->use_ping) { + I3_PRINT_INFO0( + I3_INFO_LEVEL_FATAL_ERROR, + "No i3 server details have been given and UsePing is turned off.\n" + "There is no way to obtain i3 server details. Exiting.\n" + ); + EXIT_ON_ERROR; + } + + // This function intializes the TCP socket to be used to contact the first hop i3 server, + // if UseTCP flag is set in the configuration file. + // If UsePing is set, this function blocks till the details of at least + // one i3 server is available. + init_tcp_ctx(ctx); + return ctx; - } - - /* Should TCP be used to find the first hop i3 server? */ - read_string_attribute("//I3ServerDetails", "UseTCP", useTCPStr,0); - if (strcasecmp(useTCPStr, "yes") == 0 || strcasecmp(useTCPStr, "true") == 0) { - ctx->is_tcp = 1; - } else { - ctx->is_tcp = 0; - } - - /* check whether ping is used to find a nearby server */ - read_string_attribute("//I3ServerDetails", "UsePing", usePingStr,0); - if (strcasecmp(usePingStr, "yes") == 0 || strcasecmp(usePingStr, "true") == 0) { - ctx->use_ping = 1; - } else { - ctx->use_ping = 0; - } - - if (ctx->use_ping) { -#define STATUS_URL_LEN 1024 - char status_url[STATUS_URL_LEN]; - - /* read the url containing the list of i3 serevers */ - read_string_attribute("//I3ServerDetails", "ServerListURL", status_url, 0); - - I3_PRINT_DEBUG1(I3_DEBUG_LEVEL_SUPER, "Using ping, server status url = %s\n\n", status_url); - - if (strlen(status_url) >= STATUS_URL_LEN) { - I3_PRINT_INFO1(I3_INFO_LEVEL_WARNING, "cl_ctx_init: status_url file too long in %s\n", cfg_file); - exit(-1); - } - if (strlen(status_url) == 0) { - I3_PRINT_INFO1(I3_INFO_LEVEL_WARNING, "cl_ctx_init: no status_url file in %s\n", cfg_file); - exit(-1); - } - I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_VERBOSE, "Starting ping thread\n"); - *rc = cl_init_ping(ctx, status_url); - } - - // Don't read the configuration file after this point. - release_params(); - - if (ctx->num_servers < 1 && ! ctx->use_ping) { - I3_PRINT_INFO0 ( - I3_INFO_LEVEL_FATAL_ERROR, - "No i3 server details have been given and UsePing is turned off.\n" - "There is no way to obtain i3 server details. Exiting.\n" - ); - EXIT_ON_ERROR; - } - - // This function intializes the TCP socket to be used to contact the first hop i3 server, - // if UseTCP flag is set in the configuration file. - // If UsePing is set, this function blocks till the details of at least - // one i3 server is available. - init_tcp_ctx(ctx); - - return ctx; } - /************************************************************************ * cl_ctx_exit - free all resources associated with the context (ctx) ***********************************************************************/ int cl_ctx_exit(cl_context *ctx) { - if (ctx == NULL) - return CL_RET_NO_CONTEXT; - - cl_destroy_context(ctx); - - return CL_RET_OK; + if (ctx == NULL) { + return CL_RET_NO_CONTEXT; + } + + cl_destroy_context(ctx); + + return CL_RET_OK; } - - int cl_ctx_loop(cl_context *ctx) { fd_set rset; if (ctx == NULL) { - return CL_RET_NO_CONTEXT; + return CL_RET_NO_CONTEXT; } - + FD_ZERO(&rset); - for (;;) { + for (;; ) { #ifndef _WIN32 - FD_SET(0, &rset); /* just here, to be modified if application - * listens on other fds - */ + FD_SET(0, &rset); /* just here, to be modified if application + * listens on other fds + */ #endif if (cl_select(0, &rset, NULL, NULL, NULL) < 0) { if (errno == EINTR) { - continue; + continue; } else { - I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_FATAL, "select_error\n"); + I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_FATAL, "select_error\n"); } } } - return errno; + return errno; } /************************************************************************* - * cl_ctx_create_trigger - create a trigger that points to the client, - * i.e., to the context's socket - * - * input: - * ctx - context (only for cl_ctx_create_trigger) - * id, prefix_len - trigger ID and prefix len - * key - key = h_l(id) if the trigger is left constrained, and - * h_r(id) if the trigger is right constrained, where h_l - * and h_r are two one-way hash functions - * flags - flags associated to trigger creation; possible values: - * CL_TRIGGER_CFLAG_R_CONSTRAINT - right constraint trigger - * CL_TRIGGER_CFLAG_L_CONSTRAINT - left constraint trigger - * CL_TRIGGER_CFLAG_PUBLIC - public trigger; otherwise the trigger - * is private. If the trigger is public - * then it has to be left constraint, - * i.e., CL_TRIGGER_CFLAG_R_CONSTRAINT - * and CL_TRIGGER_CFLAG_PUBLIC cannot be - * used simultaneously - * rc - error code; possible values: - * CL_RET_NO_CONTEXT - * CL_RET_TRIGGER_ALREADY_EXISTS - * error code returned by update_id_key - * - * return value: - * - pointer to the instantiated trigger - * - * Note: - * - the key field of the ID is upadted to h_l(key) or h_r(key) - *************************************************************************/ +* cl_ctx_create_trigger - create a trigger that points to the client, +* i.e., to the context's socket +* +* input: +* ctx - context (only for cl_ctx_create_trigger) +* id, prefix_len - trigger ID and prefix len +* key - key = h_l(id) if the trigger is left constrained, and +* h_r(id) if the trigger is right constrained, where h_l +* and h_r are two one-way hash functions +* flags - flags associated to trigger creation; possible values: +* CL_TRIGGER_CFLAG_R_CONSTRAINT - right constraint trigger +* CL_TRIGGER_CFLAG_L_CONSTRAINT - left constraint trigger +* CL_TRIGGER_CFLAG_PUBLIC - public trigger; otherwise the trigger +* is private. If the trigger is public +* then it has to be left constraint, +* i.e., CL_TRIGGER_CFLAG_R_CONSTRAINT +* and CL_TRIGGER_CFLAG_PUBLIC cannot be +* used simultaneously +* rc - error code; possible values: +* CL_RET_NO_CONTEXT +* CL_RET_TRIGGER_ALREADY_EXISTS +* error code returned by update_id_key +* +* return value: +* - pointer to the instantiated trigger +* +* Note: +* - the key field of the ID is upadted to h_l(key) or h_r(key) +*************************************************************************/ cl_trigger *cl_ctx_create_trigger(cl_context *ctx, - ID *id, uint16_t prefix_len, Key *key, - uint16_t flags, int *rc) + ID *id, uint16_t prefix_len, Key *key, + uint16_t flags, int *rc) { - cl_trigger *ctr; - - //ADDED_DILIP - *rc = CL_RET_OK; //default return code if nothing goes wrong - - if (!ctx) { - *rc = CL_RET_NO_CONTEXT; - return NULL; - } - - *rc = update_id_key(id, key, flags); - if (*rc != CL_RET_OK) - return NULL; - - ctr = cl_create_trigger_gen(ctx, - I3_ADDR_TYPE_IPv4, id, prefix_len, - ctx->local_ip_addr, ctx->local_port, - NULL, key, - /* flags are initialized in - * cl_ctx_insert_trigger - */ - 0); - if (!ctr) { - I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, "cl_ctx_create_trigger: duplicate trigger insertion.\n"); - ctr = cl_get_trigger_by_id(ctx->trigger_htable[CL_HASH_TRIG(id)], id); - if (ctr) - *rc = CL_RET_TRIGGER_ALREADY_EXISTS; - } - - return ctr; + cl_trigger *ctr; + + //ADDED_DILIP + *rc = CL_RET_OK; //default return code if nothing goes wrong + + if (!ctx) { + *rc = CL_RET_NO_CONTEXT; + return NULL; + } + + *rc = update_id_key(id, key, flags); + if (*rc != CL_RET_OK) { + return NULL; + } + + ctr = cl_create_trigger_gen(ctx, + I3_ADDR_TYPE_IPv4, id, prefix_len, + ctx->local_ip_addr, ctx->local_port, + NULL, key, + /* flags are initialized in + * cl_ctx_insert_trigger + */ + 0); + if (!ctr) { + I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, "cl_ctx_create_trigger: duplicate trigger insertion.\n"); + ctr = cl_get_trigger_by_id(ctx->trigger_htable[CL_HASH_TRIG(id)], id); + if (ctr) { + *rc = CL_RET_TRIGGER_ALREADY_EXISTS; + } + } + + return ctr; } - /************************************************************************* - * cl_ctx_create_trigger_stack - same as - * cl_ctx_create_trigger/cl_create_trigger_addr but the trigger - * points to stack instead of the contex's socket - *************************************************************************/ +* cl_ctx_create_trigger_stack - same as +* cl_ctx_create_trigger/cl_create_trigger_addr but the trigger +* points to stack instead of the contex's socket +*************************************************************************/ cl_trigger *cl_ctx_create_trigger_stack(cl_context *ctx, - ID *id, uint16_t prefix_len, - ID *stack, int stack_len, - uint16_t flags, int *rc) + ID *id, uint16_t prefix_len, + ID *stack, int stack_len, + uint16_t flags, int *rc) { - cl_trigger *ctr; - i3_stack *s; - - struct in_addr nothing; - nothing.s_addr = 0; // this line not necessary, but just here to avoid the warning. - - if (!ctx) { - *rc = CL_RET_NO_CONTEXT; - return NULL; - } - - if (stack_len == 0 || stack_len >= I3_MAX_STACK_LEN) { - *rc = CL_RET_INVALID_STACK_LEN; - return NULL; - } - - *rc = update_id_id(id, &stack[0], flags); - - if (*rc != CL_RET_OK) - return NULL; - - s = alloc_i3_stack(); - init_i3_stack(s, stack, stack_len); - - ctr = cl_create_trigger_gen(ctx, I3_ADDR_TYPE_STACK, - id, prefix_len, nothing, 0, s, 0, 0); - - if (!ctr) { - free_i3_stack(s); - I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, - "cl_ctx_create_trigger_stack: duplicate trigger insertion.\n"); - ctr = cl_get_trigger_by_id(ctx->trigger_htable[CL_HASH_TRIG(id)], id); - if (ctr) - *rc = CL_RET_TRIGGER_ALREADY_EXISTS; - } - - return ctr; + cl_trigger *ctr; + i3_stack *s; + + struct in_addr nothing; + nothing.s_addr = 0; // this line not necessary, but just here to avoid the warning. + + if (!ctx) { + *rc = CL_RET_NO_CONTEXT; + return NULL; + } + + if (stack_len == 0 || stack_len >= I3_MAX_STACK_LEN) { + *rc = CL_RET_INVALID_STACK_LEN; + return NULL; + } + + *rc = update_id_id(id, &stack[0], flags); + + if (*rc != CL_RET_OK) { + return NULL; + } + + s = alloc_i3_stack(); + init_i3_stack(s, stack, stack_len); + + ctr = cl_create_trigger_gen(ctx, I3_ADDR_TYPE_STACK, + id, prefix_len, nothing, 0, s, 0, 0); + + if (!ctr) { + free_i3_stack(s); + I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, + "cl_ctx_create_trigger_stack: duplicate trigger insertion.\n"); + ctr = cl_get_trigger_by_id(ctx->trigger_htable[CL_HASH_TRIG(id)], id); + if (ctr) { + *rc = CL_RET_TRIGGER_ALREADY_EXISTS; + } + } + + return ctr; } /******************************************************************** @@ -311,218 +312,236 @@ * input: * ctx - context (only for cl_ctx_destroy_trigger) * ctr - trigger to be destroyed - * + * * return value: - * - error code; possibe values + * - error code; possibe values * CL_RET_OK * CL_RET_NO_TRIGGER - * CL_RET_NO_CONTEXT - * + * CL_RET_NO_CONTEXT + * * Note: if the trigger is not removed from the infrastructure, this * function removes it *******************************************************************/ int cl_ctx_destroy_trigger(cl_context *ctx, cl_trigger *ctr) { - int rc; - - if (!ctx) - return CL_RET_NO_CONTEXT; - - if (!ctr) - return CL_RET_NO_TRIGGER; - - if (ctr->type == CL_TRIGGER_I3) { - rc = cl_ctx_remove_trigger(ctx, ctr); - if (rc != CL_RET_OK) - return rc; - } - - cl_delete_trigger(ctx, ctr); - - return CL_RET_OK; + int rc; + + if (!ctx) { + return CL_RET_NO_CONTEXT; + } + + if (!ctr) { + return CL_RET_NO_TRIGGER; + } + + if (ctr->type == CL_TRIGGER_I3) { + rc = cl_ctx_remove_trigger(ctx, ctr); + if (rc != CL_RET_OK) { + return rc; + } + } + + cl_delete_trigger(ctx, ctr); + + return CL_RET_OK; } /************************************************************************ - * cl_ctx_insert_trigger - insert a trigger into i3 - * - * input: - * ctx - context (only for cl_ctx_insert_trigger) - * ctr - trigger - * flags - flags associated to trigger insertion; possible values - * - ************************************************************************/ -int cl_ctx_insert_trigger(cl_context *ctx, cl_trigger *ctr, uint16_t flags) -{ - struct timeval tv; - - if (!ctr) - return CL_RET_NO_TRIGGER; - - if (!ctx) - return CL_RET_NO_CONTEXT; - - if (flags & CL_IFLAGS_TRIGGER_LOCAL) - ctr->type = CL_TRIGGER_LOCAL; - else - ctr->type = CL_TRIGGER_I3; - - if (flags & CL_IFLAGS_TRIGGER_ALLOW_SHORTCUT) - ctr->t->flags |= I3_TRIGGER_FLAG_ALLOW_SHORTCUT; - - if (ctr->type == CL_TRIGGER_I3) { - cl_insert_trigger_into_i3(ctx, ctr); +* cl_ctx_insert_trigger - insert a trigger into i3 +* +* input: +* ctx - context (only for cl_ctx_insert_trigger) +* ctr - trigger +* flags - flags associated to trigger insertion; possible values +* +************************************************************************/ +int cl_ctx_insert_trigger(cl_context *ctx, cl_trigger *ctr, uint16_t flags) +{ + struct timeval tv; + + if (!ctr) { + return CL_RET_NO_TRIGGER; + } + + if (!ctx) { + return CL_RET_NO_CONTEXT; + } + + if (flags & CL_IFLAGS_TRIGGER_LOCAL) { + ctr->type = CL_TRIGGER_LOCAL; + } else { + ctr->type = CL_TRIGGER_I3; + } + + if (flags & CL_IFLAGS_TRIGGER_ALLOW_SHORTCUT) { + ctr->t->flags |= I3_TRIGGER_FLAG_ALLOW_SHORTCUT; + } + + if (ctr->type == CL_TRIGGER_I3) { + cl_insert_trigger_into_i3(ctx, ctr); + if (ctr->status == CL_TRIGGER_STATUS_INSERTED) { + /* trigger already inserted; just update trigger info; + * no need to set-up timeout_ack_timer + */ + ; + } else { + /* set challenge timeout */ + tv.tv_sec = ACK_TIMEOUT; + tv.tv_usec = random_sec(); + trigger_set_timer(&tv, timeout_ack_insert, ctr); + } + } else { + /* do nothing */; + } + + //ADDED_DILIP + return CL_RET_OK; +} + +int cl_ctx_trigger_ratelimit(cl_context *ctx, cl_trigger *ctr, uint8_t type, + uint32_t depth, uint32_t r, uint32_t R) +{ + if (ctx == NULL) { + return CL_RET_NO_CONTEXT; + } + + if (!ctr) { + return CL_RET_NO_TRIGGER; + } + + if (ctr->t->flags & I3_TRIGGER_FLAG_RATE_LIMIT) { + assert(ctr->t->tb); + /* trigger is already rate limited; just update the token buket */ + ctr->t->tb->type = type; + ctr->t->tb->depth = depth; + ctr->t->tb->r = r; + ctr->t->tb->R = R; + if (ctr->precomputed_pkt.p) { + free(ctr->precomputed_pkt.p); + /* need to precompute the packet after the change */ + cl_make_trigger_packet(ctx, ctr->t, + I3_OPT_TRIGGER_INSERT, &ctr->precomputed_pkt); + } + } else { + ctr->t->flags |= I3_TRIGGER_FLAG_RATE_LIMIT; + ctr->t->tb = alloc_token_bucket(); + init_token_bucket(ctr->t->tb, type, depth, r, R); + } if (ctr->status == CL_TRIGGER_STATUS_INSERTED) { - /* trigger already inserted; just update trigger info; - * no need to set-up timeout_ack_timer - */ - ; - } else { - /* set challenge timeout */ - tv.tv_sec = ACK_TIMEOUT; - tv.tv_usec = random_sec(); - trigger_set_timer(&tv, timeout_ack_insert, ctr); - } - } else { - /* do nothing */ ; - } - - //ADDED_DILIP - return CL_RET_OK; - -} - - -int cl_ctx_trigger_ratelimit(cl_context* ctx, cl_trigger *ctr, uint8_t type, - uint32_t depth, uint32_t r, uint32_t R) -{ - if (ctx == NULL) - return CL_RET_NO_CONTEXT; - - if (!ctr) - return CL_RET_NO_TRIGGER; - - if (ctr->t->flags & I3_TRIGGER_FLAG_RATE_LIMIT) { - assert(ctr->t->tb); - /* trigger is already rate limited; just update the token buket */ - ctr->t->tb->type = type; - ctr->t->tb->depth = depth; - ctr->t->tb->r = r; - ctr->t->tb->R = R; - if (ctr->precomputed_pkt.p) { - free(ctr->precomputed_pkt.p); - /* need to precompute the packet after the change */ - cl_make_trigger_packet(ctx, ctr->t, - I3_OPT_TRIGGER_INSERT, &ctr->precomputed_pkt); - } - } else { - ctr->t->flags |= I3_TRIGGER_FLAG_RATE_LIMIT; - ctr->t->tb = alloc_token_bucket(); - init_token_bucket(ctr->t->tb, type, depth, r, R); - } - if (ctr->status == CL_TRIGGER_STATUS_INSERTED) { - /* update trigger token-bucket constraints */ - cl_insert_trigger_into_i3(ctx, ctr); - } - return CL_RET_OK; + /* update trigger token-bucket constraints */ + cl_insert_trigger_into_i3(ctx, ctr); + } + return CL_RET_OK; } //ADDED_DILIP -int cl_ctx_register_trigger_callback(cl_context* ctx, cl_trigger *ctr, uint16_t cbk_type, - void (*fun)(void*,void *data, void *fun_ctx), void *fun_ctx) -{ - if (ctx == NULL) - return CL_RET_NO_CONTEXT; - - if (!ctr) - return CL_RET_NO_TRIGGER; - - return cl_register_trigger_callback1(ctr, cbk_type, fun, fun_ctx); -} - -int cl_ctx_register_fd_callback(cl_context *ctx, int fd, - int type, void (*fun)(int, void *), void *data) -{ - fd_node *n; - - if (ctx == NULL) - return CL_RET_NO_CONTEXT; - - switch (type) { - case CL_FD_TYPE_READ: - if ((n = get_fd_node(ctx->i3fds->readfd_list, fd))!=0) - return CL_RET_DUPLICATE_FD; - if ((n = alloc_fd_node(fd, fun, data)) == NULL) - /* just to please the compiler; alloc_fd_node will panic if it cannot - * allocate memory - */ - return CL_RET_OK; - insert_fd_node_in_list(&ctx->i3fds->readfd_list, n); - break; - case CL_FD_TYPE_WRITE: - if ((n = get_fd_node(ctx->i3fds->writefd_list, fd))!=0) - return CL_RET_DUPLICATE_FD; - if ((n = alloc_fd_node(fd, fun, data)) == NULL) - return CL_RET_OK; - insert_fd_node_in_list(&ctx->i3fds->writefd_list, n); - break; - case CL_FD_TYPE_EXCEPT: - if ((n = get_fd_node(ctx->i3fds->exceptfd_list, fd))!=0) - return CL_RET_DUPLICATE_FD; - if ((n = alloc_fd_node(fd, fun, data)) == NULL) - return CL_RET_OK; - insert_fd_node_in_list(&ctx->i3fds->exceptfd_list, n); - break; - default: - I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, "cl_register_fd_callback: unknown file descriptor type\n"); - } - - ctx->i3fds->max_fd = MAX(ctx->i3fds->max_fd, fd); - - return CL_RET_OK; -} - +int cl_ctx_register_trigger_callback(cl_context *ctx, cl_trigger *ctr, uint16_t cbk_type, + void (*fun)(void *, void *data, void *fun_ctx), void *fun_ctx) +{ + if (ctx == NULL) { + return CL_RET_NO_CONTEXT; + } + + if (!ctr) { + return CL_RET_NO_TRIGGER; + } + + return cl_register_trigger_callback1(ctr, cbk_type, fun, fun_ctx); +} + +int cl_ctx_register_fd_callback(cl_context *ctx, int fd, + int type, void (*fun)(int, void *), void *data) +{ + fd_node *n; + + if (ctx == NULL) { + return CL_RET_NO_CONTEXT; + } + + switch (type) { + case CL_FD_TYPE_READ: + if ((n = get_fd_node(ctx->i3fds->readfd_list, fd)) != 0) { + return CL_RET_DUPLICATE_FD; + } + if ((n = alloc_fd_node(fd, fun, data)) == NULL) { + /* just to please the compiler; alloc_fd_node will panic if it cannot + * allocate memory + */ + return CL_RET_OK; + } + insert_fd_node_in_list(&ctx->i3fds->readfd_list, n); + break; + case CL_FD_TYPE_WRITE: + if ((n = get_fd_node(ctx->i3fds->writefd_list, fd)) != 0) { + return CL_RET_DUPLICATE_FD; + } + if ((n = alloc_fd_node(fd, fun, data)) == NULL) { + return CL_RET_OK; + } + insert_fd_node_in_list(&ctx->i3fds->writefd_list, n); + break; + case CL_FD_TYPE_EXCEPT: + if ((n = get_fd_node(ctx->i3fds->exceptfd_list, fd)) != 0) { + return CL_RET_DUPLICATE_FD; + } + if ((n = alloc_fd_node(fd, fun, data)) == NULL) { + return CL_RET_OK; + } + insert_fd_node_in_list(&ctx->i3fds->exceptfd_list, n); + break; + default: + I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, "cl_register_fd_callback: unknown file descriptor type\n"); + } + + ctx->i3fds->max_fd = MAX(ctx->i3fds->max_fd, fd); + + return CL_RET_OK; +} /************************************************************************ - * cl_ctx_unregister_fd_callback - unregister a callback associated with a - * file descriptor fd - * NOTE: this should be done once the file descriptor is closed - ************************************************************************/ +* cl_ctx_unregister_fd_callback - unregister a callback associated with a +* file descriptor fd +* NOTE: this should be done once the file descriptor is closed +************************************************************************/ int cl_ctx_unregister_fd_callback(cl_context *ctx, int fd, int type) { - fd_node *n; - - if (ctx == NULL) - return CL_RET_NO_CONTEXT; - - switch (type) { - case CL_FD_TYPE_READ: - n = get_fd_node(ctx->i3fds->readfd_list, fd); - if (!n) - return CL_RET_INVALID_FD; - remove_fd_node_from_list(&ctx->i3fds->readfd_list, n); - break; - case CL_FD_TYPE_WRITE: - n = get_fd_node(ctx->i3fds->writefd_list, fd); - if (!n) - return CL_RET_INVALID_FD; - remove_fd_node_from_list(&ctx->i3fds->writefd_list, n); - break; - case CL_FD_TYPE_EXCEPT: - n = get_fd_node(ctx->i3fds->exceptfd_list, fd); - if (!n) - return CL_RET_INVALID_FD; - remove_fd_node_from_list(&ctx->i3fds->exceptfd_list, n); - break; - default: - I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, "cl_register_fd_callback: unknown file descriptor type\n"); - } - - compute_max_i3_fds(ctx->i3fds); - - return CL_RET_OK; + fd_node *n; + + if (ctx == NULL) { + return CL_RET_NO_CONTEXT; + } + + switch (type) { + case CL_FD_TYPE_READ: + n = get_fd_node(ctx->i3fds->readfd_list, fd); + if (!n) { + return CL_RET_INVALID_FD; + } + remove_fd_node_from_list(&ctx->i3fds->readfd_list, n); + break; + case CL_FD_TYPE_WRITE: + n = get_fd_node(ctx->i3fds->writefd_list, fd); + if (!n) { + return CL_RET_INVALID_FD; + } + remove_fd_node_from_list(&ctx->i3fds->writefd_list, n); + break; + case CL_FD_TYPE_EXCEPT: + n = get_fd_node(ctx->i3fds->exceptfd_list, fd); + if (!n) { + return CL_RET_INVALID_FD; + } + remove_fd_node_from_list(&ctx->i3fds->exceptfd_list, n); + break; + default: + I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, "cl_register_fd_callback: unknown file descriptor type\n"); + } + + compute_max_i3_fds(ctx->i3fds); + + return CL_RET_OK; } - /*********************************************************************** * cl_ctx_set_timer - set timer * @@ -534,90 +553,93 @@ * callback is invoked * ************************************************************************/ -cl_timer *cl_ctx_set_timer(cl_context *ctx, struct timeval *tv, - void (*fun)(void *), void *data) +cl_timer *cl_ctx_set_timer(cl_context *ctx, struct timeval *tv, + void (*fun)(void *), void *data) { - uint64_t when; - Event *ev; - - if (ctx == NULL) - return NULL; - - when = wall_time(); - when = when + UMILLION*tv->tv_sec + tv->tv_usec; - ev = newEvent(fun, data, when); - - insertEvent(&ctx->timer_heap, ev); - - return (cl_timer *)ev; + uint64_t when; + Event *ev; + + if (ctx == NULL) { + return NULL; + } + + when = wall_time(); + when = when + UMILLION * tv->tv_sec + tv->tv_usec; + ev = newEvent(fun, data, when); + + insertEvent(&ctx->timer_heap, ev); + + return (cl_timer *) ev; } /************************************************************************** * cl_ctx_send_stack - send packet to a stack of IDs - * + * * input: * ctx - context (only for cl_ctx_send) * stack - stack, reppresented as an array of IDs; stack[0] * represents the ID where the packet is sent next - * stack_len - number of IDs in the stack + * stack_len - number of IDs in the stack * clb - payload * flags - flags associated to sending a packet; possible values: - * CL_PKT_FLAG_ALLOW_SHORTCUT - allow shortcuts - * + * CL_PKT_FLAG_ALLOW_SHORTCUT - allow shortcuts + * * return value: * - error code; possible values: * CL_RET_OK * CL_RET_NO_CONTEXT * CL_RET_INVALID_STACK_LEN - * CL_RET_MSG_SIZE - * CL_RET_NO_SERVERS - * CL_RET_NET_ERROR + * CL_RET_MSG_SIZE + * CL_RET_NO_SERVERS + * CL_RET_NET_ERROR *************************************************************************/ -int cl_ctx_send_stack(cl_context *ctx, ID *stack, int stack_len, - cl_buf *clb, uint16_t flags) +int cl_ctx_send_stack(cl_context *ctx, ID *stack, int stack_len, + cl_buf *clb, uint16_t flags) { - i3_stack *s; - int err = 0; - - if (ctx == NULL) - return CL_RET_NO_CONTEXT; - - if (stack_len == 0 || stack_len >= I3_MAX_STACK_LEN) - return CL_RET_INVALID_STACK_LEN; - - - s = alloc_i3_stack(); - init_i3_stack(s, stack, stack_len); - - // for now, setting is_total_len to "0" - err = cl_send_data_packet(ctx, s, clb, flags, 0); - free_i3_stack(s); - - return err; + i3_stack *s; + int err = 0; + + if (ctx == NULL) { + return CL_RET_NO_CONTEXT; + } + + if (stack_len == 0 || stack_len >= I3_MAX_STACK_LEN) { + return CL_RET_INVALID_STACK_LEN; + } + + + s = alloc_i3_stack(); + init_i3_stack(s, stack, stack_len); + + // for now, setting is_total_len to "0" + err = cl_send_data_packet(ctx, s, clb, flags, 0); + free_i3_stack(s); + + return err; } - - /************************************************************************ * Returns RTT of given addr (in host format) ***********************************************************************/ -int cl_ctx_get_rtt_server(cl_context* ctx, uint32_t addr, uint64_t *rtt) +int cl_ctx_get_rtt_server(cl_context *ctx, uint32_t addr, uint64_t *rtt) { - if (ctx == NULL || ctx->list == NULL) - return CL_RET_NO_AUTO_SERVER_SELECT; + if (ctx == NULL || ctx->list == NULL) { + return CL_RET_NO_AUTO_SERVER_SELECT; + } *rtt = get_rtt(ctx->list, addr); - + return CL_RET_OK; } -int cl_ctx_get_rtt_id(cl_context* ctx, ID *id, uint64_t *rtt) +int cl_ctx_get_rtt_id(cl_context *ctx, ID *id, uint64_t *rtt) { - if (ctx == NULL || ctx->list == NULL) - return CL_RET_NO_AUTO_SERVER_SELECT; + if (ctx == NULL || ctx->list == NULL) { + return CL_RET_NO_AUTO_SERVER_SELECT; + } *rtt = get_rtt_id(ctx->list, id); - + return CL_RET_OK; } @@ -627,37 +649,39 @@ * At return, "k" would contain the actual number of servers that are * returned (may be smaller than requested) ***********************************************************************/ -int cl_ctx_get_top_k_servers(cl_context* ctx, int *k, uint32_t best_addr[], - uint16_t best_port[], uint64_t best_rtt[]) -{ - if (ctx == NULL || ctx->list == NULL) - return CL_RET_NO_AUTO_SERVER_SELECT; - +int cl_ctx_get_top_k_servers(cl_context *ctx, int *k, uint32_t best_addr[], + uint16_t best_port[], uint64_t best_rtt[]) +{ + if (ctx == NULL || ctx->list == NULL) { + return CL_RET_NO_AUTO_SERVER_SELECT; + } + *k = get_top_k(ctx->list, *k, best_addr, best_port, best_rtt); - - //printf("in cl_get_top_k_servers, k returned = %d\n", *k); + + //printf("in cl_get_top_k_servers, k returned = %d\n", *k); return CL_RET_OK; } -int cl_ctx_get_top_k_ids(cl_context* ctx,int *k, ID best_id[], uint64_t best_rtt[]) +int cl_ctx_get_top_k_ids(cl_context *ctx, int *k, ID best_id[], uint64_t best_rtt[]) { - if (ctx == NULL || ctx->list == NULL) - return CL_RET_NO_AUTO_SERVER_SELECT; + if (ctx == NULL || ctx->list == NULL) { + return CL_RET_NO_AUTO_SERVER_SELECT; + } *k = get_top_k_id(ctx->list, *k, best_id, best_rtt); - + return CL_RET_OK; } -/** Close all the open sockets, including the ping socket +/** Close all the open sockets, including the ping socket */ -void i3_close_all_sockets (cl_context* ctx) { - - if (ctx->fd != -1) { - nw_close (ctx->fd); - } - if (ctx->is_tcp && ctx->tcp_fd != -1) { - nw_close (ctx->tcp_fd); - } - //close_ping_socket(); +void i3_close_all_sockets(cl_context *ctx) +{ + if (ctx->fd != -1) { + nw_close(ctx->fd); + } + if (ctx->is_tcp && ctx->tcp_fd != -1) { + nw_close(ctx->tcp_fd); + } + //close_ping_socket(); } === modified file 'i3/i3_client/i3_client_api_ctx.h' --- i3/i3_client/i3_client_api_ctx.h 2010-01-12 12:35:31 +0000 +++ i3/i3_client/i3_client_api_ctx.h 2010-02-11 11:49:47 +0000 @@ -1,9 +1,9 @@ /*************************************************************************** - i3_client_api_ctx.h - description - ------------------- - begin : Aug 20 2003 - email : istoica@xxxxxxxxxxxxxxx - ***************************************************************************/ +* i3_client_api_ctx.h - description +* ------------------- +* begin : Aug 20 2003 +* email : istoica@xxxxxxxxxxxxxxx +***************************************************************************/ #ifndef I3_CLIENT_API_CTX_H #define I3_CLIENT_API_CTX_H @@ -19,14 +19,14 @@ int cl_ctx_exit(cl_context *ctx); /* - * cl_ctx_select - function that replaces the select() function - * (sys/select.h) Either this function or cl_loop() should be - * invoked at the end of every client program since - * cl_select()/cl_loop() are responsibe with the trigger + * cl_ctx_select - function that replaces the select() function + * (sys/select.h) Either this function or cl_loop() should be + * invoked at the end of every client program since + * cl_select()/cl_loop() are responsibe with the trigger * refreshing and processing the options of the received packets. */ #define cl_ctx_select(ctx, n, readfds, writefds, exceptfds, cl_to) \ - cl_context_select(ctx, n, readfds, writefds, exceptfds, cl_to) + cl_context_select(ctx, n, readfds, writefds, exceptfds, cl_to) int cl_ctx_loop(cl_context *ctx); @@ -36,23 +36,23 @@ * CL_TRIGGER_CFLAG_L_CONSTRAINT - left constraint trigger * CL_TRIGGER_CFLAG_PUBLIC - public trigger; otherwise the trigger * is private. If the trigger is public - * then it has to be left constraint, - * i.e., CL_TRIGGER_CFLAG_R_CONSTRAINT + * then it has to be left constraint, + * i.e., CL_TRIGGER_CFLAG_R_CONSTRAINT * and CL_TRIGGER_CFLAG_PUBLIC cannot be * used simultaneously */ cl_trigger *cl_ctx_create_trigger(cl_context *ctx, - ID *id, uint16_t prefix_len, Key *key, - uint16_t flags, int *rc); + ID *id, uint16_t prefix_len, Key *key, + uint16_t flags, int *rc); /* create a trigger pointing to a stack */ cl_trigger *cl_ctx_create_trigger_stack(cl_context *ctx, - ID *id, uint16_t prefix_len, - ID *stack, int stack_len, - uint16_t flags, int *rc); + ID *id, uint16_t prefix_len, + ID *stack, int stack_len, + uint16_t flags, int *rc); /* destroy trigger */ int cl_ctx_destroy_trigger(cl_context *ctx, cl_trigger *ctr); /* insert trigger into i3 - * Possible flags: + * Possible flags: * CL_IFLAGS_TRIGGER_LOCAL - trigger is only local, i.e., it is not inserted * into i3 * CL_IFLAGS_TRIGGER_ALLOW_SHORTCUT - allow shortcut @@ -61,42 +61,41 @@ #define cl_ctx_remove_trigger(ctx, ctr) cl_remove_trigger_from_i3(ctx, ctr) -int cl_ctx_trigger_ratelimit(cl_context* ctx, cl_trigger *ctr, uint8_t type, - uint32_t depth, uint32_t r, uint32_t R); +int cl_ctx_trigger_ratelimit(cl_context *ctx, cl_trigger *ctr, uint8_t type, + uint32_t depth, uint32_t r, uint32_t R); /* send functions */ -int cl_ctx_send_stack(cl_context *ctx, ID *stack, int stack_len, - cl_buf *clb, uint16_t flags); +int cl_ctx_send_stack(cl_context *ctx, ID *stack, int stack_len, + cl_buf *clb, uint16_t flags); #define cl_ctx_send(ctx, id, clb, flags) \ - cl_ctx_send_to_stack(ctx, id, 1, clb, flags) + cl_ctx_send_to_stack(ctx, id, 1, clb, flags) /* register callback functions and timers */ #define cl_ctx_register_callback(g_ctx, cbk_type, fun, fun_ctx) \ - cl_register_context_callback(g_ctx, cbk_type, fun, fun_ctx) + cl_register_context_callback(g_ctx, cbk_type, fun, fun_ctx) //ADDED_DILIP -int cl_ctx_register_trigger_callback(cl_context *ctx, cl_trigger *ctr, uint16_t cbk_type, - void (*fun)(void* ctr, void* data, void* fun_ctx), void *fun_ctx); //DILIP - - -int cl_ctx_register_fd_callback(cl_context *ctx, int fd, - int type, void (*fun)(int, void*), void *data); +int cl_ctx_register_trigger_callback(cl_context * ctx, cl_trigger * ctr, uint16_t cbk_type, + void (*fun)(void *ctr, void *data, void *fun_ctx), void *fun_ctx); //DILIP + + +int cl_ctx_register_fd_callback(cl_context * ctx, int fd, + int type, void (*fun)(int, void *), void *data); int cl_ctx_unregister_fd_callback(cl_context *ctx, int fd, int type); -cl_timer *cl_ctx_set_timer(cl_context *ctx, struct timeval *tv, - void (*fun)(void *), void *data); +cl_timer *cl_ctx_set_timer(cl_context * ctx, struct timeval *tv, + void (*fun)(void *), void *data); -/* - * Get close servers from a list of servers +/* + * Get close servers from a list of servers * - currently uses a combination of latitude-longitude + pings */ int cl_ctx_get_rtt_server(cl_context *ctx, uint32_t addr, uint64_t *rtt); int cl_ctx_get_rtt_id(cl_context *ctx, ID *id, uint64_t *rtt); -int cl_ctx_get_top_k_servers(cl_context* ctx, int *k, uint32_t best_addr[], uint16_t best_port[], uint64_t best_rtt[]); -int cl_ctx_get_top_k_ids(cl_context* ctx, int *k, ID best_id[], uint64_t best_rtt[]); - - -void i3_close_all_sockets (cl_context* ctx); +int cl_ctx_get_top_k_servers(cl_context * ctx, int *k, uint32_t best_addr[], uint16_t best_port[], uint64_t best_rtt[]); +int cl_ctx_get_top_k_ids(cl_context * ctx, int *k, ID best_id[], uint64_t best_rtt[]); + + +void i3_close_all_sockets(cl_context *ctx); #endif // I3_CLIENT_API_CTX_H - === modified file 'i3/i3_client/i3_client_api_ext.c' --- i3/i3_client/i3_client_api_ext.c 2009-12-29 21:08:52 +0000 +++ i3/i3_client/i3_client_api_ext.c 2010-02-11 11:49:47 +0000 @@ -1,6 +1,6 @@ #include "../i3/i3.h" -#include <errno.h> +#include <errno.h> #include <time.h> #ifndef _WIN32 #include <pthread.h> @@ -18,9 +18,9 @@ #include "i3_client_api_ctx.h" /********************************************************************** - * - **********************************************************************/ -int cl_init_ping(cl_context* ctx, char *url) +* +**********************************************************************/ +int cl_init_ping(cl_context *ctx, char *url) { #ifndef _WIN32 pthread_t ping_thread; @@ -32,34 +32,34 @@ Coordinates coord; char *temp_str; int i; - - if (ctx == NULL) - return CL_RET_DUP_CONTEXT; - - ctx->list = (I3ServerList *) malloc(sizeof(I3ServerList)); + + if (ctx == NULL) { + return CL_RET_DUP_CONTEXT; + } + + ctx->list = (I3ServerList *) malloc(sizeof(I3ServerList)); ctx->ping_start_time = (uint64_t *) malloc(sizeof(uint64_t)); init_i3server_list(ctx->list); - coord.latitude = COORD_UNDEFINED; coord.longitude = COORD_UNDEFINED; - for (i = 0; i < ctx->num_servers; i++) - create_i3server(ctx->list, ctx->s_array[i].addr.s_addr, - ctx->s_array[i].port, ctx->s_array[i].id, coord); - - data = (PingThreadData *) malloc(sizeof(PingThreadData)); - temp_str = (char *) malloc(strlen(url)+1); + coord.latitude = COORD_UNDEFINED; + coord.longitude = COORD_UNDEFINED; + for (i = 0; i < ctx->num_servers; i++) { + create_i3server(ctx->list, ctx->s_array[i].addr.s_addr, + ctx->s_array[i].port, ctx->s_array[i].id, coord); + } + + data = (PingThreadData *) malloc(sizeof(PingThreadData)); + temp_str = (char *) malloc(strlen(url) + 1); strcpy(temp_str, url); - data->url = temp_str; - data->list = ctx->list; + data->url = temp_str; + data->list = ctx->list; data->ping_start_time = ctx->ping_start_time; #ifndef _WIN32 - pthread_create(&ping_thread, NULL, ping_thread_entry, (void *)data); + pthread_create(&ping_thread, NULL, ping_thread_entry, (void *) data); return CL_RET_OK; #else - err = _beginthreadex(NULL, 0, ping_thread_entry, (void *)data, 0, &ping_thread); + err = _beginthreadex(NULL, 0, ping_thread_entry, (void *) data, 0, &ping_thread); return (0 != err) ? CL_RET_OK : errno; #endif } - - - === modified file 'i3/i3_client/i3_client_callback.c' --- i3/i3_client/i3_client_callback.c 2010-01-06 22:17:32 +0000 +++ i3/i3_client/i3_client_callback.c 2010-02-11 11:49:47 +0000 @@ -1,9 +1,9 @@ /*************************************************************************** - i3_client_callback.c - description - ------------------- - begin : Aug 14 2003 - email : istoica@xxxxxxxxxxxxxxx - ***************************************************************************/ +* i3_client_callback.c - description +* ------------------- +* begin : Aug 14 2003 +* email : istoica@xxxxxxxxxxxxxxx +***************************************************************************/ #include "../i3/i3.h" #include "../i3/i3_fun.h" @@ -12,7 +12,7 @@ #include "../i3/i3_debug.h" -//#define PRINT_DEF_CBK +//#define PRINT_DEF_CBK #ifdef CLIENT_API_DEPRECIATED #define TRG(x) (x->t) @@ -21,15 +21,14 @@ #endif -void printf_def_cbk(char *str, ID *id, int intend) +void printf_def_cbk(char *str, ID *id, int intend) { #ifdef PRINT_DEF_CBK - I3_PRINT_DEBUG1(DEBUG_LEVEL_MINIMAL, "Default callback: %s\n", str); - printf_i3_id(id, intend); + I3_PRINT_DEBUG1(DEBUG_LEVEL_MINIMAL, "Default callback: %s\n", str); + printf_i3_id(id, intend); #endif } - /*********************************************************************** * cl_trigger_callback - invoke a callback associated with a trigger * @@ -44,135 +43,128 @@ * ************************************************************************/ -void cl_trigger_callback(cl_context *ctx, cl_trigger *ctr, int cbk_type, - i3_header *hdr, cl_buf *cbl) +void cl_trigger_callback(cl_context *ctx, cl_trigger *ctr, int cbk_type, + i3_header *hdr, cl_buf *cbl) { - switch (cbk_type) { - case CL_CBK_TRIGGER_INSERTED: - // printf("In Callback: trigger with following ID inserted\n"); - // printf_i3_id(&(ctr->t->id), 2); - if (ctr->cbk_trigger_inserted.fun) { - ctr->cbk_trigger_inserted.fun(TRG(ctr), - NULL, ctr->cbk_trigger_inserted.fun_ctx); - } else if (ctx->cbk_trigger_inserted.fun) { - ctx->cbk_trigger_inserted.fun(TRG(ctr), - NULL, ctx->cbk_trigger_inserted.fun_ctx); - } else { - printf_def_cbk("trigger with following ID inserted", - &(ctr->t->id), 2); - } - break; - case CL_CBK_TRIGGER_REFRESH_FAILED: - if (ctr->cbk_trigger_refresh_failed.fun) - ctr->cbk_trigger_refresh_failed.fun(TRG(ctr), - NULL, ctr->cbk_trigger_refresh_failed.fun_ctx); - else if (ctx->cbk_trigger_refresh_failed.fun) - ctx->cbk_trigger_refresh_failed.fun(TRG(ctr), - NULL, ctx->cbk_trigger_refresh_failed.fun_ctx); - else { - printf_def_cbk("trigger with following ID couldn't be inserted/refreshed", - &(ctr->t->id), 2); - } - break; + switch (cbk_type) { + case CL_CBK_TRIGGER_INSERTED: + // printf("In Callback: trigger with following ID inserted\n"); + // printf_i3_id(&(ctr->t->id), 2); + if (ctr->cbk_trigger_inserted.fun) { + ctr->cbk_trigger_inserted.fun(TRG(ctr), + NULL, ctr->cbk_trigger_inserted.fun_ctx); + } else if (ctx->cbk_trigger_inserted.fun) { + ctx->cbk_trigger_inserted.fun(TRG(ctr), + NULL, ctx->cbk_trigger_inserted.fun_ctx); + } else { + printf_def_cbk("trigger with following ID inserted", + &(ctr->t->id), 2); + } + break; + case CL_CBK_TRIGGER_REFRESH_FAILED: + if (ctr->cbk_trigger_refresh_failed.fun) { + ctr->cbk_trigger_refresh_failed.fun(TRG(ctr), + NULL, ctr->cbk_trigger_refresh_failed.fun_ctx); + } else if (ctx->cbk_trigger_refresh_failed.fun) { + ctx->cbk_trigger_refresh_failed.fun(TRG(ctr), + NULL, ctx->cbk_trigger_refresh_failed.fun_ctx); + } else { + printf_def_cbk("trigger with following ID couldn't be inserted/refreshed", + &(ctr->t->id), 2); + } + break; - case CL_CBK_TRIGGER_CONSTRAINT_FAILED: - if (ctr->cbk_trigger_constraint_failed.fun) - ctr->cbk_trigger_constraint_failed.fun(TRG(ctr), - NULL, ctr->cbk_trigger_constraint_failed.fun_ctx); - else if (ctx->cbk_trigger_constraint_failed.fun) - ctx->cbk_trigger_constraint_failed.fun(TRG(ctr), - NULL, ctx->cbk_trigger_constraint_failed.fun_ctx); - else { - printf_def_cbk("trigger with following ID didn't satisfy constraints", - &(ctr->t->id), 2); - } - break; + case CL_CBK_TRIGGER_CONSTRAINT_FAILED: + if (ctr->cbk_trigger_constraint_failed.fun) { + ctr->cbk_trigger_constraint_failed.fun(TRG(ctr), + NULL, ctr->cbk_trigger_constraint_failed.fun_ctx); + } else if (ctx->cbk_trigger_constraint_failed.fun) { + ctx->cbk_trigger_constraint_failed.fun(TRG(ctr), + NULL, ctx->cbk_trigger_constraint_failed.fun_ctx); + } else { + printf_def_cbk("trigger with following ID didn't satisfy constraints", + &(ctr->t->id), 2); + } + break; case CL_CBK_RECEIVE_PACKET: - { - // The packet and its header to be passed to the callback function - // The callback function is responsible for freeing this memory. - static cbk_packet *tmp_cbk_pkt = NULL; - if (tmp_cbk_pkt == NULL) { - tmp_cbk_pkt = malloc(sizeof(cbk_packet)); - } - tmp_cbk_pkt->ids = &(hdr->stack->ids[1]); - tmp_cbk_pkt->stack_len = hdr->stack->len - 1; - tmp_cbk_pkt->clb = cbl; - - if (hdr->stack->len <= 0) { - tmp_cbk_pkt->ids = NULL; - } - - - if (ctr->cbk_receive_packet.fun) - ctr->cbk_receive_packet.fun(TRG(ctr), tmp_cbk_pkt, - ctr->cbk_receive_packet.fun_ctx); - - else if (ctx->cbk_receive_packet.fun) - ctx->cbk_receive_packet.fun(TRG(ctr), tmp_cbk_pkt, - ctx->cbk_receive_packet.fun_ctx); - else { - printf_def_cbk("received packet matching following ID", - &(ctr->t->id), 2); - } - } + { + // The packet and its header to be passed to the callback function + // The callback function is responsible for freeing this memory. + static cbk_packet *tmp_cbk_pkt = NULL; + if (tmp_cbk_pkt == NULL) { + tmp_cbk_pkt = malloc(sizeof(cbk_packet)); + } + tmp_cbk_pkt->ids = &(hdr->stack->ids[1]); + tmp_cbk_pkt->stack_len = hdr->stack->len - 1; + tmp_cbk_pkt->clb = cbl; + + if (hdr->stack->len <= 0) { + tmp_cbk_pkt->ids = NULL; + } + + + if (ctr->cbk_receive_packet.fun) { + ctr->cbk_receive_packet.fun(TRG(ctr), tmp_cbk_pkt, + ctr->cbk_receive_packet.fun_ctx); + } else if (ctx->cbk_receive_packet.fun) { + ctx->cbk_receive_packet.fun(TRG(ctr), tmp_cbk_pkt, + ctx->cbk_receive_packet.fun_ctx); + } else { + printf_def_cbk("received packet matching following ID", + &(ctr->t->id), 2); + } + } break; - + case CL_CBK_RECEIVE_PAYLOAD: - if (ctr->cbk_receive_packet.fun) + if (ctr->cbk_receive_packet.fun) { break; - - else if (ctr->cbk_receive_payload.fun) + } else if (ctr->cbk_receive_payload.fun) { ctr->cbk_receive_payload.fun(TRG(ctr), cbl, - ctr->cbk_receive_payload.fun_ctx); - - else if (ctx->cbk_receive_packet.fun) + ctr->cbk_receive_payload.fun_ctx); + } else if (ctx->cbk_receive_packet.fun) { break; - - else if (ctx->cbk_receive_payload.fun) - - ctx->cbk_receive_payload.fun(TRG(ctr), cbl,ctx->cbk_receive_payload.fun_ctx); - - else { - printf_def_cbk("received data matching following ID", - &(ctr->t->id), 2); + } else if (ctx->cbk_receive_payload.fun) { + ctx->cbk_receive_payload.fun(TRG(ctr), cbl, ctx->cbk_receive_payload.fun_ctx); + } else { + printf_def_cbk("received data matching following ID", + &(ctr->t->id), 2); } - break; - + break; + case CL_CBK_ROUTE_BROKEN: - if (ctr->cbk_route_broken.fun) + if (ctr->cbk_route_broken.fun) { ctr->cbk_route_broken.fun(TRG(ctr), NULL, ctr->cbk_route_broken.fun_ctx); - else if (ctx->cbk_route_broken.fun) + } else if (ctx->cbk_route_broken.fun) { ctx->cbk_route_broken.fun(TRG(ctr), NULL, ctx->cbk_route_broken.fun_ctx); - else { + } else { #ifdef PRINT_DEF_CBK I3_PRINT_DEBUG1(I3_DEBUG_LEVEL_MINIMAL, "Default callback: route broken while at the following trigger\n"); - printf_i3_trigger(ctr->t, 2); + printf_i3_trigger(ctr->t, 2); #endif // PRINT_DEF_CBK - } - break; + } + break; case CL_INTERNAL_HOOK_TRIGGER_ACK_TIMEOUT: - if (ctr->internal_hook_ack_timeout.fun) { - ctr->internal_hook_ack_timeout.fun(TRG(ctr), - NULL, ctr->internal_hook_ack_timeout.fun_ctx); - + if (ctr->internal_hook_ack_timeout.fun) { + ctr->internal_hook_ack_timeout.fun(TRG(ctr), + NULL, ctr->internal_hook_ack_timeout.fun_ctx); } - break; + break; case CL_INTERNAL_HOOK_TRIGGER_REFRESH_TIMEOUT: - if (ctr->internal_hook_refresh_timeout.fun) { - ctr->internal_hook_refresh_timeout.fun(TRG(ctr), - NULL, ctr->internal_hook_refresh_timeout.fun_ctx); + if (ctr->internal_hook_refresh_timeout.fun) { + ctr->internal_hook_refresh_timeout.fun(TRG(ctr), + NULL, ctr->internal_hook_refresh_timeout.fun_ctx); } - break; - - - - default: + break; + + + + default: I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, "cl_trigger_callback: invalid callback type!\n"); - } + } } /*********************************************************************** @@ -185,51 +177,49 @@ ************************************************************************/ void cl_id_callback(cl_context *ctx, int cbk_type, ID *id, - struct in_addr *ip_addr, uint16_t *port) + struct in_addr *ip_addr, uint16_t *port) { switch (cbk_type) { - case CL_CBK_TRIGGER_NOT_FOUND: - if (ctx->cbk_trigger_not_found.fun) - ctx->cbk_trigger_not_found.fun(id, NULL, - ctx->cbk_trigger_not_found.fun_ctx); - else { - printf_def_cbk("there is no trigger matching following ID", - id, 2); - } - break; - - case CL_CBK_RATELIMIT_EXCEEDED: - if (ctx->cbk_ratelimit_exceeded.fun) - ctx->cbk_ratelimit_exceeded.fun(id, NULL, - ctx->cbk_ratelimit_exceeded.fun_ctx); - else { - printf_def_cbk("token-bucket constraints violated for ID", - id, 2); - } - break; - - case CL_CBK_SERVER_DOWN: - if (ctx->cbk_server_down.fun) { - ctx->cbk_server_down.fun(ip_addr, port, ctx->cbk_server_down.fun_ctx); - } else { - + case CL_CBK_TRIGGER_NOT_FOUND: + if (ctx->cbk_trigger_not_found.fun) { + ctx->cbk_trigger_not_found.fun(id, NULL, + ctx->cbk_trigger_not_found.fun_ctx); + } else { + printf_def_cbk("there is no trigger matching following ID", + id, 2); + } + break; + + case CL_CBK_RATELIMIT_EXCEEDED: + if (ctx->cbk_ratelimit_exceeded.fun) { + ctx->cbk_ratelimit_exceeded.fun(id, NULL, + ctx->cbk_ratelimit_exceeded.fun_ctx); + } else { + printf_def_cbk("token-bucket constraints violated for ID", + id, 2); + } + break; + + case CL_CBK_SERVER_DOWN: + if (ctx->cbk_server_down.fun) { + ctx->cbk_server_down.fun(ip_addr, port, ctx->cbk_server_down.fun_ctx); + } else { #ifdef PRINT_DEF_CBK - ip_addr->s_addr = htonl(ip_addr->s_addr); - I3_PRINT_DEBUG2(I3_DEBUG_LEVEL_MINIMAL, "Default callback: server couldn't be contacted (%s, %d)\n", - inet_ntoa(*ip_addr), *port); - ip_addr->s_addr = ntohl(ip_addr->s_addr); + ip_addr->s_addr = htonl(ip_addr->s_addr); + I3_PRINT_DEBUG2(I3_DEBUG_LEVEL_MINIMAL, "Default callback: server couldn't be contacted (%s, %d)\n", + inet_ntoa(*ip_addr), *port); + ip_addr->s_addr = ntohl(ip_addr->s_addr); #endif - } + } break; - - default: - I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, "cl_callback: invalid callback type!\n"); + + default: + I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, "cl_callback: invalid callback type!\n"); } } - /************************************************************************ - * cl_register_trigger_callback1 - associate a callback with a trigger + * cl_register_trigger_callback1 - associate a callback with a trigger * * input: * ctr - trigger @@ -239,84 +229,82 @@ *************************************************************************/ int cl_register_trigger_callback1(cl_trigger *ctr, uint16_t cbk_type, - void (*fun)(void*, void* data, void *fun_ctx), - void *fun_ctx) + void (*fun)(void *, void *data, void *fun_ctx), + void *fun_ctx) { - switch (cbk_type) { - case CL_CBK_TRIGGER_INSERTED: - if (ctr->type == CL_TRIGGER_LOCAL) { - // local triggers are not inserted in i3 - return CL_RET_INVALID_TRIGGER_TYPE; - } - ctr->cbk_trigger_inserted.fun = fun; - ctr->cbk_trigger_inserted.fun_ctx = fun_ctx; - break; - - case CL_CBK_TRIGGER_REFRESH_FAILED: - if (ctr->type == CL_TRIGGER_LOCAL) { - // local triggers are not inserted in i3 - return CL_RET_INVALID_TRIGGER_TYPE; - } - - ctr->cbk_trigger_refresh_failed.fun = fun; - ctr->cbk_trigger_refresh_failed.fun_ctx = fun_ctx; - break; - - case CL_CBK_TRIGGER_CONSTRAINT_FAILED: - if (ctr->type == CL_TRIGGER_LOCAL) { - // local triggers are not inserted in i3 - return CL_RET_INVALID_TRIGGER_TYPE; - } - - ctr->cbk_trigger_constraint_failed.fun = fun; - ctr->cbk_trigger_constraint_failed.fun_ctx = fun_ctx; - break; - - case CL_CBK_RECEIVE_PACKET: - ctr->cbk_receive_packet.fun = fun; - ctr->cbk_receive_packet.fun_ctx = fun_ctx; - /* this callback takes precedence over - * CL_CBK_RECEIVE_PAYLOAD callback */ - if (ctr->cbk_receive_payload.fun) { - return CL_RET_IGNORE_CBK_RECEIVE_PAYLOAD; - } - break; - - case CL_CBK_RECEIVE_PAYLOAD: - ctr->cbk_receive_payload.fun = fun; - ctr->cbk_receive_payload.fun_ctx = fun_ctx; - /* this callback is ignored if CL_CBK_RECEIVE_PACKET is already defined */ - if (ctr->cbk_receive_packet.fun) { - return CL_RET_IGNORE_CBK_RECEIVE_PAYLOAD; - } - break; - - case CL_CBK_ROUTE_BROKEN: - ctr->cbk_route_broken.fun = fun; - ctr->cbk_route_broken.fun_ctx = fun_ctx; - break; - - case CL_INTERNAL_HOOK_TRIGGER_ACK_TIMEOUT: - ctr->internal_hook_ack_timeout.fun = fun; - ctr->internal_hook_ack_timeout.fun_ctx = fun_ctx; - break; - - case CL_INTERNAL_HOOK_TRIGGER_REFRESH_TIMEOUT: - ctr->internal_hook_refresh_timeout.fun = fun; - ctr->internal_hook_refresh_timeout.fun_ctx = fun_ctx; - break; - - default: - panic("cl_cbk_register_trigger_callback: invalid callback type!\n"); + case CL_CBK_TRIGGER_INSERTED: + if (ctr->type == CL_TRIGGER_LOCAL) { + // local triggers are not inserted in i3 + return CL_RET_INVALID_TRIGGER_TYPE; + } + ctr->cbk_trigger_inserted.fun = fun; + ctr->cbk_trigger_inserted.fun_ctx = fun_ctx; + break; + + case CL_CBK_TRIGGER_REFRESH_FAILED: + if (ctr->type == CL_TRIGGER_LOCAL) { + // local triggers are not inserted in i3 + return CL_RET_INVALID_TRIGGER_TYPE; + } + + ctr->cbk_trigger_refresh_failed.fun = fun; + ctr->cbk_trigger_refresh_failed.fun_ctx = fun_ctx; + break; + + case CL_CBK_TRIGGER_CONSTRAINT_FAILED: + if (ctr->type == CL_TRIGGER_LOCAL) { + // local triggers are not inserted in i3 + return CL_RET_INVALID_TRIGGER_TYPE; + } + + ctr->cbk_trigger_constraint_failed.fun = fun; + ctr->cbk_trigger_constraint_failed.fun_ctx = fun_ctx; + break; + + case CL_CBK_RECEIVE_PACKET: + ctr->cbk_receive_packet.fun = fun; + ctr->cbk_receive_packet.fun_ctx = fun_ctx; + /* this callback takes precedence over + * CL_CBK_RECEIVE_PAYLOAD callback */ + if (ctr->cbk_receive_payload.fun) { + return CL_RET_IGNORE_CBK_RECEIVE_PAYLOAD; + } + break; + + case CL_CBK_RECEIVE_PAYLOAD: + ctr->cbk_receive_payload.fun = fun; + ctr->cbk_receive_payload.fun_ctx = fun_ctx; + /* this callback is ignored if CL_CBK_RECEIVE_PACKET is already defined */ + if (ctr->cbk_receive_packet.fun) { + return CL_RET_IGNORE_CBK_RECEIVE_PAYLOAD; + } + break; + + case CL_CBK_ROUTE_BROKEN: + ctr->cbk_route_broken.fun = fun; + ctr->cbk_route_broken.fun_ctx = fun_ctx; + break; + + case CL_INTERNAL_HOOK_TRIGGER_ACK_TIMEOUT: + ctr->internal_hook_ack_timeout.fun = fun; + ctr->internal_hook_ack_timeout.fun_ctx = fun_ctx; + break; + + case CL_INTERNAL_HOOK_TRIGGER_REFRESH_TIMEOUT: + ctr->internal_hook_refresh_timeout.fun = fun; + ctr->internal_hook_refresh_timeout.fun_ctx = fun_ctx; + break; + + default: + panic("cl_cbk_register_trigger_callback: invalid callback type!\n"); } - + return CL_RET_OK; } - /************************************************************************ - * cl_register_context_callback - associate a callback with a context + * cl_register_context_callback - associate a callback with a context * * input: * ctr - trigger @@ -326,71 +314,68 @@ *************************************************************************/ int cl_register_context_callback(cl_context *ctx, uint16_t cbk_type, - void (*fun)(void *ctx_data, void *data, void* fun_ctx), - void * fun_ctx) + void (*fun)(void *ctx_data, void *data, void *fun_ctx), + void *fun_ctx) { - switch (cbk_type) { - case CL_CBK_TRIGGER_NOT_FOUND: - ctx->cbk_trigger_not_found.fun = fun; - ctx->cbk_trigger_not_found.fun_ctx = fun_ctx; - break; - - case CL_CBK_TRIGGER_INSERTED: - ctx->cbk_trigger_inserted.fun = fun; - ctx->cbk_trigger_inserted.fun_ctx = fun_ctx; - break; - - case CL_CBK_TRIGGER_REFRESH_FAILED: - ctx->cbk_trigger_refresh_failed.fun = fun; - ctx->cbk_trigger_refresh_failed.fun_ctx = fun_ctx; - break; - - case CL_CBK_TRIGGER_CONSTRAINT_FAILED: - ctx->cbk_trigger_constraint_failed.fun = fun; - ctx->cbk_trigger_constraint_failed.fun_ctx = fun_ctx; - break; - - case CL_CBK_RECEIVE_PACKET: - ctx->cbk_receive_packet.fun = fun; - ctx->cbk_receive_packet.fun_ctx = fun_ctx; - /* this callback takes precedence over - * CL_CBK_RECEIVE_PAYLOAD callback - */ - - if (ctx->cbk_receive_payload.fun) { - return CL_RET_IGNORE_CBK_RECEIVE_PAYLOAD; - } - break; - - case CL_CBK_RECEIVE_PAYLOAD: - ctx->cbk_receive_payload.fun = fun; - ctx->cbk_receive_payload.fun_ctx = fun_ctx; - /* this callback is ignored if CL_CBK_RECEIVE_PACKET is already defined */ - if (ctx->cbk_receive_packet.fun) { - return CL_RET_IGNORE_CBK_RECEIVE_PAYLOAD; - } - break; - - case CL_CBK_ROUTE_BROKEN: - ctx->cbk_route_broken.fun = fun; - ctx->cbk_route_broken.fun_ctx = fun_ctx; - break; - - case CL_CBK_SERVER_DOWN: - ctx->cbk_server_down.fun = fun; - ctx->cbk_server_down.fun_ctx = fun_ctx; - break; - - case CL_CBK_RATELIMIT_EXCEEDED: - ctx->cbk_ratelimit_exceeded.fun = fun; - ctx->cbk_ratelimit_exceeded.fun_ctx = fun_ctx; - break; - - default: - I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, "cl_register_context_callback: invalid callback type!\n"); - } - return CL_RET_OK; + case CL_CBK_TRIGGER_NOT_FOUND: + ctx->cbk_trigger_not_found.fun = fun; + ctx->cbk_trigger_not_found.fun_ctx = fun_ctx; + break; + + case CL_CBK_TRIGGER_INSERTED: + ctx->cbk_trigger_inserted.fun = fun; + ctx->cbk_trigger_inserted.fun_ctx = fun_ctx; + break; + + case CL_CBK_TRIGGER_REFRESH_FAILED: + ctx->cbk_trigger_refresh_failed.fun = fun; + ctx->cbk_trigger_refresh_failed.fun_ctx = fun_ctx; + break; + + case CL_CBK_TRIGGER_CONSTRAINT_FAILED: + ctx->cbk_trigger_constraint_failed.fun = fun; + ctx->cbk_trigger_constraint_failed.fun_ctx = fun_ctx; + break; + + case CL_CBK_RECEIVE_PACKET: + ctx->cbk_receive_packet.fun = fun; + ctx->cbk_receive_packet.fun_ctx = fun_ctx; + /* this callback takes precedence over + * CL_CBK_RECEIVE_PAYLOAD callback + */ + + if (ctx->cbk_receive_payload.fun) { + return CL_RET_IGNORE_CBK_RECEIVE_PAYLOAD; + } + break; + + case CL_CBK_RECEIVE_PAYLOAD: + ctx->cbk_receive_payload.fun = fun; + ctx->cbk_receive_payload.fun_ctx = fun_ctx; + /* this callback is ignored if CL_CBK_RECEIVE_PACKET is already defined */ + if (ctx->cbk_receive_packet.fun) { + return CL_RET_IGNORE_CBK_RECEIVE_PAYLOAD; + } + break; + + case CL_CBK_ROUTE_BROKEN: + ctx->cbk_route_broken.fun = fun; + ctx->cbk_route_broken.fun_ctx = fun_ctx; + break; + + case CL_CBK_SERVER_DOWN: + ctx->cbk_server_down.fun = fun; + ctx->cbk_server_down.fun_ctx = fun_ctx; + break; + + case CL_CBK_RATELIMIT_EXCEEDED: + ctx->cbk_ratelimit_exceeded.fun = fun; + ctx->cbk_ratelimit_exceeded.fun_ctx = fun_ctx; + break; + + default: + I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, "cl_register_context_callback: invalid callback type!\n"); + } + return CL_RET_OK; } - - === modified file 'i3/i3_client/i3_client_callback.h' --- i3/i3_client/i3_client_callback.h 2010-01-06 22:17:32 +0000 +++ i3/i3_client/i3_client_callback.h 2010-02-11 11:49:47 +0000 @@ -1,25 +1,25 @@ /*************************************************************************** - i3_client_callback.h - description - ------------------- - begin : Aug 14 2003 - email : istoica@xxxxxxxxxxxxxxx - ***************************************************************************/ +* i3_client_callback.h - description +* ------------------- +* begin : Aug 14 2003 +* email : istoica@xxxxxxxxxxxxxxx +***************************************************************************/ #ifndef I3_CLIENT_CALLBACK_H #define I3_CLIENT_CALLBACK_H int cl_register_context_callback( - cl_context *ctx, uint16_t cbk_type, - void (*fun)(void *ctx_data, void *data, void* fun_ctx), - void *fun_ctx); - -int cl_register_trigger_callback1(cl_trigger *clt, uint16_t cbk_type, - void (*fun)(void*, void* data, void* fun_ctx), - void *fun_ctx); - - -void cl_trigger_callback(cl_context *ctx, cl_trigger *ctr, - int cbk_type, i3_header *hdr, cl_buf *clb); + cl_context * ctx, uint16_t cbk_type, + void (*fun)(void *ctx_data, void *data, void *fun_ctx), + void *fun_ctx); + +int cl_register_trigger_callback1(cl_trigger * clt, uint16_t cbk_type, + void (*fun)(void *, void *data, void *fun_ctx), + void *fun_ctx); + + +void cl_trigger_callback(cl_context *ctx, cl_trigger *ctr, + int cbk_type, i3_header *hdr, cl_buf *clb); void cl_id_callback(cl_context *ctx, int cbk_type, ID *id, - struct in_addr *addr, uint16_t *port); + struct in_addr *addr, uint16_t *port); #endif === modified file 'i3/i3_client/i3_client_context.c' --- i3/i3_client/i3_client_context.c 2010-01-12 12:35:31 +0000 +++ i3/i3_client/i3_client_context.c 2010-02-11 11:49:47 +0000 @@ -1,14 +1,14 @@ /*************************************************************************** - i3_client_context.c - description - ------------------- - begin : Aug 14 2003 - email : istoica@xxxxxxxxxxxxxxx - - changes: - Nov 10, 2004: - handle the anycast triggers inserted by the same node - (in cl_context_select) - - ***************************************************************************/ +* i3_client_context.c - description +* ------------------- +* begin : Aug 14 2003 +* email : istoica@xxxxxxxxxxxxxxx +* +* changes: +* Nov 10, 2004: - handle the anycast triggers inserted by the same node +* (in cl_context_select) +* +***************************************************************************/ #include <stdio.h> #include <stdarg.h> @@ -48,846 +48,862 @@ int does_id_match(ID *id1, ID *id2, int prefix_len); -void close_tcp(cl_context *ctx) { +void close_tcp(cl_context *ctx) +{ + printf("\nClosing fd = %d\n", ctx->tcp_fd); + nw_close(ctx->tcp_fd); - printf ("\nClosing fd = %d\n", ctx->tcp_fd); - nw_close(ctx->tcp_fd); - - ctx->init_tcp_ctx_flag = 0; //TCP socket is not initialized. + ctx->init_tcp_ctx_flag = 0; //TCP socket is not initialized. } /** - * This function initializes the TCP socket used to communicate - * with the first hop i3 server, if UseTCP is set in the configuration file - * @author Dilip - */ -void init_tcp_ctx(cl_context* ctx) { - int idx; - struct sockaddr_in server_addr; - - if (ctx->is_tcp) { - fprintf(stderr, "Warning: Mobility using TCP unsupported\n"); - - if (ctx->init_tcp_ctx_flag) - close_tcp(ctx); // make sure that there isn't a TCP connection - // in inconsistent state - if ((ctx->tcp_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { - perror("socket"); - I3_PRINT_INFO1(I3_INFO_LEVEL_WARNING, - "Failed to create TCP socket (errno = %d)\n", errno); - ctx->init_tcp_ctx_flag = 0; - return; - } - - printf("open TCP socket = %d\n", ctx->tcp_fd); // XXX - if (bind(ctx->tcp_fd, (struct sockaddr *) &ctx->local, - sizeof(struct sockaddr_in)) < 0) { - I3_PRINT_DEBUG1(I3_DEBUG_LEVEL_MINIMAL, - "cl_init_context: TCP bind (errno = %d)\n", errno); - close_tcp(ctx); - return; - } - - /* Get server from the list and connect to it - * For now, it is assumed that there is only one server on the - * list and (obviously) that is the first hop i3 server - */ - idx = get_i3_server(ctx->num_servers, ctx->s_array); - if (idx < 0) { - if (!ctx->use_ping) { - I3_PRINT_INFO0 (I3_INFO_LEVEL_FATAL_ERROR, - "There are no known i3 servers specified in the configuration file " - "and UsePing is deactivated. So there is no way I can get to know " - "about an i3 server.\nPlease turn on UsePing or specify i3 server " - "details in the i3 configuration file.\n" - ); - EXIT_ON_ERROR; - } - close_tcp(ctx); - return; - - //TODO fix i3 client API to include timer to reattempt tcp init later. - } - - memset(&server_addr, 0, sizeof(struct sockaddr_in)); - server_addr.sin_family = AF_INET; - server_addr.sin_addr.s_addr = htonl(ctx->s_array[idx].addr.s_addr); - server_addr.sin_port = htons(ctx->s_array[idx].port); - - I3_PRINT_INFO1 (I3_INFO_LEVEL_MINIMAL, - "I3 OC-D trying to connect to %s via TCP.\n", - inet_ntoa (((struct sockaddr_in *) &server_addr)->sin_addr)); - - if (connect(ctx->tcp_fd, (struct sockaddr *)&server_addr, - sizeof(struct sockaddr_in)) < 0) { - I3_PRINT_DEBUG1(I3_DEBUG_LEVEL_MINIMAL, - "cl_init_context: TCP connect error (errno = %d)\n", errno); - close_tcp(ctx);; - } else { - I3_PRINT_INFO1(I3_INFO_LEVEL_MINIMAL, - "I3 OC-D connected to %s via TCP.\n", - inet_ntoa (((struct sockaddr_in *) &server_addr)->sin_addr)); - ctx->init_tcp_ctx_flag = 1; //TCP socket was initialized. - } - } -} - + * This function initializes the TCP socket used to communicate + * with the first hop i3 server, if UseTCP is set in the configuration file + * @author Dilip + */ +void init_tcp_ctx(cl_context *ctx) +{ + int idx; + struct sockaddr_in server_addr; + + if (ctx->is_tcp) { + fprintf(stderr, "Warning: Mobility using TCP unsupported\n"); + + if (ctx->init_tcp_ctx_flag) { + close_tcp(ctx); // make sure that there isn't a TCP connection + } + // in inconsistent state + if ((ctx->tcp_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { + perror("socket"); + I3_PRINT_INFO1(I3_INFO_LEVEL_WARNING, + "Failed to create TCP socket (errno = %d)\n", errno); + ctx->init_tcp_ctx_flag = 0; + return; + } + + printf("open TCP socket = %d\n", ctx->tcp_fd); // XXX + if (bind(ctx->tcp_fd, (struct sockaddr *) &ctx->local, + sizeof(struct sockaddr_in)) < 0) { + I3_PRINT_DEBUG1(I3_DEBUG_LEVEL_MINIMAL, + "cl_init_context: TCP bind (errno = %d)\n", errno); + close_tcp(ctx); + return; + } + + /* Get server from the list and connect to it + * For now, it is assumed that there is only one server on the + * list and (obviously) that is the first hop i3 server + */ + idx = get_i3_server(ctx->num_servers, ctx->s_array); + if (idx < 0) { + if (!ctx->use_ping) { + I3_PRINT_INFO0(I3_INFO_LEVEL_FATAL_ERROR, + "There are no known i3 servers specified in the configuration file " + "and UsePing is deactivated. So there is no way I can get to know " + "about an i3 server.\nPlease turn on UsePing or specify i3 server " + "details in the i3 configuration file.\n" + ); + EXIT_ON_ERROR; + } + close_tcp(ctx); + return; + + //TODO fix i3 client API to include timer to reattempt tcp init later. + } + + memset(&server_addr, 0, sizeof(struct sockaddr_in)); + server_addr.sin_family = AF_INET; + server_addr.sin_addr.s_addr = htonl(ctx->s_array[idx].addr.s_addr); + server_addr.sin_port = htons(ctx->s_array[idx].port); + + I3_PRINT_INFO1(I3_INFO_LEVEL_MINIMAL, + "I3 OC-D trying to connect to %s via TCP.\n", + inet_ntoa(((struct sockaddr_in *) &server_addr)->sin_addr)); + + if (connect(ctx->tcp_fd, (struct sockaddr *) &server_addr, + sizeof(struct sockaddr_in)) < 0) { + I3_PRINT_DEBUG1(I3_DEBUG_LEVEL_MINIMAL, + "cl_init_context: TCP connect error (errno = %d)\n", errno); + close_tcp(ctx); + ; + } else { + I3_PRINT_INFO1(I3_INFO_LEVEL_MINIMAL, + "I3 OC-D connected to %s via TCP.\n", + inet_ntoa(((struct sockaddr_in *) &server_addr)->sin_addr)); + ctx->init_tcp_ctx_flag = 1; //TCP socket was initialized. + } + } +} /*************************************************************************** - * cl_create_context - allocate and initialize i3 client context. the context - * maintains the address of a default i3 server and the - * list of the triggers inserted by the client - * - * input: - * local_ip_addr, local_port - local IP address and port where - * i3 packets are to be received (in host format) - * - * return: - * allocated context - ***************************************************************************/ +* cl_create_context - allocate and initialize i3 client context. the context +* maintains the address of a default i3 server and the +* list of the triggers inserted by the client +* +* input: +* local_ip_addr, local_port - local IP address and port where +* i3 packets are to be received (in host format) +* +* return: +* allocated context +***************************************************************************/ cl_context *cl_create_context(struct in_addr *local_ip_addr, - uint16_t local_port) + uint16_t local_port) { - cl_context *ctx; - uint8_t opt_mask; - int bind_ret_val; - - aeshash_init(); - - if (local_port == 0) { - local_port = unif_rand(MIN_PORT_NUM, MAX_PORT_NUM); - I3_PRINT_DEBUG1(I3_DEBUG_LEVEL_VERBOSE, "i3 port number: %d\n", local_port); - } - - if (!(ctx = (cl_context *)calloc(1, sizeof(cl_context)))) + cl_context *ctx; + uint8_t opt_mask; + int bind_ret_val; + + aeshash_init(); + + if (local_port == 0) { + local_port = unif_rand(MIN_PORT_NUM, MAX_PORT_NUM); + I3_PRINT_DEBUG1(I3_DEBUG_LEVEL_VERBOSE, "i3 port number: %d\n", local_port); + } + + if (!(ctx = (cl_context *) calloc(1, sizeof(cl_context)))) { I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, "cl_init_context: memory allocation error (1)\n"); - - uint64_to_tval(&ctx->now, wall_time()); - - if (!(ctx->s_array = (srv_address *)calloc(MAX_NUM_SRV,sizeof(srv_address)))) + } + + uint64_to_tval(&ctx->now, wall_time()); + + if (!(ctx->s_array = (srv_address *) calloc(MAX_NUM_SRV, sizeof(srv_address)))) { I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, "cl_init_context: memory allocation error (2)\n"); - - /* read the list of i3 server addreses from the configuration file */ - read_srv_list(ctx); - - /* create field descriptor and address data structure to - * receive i3 traffic */ - - { - int tmpFD = socket (AF_INET, SOCK_DGRAM, 0); - char*tmp; - if (tmpFD < 0) { - perror ("socket"); - I3_PRINT_DEBUG1 ( I3_DEBUG_LEVEL_WARNING, - "Unable to open i3 UDP socket: %s.\n", - strerror (errno) - ); - tmp = strerror (errno); - - switch (errno) { - case EBADF: - printf ("EBADF\n"); - break; - case EINVAL: - printf ("EINVAL\n"); - break; - case EACCES: - printf ("EACCES\n"); - break; - case ENOTSOCK: - printf ("ENOTSOCK\n"); - break; - case EROFS: - printf ("EROFS \n"); - break; - - case EFAULT: - printf ("EFAULT\n"); - break; - - case ENAMETOOLONG: - printf ("ENAMETOOLONG\n"); - break; - case ENOENT: - printf ("ENOENT\n"); - break; - case ENOMEM: - printf ("ENOMEME\n"); - break; - } - exit(-1); - } else { - ctx->fd = tmpFD; - } - } - - - - memset(&ctx->local, 0, sizeof(struct sockaddr_in)); - ctx->local.sin_family = AF_INET; - ctx->local.sin_addr.s_addr = htonl(INADDR_ANY); - ctx->local.sin_port = htons(local_port); - - /* bind to the port */ - - if ((bind_ret_val = bind(ctx->fd, (struct sockaddr *) &ctx->local, sizeof(struct sockaddr_in))) < 0) { - - switch (bind_ret_val) { - case EBADF: - printf ("EBADF\n"); - break; - case EINVAL: - printf ("EINVAL\n"); - break; - case EACCES: - printf ("EACCES\n"); - break; - case ENOTSOCK: - printf ("ENOTSOCK\n"); - break; - case EROFS: - printf ("EROFS \n"); - break; - - case EFAULT: - printf ("EFAULT\n"); - break; - - case ENAMETOOLONG: - printf ("ENAMETOOLONG\n"); - break; - case ENOENT: - printf ("ENOENT\n"); - break; - case ENOMEM: - printf ("ENOMEME\n"); - break; - } - I3_PRINT_INFO1 ( - I3_INFO_LEVEL_WARNING, - "Critical Error: Unable to bind i3 socket while creating context: %s.\n", - strerror (errno) - ); - return NULL; - //panic("cl_init_context: bind\n"); - } - - I3_PRINT_DEBUG3( - I3_DEBUG_LEVEL_VERBOSE, - "Bound i3 fd=%d to %d : %s\n", - ctx->fd, - ctx->local.sin_port, - inet_ntoa(ctx->local.sin_addr) + } + + /* read the list of i3 server addreses from the configuration file */ + read_srv_list(ctx); + + /* create field descriptor and address data structure to + * receive i3 traffic */ + + { + int tmpFD = socket(AF_INET, SOCK_DGRAM, 0); + char *tmp; + if (tmpFD < 0) { + perror("socket"); + I3_PRINT_DEBUG1( I3_DEBUG_LEVEL_WARNING, + "Unable to open i3 UDP socket: %s.\n", + strerror(errno) + ); + tmp = strerror(errno); + + switch (errno) { + case EBADF: + printf("EBADF\n"); + break; + case EINVAL: + printf("EINVAL\n"); + break; + case EACCES: + printf("EACCES\n"); + break; + case ENOTSOCK: + printf("ENOTSOCK\n"); + break; + case EROFS: + printf("EROFS \n"); + break; + + case EFAULT: + printf("EFAULT\n"); + break; + + case ENAMETOOLONG: + printf("ENAMETOOLONG\n"); + break; + case ENOENT: + printf("ENOENT\n"); + break; + case ENOMEM: + printf("ENOMEME\n"); + break; + } + exit(-1); + } else { + ctx->fd = tmpFD; + } + } + + + + memset(&ctx->local, 0, sizeof(struct sockaddr_in)); + ctx->local.sin_family = AF_INET; + ctx->local.sin_addr.s_addr = htonl(INADDR_ANY); + ctx->local.sin_port = htons(local_port); + + /* bind to the port */ + + if ((bind_ret_val = bind(ctx->fd, (struct sockaddr *) &ctx->local, sizeof(struct sockaddr_in))) < 0) { + switch (bind_ret_val) { + case EBADF: + printf("EBADF\n"); + break; + case EINVAL: + printf("EINVAL\n"); + break; + case EACCES: + printf("EACCES\n"); + break; + case ENOTSOCK: + printf("ENOTSOCK\n"); + break; + case EROFS: + printf("EROFS \n"); + break; + + case EFAULT: + printf("EFAULT\n"); + break; + + case ENAMETOOLONG: + printf("ENAMETOOLONG\n"); + break; + case ENOENT: + printf("ENOENT\n"); + break; + case ENOMEM: + printf("ENOMEME\n"); + break; + } + I3_PRINT_INFO1( + I3_INFO_LEVEL_WARNING, + "Critical Error: Unable to bind i3 socket while creating context: %s.\n", + strerror(errno) + ); + return NULL; + //panic("cl_init_context: bind\n"); + } + + I3_PRINT_DEBUG3( + I3_DEBUG_LEVEL_VERBOSE, + "Bound i3 fd=%d to %d : %s\n", + ctx->fd, + ctx->local.sin_port, + inet_ntoa(ctx->local.sin_addr) ); - if (local_ip_addr) - ctx->local_ip_addr = *local_ip_addr; - else - ctx->local_ip_addr = get_local_addr_cl(); // keep it in host format - - ctx->local_port = local_port; - - /* PRIORITY QUEUE Initialization */ + if (local_ip_addr) { + ctx->local_ip_addr = *local_ip_addr; + } else { + ctx->local_ip_addr = get_local_addr_cl(); // keep it in host format + } + ctx->local_port = local_port; + + /* PRIORITY QUEUE Initialization */ #define MAX_TRIGGERS 100000 - /* precompute option part of headers */ - for (opt_mask = 0; opt_mask < MAX_OPTS_MASK_SIZE; opt_mask++) - make_data_opt(ctx, opt_mask, &ctx->precomputed_opt[opt_mask]); - - /* Ping list initialization */ - ctx->list = NULL; - - /* init timer heap */ - init_timer_heap(ctx); - - /* allocate data structure for file descriptors that the user may register */ - ctx->i3fds = alloc_i3_fds(); - - return ctx; + /* precompute option part of headers */ + for (opt_mask = 0; opt_mask < MAX_OPTS_MASK_SIZE; opt_mask++) { + make_data_opt(ctx, opt_mask, &ctx->precomputed_opt[opt_mask]); + } + + /* Ping list initialization */ + ctx->list = NULL; + + /* init timer heap */ + init_timer_heap(ctx); + + /* allocate data structure for file descriptors that the user may register */ + ctx->i3fds = alloc_i3_fds(); + + return ctx; } /* close sockets and re-open them */ void cl_reinit_context(cl_context *ctx) { - static int so_reuseaddr = 1; - uint8_t opt_mask; - - if (ctx->fd) - nw_close(ctx->fd); - if (ctx->init_tcp_ctx_flag && ctx->is_tcp) - close_tcp(ctx); - - if ((ctx->fd = socket (AF_INET, SOCK_DGRAM, 0)) < 0) { - perror ("socket recreation"); - - exit(-1); - } - - memset(&ctx->local, 0, sizeof(struct sockaddr_in)); - ctx->local.sin_family = AF_INET; - ctx->local.sin_addr.s_addr = htonl(INADDR_ANY); - ctx->local.sin_port = htons(ctx->local_port); - - if ((setsockopt(ctx->fd, SOL_SOCKET, SO_REUSEADDR, - (char *)&so_reuseaddr, sizeof(so_reuseaddr))) < 0) { - perror("setsockopt"); - } - - if (bind(ctx->fd, (struct sockaddr *) &ctx->local, - sizeof(struct sockaddr_in)) < 0) + static int so_reuseaddr = 1; + uint8_t opt_mask; + + if (ctx->fd) { + nw_close(ctx->fd); + } + if (ctx->init_tcp_ctx_flag && ctx->is_tcp) { + close_tcp(ctx); + } + + if ((ctx->fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { + perror("socket recreation"); + + exit(-1); + } + + memset(&ctx->local, 0, sizeof(struct sockaddr_in)); + ctx->local.sin_family = AF_INET; + ctx->local.sin_addr.s_addr = htonl(INADDR_ANY); + ctx->local.sin_port = htons(ctx->local_port); + + if ((setsockopt(ctx->fd, SOL_SOCKET, SO_REUSEADDR, + (char *) &so_reuseaddr, sizeof(so_reuseaddr))) < 0) { + perror("setsockopt"); + } + + if (bind(ctx->fd, (struct sockaddr *) &ctx->local, + sizeof(struct sockaddr_in)) < 0) { I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, "cl_reinit_context: bind\n"); - - /* precompute option part of headers */ - for (opt_mask = 0; opt_mask < MAX_OPTS_MASK_SIZE; opt_mask++) { - if (ctx->precomputed_opt[opt_mask].p) - free(ctx->precomputed_opt[opt_mask].p); - make_data_opt(ctx, opt_mask, &ctx->precomputed_opt[opt_mask]); - } - - if (ctx->is_tcp) { - init_tcp_ctx(ctx); - fprintf(stderr, "Warning: Mobility using TCP unsupported\n"); - } + } + + /* precompute option part of headers */ + for (opt_mask = 0; opt_mask < MAX_OPTS_MASK_SIZE; opt_mask++) { + if (ctx->precomputed_opt[opt_mask].p) { + free(ctx->precomputed_opt[opt_mask].p); + } + make_data_opt(ctx, opt_mask, &ctx->precomputed_opt[opt_mask]); + } + + if (ctx->is_tcp) { + init_tcp_ctx(ctx); + fprintf(stderr, "Warning: Mobility using TCP unsupported\n"); + } } - void cl_destroy_context(cl_context *ctx) { - int i; - uint8_t opt_mask; - - for (i = 0; i < CL_HTABLE_SIZE; i++) { - if (ctx->trigger_htable[i]) - cl_free_trigger_list(ctx->trigger_htable[i]); - if (ctx->id_htable[i]) - cl_free_id_list(ctx->id_htable[i]); - } - - free_timer_heap(ctx); - free_i3_fds(ctx->i3fds); - ctx->i3fds = NULL; - - for (opt_mask = 0; opt_mask < MAX_OPTS_MASK_SIZE; opt_mask++) - if (ctx->precomputed_opt[opt_mask].p) - free(ctx->precomputed_opt[opt_mask].p); - - free(ctx->s_array); - - // close the connections assocatied with the context - nw_close (ctx->fd); - if (ctx->init_tcp_ctx_flag) { - close_tcp(ctx); - } - - free (ctx); //deallocate the memory + int i; + uint8_t opt_mask; + + for (i = 0; i < CL_HTABLE_SIZE; i++) { + if (ctx->trigger_htable[i]) { + cl_free_trigger_list(ctx->trigger_htable[i]); + } + if (ctx->id_htable[i]) { + cl_free_id_list(ctx->id_htable[i]); + } + } + + free_timer_heap(ctx); + free_i3_fds(ctx->i3fds); + ctx->i3fds = NULL; + + for (opt_mask = 0; opt_mask < MAX_OPTS_MASK_SIZE; opt_mask++) { + if (ctx->precomputed_opt[opt_mask].p) { + free(ctx->precomputed_opt[opt_mask].p); + } + } + + free(ctx->s_array); + + // close the connections assocatied with the context + nw_close(ctx->fd); + if (ctx->init_tcp_ctx_flag) { + close_tcp(ctx); + } + + free(ctx); //deallocate the memory } #define MAX_PACKET_SIZE 4096 -int cl_context_select(cl_context *ctx, int n, - fd_set *readfds, fd_set *writefds, fd_set *exceptfds, - struct timeval *cl_to) -{ - int max_fd, rc; - static struct timeval to, tv; - uint64_t now, crt_time; - struct timeval next_to, sel_to; - static cl_buf *clb = NULL; - char packet_received; - assert(readfds); - - /* initialize vars when this method is called for the first time */ - if (NULL == clb) { - now = wall_time(); - clb = cl_alloc_buf(MAX_PACKET_SIZE); - - /* set timeout to check whether the refresh has changed */ - tv.tv_sec = ADDR_CHECK_PERIOD; - tv.tv_usec = random_sec(); - cl_set_timer(&tv, timeout_address_change, ctx); - - /* set timeout refresh the server list */ - tv.tv_sec = SERVER_UPDATE_PERIOD; - tv.tv_usec = random_sec(); - cl_set_timer(&tv, timeout_server_update, ctx); - } - - /* There are three types of file descriptors: - * 1) Descriptors on which the client receives i3 packets from - * the i3 servers (ctx->fd and ctx->fd_tcp) - * 2) Descriptors for which the application has registered callbacks - * 3) Descriptors which application has passed as arguments in - * the cl_select() function - */ - max_fd = MAX(ctx->fd + 1, n); - // printf("------------------ ctx->tcp_fd=%d, max_fd=%d\n", - // ctx->tcp_fd, max_fd); - if (ctx->is_tcp && ctx->init_tcp_ctx_flag) { - max_fd = MAX(ctx->tcp_fd + 1, max_fd); - } - max_fd = MAX(max_fd, ctx->i3fds->max_fd + 1); - - for (;;) { - /* update current time */ - now = wall_time(); - uint64_to_tval(&ctx->now, now); - - /* set socket descriptors for i3 traffic and for the callbacks - * inserted by the applications - */ - /* if another tcp connection or user connection have been opened, - * update max_fd - */ - if (ctx->is_tcp && ctx->init_tcp_ctx_flag && ctx->tcp_fd >= max_fd) { - max_fd = MAX(ctx->tcp_fd + 1, max_fd); - } - if (ctx->i3fds->max_fd >= max_fd) { - max_fd = MAX(max_fd, ctx->i3fds->max_fd + 1); - } - - FD_SET(ctx->fd, readfds); - +int cl_context_select(cl_context *ctx, int n, + fd_set *readfds, fd_set *writefds, fd_set *exceptfds, + struct timeval *cl_to) +{ + int max_fd, rc; + static struct timeval to, tv; + uint64_t now, crt_time; + struct timeval next_to, sel_to; + static cl_buf *clb = NULL; + char packet_received; + assert(readfds); + + /* initialize vars when this method is called for the first time */ + if (NULL == clb) { + now = wall_time(); + clb = cl_alloc_buf(MAX_PACKET_SIZE); + + /* set timeout to check whether the refresh has changed */ + tv.tv_sec = ADDR_CHECK_PERIOD; + tv.tv_usec = random_sec(); + cl_set_timer(&tv, timeout_address_change, ctx); + + /* set timeout refresh the server list */ + tv.tv_sec = SERVER_UPDATE_PERIOD; + tv.tv_usec = random_sec(); + cl_set_timer(&tv, timeout_server_update, ctx); + } + + /* There are three types of file descriptors: + * 1) Descriptors on which the client receives i3 packets from + * the i3 servers (ctx->fd and ctx->fd_tcp) + * 2) Descriptors for which the application has registered callbacks + * 3) Descriptors which application has passed as arguments in + * the cl_select() function + */ + max_fd = MAX(ctx->fd + 1, n); + // printf("------------------ ctx->tcp_fd=%d, max_fd=%d\n", + // ctx->tcp_fd, max_fd); if (ctx->is_tcp && ctx->init_tcp_ctx_flag) { - FD_SET(ctx->tcp_fd, readfds); - } - - set_i3_fds(ctx->i3fds, readfds, writefds, exceptfds); - - /* invoke timer callbacks inserted by the application */ - invoke_timers(ctx, now); - - /* compute timeout (to) for select() as minimum between - * (1) the timeout (cl_to) pased by application are argument of - * cl_context_select() - * (2) time to next event set by application via cl_set_timer() - * system call - */ - if (get_next_timer(ctx, &next_to, now)) { - tval_min(&to, &next_to, cl_to); - } else { - to = *cl_to; - } - - /* remember timeout of select, because some slect implementations - * may update timeout "to" to indicate how much time has passed - */ - sel_to = to; - packet_received = 0; - /* select() */ - - if ((rc = select(max_fd, readfds, writefds, exceptfds, &to)) < 0) { - int err = nw_error(); - if ((err == EINTR) || (err == EBADF)) { - if (cl_to) { - /* update cl_to with the time spent in select() */ - crt_time = wall_time(); - cl_update_to(cl_to, crt_time - now); - if (cl_to->tv_sec == 0 && cl_to->tv_usec == 0) { - /* check whether any timers expired while in select, before - * returning - */ - invoke_timers(ctx, crt_time); - /* client's timout has expired; tell client to try again... */ - errno = EINTR; - return rc; - } - } - /* check client's callbacks before continuing... */ - invoke_i3_fds(ctx->i3fds, readfds, writefds, exceptfds); - continue; - } else { - err_sys("select_error\n"); - } - } - - //printf("(3)\n"); - if (rc > 0) { - /* at least one packet has been received, thus - * timeout "to" probably didn't expire - */ - packet_received = 1; - } - - /* check whether a packet hasn't been received on any of the - * callback file descriptors - */ - rc -= invoke_i3_fds(ctx->i3fds, readfds, writefds, exceptfds); - - /* i3 packet has been received */ - if (FD_ISSET(ctx->fd, readfds) || - (ctx->is_tcp && ctx->init_tcp_ctx_flag && - FD_ISSET(ctx->tcp_fd, readfds))) { - int retVal; - - rc -= 1; - - //ADDED_DILIP - retVal = cl_process_recd_i3_pkt(ctx, clb); - - if (retVal == CL_CONTINUE) { - if (cl_to) - /* update cl_to with the time spent in select */ - cl_update_to(cl_to, wall_time() - now); - continue; - } - } - - /* either cl_to expired or a packet on another socket - * has been received*/ - /* --- WARNING: This can lead to EXTREMELY subtle bugs --- TODO! */ - if (!packet_received && cl_to && tval_equal(cl_to, &sel_to)) { - /* if no packet has been received, then the select - * timeout must have been expired. Check whether - * this timeout was equal to the client timeout, and if - * yes return - */ - cl_to->tv_sec = cl_to->tv_usec = 0; - invoke_timers(ctx, wall_time()); - return rc; - } - - if (rc > 0) { - /* there is a packet received on a socket descriptor passed by the - * client in the cl_select function - */ - /* update cl_to with the time spent in select, - * and check whether any other timeouts expired during - * this period; then return - */ - crt_time = wall_time(); - if (cl_to) - cl_update_to(cl_to, crt_time - now); - invoke_timers(ctx, crt_time); - return rc; - } - /* continue, after updating cl_to... */ - if (cl_to) - cl_update_to(cl_to, wall_time() - now); - } + max_fd = MAX(ctx->tcp_fd + 1, max_fd); + } + max_fd = MAX(max_fd, ctx->i3fds->max_fd + 1); + + for (;; ) { + /* update current time */ + now = wall_time(); + uint64_to_tval(&ctx->now, now); + + /* set socket descriptors for i3 traffic and for the callbacks + * inserted by the applications + */ + /* if another tcp connection or user connection have been opened, + * update max_fd + */ + if (ctx->is_tcp && ctx->init_tcp_ctx_flag && ctx->tcp_fd >= max_fd) { + max_fd = MAX(ctx->tcp_fd + 1, max_fd); + } + if (ctx->i3fds->max_fd >= max_fd) { + max_fd = MAX(max_fd, ctx->i3fds->max_fd + 1); + } + + FD_SET(ctx->fd, readfds); + + if (ctx->is_tcp && ctx->init_tcp_ctx_flag) { + FD_SET(ctx->tcp_fd, readfds); + } + + set_i3_fds(ctx->i3fds, readfds, writefds, exceptfds); + + /* invoke timer callbacks inserted by the application */ + invoke_timers(ctx, now); + + /* compute timeout (to) for select() as minimum between + * (1) the timeout (cl_to) pased by application are argument of + * cl_context_select() + * (2) time to next event set by application via cl_set_timer() + * system call + */ + if (get_next_timer(ctx, &next_to, now)) { + tval_min(&to, &next_to, cl_to); + } else { + to = *cl_to; + } + + /* remember timeout of select, because some slect implementations + * may update timeout "to" to indicate how much time has passed + */ + sel_to = to; + packet_received = 0; + /* select() */ + + if ((rc = select(max_fd, readfds, writefds, exceptfds, &to)) < 0) { + int err = nw_error(); + if ((err == EINTR) || (err == EBADF)) { + if (cl_to) { + /* update cl_to with the time spent in select() */ + crt_time = wall_time(); + cl_update_to(cl_to, crt_time - now); + if (cl_to->tv_sec == 0 && cl_to->tv_usec == 0) { + /* check whether any timers expired while in select, before + * returning + */ + invoke_timers(ctx, crt_time); + /* client's timout has expired; tell client to try again... */ + errno = EINTR; + return rc; + } + } + /* check client's callbacks before continuing... */ + invoke_i3_fds(ctx->i3fds, readfds, writefds, exceptfds); + continue; + } else { + err_sys("select_error\n"); + } + } + + //printf("(3)\n"); + if (rc > 0) { + /* at least one packet has been received, thus + * timeout "to" probably didn't expire + */ + packet_received = 1; + } + + /* check whether a packet hasn't been received on any of the + * callback file descriptors + */ + rc -= invoke_i3_fds(ctx->i3fds, readfds, writefds, exceptfds); + + /* i3 packet has been received */ + if (FD_ISSET(ctx->fd, readfds) || + (ctx->is_tcp && ctx->init_tcp_ctx_flag && + FD_ISSET(ctx->tcp_fd, readfds))) { + int retVal; + + rc -= 1; + + //ADDED_DILIP + retVal = cl_process_recd_i3_pkt(ctx, clb); + + if (retVal == CL_CONTINUE) { + if (cl_to) { + /* update cl_to with the time spent in select */ + cl_update_to(cl_to, wall_time() - now); + } + continue; + } + } + + /* either cl_to expired or a packet on another socket + * has been received*/ + /* --- WARNING: This can lead to EXTREMELY subtle bugs --- TODO! */ + if (!packet_received && cl_to && tval_equal(cl_to, &sel_to)) { + /* if no packet has been received, then the select + * timeout must have been expired. Check whether + * this timeout was equal to the client timeout, and if + * yes return + */ + cl_to->tv_sec = cl_to->tv_usec = 0; + invoke_timers(ctx, wall_time()); + return rc; + } + + if (rc > 0) { + /* there is a packet received on a socket descriptor passed by the + * client in the cl_select function + */ + /* update cl_to with the time spent in select, + * and check whether any other timeouts expired during + * this period; then return + */ + crt_time = wall_time(); + if (cl_to) { + cl_update_to(cl_to, crt_time - now); + } + invoke_timers(ctx, crt_time); + return rc; + } + /* continue, after updating cl_to... */ + if (cl_to) { + cl_update_to(cl_to, wall_time() - now); + } + } } /** - * This function is called when an i3 packet is received. - * The received i3 packet is processed here. - * This function is usually called from within a select loop. - */ -int cl_process_recd_i3_pkt (cl_context * ctx, cl_buf *clb) { - - struct sockaddr_in fromaddr; - i3_header *hdr; - cl_trigger *ctr, *ctr_next; - - int recv_ret_val; - - /* hdr is allocated in cl_receive_packet; remember to free it ... */ - recv_ret_val = cl_receive_packet_from (ctx, &hdr, clb, &fromaddr); - - if (recv_ret_val == 0) { - //Some error occurred while reading packet - - if (ctx->is_tcp) - close_tcp(ctx); - - return CL_RECV_ERROR; - } - - if (hdr == NULL) - return CL_CONTINUE; - - if (hdr->option_list) { - /* process option list received in the packet header */ - cl_process_option_list (ctx, hdr, &fromaddr); - } - - if (hdr->stack && hdr->stack->len) { - - /* the packet may match multiple triggers; - * implement anycast, by getting the longest prefix match - */ - int max_prefix_len; - max_prefix_len = - cl_get_max_prefix_len_from_list( - ctx->trigger_htable[CL_HASH_TRIG(hdr->stack-> ids)], hdr->stack->ids); - - /* get trigger's data structure */ - ctr = cl_get_trigger_by_id( - ctx->trigger_htable[CL_HASH_TRIG (hdr->stack->ids)], - hdr->stack->ids); - - for (; ctr;) { - if ((does_id_match (&ctr->t->id, - hdr->stack->ids, - max_prefix_len) == FALSE) - || (ctr->t->to->type != I3_ADDR_TYPE_IPv4)) { - ctr = ctr->next; - continue; - } - - ctr_next = ctr->next; - - if (ctr->cbk_receive_packet.fun != NULL) - cl_trigger_callback (ctx, ctr, CL_CBK_RECEIVE_PACKET, hdr, clb); - else if (hdr->flags & I3_DATA) - cl_trigger_callback (ctx, ctr, CL_CBK_RECEIVE_PAYLOAD, NULL, clb); - else - printf - ("Invalid i3 packet type in cl_context_select()\n"); - /* ctr pointer shouldn'be used after this call because the ctr - * might have been deleted in the callback - */ - - if (ctr_next) - ctr = cl_get_trigger_by_id (ctr_next, hdr->stack->ids); - else - break; - } - } - /* ... here we free the header */ - free_i3_header (hdr); - - return CL_NO_CONTINUE; + * This function is called when an i3 packet is received. + * The received i3 packet is processed here. + * This function is usually called from within a select loop. + */ +int cl_process_recd_i3_pkt(cl_context *ctx, cl_buf *clb) +{ + struct sockaddr_in fromaddr; + i3_header *hdr; + cl_trigger *ctr, *ctr_next; + + int recv_ret_val; + + /* hdr is allocated in cl_receive_packet; remember to free it ... */ + recv_ret_val = cl_receive_packet_from(ctx, &hdr, clb, &fromaddr); + + if (recv_ret_val == 0) { + //Some error occurred while reading packet + + if (ctx->is_tcp) { + close_tcp(ctx); + } + + return CL_RECV_ERROR; + } + + if (hdr == NULL) { + return CL_CONTINUE; + } + + if (hdr->option_list) { + /* process option list received in the packet header */ + cl_process_option_list(ctx, hdr, &fromaddr); + } + + if (hdr->stack && hdr->stack->len) { + /* the packet may match multiple triggers; + * implement anycast, by getting the longest prefix match + */ + int max_prefix_len; + max_prefix_len = + cl_get_max_prefix_len_from_list( + ctx->trigger_htable[CL_HASH_TRIG(hdr->stack->ids)], hdr->stack->ids); + + /* get trigger's data structure */ + ctr = cl_get_trigger_by_id( + ctx->trigger_htable[CL_HASH_TRIG(hdr->stack->ids)], + hdr->stack->ids); + + for (; ctr; ) { + if ((does_id_match(&ctr->t->id, + hdr->stack->ids, + max_prefix_len) == FALSE) + || (ctr->t->to->type != I3_ADDR_TYPE_IPv4)) { + ctr = ctr->next; + continue; + } + + ctr_next = ctr->next; + + if (ctr->cbk_receive_packet.fun != NULL) { + cl_trigger_callback(ctx, ctr, CL_CBK_RECEIVE_PACKET, hdr, clb); + } else if (hdr->flags & I3_DATA) { + cl_trigger_callback(ctx, ctr, CL_CBK_RECEIVE_PAYLOAD, NULL, clb); + } else { + printf + ("Invalid i3 packet type in cl_context_select()\n"); + } + /* ctr pointer shouldn'be used after this call because the ctr + * might have been deleted in the callback + */ + + if (ctr_next) { + ctr = cl_get_trigger_by_id(ctr_next, hdr->stack->ids); + } else { + break; + } + } + } + /* ... here we free the header */ + free_i3_header(hdr); + + return CL_NO_CONTINUE; } - - int get_i3_server(int num_servers, srv_address *s_array) { - int num = 0; - int i; - - //printf("In get_i3_server, num_servers = %d\n\n", num_servers); - - if (num_servers == 0) - return -1; - - for (i = 0; i < 2 * num_servers; i++) { - num = n_rand(num_servers); - if (s_array[num].status == ID_UP) - return num; - } - - num = 0; - for (i = 0; i < num_servers; i++) { - if (s_array[i].status == ID_UP) - return i; - if (s_array[i].status == ID_DOWN) - num++; - } - /* there are known servers in the list, but all of them are down; - * select a random one */ - if (num) { - num = n_rand(num); + int num = 0; + int i; + + //printf("In get_i3_server, num_servers = %d\n\n", num_servers); + + if (num_servers == 0) { + return -1; + } + + for (i = 0; i < 2 * num_servers; i++) { + num = n_rand(num_servers); + if (s_array[num].status == ID_UP) { + return num; + } + } + + num = 0; for (i = 0; i < num_servers; i++) { - if (s_array[i].status == ID_DOWN) { - if (num == 0) - return i; - else - num--; - } - } - } + if (s_array[i].status == ID_UP) { + return i; + } + if (s_array[i].status == ID_DOWN) { + num++; + } + } + /* there are known servers in the list, but all of them are down; + * select a random one */ + if (num) { + num = n_rand(num); + for (i = 0; i < num_servers; i++) { + if (s_array[i].status == ID_DOWN) { + if (num == 0) { + return i; + } else { + num--; + } + } + } + } - panic("Likely bug in get_i3_server\n"); - return -1; + panic("Likely bug in get_i3_server\n"); + return -1; } - -srv_address *set_i3_server_status(srv_address *s_array, - uint32_t ip_addr, uint16_t port, - int status) +srv_address *set_i3_server_status(srv_address *s_array, + uint32_t ip_addr, uint16_t port, + int status) { - int i; + int i; - for (i = 0; i < MAX_NUM_SRV; i++) { - if ((s_array[i].port == port) && - (s_array[i].addr.s_addr == ip_addr)) { - s_array[i].status = status; - return &s_array[i]; + for (i = 0; i < MAX_NUM_SRV; i++) { + if ((s_array[i].port == port) && + (s_array[i].addr.s_addr == ip_addr)) { + s_array[i].status = status; + return &s_array[i]; + } } - } - return NULL; + return NULL; } - - /* read the list of server addresses and their port numbers * from the configuration files */ void read_srv_list(cl_context *ctx) { - int i = 0, port, ret; - char addrstr[MAX_BUF_SIZE]; - char idstr[MAX_BUF_SIZE]; - char** addrs = read_i3server_list(&ctx->num_servers); - - for (i = 0; i < ctx->num_servers; i++) - { - ret = sscanf(addrs[i], "%s %d %s\n", addrstr, &port, idstr); - free(addrs[i]); - - I3_PRINT_DEBUG2(I3_DEBUG_LEVEL_VERBOSE,"Using i3 server at %s %d\n",addrstr,port); - - if (i >= MAX_NUM_SRV) - continue; - - if (ret >= 3) - ctx->s_array[i].id = atoi3id(idstr); - else - fprintf(stderr, "Warning: proxy configuration file has incomplete <addr> field\n"); - ctx->s_array[i].port = port; + int i = 0, port, ret; + char addrstr[MAX_BUF_SIZE]; + char idstr[MAX_BUF_SIZE]; + char **addrs = read_i3server_list(&ctx->num_servers); + + for (i = 0; i < ctx->num_servers; i++) { + ret = sscanf(addrs[i], "%s %d %s\n", addrstr, &port, idstr); + free(addrs[i]); + + I3_PRINT_DEBUG2(I3_DEBUG_LEVEL_VERBOSE, "Using i3 server at %s %d\n", addrstr, port); + + if (i >= MAX_NUM_SRV) { + continue; + } + + if (ret >= 3) { + ctx->s_array[i].id = atoi3id(idstr); + } else { + fprintf(stderr, "Warning: proxy configuration file has incomplete <addr> field\n"); + } + ctx->s_array[i].port = port; //#ifdef _WIN32 // if (inet_aton(addrstr, &ctx->s_array[i].addr) < 0) //#else - if (inet_pton(AF_INET, addrstr, &ctx->s_array[i].addr) < 0) + if (inet_pton(AF_INET, addrstr, &ctx->s_array[i].addr) < 0) { //#endif - I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, "client_init: inet_pton error\n"); - - /* inet_pton returns the address in network format; - * convert it in host format */ - ctx->s_array[i].addr.s_addr = ntohl(ctx->s_array[i].addr.s_addr); - ctx->s_array[i].status = ID_DOWN; - - } - - free(addrs); - - printf("Number of i3 servers = %d\n", ctx->num_servers); + I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, "client_init: inet_pton error\n"); + } + + /* inet_pton returns the address in network format; + * convert it in host format */ + ctx->s_array[i].addr.s_addr = ntohl(ctx->s_array[i].addr.s_addr); + ctx->s_array[i].status = ID_DOWN; + } + + free(addrs); + + printf("Number of i3 servers = %d\n", ctx->num_servers); } void update_srv_list(cl_context *ctx) { - int i, k = MAX_NUM_SRV; - uint16_t port[MAX_NUM_SRV]; - uint32_t addr[MAX_NUM_SRV]; - uint64_t rtt[MAX_NUM_SRV]; - - if (cl_ctx_get_top_k_servers(ctx, &k, addr, port, rtt) == CL_RET_OK) { - for (i = 0; i < k; i++) { - //printf("in update_srv_list i=%d port[i] = %d \n", i, port[i]); - ctx->s_array[i].addr.s_addr = addr[i]; - ctx->s_array[i].port = port[i]; - ctx->s_array[i].status = ID_UP; //ADDED by dilip + int i, k = MAX_NUM_SRV; + uint16_t port[MAX_NUM_SRV]; + uint32_t addr[MAX_NUM_SRV]; + uint64_t rtt[MAX_NUM_SRV]; + + if (cl_ctx_get_top_k_servers(ctx, &k, addr, port, rtt) == CL_RET_OK) { + for (i = 0; i < k; i++) { + //printf("in update_srv_list i=%d port[i] = %d \n", i, port[i]); + ctx->s_array[i].addr.s_addr = addr[i]; + ctx->s_array[i].port = port[i]; + ctx->s_array[i].status = ID_UP; //ADDED by dilip + } + if (k > 0) { + ctx->num_servers = k; + } } - if (k > 0) - ctx->num_servers = k; - } } - /* function used to process timeval data structures */ int tval_zero(struct timeval *t) { - if (t->tv_sec || t->tv_usec) - return FALSE; - else - return TRUE; + if (t->tv_sec || t->tv_usec) { + return FALSE; + } else { + return TRUE; + } } void tval_min(struct timeval *tmin, struct timeval *t1, struct timeval *t2) { - if (!t1) - *tmin = *t2; - else if (!t2) - *tmin = *t1; - else { - tval_normalize(t1); - tval_normalize(t2); + if (!t1) { + *tmin = *t2; + } else if (!t2) { + *tmin = *t1; + } else { + tval_normalize(t1); + tval_normalize(t2); - if (t1->tv_sec < t2->tv_sec) - *tmin = *t1; - else if (t1->tv_sec > t2->tv_sec) - *tmin = *t2; - else if (t1->tv_usec < t2->tv_usec) - *tmin = *t1; - else - *tmin = *t2; - } + if (t1->tv_sec < t2->tv_sec) { + *tmin = *t1; + } else if (t1->tv_sec > t2->tv_sec) { + *tmin = *t2; + } else if (t1->tv_usec < t2->tv_usec) { + *tmin = *t1; + } else { + *tmin = *t2; + } + } } -void cl_update_to(struct timeval *cl_to, uint64_t diff) +void cl_update_to(struct timeval *cl_to, uint64_t diff) { - diff = tval_to_uint64(cl_to) - diff; - if ((int64_t)diff < 0) { - diff = 0; - } - uint64_to_tval(cl_to, diff); + diff = tval_to_uint64(cl_to) - diff; + if ((int64_t) diff < 0) { + diff = 0; + } + uint64_to_tval(cl_to, diff); } - int tval_equal(struct timeval *t1, struct timeval *t2) { - if (t1->tv_sec == t2->tv_sec && t1->tv_usec == t2->tv_usec) - return TRUE; - else - return FALSE; + if (t1->tv_sec == t2->tv_sec && t1->tv_usec == t2->tv_usec) { + return TRUE; + } else { + return FALSE; + } } - uint64_t tval_to_uint64(struct timeval *tv) { - return tv->tv_sec*UMILLION + tv->tv_usec; + return tv->tv_sec * UMILLION + tv->tv_usec; } - void uint64_to_tval(struct timeval *tv, uint64_t time) { - tv->tv_sec = time/UMILLION; - tv->tv_usec = time % UMILLION; + tv->tv_sec = time / UMILLION; + tv->tv_usec = time % UMILLION; } - void tval_normalize(struct timeval *t) { - if (t->tv_usec >= UMILLION) { - t->tv_sec += t->tv_usec/UMILLION; - t->tv_usec = t->tv_usec % UMILLION; - } + if (t->tv_usec >= UMILLION) { + t->tv_sec += t->tv_usec / UMILLION; + t->tv_usec = t->tv_usec % UMILLION; + } } - -/* get local address -- use fn in utils/ */ +/* get local address -- use fn in utils/ */ struct in_addr get_local_addr_cl() { - struct in_addr ia; - ia.s_addr = ntohl(get_local_addr()); - return ia; + struct in_addr ia; + ia.s_addr = ntohl(get_local_addr()); + return ia; } int check_addr_change(struct in_addr *ia) { - struct in_addr newAddr; - - newAddr.s_addr = ntohl(get_local_addr()); - - if (ia->s_addr != newAddr.s_addr) { - ia->s_addr = newAddr.s_addr; - return 1; - } else { - return 0; - } + struct in_addr newAddr; + + newAddr.s_addr = ntohl(get_local_addr()); + + if (ia->s_addr != newAddr.s_addr) { + ia->s_addr = newAddr.s_addr; + return 1; + } else { + return 0; + } } void timeout_address_change(void *context) { - struct timeval tv; - cl_context *ctx = (cl_context *) context; - - if (check_addr_change(&(ctx->local_ip_addr))) { - struct in_addr temp; - temp.s_addr = htonl(ctx->local_ip_addr.s_addr); - fprintf(stderr, "Detected address change to %s: updating triggers\n", - inet_ntoa(temp)); - cl_reinit_context(ctx); - cl_update_triggers(ctx); - - // inform ping process - set_status(ctx->ping_start_time, wall_time()); - } - tv.tv_sec = ADDR_CHECK_PERIOD; - tv.tv_usec = random_sec(); - cl_set_timer(&tv, timeout_address_change, ctx); + struct timeval tv; + cl_context *ctx = (cl_context *) context; + + if (check_addr_change(&(ctx->local_ip_addr))) { + struct in_addr temp; + temp.s_addr = htonl(ctx->local_ip_addr.s_addr); + fprintf(stderr, "Detected address change to %s: updating triggers\n", + inet_ntoa(temp)); + cl_reinit_context(ctx); + cl_update_triggers(ctx); + + // inform ping process + set_status(ctx->ping_start_time, wall_time()); + } + tv.tv_sec = ADDR_CHECK_PERIOD; + tv.tv_usec = random_sec(); + cl_set_timer(&tv, timeout_address_change, ctx); } void timeout_server_update(void *context) @@ -899,13 +915,12 @@ tv.tv_sec = SERVER_UPDATE_PERIOD; tv.tv_usec = random_sec(); cl_set_timer(&tv, timeout_server_update, ctx); - + // If TCP socket had not been previous initialized, try again. - if ( ctx->is_tcp && ! ctx->init_tcp_ctx_flag) { + if (ctx->is_tcp && !ctx->init_tcp_ctx_flag) { I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_VERBOSE, - "Retrying TCP socket initialization\n" - ); + "Retrying TCP socket initialization\n" + ); init_tcp_ctx(ctx); } } - === modified file 'i3/i3_client/i3_client_context.h' --- i3/i3_client/i3_client_context.h 2010-01-12 12:35:31 +0000 +++ i3/i3_client/i3_client_context.h 2010-02-11 11:49:47 +0000 @@ -1,9 +1,9 @@ /*************************************************************************** - i3_client_context.h - description - ------------------- - begin : Aug 14 2003 - email : istoica@xxxxxxxxxxxxxxx - ***************************************************************************/ +* i3_client_context.h - description +* ------------------- +* begin : Aug 14 2003 +* email : istoica@xxxxxxxxxxxxxxx +***************************************************************************/ #ifndef I3_CLIENT_CONTEXT_H #define I3_CLIENT_CONTEXT_H @@ -15,24 +15,23 @@ #define CL_RECV_ERROR -100 cl_context *cl_create_context(struct in_addr *ip_addr, - uint16_t local_port - ); + uint16_t local_port); void cl_destroy_context(cl_context *ctx); -void init_tcp_ctx(cl_context* ctx); +void init_tcp_ctx(cl_context *ctx); -int cl_context_select(cl_context *ctx, int n, - fd_set *readfds, fd_set *writefds, fd_set *exceptfds, - struct timeval *cl_to); +int cl_context_select(cl_context *ctx, int n, + fd_set *readfds, fd_set *writefds, fd_set *exceptfds, + struct timeval *cl_to); void read_srv_list(cl_context *ctx); void update_srv_list(cl_context *ctx); -srv_address *set_i3_server_status(srv_address *s_array, - uint32_t ip_addr, uint16_t port, - int status); +srv_address *set_i3_server_status(srv_address *s_array, + uint32_t ip_addr, uint16_t port, + int status); int get_i3_server(int num_servers, srv_address *s_array); -int cl_process_recd_i3_pkt(cl_context*, cl_buf*); +int cl_process_recd_i3_pkt(cl_context *, cl_buf *); void timeout_address_change(void *ctx); void timeout_server_update(void *ctx); === modified file 'i3/i3_client/i3_client_fd.c' --- i3/i3_client/i3_client_fd.c 2010-01-06 22:17:32 +0000 +++ i3/i3_client/i3_client_fd.c 2010-02-11 11:49:47 +0000 @@ -1,14 +1,14 @@ /*************************************************************************** - i3_client_fd.c - description - ------------------- - begin : July 22 2004 - email : istoica@xxxxxxxxxxxxxxx - - This file contains functions to manipulate a list of file descriptors. - This list contains file descriptors for which the application has inserted - a callback CL_CBK_READ_FD. - - ***************************************************************************/ +* i3_client_fd.c - description +* ------------------- +* begin : July 22 2004 +* email : istoica@xxxxxxxxxxxxxxx +* +* This file contains functions to manipulate a list of file descriptors. +* This list contains file descriptors for which the application has inserted +* a callback CL_CBK_READ_FD. +* +***************************************************************************/ #include <stdlib.h> #include <sys/types.h> @@ -21,174 +21,174 @@ i3_fds *alloc_i3_fds(void) { - i3_fds *n; + i3_fds *n; - if ((n = (i3_fds *)calloc(1, sizeof(i3_fds))) != NULL) { - return n; - } - I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, "alloc_i3_fds: memory allocation error.\n"); - return NULL; + if ((n = (i3_fds *) calloc(1, sizeof(i3_fds))) != NULL) { + return n; + } + I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, "alloc_i3_fds: memory allocation error.\n"); + return NULL; } void free_i3_fds(i3_fds *fds) { - free_fd_list(fds->readfd_list); - free_fd_list(fds->writefd_list); - free_fd_list(fds->exceptfd_list); - free(fds); -} - - -int invoke_i3_fds(i3_fds *fds, - fd_set *readfds, fd_set *writefds, fd_set *exceptfds) -{ - int fd_cnt; - - fd_cnt = invoke_fd_callbacks(fds->readfd_list, readfds); - fd_cnt += invoke_fd_callbacks(fds->writefd_list, writefds); - fd_cnt += invoke_fd_callbacks(fds->exceptfd_list, exceptfds); - - return fd_cnt; -} - -void set_i3_fds(i3_fds *fds, - fd_set *readfds, fd_set *writefds, fd_set *exceptfds) -{ - fd_set_list(fds->readfd_list, readfds); - fd_set_list(fds->writefd_list, writefds); - fd_set_list(fds->exceptfd_list, exceptfds); -} - -void compute_max_i3_fds(i3_fds *fds) -{ - fds->max_fd = max_fd_list(fds->readfd_list); - fds->max_fd = MAX(fds->max_fd, max_fd_list(fds->writefd_list)); - fds->max_fd = MAX(fds->max_fd, max_fd_list(fds->exceptfd_list)); -} - + free_fd_list(fds->readfd_list); + free_fd_list(fds->writefd_list); + free_fd_list(fds->exceptfd_list); + free(fds); +} + +int invoke_i3_fds(i3_fds *fds, + fd_set *readfds, fd_set *writefds, fd_set *exceptfds) +{ + int fd_cnt; + + fd_cnt = invoke_fd_callbacks(fds->readfd_list, readfds); + fd_cnt += invoke_fd_callbacks(fds->writefd_list, writefds); + fd_cnt += invoke_fd_callbacks(fds->exceptfd_list, exceptfds); + + return fd_cnt; +} + +void set_i3_fds(i3_fds *fds, + fd_set *readfds, fd_set *writefds, fd_set *exceptfds) +{ + fd_set_list(fds->readfd_list, readfds); + fd_set_list(fds->writefd_list, writefds); + fd_set_list(fds->exceptfd_list, exceptfds); +} + +void compute_max_i3_fds(i3_fds *fds) +{ + fds->max_fd = max_fd_list(fds->readfd_list); + fds->max_fd = MAX(fds->max_fd, max_fd_list(fds->writefd_list)); + fds->max_fd = MAX(fds->max_fd, max_fd_list(fds->exceptfd_list)); +} fd_node *alloc_fd_node(int fd, void (*fun)(int, void *), void *params) { - fd_node *n; + fd_node *n; - if ((n = (fd_node *)calloc(1, sizeof(fd_node))) != NULL) { - n->fd = fd; - n->params = params; - n->fun = fun; - return n; - } - panic("alloc_fd_node: memory allocation error.\n"); - return NULL; + if ((n = (fd_node *) calloc(1, sizeof(fd_node))) != NULL) { + n->fd = fd; + n->params = params; + n->fun = fun; + return n; + } + panic("alloc_fd_node: memory allocation error.\n"); + return NULL; } - void insert_fd_node_in_list(fd_node **list, fd_node *n) { - if (!n) - /* not really needed, because alloc_fd_node panics in this case; - * just to make the compiler happy! - */ - *list = NULL; - - /* insert at the head of the list */ - n->next = *list; - *list = n; + if (!n) { + /* not really needed, because alloc_fd_node panics in this case; + * just to make the compiler happy! + */ + *list = NULL; + } + + /* insert at the head of the list */ + n->next = *list; + *list = n; } - fd_node *get_fd_node(fd_node *n, int fd) { - if (!n) + if (!n) { + return NULL; + } + + for (; n; n = n->next) { + if (n->fd == fd) { + return n; + } + } + return NULL; - - for (; n; n = n->next) - if (n->fd == fd) - return n; - - return NULL; } - void remove_fd_node_from_list(fd_node **list, fd_node *n) { - fd_node *n1; - - if (!(*list)) - return; - - if (*list == n) { - *list = (*list)->next; - free(n); - return; - } - - for (n1 = *list; n1->next; n1 = n1->next) { - if (n1->next == n) { - n1->next = n1->next->next; - free(n); - break; - } - } + fd_node *n1; + + if (!(*list)) { + return; + } + + if (*list == n) { + *list = (*list)->next; + free(n); + return; + } + + for (n1 = *list; n1->next; n1 = n1->next) { + if (n1->next == n) { + n1->next = n1->next->next; + free(n); + break; + } + } } - void free_fd_list(fd_node *list) { - fd_node *n; + fd_node *n; - while (list) { - n = list; - list = list->next; - free(n); - } + while (list) { + n = list; + list = list->next; + free(n); + } } void fd_set_list(fd_node *n, fd_set *fds) { - for (; n; n = n->next) - FD_SET(n->fd, fds); + for (; n; n = n->next) { + FD_SET(n->fd, fds); + } } - int max_fd_list(fd_node *n) { - int max = 0; - - for (; n; n = n->next) - if (max < n->fd) - max = n->fd; - - return max; + int max = 0; + + for (; n; n = n->next) { + if (max < n->fd) { + max = n->fd; + } + } + + return max; } void set_fd_list(fd_node *n, fd_set *fds) { - for (; n; n = n->next) - FD_SET(n->fd, fds); + for (; n; n = n->next) { + FD_SET(n->fd, fds); + } } int invoke_fd_callbacks(fd_node *n, fd_set *fds) { - int fd_cnt = 0; + int fd_cnt = 0; - for (; n; n = n->next) - if (FD_ISSET(n->fd, fds)) { - if (n->fun) { - fd_cnt++; - n->fun(n->fd, n->params); - } + for (; n; n = n->next) { + if (FD_ISSET(n->fd, fds)) { + if (n->fun) { + fd_cnt++; + n->fun(n->fd, n->params); + } + } } - - return fd_cnt; + + return fd_cnt; } void print_fd_list(fd_node *n) { - for (; n; n = n->next) - printf("%d, ", n->fd); - printf("\n"); + for (; n; n = n->next) { + printf("%d, ", n->fd); + } + printf("\n"); } - - - - === modified file 'i3/i3_client/i3_client_fd.h' --- i3/i3_client/i3_client_fd.h 2010-01-06 22:17:32 +0000 +++ i3/i3_client/i3_client_fd.h 2010-02-11 11:49:47 +0000 @@ -1,40 +1,40 @@ /*************************************************************************** - i3_client_fd.h - description - ------------------- - begin : Aug 14 2003 - email : istoica@xxxxxxxxxxxxxxx - ***************************************************************************/ +* i3_client_fd.h - description +* ------------------- +* begin : Aug 14 2003 +* email : istoica@xxxxxxxxxxxxxxx +***************************************************************************/ #ifndef I3_CLIENT_FD_H -#define I3_CLIENT_FD_H +#define I3_CLIENT_FD_H #include <sys/types.h> typedef struct fd_ { - void (*fun)(int, void*); - void *params; - int fd; - struct fd_ *next; + void (*fun)(int, void *); + void * params; + int fd; + struct fd_ *next; } fd_node; typedef struct i3_fds_ { - int max_fd; - fd_node *readfd_list; - fd_node *writefd_list; - fd_node *exceptfd_list; + int max_fd; + fd_node *readfd_list; + fd_node *writefd_list; + fd_node *exceptfd_list; } i3_fds; - + /* functions implemented in i3_client_fd.c */ i3_fds *alloc_i3_fds(void); void free_i3_fds(i3_fds *fds); -int invoke_i3_fds(i3_fds *fds, - fd_set *readfds, fd_set *writefds, fd_set *exceptfds); -void set_i3_fds(i3_fds *fds, - fd_set *readfds, fd_set *writefds, fd_set *exceptfds); +int invoke_i3_fds(i3_fds *fds, + fd_set *readfds, fd_set *writefds, fd_set *exceptfds); +void set_i3_fds(i3_fds *fds, + fd_set *readfds, fd_set *writefds, fd_set *exceptfds); void compute_max_i3_fds(i3_fds *fds); -fd_node *alloc_fd_node(int fd, void (*fun)(int, void*), void *params); +fd_node *alloc_fd_node(int fd, void (*fun)(int, void *), void *params); void insert_fd_node_in_list(fd_node **list, fd_node *n); fd_node *get_fd_node(fd_node *n, int fd); void remove_fd_node_from_list(fd_node **list, fd_node *n); === modified file 'i3/i3_client/i3_client_fun.h' --- i3/i3_client/i3_client_fun.h 2009-12-11 22:49:11 +0000 +++ i3/i3_client/i3_client_fun.h 2010-02-11 11:49:47 +0000 @@ -1,10 +1,10 @@ /*************************************************************************** - i3_client_fun.h - description - ------------------- - begin : Aug 14 2003 - copyright : (C) 2003 by Ion Stoica - email : istoica@xxxxxxxxxxxxxxx - ***************************************************************************/ +* i3_client_fun.h - description +* ------------------- +* begin : Aug 14 2003 +* copyright : (C) 2003 by Ion Stoica +* email : istoica@xxxxxxxxxxxxxxx +***************************************************************************/ #ifndef I3_CLIENT_FUN_H #define I3_CLIENT_FUN_H === modified file 'i3/i3_client/i3_client_id.c' --- i3/i3_client/i3_client_id.c 2010-01-12 12:35:31 +0000 +++ i3/i3_client/i3_client_id.c 2010-02-11 11:49:47 +0000 @@ -1,9 +1,9 @@ /*************************************************************************** - i3_client_id.c - description - ------------------- - begin : Aug 14 2003 - email : istoica@xxxxxxxxxxxxxxx - ***************************************************************************/ +* i3_client_id.c - description +* ------------------- +* begin : Aug 14 2003 +* email : istoica@xxxxxxxxxxxxxxx +***************************************************************************/ #include "../i3/i3.h" #include "../i3/i3_fun.h" @@ -14,362 +14,362 @@ cl_id *cl_alloc_id() { - cl_id *cid; - - if ((cid = (cl_id *)calloc(1, sizeof(cl_id))) != NULL) - return cid; - - I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, "cl_alloc_id: memory allocation error.\n"); - return NULL; + cl_id *cid; + + if ((cid = (cl_id *) calloc(1, sizeof(cl_id))) != NULL) { + return cid; + } + + I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, "cl_alloc_id: memory allocation error.\n"); + return NULL; } void cl_free_id(cl_id *cid) { - free(cid); + free(cid); } - void cl_free_id_list(cl_id *cid_head) { - cl_id *cid; - - assert(cid_head); - - while (cid_head) { - cid = cid_head->next; - cl_free_id(cid_head); - cid_head = cid; - } + cl_id *cid; + + assert(cid_head); + + while (cid_head) { + cid = cid_head->next; + cl_free_id(cid_head); + cid_head = cid; + } } - /* return a node whose id is on the same i3 server */ cl_id *cl_get_id_from_list(cl_id *head, ID *id) { - cl_id *cid; + cl_id *cid; - for (cid = head; cid; cid = cid->next) - if (!memcmp((char *)&cid->id, (char *)id, (MIN_PREFIX_LEN >> 3))) - return cid; - return NULL; + for (cid = head; cid; cid = cid->next) { + if (!memcmp((char *) &cid->id, (char *) id, (MIN_PREFIX_LEN >> 3))) { + return cid; + } + } + return NULL; } - -/* remove a given identifier node from list; don't destroy it */ +/* remove a given identifier node from list; don't destroy it */ void cl_remove_id_from_list(cl_id **phead, cl_id *cid) { - - assert(cid); - - if (*phead == cid) { - *phead = (*phead)->next; - if (*phead) - (*phead)->prev = NULL; - } else { - cid->prev->next = cid->next; - if (cid->next) - cid->next->prev = cid->prev; - } + assert(cid); + + if (*phead == cid) { + *phead = (*phead)->next; + if (*phead) { + (*phead)->prev = NULL; + } + } else { + cid->prev->next = cid->next; + if (cid->next) { + cid->next->prev = cid->prev; + } + } } /* add identifier at the head of the list */ void cl_add_id_to_list(cl_id **phead, cl_id *cid) { - assert(cid); + assert(cid); - cid->next = *phead; - if (*phead) - (*phead)->prev = cid; - cid->prev = NULL; - *phead = cid; + cid->next = *phead; + if (*phead) { + (*phead)->prev = cid; + } + cid->prev = NULL; + *phead = cid; } cl_id *cl_get_valid_id(cl_context *ctx, ID *id, int *refresh) { - cl_id *cid; - int idx = CL_HASH_ID(id); - srv_address *srv; - struct in_addr ia; - - *refresh = TRUE; - if ((cid = cl_get_id_from_list(ctx->id_htable[idx], id)) == NULL) - return NULL; - if (cid->retries_cnt >= MAX_NUM_ID_RETRIES) { - cl_remove_id_from_list(&ctx->id_htable[idx], cid); - srv = set_i3_server_status(ctx->s_array, - htonl(cid->cache_addr.sin_addr.s_addr), - htons(cid->cache_addr.sin_port), ID_DOWN); - ia.s_addr = htonl(cid->cache_addr.sin_addr.s_addr); - if (NULL == srv) - return NULL; - cl_id_callback(ctx, CL_CBK_SERVER_DOWN, id, &srv->addr, &srv->port); - cl_free_id(cid); - return NULL; - } else { - if (ctx->now.tv_sec - cid->last_ack.tv_sec > - ID_REFRESH_PERIOD-ACK_TIMEOUT*(MAX_NUM_ID_RETRIES-cid->retries_cnt)) { - cid->retries_cnt++; - return cid; - } - } - *refresh = FALSE; - return cid; + cl_id *cid; + int idx = CL_HASH_ID(id); + srv_address *srv; + struct in_addr ia; + + *refresh = TRUE; + if ((cid = cl_get_id_from_list(ctx->id_htable[idx], id)) == NULL) { + return NULL; + } + if (cid->retries_cnt >= MAX_NUM_ID_RETRIES) { + cl_remove_id_from_list(&ctx->id_htable[idx], cid); + srv = set_i3_server_status(ctx->s_array, + htonl(cid->cache_addr.sin_addr.s_addr), + htons(cid->cache_addr.sin_port), ID_DOWN); + ia.s_addr = htonl(cid->cache_addr.sin_addr.s_addr); + if (NULL == srv) { + return NULL; + } + cl_id_callback(ctx, CL_CBK_SERVER_DOWN, id, &srv->addr, &srv->port); + cl_free_id(cid); + return NULL; + } else { + if (ctx->now.tv_sec - cid->last_ack.tv_sec > + ID_REFRESH_PERIOD - ACK_TIMEOUT * (MAX_NUM_ID_RETRIES - cid->retries_cnt)) { + cid->retries_cnt++; + return cid; + } + } + *refresh = FALSE; + return cid; } - /*********************************************************************** - * cl_create_id - associate an id with a cache address. This function - * is invoked upon receiving I3_OPT_CACHE_ADDR, - * I3_OPT_CACHE_SHORTCUT_ADDR or I3_OPT_CACHE_DEST_ADDR - * options - * input: - * ctx - context - * id - identifier - * ip_addr, port - IP address and port numbers contained in the - * trigger associated to the option. In the case of - * I3_OPT_CACHE_ADDR, (ip_addr, port) represents the - * i3 server responsible for id. Otherwise, (ip_addr, - * port) represents the sender. - * fromaddr - contains the IP *routable* address and the port number - * of the sender. If the sender is behind a NAT, fromaddr - * is different from (ip_addr, port) returned by the - * I3_OPT_CACHE_SHORTCUT_ADDR option. Otherwise the two - * are equal. - * return: identifier data structure - * - * Note: ip_addr and port number are in host format; fromaddr is in - * network format - ***********************************************************************/ +* cl_create_id - associate an id with a cache address. This function +* is invoked upon receiving I3_OPT_CACHE_ADDR, +* I3_OPT_CACHE_SHORTCUT_ADDR or I3_OPT_CACHE_DEST_ADDR +* options +* input: +* ctx - context +* id - identifier +* ip_addr, port - IP address and port numbers contained in the +* trigger associated to the option. In the case of +* I3_OPT_CACHE_ADDR, (ip_addr, port) represents the +* i3 server responsible for id. Otherwise, (ip_addr, +* port) represents the sender. +* fromaddr - contains the IP *routable* address and the port number +* of the sender. If the sender is behind a NAT, fromaddr +* is different from (ip_addr, port) returned by the +* I3_OPT_CACHE_SHORTCUT_ADDR option. Otherwise the two +* are equal. +* return: identifier data structure +* +* Note: ip_addr and port number are in host format; fromaddr is in +* network format +***********************************************************************/ cl_id *cl_create_id(cl_context *ctx, ID *id, int opt_type, - struct in_addr *ip_addr, uint16_t port, - struct sockaddr_in *fromaddr) -{ - cl_id *cid; - - if ((cid = cl_get_id_from_list(ctx->id_htable[CL_HASH_ID(id)], id)) != NULL) - return cid; - - cid = cl_alloc_id(); - memcpy((char *)&cid->id, id, ID_LEN); - memset(&cid->cache_addr, 0, sizeof(struct sockaddr_in)); - cid->cache_addr.sin_family = AF_INET; - cid->dest_addr.sin_family = AF_INET; - cl_add_id_to_list(&ctx->id_htable[CL_HASH_ID(&cid->id)], cid); - - switch (opt_type) { - case I3_OPT_CACHE_ADDR: - case I3_OPT_FORCE_CACHE_ADDR: - cid->cache_addr.sin_addr.s_addr = ntohl(ip_addr->s_addr); - cid->cache_addr.sin_port = ntohs(port); - cid->retries_cnt = 0; - cid->last_ack = ctx->now; - set_i3_server_status(ctx->s_array, ip_addr->s_addr, port, ID_UP); - break; - case I3_OPT_CACHE_SHORTCUT_ADDR: - assert(fromaddr); - /* no need to convert since fromaddr is already in network format */ - cid->cache_addr.sin_addr.s_addr = fromaddr->sin_addr.s_addr; - cid->cache_addr.sin_port = fromaddr->sin_port; - cid->retries_cnt = 0; - cid->last_ack = ctx->now; - set_i3_server_status(ctx->s_array, htonl(fromaddr->sin_addr.s_addr), - htons(fromaddr->sin_port), ID_UP); - break; - case I3_OPT_CACHE_DEST_ADDR: - cid->dest_addr.sin_addr.s_addr = ntohl(ip_addr->s_addr); - cid->dest_addr.sin_port = ntohs(port); - set_i3_server_status(ctx->s_array, - ip_addr->s_addr, port, ID_UP); - break; - default: - I3_PRINT_DEBUG1(I3_DEBUG_LEVEL_MINIMAL, "cl_create_id: unknown option %d\n", opt_type); - } - return cid; -} - -/* see cl_create_id */ -cl_id *cl_update_id(cl_context *ctx, ID *id, int opt_type, - struct in_addr *ip_addr, uint16_t port, - struct sockaddr_in *fromaddr) -{ - cl_id *cid; - - - if ((cid = cl_get_id_from_list(ctx->id_htable[CL_HASH_ID(id)], id)) != NULL){ + struct in_addr *ip_addr, uint16_t port, + struct sockaddr_in *fromaddr) +{ + cl_id *cid; + + if ((cid = cl_get_id_from_list(ctx->id_htable[CL_HASH_ID(id)], id)) != NULL) { + return cid; + } + + cid = cl_alloc_id(); + memcpy((char *) &cid->id, id, ID_LEN); + memset(&cid->cache_addr, 0, sizeof(struct sockaddr_in)); + cid->cache_addr.sin_family = AF_INET; + cid->dest_addr.sin_family = AF_INET; + cl_add_id_to_list(&ctx->id_htable[CL_HASH_ID(&cid->id)], cid); + switch (opt_type) { case I3_OPT_CACHE_ADDR: case I3_OPT_FORCE_CACHE_ADDR: - assert(ip_addr->s_addr); - cid->cache_addr.sin_addr.s_addr = ntohl(ip_addr->s_addr); - cid->cache_addr.sin_port = ntohs(port); - set_i3_server_status(ctx->s_array, ip_addr->s_addr, port, ID_UP); - cid->retries_cnt = 0; - cid->last_ack = ctx->now; - break; + cid->cache_addr.sin_addr.s_addr = ntohl(ip_addr->s_addr); + cid->cache_addr.sin_port = ntohs(port); + cid->retries_cnt = 0; + cid->last_ack = ctx->now; + set_i3_server_status(ctx->s_array, ip_addr->s_addr, port, ID_UP); + break; case I3_OPT_CACHE_SHORTCUT_ADDR: - assert(fromaddr); - /* fromaddr already in network format; no need to convert */ - cid->cache_addr.sin_addr.s_addr = fromaddr->sin_addr.s_addr; - cid->cache_addr.sin_port = fromaddr->sin_port; - set_i3_server_status(ctx->s_array, htonl(fromaddr->sin_addr.s_addr), - htons(fromaddr->sin_port), ID_UP); - cid->retries_cnt = 0; - cid->last_ack = ctx->now; - break; + assert(fromaddr); + /* no need to convert since fromaddr is already in network format */ + cid->cache_addr.sin_addr.s_addr = fromaddr->sin_addr.s_addr; + cid->cache_addr.sin_port = fromaddr->sin_port; + cid->retries_cnt = 0; + cid->last_ack = ctx->now; + set_i3_server_status(ctx->s_array, htonl(fromaddr->sin_addr.s_addr), + htons(fromaddr->sin_port), ID_UP); + break; case I3_OPT_CACHE_DEST_ADDR: - cid->dest_addr.sin_addr.s_addr = ntohl(ip_addr->s_addr); - cid->dest_addr.sin_port = ntohs(port); - set_i3_server_status(ctx->s_array, - ip_addr->s_addr, port, ID_UP); - break; + cid->dest_addr.sin_addr.s_addr = ntohl(ip_addr->s_addr); + cid->dest_addr.sin_port = ntohs(port); + set_i3_server_status(ctx->s_array, + ip_addr->s_addr, port, ID_UP); + break; default: - I3_PRINT_DEBUG1(I3_DEBUG_LEVEL_MINIMAL, "cl_update_id: unknown option %d\n", opt_type); + I3_PRINT_DEBUG1(I3_DEBUG_LEVEL_MINIMAL, "cl_create_id: unknown option %d\n", opt_type); } return cid; - } else - return NULL; -} - +} + +/* see cl_create_id */ +cl_id *cl_update_id(cl_context *ctx, ID *id, int opt_type, + struct in_addr *ip_addr, uint16_t port, + struct sockaddr_in *fromaddr) +{ + cl_id *cid; + + + if ((cid = cl_get_id_from_list(ctx->id_htable[CL_HASH_ID(id)], id)) != NULL) { + switch (opt_type) { + case I3_OPT_CACHE_ADDR: + case I3_OPT_FORCE_CACHE_ADDR: + assert(ip_addr->s_addr); + cid->cache_addr.sin_addr.s_addr = ntohl(ip_addr->s_addr); + cid->cache_addr.sin_port = ntohs(port); + set_i3_server_status(ctx->s_array, ip_addr->s_addr, port, ID_UP); + cid->retries_cnt = 0; + cid->last_ack = ctx->now; + break; + case I3_OPT_CACHE_SHORTCUT_ADDR: + assert(fromaddr); + /* fromaddr already in network format; no need to convert */ + cid->cache_addr.sin_addr.s_addr = fromaddr->sin_addr.s_addr; + cid->cache_addr.sin_port = fromaddr->sin_port; + set_i3_server_status(ctx->s_array, htonl(fromaddr->sin_addr.s_addr), + htons(fromaddr->sin_port), ID_UP); + cid->retries_cnt = 0; + cid->last_ack = ctx->now; + break; + case I3_OPT_CACHE_DEST_ADDR: + cid->dest_addr.sin_addr.s_addr = ntohl(ip_addr->s_addr); + cid->dest_addr.sin_port = ntohs(port); + set_i3_server_status(ctx->s_array, + ip_addr->s_addr, port, ID_UP); + break; + default: + I3_PRINT_DEBUG1(I3_DEBUG_LEVEL_MINIMAL, "cl_update_id: unknown option %d\n", opt_type); + } + return cid; + } else { + return NULL; + } +} /** This function forces the specified id to be public - * It sets/unsets the appropriate bit in the id. - * Note that id changes; please remember this when you try to use - * the 'same' id for sending packets. - */ + * It sets/unsets the appropriate bit in the id. + * Note that id changes; please remember this when you try to use + * the 'same' id for sending packets. + */ void cl_set_public_id(ID *id) { set_id_type(id, I3_ID_TYPE_PUBLIC); } /** This function forces the specified id to be private. - * It sets/unsets the appropriate bit in the id. - * Note that id changes; please remember this when you try to use - * the 'same' id for sending packets. - */ + * It sets/unsets the appropriate bit in the id. + * Note that id changes; please remember this when you try to use + * the 'same' id for sending packets. + */ void cl_set_private_id(ID *id) { set_id_type(id, I3_ID_TYPE_PRIVATE); } /*************************************************************************** - * update_id_key - update a trigger ID according using key according to the - * specified constraint - * - * input: - * id - trigger ID - * key - * flags - flags associated to creating a trigger; possible values: - * CL_TRIGGER_CFLAG_R_CONSTRAINT - right constraint; id.key = h_l(key) - * CL_TRIGGER_CFLAG_L_CONSTRAINT - left constraint; id.key = h_r(key) - * CL_TRIGGER_CFLAG_PUBLIC - public ID; otherwise the ID - * is private. If the trigger is public - * then it has to be left constraint, - * i.e., CL_TRIGGER_CFLAG_R_CONSTRAINT - * and CL_TRIGGER_CFLAG_PUBLIC cannot be - * - * return value: - * error code; possible values - * CL_RET_INVALID_FLAGS - * CL_RET_OK - ***************************************************************************/ +* update_id_key - update a trigger ID according using key according to the +* specified constraint +* +* input: +* id - trigger ID +* key +* flags - flags associated to creating a trigger; possible values: +* CL_TRIGGER_CFLAG_R_CONSTRAINT - right constraint; id.key = h_l(key) +* CL_TRIGGER_CFLAG_L_CONSTRAINT - left constraint; id.key = h_r(key) +* CL_TRIGGER_CFLAG_PUBLIC - public ID; otherwise the ID +* is private. If the trigger is public +* then it has to be left constraint, +* i.e., CL_TRIGGER_CFLAG_R_CONSTRAINT +* and CL_TRIGGER_CFLAG_PUBLIC cannot be +* +* return value: +* error code; possible values +* CL_RET_INVALID_FLAGS +* CL_RET_OK +***************************************************************************/ int update_id_key(ID *id, Key *key, uint16_t flags) { Key k; - if ((flags & CL_TRIGGER_CFLAG_PUBLIC) && + if ((flags & CL_TRIGGER_CFLAG_PUBLIC) && (flags & CL_TRIGGER_CFLAG_R_CONSTRAINT)) { - return CL_RET_INVALID_FLAGS; } if ((flags & CL_TRIGGER_CFLAG_R_CONSTRAINT) && (flags & CL_TRIGGER_CFLAG_L_CONSTRAINT)) { - - return CL_RET_INVALID_FLAGS; + return CL_RET_INVALID_FLAGS; } - - + + if (flags & CL_TRIGGER_CFLAG_PUBLIC) { cl_set_public_id(id); - } else if (flags) { // & CL_TRIGGER_CFLAG_PRIVATE) { cl_set_private_id(id); - - /* - } else if (flags & CL_TRIGGER_CFLAG_UNCONSTRAINED) { - set_id_type (id, I3_ID_TYPE_UNCONSTRAINED); - */ - + /* + * } else if (flags & CL_TRIGGER_CFLAG_UNCONSTRAINED) { + * set_id_type (id, I3_ID_TYPE_UNCONSTRAINED); + * + */ } - + if (flags & CL_TRIGGER_CFLAG_R_CONSTRAINT) { generate_constraint_id(id, key, R_CONSTRAINT); } - + if (flags & CL_TRIGGER_CFLAG_L_CONSTRAINT) { memcpy(&k.x, KEY_ID_PTR(id), KEY_LEN); generate_l_constraint_addr(key, &k); memcpy(KEY_ID_PTR(id), &k.x, KEY_LEN); - } - return CL_RET_OK; + } + return CL_RET_OK; } - /*************************************************************************** - * update_id_id - constrain the trigger ID and the target ID - * - * input: - * id - trigger ID - * id_target - target ID - * flags - flags associated to creating a trigger; possible values: - * CL_TRIGGER_CFLAG_R_CONSTRAINT - right constraint; - * id.key = h_l(id_target) - * CL_TRIGGER_CFLAG_L_CONSTRAINT - left constraint; - * id_target.key = h_r(id) - * CL_TRIGGER_CFLAG_PUBLIC - public ID; otherwise the ID - * is private. If the trigger is public - * then it has to be left constraint, - * i.e., CL_TRIGGER_CFLAG_R_CONSTRAINT - * and CL_TRIGGER_CFLAG_PUBLIC cannot be - * - * return value: - * error code; possible values - * CL_RET_INVALID_FLAGS - * CL_RET_OK - ***************************************************************************/ +* update_id_id - constrain the trigger ID and the target ID +* +* input: +* id - trigger ID +* id_target - target ID +* flags - flags associated to creating a trigger; possible values: +* CL_TRIGGER_CFLAG_R_CONSTRAINT - right constraint; +* id.key = h_l(id_target) +* CL_TRIGGER_CFLAG_L_CONSTRAINT - left constraint; +* id_target.key = h_r(id) +* CL_TRIGGER_CFLAG_PUBLIC - public ID; otherwise the ID +* is private. If the trigger is public +* then it has to be left constraint, +* i.e., CL_TRIGGER_CFLAG_R_CONSTRAINT +* and CL_TRIGGER_CFLAG_PUBLIC cannot be +* +* return value: +* error code; possible values +* CL_RET_INVALID_FLAGS +* CL_RET_OK +***************************************************************************/ int update_id_id(ID *id, ID *id_target, uint16_t flags) { - Key k; - //char tmpBuf[10000]; - - //printf("\n\n\n------------------->update_id_id: original id = %s, flags=%d\n", sprintf_i3_id (tmpBuf,id), flags); - //printf("\n\n\n------------------->update_id_id: constrained id = %s\n", sprintf_i3_id (tmpBuf,id_target)); - if ((flags & CL_TRIGGER_CFLAG_PUBLIC) && - (flags & CL_TRIGGER_CFLAG_R_CONSTRAINT)) - return CL_RET_INVALID_FLAGS; - - if ((flags & CL_TRIGGER_CFLAG_R_CONSTRAINT) && - (flags & CL_TRIGGER_CFLAG_L_CONSTRAINT)) - return CL_RET_INVALID_FLAGS; - - if (flags & CL_TRIGGER_CFLAG_PUBLIC) - cl_set_public_id(id); - else - cl_set_private_id(id); - - if (flags & CL_TRIGGER_CFLAG_R_CONSTRAINT) { - generate_constraint_id(id, &k, R_CONSTRAINT); - memcpy(KEY_ID_PTR(id_target), &k.x, KEY_LEN); - } - - //printf("------------------->update_id_id: constrained id = %s\n\n\n\n", sprintf_i3_id (tmpBuf,id_target)); - if (flags & CL_TRIGGER_CFLAG_L_CONSTRAINT) { - generate_constraint_id(id_target, &k, L_CONSTRAINT); - memcpy(KEY_ID_PTR(id), &k.x, KEY_LEN); - } - return CL_RET_OK; + Key k; + //char tmpBuf[10000]; + + //printf("\n\n\n------------------->update_id_id: original id = %s, flags=%d\n", sprintf_i3_id (tmpBuf,id), flags); + //printf("\n\n\n------------------->update_id_id: constrained id = %s\n", sprintf_i3_id (tmpBuf,id_target)); + if ((flags & CL_TRIGGER_CFLAG_PUBLIC) && + (flags & CL_TRIGGER_CFLAG_R_CONSTRAINT)) { + return CL_RET_INVALID_FLAGS; + } + + if ((flags & CL_TRIGGER_CFLAG_R_CONSTRAINT) && + (flags & CL_TRIGGER_CFLAG_L_CONSTRAINT)) { + return CL_RET_INVALID_FLAGS; + } + + if (flags & CL_TRIGGER_CFLAG_PUBLIC) { + cl_set_public_id(id); + } else { + cl_set_private_id(id); + } + + if (flags & CL_TRIGGER_CFLAG_R_CONSTRAINT) { + generate_constraint_id(id, &k, R_CONSTRAINT); + memcpy(KEY_ID_PTR(id_target), &k.x, KEY_LEN); + } + + //printf("------------------->update_id_id: constrained id = %s\n\n\n\n", sprintf_i3_id (tmpBuf,id_target)); + if (flags & CL_TRIGGER_CFLAG_L_CONSTRAINT) { + generate_constraint_id(id_target, &k, L_CONSTRAINT); + memcpy(KEY_ID_PTR(id), &k.x, KEY_LEN); + } + return CL_RET_OK; } - - === modified file 'i3/i3_client/i3_client_id.h' --- i3/i3_client/i3_client_id.h 2010-01-06 22:17:32 +0000 +++ i3/i3_client/i3_client_id.h 2010-02-11 11:49:47 +0000 @@ -1,14 +1,14 @@ /*************************************************************************** - i3_client_id.h - description - ------------------- - begin : Aug 14 2003 - email : istoica@xxxxxxxxxxxxxxx - ***************************************************************************/ +* i3_client_id.h - description +* ------------------- +* begin : Aug 14 2003 +* email : istoica@xxxxxxxxxxxxxxx +***************************************************************************/ #ifndef I3_CLIENT_ID_H -#define I3_CLIENT_ID_H - - +#define I3_CLIENT_ID_H + + /* functions implemented in i3_client_id.c */ cl_id *cl_alloc_id(void); void cl_free_id(cl_id *cid); @@ -19,12 +19,12 @@ void cl_add_id_to_list(cl_id **phead, cl_id *cid); /* ip_addr and port number are in host format */ cl_id *cl_create_id(cl_context *ctx, ID *id, int opt_type, - struct in_addr *ip_addr, uint16_t port, - struct sockaddr_in *fromaddr); + struct in_addr *ip_addr, uint16_t port, + struct sockaddr_in *fromaddr); /* ip_addr and port number are in host format */ cl_id *cl_update_id(cl_context *ctx, ID *id, int opt_type, - struct in_addr *ip_addr, uint16_t port, - struct sockaddr_in *fromaddr); + struct in_addr *ip_addr, uint16_t port, + struct sockaddr_in *fromaddr); void cl_set_public_id(ID *id); void cl_set_private_id(ID *id); === modified file 'i3/i3_client/i3_client_params.h' --- i3/i3_client/i3_client_params.h 2009-12-11 22:49:11 +0000 +++ i3/i3_client/i3_client_params.h 2010-02-11 11:49:47 +0000 @@ -11,14 +11,14 @@ #define SERVER_UPDATE_PERIOD 30 /* in seconds */ /** How often should a trigger be refreshed? - * This value should always be a little less than - * the trigger refresh value at the i3 server. - */ -#define TRIGGER_REFRESH_PERIOD 20 -#define ACK_TIMEOUT 2 -#define ID_REFRESH_PERIOD 10 -#define MAX_NUM_TRIG_RETRIES 6 -#define MAX_NUM_ID_RETRIES 3 + * This value should always be a little less than + * the trigger refresh value at the i3 server. + */ +#define TRIGGER_REFRESH_PERIOD 20 +#define ACK_TIMEOUT 2 +#define ID_REFRESH_PERIOD 10 +#define MAX_NUM_TRIG_RETRIES 6 +#define MAX_NUM_ID_RETRIES 3 #endif === modified file 'i3/i3_client/i3_client_pkt.c' --- i3/i3_client/i3_client_pkt.c 2009-12-29 21:08:52 +0000 +++ i3/i3_client/i3_client_pkt.c 2010-02-11 11:49:47 +0000 @@ -1,9 +1,9 @@ /*************************************************************************** - i3_client_pkt.h - description - ------------------- - begin : Aug 14 2003 - email : istoica@xxxxxxxxxxxxxxx - ***************************************************************************/ +* i3_client_pkt.h - description +* ------------------- +* begin : Aug 14 2003 +* email : istoica@xxxxxxxxxxxxxxx +***************************************************************************/ #include <stdio.h> #include <stdarg.h> @@ -12,7 +12,7 @@ #include <time.h> /* timespec{} for pselect() */ #ifndef _WIN32 #include <sys/time.h> /* timeval{} for select() */ - #include <sys/errno.h> + #include <sys/errno.h> #endif #include "../utils/netwrap.h" @@ -25,455 +25,448 @@ #include "../i3/i3_tcp_fns.h" -void fast_pack_i3_header(char *p, char data, - i3_stack *s, char *packed_ol, - unsigned short packed_ol_len); +void fast_pack_i3_header(char *p, char data, + i3_stack *s, char *packed_ol, + unsigned short packed_ol_len); void make_opt_cache_address_pkt(cl_context *ctx, ID *id, int prefix_len, - char *buf, unsigned short *buf_len); - -cl_buf *cl_alloc_buf(unsigned int len) { - - cl_buf *clb; - int tmp_internal_buf_len = 0; - - if ((clb = (cl_buf *)malloc(sizeof(cl_buf))) == NULL) { - I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, "cl_alloc_buf(1): memory allocation error\n"); - } else { - memset (clb, 0, sizeof (cl_buf)); - } - - tmp_internal_buf_len = len + 2 * CL_PREFIX_LEN; - if ((clb->internal_buf = (char *)malloc(tmp_internal_buf_len)) == NULL) { - I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, "cl_alloc_buf(2): memory allocation error\n"); - } else { - memset (clb->internal_buf, 0, tmp_internal_buf_len); - } - - clb->data = clb->internal_buf + CL_PREFIX_LEN; - clb->max_len = len; - - return clb; + char *buf, unsigned short *buf_len); + +cl_buf *cl_alloc_buf(unsigned int len) +{ + cl_buf *clb; + int tmp_internal_buf_len = 0; + + if ((clb = (cl_buf *) malloc(sizeof(cl_buf))) == NULL) { + I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, "cl_alloc_buf(1): memory allocation error\n"); + } else { + memset(clb, 0, sizeof(cl_buf)); + } + + tmp_internal_buf_len = len + 2 * CL_PREFIX_LEN; + if ((clb->internal_buf = (char *) malloc(tmp_internal_buf_len)) == NULL) { + I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, "cl_alloc_buf(2): memory allocation error\n"); + } else { + memset(clb->internal_buf, 0, tmp_internal_buf_len); + } + + clb->data = clb->internal_buf + CL_PREFIX_LEN; + clb->max_len = len; + + return clb; } - void cl_free_buf(cl_buf *clb) { - if (clb) { - if (clb->internal_buf) - free(clb->internal_buf); - free(clb); - } + if (clb) { + if (clb->internal_buf) { + free(clb->internal_buf); + } + free(clb); + } } - - int cl_send_data_packet(cl_context *ctx, i3_stack *stack, - cl_buf *clb, uint16_t flags, char is_total_len) + cl_buf *clb, uint16_t flags, char is_total_len) { - unsigned short len; - cl_id *cid; - int refresh, total_len = 0, err = 0; - uint8_t opts_mask = 0; - - /* is stack->ids[0] cached ? */ - cid = cl_get_valid_id(ctx, &stack->ids[0], &refresh); - - /* form the complete mask using refresh also */ - if (flags & CL_PKT_FLAG_ALLOW_SHORTCUT) - opts_mask |= (refresh != 0) ? REFRESH_SHORTCUT_MASK : 0; - else - opts_mask |= (refresh != 0) ? REFRESH_MASK : 0; - - assert(opts_mask < MAX_OPTS_MASK_SIZE); - - /* use appropriate precomputed option */ - len = 2 * sizeof(char) + get_i3_stack_len(stack) + - ctx->precomputed_opt[opts_mask].len; - assert(len <= CL_PREFIX_LEN); - - /* check whether header and payload exceed maximum packet size of - transport protocol */ - total_len = clb->data_len; - if (!is_total_len) { - total_len += len; - } - if (total_len > ((1 << 16) - 8)) { - return CL_RET_MSG_SIZE; - } - - fast_pack_i3_header(clb->data - len, TRUE, stack, - ctx->precomputed_opt[opts_mask].p, - ctx->precomputed_opt[opts_mask].len); - /* set first flag */ - set_first_hop(clb->data - len); - - if (!is_total_len) { - err = cl_sendto(ctx, clb->data - len, clb->data_len + len, - cid, &stack->ids[0]); - } else { - err = cl_sendto(ctx, clb->data - len, clb->data_len, cid, &stack->ids[0]); - } - - return err; + unsigned short len; + cl_id *cid; + int refresh, total_len = 0, err = 0; + uint8_t opts_mask = 0; + + /* is stack->ids[0] cached ? */ + cid = cl_get_valid_id(ctx, &stack->ids[0], &refresh); + + /* form the complete mask using refresh also */ + if (flags & CL_PKT_FLAG_ALLOW_SHORTCUT) { + opts_mask |= (refresh != 0) ? REFRESH_SHORTCUT_MASK : 0; + } else { + opts_mask |= (refresh != 0) ? REFRESH_MASK : 0; + } + + assert(opts_mask < MAX_OPTS_MASK_SIZE); + + /* use appropriate precomputed option */ + len = 2 * sizeof(char) + get_i3_stack_len(stack) + + ctx->precomputed_opt[opts_mask].len; + assert(len <= CL_PREFIX_LEN); + + /* check whether header and payload exceed maximum packet size of + * transport protocol */ + total_len = clb->data_len; + if (!is_total_len) { + total_len += len; + } + if (total_len > ((1 << 16) - 8)) { + return CL_RET_MSG_SIZE; + } + + fast_pack_i3_header(clb->data - len, TRUE, stack, + ctx->precomputed_opt[opts_mask].p, + ctx->precomputed_opt[opts_mask].len); + /* set first flag */ + set_first_hop(clb->data - len); + + if (!is_total_len) { + err = cl_sendto(ctx, clb->data - len, clb->data_len + len, + cid, &stack->ids[0]); + } else { + err = cl_sendto(ctx, clb->data - len, clb->data_len, cid, &stack->ids[0]); + } + + return err; } - int cl_send_packet(cl_context *ctx, i3_header *hdr, - cl_buf *clb, uint8_t opts_mask) + cl_buf *clb, uint8_t opts_mask) // TODO XXX -- opts mask is unimplemented in this case { - char *pkt; - unsigned short len; - cl_id *cid; - int refresh, err = 0; - - /* is there a cache entry for the first identifier in the stack ? */ - cid = cl_get_valid_id(ctx, &hdr->stack->ids[0], &refresh); - if (refresh) { - /* cache entry doesn't exist or needs to be refreshed */ - i3_option *o; - o = alloc_i3_option(); - init_i3_option(o, I3_OPT_REQUEST_FOR_CACHE, NULL); - append_i3_option(hdr->option_list, o); - } - - /* get header length */ - len = get_i3_header_len(hdr); - - /* check whether we have enough room to prepend header */ - assert (len <= clb->data - clb->internal_buf); - pkt = clb->data - len; - /* copy header in front of payload */ - pack_i3_header(pkt, hdr, &len); - set_first_hop(pkt); - err = cl_sendto(ctx, pkt, len + clb->data_len, cid, &hdr->stack->ids[0]); - - free_i3_header(hdr); - - return err; + char *pkt; + unsigned short len; + cl_id *cid; + int refresh, err = 0; + + /* is there a cache entry for the first identifier in the stack ? */ + cid = cl_get_valid_id(ctx, &hdr->stack->ids[0], &refresh); + if (refresh) { + /* cache entry doesn't exist or needs to be refreshed */ + i3_option *o; + o = alloc_i3_option(); + init_i3_option(o, I3_OPT_REQUEST_FOR_CACHE, NULL); + append_i3_option(hdr->option_list, o); + } + + /* get header length */ + len = get_i3_header_len(hdr); + + /* check whether we have enough room to prepend header */ + assert(len <= clb->data - clb->internal_buf); + pkt = clb->data - len; + /* copy header in front of payload */ + pack_i3_header(pkt, hdr, &len); + set_first_hop(pkt); + err = cl_sendto(ctx, pkt, len + clb->data_len, cid, &hdr->stack->ids[0]); + + free_i3_header(hdr); + + return err; } - - /* return the header and the payload of an i3 packet; * hdr is allocated and needs to be freed in the calling function * pkt ix expected to be allocated by the calling function */ int cl_receive_packet_from(cl_context *ctx, i3_header **phdr, cl_buf *clb, - struct sockaddr_in *fromaddr) + struct sockaddr_in *fromaddr) { - int n; - int len, errcode; - unsigned short hdr_len; - - *phdr = NULL; - len = sizeof(struct sockaddr_in); - /* leave enough room to allow caller to invoke a cl_send operation - * using the same buffer - */ - clb->data = clb->internal_buf + CL_PREFIX_LEN; - /* recall that total length of the allocated buffer in the clb structure is - * clb->max_len + CL_PREFIX_LEN */ - if (ctx->is_tcp && ctx->init_tcp_ctx_flag) { - if ((n = recv_tcp(clb->data, clb->max_len + CL_PREFIX_LEN, - ctx->tcp_fd)) < 0) { - I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, "tcp recvfrom error"); - perror ("recvfrom tcp"); - return 0; - } - if (n == 0) { - I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_VERBOSE, - "Connection closed by server, exiting...\n"); - exit(0); - } - } else - if ((n = recvfrom(ctx->fd, clb->data, clb->max_len + CL_PREFIX_LEN, 0, - (struct sockaddr *)fromaddr, (unsigned int*)&len)) < 0) { - - I3_PRINT_DEBUG1 (I3_DEBUG_LEVEL_WARNING, "Error while receiving packet: %s.\n", - strerror (errno) - ); - perror("recvfrom udp"); - return 0; - } - - - if (clb->data[0] == I3_v01) { - /* check whether the packet is wellformed */ - errcode = check_i3_header(clb->data, n); - if (errcode) { - I3_PRINT_DEBUG1(I3_DEBUG_LEVEL_SUPER, "invalid i3 header, errcode=%d", - errcode); - return 0; - } - *phdr = unpack_i3_header(clb->data, &hdr_len); - clb->data += hdr_len; /* this where the payload starts... */ - clb->data_len = n - hdr_len; /* ... and this is the payload length */ - } - - return 1; + int n; + int len, errcode; + unsigned short hdr_len; + + *phdr = NULL; + len = sizeof(struct sockaddr_in); + /* leave enough room to allow caller to invoke a cl_send operation + * using the same buffer + */ + clb->data = clb->internal_buf + CL_PREFIX_LEN; + /* recall that total length of the allocated buffer in the clb structure is + * clb->max_len + CL_PREFIX_LEN */ + if (ctx->is_tcp && ctx->init_tcp_ctx_flag) { + if ((n = recv_tcp(clb->data, clb->max_len + CL_PREFIX_LEN, + ctx->tcp_fd)) < 0) { + I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, "tcp recvfrom error"); + perror("recvfrom tcp"); + return 0; + } + if (n == 0) { + I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_VERBOSE, + "Connection closed by server, exiting...\n"); + exit(0); + } + } else if ((n = recvfrom(ctx->fd, clb->data, clb->max_len + CL_PREFIX_LEN, 0, + (struct sockaddr *) fromaddr, (unsigned int *) &len)) < 0) { + I3_PRINT_DEBUG1(I3_DEBUG_LEVEL_WARNING, "Error while receiving packet: %s.\n", + strerror(errno) + ); + perror("recvfrom udp"); + return 0; + } + + + if (clb->data[0] == I3_v01) { + /* check whether the packet is wellformed */ + errcode = check_i3_header(clb->data, n); + if (errcode) { + I3_PRINT_DEBUG1(I3_DEBUG_LEVEL_SUPER, "invalid i3 header, errcode=%d", + errcode); + return 0; + } + *phdr = unpack_i3_header(clb->data, &hdr_len); + clb->data += hdr_len; /* this where the payload starts... */ + clb->data_len = n - hdr_len; /* ... and this is the payload length */ + } + + return 1; } void cl_receive_packet(cl_context *ctx, i3_header **phdr, cl_buf *clb) { - struct sockaddr_in fromaddr; - cl_receive_packet_from(ctx, phdr, clb, &fromaddr); + struct sockaddr_in fromaddr; + cl_receive_packet_from(ctx, phdr, clb, &fromaddr); } - -int cl_sendto(cl_context *ctx, char *pkt, - uint16_t pkt_len, cl_id *cid, ID *id) +int cl_sendto(cl_context *ctx, char *pkt, + uint16_t pkt_len, cl_id *cid, ID *id) { - if (cid == NULL) { - int idx = get_i3_server(ctx->num_servers, ctx->s_array); - if (-1 == idx) { - fprintf(stderr, "cl_sendto: cannot get i3_servers\n"); - return CL_RET_NO_SERVERS; - } - - - cid = cl_create_id(ctx, id, I3_OPT_CACHE_ADDR, &ctx->s_array[idx].addr, - ctx->s_array[idx].port, NULL); - } - assert(cid); - - I3_PRINT_DEBUG2(I3_DEBUG_LEVEL_VERBOSE, - "in cl_sendto: using server %s:%u\n", - inet_ntoa(cid->cache_addr.sin_addr), - ntohs(cid->cache_addr.sin_port) - ); - - if (ctx->is_tcp) { - if (!ctx->init_tcp_ctx_flag) { - // TCP connection had not been earlier established. - // Try again - init_tcp_ctx(ctx); - - if (!ctx->init_tcp_ctx_flag) { - //failed again - I3_PRINT_DEBUG0 (I3_DEBUG_LEVEL_MINIMAL, - "send failed as tcp connection could not be established.\n" - ); - return CL_RET_NET_ERROR; - } - } - - if (ctx->is_tcp && ctx->init_tcp_ctx_flag) - if (send_tcp(pkt, pkt_len, ctx->tcp_fd) < 0) - return CL_RET_NET_ERROR; - - } else { - int numSent = 0; - if ((numSent = sendto(ctx->fd, pkt, pkt_len, 0, - (struct sockaddr *)&cid->cache_addr, - sizeof(cid->cache_addr))) < 0) { - perror("cl_sendto"); - if (errno == ENETUNREACH) { - if (cid->retries_cnt > 0) { - cid->retries_cnt--; - } - } else { - return CL_RET_NET_ERROR; - } - } - } - - return CL_RET_OK; + if (cid == NULL) { + int idx = get_i3_server(ctx->num_servers, ctx->s_array); + if (-1 == idx) { + fprintf(stderr, "cl_sendto: cannot get i3_servers\n"); + return CL_RET_NO_SERVERS; + } + + + cid = cl_create_id(ctx, id, I3_OPT_CACHE_ADDR, &ctx->s_array[idx].addr, + ctx->s_array[idx].port, NULL); + } + assert(cid); + + I3_PRINT_DEBUG2(I3_DEBUG_LEVEL_VERBOSE, + "in cl_sendto: using server %s:%u\n", + inet_ntoa(cid->cache_addr.sin_addr), + ntohs(cid->cache_addr.sin_port) + ); + + if (ctx->is_tcp) { + if (!ctx->init_tcp_ctx_flag) { + // TCP connection had not been earlier established. + // Try again + init_tcp_ctx(ctx); + + if (!ctx->init_tcp_ctx_flag) { + //failed again + I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, + "send failed as tcp connection could not be established.\n" + ); + return CL_RET_NET_ERROR; + } + } + + if (ctx->is_tcp && ctx->init_tcp_ctx_flag) { + if (send_tcp(pkt, pkt_len, ctx->tcp_fd) < 0) { + return CL_RET_NET_ERROR; + } + } + } else { + int numSent = 0; + if ((numSent = sendto(ctx->fd, pkt, pkt_len, 0, + (struct sockaddr *) &cid->cache_addr, + sizeof(cid->cache_addr))) < 0) { + perror("cl_sendto"); + if (errno == ENETUNREACH) { + if (cid->retries_cnt > 0) { + cid->retries_cnt--; + } + } else { + return CL_RET_NET_ERROR; + } + } + } + + return CL_RET_OK; } - void make_data_opt(cl_context *ctx, uint8_t opt_mask, buf_struct *b) { - unsigned short len; - i3_addr *a; - i3_option *o; - i3_option_list *ol; - - ol = alloc_i3_option_list(); - - /* create ID_OPT_SENDER to tell the i3 server where to reply if - * trigger not present - */ - a = alloc_i3_addr(); - init_i3_addr_ipv4(a, ctx->local_ip_addr, ctx->local_port); - o = alloc_i3_option(); - init_i3_option(o, I3_OPT_SENDER, (void *)a); - append_i3_option(ol, o); - - // Code_Clean: make this 3 ifs into a loop - if (opt_mask & REFRESH_MASK) { - /* add "request for cache" option if needed */ - o = alloc_i3_option(); - init_i3_option(o, I3_OPT_REQUEST_FOR_CACHE, NULL); - append_i3_option(ol, o); - } - - if (opt_mask & REFRESH_SHORTCUT_MASK) { - /* add "request for cache" option if needed */ - o = alloc_i3_option(); - init_i3_option(o, I3_OPT_REQUEST_FOR_CACHE_SHORTCUT, NULL); - append_i3_option(ol, o); - } + unsigned short len; + i3_addr *a; + i3_option *o; + i3_option_list *ol; + + ol = alloc_i3_option_list(); + + /* create ID_OPT_SENDER to tell the i3 server where to reply if + * trigger not present + */ + a = alloc_i3_addr(); + init_i3_addr_ipv4(a, ctx->local_ip_addr, ctx->local_port); + o = alloc_i3_option(); + init_i3_option(o, I3_OPT_SENDER, (void *) a); + append_i3_option(ol, o); + + // Code_Clean: make this 3 ifs into a loop + if (opt_mask & REFRESH_MASK) { + /* add "request for cache" option if needed */ + o = alloc_i3_option(); + init_i3_option(o, I3_OPT_REQUEST_FOR_CACHE, NULL); + append_i3_option(ol, o); + } + + if (opt_mask & REFRESH_SHORTCUT_MASK) { + /* add "request for cache" option if needed */ + o = alloc_i3_option(); + init_i3_option(o, I3_OPT_REQUEST_FOR_CACHE_SHORTCUT, NULL); + append_i3_option(ol, o); + } #if NEWS_INSTRUMENT - if (opt_mask & LOG_PKT_MASK) { - /* add "log packet" option if needed */ - o = alloc_i3_option(); - init_i3_option(o, I3_OPT_LOG_PACKET, NULL); - append_i3_option(ol, o); - } + if (opt_mask & LOG_PKT_MASK) { + /* add "log packet" option if needed */ + o = alloc_i3_option(); + init_i3_option(o, I3_OPT_LOG_PACKET, NULL); + append_i3_option(ol, o); + } - if (opt_mask & APP_TS_MASK) { - /* add "append ts" option if needed */ - o = alloc_i3_option(); - init_i3_option(o, I3_OPT_APPEND_TS, NULL); - append_i3_option(ol, o); - } + if (opt_mask & APP_TS_MASK) { + /* add "append ts" option if needed */ + o = alloc_i3_option(); + init_i3_option(o, I3_OPT_APPEND_TS, NULL); + append_i3_option(ol, o); + } #endif - - /* get option length ... */ - len = get_i3_option_list_len(ol); - - /* ... allocate memory ... */ - if ((b->p = (char *)malloc(len)) == NULL) - I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, "make_data_hdr: memory allocation error\n"); - - /* ... and pack the option list */ - pack_i3_option_list(b->p, ol, &len); - b->len = len; - - free_i3_option_list(ol); + + /* get option length ... */ + len = get_i3_option_list_len(ol); + + /* ... allocate memory ... */ + if ((b->p = (char *) malloc(len)) == NULL) { + I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, "make_data_hdr: memory allocation error\n"); + } + + /* ... and pack the option list */ + pack_i3_option_list(b->p, ol, &len); + b->len = len; + + free_i3_option_list(ol); } -void fast_pack_i3_header(char *p, char data, i3_stack *stack, - char *packed_ol, unsigned short packed_ol_len) +void fast_pack_i3_header(char *p, char data, i3_stack *stack, + char *packed_ol, unsigned short packed_ol_len) { - unsigned short len = 0; - - *p = I3_v01; - p += sizeof(char); - //len = sizeof(char); - *p = (data ? I3_DATA : 0); - if (!packed_ol) - *p = *p & (~I3_OPTION_LIST); - else - *p = *p | I3_OPTION_LIST; - p++; //len += sizeof(char); - *p=0; - if (stack) { - pack_i3_stack(p, stack, &len); - p += len; - } - - memcpy(p, packed_ol, packed_ol_len); + unsigned short len = 0; + + *p = I3_v01; + p += sizeof(char); + //len = sizeof(char); + *p = (data ? I3_DATA : 0); + if (!packed_ol) { + *p = *p & (~I3_OPTION_LIST); + } else { + *p = *p | I3_OPTION_LIST; + } + p++; //len += sizeof(char); + *p = 0; + if (stack) { + pack_i3_stack(p, stack, &len); + p += len; + } + + memcpy(p, packed_ol, packed_ol_len); } - void make_opt_cache_address_pkt(cl_context *ctx, ID *id, int prefix_len, - char *buf, unsigned short *buf_len) -{ - i3_header *h; - i3_option *o; - i3_option_list *ol; - i3_trigger *t; - i3_addr *a; - static Key null_key; - - ol = alloc_i3_option_list(); - o = alloc_i3_option(); - t = alloc_i3_trigger(); - a = alloc_i3_addr(); - init_i3_addr_ipv4(a, ctx->local_ip_addr, ntohs(ctx->local.sin_port)); - init_i3_trigger(t, id, prefix_len, a, &null_key, 0); - init_i3_option(o, I3_OPT_CACHE_SHORTCUT_ADDR, t); - append_i3_option(ol, o); - - /* finish create the header */ - h = alloc_i3_header(); - init_i3_header(h, FALSE, NULL, ol); - pack_i3_header(buf, h, buf_len); - free_i3_header(h); -} - -/* send cache reply to the sender; used when shortcut is enabled */ -void cl_send_opt_cache_address_indir(cl_context *ctx, ID *id, int prefix_len, - i3_addr *to) -{ -#define MAX_PKT_SIZE 1024 - char pkt[MAX_PKT_SIZE]; - unsigned short len; - - assert(to->type != I3_ADDR_TYPE_STACK); - - make_opt_cache_address_pkt(ctx, id, prefix_len, pkt, &len); - - /* send packet */ - I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, "send back cache address\n"); - switch(to->type) { - case I3_ADDR_TYPE_IPv4: - send_packet_ipv4(pkt, len, &to->t.v4.addr, to->t.v4.port, ctx->fd); - break; - case I3_ADDR_TYPE_IPv4_NAT: - send_packet_ipv4(pkt, len, &to->t.v4_nat.nat_addr, - to->t.v4_nat.nat_port, ctx->fd); - break; - default: - I3_PRINT_DEBUG1(I3_DEBUG_LEVEL_MINIMAL, "cl_send_opt_cache_address: invalid addr type: %d\n", - to->type); - } -} - - -/* send cache reply to the sender; used when shortcut is enabled */ -void cl_send_opt_cache_address(cl_context *ctx, ID *id, int prefix_len, - struct sockaddr_in *fromaddr) -{ -#define MAX_PKT_SIZE 1024 - char pkt[MAX_PKT_SIZE]; - unsigned short len; - - make_opt_cache_address_pkt(ctx, id, prefix_len, pkt, &len); - - /* send packet */ - I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, "send back cache address\n"); - - if (sendto(ctx->fd, pkt, len, 0, - (struct sockaddr *)fromaddr, sizeof(*fromaddr)) < 0) - I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL," cl_send_opt_cache_address: sendto error\n"); -} - + char *buf, unsigned short *buf_len) +{ + i3_header *h; + i3_option *o; + i3_option_list *ol; + i3_trigger *t; + i3_addr *a; + static Key null_key; + + ol = alloc_i3_option_list(); + o = alloc_i3_option(); + t = alloc_i3_trigger(); + a = alloc_i3_addr(); + init_i3_addr_ipv4(a, ctx->local_ip_addr, ntohs(ctx->local.sin_port)); + init_i3_trigger(t, id, prefix_len, a, &null_key, 0); + init_i3_option(o, I3_OPT_CACHE_SHORTCUT_ADDR, t); + append_i3_option(ol, o); + + /* finish create the header */ + h = alloc_i3_header(); + init_i3_header(h, FALSE, NULL, ol); + pack_i3_header(buf, h, buf_len); + free_i3_header(h); +} + +/* send cache reply to the sender; used when shortcut is enabled */ +void cl_send_opt_cache_address_indir(cl_context *ctx, ID *id, int prefix_len, + i3_addr *to) +{ +#define MAX_PKT_SIZE 1024 + char pkt[MAX_PKT_SIZE]; + unsigned short len; + + assert(to->type != I3_ADDR_TYPE_STACK); + + make_opt_cache_address_pkt(ctx, id, prefix_len, pkt, &len); + + /* send packet */ + I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, "send back cache address\n"); + switch (to->type) { + case I3_ADDR_TYPE_IPv4: + send_packet_ipv4(pkt, len, &to->t.v4.addr, to->t.v4.port, ctx->fd); + break; + case I3_ADDR_TYPE_IPv4_NAT: + send_packet_ipv4(pkt, len, &to->t.v4_nat.nat_addr, + to->t.v4_nat.nat_port, ctx->fd); + break; + default: + I3_PRINT_DEBUG1(I3_DEBUG_LEVEL_MINIMAL, "cl_send_opt_cache_address: invalid addr type: %d\n", + to->type); + } +} + +/* send cache reply to the sender; used when shortcut is enabled */ +void cl_send_opt_cache_address(cl_context *ctx, ID *id, int prefix_len, + struct sockaddr_in *fromaddr) +{ +#define MAX_PKT_SIZE 1024 + char pkt[MAX_PKT_SIZE]; + unsigned short len; + + make_opt_cache_address_pkt(ctx, id, prefix_len, pkt, &len); + + /* send packet */ + I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, "send back cache address\n"); + + if (sendto(ctx->fd, pkt, len, 0, + (struct sockaddr *) fromaddr, sizeof(*fromaddr)) < 0) { + I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, " cl_send_opt_cache_address: sendto error\n"); + } +} void cl_send_request_for_shortcut(cl_context *ctx, cl_id *cid, int refresh) { - uint8_t opts_mask; - char pkt[CL_PREFIX_LEN]; - i3_stack *s; - unsigned short len; - - opts_mask = REFRESH_SHORTCUT_MASK; - - /* create I3_OPT_REQUEST_FOR_CACHE_SHORTCUT packet and send it - * directly to destination - */ - /* pack ID */ - s = alloc_i3_stack(); - init_i3_stack(s, &cid->id, 1); - - /* compute packet length */ - len = 2 * sizeof(char) + get_i3_stack_len(s) + - ctx->precomputed_opt[opts_mask].len; - assert(len <= CL_PREFIX_LEN); - - fast_pack_i3_header(pkt, FALSE, s, - ctx->precomputed_opt[opts_mask].p, - ctx->precomputed_opt[opts_mask].len); - free_i3_stack(s); - assert(len < CL_PREFIX_LEN); - - if (sendto(ctx->fd, pkt, len, 0, - (struct sockaddr *)&cid->dest_addr, sizeof(cid->dest_addr)) < 0) { - perror("cl_sendto"); - } + uint8_t opts_mask; + char pkt[CL_PREFIX_LEN]; + i3_stack *s; + unsigned short len; + + opts_mask = REFRESH_SHORTCUT_MASK; + + /* create I3_OPT_REQUEST_FOR_CACHE_SHORTCUT packet and send it + * directly to destination + */ + /* pack ID */ + s = alloc_i3_stack(); + init_i3_stack(s, &cid->id, 1); + + /* compute packet length */ + len = 2 * sizeof(char) + get_i3_stack_len(s) + + ctx->precomputed_opt[opts_mask].len; + assert(len <= CL_PREFIX_LEN); + + fast_pack_i3_header(pkt, FALSE, s, + ctx->precomputed_opt[opts_mask].p, + ctx->precomputed_opt[opts_mask].len); + free_i3_stack(s); + assert(len < CL_PREFIX_LEN); + + if (sendto(ctx->fd, pkt, len, 0, + (struct sockaddr *) &cid->dest_addr, sizeof(cid->dest_addr)) < 0) { + perror("cl_sendto"); + } } === modified file 'i3/i3_client/i3_client_pkt.h' --- i3/i3_client/i3_client_pkt.h 2009-12-11 22:49:11 +0000 +++ i3/i3_client/i3_client_pkt.h 2010-02-11 11:49:47 +0000 @@ -1,27 +1,27 @@ /*************************************************************************** - i3_client_pkt.h - description - ------------------- - begin : Aug 14 2003 - email : istoica@xxxxxxxxxxxxxxx - ***************************************************************************/ +* i3_client_pkt.h - description +* ------------------- +* begin : Aug 14 2003 +* email : istoica@xxxxxxxxxxxxxxx +***************************************************************************/ #ifndef I3_CLIENT_PKT_H #define I3_CLIENT_PKT_H - + /* functions implemented in i3_client_pkt.c */ int cl_send_data_packet(cl_context *ctx, i3_stack *stack, - cl_buf *clb, uint16_t flags, char is_total_len); + cl_buf *clb, uint16_t flags, char is_total_len); int cl_send_packet(cl_context *ctx, i3_header *header, - cl_buf *clb, uint8_t opts); + cl_buf *clb, uint8_t opts); int cl_sendto(cl_context *ctx, char *pkt, uint16_t pkt_len, - cl_id *cid, ID *id); + cl_id *cid, ID *id); int cl_receive_packet_from(cl_context *ctx, i3_header **phdr, cl_buf *clb, - struct sockaddr_in *fromaddr); + struct sockaddr_in *fromaddr); void cl_receive_packet(cl_context *ctx, i3_header **phdr, cl_buf *clb); void make_data_opt(cl_context *ctx, uint8_t opts_mask, buf_struct *b); -void cl_send_opt_cache_address_indir(cl_context *ctx, ID *id, int prefix_len, - i3_addr *to); -void cl_send_opt_cache_address(cl_context *ctx, ID *id, int prefix_len, - struct sockaddr_in *fromaddr); +void cl_send_opt_cache_address_indir(cl_context *ctx, ID *id, int prefix_len, + i3_addr *to); +void cl_send_opt_cache_address(cl_context *ctx, ID *id, int prefix_len, + struct sockaddr_in *fromaddr); void cl_send_request_for_shortcut(cl_context *ctx, cl_id *cid, int refresh); #endif === modified file 'i3/i3_client/i3_client_timer.c' --- i3/i3_client/i3_client_timer.c 2010-01-06 22:17:32 +0000 +++ i3/i3_client/i3_client_timer.c 2010-02-11 11:49:47 +0000 @@ -1,4 +1,3 @@ - #include "../i3/i3.h" #include "../i3/i3_fun.h" #include "i3_client.h" @@ -9,16 +8,16 @@ void init_timer_heap(cl_context *ctx) { - - ctx->timer_heap.heap = newEventArray(TIMER_HEAP_SIZE); - ctx->timer_heap.size = 0; - ctx->timer_heap.max_size = TIMER_HEAP_SIZE; + ctx->timer_heap.heap = newEventArray(TIMER_HEAP_SIZE); + ctx->timer_heap.size = 0; + ctx->timer_heap.max_size = TIMER_HEAP_SIZE; } void free_timer_heap(cl_context *ctx) { - if (ctx->timer_heap.heap) - free(ctx->timer_heap.heap); + if (ctx->timer_heap.heap) { + free(ctx->timer_heap.heap); + } } /*********************************************************************** @@ -27,41 +26,41 @@ void invoke_timers(cl_context *ctx, uint64_t now) { - Event *ev; - void (*fun)(void *); - void *data; + Event *ev; + void (*fun)(void *); + void *data; - while (1) { - ev = getNextEvent(&ctx->timer_heap); - if (ev && ev->time <= now) { - if (ev->cancel == FALSE) { - /* invoke timer only if it wasn't canceled in between */ - fun = ev->fun; - data = ev->params; - fun(data); - } - removeNextEvent(&ctx->timer_heap); - } else - return; - } + while (1) { + ev = getNextEvent(&ctx->timer_heap); + if (ev && ev->time <= now) { + if (ev->cancel == FALSE) { + /* invoke timer only if it wasn't canceled in between */ + fun = ev->fun; + data = ev->params; + fun(data); + } + removeNextEvent(&ctx->timer_heap); + } else { + return; + } + } } - int get_next_timer(cl_context *ctx, struct timeval *to, uint64_t now) { - uint64_t diff; - Event *ev = getNextEvent(&ctx->timer_heap); - - if (!ev) - return 0; - - if (ev->time < now) - to->tv_sec = to->tv_usec = 0; - else { - diff = ev->time - now; - to->tv_usec = diff % UMILLION; - to->tv_sec = diff / UMILLION; - } - return 1; + uint64_t diff; + Event *ev = getNextEvent(&ctx->timer_heap); + + if (!ev) { + return 0; + } + + if (ev->time < now) { + to->tv_sec = to->tv_usec = 0; + } else { + diff = ev->time - now; + to->tv_usec = diff % UMILLION; + to->tv_sec = diff / UMILLION; + } + return 1; } - === modified file 'i3/i3_client/i3_client_timer.h' --- i3/i3_client/i3_client_timer.h 2009-12-11 22:49:11 +0000 +++ i3/i3_client/i3_client_timer.h 2010-02-11 11:49:47 +0000 @@ -1,12 +1,12 @@ /*************************************************************************** - i3_client_id.h - description - ------------------- - begin : Aug 14 2003 - email : istoica@xxxxxxxxxxxxxxx - ***************************************************************************/ +* i3_client_id.h - description +* ------------------- +* begin : Aug 14 2003 +* email : istoica@xxxxxxxxxxxxxxx +***************************************************************************/ #ifndef I3_CLIENT_TIMER_H -#define I3_CLIENT_TIMER_H +#define I3_CLIENT_TIMER_H /* functions implemented in i3_client_timer.c */ void init_timer_heap(cl_context *ctx); === modified file 'i3/i3_client/i3_client_trigger.c' --- i3/i3_client/i3_client_trigger.c 2010-01-06 22:17:32 +0000 +++ i3/i3_client/i3_client_trigger.c 2010-02-11 11:49:47 +0000 @@ -1,17 +1,17 @@ /*************************************************************************** - i3_client_trigger.c - description - ------------------- - begin : Aug 14 2003 - email : istoica@xxxxxxxxxxxxxxx - - changes: - Nov 10, 2004: added two functions (num_matched_bits and - cl_get_max_prefix_len_from_list) needed for - handling anycast triggers inserted by the same node; - see the cl_context_select function in i3_client_context.c - - Nov 12, 2004: added the shortcut functionality - ***************************************************************************/ +* i3_client_trigger.c - description +* ------------------- +* begin : Aug 14 2003 +* email : istoica@xxxxxxxxxxxxxxx +* +* changes: +* Nov 10, 2004: added two functions (num_matched_bits and +* cl_get_max_prefix_len_from_list) needed for +* handling anycast triggers inserted by the same node; +* see the cl_context_select function in i3_client_context.c +* +* Nov 12, 2004: added the shortcut functionality +***************************************************************************/ #include <stdlib.h> #ifndef _WIN32 @@ -35,87 +35,84 @@ void trigger_cancel_timer(cl_trigger *ctr); /********************************************************************* - * cl_create_trigger_gen - create a trigger entry and insert it in - * a hash data structure - * input: - * ctx - context - * addr_type - trigger type - * id - trigger's ID - * prefix_len - length of the trigger's ID preffix - * ip_addr, port - address and port number of the receiver - * (addr_type == I3_ADDR_TYPE_IPv4) - * stack - stack of ID (addr_type == I3_ADDR_TYPE_STACK) - * flags - flags associated to the trigger (e.g., - * I3_TRIGGER_FLAG_ALLOW_SHORTCUT) - * - * output: - * trigger entry, if allocation succesful; NULL, otherwise - *********************************************************************/ +* cl_create_trigger_gen - create a trigger entry and insert it in +* a hash data structure +* input: +* ctx - context +* addr_type - trigger type +* id - trigger's ID +* prefix_len - length of the trigger's ID preffix +* ip_addr, port - address and port number of the receiver +* (addr_type == I3_ADDR_TYPE_IPv4) +* stack - stack of ID (addr_type == I3_ADDR_TYPE_STACK) +* flags - flags associated to the trigger (e.g., +* I3_TRIGGER_FLAG_ALLOW_SHORTCUT) +* +* output: +* trigger entry, if allocation succesful; NULL, otherwise +*********************************************************************/ cl_trigger *cl_create_trigger_gen(cl_context *ctx, - uint16_t addr_type, - ID *id, uint16_t prefix_len, - struct in_addr ip_addr, uint16_t port, - i3_stack *stack, Key *key, uint16_t flags) + uint16_t addr_type, + ID *id, uint16_t prefix_len, + struct in_addr ip_addr, uint16_t port, + i3_stack *stack, Key *key, uint16_t flags) { - i3_trigger *t; - i3_addr *a; - cl_trigger *ctr; - int idx = CL_HASH_TRIG(id); - - t = alloc_i3_trigger(); - a = alloc_i3_addr(); - - switch (addr_type) { - case I3_ADDR_TYPE_IPv4: - init_i3_addr_ipv4(a, ip_addr, port); - break; - case I3_ADDR_TYPE_STACK: - init_i3_addr_stack(a, stack); - break; - default: - I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, - "cl_create_trigger_gen: invalid address type\n"); - } - - init_i3_trigger(t, id, MAX(prefix_len, MIN_PREFIX_LEN), a, key, flags); - - if (cl_get_trigger_from_list(ctx->trigger_htable[idx], t) == NULL) { - ctr = cl_alloc_trigger(); - ctr->t = t; - ctr->status = CL_TRIGGER_STATUS_IDLE; - ctr->is_queued = FALSE; /* Not yet inserted in PRIORITY QUEUE */ - ctr->retries_cnt = 0; - ctr->ctx = ctx; - ctr->timer = NULL; - - cl_add_trigger_to_list(&ctx->trigger_htable[idx], ctr); - return ctr; - } else { - /* trigger already presented */ - free_i3_trigger(t); - return NULL; - } + i3_trigger *t; + i3_addr *a; + cl_trigger *ctr; + int idx = CL_HASH_TRIG(id); + + t = alloc_i3_trigger(); + a = alloc_i3_addr(); + + switch (addr_type) { + case I3_ADDR_TYPE_IPv4: + init_i3_addr_ipv4(a, ip_addr, port); + break; + case I3_ADDR_TYPE_STACK: + init_i3_addr_stack(a, stack); + break; + default: + I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, + "cl_create_trigger_gen: invalid address type\n"); + } + + init_i3_trigger(t, id, MAX(prefix_len, MIN_PREFIX_LEN), a, key, flags); + + if (cl_get_trigger_from_list(ctx->trigger_htable[idx], t) == NULL) { + ctr = cl_alloc_trigger(); + ctr->t = t; + ctr->status = CL_TRIGGER_STATUS_IDLE; + ctr->is_queued = FALSE; /* Not yet inserted in PRIORITY QUEUE */ + ctr->retries_cnt = 0; + ctr->ctx = ctx; + ctr->timer = NULL; + + cl_add_trigger_to_list(&ctx->trigger_htable[idx], ctr); + return ctr; + } else { + /* trigger already presented */ + free_i3_trigger(t); + return NULL; + } } - /************************************************************************ * cl_delete_trigger - delete a given trigger; remove it from - * ctx->trigger_htable and free memory + * ctx->trigger_htable and free memory *************************************************************************/ void cl_delete_trigger(cl_context *ctx, cl_trigger *ctr) { - int idx = CL_HASH_TRIG(&ctr->t->id); + int idx = CL_HASH_TRIG(&ctr->t->id); - cl_remove_trigger_from_list(&ctx->trigger_htable[idx], ctr); - cl_free_trigger(ctr); + cl_remove_trigger_from_list(&ctx->trigger_htable[idx], ctr); + cl_free_trigger(ctr); } - - /************************************************************************ - * cl_insert_trigger_into_i3 - insert a given trigger + * cl_insert_trigger_into_i3 - insert a given trigger * * input: * ctx - context @@ -124,43 +121,44 @@ int cl_insert_trigger_into_i3(cl_context *ctx, cl_trigger *ctr) { - int refresh; - - assert(ctr); - if (ctr->type == CL_TRIGGER_LOCAL) { - I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, - "This trigger is local so it shouldn't be inserted in i3\n"); + int refresh; + + assert(ctr); + if (ctr->type == CL_TRIGGER_LOCAL) { + I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, + "This trigger is local so it shouldn't be inserted in i3\n"); + return CL_RET_OK; + } + + if (ctr->precomputed_pkt.p == NULL) { + /* Beware of side effects! The precomputed packet can be + * *changed in cl_ctx_trigger_ratelimit() and process_trigger_option() + */ + cl_make_trigger_packet(ctx, ctr->t, + I3_OPT_TRIGGER_INSERT, &ctr->precomputed_pkt); + } + + if (ctr->status == CL_TRIGGER_STATUS_INSERTED) { + /* trigger already inserted; this is a redundant trigger insertion call */ + ; + } else { + ctr->status = CL_TRIGGER_STATUS_PENDING; + } + + /* insert trigger into i3; + * "refresh" doesn't matter here as trigger inserts are always + * acked with a control message (I3_OPT_TRIGGER_CHALLENGE or + * I3_OPT_TRIGGER_ACK) that includes the option I3_OPT_CACHE_ADDR + */ + cl_sendto(ctx, ctr->precomputed_pkt.p, ctr->precomputed_pkt.len, + cl_get_valid_id(ctx, &ctr->t->id, &refresh), + &ctr->t->id); + return CL_RET_OK; - } - - if (ctr->precomputed_pkt.p == NULL) - /* Beware of side effects! The precomputed packet can be - *changed in cl_ctx_trigger_ratelimit() and process_trigger_option() - */ - cl_make_trigger_packet(ctx, ctr->t, - I3_OPT_TRIGGER_INSERT, &ctr->precomputed_pkt); - - if (ctr->status == CL_TRIGGER_STATUS_INSERTED) { - /* trigger already inserted; this is a redundant trigger insertion call */ - ; - } else - ctr->status = CL_TRIGGER_STATUS_PENDING; - - /* insert trigger into i3; - * "refresh" doesn't matter here as trigger inserts are always - * acked with a control message (I3_OPT_TRIGGER_CHALLENGE or - * I3_OPT_TRIGGER_ACK) that includes the option I3_OPT_CACHE_ADDR - */ - cl_sendto(ctx, ctr->precomputed_pkt.p, ctr->precomputed_pkt.len, - cl_get_valid_id(ctx, &ctr->t->id, &refresh), - &ctr->t->id); - - return CL_RET_OK; } - /************************************************************************ - * cl_remove_trigger_from_i3 - remove given trigger + * cl_remove_trigger_from_i3 - remove given trigger * * input: * ctx - context @@ -169,539 +167,555 @@ int cl_remove_trigger_from_i3(cl_context *ctx, cl_trigger *ctr) { - buf_struct b; - int refresh; - int idx = CL_HASH_TRIG(&ctr->t->id);; - - if (ctr->type == CL_TRIGGER_LOCAL) { - I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, - "This trigger is local so it shouldn't be inserted in i3\n"); + buf_struct b; + int refresh; + int idx = CL_HASH_TRIG(&ctr->t->id); + ; + + if (ctr->type == CL_TRIGGER_LOCAL) { + I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, + "This trigger is local so it shouldn't be inserted in i3\n"); + return CL_RET_OK; + } + + if ((ctr = cl_get_trigger_from_list(ctx->trigger_htable[idx], ctr->t)) + == NULL) { + return CL_RET_TRIGGER_NOT_FOUND; + } + + cl_make_trigger_packet(ctx, ctr->t, I3_OPT_TRIGGER_REMOVE, &b); + + cl_sendto(ctx, b.p, b.len, cl_get_valid_id(ctx, &ctr->t->id, &refresh), + &ctr->t->id); + ctr->status = CL_TRIGGER_STATUS_IDLE; + + free(b.p); /* ... because b.p is allocated in cl_make_trigger_packet */ + + /* cancel any timer associated to the trigger, if any */ + trigger_cancel_timer(ctr); + return CL_RET_OK; - } - - if ((ctr = cl_get_trigger_from_list(ctx->trigger_htable[idx], ctr->t)) - == NULL) - return CL_RET_TRIGGER_NOT_FOUND; - - cl_make_trigger_packet(ctx, ctr->t, I3_OPT_TRIGGER_REMOVE, &b); - - cl_sendto(ctx, b.p, b.len, cl_get_valid_id(ctx, &ctr->t->id, &refresh), - &ctr->t->id); - ctr->status = CL_TRIGGER_STATUS_IDLE; - - free(b.p); /* ... because b.p is allocated in cl_make_trigger_packet */ - - /* cancel any timer associated to the trigger, if any */ - trigger_cancel_timer(ctr); - - return CL_RET_OK; } /* basic operations for manipulating triggers on the client side */ cl_trigger *cl_alloc_trigger() { - cl_trigger *ctr; - - if ((ctr = (cl_trigger *)calloc(1, sizeof(cl_trigger))) != NULL) - return ctr; - - I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, - "cl_alloc_trigger: memory allocation error.\n"); - return NULL; + cl_trigger *ctr; + + if ((ctr = (cl_trigger *) calloc(1, sizeof(cl_trigger))) != NULL) { + return ctr; + } + + I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, + "cl_alloc_trigger: memory allocation error.\n"); + return NULL; } void cl_free_trigger(cl_trigger *ctr) { - /* cancel any timer associated to the trigger, if any */ - trigger_cancel_timer(ctr); + /* cancel any timer associated to the trigger, if any */ + trigger_cancel_timer(ctr); - free_i3_trigger(ctr->t); - if (ctr->precomputed_pkt.p) - free(ctr->precomputed_pkt.p); - free(ctr); + free_i3_trigger(ctr->t); + if (ctr->precomputed_pkt.p) { + free(ctr->precomputed_pkt.p); + } + free(ctr); } - void cl_free_trigger_list(cl_trigger *ctr_head) { - cl_trigger *ctr; - - assert(ctr_head); - - while (ctr_head) { - ctr = ctr_head->next; - cl_free_trigger(ctr_head); - ctr_head = ctr; - } + cl_trigger *ctr; + + assert(ctr_head); + + while (ctr_head) { + ctr = ctr_head->next; + cl_free_trigger(ctr_head); + ctr_head = ctr; + } } #define MAX_TRIG_PER_HASH 10000 cl_trigger *cl_get_trigger_from_list(cl_trigger *head, i3_trigger *t) { - cl_trigger *ctr; - int count = 0; + cl_trigger *ctr; + int count = 0; - for (ctr = head; ctr; ctr = ctr->next) { - count++; - if (count > MAX_TRIG_PER_HASH) - I3_PRINT_INFO1(I3_INFO_LEVEL_VERBOSE, - "Too many triggers per entry! %d\n", count); - if (trigger_equal(t, ctr->t)) { - return ctr; - } - } - return NULL; + for (ctr = head; ctr; ctr = ctr->next) { + count++; + if (count > MAX_TRIG_PER_HASH) { + I3_PRINT_INFO1(I3_INFO_LEVEL_VERBOSE, + "Too many triggers per entry! %d\n", count); + } + if (trigger_equal(t, ctr->t)) { + return ctr; + } + } + return NULL; } int does_id_match(ID *id1, ID *id2, int prefix_len) { - int d = prefix_len / 8; /* number of bytes */ - int r = prefix_len % 8; - char mask = 0; - - if (memcmp((char *)id1, (char *)id2, d)) + int d = prefix_len / 8; /* number of bytes */ + int r = prefix_len % 8; + char mask = 0; + + if (memcmp((char *) id1, (char *) id2, d)) { + return FALSE; + } + + if (r == 0) { + return TRUE; + } + + mask = ~(0x7f >> (r - 1)); + + if ((id1->x[d] & mask) == (id2->x[d] & mask)) { + return TRUE; + } + return FALSE; - - if (r == 0) - return TRUE; - - mask = ~(0x7f >> (r - 1)); - - if ((id1->x[d] & mask) == (id2->x[d] & mask)) - return TRUE; - - return FALSE; } cl_trigger *cl_get_trigger_by_id(cl_trigger *ctr_head, ID *id) { - cl_trigger *ctr; - - for (ctr = ctr_head; ctr; ctr = ctr->next) - if (does_id_match(&ctr->t->id, id, ctr->t->prefix_len) == TRUE) - return ctr; - - return NULL; + cl_trigger *ctr; + + for (ctr = ctr_head; ctr; ctr = ctr->next) { + if (does_id_match(&ctr->t->id, id, ctr->t->prefix_len) == TRUE) { + return ctr; + } + } + + return NULL; } /* get the common prefix length of x and y */ int num_matched_bits(ID *id1, ID *id2) { - int i, j; - char mask = 0x80; - - for (i = 0; i < ID_LEN; i += sizeof(long)) { - if (*(long *)&id1->x[i] != *(long *)&id2->x[i]) - break; - } - - if (i == ID_LEN) - return i*8; - - for (; i < ID_LEN; i++) { - if (id1->x[i] != id2->x[i]) - break; - } - if (i == ID_LEN) - return i*8; - - for (j = 0; j < 8; j++) { - if ((id1->x[i] & mask) != (id2->x[i] & mask)) - break; - mask = mask >> 1; - } - - return i*8 + j; + int i, j; + char mask = 0x80; + + for (i = 0; i < ID_LEN; i += sizeof(long)) { + if (*(long *) &id1->x[i] != *(long *) &id2->x[i]) { + break; + } + } + + if (i == ID_LEN) { + return i * 8; + } + + for (; i < ID_LEN; i++) { + if (id1->x[i] != id2->x[i]) { + break; + } + } + if (i == ID_LEN) { + return i * 8; + } + + for (j = 0; j < 8; j++) { + if ((id1->x[i] & mask) != (id2->x[i] & mask)) { + break; + } + mask = mask >> 1; + } + + return i * 8 + j; } - int cl_get_max_prefix_len_from_list(cl_trigger *ctr_head, ID *id) { - cl_trigger *ctr; - int max_prefix_len = 0, n; + cl_trigger *ctr; + int max_prefix_len = 0, n; - for (ctr = ctr_head; ctr; ctr = ctr->next) { - n = num_matched_bits(&(ctr->t->id), id); - if (n > max_prefix_len) - max_prefix_len = n; - } - return max_prefix_len; + for (ctr = ctr_head; ctr; ctr = ctr->next) { + n = num_matched_bits(&(ctr->t->id), id); + if (n > max_prefix_len) { + max_prefix_len = n; + } + } + return max_prefix_len; } - -/* remove a given trigger from list; don't destroy it */ +/* remove a given trigger from list; don't destroy it */ void cl_remove_trigger_from_list(cl_trigger **phead, cl_trigger *ctr) { + assert(ctr); - assert(ctr); - - if (*phead == ctr) { - *phead = (*phead)->next; - if (*phead) - (*phead)->prev = NULL; - } else { - ctr->prev->next = ctr->next; - if (ctr->next) - ctr->next->prev = ctr->prev; - } + if (*phead == ctr) { + *phead = (*phead)->next; + if (*phead) { + (*phead)->prev = NULL; + } + } else { + ctr->prev->next = ctr->next; + if (ctr->next) { + ctr->next->prev = ctr->prev; + } + } } - /* insert at the head of the list */ void cl_add_trigger_to_list(cl_trigger **phead, cl_trigger *ctr) { - assert(ctr); + assert(ctr); - ctr->next = *phead; - if (*phead) - (*phead)->prev = ctr; - ctr->prev = NULL; - *phead = ctr; + ctr->next = *phead; + if (*phead) { + (*phead)->prev = ctr; + } + ctr->prev = NULL; + *phead = ctr; } /* update (id,R) --> (id,R'). called when IP addr change is detected */ void cl_update_triggers(cl_context *ctx) { - int idx; - cl_trigger *ctr; - - for (idx = 0; idx < CL_HTABLE_SIZE; idx++) { - for (ctr = ctx->trigger_htable[idx]; ctr; ctr = ctr->next) { - if (I3_ADDR_TYPE_IPv4 == ctr->t->to->type) - { - /* (i) update addr */ - ctr->t->to->t.v4.addr = ctx->local_ip_addr; - - /* (ii) invalidate */ - ctr->is_queued = FALSE; - ctr->retries_cnt = 0; - free(ctr->precomputed_pkt.p); - ctr->precomputed_pkt.p = NULL; - - /* (iii) re-insert in i3 */ - cl_insert_trigger_into_i3(ctx, ctr); - } - } - } -} - -void process_trigger_option(cl_context *ctx, i3_trigger *t, - int opt_type, struct sockaddr_in *fromaddr) -{ - cl_trigger *ctr; - int refresh; - struct timeval tv; - struct sockaddr_in *faddr = fromaddr; - - assert(ctx != NULL); - - switch (opt_type) { - case I3_OPT_TRIGGER_CHALLENGE: - - ctr = cl_get_trigger_from_list( - ctx->trigger_htable[CL_HASH_TRIG(&t->id)], t); - - if (NULL == ctr) { - #ifdef CONFIG_HIP_DEBUG - { - char tmpIdStr[100]; - I3_PRINT_DEBUG1(I3_DEBUG_LEVEL_MINIMAL, - "Ignoring reply to a removed trigger with id %s\n", - sprintf_i3_id (tmpIdStr, &(t->id))); - } - #endif - break; - } - - memcpy((char *)ctr->t->nonce, (char *)t->nonce, NONCE_LEN); - - /* check whether this trigger has been already precomputed */ - if (ctr->precomputed_pkt.p) - free(ctr->precomputed_pkt.p); - - cl_make_trigger_packet(ctx, ctr->t, I3_OPT_TRIGGER_INSERT, - &ctr->precomputed_pkt); - - cl_sendto(ctx, ctr->precomputed_pkt.p, - ctr->precomputed_pkt.len, - cl_get_valid_id(ctx, &t->id, &refresh), &t->id); - - cl_trigger_callback(ctx, ctr, - CL_INTERNAL_HOOK_TRIGGER_ACK_TIMEOUT, NULL, NULL); - /* set ack timeout */ - tv.tv_sec = ACK_TIMEOUT; - tv.tv_usec = random_sec(); - trigger_set_timer(&tv, timeout_ack_refresh, ctr); - break; - - - case I3_OPT_TRIGGER_ACK: - ctr = cl_get_trigger_from_list( - ctx->trigger_htable[CL_HASH_TRIG(&t->id)], t); - if (NULL == ctr) { - I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, - "Ignoring reply to a removed trigger\n"); - break; - } - - if (ctr->status == CL_TRIGGER_STATUS_PENDING || - ctr->status == CL_TRIGGER_STATUS_IDLE) { - ctr->status = CL_TRIGGER_STATUS_INSERTED; - ctr->retries_cnt = 0; - cl_trigger_callback(ctx, ctr, CL_CBK_TRIGGER_INSERTED, NULL, NULL); - } - - cl_trigger_callback(ctx, ctr, - CL_INTERNAL_HOOK_TRIGGER_REFRESH_TIMEOUT, NULL, NULL); - - /* set ack timeout */ - tv.tv_sec = TRIGGER_REFRESH_PERIOD - ACK_TIMEOUT*MAX_NUM_TRIG_RETRIES; - tv.tv_usec = random_sec(); - trigger_set_timer(&tv, timeout_ack_refresh, ctr); - break; - - case I3_OPT_CONSTRAINT_FAILED: - ctr = cl_get_trigger_from_list( - ctx->trigger_htable[CL_HASH_TRIG(&t->id)], t); - cl_trigger_callback(ctx, ctr, - CL_CBK_TRIGGER_CONSTRAINT_FAILED, NULL, NULL); - break; - - case I3_OPT_ROUTE_BROKEN: - ctr = cl_get_trigger_from_list( - ctx->trigger_htable[CL_HASH_TRIG(&t->id)], t); - cl_trigger_callback(ctx, ctr, CL_CBK_ROUTE_BROKEN, NULL, NULL); - break; - - case I3_OPT_CACHE_ADDR: - case I3_OPT_CACHE_SHORTCUT_ADDR: - case I3_OPT_CACHE_DEST_ADDR: - { - cl_id *cid=NULL; - - if (t->to->type == I3_ADDR_TYPE_IPv4) { - if ((cid = cl_update_id(ctx, &t->id, opt_type, - &t->to->t.v4.addr, - t->to->t.v4.port, faddr)) == NULL) - cid = cl_create_id(ctx, &t->id, opt_type, - &t->to->t.v4.addr, t->to->t.v4.port, faddr); - } else if (t->to->type == I3_ADDR_TYPE_IPv4_NAT) { - if ((cid = cl_update_id(ctx, &t->id, opt_type, - &t->to->t.v4_nat.nat_addr, - t->to->t.v4_nat.nat_port, faddr)) == NULL) - cid = cl_create_id(ctx, &t->id, opt_type, - &t->to->t.v4_nat.nat_addr, - t->to->t.v4_nat.nat_port, faddr); - } - if (opt_type == I3_OPT_CACHE_DEST_ADDR) { - /* ask for I3_OPT_REQUEST_FOR_SHORTCUT */ - cl_send_request_for_shortcut(ctx, cid, 1); - } - } - break; - case I3_OPT_REQUEST_FOR_CACHE_SHORTCUT: - case I3_OPT_REQUEST_FOR_CACHE_SHORTCUT_INDIR: - ; - - default: - I3_PRINT_DEBUG1(I3_DEBUG_LEVEL_MINIMAL, - "process_trigger_option: unknown option %d\n", opt_type); - } -} - - -void cl_process_option_list(cl_context *ctx, i3_header *hdr, - struct sockaddr_in *fromaddr) -{ - i3_option *option; - cl_id *cid; - i3_addr *ret_a = NULL; - i3_option_list *ol = hdr->option_list; - - /* When client reeives a i3_opt_force_cache_addr, - * it updates its cache, before processing other options in the message. - */ - for (option = ol->head; option; option = option->next) { - i3_trigger *t; - - switch (option->type) { - case I3_OPT_FORCE_CACHE_ADDR: - t = option->entry.trigger; - if (t->to->type == I3_ADDR_TYPE_IPv4) - cl_update_id(ctx, &t->id, I3_OPT_FORCE_CACHE_ADDR, - &t->to->t.v4.addr, t->to->t.v4.port, fromaddr); - break; - case I3_OPT_SENDER: - /* this is the sender address, where replies are sent */ - ret_a = option->entry.ret_addr; - break; - default: - break; - } - } - for (option = ol->head; option; option = option->next) { - switch (option->type) { + int idx; + cl_trigger *ctr; + + for (idx = 0; idx < CL_HTABLE_SIZE; idx++) { + for (ctr = ctx->trigger_htable[idx]; ctr; ctr = ctr->next) { + if (I3_ADDR_TYPE_IPv4 == ctr->t->to->type) { + /* (i) update addr */ + ctr->t->to->t.v4.addr = ctx->local_ip_addr; + + /* (ii) invalidate */ + ctr->is_queued = FALSE; + ctr->retries_cnt = 0; + free(ctr->precomputed_pkt.p); + ctr->precomputed_pkt.p = NULL; + + /* (iii) re-insert in i3 */ + cl_insert_trigger_into_i3(ctx, ctr); + } + } + } +} + +void process_trigger_option(cl_context *ctx, i3_trigger *t, + int opt_type, struct sockaddr_in *fromaddr) +{ + cl_trigger *ctr; + int refresh; + struct timeval tv; + struct sockaddr_in *faddr = fromaddr; + + assert(ctx != NULL); + + switch (opt_type) { case I3_OPT_TRIGGER_CHALLENGE: + + ctr = cl_get_trigger_from_list( + ctx->trigger_htable[CL_HASH_TRIG(&t->id)], t); + + if (NULL == ctr) { + #ifdef CONFIG_HIP_DEBUG + { + char tmpIdStr[100]; + I3_PRINT_DEBUG1(I3_DEBUG_LEVEL_MINIMAL, + "Ignoring reply to a removed trigger with id %s\n", + sprintf_i3_id(tmpIdStr, &(t->id))); + } + #endif + break; + } + + memcpy((char *) ctr->t->nonce, (char *) t->nonce, NONCE_LEN); + + /* check whether this trigger has been already precomputed */ + if (ctr->precomputed_pkt.p) { + free(ctr->precomputed_pkt.p); + } + + cl_make_trigger_packet(ctx, ctr->t, I3_OPT_TRIGGER_INSERT, + &ctr->precomputed_pkt); + + cl_sendto(ctx, ctr->precomputed_pkt.p, + ctr->precomputed_pkt.len, + cl_get_valid_id(ctx, &t->id, &refresh), &t->id); + + cl_trigger_callback(ctx, ctr, + CL_INTERNAL_HOOK_TRIGGER_ACK_TIMEOUT, NULL, NULL); + /* set ack timeout */ + tv.tv_sec = ACK_TIMEOUT; + tv.tv_usec = random_sec(); + trigger_set_timer(&tv, timeout_ack_refresh, ctr); + break; + + case I3_OPT_TRIGGER_ACK: + ctr = cl_get_trigger_from_list( + ctx->trigger_htable[CL_HASH_TRIG(&t->id)], t); + if (NULL == ctr) { + I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, + "Ignoring reply to a removed trigger\n"); + break; + } + + if (ctr->status == CL_TRIGGER_STATUS_PENDING || + ctr->status == CL_TRIGGER_STATUS_IDLE) { + ctr->status = CL_TRIGGER_STATUS_INSERTED; + ctr->retries_cnt = 0; + cl_trigger_callback(ctx, ctr, CL_CBK_TRIGGER_INSERTED, NULL, NULL); + } + + cl_trigger_callback(ctx, ctr, + CL_INTERNAL_HOOK_TRIGGER_REFRESH_TIMEOUT, NULL, NULL); + + /* set ack timeout */ + tv.tv_sec = TRIGGER_REFRESH_PERIOD - ACK_TIMEOUT * MAX_NUM_TRIG_RETRIES; + tv.tv_usec = random_sec(); + trigger_set_timer(&tv, timeout_ack_refresh, ctr); + break; + case I3_OPT_CONSTRAINT_FAILED: + ctr = cl_get_trigger_from_list( + ctx->trigger_htable[CL_HASH_TRIG(&t->id)], t); + cl_trigger_callback(ctx, ctr, + CL_CBK_TRIGGER_CONSTRAINT_FAILED, NULL, NULL); + break; + + case I3_OPT_ROUTE_BROKEN: + ctr = cl_get_trigger_from_list( + ctx->trigger_htable[CL_HASH_TRIG(&t->id)], t); + cl_trigger_callback(ctx, ctr, CL_CBK_ROUTE_BROKEN, NULL, NULL); + break; + case I3_OPT_CACHE_ADDR: + case I3_OPT_CACHE_SHORTCUT_ADDR: case I3_OPT_CACHE_DEST_ADDR: - case I3_OPT_CACHE_SHORTCUT_ADDR: - case I3_OPT_ROUTE_BROKEN: - process_trigger_option(ctx, option->entry.trigger, - option->type, fromaddr); - break; + { + cl_id *cid = NULL; + + if (t->to->type == I3_ADDR_TYPE_IPv4) { + if ((cid = cl_update_id(ctx, &t->id, opt_type, + &t->to->t.v4.addr, + t->to->t.v4.port, faddr)) == NULL) { + cid = cl_create_id(ctx, &t->id, opt_type, + &t->to->t.v4.addr, t->to->t.v4.port, faddr); + } + } else if (t->to->type == I3_ADDR_TYPE_IPv4_NAT) { + if ((cid = cl_update_id(ctx, &t->id, opt_type, + &t->to->t.v4_nat.nat_addr, + t->to->t.v4_nat.nat_port, faddr)) == NULL) { + cid = cl_create_id(ctx, &t->id, opt_type, + &t->to->t.v4_nat.nat_addr, + t->to->t.v4_nat.nat_port, faddr); + } + } + if (opt_type == I3_OPT_CACHE_DEST_ADDR) { + /* ask for I3_OPT_REQUEST_FOR_SHORTCUT */ + cl_send_request_for_shortcut(ctx, cid, 1); + } + } + break; + case I3_OPT_REQUEST_FOR_CACHE_SHORTCUT: case I3_OPT_REQUEST_FOR_CACHE_SHORTCUT_INDIR: - cl_send_opt_cache_address_indir(ctx, hdr->stack->ids, - ID_LEN_BITS, ret_a); - break; - case I3_OPT_REQUEST_FOR_CACHE_SHORTCUT: - cl_send_opt_cache_address(ctx, hdr->stack->ids, ID_LEN_BITS, fromaddr); - break; - case I3_OPT_TRIGGER_NOT_PRESENT: - /* trigger not present */ - cid = cl_get_id_from_list(ctx->id_htable[CL_HASH_ID(option->entry.id)], - option->entry.id); - cl_id_callback(ctx, CL_CBK_TRIGGER_NOT_FOUND, - option->entry.id, NULL, NULL); - break; - case I3_OPT_TRIGGER_RATELIMIT: - /* trigger not present */ - cid = cl_get_id_from_list(ctx->id_htable[CL_HASH_ID(option->entry.id)], - option->entry.id); - cl_id_callback(ctx, CL_CBK_RATELIMIT_EXCEEDED, - option->entry.id, NULL, NULL); - break; - case I3_OPT_SENDER: - case I3_OPT_FORCE_CACHE_ADDR: - break; + ; + default: - I3_PRINT_DEBUG1(I3_DEBUG_LEVEL_MINIMAL, - "Invalid option_type = %d\n", option->type); - } - } -} - + I3_PRINT_DEBUG1(I3_DEBUG_LEVEL_MINIMAL, + "process_trigger_option: unknown option %d\n", opt_type); + } +} + +void cl_process_option_list(cl_context *ctx, i3_header *hdr, + struct sockaddr_in *fromaddr) +{ + i3_option *option; + cl_id *cid; + i3_addr *ret_a = NULL; + i3_option_list *ol = hdr->option_list; + + /* When client reeives a i3_opt_force_cache_addr, + * it updates its cache, before processing other options in the message. + */ + for (option = ol->head; option; option = option->next) { + i3_trigger *t; + + switch (option->type) { + case I3_OPT_FORCE_CACHE_ADDR: + t = option->entry.trigger; + if (t->to->type == I3_ADDR_TYPE_IPv4) { + cl_update_id(ctx, &t->id, I3_OPT_FORCE_CACHE_ADDR, + &t->to->t.v4.addr, t->to->t.v4.port, fromaddr); + } + break; + case I3_OPT_SENDER: + /* this is the sender address, where replies are sent */ + ret_a = option->entry.ret_addr; + break; + default: + break; + } + } + for (option = ol->head; option; option = option->next) { + switch (option->type) { + case I3_OPT_TRIGGER_CHALLENGE: + case I3_OPT_TRIGGER_ACK: + case I3_OPT_CONSTRAINT_FAILED: + case I3_OPT_CACHE_ADDR: + case I3_OPT_CACHE_DEST_ADDR: + case I3_OPT_CACHE_SHORTCUT_ADDR: + case I3_OPT_ROUTE_BROKEN: + process_trigger_option(ctx, option->entry.trigger, + option->type, fromaddr); + break; + case I3_OPT_REQUEST_FOR_CACHE_SHORTCUT_INDIR: + cl_send_opt_cache_address_indir(ctx, hdr->stack->ids, + ID_LEN_BITS, ret_a); + break; + case I3_OPT_REQUEST_FOR_CACHE_SHORTCUT: + cl_send_opt_cache_address(ctx, hdr->stack->ids, ID_LEN_BITS, fromaddr); + break; + case I3_OPT_TRIGGER_NOT_PRESENT: + /* trigger not present */ + cid = cl_get_id_from_list(ctx->id_htable[CL_HASH_ID(option->entry.id)], + option->entry.id); + cl_id_callback(ctx, CL_CBK_TRIGGER_NOT_FOUND, + option->entry.id, NULL, NULL); + break; + case I3_OPT_TRIGGER_RATELIMIT: + /* trigger not present */ + cid = cl_get_id_from_list(ctx->id_htable[CL_HASH_ID(option->entry.id)], + option->entry.id); + cl_id_callback(ctx, CL_CBK_RATELIMIT_EXCEEDED, + option->entry.id, NULL, NULL); + break; + case I3_OPT_SENDER: + case I3_OPT_FORCE_CACHE_ADDR: + break; + default: + I3_PRINT_DEBUG1(I3_DEBUG_LEVEL_MINIMAL, + "Invalid option_type = %d\n", option->type); + } + } +} /* create trigger packet -- trigger is not freed here */ -void cl_make_trigger_packet(cl_context *ctx, i3_trigger *t, - char opt_type, buf_struct *buf) +void cl_make_trigger_packet(cl_context *ctx, i3_trigger *t, + char opt_type, buf_struct *buf) { - i3_addr *a; - i3_option *o; - i3_option_list *ol; - i3_stack *s; - i3_header *h; - - ol = alloc_i3_option_list(); - - if (opt_type != I3_OPT_TRIGGER_REMOVE) { - /* create ID_OPT_SENDER to tell the i3 server where to reply with - * an ack or challenge message - */ - a = alloc_i3_addr(); - init_i3_addr_ipv4(a, ctx->local_ip_addr, ctx->local_port); - o = alloc_i3_option(); - init_i3_option(o, I3_OPT_SENDER, (void *)a); + i3_addr *a; + i3_option *o; + i3_option_list *ol; + i3_stack *s; + i3_header *h; + + ol = alloc_i3_option_list(); + + if (opt_type != I3_OPT_TRIGGER_REMOVE) { + /* create ID_OPT_SENDER to tell the i3 server where to reply with + * an ack or challenge message + */ + a = alloc_i3_addr(); + init_i3_addr_ipv4(a, ctx->local_ip_addr, ctx->local_port); + o = alloc_i3_option(); + init_i3_option(o, I3_OPT_SENDER, (void *) a); + append_i3_option(ol, o); + } + + /* create "insert trigger" option */ + o = alloc_i3_option(); + init_i3_option(o, opt_type, (void *) duplicate_i3_trigger(t)); append_i3_option(ol, o); - } - - /* create "insert trigger" option */ - o = alloc_i3_option(); - init_i3_option(o, opt_type, (void *)duplicate_i3_trigger(t)); - append_i3_option(ol, o); - - s = alloc_i3_stack(); - init_i3_stack(s, &t->id, 1 /* only one ID in the stack */); - - h = alloc_i3_header(); - init_i3_header(h, FALSE, s, ol); - - buf->len = get_i3_header_len(h); - - if ((buf->p = (char *)malloc(buf->len)) == NULL) - I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, - "cl_make_trigger_packet: memory allocation error\n"); - - pack_i3_header(buf->p, h, &buf->len); - set_first_hop(buf->p); - - free_i3_header(h); + + s = alloc_i3_stack(); + init_i3_stack(s, &t->id, 1 /* only one ID in the stack */); + + h = alloc_i3_header(); + init_i3_header(h, FALSE, s, ol); + + buf->len = get_i3_header_len(h); + + if ((buf->p = (char *) malloc(buf->len)) == NULL) { + I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, + "cl_make_trigger_packet: memory allocation error\n"); + } + + pack_i3_header(buf->p, h, &buf->len); + set_first_hop(buf->p); + + free_i3_header(h); } - /******************************************************************** - * timeout associated with trigger insertion (i.e., chalenge message); - * if timeout, reinsert the trigger - ********************************************************************/ +* timeout associated with trigger insertion (i.e., chalenge message); +* if timeout, reinsert the trigger +********************************************************************/ void timeout_ack_insert(void *ctrx) { - int refresh; - struct timeval tv; - cl_trigger *ctr = (cl_trigger *)ctrx; - cl_context *ctx = ctr->ctx; - - if( ctx->init_tcp_ctx_flag ) { - I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, "Trigger still pending, reinsert it\n"); - - cl_sendto(ctx, ctr->precomputed_pkt.p, - ctr->precomputed_pkt.len, - cl_get_valid_id(ctx, &ctr->t->id, &refresh), - &ctr->t->id); - } - tv.tv_sec = ACK_TIMEOUT; - tv.tv_usec = random_sec(); - trigger_set_timer(&tv, timeout_ack_insert, ctr); + int refresh; + struct timeval tv; + cl_trigger *ctr = (cl_trigger *) ctrx; + cl_context *ctx = ctr->ctx; + + if (ctx->init_tcp_ctx_flag) { + I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, "Trigger still pending, reinsert it\n"); + + cl_sendto(ctx, ctr->precomputed_pkt.p, + ctr->precomputed_pkt.len, + cl_get_valid_id(ctx, &ctr->t->id, &refresh), + &ctr->t->id); + } + tv.tv_sec = ACK_TIMEOUT; + tv.tv_usec = random_sec(); + trigger_set_timer(&tv, timeout_ack_insert, ctr); } - /******************************************************************** - * timeout associated with a trigger refresh message - * if timeout, resend the refresh message - ********************************************************************/ +* timeout associated with a trigger refresh message +* if timeout, resend the refresh message +********************************************************************/ void timeout_ack_refresh(void *ctrx) { - struct timeval tv; - cl_trigger *ctr = (cl_trigger *) ctrx; - cl_context *ctx = ctr->ctx; - int refresh; - - assert(ctr); - - if (ctr->retries_cnt <= MAX_NUM_TRIG_RETRIES) { - cl_sendto(ctx, ctr->precomputed_pkt.p, ctr->precomputed_pkt.len, - cl_get_valid_id(ctx, &ctr->t->id, &refresh), &ctr->t->id); - ctr->retries_cnt++; - tv.tv_sec = ACK_TIMEOUT; - tv.tv_usec = random_sec(); - - cl_trigger_callback(ctx, ctr, - CL_INTERNAL_HOOK_TRIGGER_ACK_TIMEOUT, NULL, NULL); - - } else { - /* refresh failed MAX_NUM_TRIG_RETRIES times; try again later */ - I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_VERBOSE, "Timeout exceeded, resending\n"); - ctr->retries_cnt = 0; - tv.tv_sec = TRIGGER_REFRESH_PERIOD - ACK_TIMEOUT*MAX_NUM_TRIG_RETRIES; - tv.tv_usec = random_sec(); - - cl_trigger_callback(ctx, ctr, - CL_INTERNAL_HOOK_TRIGGER_REFRESH_TIMEOUT, NULL, NULL); - } - trigger_set_timer(&tv, timeout_ack_refresh, ctr); + struct timeval tv; + cl_trigger *ctr = (cl_trigger *) ctrx; + cl_context *ctx = ctr->ctx; + int refresh; + + assert(ctr); + + if (ctr->retries_cnt <= MAX_NUM_TRIG_RETRIES) { + cl_sendto(ctx, ctr->precomputed_pkt.p, ctr->precomputed_pkt.len, + cl_get_valid_id(ctx, &ctr->t->id, &refresh), &ctr->t->id); + ctr->retries_cnt++; + tv.tv_sec = ACK_TIMEOUT; + tv.tv_usec = random_sec(); + + cl_trigger_callback(ctx, ctr, + CL_INTERNAL_HOOK_TRIGGER_ACK_TIMEOUT, NULL, NULL); + } else { + /* refresh failed MAX_NUM_TRIG_RETRIES times; try again later */ + I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_VERBOSE, "Timeout exceeded, resending\n"); + ctr->retries_cnt = 0; + tv.tv_sec = TRIGGER_REFRESH_PERIOD - ACK_TIMEOUT * MAX_NUM_TRIG_RETRIES; + tv.tv_usec = random_sec(); + + cl_trigger_callback(ctx, ctr, + CL_INTERNAL_HOOK_TRIGGER_REFRESH_TIMEOUT, NULL, NULL); + } + trigger_set_timer(&tv, timeout_ack_refresh, ctr); } - void trigger_set_timer(struct timeval *tv, void (*fun)(void *), cl_trigger *ctr) { - /* cancel timer associated to trigger, if any */ - if (ctr->timer) cl_cancel_timer(ctr->timer); - ctr->timer = cl_set_timer(tv, fun, ctr); + /* cancel timer associated to trigger, if any */ + if (ctr->timer) { + cl_cancel_timer(ctr->timer); + } + ctr->timer = cl_set_timer(tv, fun, ctr); } void trigger_cancel_timer(cl_trigger *ctr) { - if (ctr->timer) cl_cancel_timer(ctr->timer); - ctr->timer = NULL; + if (ctr->timer) { + cl_cancel_timer(ctr->timer); + } + ctr->timer = NULL; } === modified file 'i3/i3_client/i3_client_trigger.h' --- i3/i3_client/i3_client_trigger.h 2010-01-06 22:17:32 +0000 +++ i3/i3_client/i3_client_trigger.h 2010-02-11 11:49:47 +0000 @@ -1,14 +1,14 @@ /*************************************************************************** - i3_client_trigger.h - description - ------------------- - begin : Aug 14 2003 - email : istoica@xxxxxxxxxxxxxxx - ***************************************************************************/ +* i3_client_trigger.h - description +* ------------------- +* begin : Aug 14 2003 +* email : istoica@xxxxxxxxxxxxxxx +***************************************************************************/ #ifndef I3_CLIENT_TRIGGER_H #define I3_CLIENT_TRIGGER_H - + /* functions implemented in i3_client_trigger.c */ int cl_insert_trigger_into_i3(cl_context *ctx, cl_trigger *ctr); int cl_remove_trigger_from_i3(cl_context *ctx, cl_trigger *ctr); @@ -23,17 +23,17 @@ void cl_update_triggers(cl_context *ctx); void cl_delete_trigger(cl_context *ctx, cl_trigger *ctr); -cl_trigger *cl_create_trigger_gen(cl_context *ctx, - uint16_t addr_type, - ID *id, uint16_t prefix_len, - struct in_addr ip_addr, uint16_t port, - i3_stack *stack, Key *key, uint16_t); -void process_trigger_option(cl_context *ctx, i3_trigger *t, - int opt_type, struct sockaddr_in *fromaddr); +cl_trigger *cl_create_trigger_gen(cl_context * ctx, + uint16_t addr_type, + ID * id, uint16_t prefix_len, + struct in_addr ip_addr, uint16_t port, + i3_stack * stack, Key * key, uint16_t); +void process_trigger_option(cl_context *ctx, i3_trigger *t, + int opt_type, struct sockaddr_in *fromaddr); void cl_process_option_list(cl_context *ctx, i3_header *hdr, - struct sockaddr_in *fromaddr); -void cl_make_trigger_packet(cl_context *ctx, i3_trigger *t, - char opt_type, buf_struct *buf); + struct sockaddr_in *fromaddr); +void cl_make_trigger_packet(cl_context *ctx, i3_trigger *t, + char opt_type, buf_struct *buf); void timeout_ack_insert(void *ctr); === modified file 'i3/i3_client/i3server_list.c' --- i3/i3_client/i3server_list.c 2010-01-06 22:17:32 +0000 +++ i3/i3_client/i3server_list.c 2010-02-11 11:49:47 +0000 @@ -1,4 +1,4 @@ -/* +/* * Purpose: Maintain list of i3 servers that are active. * Implemented as a hash table + circular array */ @@ -14,34 +14,35 @@ #include <stdio.h> #include <stdlib.h> #ifndef _WIN32 - #include <pthread.h> + #include <pthread.h> #endif #include "../utils/netwrap.h" #ifndef _WIN32 pthread_mutex_t i3server_list_mutex = PTHREAD_MUTEX_INITIALIZER; #else -HANDLE i3server_list_mutex = NULL; +HANDLE i3server_list_mutex = NULL; #endif int i3server_list_lock(void) { #ifndef _WIN32 if (pthread_mutex_lock(&i3server_list_mutex)) { - fprintf(stderr, "i3server_list_mutex: problem with locking mutex\n"); - return 1; + fprintf(stderr, "i3server_list_mutex: problem with locking mutex\n"); + return 1; } #else - WaitForSingleObject(i3server_list_mutex, INFINITE); + WaitForSingleObject(i3server_list_mutex, INFINITE); #endif return 0; } + int i3server_list_unlock(void) { #ifndef _WIN32 if (pthread_mutex_unlock(&i3server_list_mutex)) { - fprintf(stderr, "i3server_list_mutex: problem with unlocking mutex\n"); - return 1; + fprintf(stderr, "i3server_list_mutex: problem with unlocking mutex\n"); + return 1; } #else ReleaseMutex(i3server_list_mutex); @@ -57,41 +58,41 @@ #define AH_MULTIPLIER 31 static uint32_t i3server_hash(uint32_t addr, uint32_t n) { - uint32_t h = 0; - int32_t i; + uint32_t h = 0; + int32_t i; unsigned char *b; - + b = (unsigned char *) &addr; - for (i = 0; i < 4; i++) - h = AH_MULTIPLIER * h + b[i]; - + for (i = 0; i < 4; i++) { + h = AH_MULTIPLIER * h + b[i]; + } + return h % n; } - /*************************************************************************** * Purpose: To initialize an i3server node structure **************************************************************************/ I3ServerListNode *init_i3server_node(uint32_t addr, - uint16_t port, ID id, Coordinates coord) + uint16_t port, ID id, Coordinates coord) { - I3ServerListNode *node; - uint32_t h; - - h = i3server_hash(addr, I3SERVERHASH); - - node = (I3ServerListNode *) malloc(sizeof(I3ServerListNode)); - node->addr = addr; - node->port = port; - node->id = id; - node->coord = coord; + I3ServerListNode *node; + uint32_t h; + + h = i3server_hash(addr, I3SERVERHASH); + + node = (I3ServerListNode *) malloc(sizeof(I3ServerListNode)); + node->addr = addr; + node->port = port; + node->id = id; + node->coord = coord; node->status = I3SERVER_ALIVE; - node->head = 0; node->n = 0; + node->head = 0; + node->n = 0; return node; } - /*************************************************************************** * Purpose: Init i3 server list entries **************************************************************************/ @@ -101,57 +102,57 @@ #ifdef _WIN32 // initialize the mutex object - i3server_list_mutex = CreateMutex(NULL, FALSE, NULL); - if (NULL == i3server_list_mutex) { - // stg: a return value would be nice for error handling... - perror("Unable to create mutex object"); - return; - } + i3server_list_mutex = CreateMutex(NULL, FALSE, NULL); + if (NULL == i3server_list_mutex) { + // stg: a return value would be nice for error handling... + perror("Unable to create mutex object"); + return; + } #endif - + i3server_list_lock(); - - i3list->num_ping_list = 0; - i3list->list = NULL; - for (i = 0; i < I3SERVERHASH; i++) - i3list->hash[i] = NULL; - + + i3list->num_ping_list = 0; + i3list->list = NULL; + for (i = 0; i < I3SERVERHASH; i++) { + i3list->hash[i] = NULL; + } + i3list->num_newservers = 0; - i3list->full_list = NULL; + i3list->full_list = NULL; i3server_list_unlock(); } - /*************************************************************************** * Purpose: Delete i3 servers that are old - * a) delete_i3server_hash -- from hash table - * b) delete_dead_i3servers -- from list + * a) delete_i3server_hash -- from hash table + * b) delete_dead_i3servers -- from list **************************************************************************/ -static I3ServerListNode *delete_i3server_hash(I3ServerList *list, - uint32_t addr, uint16_t port) +static I3ServerListNode *delete_i3server_hash(I3ServerList *list, + uint32_t addr, uint16_t port) { - I3ServerListNode *node, *prev; - uint32_t h; - int deleted_hash = 0; - + I3ServerListNode *node, *prev; + uint32_t h; + int deleted_hash = 0; + h = i3server_hash(addr, I3SERVERHASH); - + for (node = list->hash[h], prev = 0; - node != NULL; - node = node->next_hash) - { - if (addr == node->addr) { - deleted_hash = 1; - if (prev == 0) - list->hash[h] = node->next_hash; - else - prev->next_hash = node->next_hash; - break; - } - prev = node; + node != NULL; + node = node->next_hash) { + if (addr == node->addr) { + deleted_hash = 1; + if (prev == 0) { + list->hash[h] = node->next_hash; + } else { + prev->next_hash = node->next_hash; + } + break; + } + prev = node; } - + assert(1 == deleted_hash); return node; } @@ -159,48 +160,51 @@ void delete_dead_i3servers(I3ServerList *i3list) { I3ServerListNode *curr, *prev; - + i3server_list_lock(); - - prev = NULL; curr = i3list->list; + + prev = NULL; + curr = i3list->list; while (curr != NULL) { - if (I3SERVER_DEAD == curr->status) { - I3ServerListNode *to_delete = curr; - delete_i3server_hash(i3list, curr->addr, curr->port); - if (NULL == prev) { - i3list->list = curr->next_list; - } else { - prev->next_list = curr->next_list; - } - curr = curr->next_list; - free(to_delete); - i3list->num_ping_list--; - } else { - prev = curr; curr = curr->next_list; - } + if (I3SERVER_DEAD == curr->status) { + I3ServerListNode *to_delete = curr; + delete_i3server_hash(i3list, curr->addr, curr->port); + if (NULL == prev) { + i3list->list = curr->next_list; + } else { + prev->next_list = curr->next_list; + } + curr = curr->next_list; + free(to_delete); + i3list->num_ping_list--; + } else { + prev = curr; + curr = curr->next_list; + } } - prev = NULL; curr = i3list->full_list; + prev = NULL; + curr = i3list->full_list; while (curr != NULL) { - if (I3SERVER_DEAD == curr->status) { - I3ServerListNode *to_delete = curr; - if (NULL == prev) { - i3list->full_list = curr->next_list; - } else { - prev->next_list = curr->next_list; - } - curr = curr->next_list; - free(to_delete); - i3list->num_newservers--; - } else { - prev = curr; curr = curr->next_list; - } + if (I3SERVER_DEAD == curr->status) { + I3ServerListNode *to_delete = curr; + if (NULL == prev) { + i3list->full_list = curr->next_list; + } else { + prev->next_list = curr->next_list; + } + curr = curr->next_list; + free(to_delete); + i3list->num_newservers--; + } else { + prev = curr; + curr = curr->next_list; + } } i3server_list_unlock(); } - /*************************************************************************** * Purpose: To update ping list with a node **************************************************************************/ @@ -209,61 +213,60 @@ uint32_t h = i3server_hash(node->addr, I3SERVERHASH); list->num_ping_list++; - + node->next_hash = list->hash[h]; - list->hash[h] = node; - + list->hash[h] = node; + node->next_list = list->list; - list->list = node; + list->list = node; } - /*************************************************************************** * Purpose: Create new entry for a new i3 server **************************************************************************/ I3ServerListNode *create_i3server(I3ServerList *list, - uint32_t addr, uint16_t port, ID id, Coordinates coord) + uint32_t addr, uint16_t port, ID id, Coordinates coord) { I3ServerListNode *node = init_i3server_node(addr, port, id, coord); add_to_ping_list(list, node); return node; } - /*************************************************************************** * Purpose: To update ping information when a packet is received **************************************************************************/ -int update_ping_information(I3ServerList *list, - uint32_t addr, uint16_t seq, uint64_t rtt) +int update_ping_information(I3ServerList *list, + uint32_t addr, uint16_t seq, uint64_t rtt) { - uint32_t h; - I3ServerListNode *node; + uint32_t h; + I3ServerListNode *node; i3server_list_lock(); - + h = i3server_hash(addr, I3SERVERHASH); for (node = list->hash[h]; node != NULL; node = node->next_hash) { - if (addr == node->addr) { - int index = node->head; - node->ping_info[index].seq = seq; - node->ping_info[index].rtt = rtt; - node->head = (node->head + 1) % HISTORY_SIZE; - if (node->n < HISTORY_SIZE) - node->n++; - i3server_list_unlock(); - return 1; - } + if (addr == node->addr) { + int index = node->head; + node->ping_info[index].seq = seq; + node->ping_info[index].rtt = rtt; + node->head = (node->head + 1) % HISTORY_SIZE; + if (node->n < HISTORY_SIZE) { + node->n++; + } + i3server_list_unlock(); + return 1; + } } i3server_list_unlock(); return 0; } - + /************************************************************* * Purpose: Add to full-list of i3servers ************************************************************/ I3ServerListNode *add_to_new_i3servers(I3ServerList *list, - uint32_t addr, uint16_t port, ID id, Coordinates coord) + uint32_t addr, uint16_t port, ID id, Coordinates coord) { I3ServerListNode *node = init_i3server_node(addr, port, id, coord); @@ -277,39 +280,39 @@ /*************************************************************************** * Purpose: Lookup an i3 server from list. If *refresh is TRUE, the - * server entry is refreshed. If entry does not exist, it is created. - * If it is created, refresh remains TRUE, else is set to FALSE. + * server entry is refreshed. If entry does not exist, it is created. + * If it is created, refresh remains TRUE, else is set to FALSE. **************************************************************************/ I3ServerListNode *update_i3server(I3ServerList *list, - uint32_t addr, uint16_t port, ID id, Coordinates coord) + uint32_t addr, uint16_t port, ID id, Coordinates coord) { - uint32_t h; - I3ServerListNode *node; - + uint32_t h; + I3ServerListNode *node; + i3server_list_lock(); h = i3server_hash(addr, I3SERVERHASH); for (node = list->hash[h]; node != NULL; node = node->next_hash) { - if (addr == node->addr) { - node->port = port; - node->id = id; - node->coord = coord; - node->status = I3SERVER_ALIVE; - i3server_list_unlock(); - return node; - } + if (addr == node->addr) { + node->port = port; + node->id = id; + node->coord = coord; + node->status = I3SERVER_ALIVE; + i3server_list_unlock(); + return node; + } } for (node = list->full_list; node != NULL; node = node->next_list) { - if (addr == node->addr) { - node->port = port; - node->id = id; - node->coord = coord; - node->status = I3SERVER_ALIVE; - i3server_list_unlock(); - return node; - } + if (addr == node->addr) { + node->port = port; + node->id = id; + node->coord = coord; + node->status = I3SERVER_ALIVE; + i3server_list_unlock(); + return node; + } } - + i3server_list_unlock(); return add_to_new_i3servers(list, addr, port, id, coord); @@ -317,28 +320,28 @@ I3ServerListNode *lookup_i3server(I3ServerList *list, uint32_t addr) { - uint32_t h; - I3ServerListNode *node; - + uint32_t h; + I3ServerListNode *node; + i3server_list_lock(); h = i3server_hash(addr, I3SERVERHASH); for (node = list->hash[h]; node != NULL; node = node->next_hash) { - if (addr == node->addr) { - i3server_list_unlock(); - return node; - } + if (addr == node->addr) { + i3server_list_unlock(); + return node; + } } for (node = list->full_list; node != NULL; node = node->next_list) { - if (addr == node->addr) { - i3server_list_unlock(); - return node; - } + if (addr == node->addr) { + i3server_list_unlock(); + return node; + } } - + i3server_list_unlock(); - return NULL; + return NULL; } /*************************************************************************** @@ -349,51 +352,50 @@ I3ServerListNode *node; struct in_addr ia; printf("Printing list of all entries\n"); - + for (node = list->list; - node != 0; - node = node->next_list) { - ia.s_addr = htonl(node->addr); - printf("(%s:%d) ", inet_ntoa(ia), node->port); + node != 0; + node = node->next_list) { + ia.s_addr = htonl(node->addr); + printf("(%s:%d) ", inet_ntoa(ia), node->port); } printf("\n"); for (node = list->full_list; - node != 0; - node = node->next_list) { - ia.s_addr = htonl(node->addr); - printf("(%s:%d) ", inet_ntoa(ia), node->port); + node != 0; + node = node->next_list) { + ia.s_addr = htonl(node->addr); + printf("(%s:%d) ", inet_ntoa(ia), node->port); } printf("\n"); } void mark_i3servers_dead(I3ServerList *list) { - I3ServerListNode *node; - + I3ServerListNode *node; + for (node = list->list; - node != NULL; - node = node->next_list) { - node->status = I3SERVER_DEAD; + node != NULL; + node = node->next_list) { + node->status = I3SERVER_DEAD; } for (node = list->full_list; - node != NULL; - node = node->next_list) { - node->status = I3SERVER_DEAD; + node != NULL; + node = node->next_list) { + node->status = I3SERVER_DEAD; } } - /*************************************************************************** * Purpose: get closest node and its rtt - * a) get_rtt -- gets rtt for a single node. picks median of the - * last k tries subject to the fact that loss < THRES_LOSS - * b) get_closest -- - * (i) of all nodes, get lowest rtt - * (ii) get rtt of previous best node + * a) get_rtt -- gets rtt for a single node. picks median of the + * last k tries subject to the fact that loss < THRES_LOSS + * b) get_closest -- + * (i) of all nodes, get lowest rtt + * (ii) get rtt of previous best node **************************************************************************/ -#define MAX_RTT 10*1000000ULL +#define MAX_RTT 10 * 1000000ULL #define THRES_LOSS 0.4 uint64_t get_rtt_node(I3ServerListNode *node) { @@ -401,71 +403,74 @@ int i, start, total; int n_lost = 0, prev_seq; uint64_t median_rtt, rtt_arr[HISTORY_SIZE]; - + if (0 == node->n) { - ia.s_addr = htonl(node->addr); - return MAX_RTT; + ia.s_addr = htonl(node->addr); + return MAX_RTT; } - + /* sort */ - for (i = 0; i < node->n; i++) - rtt_arr[i] = node->ping_info[i].rtt; - qksort(rtt_arr, 0, node->n-1); - median_rtt = rtt_arr[node->n/2]; - + for (i = 0; i < node->n; i++) { + rtt_arr[i] = node->ping_info[i].rtt; + } + qksort(rtt_arr, 0, node->n - 1); + median_rtt = rtt_arr[node->n / 2]; + /* check number of lost packets */ if (node->n < HISTORY_SIZE) { - i = 0; start = 1; total = node->n-1; + i = 0; + start = 1; + total = node->n - 1; } else { - i = node->head; - start = (node->head + 1) % HISTORY_SIZE; - total = HISTORY_SIZE-1; + i = node->head; + start = (node->head + 1) % HISTORY_SIZE; + total = HISTORY_SIZE - 1; } prev_seq = node->ping_info[i].seq; for (i = 0; i < total; i++) { - int index = (start + i) % HISTORY_SIZE; - n_lost += (node->ping_info[index].seq - prev_seq - 1); - prev_seq = node->ping_info[index].seq; + int index = (start + i) % HISTORY_SIZE; + n_lost += (node->ping_info[index].seq - prev_seq - 1); + prev_seq = node->ping_info[index].seq; } - if (n_lost > (int)(THRES_LOSS * HISTORY_SIZE)) { - I3_PRINT_DEBUG2(I3_DEBUG_LEVEL_MINIMAL, "Too many losses -- ignoring: %d, %d\n", - n_lost, (int)(THRES_LOSS * HISTORY_SIZE)); - return MAX_RTT; + if (n_lost > (int) (THRES_LOSS * HISTORY_SIZE)) { + I3_PRINT_DEBUG2(I3_DEBUG_LEVEL_MINIMAL, "Too many losses -- ignoring: %d, %d\n", + n_lost, (int) (THRES_LOSS * HISTORY_SIZE)); + return MAX_RTT; } /* return median */ return median_rtt; } - /*************************************************************************** * Purpose: Sort ping-list based on rtt **************************************************************************/ int sort_ping_list(I3ServerList *list, - I3ServerListNode *sorted_list[], uint64_t sorted_rtt[]) + I3ServerListNode *sorted_list[], uint64_t sorted_rtt[]) { - I3ServerListNode *curr; + I3ServerListNode *curr; int num = 0, i, j; uint64_t temp_rtt; - + for (curr = list->list; curr != NULL; curr = curr->next_list) { - sorted_list[num] = curr; - sorted_rtt[num] = get_rtt_node(curr); - num++; - } - - for (i = 1; i < num; i++) - for (j = 0; j < num - i; j++) { - if (sorted_rtt[j] > sorted_rtt[j+1]) { - temp_rtt = sorted_rtt[j]; - sorted_rtt[j] = sorted_rtt[j+1]; - sorted_rtt[j+1] = temp_rtt; - - curr = sorted_list[j]; - sorted_list[j] = sorted_list[j+1]; - sorted_list[j+1] = curr; - } - } + sorted_list[num] = curr; + sorted_rtt[num] = get_rtt_node(curr); + num++; + } + + for (i = 1; i < num; i++) { + for (j = 0; j < num - i; j++) { + if (sorted_rtt[j] > sorted_rtt[j + 1]) { + temp_rtt = sorted_rtt[j]; + sorted_rtt[j] = sorted_rtt[j + 1]; + sorted_rtt[j + 1] = temp_rtt; + + curr = sorted_list[j]; + sorted_list[j] = sorted_list[j + 1]; + sorted_list[j + 1] = curr; + } + } + } return num; } @@ -473,38 +478,39 @@ /*************************************************************************** * Purpose: Sort full-list based on coordinates **************************************************************************/ -int sort_coord(I3ServerList *list, I3ServerListNode *sorted_list[], - float sorted_rtt[]) +int sort_coord(I3ServerList *list, I3ServerListNode *sorted_list[], + float sorted_rtt[]) { - I3ServerListNode *curr; + I3ServerListNode *curr; int num = 0, i, j; uint64_t temp_rtt; - + for (curr = list->full_list; curr != NULL; curr = curr->next_list) { - assert(num < MAX_I3_SERVER_LIST_SIZE); - sorted_list[num] = curr; - sorted_rtt[num] = coordinates_distance(curr->coord); - ++num; - } - - for (i = 1; i < num; ++i) - for (j = 0; j < num - i; ++j) { - if (sorted_rtt[j] > sorted_rtt[j+1]) { - temp_rtt = sorted_rtt[j]; - sorted_rtt[j] = sorted_rtt[j+1]; - sorted_rtt[j+1] = temp_rtt; - - curr = sorted_list[j]; - sorted_list[j] = sorted_list[j+1]; - sorted_list[j+1] = curr; - } - } + assert(num < MAX_I3_SERVER_LIST_SIZE); + sorted_list[num] = curr; + sorted_rtt[num] = coordinates_distance(curr->coord); + ++num; + } + + for (i = 1; i < num; ++i) { + for (j = 0; j < num - i; ++j) { + if (sorted_rtt[j] > sorted_rtt[j + 1]) { + temp_rtt = sorted_rtt[j]; + sorted_rtt[j] = sorted_rtt[j + 1]; + sorted_rtt[j + 1] = temp_rtt; + + curr = sorted_list[j]; + sorted_list[j] = sorted_list[j + 1]; + sorted_list[j + 1] = curr; + } + } + } return num; } int get_top_k(I3ServerList *list, int k, - uint32_t best_addr[], uint16_t best_port[], uint64_t best_rtt[]) + uint32_t best_addr[], uint16_t best_port[], uint64_t best_rtt[]) { I3ServerListNode *sorted_list[MAX_PING_LIST_SIZE]; uint64_t sorted_rtt[MAX_PING_LIST_SIZE]; @@ -513,36 +519,37 @@ i3server_list_lock(); num = sort_ping_list(list, sorted_list, sorted_rtt); i3server_list_unlock(); - + for (i = 0; i < num; i++) { - if (i >= k) - return k; - best_addr[i] = sorted_list[i]->addr; - best_port[i] = sorted_list[i]->port; - best_rtt[i] = sorted_rtt[i]; + if (i >= k) { + return k; + } + best_addr[i] = sorted_list[i]->addr; + best_port[i] = sorted_list[i]->port; + best_rtt[i] = sorted_rtt[i]; } return num; } uint64_t get_rtt(I3ServerList *list, uint32_t addr) { - uint32_t h; - I3ServerListNode *node; - + uint32_t h; + I3ServerListNode *node; + i3server_list_lock(); h = i3server_hash(addr, I3SERVERHASH); for (node = list->hash[h]; node != NULL; node = node->next_hash) { - if (addr == node->addr) { - i3server_list_unlock(); - return get_rtt_node(node); - } + if (addr == node->addr) { + i3server_list_unlock(); + return get_rtt_node(node); + } } i3server_list_unlock(); return MAX_RTT; } int get_top_k_id(I3ServerList *list, int k, - ID best_id[], uint64_t best_rtt[]) + ID best_id[], uint64_t best_rtt[]) { I3ServerListNode *sorted_list[MAX_PING_LIST_SIZE]; uint64_t sorted_rtt[MAX_PING_LIST_SIZE]; @@ -551,13 +558,14 @@ i3server_list_lock(); num = sort_ping_list(list, sorted_list, sorted_rtt); i3server_list_unlock(); - + for (i = 0; i < num; i++) { - if (i >= k) - return k; + if (i >= k) { + return k; + } - best_id[i] = sorted_list[i]->id; - best_rtt[i] = sorted_rtt[i]; + best_id[i] = sorted_list[i]->id; + best_rtt[i] = sorted_rtt[i]; } return num; } @@ -568,26 +576,27 @@ int b = compare_ids(middle, end); int c = compare_ids(end, start); - if ((a <= 0 && b < 0) || (a <= 0 && c < 0) || (b < 0 && c < 0)) - return 1; - else - return 0; + if ((a <= 0 && b < 0) || (a <= 0 && c < 0) || (b < 0 && c < 0)) { + return 1; + } else { + return 0; + } } uint64_t get_rtt_id(I3ServerList *list, ID *id) { - int start = 1; - I3ServerListNode *node; + int start = 1; + I3ServerListNode *node; ID closestID; uint64_t closestRTT = MAX_RTT; - + i3server_list_lock(); for (node = list->list; node != NULL; node = node->next_list) { - if (start || is_between(&(node->id), id, &closestID)) { - closestID = node->id; - closestRTT = get_rtt_node(node); - start = 0; - } + if (start || is_between(&(node->id), id, &closestID)) { + closestID = node->id; + closestRTT = get_rtt_node(node); + start = 0; + } } i3server_list_unlock(); return closestRTT; @@ -596,20 +605,22 @@ /*************************************************************************** * Purpose: Find next element in the list that is alive **************************************************************************/ -I3ServerListNode *find_next_alive_ping_list(I3ServerList *list, - I3ServerListNode *curr) +I3ServerListNode *find_next_alive_ping_list(I3ServerList *list, + I3ServerListNode *curr) { while (NULL != curr) { - if (I3SERVER_ALIVE == curr->status) - return curr; - curr = curr->next_list; + if (I3SERVER_ALIVE == curr->status) { + return curr; + } + curr = curr->next_list; } curr = list->list; while (NULL != curr) { - if (I3SERVER_ALIVE == curr->status) - return curr; - curr = curr->next_list; + if (I3SERVER_ALIVE == curr->status) { + return curr; + } + curr = curr->next_list; } return NULL; @@ -623,43 +634,48 @@ I3ServerListNode *sorted_list[MAX_PING_LIST_SIZE], *prev, *curr; uint64_t sorted_rtt[MAX_PING_LIST_SIZE]; int num = 0, i; - + I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_VERBOSE, "Purging from ping list:\n"); - + num = sort_ping_list(list, sorted_list, sorted_rtt); - + for (i = 0; i < num; i++) { - if (i >= MAX_PING_LIST_SIZE - num_remove) - sorted_list[i]->status = I3SERVER_DEAD; - else - sorted_list[i]->status = I3SERVER_ALIVE; + if (i >= MAX_PING_LIST_SIZE - num_remove) { + sorted_list[i]->status = I3SERVER_DEAD; + } else { + sorted_list[i]->status = I3SERVER_ALIVE; + } } - prev = NULL; curr = list->list; + prev = NULL; + curr = list->list; while (curr != NULL) { - if (I3SERVER_DEAD == curr->status) { - I3ServerListNode *to_move = curr; - struct in_addr ia; - - ia.s_addr = htonl(curr->addr); - I3_PRINT_DEBUG1(I3_DEBUG_LEVEL_VERBOSE, "%s\n", inet_ntoa(ia)); - - delete_i3server_hash(list, curr->addr, curr->port); - if (NULL == prev) list->list = curr->next_list; - else prev->next_list = curr->next_list; - curr = curr->next_list; - list->num_ping_list--; - - to_move->next_list = list->full_list; - list->full_list = to_move; - list->num_newservers++; - } else { - prev = curr; curr = curr->next_list; - } + if (I3SERVER_DEAD == curr->status) { + I3ServerListNode *to_move = curr; + struct in_addr ia; + + ia.s_addr = htonl(curr->addr); + I3_PRINT_DEBUG1(I3_DEBUG_LEVEL_VERBOSE, "%s\n", inet_ntoa(ia)); + + delete_i3server_hash(list, curr->addr, curr->port); + if (NULL == prev) { + list->list = curr->next_list; + } else { prev->next_list = curr->next_list; + } + curr = curr->next_list; + list->num_ping_list--; + + to_move->next_list = list->full_list; + list->full_list = to_move; + list->num_newservers++; + } else { + prev = curr; + curr = curr->next_list; + } } I3_PRINT_DEBUG2(I3_DEBUG_LEVEL_VERBOSE, "After purge (ping list = %d, rest = %d)\n", - list->num_ping_list, list->num_newservers); + list->num_ping_list, list->num_newservers); } /**************************************************************** @@ -674,54 +690,58 @@ I3ServerListNode *sorted_list[MAX_I3_SERVER_LIST_SIZE]; float sorted_coord_dist[MAX_I3_SERVER_LIST_SIZE]; - /* sort the servers based on synthetic coordinates - * and mark the servers that need to be added using + /* sort the servers based on synthetic coordinates + * and mark the servers that need to be added using * I3SERVER_ALIVE */ - num = sort_coord(list, sorted_list, sorted_coord_dist); + num = sort_coord(list, sorted_list, sorted_coord_dist); num_added = MIN(num, MAX_PING_LIST_SIZE - list->num_ping_list); for (i = 0; i < num; i++) { - if (i < num_added) - sorted_list[i]->status = I3SERVER_ALIVE; - else - sorted_list[i]->status = I3SERVER_DEAD; + if (i < num_added) { + sorted_list[i]->status = I3SERVER_ALIVE; + } else { + sorted_list[i]->status = I3SERVER_DEAD; + } } /* pick top based on sorted synthetic coordinates */ i3server_list_lock(); I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_VERBOSE, "Adding servers:\n"); - - curr = list->full_list; prev = NULL; + + curr = list->full_list; + prev = NULL; while (NULL != curr) { - I3ServerListNode *tomove = curr; - struct in_addr ia; - - /* ignore if it is not in top k */ - if (I3SERVER_DEAD == curr->status) { - prev = curr; curr = curr->next_list; - continue; - } - - /* remove node from new list */ - curr = curr->next_list; - if (NULL == prev) { - list->full_list = curr; - } else { - prev->next_list = curr; - } - list->num_newservers--; - - /* add node to list */ - tomove->head = 0; tomove->n = 0; - add_to_ping_list(list, tomove); - - ia.s_addr = htonl(tomove->addr); - I3_PRINT_DEBUG1(I3_DEBUG_LEVEL_VERBOSE, "%s\n", inet_ntoa(ia)); + I3ServerListNode *tomove = curr; + struct in_addr ia; + + /* ignore if it is not in top k */ + if (I3SERVER_DEAD == curr->status) { + prev = curr; + curr = curr->next_list; + continue; + } + + /* remove node from new list */ + curr = curr->next_list; + if (NULL == prev) { + list->full_list = curr; + } else { + prev->next_list = curr; + } + list->num_newservers--; + + /* add node to list */ + tomove->head = 0; + tomove->n = 0; + add_to_ping_list(list, tomove); + + ia.s_addr = htonl(tomove->addr); + I3_PRINT_DEBUG1(I3_DEBUG_LEVEL_VERBOSE, "%s\n", inet_ntoa(ia)); } i3server_list_unlock(); *next_ping = list->list; } - + /**************************************************************** * Fill up the ping list * - closeness based on euclidean dist over the coordinate space @@ -734,12 +754,14 @@ /* Not particularly random, but good enough */ num = MAX_PING_LIST_SIZE - list->num_ping_list; if (list->num_newservers > 0) { - r = rand() % list->num_newservers; - node = list->full_list; prev = NULL; - - I3_PRINT_DEBUG2(I3_DEBUG_LEVEL_VERBOSE, - "Num full servers = %d, r = %d\n", list->num_newservers, r); - for (i = 0; i < r; prev = node, node = node->next_list, ++i) {} + r = rand() % list->num_newservers; + node = list->full_list; + prev = NULL; + + I3_PRINT_DEBUG2(I3_DEBUG_LEVEL_VERBOSE, + "Num full servers = %d, r = %d\n", list->num_newservers, r); + for (i = 0; i < r; prev = node, node = node->next_list, ++i) { + } } i3server_list_lock(); @@ -747,37 +769,39 @@ num_added = 0; while (list->num_newservers > 0) { - I3ServerListNode *tomove; - struct in_addr ia; - - /* done adding enough servers */ - if (num_added >= num) - break; - - /* end of list reached, go to start */ - if (NULL == node) { - node = list->full_list; - prev = NULL; - } - tomove = node; - node = node->next_list; - - /* remove node from new list */ - if (NULL == prev) { - list->full_list = node; - } else { - prev->next_list = node; - } - list->num_newservers--; - - /* add node to list */ - tomove->head = 0; tomove->n = 0; - add_to_ping_list(list, tomove); - - ia.s_addr = htonl(tomove->addr); - I3_PRINT_DEBUG1(I3_DEBUG_LEVEL_VERBOSE, "%s\n", inet_ntoa(ia)); - - num_added++; + I3ServerListNode *tomove; + struct in_addr ia; + + /* done adding enough servers */ + if (num_added >= num) { + break; + } + + /* end of list reached, go to start */ + if (NULL == node) { + node = list->full_list; + prev = NULL; + } + tomove = node; + node = node->next_list; + + /* remove node from new list */ + if (NULL == prev) { + list->full_list = node; + } else { + prev->next_list = node; + } + list->num_newservers--; + + /* add node to list */ + tomove->head = 0; + tomove->n = 0; + add_to_ping_list(list, tomove); + + ia.s_addr = htonl(tomove->addr); + I3_PRINT_DEBUG1(I3_DEBUG_LEVEL_VERBOSE, "%s\n", inet_ntoa(ia)); + + num_added++; } i3server_list_unlock(); @@ -785,18 +809,18 @@ } /*********************************************************** - * Update ping-list: + * Update ping-list: * - remove high latency servers - * - introduce servers that are good + * - introduce servers that are good **********************************************************/ -void change_ping_list(I3ServerList *list, - I3ServerListNode **next_ping, int closest_coordinate) +void change_ping_list(I3ServerList *list, + I3ServerListNode **next_ping, int closest_coordinate) { if (closest_coordinate) { - remove_bad_servers_ping_list(list, MAX_PING_LIST_SIZE); - fill_up_ping_list_closest(list, next_ping); + remove_bad_servers_ping_list(list, MAX_PING_LIST_SIZE); + fill_up_ping_list_closest(list, next_ping); } else { - remove_bad_servers_ping_list(list, NUM_TO_PURGE); - fill_up_ping_list_random(list, next_ping); + remove_bad_servers_ping_list(list, NUM_TO_PURGE); + fill_up_ping_list_random(list, next_ping); } } === modified file 'i3/i3_client/i3server_list.h' --- i3/i3_client/i3server_list.h 2009-12-11 22:49:11 +0000 +++ i3/i3_client/i3server_list.h 2010-02-11 11:49:47 +0000 @@ -1,7 +1,7 @@ #ifndef _HOST_LIST_H -#define _HOST_LIST_H +#define _HOST_LIST_H -#if !defined(_WIN32) +#if !defined(_WIN32) #include <inttypes.h> #else #include "../utils/fwint.h" @@ -9,10 +9,10 @@ #include "../i3/i3.h" #include "coordinates.h" -#define I3SERVERHASH 200 -#define MAX_I3_SERVER_LIST_SIZE 200 -#define MAX_PING_LIST_SIZE 8 -#define NUM_TO_PURGE 2 +#define I3SERVERHASH 200 +#define MAX_I3_SERVER_LIST_SIZE 200 +#define MAX_PING_LIST_SIZE 8 +#define NUM_TO_PURGE 2 #define I3SERVER_ALIVE 1 #define I3SERVER_DEAD 0 @@ -27,54 +27,54 @@ /* Maintain a list of i3 servers as (i) hash table (ii) circular ring */ typedef struct I3ServerListNode { - uint32_t addr; - uint16_t port; - ID id; - int status; // ideally, we should use an assoc array; this is shortcut - - Coordinates coord; - int head, n; - PingInfo ping_info[HISTORY_SIZE]; - - struct I3ServerListNode *next_hash;// next in the chained hash - struct I3ServerListNode *next_list;// next in the list + uint32_t addr; + uint16_t port; + ID id; + int status; // ideally, we should use an assoc array; this is shortcut + + Coordinates coord; + int head, n; + PingInfo ping_info[HISTORY_SIZE]; + + struct I3ServerListNode *next_hash; // next in the chained hash + struct I3ServerListNode *next_list; // next in the list } I3ServerListNode; typedef struct I3ServerList { - int num_ping_list; - I3ServerListNode *hash[I3SERVERHASH]; - I3ServerListNode *list; - - int num_newservers; - I3ServerListNode *full_list; // new servers when getting server list + int num_ping_list; + I3ServerListNode *hash[I3SERVERHASH]; + I3ServerListNode *list; + + int num_newservers; + I3ServerListNode *full_list; // new servers when getting server list } I3ServerList; /* External methods */ void init_i3server_list(I3ServerList *list); I3ServerListNode *lookup_i3server(I3ServerList *list, uint32_t addr); -I3ServerListNode *update_i3server(I3ServerList *list, - uint32_t addr, uint16_t port, ID id, Coordinates coord); +I3ServerListNode *update_i3server(I3ServerList *list, + uint32_t addr, uint16_t port, ID id, Coordinates coord); I3ServerListNode *add_to_new_i3servers(I3ServerList *list, - uint32_t addr, uint16_t port, ID id, Coordinates coord); + uint32_t addr, uint16_t port, ID id, Coordinates coord); I3ServerListNode *create_i3server(I3ServerList *list, - uint32_t addr, uint16_t port, ID id, Coordinates coord); -void change_ping_list(I3ServerList *list, - I3ServerListNode **next_ping, int closest_coordinate); + uint32_t addr, uint16_t port, ID id, Coordinates coord); +void change_ping_list(I3ServerList *list, + I3ServerListNode **next_ping, int closest_coordinate); int is_empty_new_i3servers(I3ServerList *list); void delete_dead_i3servers(I3ServerList *list); -int update_ping_information(I3ServerList *list, - uint32_t addr, uint16_t seq, uint64_t rtt); +int update_ping_information(I3ServerList *list, + uint32_t addr, uint16_t seq, uint64_t rtt); void mark_i3servers_dead(I3ServerList *list); void print_i3servers(I3ServerList *list); -int get_top_k(I3ServerList *list, int k, - uint32_t best_addr[], uint16_t best_port[], uint64_t best_rtt[]); +int get_top_k(I3ServerList * list, int k, + uint32_t best_addr[], uint16_t best_port[], uint64_t best_rtt[]); uint64_t get_rtt_node(I3ServerListNode *node); uint64_t get_rtt(I3ServerList *list, uint32_t addr); uint64_t get_rtt_id(I3ServerList *list, ID *id); -int get_top_k_id(I3ServerList *list, int k, ID best_id[], uint64_t best_rtt[]); +int get_top_k_id(I3ServerList * list, int k, ID best_id[], uint64_t best_rtt[]); -I3ServerListNode *find_next_alive_ping_list(I3ServerList *list, - I3ServerListNode *curr); +I3ServerListNode *find_next_alive_ping_list(I3ServerList *list, + I3ServerListNode *curr); #endif === modified file 'i3/i3_client/ping.c' --- i3/i3_client/ping.c 2009-12-29 21:08:52 +0000 +++ i3/i3_client/ping.c 2010-02-11 11:49:47 +0000 @@ -17,22 +17,22 @@ { struct sockaddr_in saddr; int ret; - + *sock = socket(AF_INET, SOCK_DGRAM, 0); if (*sock < 0) { - perror("udp socket"); - return -1; + perror("udp socket"); + return -1; } - + saddr.sin_addr.s_addr = htonl(INADDR_ANY); - saddr.sin_family = AF_INET; - saddr.sin_port = htons(0); - ret = bind(*sock, (const struct sockaddr *)&saddr, sizeof(saddr)); + saddr.sin_family = AF_INET; + saddr.sin_port = htons(0); + ret = bind(*sock, (const struct sockaddr *) &saddr, sizeof(saddr)); if (ret != 0) { - perror("bind"); - return -1; + perror("bind"); + return -1; } - + nw_set_nblk(*sock, 1); return 0; @@ -43,113 +43,110 @@ { struct sockaddr_in saddr; int ret; - + *sock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); if (*sock < 0) { - perror("icmp socket"); - return -1; + perror("icmp socket"); + return -1; } - + saddr.sin_addr.s_addr = htonl(INADDR_ANY); - saddr.sin_family = AF_INET; - saddr.sin_port = htons(0); - ret = bind(*sock, (const struct sockaddr *)&saddr, sizeof(saddr)); + saddr.sin_family = AF_INET; + saddr.sin_port = htons(0); + ret = bind(*sock, (const struct sockaddr *) &saddr, sizeof(saddr)); if (ret != 0) { - perror("bind()"); - return -1; + perror("bind()"); + return -1; } - + nw_set_nblk(*sock, 1); return 0; } /* Fill in echo request packet and send to destination */ -int send_echo_request(nw_skt_t socket, uint32_t addr, int seq) +int send_echo_request(nw_skt_t socket, uint32_t addr, int seq) { - EchoRequest echoReq; - static int nId = 1; - int i, nRet; + EchoRequest echoReq; + static int nId = 1; + int i, nRet; struct sockaddr_in to_addr; - + /* fill in echo request packet */ /* header */ - echoReq.icmphdr.type = ICMP_ECHOREQ; - echoReq.icmphdr.code = 0; - echoReq.icmphdr.checksum = 0; - echoReq.icmphdr.id = nId; - echoReq.icmphdr.seq = seq; + echoReq.icmphdr.type = ICMP_ECHOREQ; + echoReq.icmphdr.code = 0; + echoReq.icmphdr.checksum = 0; + echoReq.icmphdr.id = nId; + echoReq.icmphdr.seq = seq; /* target of ICMP ping */ - echoReq.addr = addr; - echoReq.time = wall_time(); + echoReq.addr = addr; + echoReq.time = wall_time(); /* fill random data */ - for (i = 0; i < REQ_DATASIZE; i++) - echoReq.data[i] = (char)n_rand(256); + for (i = 0; i < REQ_DATASIZE; i++) { + echoReq.data[i] = (char) n_rand(256); + } /* compute checksum */ - echoReq.icmphdr.checksum = in_ping_cksum((uint16_t *)&echoReq, - sizeof(EchoRequest)); - + echoReq.icmphdr.checksum = in_ping_cksum((uint16_t *) &echoReq, + sizeof(EchoRequest)); + /* fill address structure */ memset((void *) &to_addr, 0, sizeof(struct sockaddr_in)); - to_addr.sin_family = AF_INET; + to_addr.sin_family = AF_INET; to_addr.sin_addr.s_addr = htonl(addr); - to_addr.sin_port = htons(0); - + to_addr.sin_port = htons(0); + /* Send the echo request */ - nRet = sendto(socket, (void *) &echoReq, sizeof(EchoRequest), 0, - (struct sockaddr *) &to_addr, sizeof(struct sockaddr_in)); - - if (nRet < 0) - perror("icmp sendto()"); + nRet = sendto(socket, (void *) &echoReq, sizeof(EchoRequest), 0, + (struct sockaddr *) &to_addr, sizeof(struct sockaddr_in)); + + if (nRet < 0) { + perror("icmp sendto()"); + } return nRet; } /* Process received ICMP packet: code is self-documenting */ int recv_echo_reply(nw_skt_t s, uint32_t *ret_addr, uint16_t *ret_seq, uint64_t *ret_rtt) -{ +{ IPHdr *iphdr; EchoRequest *echoReply; struct sockaddr_in addr; char data[MAX_PKT_LEN]; int nAddrLen = sizeof(struct sockaddr_in); int nRet; - - nRet = recvfrom(s, (char *)data, MAX_PKT_LEN, - 0, (struct sockaddr *)& addr, (unsigned int*)&nAddrLen); - iphdr = (IPHdr *) data; + + nRet = recvfrom(s, (char *) data, MAX_PKT_LEN, + 0, (struct sockaddr *) &addr, (unsigned int *) &nAddrLen); + iphdr = (IPHdr *) data; echoReply = (EchoRequest *) (data + sizeof(IPHdr)); - + if (nRet < 0) { - perror("echo_reply"); - } - else if (nRet < sizeof(IPHdr) + sizeof(ICMPHdr)) { - I3_PRINT_DEBUG3(I3_DEBUG_LEVEL_MINIMAL, - "Not enough bytes received: ignoring ICMP packet: %d, %d, %d\n", - nRet,sizeof(IPHdr), sizeof(ICMPHdr)); - } - else if ((iphdr->protocol != IPPROTO_ICMP)) { - I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, "Incorrect protocol type received\n"); - } - else if (ntohl(addr.sin_addr.s_addr) != echoReply->addr) { - struct in_addr ia; - ia.s_addr = htonl(echoReply->addr); - I3_PRINT_DEBUG1(I3_DEBUG_LEVEL_VERBOSE, - "Sent address (%s) does not match recv address ", inet_ntoa(ia)); - I3_PRINT_DEBUG1(I3_DEBUG_LEVEL_VERBOSE, "%s\n", inet_ntoa(addr.sin_addr)); - } - else if (echoReply->icmphdr.type != ICMP_ECHOREPLY) { - I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, "Not ECHO_REPLY message: ignoring ICMP packet\n"); - } - else if (nRet >= sizeof(EchoRequest) + sizeof(IPHdr)) { - *ret_rtt = wall_time() - echoReply->time; - *ret_addr = echoReply->addr; - *ret_seq = echoReply->icmphdr.seq; - //printf("IP = %s, RTT = %Ld, Seq = %d\n", - // inet_ntoa(addr.sin_addr), *ret_rtt, *ret_seq); - return 1; + perror("echo_reply"); + } else if (nRet < sizeof(IPHdr) + sizeof(ICMPHdr)) { + I3_PRINT_DEBUG3(I3_DEBUG_LEVEL_MINIMAL, + "Not enough bytes received: ignoring ICMP packet: %d, %d, %d\n", + nRet, sizeof(IPHdr), sizeof(ICMPHdr)); + } else if ((iphdr->protocol != IPPROTO_ICMP)) { + I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, "Incorrect protocol type received\n"); + } else if (ntohl(addr.sin_addr.s_addr) != echoReply->addr) { + struct in_addr ia; + ia.s_addr = htonl(echoReply->addr); + I3_PRINT_DEBUG1(I3_DEBUG_LEVEL_VERBOSE, + "Sent address (%s) does not match recv address ", inet_ntoa(ia)); + I3_PRINT_DEBUG1(I3_DEBUG_LEVEL_VERBOSE, "%s\n", inet_ntoa(addr.sin_addr)); + } else if (echoReply->icmphdr.type != ICMP_ECHOREPLY) { + I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, "Not ECHO_REPLY message: ignoring ICMP packet\n"); + } else if (nRet >= sizeof(EchoRequest) + sizeof(IPHdr)) { + *ret_rtt = wall_time() - echoReply->time; + *ret_addr = echoReply->addr; + *ret_seq = echoReply->icmphdr.seq; + //printf("IP = %s, RTT = %Ld, Seq = %d\n", + // inet_ntoa(addr.sin_addr), *ret_rtt, *ret_seq); + return 1; } else { - I3_PRINT_DEBUG3(I3_DEBUG_LEVEL_MINIMAL, "Not enough bytes received: %d, %d, %d\n", - nRet, sizeof(EchoRequest), sizeof(IPHdr)); + I3_PRINT_DEBUG3(I3_DEBUG_LEVEL_MINIMAL, "Not enough bytes received: %d, %d, %d\n", + nRet, sizeof(EchoRequest), sizeof(IPHdr)); } return 0; @@ -158,32 +155,32 @@ /* IN_CKSUM: Internet checksum routine */ uint16_t in_ping_cksum(uint16_t *addr, int len) { - register int nleft = len; + register int nleft = len; register uint16_t *w = addr; register uint16_t answer; - register int sum = 0; - + register int sum = 0; + /* * Our algorithm is simple, using a 32 bit accumulator (sum), we * add sequential 16 bit words to it, and at the end, fold back * all the carry bits from the top 16 bits into the lower 16 bits. */ - while( nleft > 1 ) { - sum += *w++; - nleft -= 2; + while (nleft > 1) { + sum += *w++; + nleft -= 2; } - + /* mop up an odd byte, if necessary */ if (nleft == 1) { - uint16_t u = 0; - - *(uint8_t *)(&u) = *(uint8_t *)w ; - sum += u; + uint16_t u = 0; + + *(uint8_t *) (&u) = *(uint8_t *) w; + sum += u; } - + /* add back carry outs from top 16 bits to low 16 bits */ - sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */ - sum += (sum >> 16); /* add carry */ - answer = ~sum; /* truncate to 16 bits */ - return (answer); + sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */ + sum += (sum >> 16); /* add carry */ + answer = ~sum; /* truncate to 16 bits */ + return answer; } === modified file 'i3/i3_client/ping.h' --- i3/i3_client/ping.h 2009-12-11 22:49:11 +0000 +++ i3/i3_client/ping.h 2010-02-11 11:49:47 +0000 @@ -13,52 +13,48 @@ #define MAX_PKT_LEN 4096 /* IP Header -- RFC 791 */ -typedef struct IPHdr -{ - uint8_t vihl; // Version and IHL - uint8_t tos; // Type Of Service - uint16_t tlen; // Total Length - uint16_t id; // Identification - uint16_t flagoff;// Flags and Fragment Offset - uint8_t ttl; // Time To Live - uint8_t protocol; // Protocol - uint16_t checksum; // Checksum - struct in_addr src; // Internet Address - Source - struct in_addr dst; // Internet Address - Destination +typedef struct IPHdr { + uint8_t vihl; // Version and IHL + uint8_t tos; // Type Of Service + uint16_t tlen; // Total Length + uint16_t id; // Identification + uint16_t flagoff; // Flags and Fragment Offset + uint8_t ttl; // Time To Live + uint8_t protocol; // Protocol + uint16_t checksum; // Checksum + struct in_addr src; // Internet Address - Source + struct in_addr dst; // Internet Address - Destination } IPHdr; /* ICMP Header - RFC 792 */ -typedef struct ICMPHdr -{ - uint8_t type; // Type - uint8_t code; // Code - uint16_t checksum; // Checksum - uint16_t id; // Identification - uint16_t seq; // Sequence - //char data; // Data +typedef struct ICMPHdr { + uint8_t type; // Type + uint8_t code; // Code + uint16_t checksum; // Checksum + uint16_t id; // Identification + uint16_t seq; // Sequence + //char data; // Data } ICMPHdr; -#define REQ_DATASIZE 64 // Echo Request Data size +#define REQ_DATASIZE 64 // Echo Request Data size /* ICMP Echo Request */ -typedef struct EchoRequest -{ - ICMPHdr icmphdr; - uint32_t addr; - uint64_t time; - char data[REQ_DATASIZE]; +typedef struct EchoRequest { + ICMPHdr icmphdr; + uint32_t addr; + uint64_t time; + char data[REQ_DATASIZE]; } EchoRequest; /* ICMP Echo Reply */ -typedef struct EchoReply -{ - IPHdr iphdr; - ICMPHdr icmphdr; - uint32_t addr; - uint64_t time; - char data[REQ_DATASIZE]; - char filler[256]; +typedef struct EchoReply { + IPHdr iphdr; + ICMPHdr icmphdr; + uint32_t addr; + uint64_t time; + char data[REQ_DATASIZE]; + char filler[256]; } EchoReply; uint16_t in_ping_cksum(uint16_t *addr, int len); === modified file 'i3/i3_client/ping_thread.c' --- i3/i3_client/ping_thread.c 2010-01-06 22:17:32 +0000 +++ i3/i3_client/ping_thread.c 2010-02-11 11:49:47 +0000 @@ -19,49 +19,51 @@ // #define ICMP_PING -#define START_TIME 5 * 60 * 1000000ULL -#define PERIOD_PING_START 10 * 1000000ULL -#define PERIOD_PING_STEADY 50 * 1000000ULL -#define PERIOD_PICK_NEW_SERVER_START 20 * 1000000ULL -#define PERIOD_PICK_NEW_SERVER_STEADY 3 * 60 * 1000000ULL -#define PERIOD_SERVERLIST_WGET 5 * 60 * 1000000ULL -#define PING_STEADY_TIME 5 * 60 * 1000000ULL +#define START_TIME 5 * 60 * 1000000ULL +#define PERIOD_PING_START 10 * 1000000ULL +#define PERIOD_PING_STEADY 50 * 1000000ULL +#define PERIOD_PICK_NEW_SERVER_START 20 * 1000000ULL +#define PERIOD_PICK_NEW_SERVER_STEADY 3 * 60 * 1000000ULL +#define PERIOD_SERVERLIST_WGET 5 * 60 * 1000000ULL +#define PING_STEADY_TIME 5 * 60 * 1000000ULL uint64_t period_ping[2] = {PERIOD_PING_START, PERIOD_PING_STEADY}; uint64_t period_pick_new_server[2] = { - PERIOD_PICK_NEW_SERVER_START, PERIOD_PICK_NEW_SERVER_STEADY}; + PERIOD_PICK_NEW_SERVER_START, PERIOD_PICK_NEW_SERVER_STEADY +}; /** The socket used to listen for ping (ICMP or UDP) replies */ nw_skt_t ping_sock = -1; - + /******************************************************** * Locking for status of ping process *******************************************************/ #ifndef _WIN32 pthread_mutex_t status_mutex = PTHREAD_MUTEX_INITIALIZER; #else -HANDLE status_mutex = NULL; +HANDLE status_mutex = NULL; #endif int status_lock(void) { #ifndef _WIN32 if (pthread_mutex_lock(&status_mutex)) { - fprintf(stderr, "status_mutex: problem with locking mutex\n"); - return 1; + fprintf(stderr, "status_mutex: problem with locking mutex\n"); + return 1; } #else WaitForSingleObject(status_mutex, INFINITE); #endif return 0; } + int status_unlock(void) { #ifndef _WIN32 if (pthread_mutex_unlock(&status_mutex)) { - fprintf(stderr, "status_mutex: problem with unlocking mutex\n"); - return 1; + fprintf(stderr, "status_mutex: problem with unlocking mutex\n"); + return 1; } #else ReleaseMutex(status_mutex); @@ -71,17 +73,19 @@ char is_valid(char type) { - if (PING_STATUS_STEADY == type || PING_STATUS_START == type) - return 1; - else - return 0; + if (PING_STATUS_STEADY == type || PING_STATUS_START == type) { + return 1; + } else { + return 0; + } } void set_status(uint64_t *ping_start_time, uint64_t curr_time) { status_lock(); - if (ping_start_time != NULL) - *ping_start_time = curr_time; + if (ping_start_time != NULL) { + *ping_start_time = curr_time; + } status_unlock(); } @@ -90,9 +94,9 @@ char ret = PING_STATUS_STEADY; status_lock(); if (curr_time - *ping_start_time > PING_STEADY_TIME) { - ret = PING_STATUS_STEADY; + ret = PING_STATUS_STEADY; } else { - ret = PING_STATUS_START; + ret = PING_STATUS_START; } status_unlock(); return ret; @@ -104,112 +108,118 @@ int i; static int seq = 1; struct in_addr ia; - + n = MIN(n, list->num_ping_list); for (i = 0; i < n; i++) { - ia.s_addr = htonl((*node)->addr); - I3_PRINT_DEBUG1(I3_DEBUG_LEVEL_VERBOSE, - "Sending echo request to %s\n", inet_ntoa(ia)); + ia.s_addr = htonl((*node)->addr); + I3_PRINT_DEBUG1(I3_DEBUG_LEVEL_VERBOSE, + "Sending echo request to %s\n", inet_ntoa(ia)); #ifdef ICMP_PING - send_echo_request(sock, (*node)->addr, seq); + send_echo_request(sock, (*node)->addr, seq); #else - i3_echo_request(sock, (*node)->addr, (*node)->port, seq); + i3_echo_request(sock, (*node)->addr, (*node)->port, seq); #endif - - *node = (*node)->next_list; - if (NULL == *node) { - *node = list->list; - seq++; - } + + *node = (*node)->next_list; + if (NULL == *node) { + *node = list->list; + seq++; + } } } /********** Coordinate computation *******************/ #define NUM_LANDMARKS_COORDINATE 10 -#define COORD_INIT_PING_WAIT_TIME 3*1000000ULL +#define COORD_INIT_PING_WAIT_TIME 3 * 1000000ULL /* To determine the coordinates of the local node initially * Ping a subset of nodes and determine coordinates */ void init_coordinates(I3ServerList *list) { - int n = MIN(NUM_LANDMARKS_COORDINATE, list->num_newservers + list->num_ping_list); + int n = MIN(NUM_LANDMARKS_COORDINATE, list->num_newservers + list->num_ping_list); I3ServerListNode *node = list->list, *temp_node; - uint64_t start_time = wall_time(); + uint64_t start_time = wall_time(); Coordinates_RTT coord_rtt[NUM_LANDMARKS_COORDINATE]; - int num_landmarks = 0; int started_full_list = 0; + int num_landmarks = 0; + int started_full_list = 0; struct in_addr ia; nw_skt_t tmp_ping_sock; #ifdef ICMP_PING - if (init_icmp_socket(&tmp_ping_sock) == -1) - abort(); + if (init_icmp_socket(&tmp_ping_sock) == -1) { + abort(); + } #else - if (init_udp_socket(&tmp_ping_sock) == -1) - abort(); + if (init_udp_socket(&tmp_ping_sock) == -1) { + abort(); + } #endif // wait for responses and accumulate // cut and pasted from below - while ((wall_time() - start_time < COORD_INIT_PING_WAIT_TIME) && - (num_landmarks < n)) { - fd_set rset; - struct timeval to; - int ret; - - FD_ZERO(&rset); - - if (!node && !started_full_list) { - node = list-> full_list; - started_full_list = 1; - } - - if (node) { - ia.s_addr = htonl(node->addr); - I3_PRINT_DEBUG1(I3_DEBUG_LEVEL_VERBOSE, - "Sending ICMP echo request to %s\n", inet_ntoa(ia)); + while ((wall_time() - start_time < COORD_INIT_PING_WAIT_TIME) && + (num_landmarks < n)) { + fd_set rset; + struct timeval to; + int ret; + + FD_ZERO(&rset); + + if (!node && !started_full_list) { + node = list->full_list; + started_full_list = 1; + } + + if (node) { + ia.s_addr = htonl(node->addr); + I3_PRINT_DEBUG1(I3_DEBUG_LEVEL_VERBOSE, + "Sending ICMP echo request to %s\n", inet_ntoa(ia)); #ifdef ICMP_PING - send_echo_request(tmp_ping_sock, node->addr, 0); + send_echo_request(tmp_ping_sock, node->addr, 0); #else - i3_echo_request(tmp_ping_sock, node->addr, node->port, 0); + i3_echo_request(tmp_ping_sock, node->addr, node->port, 0); #endif - node = node->next_list; - } + node = node->next_list; + } - FD_SET(tmp_ping_sock, &rset); - to.tv_sec = 0; to.tv_usec = 200000ULL; - if ((ret = select(tmp_ping_sock+1, &rset, NULL, NULL, &to)) < 0) { - int err = nw_error(); - if (err == EINTR) + FD_SET(tmp_ping_sock, &rset); + to.tv_sec = 0; + to.tv_usec = 200000ULL; + if ((ret = select(tmp_ping_sock + 1, &rset, NULL, NULL, &to)) < 0) { + int err = nw_error(); + if (err == EINTR) { continue; - else { + } else { perror("select"); abort(); } } - // message received on icmp socket - if (FD_ISSET(tmp_ping_sock, &rset)) { - uint32_t addr; uint16_t port, seq; uint64_t rtt; + // message received on icmp socket + if (FD_ISSET(tmp_ping_sock, &rset)) { + uint32_t addr; + uint16_t port, seq; + uint64_t rtt; #ifdef ICMP_PING - if (recv_echo_reply(tmp_ping_sock, &addr, &seq, &rtt)) { + if (recv_echo_reply(tmp_ping_sock, &addr, &seq, &rtt)) { #else - if (recv_i3_echo_reply(tmp_ping_sock, &addr, &port, &seq, &rtt)) { + if (recv_i3_echo_reply(tmp_ping_sock, &addr, &port, &seq, &rtt)) { #endif - temp_node = lookup_i3server(list, addr); - assert(NULL != temp_node); - - coord_rtt[num_landmarks].coord = temp_node->coord; - coord_rtt[num_landmarks].rtt = rtt; - num_landmarks++; - - ia.s_addr = htonl(addr); - I3_PRINT_DEBUG4(I3_DEBUG_LEVEL_VERBOSE, - "Node: %s Coordinate: %.1f:%.1f RTT: %Ld\n", - inet_ntoa(ia), temp_node->coord.latitude, - temp_node->coord.longitude, rtt); - } - } + temp_node = lookup_i3server(list, addr); + assert(NULL != temp_node); + + coord_rtt[num_landmarks].coord = temp_node->coord; + coord_rtt[num_landmarks].rtt = rtt; + num_landmarks++; + + ia.s_addr = htonl(addr); + I3_PRINT_DEBUG4(I3_DEBUG_LEVEL_VERBOSE, + "Node: %s Coordinate: %.1f:%.1f RTT: %Ld\n", + inet_ntoa(ia), temp_node->coord.latitude, + temp_node->coord.longitude, rtt); + } + } } nw_close(tmp_ping_sock); @@ -226,37 +236,41 @@ // n1 and n2: number of landmarks from ping_list and rest in // proportion to the number of nodes in those lists - int i, n = MIN(NUM_LANDMARKS_COORDINATE, - list->num_newservers + list->num_ping_list); - int n1 = ((float)list->num_ping_list/ - (list->num_newservers + list->num_ping_list)) * n; - int n2 = n-n1; + int i, n = MIN(NUM_LANDMARKS_COORDINATE, + list->num_newservers + list->num_ping_list); + int n1 = ((float) list->num_ping_list / + (list->num_newservers + list->num_ping_list)) * n; + int n2 = n - n1; // add from ping list count = 0; - for (i = 0, node = list->list; - count < n1; - node = node->next_list, ++i) { - if( i >= list->num_ping_list ) break; - if (node->n > 0) { - coord_rtt[count].rtt = get_rtt_node(node); - coord_rtt[count].coord = node->coord; - count++; - } + for (i = 0, node = list->list; + count < n1; + node = node->next_list, ++i) { + if (i >= list->num_ping_list) { + break; + } + if (node->n > 0) { + coord_rtt[count].rtt = get_rtt_node(node); + coord_rtt[count].coord = node->coord; + count++; + } } num_landmarks = count; // add from rest - count = 0; - for (i = 0, node = list->full_list; - count < n2; - node = node->next_list, ++i) { - if( i>= list->num_newservers ) break; - if (node->n > 0) { - coord_rtt[num_landmarks + count].rtt = get_rtt_node(node); - coord_rtt[num_landmarks + count].coord = node->coord; - count++; - } + count = 0; + for (i = 0, node = list->full_list; + count < n2; + node = node->next_list, ++i) { + if (i >= list->num_newservers) { + break; + } + if (node->n > 0) { + coord_rtt[num_landmarks + count].rtt = get_rtt_node(node); + coord_rtt[num_landmarks + count].coord = node->coord; + count++; + } } num_landmarks += count; @@ -269,16 +283,16 @@ /** This function is called to close the ping socket */ -void close_ping_socket() { - - if (ping_sock != -1) { - nw_close (ping_sock); - } +void close_ping_socket() +{ + if (ping_sock != -1) { + nw_close(ping_sock); + } } extern int usleep(__useconds_t useconds); /********************************************************* - * Main ping thread + * Main ping thread ********************************************************/ #ifndef _WIN32 void *ping_thread_entry(void *data) @@ -286,35 +300,37 @@ unsigned int __stdcall ping_thread_entry(void *data) #endif { - PingThreadData *pdata = (PingThreadData *)data; - + PingThreadData *pdata = (PingThreadData *) data; + int maxfd, ret; fd_set all_rset, rset; struct timeval to; - I3ServerList *list = pdata->list; - char *url = pdata->url; + I3ServerList *list = pdata->list; + char *url = pdata->url; uint64_t *ping_start_time = pdata->ping_start_time; - + int num_pings; I3ServerListNode *next_to_ping; uint64_t last_ping_time, curr_time; uint64_t last_add_new_i3servers, last_update_serverlist; - + FD_ZERO(&all_rset); FD_ZERO(&rset); /* socket init */ #ifdef ICMP_PING - if (init_icmp_socket(&ping_sock) == -1) - abort(); + if (init_icmp_socket(&ping_sock) == -1) { + abort(); + } #else - if (init_udp_socket(&ping_sock) == -1) - abort(); + if (init_udp_socket(&ping_sock) == -1) { + abort(); + } #endif FD_SET(ping_sock, &all_rset); maxfd = ping_sock + 1; - + /* initial populate the list of i3 servers */ update_i3_server_list(url, list, &next_to_ping); @@ -323,101 +339,106 @@ /* add some close-by servers from the list based on coordinates */ change_ping_list(list, &next_to_ping, 1); - + /* eternal loop */ last_ping_time = last_add_new_i3servers = last_update_serverlist = wall_time(); set_status(ping_start_time, last_ping_time); - for (;;) { - rset = all_rset; - to.tv_sec = 0; to.tv_usec = 10000; + for (;; ) { + rset = all_rset; + to.tv_sec = 0; + to.tv_usec = 10000; if ((ret = select(maxfd, &rset, NULL, NULL, &to)) < 0) { - if (errno == EINTR) + if (errno == EINTR) { continue; - else { + } else { perror("select"); abort(); } } - /* message received on icmp socket */ - if (FD_ISSET(ping_sock, &rset)) { - uint32_t addr; uint16_t port, seq; uint64_t rtt; + /* message received on icmp socket */ + if (FD_ISSET(ping_sock, &rset)) { + uint32_t addr; + uint16_t port, seq; + uint64_t rtt; #ifdef ICMP_PING - if (recv_echo_reply(ping_sock, &addr, &seq, &rtt)) { + if (recv_echo_reply(ping_sock, &addr, &seq, &rtt)) { #else - if (recv_i3_echo_reply(ping_sock, &addr, &port, &seq, &rtt)) { + if (recv_i3_echo_reply(ping_sock, &addr, &port, &seq, &rtt)) { #endif - update_ping_information(list, addr, seq, rtt); - } - } - - /* need to ping */ - curr_time = wall_time(); - if (list->num_ping_list > 0) { - char status = get_status(ping_start_time, curr_time); - num_pings = (curr_time - last_ping_time)/ - (period_ping[(int)status]/list->num_ping_list); - if (num_pings > 0) { - if (NULL == next_to_ping) { - I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, - "No servers to ping. Aborting\n"); - } - send_npings(ping_sock, list, &next_to_ping, num_pings); - last_ping_time = curr_time; - } - } - - /* change the list of i3 servers */ - if (curr_time - last_add_new_i3servers > - period_pick_new_server[(int)get_status(ping_start_time, curr_time)]) { - /* testing just the best server */ - uint32_t best_addr; uint16_t best_port; uint64_t best_rtt; - struct in_addr ia; - int required_k = 1; - int ret = get_top_k(list, required_k, &best_addr, &best_port, &best_rtt); - - if (ret != required_k) { - // We couldn't find the request k top nodes. - - I3_PRINT_INFO0 ( - I3_INFO_LEVEL_WARNING, - "I3 Ping Thread: Unable to obtain top k nodes.\n" - ); - // Dilip: Feb 20, 2006. I don't think the following works. - // TODO: Start - // We set the last_add_new_servers to fool the thread - // to wait for some time before trying again to get - // the top k nodes. - //last_add_new_i3servers = curr_time; - // TODO: End - - // Sleep for some time before trying again. -# if defined (_WIN32) - Sleep ( 25 ); // 25 milliseconds -# else - usleep(25 * 1000); // 25 milliseconds -# endif - continue; - } - - ia.s_addr = htonl(best_addr); - I3_PRINT_DEBUG3(I3_INFO_LEVEL_MINIMAL, - "Best node: %s:%d with RTT %Ld\n", - inet_ntoa(ia), best_port, best_rtt - ); - - I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_VERBOSE, "Adding new servers to list\n"); - change_ping_list(list, &next_to_ping, 0); - last_add_new_i3servers = curr_time; - } - - /* update (wget) i3 server list */ - if (curr_time - last_update_serverlist > PERIOD_SERVERLIST_WGET) { - I3_PRINT_DEBUG0( I3_DEBUG_LEVEL_VERBOSE, - "Updating server list from server\n"); - update_i3_server_list(url, list, &next_to_ping); - last_update_serverlist = curr_time; - } + update_ping_information(list, addr, seq, rtt); + } + } + + /* need to ping */ + curr_time = wall_time(); + if (list->num_ping_list > 0) { + char status = get_status(ping_start_time, curr_time); + num_pings = (curr_time - last_ping_time) / + (period_ping[(int) status] / list->num_ping_list); + if (num_pings > 0) { + if (NULL == next_to_ping) { + I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, + "No servers to ping. Aborting\n"); + } + send_npings(ping_sock, list, &next_to_ping, num_pings); + last_ping_time = curr_time; + } + } + + /* change the list of i3 servers */ + if (curr_time - last_add_new_i3servers > + period_pick_new_server[(int) get_status(ping_start_time, curr_time)]) { + /* testing just the best server */ + uint32_t best_addr; + uint16_t best_port; + uint64_t best_rtt; + struct in_addr ia; + int required_k = 1; + int ret = get_top_k(list, required_k, &best_addr, &best_port, &best_rtt); + + if (ret != required_k) { + // We couldn't find the request k top nodes. + + I3_PRINT_INFO0( + I3_INFO_LEVEL_WARNING, + "I3 Ping Thread: Unable to obtain top k nodes.\n" + ); + // Dilip: Feb 20, 2006. I don't think the following works. + // TODO: Start + // We set the last_add_new_servers to fool the thread + // to wait for some time before trying again to get + // the top k nodes. + //last_add_new_i3servers = curr_time; + // TODO: End + + // Sleep for some time before trying again. +# if defined (_WIN32) + Sleep( 25 ); // 25 milliseconds +# else + usleep(25 * 1000); // 25 milliseconds +# endif + continue; + } + + ia.s_addr = htonl(best_addr); + I3_PRINT_DEBUG3(I3_INFO_LEVEL_MINIMAL, + "Best node: %s:%d with RTT %Ld\n", + inet_ntoa(ia), best_port, best_rtt + ); + + I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_VERBOSE, "Adding new servers to list\n"); + change_ping_list(list, &next_to_ping, 0); + last_add_new_i3servers = curr_time; + } + + /* update (wget) i3 server list */ + if (curr_time - last_update_serverlist > PERIOD_SERVERLIST_WGET) { + I3_PRINT_DEBUG0( I3_DEBUG_LEVEL_VERBOSE, + "Updating server list from server\n"); + update_i3_server_list(url, list, &next_to_ping); + last_update_serverlist = curr_time; + } } #ifndef _WIN32 === modified file 'i3/i3_client/ping_thread.h' --- i3/i3_client/ping_thread.h 2010-01-06 22:17:32 +0000 +++ i3/i3_client/ping_thread.h 2010-02-11 11:49:47 +0000 @@ -8,8 +8,8 @@ typedef struct PingThreadData { I3ServerList *list; - char *url; - uint64_t *ping_start_time; + char * url; + uint64_t * ping_start_time; } PingThreadData; void close_ping_socket(void); === modified file 'i3/i3_client/qsort.c' --- i3/i3_client/qsort.c 2009-12-11 22:49:11 +0000 +++ i3/i3_client/qsort.c 2010-02-11 11:49:47 +0000 @@ -1,49 +1,50 @@ #include "qsort.h" -void qksort(uint64_t *A, int ilo, int ihi) { - uint64_t pivot; // pivot value for partitioning array - int ulo, uhi; // indices at ends of unpartitioned region - int ieq; // least index of array entry with value equal to pivot - uint64_t tempEntry; // temporary entry used for swapping +void qksort(uint64_t *A, int ilo, int ihi) +{ + uint64_t pivot; // pivot value for partitioning array + int ulo, uhi; // indices at ends of unpartitioned region + int ieq; // least index of array entry with value equal to pivot + uint64_t tempEntry; // temporary entry used for swapping if (ilo >= ihi) { - return; + return; } // Select a pivot value. - pivot = A[(ilo + ihi)/2]; + pivot = A[(ilo + ihi) / 2]; // Initialize ends of unpartitioned region and least index of entry // with value equal to pivot. - ieq = ulo = ilo; - uhi = ihi; + ieq = ulo = ilo; + uhi = ihi; // While the unpartitioned region is not empty, try to reduce its size. while (ulo <= uhi) { - if (A[uhi] > pivot) { - // Here, we can reduce the size of the unpartitioned region and - // try again. - uhi--; - } else { - // Here, A[uhi] <= pivot, so swap entries at indices ulo and - // uhi. - tempEntry = A[ulo]; - A[ulo] = A[uhi]; - A[uhi] = tempEntry; - // After the swap, A[ulo] <= pivot. - if (A[ulo] < pivot) { - // Swap entries at indices ieq and ulo. - tempEntry = A[ieq]; - A[ieq] = A[ulo]; - A[ulo] = tempEntry; - // After the swap, A[ieq] < pivot, so we need to change - // ieq. - ieq++; - // We also need to change ulo, but we also need to do - // that when A[ulo] = pivot, so we do it after this if - // statement. - } - // Once again, we can reduce the size of the unpartitioned - // region and try again. - ulo++; - } + if (A[uhi] > pivot) { + // Here, we can reduce the size of the unpartitioned region and + // try again. + uhi--; + } else { + // Here, A[uhi] <= pivot, so swap entries at indices ulo and + // uhi. + tempEntry = A[ulo]; + A[ulo] = A[uhi]; + A[uhi] = tempEntry; + // After the swap, A[ulo] <= pivot. + if (A[ulo] < pivot) { + // Swap entries at indices ieq and ulo. + tempEntry = A[ieq]; + A[ieq] = A[ulo]; + A[ulo] = tempEntry; + // After the swap, A[ieq] < pivot, so we need to change + // ieq. + ieq++; + // We also need to change ulo, but we also need to do + // that when A[ulo] = pivot, so we do it after this if + // statement. + } + // Once again, we can reduce the size of the unpartitioned + // region and try again. + ulo++; + } } // Now, all entries from index ilo to ieq - 1 are less than the pivot // and all entries from index uhi to ihi + 1 are greater than the === modified file 'i3/utils/byteorder.c' --- i3/utils/byteorder.c 2009-12-11 22:49:11 +0000 +++ i3/utils/byteorder.c 2010-02-11 11:49:47 +0000 @@ -1,108 +1,108 @@ -#include <sys/types.h> -#ifndef _WIN32 - #include <netinet/in.h> -#else - #include "fwint.h" - #include <Winsock2.h> -#endif - -#include "byteorder.h" - -/* Purpose: To raise num to exponent in u64 - * Caveat: No range checking is done! - */ -static uint64_t pow_u64(uint16_t num, uint8_t exp) -{ - uint64_t ret; - int count; - - if (exp <= 30) - ret = 1 << exp; - else - ret = 1 << 30; - - for (count = 0; count < exp - 30; count++) - ret *= 2; - - return ret; -} - - -void hnputl(void *p, uint32_t v) -{ - uint32_t *a; - - a = p; - *a = htonl(v); -} - -void hnputs(void *p, uint16_t v) -{ - uint16_t *a; - - a = p; - *a = htons(v); -} - -void hnput64(void *p, uint64_t v) -{ - // workaround for "initializer element is not constant" - static char first_call = 1; - static uint64_t two_32; - - uint64_t u64_hi, u64_lo; - uint32_t hi,lo; - uint32_t *hi_ptr, *lo_ptr; - - if (first_call) { - two_32 = pow_u64(2, 32); - first_call = 0; - } - - lo_ptr = (uint32_t *) p; - hi_ptr = (uint32_t *) ((char *) p + sizeof(uint32_t)); - - u64_lo = v % two_32; - u64_hi = v / two_32; - - lo = (uint32_t) u64_lo; - hi = (uint32_t) u64_hi; - - *lo_ptr = htonl(lo); - *hi_ptr = htonl(hi); -} - - -uint32_t nhgetl(void *p) -{ - uint32_t *a; - - a = p; - return ntohl(*a); -} - -uint16_t nhgets(void *p) -{ - uint16_t *a; - - a = p; - return ntohs(*a); -} - -uint64_t nhget64(void *p) -{ - // workaround for "initializer element is not constant" - static char first_call = 1; - static uint64_t two_32; - uint32_t *lo_ptr, *hi_ptr; - - if (first_call) { - two_32 = pow_u64(2, 32); - first_call = 0; - } - - lo_ptr = (uint32_t *) p; - hi_ptr = (uint32_t *) ((char *) p + sizeof(uint32_t)); - - return ntohl(*lo_ptr) + two_32 * ntohl(*hi_ptr); -} +#include <sys/types.h> +#ifndef _WIN32 + #include <netinet/in.h> +#else + #include "fwint.h" + #include <Winsock2.h> +#endif + +#include "byteorder.h" + +/* Purpose: To raise num to exponent in u64 + * Caveat: No range checking is done! + */ +static uint64_t pow_u64(uint16_t num, uint8_t exp) +{ + uint64_t ret; + int count; + + if (exp <= 30) { + ret = 1 << exp; + } else { + ret = 1 << 30; + } + + for (count = 0; count < exp - 30; count++) { + ret *= 2; + } + + return ret; +} + +void hnputl(void *p, uint32_t v) +{ + uint32_t *a; + + a = p; + *a = htonl(v); +} + +void hnputs(void *p, uint16_t v) +{ + uint16_t *a; + + a = p; + *a = htons(v); +} + +void hnput64(void *p, uint64_t v) +{ + // workaround for "initializer element is not constant" + static char first_call = 1; + static uint64_t two_32; + + uint64_t u64_hi, u64_lo; + uint32_t hi, lo; + uint32_t *hi_ptr, *lo_ptr; + + if (first_call) { + two_32 = pow_u64(2, 32); + first_call = 0; + } + + lo_ptr = (uint32_t *) p; + hi_ptr = (uint32_t *) ((char *) p + sizeof(uint32_t)); + + u64_lo = v % two_32; + u64_hi = v / two_32; + + lo = (uint32_t) u64_lo; + hi = (uint32_t) u64_hi; + + *lo_ptr = htonl(lo); + *hi_ptr = htonl(hi); +} + +uint32_t nhgetl(void *p) +{ + uint32_t *a; + + a = p; + return ntohl(*a); +} + +uint16_t nhgets(void *p) +{ + uint16_t *a; + + a = p; + return ntohs(*a); +} + +uint64_t nhget64(void *p) +{ + // workaround for "initializer element is not constant" + static char first_call = 1; + static uint64_t two_32; + uint32_t *lo_ptr, *hi_ptr; + + if (first_call) { + two_32 = pow_u64(2, 32); + first_call = 0; + } + + lo_ptr = (uint32_t *) p; + hi_ptr = (uint32_t *) ((char *) p + sizeof(uint32_t)); + + return ntohl(*lo_ptr) + two_32 *ntohl(*hi_ptr); +} === modified file 'i3/utils/byteorder.h' --- i3/utils/byteorder.h 2009-12-11 22:49:11 +0000 +++ i3/utils/byteorder.h 2010-02-11 11:49:47 +0000 @@ -1,23 +1,23 @@ -#ifndef _BYTE_ORDER_H -#define _BYTE_ORDER_H - -#include <sys/types.h> +#ifndef _BYTE_ORDER_H +#define _BYTE_ORDER_H + +#include <sys/types.h> /* stg: under cygwin, _WIN32 can be defined if win32api header files get included */ #if defined(_WIN32) - #include "fwint.h" -#else - #include <inttypes.h> -#endif - -/*************************************************************************** - * Purpose: Wrapper functions for byte order conversion - **************************************************************************/ - -void hnputl(void *p, uint32_t v); -void hnputs(void *p, uint16_t v); -void hnput64(void *p, uint64_t v); -uint32_t nhgetl(void *p); -uint16_t nhgets(void *p); -uint64_t nhget64(void *p); - -#endif + #include "fwint.h" +#else + #include <inttypes.h> +#endif + +/*************************************************************************** + * Purpose: Wrapper functions for byte order conversion + **************************************************************************/ + +void hnputl(void *p, uint32_t v); +void hnputs(void *p, uint16_t v); +void hnput64(void *p, uint64_t v); +uint32_t nhgetl(void *p); +uint16_t nhgets(void *p); +uint64_t nhget64(void *p); + +#endif === modified file 'i3/utils/eprintf.c' --- i3/utils/eprintf.c 2009-12-11 22:49:11 +0000 +++ i3/utils/eprintf.c 2010-02-11 11:49:47 +0000 @@ -1,108 +1,117 @@ -/* Copyright (C) 1999 Lucent Technologies */ -/* Excerpted from 'The Practice of Programming' */ -/* by Brian W. Kernighan and Rob Pike */ - -#include <stdio.h> -#include <stdlib.h> -#include <stdarg.h> -#include <string.h> -#include <errno.h> -#include "eprintf.h" - -/* eprintf: print error message and exit */ -void eprintf (char *fmt, ...) -{ - va_list args; - - fflush (stdout); - if (getprogname () != NULL) - fprintf (stderr, "%s: ", getprogname ()); - - va_start (args, fmt); - vfprintf (stderr, fmt, args); - va_end (args); - - if (fmt[0] != '\0' && fmt[strlen (fmt) - 1] == ':') - fprintf (stderr, " %s", strerror (errno)); - fprintf (stderr, "\n"); - exit (2); /* conventional value for failed execution */ -} - -/* weprintf: print warning message */ -void weprintf (char *fmt, ...) -{ - va_list args; - - fflush (stdout); - fprintf (stderr, "warning: "); - if (getprogname () != NULL) - fprintf (stderr, "%s: ", getprogname ()); - va_start (args, fmt); - vfprintf (stderr, fmt, args); - va_end (args); - if (fmt[0] != '\0' && fmt[strlen (fmt) - 1] == ':') - fprintf (stderr, " %s\n", strerror (errno)); - else - fprintf (stderr, "\n"); -} - -/* emalloc: malloc and report if error */ -void *emalloc (size_t n) -{ - void *p; - - p = malloc (n); - if (p == NULL) - eprintf ("malloc of %u bytes failed:", n); - return p; -} - -/* erealloc: realloc and report if error */ -void *erealloc (void *vp, size_t n) -{ - void *p; - - p = realloc (vp, n); - if (p == NULL) - eprintf ("realloc of %u bytes failed:", n); - return p; -} - -/* ecalloc: calloc and report if error */ -void *ecalloc (size_t n, size_t w) -{ - void *p; - - p = calloc (n, w); - if (p == NULL) - eprintf ("calloc of %u x %u bytes failed:", n, w); - return p; -} - -/* estrdup: duplicate a string, report if error */ -char *estrdup (char *s) -{ - char *t; - - t = (char *) malloc (strlen (s) + 1); - if (t == NULL) - eprintf ("estrdup(\"%.20s\") failed:", s); - strcpy (t, s); - return t; -} - -#ifndef __APPLE__ -static const char *progname; - -/* setprogname: set name of program */ -void setprogname (const char *name) -{ - progname = name; -} - -/* getprogname: return name of program */ -const char *getprogname (void) -{ - return progname; -} -#endif +/* Copyright (C) 1999 Lucent Technologies */ +/* Excerpted from 'The Practice of Programming' */ +/* by Brian W. Kernighan and Rob Pike */ + +#include <stdio.h> +#include <stdlib.h> +#include <stdarg.h> +#include <string.h> +#include <errno.h> +#include "eprintf.h" + +/* eprintf: print error message and exit */ +void eprintf(char *fmt, ...) +{ + va_list args; + + fflush(stdout); + if (getprogname() != NULL) { + fprintf(stderr, "%s: ", getprogname()); + } + + va_start(args, fmt); + vfprintf(stderr, fmt, args); + va_end(args); + + if (fmt[0] != '\0' && fmt[strlen(fmt) - 1] == ':') { + fprintf(stderr, " %s", strerror(errno)); + } + fprintf(stderr, "\n"); + exit(2); /* conventional value for failed execution */ +} + +/* weprintf: print warning message */ +void weprintf(char *fmt, ...) +{ + va_list args; + + fflush(stdout); + fprintf(stderr, "warning: "); + if (getprogname() != NULL) { + fprintf(stderr, "%s: ", getprogname()); + } + va_start(args, fmt); + vfprintf(stderr, fmt, args); + va_end(args); + if (fmt[0] != '\0' && fmt[strlen(fmt) - 1] == ':') { + fprintf(stderr, " %s\n", strerror(errno)); + } else { + fprintf(stderr, "\n"); + } +} + +/* emalloc: malloc and report if error */ +void *emalloc(size_t n) +{ + void *p; + + p = malloc(n); + if (p == NULL) { + eprintf("malloc of %u bytes failed:", n); + } + return p; +} + +/* erealloc: realloc and report if error */ +void *erealloc(void *vp, size_t n) +{ + void *p; + + p = realloc(vp, n); + if (p == NULL) { + eprintf("realloc of %u bytes failed:", n); + } + return p; +} + +/* ecalloc: calloc and report if error */ +void *ecalloc(size_t n, size_t w) +{ + void *p; + + p = calloc(n, w); + if (p == NULL) { + eprintf("calloc of %u x %u bytes failed:", n, w); + } + return p; +} + +/* estrdup: duplicate a string, report if error */ +char *estrdup(char *s) +{ + char *t; + + t = (char *) malloc(strlen(s) + 1); + if (t == NULL) { + eprintf("estrdup(\"%.20s\") failed:", s); + } + strcpy(t, s); + return t; +} + +#ifndef __APPLE__ +static const char *progname; + +/* setprogname: set name of program */ +void setprogname(const char *name) +{ + progname = name; +} + +/* getprogname: return name of program */ +const char *getprogname(void) +{ + return progname; +} + +#endif === modified file 'i3/utils/eprintf.h' --- i3/utils/eprintf.h 2009-12-11 22:49:11 +0000 +++ i3/utils/eprintf.h 2010-02-11 11:49:47 +0000 @@ -1,25 +1,25 @@ -#ifndef _EPRINTF_H -#define _EPRINTF_H - -/* Copyright (C) 1999 Lucent Technologies */ -/* Excerpted from 'The Practice of Programming' */ -/* by Brian W. Kernighan and Rob Pike */ - -#include <time.h> - -/* eprintf.h: error wrapper functions */ -extern void eprintf (char *, ...); -extern void weprintf (char *, ...); -extern char *estrdup (char *); -extern void *emalloc (size_t); -extern void *erealloc (void *, size_t); -extern void *ecalloc (size_t, size_t); -extern void setprogname (const char *); -extern const char *getprogname (void); - -#ifdef CCURED -#pragma ccuredalloc("emalloc", sizein(1)) -#pragma ccuredvararg("eprintf", printf(1)) -#pragma ccuredvararg("weprintf", printf(1)) -#endif -#endif +#ifndef _EPRINTF_H +#define _EPRINTF_H + +/* Copyright (C) 1999 Lucent Technologies */ +/* Excerpted from 'The Practice of Programming' */ +/* by Brian W. Kernighan and Rob Pike */ + +#include <time.h> + +/* eprintf.h: error wrapper functions */ +extern void eprintf(char *, ...); +extern void weprintf(char *, ...); +extern char *estrdup(char *); +extern void *emalloc(size_t); +extern void *erealloc(void *, size_t); +extern void *ecalloc(size_t, size_t); +extern void setprogname(const char *); +extern const char *getprogname(void); + +#ifdef CCURED +#pragma ccuredalloc("emalloc", sizein(1)) +#pragma ccuredvararg("eprintf", printf(1)) +#pragma ccuredvararg("weprintf", printf(1)) +#endif +#endif === modified file 'i3/utils/event.c' --- i3/utils/event.c 2010-01-06 22:17:32 +0000 +++ i3/utils/event.c 2010-02-11 11:49:47 +0000 @@ -1,161 +1,162 @@ -/* - * - * Copyright (C) 2001 Ion Stoica (istoica@xxxxxxxxxxxxxxx) - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - */ - -#include <stdio.h> -#include <stdlib.h> -#ifndef _WIN32 - #include <inttypes.h> -#else - #include "fwint.h" -#endif - - -#include "event.h" - -Event *newEvent(void (*fun)(void *), void *params, uint64_t time) -{ - Event *ev; - - if (!(ev = (Event *)calloc(1, sizeof(Event)))) { - printf("newEvent: memory alloc. error.\n"); - exit(-1); - } - ev->fun = fun; - ev->params = params; - ev->time = time; - ev->cancel = 0; - - return ev; -} - -// allocate an array of pointers to events -Event **newEventArray(int max_heap_size) -{ - Event **q; - - if (!(q = (Event **)calloc(1, max_heap_size*sizeof(Event **)))) { - printf("initEventQueue: memory alloc. error.\n"); - exit(-1); - } - return q; -} - - -// swap two events in the heap -void swap_events(EventHeap *h, unsigned int idx, unsigned int idx1) -{ - Event *t; - - t = h->heap[idx]; - h->heap[idx] = h->heap[idx1]; - h->heap[idx1] = t; -} - - -// insert new event in the heap -void insertEvent(EventHeap *h, Event *ev) -{ - int idx, idx1; - - if (h->size > h->max_size - 1) { - printf("Event not inserted; too many events.\n"); - return; - } - - h->heap[h->size] = ev; - (h->size)++; - - // rebuild heap - idx = h->size - 1; - idx1 = (idx-1)/2; - while ((idx >= 1) && (h->heap[idx]->time < h->heap[idx1]->time)) { - swap_events(h, idx, idx1); - idx = idx1; - idx1 = (idx-1)/2; - } -} - -// get the top of the heap -Event *getNextEvent(EventHeap *h) -{ - if (h->size > 0) - return h->heap[0]; - else - return NULL; -} - - -// remove the event at the top of the heap -void removeNextEvent(EventHeap *h) -{ - unsigned int idx, idx1, idx_left, idx_right; - - free(h->heap[0]); - if (h->size > 1) - h->heap[0] = h->heap[h->size - 1]; - if (h->size) - h->size--; - - // rebuild heap - idx = 0; - while (1) { - idx_left = 2*idx + 1; - idx_right = idx_left + 1; - if (idx_left >= h->size) { - return; - } - if (idx_left == h->size - 1) - // only left child - idx1 = idx_left; - else { - if (h->heap[idx_left]->time < h->heap[idx_right]->time) - idx1 = idx_left; - else - idx1 = idx_right; - } - if (h->heap[idx]->time > h->heap[idx1]->time) { - swap_events(h, idx, idx1); - idx = idx1; - } else { - return; - } - } -} - -void printEventHeap(EventHeap *h) -{ - int i; - - printf(" (%d/%d)\n", h->size, h->max_size); - printf(" "); - - for (i = 0; i < h->size; i++) { - Event *ev = h->heap[i]; - printf("[%p/", ev); - printf("%llu/", (unsigned long long int)ev->time); - printf("%d]", ev->cancel); - } - printf("\n"); -} +/* + * + * Copyright (C) 2001 Ion Stoica (istoica@xxxxxxxxxxxxxxx) + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#include <stdio.h> +#include <stdlib.h> +#ifndef _WIN32 + #include <inttypes.h> +#else + #include "fwint.h" +#endif + + +#include "event.h" + +Event *newEvent(void (*fun)(void *), void *params, uint64_t time) +{ + Event *ev; + + if (!(ev = (Event *) calloc(1, sizeof(Event)))) { + printf("newEvent: memory alloc. error.\n"); + exit(-1); + } + ev->fun = fun; + ev->params = params; + ev->time = time; + ev->cancel = 0; + + return ev; +} + +// allocate an array of pointers to events +Event **newEventArray(int max_heap_size) +{ + Event **q; + + if (!(q = (Event **) calloc(1, max_heap_size * sizeof(Event * *)))) { + printf("initEventQueue: memory alloc. error.\n"); + exit(-1); + } + return q; +} + +// swap two events in the heap +void swap_events(EventHeap *h, unsigned int idx, unsigned int idx1) +{ + Event *t; + + t = h->heap[idx]; + h->heap[idx] = h->heap[idx1]; + h->heap[idx1] = t; +} + +// insert new event in the heap +void insertEvent(EventHeap *h, Event *ev) +{ + int idx, idx1; + + if (h->size > h->max_size - 1) { + printf("Event not inserted; too many events.\n"); + return; + } + + h->heap[h->size] = ev; + (h->size)++; + + // rebuild heap + idx = h->size - 1; + idx1 = (idx - 1) / 2; + while ((idx >= 1) && (h->heap[idx]->time < h->heap[idx1]->time)) { + swap_events(h, idx, idx1); + idx = idx1; + idx1 = (idx - 1) / 2; + } +} + +// get the top of the heap +Event *getNextEvent(EventHeap *h) +{ + if (h->size > 0) { + return h->heap[0]; + } else { + return NULL; + } +} + +// remove the event at the top of the heap +void removeNextEvent(EventHeap *h) +{ + unsigned int idx, idx1, idx_left, idx_right; + + free(h->heap[0]); + if (h->size > 1) { + h->heap[0] = h->heap[h->size - 1]; + } + if (h->size) { + h->size--; + } + + // rebuild heap + idx = 0; + while (1) { + idx_left = 2 * idx + 1; + idx_right = idx_left + 1; + if (idx_left >= h->size) { + return; + } + if (idx_left == h->size - 1) { + // only left child + idx1 = idx_left; + } else { + if (h->heap[idx_left]->time < h->heap[idx_right]->time) { + idx1 = idx_left; + } else { + idx1 = idx_right; + } + } + if (h->heap[idx]->time > h->heap[idx1]->time) { + swap_events(h, idx, idx1); + idx = idx1; + } else { + return; + } + } +} + +void printEventHeap(EventHeap *h) +{ + int i; + + printf(" (%d/%d)\n", h->size, h->max_size); + printf(" "); + + for (i = 0; i < h->size; i++) { + Event *ev = h->heap[i]; + printf("[%p/", ev); + printf("%llu/", (unsigned long long int) ev->time); + printf("%d]", ev->cancel); + } + printf("\n"); +} === modified file 'i3/utils/event.h' --- i3/utils/event.h 2010-01-06 22:17:32 +0000 +++ i3/utils/event.h 2010-02-11 11:49:47 +0000 @@ -1,60 +1,60 @@ -/* - * - * Copyright (C) 2001 Ion Stoica (istoica@xxxxxxxxxxxxxxx) - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - */ - -#ifndef INCL_EVENTS -#define INCL_EVENTS - +/* + * + * Copyright (C) 2001 Ion Stoica (istoica@xxxxxxxxxxxxxxx) + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#ifndef INCL_EVENTS +#define INCL_EVENTS + /* stg: under cygwin, _WIN32 can be defined if win32api header files get included */ #if defined(_WIN32) - #include "fwint.h" -#else - #include <inttypes.h> -#endif - -typedef struct _event { - uint64_t time; - uint16_t cancel; /* specify whether the timeout is canceled */ - void (*fun)(void *); /* function to be called when the evnt occurs */ - void *params; /* address to the parameters to be passed to fun */ -} Event; - -typedef struct _eventHeap { - Event **heap; - unsigned int size; - unsigned int max_size; -} EventHeap; - - -#define isEventCanceled(ev) (ev->cancel) - -/* function prototypes */ -Event *newEvent(void (*fun)(void *), void *params, uint64_t time); -Event **newEventArray(int max_heap_size); -void insertEvent(EventHeap *h, Event *ev); -Event *getNextEvent(EventHeap *h); -void removeNextEvent(EventHeap *h); -void printEventHeap(EventHeap *h); - -#endif + #include "fwint.h" +#else + #include <inttypes.h> +#endif + +typedef struct _event { + uint64_t time; + uint16_t cancel; /* specify whether the timeout is canceled */ + void (*fun)(void *); /* function to be called when the evnt occurs */ + void * params; /* address to the parameters to be passed to fun */ +} Event; + +typedef struct _eventHeap { + Event ** heap; + unsigned int size; + unsigned int max_size; +} EventHeap; + + +#define isEventCanceled(ev) (ev->cancel) + +/* function prototypes */ +Event *newEvent(void (*fun)(void *), void *params, uint64_t time); +Event **newEventArray(int max_heap_size); +void insertEvent(EventHeap *h, Event *ev); +Event *getNextEvent(EventHeap *h); +void removeNextEvent(EventHeap *h); +void printEventHeap(EventHeap *h); + +#endif === modified file 'i3/utils/fwint.h' --- i3/utils/fwint.h 2009-12-11 22:49:11 +0000 +++ i3/utils/fwint.h 2010-02-11 11:49:47 +0000 @@ -31,7 +31,7 @@ typedef long long int64_t; #ifndef _INTPTR_T_DEFINED -typedef int32_t intptr_t; +typedef int32_t intptr_t; #define _INTPTR_T_DEFINED 1 #endif @@ -54,7 +54,7 @@ typedef long int64_t; #ifndef _INTPTR_T_DEFINED -typedef int64_t intptr_t; +typedef int64_t intptr_t; #define _INTPTR_T_DEFINED 1 #endif === modified file 'i3/utils/gen_utils.c' --- i3/utils/gen_utils.c 2009-12-11 22:49:11 +0000 +++ i3/utils/gen_utils.c 2010-02-11 11:49:47 +0000 @@ -1,130 +1,132 @@ -#include "gen_utils.h" -#include <stdio.h> -#include <stdlib.h> -#include <ctype.h> -#include <string.h> -#include <assert.h> -#ifndef _WIN32 - #include <sys/time.h> - #include <inttypes.h> -#else - #include "fwint.h" - #include <sys/types.h> // _ftime() - #include <sys/timeb.h> // _ftime() - #include <Windows.h> // struct timeval - #include <time.h> -#endif - -extern time_t time ( time_t * timer ); - -#define UMILLION 1000000ULL - -/**********************************************************************/ - -/* init_rand: initialize the PRNG with a seed. */ -void init_rand(void) -{ - //unsigned int seed = 0; - time_t t; - - srand(time(&t)); -} - -/* f_rand: return a random double between 0.0 and 1.0 */ -double f_rand(void) -{ - int64_t l, r; - - l = (int64_t) (rand() & ((1 << 26) - 1)); - r = (int64_t) (rand() & ((1 << 27) - 1)); - return ((l << 27) + r) / (double)(1LL << 53); -} - -/**********************************************************************/ - -/* funif_rand: Return a random number between a and b */ -double funif_rand(double a, double b) -{ - return a + (b - a) * f_rand(); -} - -/**********************************************************************/ - -/* n_rand: return a random integer in [0, n), - borrowed from Java Random class */ -int n_rand(int n) -{ - int bits, val; - - assert(n >= 0); /* n must be positive */ - - /* Special case: power of 2 */ - if ((n & -n) == n) - return rand() & (n - 1); - - do { - bits = rand(); - val = bits % n; - } while (bits - val + (n - 1) < 0); - return val; -} - -/**********************************************************************/ - -/* unif_rand: return a random integer number in the interval [a, b) */ -int unif_rand(int a, int b) -{ - return a + n_rand(b - a); -} - -/* return a random number in an one second interval, in usec */ -int random_sec(void) -{ - return unif_rand(0, 1000000ULL); -} - -/**********************************************************************/ - -/* getusec: return wall time in usec */ -uint64_t wall_time(void) -{ -#ifdef _WIN32 - struct timeb t; - ftime(&t); - return t.time * 1000000ULL + t.millitm * 1000; -#else - struct timeval tv; - gettimeofday(&tv, NULL); - return tv.tv_sec * 1000000ULL + tv.tv_usec; -#endif -} - - -/**********************************************************************/ - -void sub_wall_time(struct timeval *tv, uint64_t a, uint64_t b) -{ - if (a < b) { - tv->tv_sec = tv->tv_usec = 0; - } else { - tv->tv_sec = (a - b) / UMILLION; - tv->tv_usec = (a - b) % UMILLION; - } -} - -#if defined(_ARCH_PPC) || defined(_WIN32) -uint64_t get_cycles(void) -{ - exit(-1); -} -#else -#define rdtscll(val) \ - __asm__ __volatile__("rdtsc" : "=A" (val)) - -uint64_t get_cycles(void) -{ - uint64_t ret; - rdtscll(ret); - return ret; -} -#endif +#include "gen_utils.h" +#include <stdio.h> +#include <stdlib.h> +#include <ctype.h> +#include <string.h> +#include <assert.h> +#ifndef _WIN32 + #include <sys/time.h> + #include <inttypes.h> +#else + #include "fwint.h" + #include <sys/types.h> // _ftime() + #include <sys/timeb.h> // _ftime() + #include <Windows.h> // struct timeval + #include <time.h> +#endif + +extern time_t time( time_t *timer ); + +#define UMILLION 1000000ULL + +/**********************************************************************/ + +/* init_rand: initialize the PRNG with a seed. */ +void init_rand(void) +{ + //unsigned int seed = 0; + time_t t; + + srand(time(&t)); +} + +/* f_rand: return a random double between 0.0 and 1.0 */ +double f_rand(void) +{ + int64_t l, r; + + l = (int64_t) (rand() & ((1 << 26) - 1)); + r = (int64_t) (rand() & ((1 << 27) - 1)); + return ((l << 27) + r) / (double) (1LL << 53); +} + +/**********************************************************************/ + +/* funif_rand: Return a random number between a and b */ +double funif_rand(double a, double b) +{ + return a + (b - a) * f_rand(); +} + +/**********************************************************************/ + +/* n_rand: return a random integer in [0, n), + * borrowed from Java Random class */ +int n_rand(int n) +{ + int bits, val; + + assert(n >= 0); /* n must be positive */ + + /* Special case: power of 2 */ + if ((n & - n) == n) { + return rand() & (n - 1); + } + + do { + bits = rand(); + val = bits % n; + } while (bits - val + (n - 1) < 0); + return val; +} + +/**********************************************************************/ + +/* unif_rand: return a random integer number in the interval [a, b) */ +int unif_rand(int a, int b) +{ + return a + n_rand(b - a); +} + +/* return a random number in an one second interval, in usec */ +int random_sec(void) +{ + return unif_rand(0, 1000000ULL); +} + +/**********************************************************************/ + +/* getusec: return wall time in usec */ +uint64_t wall_time(void) +{ +#ifdef _WIN32 + struct timeb t; + ftime(&t); + return t.time * 1000000ULL + t.millitm * 1000; +#else + struct timeval tv; + gettimeofday(&tv, NULL); + return tv.tv_sec * 1000000ULL + tv.tv_usec; +#endif +} + +/**********************************************************************/ + +void sub_wall_time(struct timeval *tv, uint64_t a, uint64_t b) +{ + if (a < b) { + tv->tv_sec = tv->tv_usec = 0; + } else { + tv->tv_sec = (a - b) / UMILLION; + tv->tv_usec = (a - b) % UMILLION; + } +} + +#if defined(_ARCH_PPC) || defined(_WIN32) +uint64_t get_cycles(void) +{ + exit(-1); +} + +#else +#define rdtscll(val) \ + __asm__ __volatile__ ("rdtsc" : "=A" (val)) + +uint64_t get_cycles(void) +{ + uint64_t ret; + rdtscll(ret); + return ret; +} + +#endif === modified file 'i3/utils/gen_utils.h' --- i3/utils/gen_utils.h 2009-12-11 22:49:11 +0000 +++ i3/utils/gen_utils.h 2010-02-11 11:49:47 +0000 @@ -1,31 +1,31 @@ -#ifndef _GEN_UTILS_H -#define _GEN_UTILS_H - +#ifndef _GEN_UTILS_H +#define _GEN_UTILS_H + /* stg: under cygwin, _WIN32 can be defined if win32api header files get included */ #if defined(_WIN32) - #include "fwint.h" // Need uint8_t - #include <Winsock2.h> // struct timeval -#else - #include <inttypes.h> - #include <sys/time.h> // struct timeval -#endif - -#ifndef MAX -#define MAX(x, y) ((x) > (y) ? (x) : (y)) -#endif - -#ifndef MIN -#define MIN(x, y) ((x) < (y) ? (x) : (y)) -#endif - -void init_rand(void); -double f_rand(void); -double funif_rand(double a, double b); -int n_rand(int n); -int unif_rand(int a, int b); -int random_sec(void); -uint64_t wall_time(void); -void sub_wall_time(struct timeval *tv, uint64_t a, uint64_t b); -uint64_t get_cycles(void); - -#endif + #include "fwint.h" // Need uint8_t + #include <Winsock2.h> // struct timeval +#else + #include <inttypes.h> + #include <sys/time.h> // struct timeval +#endif + +#ifndef MAX +#define MAX(x, y) ((x) > (y) ? (x) : (y)) +#endif + +#ifndef MIN +#define MIN(x, y) ((x) < (y) ? (x) : (y)) +#endif + +void init_rand(void); +double f_rand(void); +double funif_rand(double a, double b); +int n_rand(int n); +int unif_rand(int a, int b); +int random_sec(void); +uint64_t wall_time(void); +void sub_wall_time(struct timeval *tv, uint64_t a, uint64_t b); +uint64_t get_cycles(void); + +#endif === modified file 'i3/utils/inetfns.c' --- i3/utils/inetfns.c 2010-01-06 22:17:32 +0000 +++ i3/utils/inetfns.c 2010-02-11 11:49:47 +0000 @@ -1,357 +1,351 @@ -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <errno.h> -#include <assert.h> - -#ifndef _WIN32 - - #include <sys/types.h> - #include <netinet/in.h> - #include <arpa/inet.h> - #include <sys/utsname.h> - #include <netdb.h> - //extern int h_errno; - #include <sys/ioctl.h> - #include <net/if.h> - - #include <sys/sysctl.h> -#endif - -#include "eprintf.h" - - -#define TRIVIAL_LOCAL_ADDR "127.0.0.1" -#define MAX_NUM_INTERFACES 3 -#define IFNAME_LEN 256 - -#ifndef _WIN32 -extern int close(int); -/*************************************************************************** - * - * Purpose: Get IP address of local machine by ioctl on eth0-ethk - * - * Return: As an unsigned long in network byte order - * - **************************************************************************/ -uint32_t get_local_addr_eth(void) -{ - int i, tempfd; - struct sockaddr_in addr; - char ifname[IFNAME_LEN]; - struct ifreq ifr; - - for (i = 0; i < MAX_NUM_INTERFACES; i++) { - sprintf(ifname, "eth%d", i); - strcpy(ifr.ifr_name, ifname); - tempfd = socket(AF_INET, SOCK_DGRAM, 0); - - if (-1 != ioctl(tempfd, SIOCGIFFLAGS, (char *)&ifr)) { - if (0 != (ifr.ifr_flags & IFF_UP)) { - if (-1 != ioctl(tempfd, SIOCGIFADDR, (char *)&ifr)) { - addr = *((struct sockaddr_in *) &ifr.ifr_addr); - close(tempfd); - return addr.sin_addr.s_addr; - } - } - } - close(tempfd); - } - return inet_addr(TRIVIAL_LOCAL_ADDR); -} - -/*************************************************************************** - * - * Purpose: Get the IP address of an arbitrary machine - * given the name of the machine - * - * Return: As an unsigned long in network byte order - * - **************************************************************************/ -uint32_t name_to_addr(const char *name) -{ - int i; - struct hostent *hptr = gethostbyname(name); - if (!hptr) { - weprintf("gethostbyname(%s) failed", name); - } - else { - for (i = 0; i < hptr->h_length/sizeof(uint32_t); i++) { - uint32_t addr = *((uint32_t *) hptr->h_addr_list[i]); - if (inet_addr(TRIVIAL_LOCAL_ADDR) != addr) - return addr; - } - } - return 0; -} - - -/*************************************************************************** - * - * Purpose: Get IP address of local machine by uname/gethostbyname - * - * Return: As an unsigned long in network byte order - * - **************************************************************************/ -uint32_t get_local_addr_uname(void) -{ - struct utsname myname; - uint32_t addr = 0; - - if (uname(&myname) < 0) { - weprintf("uname failed:"); - } else { - addr = name_to_addr(myname.nodename); - } - - if (addr == 0) - return inet_addr(TRIVIAL_LOCAL_ADDR); - else - return addr; -} - - -/*************************************************************************** - * - * Purpose: Get IP address of local machine by trying out all possible - * interfaces starting with interfaceName. For eg:, if interfaceName = "eth", - * try out eth0, eth1, eth2, etc. - * - * Return: As an unsigned long in network byte order - * - **************************************************************************/ -uint32_t get_local_addr_by_interface(char *interfaceName) -{ - int i, tempfd; - struct sockaddr_in addr; - char ifname[IFNAME_LEN]; - struct ifreq ifr; - - for (i = 0; i < MAX_NUM_INTERFACES; i++) { - sprintf(ifname, "%s%d", interfaceName, i); - strcpy(ifr.ifr_name, ifname); - tempfd = socket(AF_INET, SOCK_DGRAM, 0); - - if (-1 != ioctl(tempfd, SIOCGIFFLAGS, (char *)&ifr)) { - if (0 != (ifr.ifr_flags & IFF_UP)) { - if (-1 != ioctl(tempfd, SIOCGIFADDR, (char *)&ifr)) { - addr = *((struct sockaddr_in *) &ifr.ifr_addr); - close(tempfd); - return addr.sin_addr.s_addr; - } - } - } - close(tempfd); - } - return inet_addr(TRIVIAL_LOCAL_ADDR); -} - - - -/*************************************************************************** - * - * Purpose: Get IP address of local machine - * - * Return: As an unsigned long in network byte order - * - **************************************************************************/ -uint32_t get_local_addr(void) -{ - uint32_t addr; - - // TODO Don't hardcode eth, wlan, ath.. Either read from main - // proxy config file or get a better, portable way to decide all - // interfaces on the system. - - /* First try ioctl on eth interfaces */ - if ((addr = get_local_addr_by_interface("eth")) != - inet_addr(TRIVIAL_LOCAL_ADDR)) { - return addr; - } - - /* First try ioctl on wlan interfaces */ - if ((addr = get_local_addr_by_interface("wlan")) != - inet_addr(TRIVIAL_LOCAL_ADDR)) { - return addr; - } - - /* First try ioctl on eth interfaces */ - if ((addr = get_local_addr_by_interface("ath")) != - inet_addr(TRIVIAL_LOCAL_ADDR)) { - return addr; - } - - /* If that is unsuccessful, try uname/gethostbyname */ - if ((addr = get_local_addr_uname()) != inet_addr(TRIVIAL_LOCAL_ADDR)) { - return addr; - } - - /* This is hopeless, return TRIVIAL_IP */ - return(inet_addr(TRIVIAL_LOCAL_ADDR)); -} - - -#else -/*** WIN32 IMPLEMENTATION ***/ - -#include <Winsock2.h> -#include <Ws2tcpip.h> -#include <Iphlpapi.h> -#include <assert.h> -#include "inetfns.h" -#include "eprintf.h" - -#include "netwrap.h" - -/*************************************************************************** - * - * Purpose: Get IP address of local machine - * - * Return: As an unsigned long in network byte order - * - **************************************************************************/ -uint32_t get_local_addr(void) -{ - uint32_t addr; - - PIP_ADAPTER_INFO pAdapterInfo; - PIP_ADAPTER_INFO pai; - - ULONG OutBufLen = 0; - - addr = inet_addr(TRIVIAL_LOCAL_ADDR); - - GetAdaptersInfo(NULL, &OutBufLen); - pAdapterInfo = (PIP_ADAPTER_INFO)malloc(OutBufLen); - GetAdaptersInfo(pAdapterInfo, &OutBufLen); - - pai = pAdapterInfo; - while (pai) { - if (pai->GatewayList.IpAddress.String[0] != 0) - addr = inet_addr(pai->IpAddressList.IpAddress.String); - pai = pai->Next; - } - free(pAdapterInfo); - return addr; - -} - -uint32_t -get_local_addr_eth() -{ - return get_local_addr(); -} - -uint32_t -name_to_addr(const char *name) -{ - uint32_t ret_val = 0; - int err = 0; - struct addrinfo hints; - struct addrinfo* res = NULL; - - hints.ai_flags = 0; - hints.ai_family = PF_INET; - hints.ai_socktype = 0; - hints.ai_protocol = 0; - hints.ai_addrlen = 0; - hints.ai_canonname = NULL; - hints.ai_addr = NULL; - hints.ai_next = NULL; - - err = getaddrinfo(name, // const char* nodename, - NULL, // const char* servname, - &hints, // const struct addrinfo* hints, - &res); // struct addrinfo** res - - if (0 == err) { - struct sockaddr_in *addr; - - assert(NULL != res); - assert(NULL != res->ai_addr); - addr = (struct sockaddr_in*)res->ai_addr; - assert(PF_INET == addr->sin_family); - - ret_val = addr->sin_addr.S_un.S_addr; - freeaddrinfo(res); - return ret_val; - } else { - weprintf("getaddrinfo(%s) failed: %s", name, strerror(WSAGetLastError())); - return 0; - } -} - -uint32_t -get_local_addr_uname() -{ - char *buf; - int buf_size = 1024; - uint32_t ret; - - buf = calloc(buf_size, 1); - assert(NULL != buf); - - if (0 == gethostname(buf, buf_size)) { - ret = name_to_addr(buf); - } else { - weprintf("Unable to retrieve host name!"); - ret = 0; - } - free(buf); - - return ret; -} -/* -uint32_t -get_local_addr() -{ - // - retrieve information about all network adapters - // - look for the first non-loopback interface - DWORD err = 0; - PIP_ADAPTER_ADDRESSES addresses = NULL; - ULONG size; - uint32_t lb_addr, ret_val; - - lb_addr = inet_addr("127.0.0.1"); - - // allocate a Real Large Buffer hoping that it's big enough - size = sizeof(IP_ADAPTER_ADDRESSES) * 64; - addresses = (PIP_ADAPTER_ADDRESSES)calloc(size, 1); - assert(NULL != addresses); - - err = GetAdaptersAddresses(AF_INET, GAA_FLAG_SKIP_ANYCAST || GAA_FLAG_SKIP_FRIENDLY_NAME || GAA_FLAG_SKIP_MULTICAST || GAA_FLAG_SKIP_DNS_SERVER, NULL, addresses, &size); - switch(err) - { - case ERROR_SUCCESS: - while (NULL != addresses) { - PIP_ADAPTER_UNICAST_ADDRESS addr = addresses->FirstUnicastAddress; - while (NULL != addr) { - if (AF_INET == addr->Address.lpSockaddr->sa_family && ((SOCKADDR_IN*)addr->Address.lpSockaddr)->sin_addr.S_un.S_addr != lb_addr) { - ret_val = ((SOCKADDR_IN*)addr->Address.lpSockaddr)->sin_addr.S_un.S_addr; - free(addresses); - return ret_val; - } - addr = addr->Next; - } - addresses = addresses->Next; - } - break; - case ERROR_NOT_ENOUGH_MEMORY: - weprintf("GetAdaptersAddresses returned NOT ENOUGH MEMORY!"); - break; - case ERROR_BUFFER_OVERFLOW: - weprintf("GetAdaptersAddresses returned BUFFER OVERFLOW\n"); - break; - case ERROR_INVALID_PARAMETER: - weprintf("GetAdaptersAddresses returned INVALID PARAMETER\n"); - break; - default: - weprintf("GetAdaptersAddresses returned unknown return code\n"); - break; - } - free(addresses); - return 0; -} -*/ - -#endif //_WIN32 +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <assert.h> + +#ifndef _WIN32 + + #include <sys/types.h> + #include <netinet/in.h> + #include <arpa/inet.h> + #include <sys/utsname.h> + #include <netdb.h> +//extern int h_errno; + #include <sys/ioctl.h> + #include <net/if.h> + + #include <sys/sysctl.h> +#endif + +#include "eprintf.h" + + +#define TRIVIAL_LOCAL_ADDR "127.0.0.1" +#define MAX_NUM_INTERFACES 3 +#define IFNAME_LEN 256 + +#ifndef _WIN32 +extern int close(int); +/*************************************************************************** + * + * Purpose: Get IP address of local machine by ioctl on eth0-ethk + * + * Return: As an unsigned long in network byte order + * + **************************************************************************/ +uint32_t get_local_addr_eth(void) +{ + int i, tempfd; + struct sockaddr_in addr; + char ifname[IFNAME_LEN]; + struct ifreq ifr; + + for (i = 0; i < MAX_NUM_INTERFACES; i++) { + sprintf(ifname, "eth%d", i); + strcpy(ifr.ifr_name, ifname); + tempfd = socket(AF_INET, SOCK_DGRAM, 0); + + if (-1 != ioctl(tempfd, SIOCGIFFLAGS, (char *) &ifr)) { + if (0 != (ifr.ifr_flags & IFF_UP)) { + if (-1 != ioctl(tempfd, SIOCGIFADDR, (char *) &ifr)) { + addr = *((struct sockaddr_in *) &ifr.ifr_addr); + close(tempfd); + return addr.sin_addr.s_addr; + } + } + } + close(tempfd); + } + return inet_addr(TRIVIAL_LOCAL_ADDR); +} + +/*************************************************************************** + * + * Purpose: Get the IP address of an arbitrary machine + * given the name of the machine + * + * Return: As an unsigned long in network byte order + * + **************************************************************************/ +uint32_t name_to_addr(const char *name) +{ + int i; + struct hostent *hptr = gethostbyname(name); + if (!hptr) { + weprintf("gethostbyname(%s) failed", name); + } else { + for (i = 0; i < hptr->h_length / sizeof(uint32_t); i++) { + uint32_t addr = *((uint32_t *) hptr->h_addr_list[i]); + if (inet_addr(TRIVIAL_LOCAL_ADDR) != addr) { + return addr; + } + } + } + return 0; +} + +/*************************************************************************** + * + * Purpose: Get IP address of local machine by uname/gethostbyname + * + * Return: As an unsigned long in network byte order + * + **************************************************************************/ +uint32_t get_local_addr_uname(void) +{ + struct utsname myname; + uint32_t addr = 0; + + if (uname(&myname) < 0) { + weprintf("uname failed:"); + } else { + addr = name_to_addr(myname.nodename); + } + + if (addr == 0) { + return inet_addr(TRIVIAL_LOCAL_ADDR); + } else { + return addr; + } +} + +/*************************************************************************** + * + * Purpose: Get IP address of local machine by trying out all possible + * interfaces starting with interfaceName. For eg:, if interfaceName = "eth", + * try out eth0, eth1, eth2, etc. + * + * Return: As an unsigned long in network byte order + * + **************************************************************************/ +uint32_t get_local_addr_by_interface(char *interfaceName) +{ + int i, tempfd; + struct sockaddr_in addr; + char ifname[IFNAME_LEN]; + struct ifreq ifr; + + for (i = 0; i < MAX_NUM_INTERFACES; i++) { + sprintf(ifname, "%s%d", interfaceName, i); + strcpy(ifr.ifr_name, ifname); + tempfd = socket(AF_INET, SOCK_DGRAM, 0); + + if (-1 != ioctl(tempfd, SIOCGIFFLAGS, (char *) &ifr)) { + if (0 != (ifr.ifr_flags & IFF_UP)) { + if (-1 != ioctl(tempfd, SIOCGIFADDR, (char *) &ifr)) { + addr = *((struct sockaddr_in *) &ifr.ifr_addr); + close(tempfd); + return addr.sin_addr.s_addr; + } + } + } + close(tempfd); + } + return inet_addr(TRIVIAL_LOCAL_ADDR); +} + +/*************************************************************************** + * + * Purpose: Get IP address of local machine + * + * Return: As an unsigned long in network byte order + * + **************************************************************************/ +uint32_t get_local_addr(void) +{ + uint32_t addr; + + // TODO Don't hardcode eth, wlan, ath.. Either read from main + // proxy config file or get a better, portable way to decide all + // interfaces on the system. + + /* First try ioctl on eth interfaces */ + if ((addr = get_local_addr_by_interface("eth")) != + inet_addr(TRIVIAL_LOCAL_ADDR)) { + return addr; + } + + /* First try ioctl on wlan interfaces */ + if ((addr = get_local_addr_by_interface("wlan")) != + inet_addr(TRIVIAL_LOCAL_ADDR)) { + return addr; + } + + /* First try ioctl on eth interfaces */ + if ((addr = get_local_addr_by_interface("ath")) != + inet_addr(TRIVIAL_LOCAL_ADDR)) { + return addr; + } + + /* If that is unsuccessful, try uname/gethostbyname */ + if ((addr = get_local_addr_uname()) != inet_addr(TRIVIAL_LOCAL_ADDR)) { + return addr; + } + + /* This is hopeless, return TRIVIAL_IP */ + return inet_addr(TRIVIAL_LOCAL_ADDR); +} + +#else +/*** WIN32 IMPLEMENTATION ***/ + +#include <Winsock2.h> +#include <Ws2tcpip.h> +#include <Iphlpapi.h> +#include <assert.h> +#include "inetfns.h" +#include "eprintf.h" + +#include "netwrap.h" + +/*************************************************************************** + * + * Purpose: Get IP address of local machine + * + * Return: As an unsigned long in network byte order + * + **************************************************************************/ +uint32_t get_local_addr(void) +{ + uint32_t addr; + + PIP_ADAPTER_INFO pAdapterInfo; + PIP_ADAPTER_INFO pai; + + ULONG OutBufLen = 0; + + addr = inet_addr(TRIVIAL_LOCAL_ADDR); + + GetAdaptersInfo(NULL, &OutBufLen); + pAdapterInfo = (PIP_ADAPTER_INFO) malloc(OutBufLen); + GetAdaptersInfo(pAdapterInfo, &OutBufLen); + + pai = pAdapterInfo; + while (pai) { + if (pai->GatewayList.IpAddress.String[0] != 0) { + addr = inet_addr(pai->IpAddressList.IpAddress.String); + } + pai = pai->Next; + } + free(pAdapterInfo); + return addr; +} + +uint32_t get_local_addr_eth() +{ + return get_local_addr(); +} + +uint32_t name_to_addr(const char *name) +{ + uint32_t ret_val = 0; + int err = 0; + struct addrinfo hints; + struct addrinfo *res = NULL; + + hints.ai_flags = 0; + hints.ai_family = PF_INET; + hints.ai_socktype = 0; + hints.ai_protocol = 0; + hints.ai_addrlen = 0; + hints.ai_canonname = NULL; + hints.ai_addr = NULL; + hints.ai_next = NULL; + + err = getaddrinfo(name, // const char* nodename, + NULL, // const char* servname, + &hints, // const struct addrinfo* hints, + &res); // struct addrinfo** res + + if (0 == err) { + struct sockaddr_in *addr; + + assert(NULL != res); + assert(NULL != res->ai_addr); + addr = (struct sockaddr_in *) res->ai_addr; + assert(PF_INET == addr->sin_family); + + ret_val = addr->sin_addr.S_un.S_addr; + freeaddrinfo(res); + return ret_val; + } else { + weprintf("getaddrinfo(%s) failed: %s", name, strerror(WSAGetLastError())); + return 0; + } +} + +uint32_t get_local_addr_uname() +{ + char *buf; + int buf_size = 1024; + uint32_t ret; + + buf = calloc(buf_size, 1); + assert(NULL != buf); + + if (0 == gethostname(buf, buf_size)) { + ret = name_to_addr(buf); + } else { + weprintf("Unable to retrieve host name!"); + ret = 0; + } + free(buf); + + return ret; +} + +/* + * uint32_t + * get_local_addr() + * { + * // - retrieve information about all network adapters + * // - look for the first non-loopback interface + * DWORD err = 0; + * PIP_ADAPTER_ADDRESSES addresses = NULL; + * ULONG size; + * uint32_t lb_addr, ret_val; + * + * lb_addr = inet_addr("127.0.0.1"); + * + * // allocate a Real Large Buffer hoping that it's big enough + * size = sizeof(IP_ADAPTER_ADDRESSES) * 64; + * addresses = (PIP_ADAPTER_ADDRESSES)calloc(size, 1); + * assert(NULL != addresses); + * + * err = GetAdaptersAddresses(AF_INET, GAA_FLAG_SKIP_ANYCAST || GAA_FLAG_SKIP_FRIENDLY_NAME || GAA_FLAG_SKIP_MULTICAST || GAA_FLAG_SKIP_DNS_SERVER, NULL, addresses, &size); + * switch(err) + * { + * case ERROR_SUCCESS: + * while (NULL != addresses) { + * PIP_ADAPTER_UNICAST_ADDRESS addr = addresses->FirstUnicastAddress; + * while (NULL != addr) { + * if (AF_INET == addr->Address.lpSockaddr->sa_family && ((SOCKADDR_IN*)addr->Address.lpSockaddr)->sin_addr.S_un.S_addr != lb_addr) { + * ret_val = ((SOCKADDR_IN*)addr->Address.lpSockaddr)->sin_addr.S_un.S_addr; + * free(addresses); + * return ret_val; + * } + * addr = addr->Next; + * } + * addresses = addresses->Next; + * } + * break; + * case ERROR_NOT_ENOUGH_MEMORY: + * weprintf("GetAdaptersAddresses returned NOT ENOUGH MEMORY!"); + * break; + * case ERROR_BUFFER_OVERFLOW: + * weprintf("GetAdaptersAddresses returned BUFFER OVERFLOW\n"); + * break; + * case ERROR_INVALID_PARAMETER: + * weprintf("GetAdaptersAddresses returned INVALID PARAMETER\n"); + * break; + * default: + * weprintf("GetAdaptersAddresses returned unknown return code\n"); + * break; + * } + * free(addresses); + * return 0; + * } + */ + +#endif //_WIN32 === modified file 'i3/utils/inetfns.h' --- i3/utils/inetfns.h 2010-01-06 22:17:32 +0000 +++ i3/utils/inetfns.h 2010-02-11 11:49:47 +0000 @@ -1,17 +1,17 @@ -#ifndef _INET_FNS_H -#define _INET_FNS_H - +#ifndef _INET_FNS_H +#define _INET_FNS_H + /* stg: under cygwin, _WIN32 can be defined if win32api header files get included */ #if defined(_WIN32) - #include "fwint.h" -#else - #include <inttypes.h> -#endif - -/* Get address of local machine */ -uint32_t get_local_addr_eth(void); -uint32_t name_to_addr(const char *); -uint32_t get_local_addr_uname(void); -uint32_t get_local_addr(void); - -#endif + #include "fwint.h" +#else + #include <inttypes.h> +#endif + +/* Get address of local machine */ +uint32_t get_local_addr_eth(void); +uint32_t name_to_addr(const char *); +uint32_t get_local_addr_uname(void); +uint32_t get_local_addr(void); + +#endif === modified file 'i3/utils/netwrap.h' --- i3/utils/netwrap.h 2009-12-11 22:49:11 +0000 +++ i3/utils/netwrap.h 2010-02-11 11:49:47 +0000 @@ -20,127 +20,127 @@ extern const char *inet_ntop(const int af, const void *src, char *dst, const size_t cnt); /* additional error numbers supported in POSIX */ -#define EPERM 1 /* Operation not permitted */ -#define ENOENT 2 /* No such file or directory */ -#define ESRCH 3 /* No such process */ -#define EINTR 4 /* Interrupted system call */ -#define EIO 5 /* I/O error */ -#define ENXIO 6 /* No such device or address */ -#define E2BIG 7 /* Arg list too long */ -#define ENOEXEC 8 /* Exec format error */ -#define EBADF 9 /* Bad file number */ -#define ECHILD 10 /* No child processes */ -#define EAGAIN 11 /* Try again */ -#define ENOMEM 12 /* Out of memory */ -#define EACCES 13 /* Permission denied */ -#define EFAULT 14 /* Bad address */ -#define ENOTBLK 15 /* Block device required */ -#define EBUSY 16 /* Device or resource busy */ -#define EEXIST 17 /* File exists */ -#define EXDEV 18 /* Cross-device link */ -#define ENODEV 19 /* No such device */ -#define ENOTDIR 20 /* Not a directory */ -#define EISDIR 21 /* Is a directory */ -#define EINVAL 22 /* Invalid argument */ -#define ENFILE 23 /* File table overflow */ -#define EMFILE 24 /* Too many open files */ -#define ENOTTY 25 /* Not a typewriter */ -#define ETXTBSY 26 /* Text file busy */ -#define EFBIG 27 /* File too large */ -#define ENOSPC 28 /* No space left on device */ -#define ESPIPE 29 /* Illegal seek */ -#define EROFS 30 /* Read-only file system */ -#define EMLINK 31 /* Too many links */ -#define EPIPE 32 /* Broken pipe */ -#define EDOM 33 /* Math argument out of domain of func */ -#define ERANGE 34 /* Math result not representable */ -#define ELOOP 40 /* Too many symbolic links encountered */ -#define EWOULDBLOCK EAGAIN /* Operation would block */ -#define ENOMSG 42 /* No message of desired type */ -#define EIDRM 43 /* Identifier removed */ -#define ECHRNG 44 /* Channel number out of range */ -#define EL2NSYNC 45 /* Level 2 not synchronized */ -#define EL3HLT 46 /* Level 3 halted */ -#define EL3RST 47 /* Level 3 reset */ -#define ELNRNG 48 /* Link number out of range */ -#define EUNATCH 49 /* Protocol driver not attached */ -#define ENOCSI 50 /* No CSI structure available */ -#define EL2HLT 51 /* Level 2 halted */ -#define EBADE 52 /* Invalid exchange */ -#define EBADR 53 /* Invalid request descriptor */ -#define EXFULL 54 /* Exchange full */ -#define ENOANO 55 /* No anode */ -#define EBADRQC 56 /* Invalid request code */ -#define EBADSLT 57 /* Invalid slot */ - -#define EDEADLOCK EDEADLK - -#define EBFONT 59 /* Bad font file format */ -#define ENOSTR 60 /* Device not a stream */ -#define ENODATA 61 /* No data available */ -#define ETIME 62 /* Timer expired */ -#define ENOSR 63 /* Out of streams resources */ -#define ENONET 64 /* Machine is not on the network */ -#define ENOPKG 65 /* Package not installed */ -#define EREMOTE 66 /* Object is remote */ -#define ENOLINK 67 /* Link has been severed */ -#define EADV 68 /* Advertise error */ -#define ESRMNT 69 /* Srmount error */ -#define ECOMM 70 /* Communication error on send */ -#define EPROTO 71 /* Protocol error */ -#define EMULTIHOP 72 /* Multihop attempted */ -#define EDOTDOT 73 /* RFS specific error */ -#define EBADMSG 74 /* Not a data message */ -#define EOVERFLOW 75 /* Value too large for defined data type */ -#define ENOTUNIQ 76 /* Name not unique on network */ -#define EBADFD 77 /* File descriptor in bad state */ -#define EREMCHG 78 /* Remote address changed */ -#define ELIBACC 79 /* Can not access a needed shared library */ -#define ELIBBAD 80 /* Accessing a corrupted shared library */ -#define ELIBSCN 81 /* .lib section in a.out corrupted */ -#define ELIBMAX 82 /* Attempting to link in too many shared libraries */ -#define ELIBEXEC 83 /* Cannot exec a shared library directly */ -#define ERESTART 85 /* Interrupted system call should be restarted */ -#define ESTRPIPE 86 /* Streams pipe error */ -#define EUSERS 87 /* Too many users */ -#define ENOTSOCK 88 /* Socket operation on non-socket */ -#define EDESTADDRREQ 89 /* Destination address required */ -#define EMSGSIZE 90 /* Message too long */ -#define EPROTOTYPE 91 /* Protocol wrong type for socket */ -#define ENOPROTOOPT 92 /* Protocol not available */ -#define EPROTONOSUPPORT 93 /* Protocol not supported */ -#define ESOCKTNOSUPPORT 94 /* Socket type not supported */ -#define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */ -#define EPFNOSUPPORT 96 /* Protocol family not supported */ -#define EAFNOSUPPORT 97 /* Address family not supported by protocol */ -#define EADDRINUSE 98 /* Address already in use */ -#define EADDRNOTAVAIL 99 /* Cannot assign requested address */ -#define ENETDOWN 100 /* Network is down */ -#define ENETUNREACH 101 /* Network is unreachable */ -#define ENETRESET 102 /* Network dropped connection because of reset */ -#define ECONNABORTED 103 /* Software caused connection abort */ -#define ECONNRESET 104 /* Connection reset by peer */ -#define ENOBUFS 105 /* No buffer space available */ -#define EISCONN 106 /* Transport endpoint is already connected */ -#define ENOTCONN 107 /* Transport endpoint is not connected */ -#define ESHUTDOWN 108 /* Cannot send after transport endpoint shutdown */ -#define ETOOMANYREFS 109 /* Too many references: cannot splice */ -#define ETIMEDOUT 110 /* Connection timed out */ -#define ECONNREFUSED 111 /* Connection refused */ -#define EHOSTDOWN 112 /* Host is down */ -#define EHOSTUNREACH 113 /* No route to host */ -#define EALREADY 114 /* Operation already in progress */ -#define EINPROGRESS 115 /* Operation now in progress */ -#define ESTALE 116 /* Stale NFS file handle */ -#define EUCLEAN 117 /* Structure needs cleaning */ -#define ENOTNAM 118 /* Not a XENIX named type file */ -#define ENAVAIL 119 /* No XENIX semaphores available */ -#define EISNAM 120 /* Is a named type file */ -#define EREMOTEIO 121 /* Remote I/O error */ -#define EDQUOT 122 /* Quota exceeded */ - -#define ENOMEDIUM 123 /* No medium found */ -#define EMEDIUMTYPE 124 /* Wrong medium type */ +#define EPERM 1 /* Operation not permitted */ +#define ENOENT 2 /* No such file or directory */ +#define ESRCH 3 /* No such process */ +#define EINTR 4 /* Interrupted system call */ +#define EIO 5 /* I/O error */ +#define ENXIO 6 /* No such device or address */ +#define E2BIG 7 /* Arg list too long */ +#define ENOEXEC 8 /* Exec format error */ +#define EBADF 9 /* Bad file number */ +#define ECHILD 10 /* No child processes */ +#define EAGAIN 11 /* Try again */ +#define ENOMEM 12 /* Out of memory */ +#define EACCES 13 /* Permission denied */ +#define EFAULT 14 /* Bad address */ +#define ENOTBLK 15 /* Block device required */ +#define EBUSY 16 /* Device or resource busy */ +#define EEXIST 17 /* File exists */ +#define EXDEV 18 /* Cross-device link */ +#define ENODEV 19 /* No such device */ +#define ENOTDIR 20 /* Not a directory */ +#define EISDIR 21 /* Is a directory */ +#define EINVAL 22 /* Invalid argument */ +#define ENFILE 23 /* File table overflow */ +#define EMFILE 24 /* Too many open files */ +#define ENOTTY 25 /* Not a typewriter */ +#define ETXTBSY 26 /* Text file busy */ +#define EFBIG 27 /* File too large */ +#define ENOSPC 28 /* No space left on device */ +#define ESPIPE 29 /* Illegal seek */ +#define EROFS 30 /* Read-only file system */ +#define EMLINK 31 /* Too many links */ +#define EPIPE 32 /* Broken pipe */ +#define EDOM 33 /* Math argument out of domain of func */ +#define ERANGE 34 /* Math result not representable */ +#define ELOOP 40 /* Too many symbolic links encountered */ +#define EWOULDBLOCK EAGAIN /* Operation would block */ +#define ENOMSG 42 /* No message of desired type */ +#define EIDRM 43 /* Identifier removed */ +#define ECHRNG 44 /* Channel number out of range */ +#define EL2NSYNC 45 /* Level 2 not synchronized */ +#define EL3HLT 46 /* Level 3 halted */ +#define EL3RST 47 /* Level 3 reset */ +#define ELNRNG 48 /* Link number out of range */ +#define EUNATCH 49 /* Protocol driver not attached */ +#define ENOCSI 50 /* No CSI structure available */ +#define EL2HLT 51 /* Level 2 halted */ +#define EBADE 52 /* Invalid exchange */ +#define EBADR 53 /* Invalid request descriptor */ +#define EXFULL 54 /* Exchange full */ +#define ENOANO 55 /* No anode */ +#define EBADRQC 56 /* Invalid request code */ +#define EBADSLT 57 /* Invalid slot */ + +#define EDEADLOCK EDEADLK + +#define EBFONT 59 /* Bad font file format */ +#define ENOSTR 60 /* Device not a stream */ +#define ENODATA 61 /* No data available */ +#define ETIME 62 /* Timer expired */ +#define ENOSR 63 /* Out of streams resources */ +#define ENONET 64 /* Machine is not on the network */ +#define ENOPKG 65 /* Package not installed */ +#define EREMOTE 66 /* Object is remote */ +#define ENOLINK 67 /* Link has been severed */ +#define EADV 68 /* Advertise error */ +#define ESRMNT 69 /* Srmount error */ +#define ECOMM 70 /* Communication error on send */ +#define EPROTO 71 /* Protocol error */ +#define EMULTIHOP 72 /* Multihop attempted */ +#define EDOTDOT 73 /* RFS specific error */ +#define EBADMSG 74 /* Not a data message */ +#define EOVERFLOW 75 /* Value too large for defined data type */ +#define ENOTUNIQ 76 /* Name not unique on network */ +#define EBADFD 77 /* File descriptor in bad state */ +#define EREMCHG 78 /* Remote address changed */ +#define ELIBACC 79 /* Can not access a needed shared library */ +#define ELIBBAD 80 /* Accessing a corrupted shared library */ +#define ELIBSCN 81 /* .lib section in a.out corrupted */ +#define ELIBMAX 82 /* Attempting to link in too many shared libraries */ +#define ELIBEXEC 83 /* Cannot exec a shared library directly */ +#define ERESTART 85 /* Interrupted system call should be restarted */ +#define ESTRPIPE 86 /* Streams pipe error */ +#define EUSERS 87 /* Too many users */ +#define ENOTSOCK 88 /* Socket operation on non-socket */ +#define EDESTADDRREQ 89 /* Destination address required */ +#define EMSGSIZE 90 /* Message too long */ +#define EPROTOTYPE 91 /* Protocol wrong type for socket */ +#define ENOPROTOOPT 92 /* Protocol not available */ +#define EPROTONOSUPPORT 93 /* Protocol not supported */ +#define ESOCKTNOSUPPORT 94 /* Socket type not supported */ +#define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */ +#define EPFNOSUPPORT 96 /* Protocol family not supported */ +#define EAFNOSUPPORT 97 /* Address family not supported by protocol */ +#define EADDRINUSE 98 /* Address already in use */ +#define EADDRNOTAVAIL 99 /* Cannot assign requested address */ +#define ENETDOWN 100 /* Network is down */ +#define ENETUNREACH 101 /* Network is unreachable */ +#define ENETRESET 102 /* Network dropped connection because of reset */ +#define ECONNABORTED 103 /* Software caused connection abort */ +#define ECONNRESET 104 /* Connection reset by peer */ +#define ENOBUFS 105 /* No buffer space available */ +#define EISCONN 106 /* Transport endpoint is already connected */ +#define ENOTCONN 107 /* Transport endpoint is not connected */ +#define ESHUTDOWN 108 /* Cannot send after transport endpoint shutdown */ +#define ETOOMANYREFS 109 /* Too many references: cannot splice */ +#define ETIMEDOUT 110 /* Connection timed out */ +#define ECONNREFUSED 111 /* Connection refused */ +#define EHOSTDOWN 112 /* Host is down */ +#define EHOSTUNREACH 113 /* No route to host */ +#define EALREADY 114 /* Operation already in progress */ +#define EINPROGRESS 115 /* Operation now in progress */ +#define ESTALE 116 /* Stale NFS file handle */ +#define EUCLEAN 117 /* Structure needs cleaning */ +#define ENOTNAM 118 /* Not a XENIX named type file */ +#define ENAVAIL 119 /* No XENIX semaphores available */ +#define EISNAM 120 /* Is a named type file */ +#define EREMOTEIO 121 /* Remote I/O error */ +#define EDQUOT 122 /* Quota exceeded */ + +#define ENOMEDIUM 123 /* No medium found */ +#define EMEDIUMTYPE 124 /* Wrong medium type */ #else /* !_WIN32 */ #include <sys/socket.h> === modified file 'i3/utils/netwrap_posix.c' --- i3/utils/netwrap_posix.c 2009-12-11 22:49:11 +0000 +++ i3/utils/netwrap_posix.c 2010-02-11 11:49:47 +0000 @@ -3,40 +3,35 @@ #include <fcntl.h> #include <errno.h> -int -nw_init(void) -{ - return 0; -} - -int -nw_fini(void) -{ - return 0; -} - -int -nw_close(nw_skt_t socket) +int nw_init(void) +{ + return 0; +} + +int nw_fini(void) +{ + return 0; +} + +int nw_close(nw_skt_t socket) { return close(socket); } -int -nw_error(void) +int nw_error(void) { return errno; } -int -nw_set_nblk(nw_skt_t socket, int nblk) +int nw_set_nblk(nw_skt_t socket, int nblk) { int flags; flags = fcntl(socket, F_GETFL); if (0 != nblk) { - flags |= O_NONBLOCK; + flags |= O_NONBLOCK; } else { - flags &= ~O_NONBLOCK; + flags &= ~O_NONBLOCK; } return (-1 != fcntl(socket, F_SETFL, flags)) ? 0 : -1; } === modified file 'i3/utils/netwrap_win32.c' --- i3/utils/netwrap_win32.c 2009-12-11 22:49:11 +0000 +++ i3/utils/netwrap_win32.c 2010-02-11 11:49:47 +0000 @@ -3,145 +3,138 @@ #include "fwint.h" #include <errno.h> -int -inet_pton(const int af, - const char *src, - void *dst) +int inet_pton(const int af, + const char *src, + void *dst) { int ret = -1; if (AF_INET == af) { - *(uint32_t *)dst = inet_addr(src); - ret = 1; + *(uint32_t *) dst = inet_addr(src); + ret = 1; } else if (AF_INET6 == af) { - INT err; - struct sockaddr_in6 saddr; - INT saddr_len = sizeof(saddr); - - err = WSAStringToAddress((char *)src, // LPTSTR AddressString, - af, // INT AddressFamily, - NULL, // LPWSAPROTOCOL_INFO lpProtocolInfo, - (LPSOCKADDR)&saddr, // LPSOCKADDR lpAddress, - &saddr_len); // LPINT lpAddressLength - if (0 == err) { - memcpy((char *)dst, saddr.sin6_addr.u.Byte, sizeof(struct in6_addr)); - ret = 1; - } else { - ret = 0; - } + INT err; + struct sockaddr_in6 saddr; + INT saddr_len = sizeof(saddr); + + err = WSAStringToAddress((char *) src, // LPTSTR AddressString, + af, // INT AddressFamily, + NULL, // LPWSAPROTOCOL_INFO lpProtocolInfo, + (LPSOCKADDR) &saddr, // LPSOCKADDR lpAddress, + &saddr_len); // LPINT lpAddressLength + if (0 == err) { + memcpy((char *) dst, saddr.sin6_addr.u.Byte, sizeof(struct in6_addr)); + ret = 1; + } else { + ret = 0; + } } return ret; } -const char * -inet_ntop(const int af, - const void *src, - char *dst, - const size_t cnt) +const char *inet_ntop(const int af, + const void *src, + char *dst, + const size_t cnt) { char *ret = NULL; if (AF_INET == af) { - char *res = inet_ntoa(*(struct in_addr *)src); - if (cnt > strlen(res)) { - strcpy(dst, res); - ret = dst; - } + char *res = inet_ntoa(*(struct in_addr *) src); + if (cnt > strlen(res)) { + strcpy(dst, res); + ret = dst; + } } else if (AF_INET6 == af) { - // WSAAddressToString() does a bit more than we need + // WSAAddressToString() does a bit more than we need } return ret; } -int -nw_init(void) +int nw_init(void) { WORD wVersionRequested; WSADATA wsaData; int err; - + wVersionRequested = MAKEWORD( 2, 2 ); - - err = WSAStartup( wVersionRequested, &wsaData ); - if ( err == 0 ) { - if ( LOBYTE( wsaData.wVersion ) == 2 && HIBYTE( wsaData.wVersion ) == 2 ) { - return 0; - } - WSACleanup( ); + + err = WSAStartup( wVersionRequested, &wsaData ); + if (err == 0) { + if (LOBYTE( wsaData.wVersion ) == 2 && HIBYTE( wsaData.wVersion ) == 2) { + return 0; + } + WSACleanup( ); } - + return 1; } -int -nw_fini(void) +int nw_fini(void) { return WSACleanup(); } -int -nw_close(nw_skt_t socket) +int nw_close(nw_skt_t socket) { return closesocket(socket); } -int -nw_error(void) +int nw_error(void) { // return UNIX errno values int err = WSAGetLastError(); switch (err) { - case WSANOTINITIALISED: - case WSAEINVAL: - case WSAEINPROGRESS: - case WSAEADDRNOTAVAIL: - case WSAEAFNOSUPPORT: - return EINVAL; - case WSAEINTR: - return EINTR; - case WSAENOTSOCK: - return EBADF; - case WSAENETDOWN: - return ENETDOWN; - case WSAEACCES: - return EAFNOSUPPORT; - case WSAEFAULT: - return EFAULT; - case WSAENETRESET: - return ECONNRESET; - case WSAENOBUFS: - return ENOBUFS; - case WSAENOTCONN: - return ENOTCONN; - case WSAEOPNOTSUPP: - return EOPNOTSUPP; - case WSAESHUTDOWN: - return ENOTCONN; - case WSAEWOULDBLOCK: - return EWOULDBLOCK; - case WSAEMSGSIZE: - return EMSGSIZE; - case WSAEHOSTUNREACH: - return EHOSTUNREACH; - case WSAECONNABORTED: - case WSAECONNRESET: - return ECONNRESET; - case WSAEDESTADDRREQ: - return EDESTADDRREQ; - case WSAENETUNREACH: - return ENETUNREACH; - case WSAETIMEDOUT: - return EHOSTUNREACH; - default: - return err; + case WSANOTINITIALISED: + case WSAEINVAL: + case WSAEINPROGRESS: + case WSAEADDRNOTAVAIL: + case WSAEAFNOSUPPORT: + return EINVAL; + case WSAEINTR: + return EINTR; + case WSAENOTSOCK: + return EBADF; + case WSAENETDOWN: + return ENETDOWN; + case WSAEACCES: + return EAFNOSUPPORT; + case WSAEFAULT: + return EFAULT; + case WSAENETRESET: + return ECONNRESET; + case WSAENOBUFS: + return ENOBUFS; + case WSAENOTCONN: + return ENOTCONN; + case WSAEOPNOTSUPP: + return EOPNOTSUPP; + case WSAESHUTDOWN: + return ENOTCONN; + case WSAEWOULDBLOCK: + return EWOULDBLOCK; + case WSAEMSGSIZE: + return EMSGSIZE; + case WSAEHOSTUNREACH: + return EHOSTUNREACH; + case WSAECONNABORTED: + case WSAECONNRESET: + return ECONNRESET; + case WSAEDESTADDRREQ: + return EDESTADDRREQ; + case WSAENETUNREACH: + return ENETUNREACH; + case WSAETIMEDOUT: + return EHOSTUNREACH; + default: + return err; } } -int -nw_set_nblk(nw_skt_t socket, int nblk) +int nw_set_nblk(nw_skt_t socket, int nblk) { - u_long par = (u_long)nblk; + u_long par = (u_long) nblk; return ioctlsocket(socket, FIONBIO, &par); } === modified file 'i3/utils/utils.h' --- i3/utils/utils.h 2009-12-11 22:49:11 +0000 +++ i3/utils/utils.h 2010-02-11 11:49:47 +0000 @@ -1,9 +1,9 @@ -#ifndef _UTILS_H -#define _UTILS_H - -#include "eprintf.h" -#include "byteorder.h" -#include "inetfns.h" -#include "gen_utils.h" - -#endif +#ifndef _UTILS_H +#define _UTILS_H + +#include "eprintf.h" +#include "byteorder.h" +#include "inetfns.h" +#include "gen_utils.h" + +#endif