Changeset 1259:82280e745a89 in freeDiameter for extensions/rt_redirect/redir_out.c
- Timestamp:
- Mar 24, 2014, 9:13:38 PM (10 years ago)
- Branch:
- default
- Phase:
- public
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
extensions/rt_redirect/redir_out.c
r1216 r1259 41 41 { 42 42 TRACE_ENTRY("%d %p %p %p", type, msg, data, nodata); 43 43 44 44 /* Initialize the data area */ 45 45 memset(data, 0, sizeof(union matchdata)); 46 46 *nodata = 0; 47 47 48 48 /* Now, find the appropriate information, depending on type */ 49 49 switch (type) { … … 51 51 data->message.msg = msg; 52 52 break; 53 53 54 54 case ALL_SESSION: 55 55 { … … 65 65 } 66 66 break; 67 67 68 68 case ALL_REALM: 69 69 { … … 82 82 } 83 83 break; 84 84 85 85 case REALM_AND_APPLICATION: 86 86 { … … 96 96 data->realm_app.s = ahdr->avp_value->os.data; 97 97 data->realm_app.l = ahdr->avp_value->os.len; 98 98 99 99 /* and then the application */ 100 100 { … … 107 107 } 108 108 break; 109 109 110 110 case ALL_APPLICATION: 111 111 { … … 116 116 } 117 117 break; 118 118 119 119 case ALL_HOST: 120 120 /* This is more complex, we need to match with all candidates in each rule, it'll be done later */ 121 121 break; 122 122 123 123 case ALL_USER: 124 124 { … … 137 137 } 138 138 break; 139 139 140 140 default: 141 141 ASSERT(0); … … 153 153 struct rtd_candidate * c_oh = NULL; 154 154 int cmp; 155 155 156 156 TRACE_ENTRY("%p %p %p", e, msg, candidates); 157 157 ASSERT( e && msg && candidates ); 158 158 159 159 if (FD_IS_LIST_EMPTY(candidates)) { 160 160 TRACE_DEBUG(ANNOYING, "Skip Redirect rule since candidates list is empty"); 161 161 return 0; 162 162 } 163 163 164 164 /* Now search common peers between e->target_peers_list and candidates */ 165 165 TRACE_DEBUG(ANNOYING, "Message %p matches a Redirect rule (t:%d, @%p), processing candidates list", msg, e->type, e); 166 166 167 167 /* First, decrease the score of the host that we received the previous Redirect from, in case it is in the list */ 168 168 for (lic = candidates->next; lic != candidates; lic = lic->next) { 169 169 struct rtd_candidate * cand = (struct rtd_candidate *) lic; 170 170 171 171 /* Special case: ALL_HOST rules: we decrease the score of the Origin-Host if present */ 172 172 if (e->type == ALL_HOST) { … … 179 179 } 180 180 } 181 181 182 182 cmp = fd_os_cmp(cand->diamid, cand->diamidlen, e->from.s, e->from.l); 183 183 if (!cmp) { … … 185 185 cand->score += FD_SCORE_SENT_REDIRECT; 186 186 } 187 188 } 189 187 188 } 189 190 190 if ((e->type == ALL_HOST) && (c_oh == NULL)) { 191 191 /* The rule does not apply, we're done */ 192 192 return 0; 193 193 } 194 194 195 195 /* for each candidate, if it is found in the target_peers list, we add the rule's score to this candidate */ 196 196 for (lic = candidates->next; lic != candidates; lic = lic->next) { 197 197 /* the candidates list is not guaranteed to be ordered at this time, so we cannot avoid the two imbricated loops */ 198 198 struct rtd_candidate * cand = (struct rtd_candidate *) lic; 199 199 200 200 /* Is this candidate in the "Redirect-Host" list ? We must search caseinsentive here. */ 201 201 for (lirh = e->target_peers_list.next; lirh != &e->target_peers_list; lirh = lirh->next) { 202 202 struct redir_host * host = lirh->o; 203 203 int cont; 204 204 205 205 cmp = fd_os_almostcasesrch( cand->diamid, cand->diamidlen, host->id, host->len, &cont ); 206 206 207 207 if (cmp == 0) { 208 208 TRACE_DEBUG(FULL, "Redirect msg %p: peer '%.*s' += %d (rule t:%d @%p)", msg, (int)cand->diamidlen, cand->diamid, redirects_usages[e->type].score, e->type, e); … … 214 214 } 215 215 } 216 216 217 217 return 0; 218 218 } … … 224 224 int i, ret = 0; 225 225 struct msg * msg = *pmsg; 226 226 227 227 TRACE_ENTRY("%p %p %p", cbdata, msg, candidates); 228 228 229 229 for (i = 0; i <= H_U_MAX; i++) { 230 230 /* Lock the line. We write lock in case of DONT_CACHE so we can directly unlink the entry. read in other cases is sufficient */ … … 234 234 CHECK_POSIX( pthread_rwlock_rdlock( &redirects_usages[i].lock ) ); 235 235 } 236 236 237 237 if (!FD_IS_LIST_EMPTY(&redirects_usages[i].sentinel)) { 238 238 union matchdata data; 239 239 int nodata; /* The message does not allow to apply this rule, skip */ 240 240 241 241 /* Retrieve the data that may match in the message */ 242 242 CHECK_FCT_DO( ret = get_data_to_match(i, msg, &data, &nodata), goto out ); 243 243 244 244 /* If this message may match some of our rules */ 245 245 if (!nodata) { … … 248 248 for (li = redirects_usages[i].sentinel.next; li != &redirects_usages[i].sentinel; li = li->next) { 249 249 struct redir_entry * e = li->o; 250 250 251 251 /* Does it match ? */ 252 252 if (i != ALL_HOST) { /* this one is an exception, we handle it separately */ … … 257 257 break; 258 258 } 259 259 260 260 /* This rule matches (or we are in ALL_HOST), apply */ 261 261 CHECK_FCT_DO( ret = apply_rule(e, msg, candidates), goto out ); 262 262 263 263 /* If this was a DONT_CACHE rule, we unlink it, so that it will not be used again */ 264 264 if (i == DONT_CACHE) { 265 265 li=li->prev; 266 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... 267 /* We cannot delete here without taking the mutex, which would mean we have first to release the lock... 268 268 just let expiry garbage collet the rule */ 269 269 } 270 270 } 271 271 } 272 273 } 274 out: 272 273 } 274 out: 275 275 CHECK_POSIX( pthread_rwlock_unlock( &redirects_usages[i].lock ) ); 276 276 if (ret) 277 277 return ret; 278 278 } 279 279 280 280 return 0; 281 281 }
Note: See TracChangeset
for help on using the changeset viewer.