Changeset 1260:4f6f61e67599 in freeDiameter for extensions/rt_redirect
- Timestamp:
- Mar 24, 2014, 9:21:41 PM (10 years ago)
- Branch:
- default
- Phase:
- public
- Location:
- extensions/rt_redirect
- Files:
-
- 1 added
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
extensions/rt_redirect/CMakeLists.txt
r717 r1260 9 9 redir_fwd.c 10 10 redir_out.c 11 uthash.h 11 12 ) 12 13 -
extensions/rt_redirect/redir_entries.c
r1259 r1260 1 1 /********************************************************************************************************* 2 2 * Software License Agreement (BSD License) * 3 * Author: Sebastien Decugis <sdecugis@freediameter.net> * 3 * Authors: Sebastien Decugis <sdecugis@freediameter.net> * 4 * and Thomas Klausner <tk@giga.or.at> * 4 5 * * 5 * Copyright (c) 2011, WIDE Project and NICT*6 * Copyright (c) 2011, 2014, WIDE Project and NICT * 6 7 * All rights reserved. * 7 8 * * … … 35 36 36 37 #include "rt_redir.h" 38 #include "uthash.h" 37 39 38 40 /* The array with all entries ordered by their data */ 39 41 struct redir_line redirects_usages[H_U_MAX + 1]; 42 43 /* for symmetry reasons, hash tables for all types exist, but only ALL_SESSION and ALL_USER will be used */ 44 struct redir_entry *redirect_hash_table[H_U_MAX+1]; 40 45 41 46 /* Initialize the array */ … … 50 55 51 56 for (i = 0; i <= H_U_MAX; i++) { 57 /* only one of the two will be used for each type, but initialize both to be on the safe side */ 58 59 /* initialize list */ 52 60 CHECK_POSIX( pthread_rwlock_init( &redirects_usages[i].lock, NULL) ); 53 61 fd_list_init( &redirects_usages[i].sentinel, &redirects_usages[i] ); 62 63 /* initialize hash table */ 64 redirect_hash_table[i] = NULL; 54 65 } 55 66 … … 66 77 } 67 78 79 int redir_entry_fini() 80 { 81 int i; 82 struct redir_entry *current_entry, *tmp; 83 84 /* Empty all entries */ 85 CHECK_POSIX_DO( pthread_mutex_lock(&redir_exp_peer_lock), ); 86 for (i = 0; i <= H_U_MAX; i++) { 87 CHECK_POSIX_DO( pthread_rwlock_wrlock( &redirects_usages[i].lock), ); 88 switch(i) { 89 case ALL_SESSION: 90 case ALL_USER: 91 HASH_ITER(hh, redirect_hash_table[i], current_entry, tmp) { 92 HASH_DEL(redirect_hash_table[i], current_entry); 93 CHECK_FCT_DO( redir_entry_destroy(current_entry), ); 94 } 95 break; 96 default: 97 while (!FD_IS_LIST_EMPTY(&redirects_usages[i].sentinel)) { 98 struct redir_entry * e = redirects_usages[i].sentinel.next->o; 99 fd_list_unlink(&e->redir_list); 100 CHECK_FCT_DO( redir_entry_destroy(e), ); 101 } 102 } 103 CHECK_POSIX_DO( pthread_rwlock_unlock( &redirects_usages[i].lock), ); 104 CHECK_POSIX_DO( pthread_rwlock_destroy( &redirects_usages[i].lock), ); 105 } 106 CHECK_POSIX_DO( pthread_mutex_unlock(&redir_exp_peer_lock), ); 107 108 return 0; 109 } 68 110 69 111 /* Create a new redir_entry and add the correct data */ … … 91 133 92 134 entry->type = rhu; 135 /* list entry for putting into redirects_usage; also doubles as pointer into that list so it can be removed easily */ 93 136 fd_list_init(&entry->redir_list, entry); 94 137 /* finally initialize the data */ … … 238 281 { 239 282 struct fd_list * li; 283 struct redir_entry * r = NULL; 240 284 241 285 TRACE_ENTRY("%p", e); … … 245 289 CHECK_POSIX( pthread_rwlock_wrlock( RWLOCK_REDIR(e) ) ); 246 290 247 for (li = redirects_usages[e->type].sentinel.next; li != &redirects_usages[e->type].sentinel; li = li->next) { 248 struct redir_entry * n = li->o; 249 int cmp = redir_entry_cmp_key[e->type](&e->data, &n->data); 250 if (cmp <= 0) 251 break; 252 } 253 254 fd_list_insert_before(li, &e->redir_list); 291 switch (e->type) { 292 case ALL_SESSION: 293 HASH_FIND(hh, redirect_hash_table[e->type], e->data.session.s, e->data.session.l, r); 294 if (r) { 295 /* previously existing entry, delete it from hash and free it */ 296 HASH_DELETE(hh, redirect_hash_table[e->type], r); 297 CHECK_FCT_DO( redir_entry_destroy(r), ); 298 } 299 HASH_ADD_KEYPTR(hh, redirect_hash_table[e->type], e->data.session.s, e->data.session.l, e); 300 break; 301 case ALL_USER: 302 HASH_FIND(hh, redirect_hash_table[e->type], e->data.user.s, e->data.user.l, r); 303 if (r) { 304 /* previously existing entry, delete it from hash and free it */ 305 HASH_DELETE(hh, redirect_hash_table[e->type], r); 306 CHECK_FCT_DO( redir_entry_destroy(r), ); 307 } 308 HASH_ADD_KEYPTR(hh, redirect_hash_table[e->type], e->data.user.s, e->data.user.l, e); 309 break; 310 default: 311 for (li = redirects_usages[e->type].sentinel.next; li != &redirects_usages[e->type].sentinel; li = li->next) { 312 struct redir_entry * n = li->o; 313 int cmp = redir_entry_cmp_key[e->type](&e->data, &n->data); 314 if (cmp <= 0) 315 break; 316 } 317 318 fd_list_insert_before(li, &e->redir_list); 319 break; 320 } 255 321 256 322 /* unLock the line */ … … 263 329 int redir_entry_destroy(struct redir_entry * e) 264 330 { 331 struct redir_entry *match; 265 332 TRACE_ENTRY("%p", e); 266 333 CHECK_PARAMS(e && (e->eyec == REDIR_ENTRY_EYEC)); 267 334 268 /* If the entry is linked, lock the rwlock also */ 269 if (!FD_IS_LIST_EMPTY(&e->redir_list)) { 270 CHECK_POSIX( pthread_rwlock_wrlock( RWLOCK_REDIR(e) ) ); 271 fd_list_unlink(&e->redir_list); 272 CHECK_POSIX( pthread_rwlock_unlock( RWLOCK_REDIR(e) ) ); 335 switch (e->type) { 336 case ALL_SESSION: 337 /* If the entry is in the hash table, lock the rwlock also */ 338 HASH_FIND(hh, redirect_hash_table[e->type], e->data.session.s, e->data.session.l, match); 339 if (match) { 340 /* TODO: check if e == match? */ 341 CHECK_POSIX( pthread_rwlock_wrlock( RWLOCK_REDIR(e) ) ); 342 HASH_DELETE(hh, redirect_hash_table[e->type], match); 343 CHECK_POSIX( pthread_rwlock_unlock( RWLOCK_REDIR(e) ) ); 344 } 345 break; 346 case ALL_USER: 347 /* If the entry is in the hash table, lock the rwlock also */ 348 HASH_FIND(hh, redirect_hash_table[e->type], e->data.user.s, e->data.user.l, match); 349 if (match) { 350 /* TODO: check if e == match? */ 351 CHECK_POSIX( pthread_rwlock_wrlock( RWLOCK_REDIR(e) ) ); 352 HASH_DELETE(hh, redirect_hash_table[e->type], match); 353 CHECK_POSIX( pthread_rwlock_unlock( RWLOCK_REDIR(e) ) ); 354 } 355 break; 356 default: 357 /* If the entry is linked, lock the rwlock also */ 358 if (!FD_IS_LIST_EMPTY(&e->redir_list)) { 359 CHECK_POSIX( pthread_rwlock_wrlock( RWLOCK_REDIR(e) ) ); 360 fd_list_unlink(&e->redir_list); 361 CHECK_POSIX( pthread_rwlock_unlock( RWLOCK_REDIR(e) ) ); 362 } 363 break; 273 364 } 274 365 -
extensions/rt_redirect/redir_out.c
r1259 r1260 1 1 /********************************************************************************************************* 2 2 * Software License Agreement (BSD License) * 3 * Author: Sebastien Decugis <sdecugis@freediameter.net> * 3 * Authors: Sebastien Decugis <sdecugis@freediameter.net> * 4 * and Thomas Klausner <tk@giga.or.at> * 4 5 * * 5 * Copyright (c) 2013, WIDE Project and NICT*6 * Copyright (c) 2013, 2014, WIDE Project and NICT * 6 7 * All rights reserved. * 7 8 * * … … 218 219 } 219 220 221 static int redir_exist_for_type(int rule_type) 222 { 223 int ret; 224 225 switch(rule_type) { 226 case ALL_SESSION: 227 case ALL_USER: 228 ret = redirect_hash_table[rule_type] != NULL; 229 break; 230 default: 231 ret = !FD_IS_LIST_EMPTY(&redirects_usages[rule_type].sentinel); 232 break; 233 } 234 return ret; 235 } 236 237 static int match_message(int rule_type, struct msg *msg, union matchdata *data, struct fd_list * candidates) 238 { 239 struct fd_list * li; 240 struct redir_entry * e = NULL; 241 int ret = 0; 242 243 switch(rule_type) { 244 case ALL_SESSION: 245 HASH_FIND(hh, redirect_hash_table[rule_type], data->session.s, data->session.l, e); 246 if (e) { 247 /* This message matches a rule, apply */ 248 CHECK_FCT_DO( ret = apply_rule(e, msg, candidates), break ); 249 } 250 break; 251 case ALL_USER: 252 HASH_FIND(hh, redirect_hash_table[rule_type], data->user.s, data->user.l, e); 253 if (e) { 254 /* This message matches a rule, apply */ 255 CHECK_FCT_DO( ret = apply_rule(e, msg, candidates), break ); 256 } 257 break; 258 default: 259 /* Attempt each rule we have stored */ 260 for (li = redirects_usages[rule_type].sentinel.next; li != &redirects_usages[rule_type].sentinel; li = li->next) { 261 e = li->o; 262 263 /* Does it match ? */ 264 if (rule_type != ALL_HOST) { /* this one is an exception, we handle it separately */ 265 int cmp = redir_entry_cmp_key[rule_type](data, &e->data); 266 if (cmp > 0) 267 continue; 268 if (cmp < 0) 269 break; 270 } 271 272 /* This rule matches (or we are in ALL_HOST), apply */ 273 CHECK_FCT_DO( ret = apply_rule(e, msg, candidates), break ); 274 275 /* If this was a DONT_CACHE rule, we unlink it, so that it will not be used again */ 276 if (rule_type == DONT_CACHE) { 277 li = li->prev; 278 fd_list_unlink( li->next ); 279 /* We cannot delete here without taking the mutex, which would mean we have first to release the lock... 280 just let expiry garbage collect the rule */ 281 } 282 } 283 } 284 285 return ret; 286 } 220 287 221 288 /* OUT callback */ … … 235 302 } 236 303 237 if ( !FD_IS_LIST_EMPTY(&redirects_usages[i].sentinel)) {304 if (redir_exist_for_type(i)) { 238 305 union matchdata data; 239 306 int nodata; /* The message does not allow to apply this rule, skip */ … … 242 309 CHECK_FCT_DO( ret = get_data_to_match(i, msg, &data, &nodata), goto out ); 243 310 244 /* If this message may match some of our rules */ 245 if (!nodata) { 246 struct fd_list * li; 247 /* Attempt each rule we have stored */ 248 for (li = redirects_usages[i].sentinel.next; li != &redirects_usages[i].sentinel; li = li->next) { 249 struct redir_entry * e = li->o; 250 251 /* Does it match ? */ 252 if (i != ALL_HOST) { /* this one is an exception, we handle it separately */ 253 int cmp = redir_entry_cmp_key[i](&data, &e->data); 254 if (cmp > 0) 255 continue; 256 if (cmp < 0) 257 break; 258 } 259 260 /* This rule matches (or we are in ALL_HOST), apply */ 261 CHECK_FCT_DO( ret = apply_rule(e, msg, candidates), goto out ); 262 263 /* If this was a DONT_CACHE rule, we unlink it, so that it will not be used again */ 264 if (i == DONT_CACHE) { 265 li=li->prev; 266 fd_list_unlink( li->next ); 267 /* We cannot delete here without taking the mutex, which would mean we have first to release the lock... 268 just let expiry garbage collet the rule */ 269 } 270 } 271 } 272 311 /* If data found for this type of rule, then try matching it */ 312 if (!nodata) 313 ret = match_message(i, msg, &data, candidates); 273 314 } 274 315 out: -
extensions/rt_redirect/rt_redir.c
r1259 r1260 1 1 /********************************************************************************************************* 2 2 * Software License Agreement (BSD License) * 3 * Author: Sebastien Decugis <sdecugis@freediameter.net> * 3 * Authors: Sebastien Decugis <sdecugis@freediameter.net> * 4 * and Thomas Klausner <tk@giga.or.at> * 4 5 * * 5 * Copyright (c) 2011, WIDE Project and NICT*6 * Copyright (c) 2011, 2014, WIDE Project and NICT * 6 7 * All rights reserved. * 7 8 * * … … 72 73 void fd_ext_fini(void) 73 74 { 74 int i;75 76 75 /* Unregister the callbacks */ 77 76 if (fwd_hdl) { … … 86 85 87 86 /* Empty all entries */ 88 CHECK_POSIX_DO( pthread_mutex_lock(&redir_exp_peer_lock), ); 89 for (i = 0; i <= H_U_MAX; i++) { 90 CHECK_POSIX_DO( pthread_rwlock_wrlock( &redirects_usages[i].lock), ); 91 while (!FD_IS_LIST_EMPTY(&redirects_usages[i].sentinel)) { 92 struct redir_entry * e = redirects_usages[i].sentinel.next->o; 93 fd_list_unlink(&e->redir_list); 94 CHECK_FCT_DO( redir_entry_destroy(e), ); 95 } 96 CHECK_POSIX_DO( pthread_rwlock_unlock( &redirects_usages[i].lock), ); 97 CHECK_POSIX_DO( pthread_rwlock_destroy( &redirects_usages[i].lock), ); 98 } 99 CHECK_POSIX_DO( pthread_mutex_unlock(&redir_exp_peer_lock), ); 87 redir_entry_fini(); 100 88 101 89 return; -
extensions/rt_redirect/rt_redir.h
r1259 r1260 1 1 /********************************************************************************************************* 2 2 * Software License Agreement (BSD License) * 3 * Author: Sebastien Decugis <sdecugis@freediameter.net> * 4 * * 5 * Copyright (c) 2013, WIDE Project and NICT * 3 * Author: Sebastien Decugis <sdecugis@freediameter.net> and * 4 * Thomas Klausner <tk@giga.or.at> * 5 * * 6 * Copyright (c) 2013, 2014, WIDE Project and NICT * 6 7 * All rights reserved. * 7 8 * * … … 36 37 /* Diameter Redirect management */ 37 38 #include <freeDiameter/extension.h> 39 40 #include "uthash.h" 38 41 39 42 /* There are 2 locks in this module. The priority is established as follow to avoid deadlocks: … … 130 133 struct fd_list target_peers_list; /* The list of Redirect-Hosts for this entry */ 131 134 132 struct timespec timeout; /* When does this entry expire s? */135 struct timespec timeout; /* When does this entry expire? */ 133 136 struct fd_list exp_list; /* chain in the expire_list list, ordered by expiration date, protected by exp_peer_lock */ 134 137 135 enum redir_h_u type; /* Type of this entry */138 enum redir_h_u type; /* Type of this entry */ 136 139 struct fd_list redir_list; /* link in redirects_usages lists. Lists are ordered by the data value. Protected by rw locks */ 137 union matchdata data; /* The strings are duplicated & must be freed in this structure */ 140 union matchdata data; /* The strings are duplicated & must be freed in this structure */ 141 UT_hash_handle hh; /* magic entry for hash table */ 138 142 }; 139 143 … … 145 149 }; 146 150 extern struct redir_line redirects_usages[]; 151 /* the hash table where entries are stored for ALL_SESSION and ALL_USER */ 152 extern struct redir_entry *redirect_hash_table[]; 147 153 148 154 /* Accelerator to the line lock */ … … 158 164 /* Functions on redir_entry */ 159 165 int redir_entry_init(); 166 int redir_entry_fini(); 160 167 int redir_entry_new(struct redir_entry ** e, struct fd_list * targets, uint32_t rhu, struct msg * qry, DiamId_t nh, size_t nhlen, os0_t oh, size_t ohlen); 161 168 extern int (*redir_entry_cmp_key[])(union matchdata * , union matchdata *); /* compare functions */
Note: See TracChangeset
for help on using the changeset viewer.