Navigation


Changeset 706:4ffbc9f1e922 in freeDiameter for libfdproto/lists.c


Ignore:
Timestamp:
Feb 9, 2011, 3:26:58 PM (13 years ago)
Author:
Sebastien Decugis <sdecugis@nict.go.jp>
Branch:
default
Phase:
public
Message:

Large UNTESTED commit with the following changes:

  • Improved DiameterIdentity? handling (esp. interationalization issues), and improve efficiency of some string operations in peers, sessions, and dictionary modules (closes #7)
  • Cleanup in the session module to free only unreferenced sessions (#16)
  • Removed fd_cpu_flush_cache(), replaced by more robust alternatives.
  • Improved peer state machine algorithm to counter SCTP multistream race condition.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • libfdproto/lists.c

    r662 r706  
    163163
    164164
    165 /********************************************************************************************************/
    166 /* Hash function -- credits to Austin Appleby, thank you ^^ */
    167 /* See http://murmurhash.googlepages.com for more information on this function */
    168 
    169 /* the strings are NOT always aligned properly (ex: received in RADIUS message), so we use the aligned MurmurHash2 function as needed */
    170 #define _HASH_MIX(h,k,m) { k *= m; k ^= k >> r; k *= m; h *= m; h ^= k; }
    171 uint32_t fd_hash ( char * string, size_t len )
    172 {
    173         uint32_t hash = len;
    174         char * data = string;
    175        
    176         const unsigned int m = 0x5bd1e995;
    177         const int r = 24;
    178         int align = (long)string & 3;
    179        
    180         if (!align || (len < 4)) {
    181                
    182                 /* In case data is aligned, MurmurHash2 function */
    183                 while(len >= 4)
    184                 {
    185                         /* Mix 4 bytes at a time into the hash */
    186                         uint32_t k = *(uint32_t *)data; /* We don't care about the byte order */
    187 
    188                         _HASH_MIX(hash, k, m);
    189 
    190                         data += 4;
    191                         len -= 4;
    192                 }
    193 
    194                 /* Handle the last few bytes of the input */
    195                 switch(len) {
    196                         case 3: hash ^= data[2] << 16;
    197                         case 2: hash ^= data[1] << 8;
    198                         case 1: hash ^= data[0];
    199                                 hash *= m;
    200                 }
    201                
    202         } else {
    203                 /* Unaligned data, use alignment-safe slower version */
    204                
    205                 /* Pre-load the temp registers */
    206                 uint32_t t = 0, d = 0;
    207                 switch(align)
    208                 {
    209                         case 1: t |= data[2] << 16;
    210                         case 2: t |= data[1] << 8;
    211                         case 3: t |= data[0];
    212                 }
    213                 t <<= (8 * align);
    214 
    215                 data += 4-align;
    216                 len -= 4-align;
    217                
    218                 /* From this point, "data" can be read by chunks of 4 bytes */
    219                
    220                 int sl = 8 * (4-align);
    221                 int sr = 8 * align;
    222 
    223                 /* Mix */
    224                 while(len >= 4)
    225                 {
    226                         uint32_t k;
    227                        
    228                         d = *(unsigned int *)data;
    229                         k = (t >> sr) | (d << sl);
    230 
    231                         _HASH_MIX(hash, k, m);
    232 
    233                         t = d;
    234 
    235                         data += 4;
    236                         len -= 4;
    237                 }
    238 
    239                 /* Handle leftover data in temp registers */
    240                 d = 0;
    241                 if(len >= align)
    242                 {
    243                         uint32_t k;
    244                        
    245                         switch(align)
    246                         {
    247                         case 3: d |= data[2] << 16;
    248                         case 2: d |= data[1] << 8;
    249                         case 1: d |= data[0];
    250                         }
    251 
    252                         k = (t >> sr) | (d << sl);
    253                         _HASH_MIX(hash, k, m);
    254 
    255                         data += align;
    256                         len -= align;
    257 
    258                         /* Handle tail bytes */
    259 
    260                         switch(len)
    261                         {
    262                         case 3: hash ^= data[2] << 16;
    263                         case 2: hash ^= data[1] << 8;
    264                         case 1: hash ^= data[0];
    265                                         hash *= m;
    266                         };
    267                 }
    268                 else
    269                 {
    270                         switch(len)
    271                         {
    272                         case 3: d |= data[2] << 16;
    273                         case 2: d |= data[1] << 8;
    274                         case 1: d |= data[0];
    275                         case 0: hash ^= (t >> sr) | (d << sl);
    276                                         hash *= m;
    277                         }
    278                 }
    279 
    280 
    281         }
    282 
    283         /* Do a few final mixes of the hash to ensure the last few
    284            bytes are well-incorporated. */
    285         hash ^= hash >> 13;
    286         hash *= m;
    287         hash ^= hash >> 15;
    288 
    289         return hash;
    290 }
Note: See TracChangeset for help on using the changeset viewer.