Definition in file scscf_list.h.
#include "../../sr_module.h"
#include "mod.h"
Go to the source code of this file.
Data Structures | |
| struct | _scscf_entry |
| S-CSCF list element. More... | |
| struct | _scscf_list |
| S-CSCF list. More... | |
| struct | i_hash_slot |
| hash slot for S-CSCF lists More... | |
| struct | _scscf_capabilities |
| S-CSCF with attached capabilities. More... | |
Typedefs | |
| typedef _scscf_entry | scscf_entry |
| S-CSCF list element. | |
| typedef _scscf_list | scscf_list |
| S-CSCF list. | |
| typedef _scscf_capabilities | scscf_capabilities |
| S-CSCF with attached capabilities. | |
Functions | |
| int | I_get_capabilities () |
| Refreshes the capabilities list reading them from the db. | |
| scscf_entry * | I_get_capab_ordered (str scscf_name, int *m, int mcnt, int *o, int ocnt, str *p, int pcnt, int orig) |
| Returns a list of S-CSCFs that we should try on, based on the capabilities requested. | |
| unsigned int | get_call_id_hash (str callid, int hash_size) |
| Computes the hash for a string. | |
| int | i_hash_table_init (int hash_size) |
| Initialize the hash with S-CSCF lists. | |
| void | i_hash_table_destroy () |
| Destroy the hash with S-CSCF lists. | |
| void | i_lock (unsigned int hash) |
| Locks the required part of hash with S-CSCF lists. | |
| void | i_unlock (unsigned int hash) |
| UnLocks the required part of hash with S-CSCF lists. | |
| scscf_entry * | new_scscf_entry (str name, int score, int orig) |
| scscf_list * | new_scscf_list (str callid, scscf_entry *sl) |
| int | add_scscf_list (str call_id, scscf_entry *sl) |
| int | is_scscf_list (str call_id) |
| str | take_scscf_entry (str call_id) |
| Takes on S-CSCF name for the respective Call-ID from the respective name list. | |
| void | del_scscf_list (str call_id) |
| void | free_scscf_list (scscf_list *sl) |
| void | print_scscf_list (int log_level) |
| int | I_trans_in_processing (struct sip_msg *msg, char *str1, char *str2) |
| int | I_scscf_select (struct sip_msg *msg, char *str1, char *str2) |
| int | I_scscf_drop (struct sip_msg *msg, char *str1, char *str2) |
| typedef struct _scscf_entry scscf_entry |
S-CSCF list element.
| typedef struct _scscf_list scscf_list |
S-CSCF list.
| typedef struct _scscf_capabilities scscf_capabilities |
S-CSCF with attached capabilities.
| int I_get_capabilities | ( | ) |
Refreshes the capabilities list reading them from the db.
Drops the old cache and queries the db
Definition at line 90 of file scscf_list.c.
References _scscf_capabilities::cnt, icscf_db_get_capabilities(), icscf_db_get_scscf(), id_s_cscf, M_NAME, SCSCF_Capabilities, SCSCF_Capabilities_cnt, _scscf_capabilities::scscf_name, and scscf_name.
Referenced by icscf_mod_init().
00091 { 00092 int i,j,r; 00093 /* free the old cache */ 00094 if (SCSCF_Capabilities!=0){ 00095 for(i=0;i<SCSCF_Capabilities_cnt;i++){ 00096 if (SCSCF_Capabilities[i].capabilities) 00097 shm_free(SCSCF_Capabilities[i].capabilities); 00098 } 00099 shm_free(SCSCF_Capabilities); 00100 } 00101 00102 SCSCF_Capabilities_cnt = icscf_db_get_scscf(&SCSCF_Capabilities); 00103 00104 r = icscf_db_get_capabilities(&SCSCF_Capabilities,SCSCF_Capabilities_cnt); 00105 00106 LOG(L_DBG,"DBG:"M_NAME":------ S-CSCF Map with Capabilities begin ------\n"); 00107 if (SCSCF_Capabilities!=0){ 00108 for(i=0;i<SCSCF_Capabilities_cnt;i++){ 00109 LOG(L_DBG,"DBG:"M_NAME":S-CSCF [%d] <%.*s>\n", 00110 SCSCF_Capabilities[i].id_s_cscf, 00111 SCSCF_Capabilities[i].scscf_name.len, 00112 SCSCF_Capabilities[i].scscf_name.s); 00113 for(j=0;j<SCSCF_Capabilities[i].cnt;j++) 00114 LOG(L_DBG,"DBG:"M_NAME": \t [%d]\n", 00115 SCSCF_Capabilities[i].capabilities[j]); 00116 } 00117 } 00118 LOG(L_DBG,"DBG:"M_NAME":------ S-CSCF Map with Capabilities end ------\n"); 00119 00120 return r; 00121 }
| scscf_entry* I_get_capab_ordered | ( | str | scscf_name, | |
| int * | m, | |||
| int | mcnt, | |||
| int * | o, | |||
| int | ocnt, | |||
| str * | p, | |||
| int | pcnt, | |||
| int | orig | |||
| ) |
Returns a list of S-CSCFs that we should try on, based on the capabilities requested.
| scscf_name | - the first S-CSCF if specified | |
| m | - mandatory capabilities list | |
| mcnt | - mandatory capabilities list size | |
| o | - optional capabilities list | |
| ocnt | - optional capabilities list size | |
| orig | - indicates originating session case |
Definition at line 196 of file scscf_list.c.
References I_add_to_scscf_list(), I_get_capab_match(), M_NAME, SCSCF_Capabilities, SCSCF_Capabilities_cnt, and _scscf_capabilities::scscf_name.
Referenced by I_LIA(), and I_UAA().
00197 { 00198 scscf_entry *list=0; 00199 int i,r; 00200 00201 if (scscf_name.len) list = I_add_to_scscf_list(list,scscf_name,MAXINT, orig); 00202 00203 for(i=0;i<pcnt;i++) 00204 list = I_add_to_scscf_list(list,p[i],MAXINT-i,orig); 00205 00206 for(i=0;i<SCSCF_Capabilities_cnt;i++){ 00207 r = I_get_capab_match(SCSCF_Capabilities+i,m,mcnt,o,ocnt); 00208 if (r!=-1){ 00209 list = I_add_to_scscf_list(list,SCSCF_Capabilities[i].scscf_name,r, orig); 00210 LOG(L_DBG,"DBG:"M_NAME":I_get_capab_ordered: <%.*s> Added to the list, orig=%d\n", 00211 SCSCF_Capabilities[i].scscf_name.len,SCSCF_Capabilities[i].scscf_name.s, orig); 00212 } 00213 } 00214 return list; 00215 }
| unsigned int get_call_id_hash | ( | str | callid, | |
| int | hash_size | |||
| ) | [inline] |
Computes the hash for a string.
Definition at line 221 of file scscf_list.c.
References h_inc.
Referenced by add_scscf_list(), del_scscf_list(), is_scscf_list(), and take_scscf_entry().
00222 { 00223 #define h_inc h+=v^(v>>3) 00224 char* p; 00225 register unsigned v; 00226 register unsigned h; 00227 00228 h=0; 00229 for (p=callid.s; p<=(callid.s+callid.len-4); p+=4){ 00230 v=(*p<<24)+(p[1]<<16)+(p[2]<<8)+p[3]; 00231 h_inc; 00232 } 00233 v=0; 00234 for (;p<(callid.s+callid.len); p++) { 00235 v<<=8; 00236 v+=*p; 00237 } 00238 h_inc; 00239 00240 h=((h)+(h>>11))+((h>>13)+(h>>23)); 00241 return (h)%hash_size; 00242 #undef h_inc 00243 }
| int i_hash_table_init | ( | int | hash_size | ) |
Initialize the hash with S-CSCF lists.
Definition at line 248 of file scscf_list.c.
References i_hash_size, i_hash_table, i_hash_slot::lock, and M_NAME.
Referenced by icscf_mod_init().
00249 { 00250 int i; 00251 00252 i_hash_size = hash_size; 00253 i_hash_table = shm_malloc(sizeof(i_hash_slot)*i_hash_size); 00254 00255 if (!i_hash_table) return 0; 00256 00257 memset(i_hash_table,0,sizeof(i_hash_slot)*i_hash_size); 00258 00259 for(i=0;i<i_hash_size;i++){ 00260 i_hash_table[i].lock = lock_alloc(); 00261 if (!i_hash_table[i].lock){ 00262 LOG(L_ERR,"ERR:"M_NAME":i_hash_table_init(): Error creating lock\n"); 00263 return 0; 00264 } 00265 i_hash_table[i].lock = lock_init(i_hash_table[i].lock); 00266 } 00267 00268 return 1; 00269 }
| void i_hash_table_destroy | ( | ) |
Destroy the hash with S-CSCF lists.
Definition at line 274 of file scscf_list.c.
References free_scscf_list(), i_hash_slot::head, i_hash_size, i_hash_table, i_lock(), i_unlock(), and _scscf_list::next.
Referenced by icscf_mod_destroy().
00275 { 00276 int i; 00277 scscf_list *sl,*nsl; 00278 for(i=0;i<i_hash_size;i++){ 00279 i_lock(i); 00280 sl = i_hash_table[i].head; 00281 while(sl){ 00282 nsl = sl->next; 00283 free_scscf_list(sl); 00284 sl = nsl; 00285 } 00286 i_unlock(i); 00287 lock_dealloc(i_hash_table[i].lock); 00288 } 00289 shm_free(i_hash_table); 00290 }
| void i_lock | ( | unsigned int | hash | ) | [inline] |
Locks the required part of hash with S-CSCF lists.
Definition at line 295 of file scscf_list.c.
References i_hash_table.
Referenced by add_scscf_list(), del_scscf_list(), i_hash_table_destroy(), is_scscf_list(), print_scscf_list(), and take_scscf_entry().
00296 { 00297 // LOG(L_CRIT,"GET %d\n",hash); 00298 lock_get(i_hash_table[(hash)].lock); 00299 // LOG(L_CRIT,"GOT %d\n",hash); 00300 }
| void i_unlock | ( | unsigned int | hash | ) | [inline] |
UnLocks the required part of hash with S-CSCF lists.
Definition at line 305 of file scscf_list.c.
References i_hash_table.
Referenced by add_scscf_list(), del_scscf_list(), i_hash_table_destroy(), is_scscf_list(), print_scscf_list(), and take_scscf_entry().
00306 { 00307 lock_release(i_hash_table[(hash)].lock); 00308 // LOG(L_CRIT,"RELEASED %d\n",hash); 00309 }
| scscf_entry* new_scscf_entry | ( | str | name, | |
| int | score, | |||
| int | orig | |||
| ) |
Definition at line 311 of file scscf_list.c.
References M_NAME, _scscf_entry::next, _scscf_entry::score, and _scscf_entry::scscf_name.
Referenced by I_add_to_scscf_list(), and I_LIA().
00312 { 00313 scscf_entry *x=0; 00314 x = shm_malloc(sizeof(scscf_entry)); 00315 if (!x) { 00316 LOG(L_ERR,"ERR:"M_NAME":new_scscf_entry: Error allocating %d bytes\n", 00317 sizeof(scscf_entry)); 00318 return 0; 00319 } 00320 /* duplicate always the scscf_name because of possible list reloads and scscf_name coming in LIA/UAA */ 00321 if (orig) x->scscf_name.s = shm_malloc(name.len+5); 00322 else x->scscf_name.s = shm_malloc(name.len); 00323 if (!x->scscf_name.s){ 00324 LOG(L_ERR,"ERR:"M_NAME":new_scscf_entry: Error allocating %d bytes\n", 00325 orig?name.len+5:name.len); 00326 shm_free(x); 00327 return 0; 00328 } 00329 memcpy(x->scscf_name.s,name.s,name.len); 00330 x->scscf_name.len = name.len; 00331 if (orig) { 00332 memcpy(x->scscf_name.s+name.len, ";orig", 5); 00333 x->scscf_name.len += 5; 00334 } 00335 00336 LOG(L_INFO,"INFO:"M_NAME":new_scscf_entry: <%.*s>\n",x->scscf_name.len,x->scscf_name.s); 00337 00338 x->score = score; 00339 x->next = 0; 00340 return x; 00341 }
| scscf_list* new_scscf_list | ( | str | callid, | |
| scscf_entry * | sl | |||
| ) |
Definition at line 344 of file scscf_list.c.
References _scscf_list::call_id, _scscf_list::list, M_NAME, and STR_SHM_DUP.
Referenced by add_scscf_list().
00345 { 00346 scscf_list *l; 00347 00348 l = shm_malloc(sizeof(scscf_list)); 00349 if (!l) { 00350 LOG(L_ERR,"ERR:"M_NAME":new_scscf_list(): Unable to alloc %d bytes\n", 00351 sizeof(scscf_list)); 00352 goto error; 00353 } 00354 memset(l,0,sizeof(scscf_list)); 00355 00356 STR_SHM_DUP(l->call_id,call_id,"shm"); 00357 l->list = sl; 00358 00359 return l; 00360 error: 00361 out_of_memory: 00362 if (l){ 00363 shm_free(l); 00364 } 00365 return 0; 00366 }
| int add_scscf_list | ( | str | call_id, | |
| scscf_entry * | sl | |||
| ) |
Definition at line 368 of file scscf_list.c.
References get_call_id_hash(), i_hash_slot::head, i_hash_size, i_hash_table, i_lock(), i_unlock(), new_scscf_list(), _scscf_list::next, _scscf_list::prev, and i_hash_slot::tail.
Referenced by I_LIA(), and I_UAA().
00369 { 00370 scscf_list *l; 00371 unsigned int hash = get_call_id_hash(call_id,i_hash_size); 00372 00373 l = new_scscf_list(call_id,sl); 00374 if (!l) return 0; 00375 00376 i_lock(hash); 00377 l->prev = 0; 00378 l->next = i_hash_table[hash].head; 00379 if (l->next) l->next->prev = l; 00380 i_hash_table[hash].head = l; 00381 if (!i_hash_table[hash].tail) i_hash_table[hash].tail = l; 00382 i_unlock(hash); 00383 00384 return 1; 00385 }
| int is_scscf_list | ( | str | call_id | ) |
Definition at line 387 of file scscf_list.c.
References _scscf_list::call_id, get_call_id_hash(), i_hash_slot::head, i_hash_size, i_hash_table, i_lock(), i_unlock(), and _scscf_list::next.
00388 { 00389 scscf_list *l=0; 00390 unsigned int hash = get_call_id_hash(call_id,i_hash_size); 00391 00392 i_lock(hash); 00393 l = i_hash_table[hash].head; 00394 while(l){ 00395 if (l->call_id.len == call_id.len && 00396 strncasecmp(l->call_id.s,call_id.s,call_id.len)==0) { 00397 i_unlock(hash); 00398 return 1; 00399 } 00400 l = l->next; 00401 } 00402 i_unlock(hash); 00403 return 0; 00404 }
| str take_scscf_entry | ( | str | call_id | ) |
Takes on S-CSCF name for the respective Call-ID from the respective name list.
Should shm_free the result.s when no longer needed.
| call_id | - the id of the call |
Definition at line 412 of file scscf_list.c.
References _scscf_list::call_id, get_call_id_hash(), i_hash_slot::head, i_hash_size, i_hash_table, i_lock(), i_unlock(), _scscf_list::list, _scscf_list::next, _scscf_entry::next, and _scscf_entry::scscf_name.
Referenced by I_scscf_select().
00413 { 00414 str scscf={0,0}; 00415 scscf_list *l=0; 00416 scscf_entry *sl; 00417 unsigned int hash = get_call_id_hash(call_id,i_hash_size); 00418 00419 i_lock(hash); 00420 l = i_hash_table[hash].head; 00421 while(l){ 00422 if (l->call_id.len == call_id.len && 00423 strncasecmp(l->call_id.s,call_id.s,call_id.len)==0) { 00424 if (l->list){ 00425 scscf = l->list->scscf_name; 00426 sl = l->list->next; 00427 shm_free(l->list); 00428 l->list = sl; 00429 } 00430 break; 00431 } 00432 l = l->next; 00433 } 00434 i_unlock(hash); 00435 return scscf; 00436 }
| void del_scscf_list | ( | str | call_id | ) |
Definition at line 438 of file scscf_list.c.
References _scscf_list::call_id, free_scscf_list(), get_call_id_hash(), i_hash_slot::head, i_hash_size, i_hash_table, i_lock(), i_unlock(), _scscf_list::next, _scscf_list::prev, and i_hash_slot::tail.
Referenced by I_scscf_drop().
00439 { 00440 scscf_list *l=0; 00441 unsigned int hash = get_call_id_hash(call_id,i_hash_size); 00442 00443 i_lock(hash); 00444 l = i_hash_table[hash].head; 00445 while(l){ 00446 if (l->call_id.len == call_id.len && 00447 strncasecmp(l->call_id.s,call_id.s,call_id.len)==0) { 00448 if (l->prev) l->prev->next = l->next; 00449 else i_hash_table[hash].head = l->next; 00450 if (l->next) l->next->prev = l->prev; 00451 else i_hash_table[hash].tail = l->prev; 00452 i_unlock(hash); 00453 free_scscf_list(l); 00454 return; 00455 } 00456 l = l->next; 00457 } 00458 i_unlock(hash); 00459 }
| void free_scscf_list | ( | scscf_list * | sl | ) |
Definition at line 461 of file scscf_list.c.
References _scscf_list::call_id, _scscf_list::list, _scscf_entry::next, and _scscf_entry::scscf_name.
Referenced by del_scscf_list(), and i_hash_table_destroy().
00462 { 00463 scscf_entry *i; 00464 if (!sl) return; 00465 if (sl->call_id.s) shm_free(sl->call_id.s); 00466 while (sl->list) { 00467 i = sl->list->next; 00468 if (sl->list->scscf_name.s) shm_free(sl->list->scscf_name.s); 00469 shm_free(sl->list); 00470 sl->list = i; 00471 } 00472 shm_free(sl); 00473 }
| void print_scscf_list | ( | int | log_level | ) |
Definition at line 475 of file scscf_list.c.
References _scscf_list::call_id, i_hash_slot::head, i_hash_size, i_hash_table, i_lock(), i_unlock(), _scscf_list::list, M_NAME, _scscf_list::next, and _scscf_entry::next.
00476 { 00477 scscf_list *l; 00478 int i; 00479 scscf_entry *sl; 00480 LOG(log_level,"INF:"M_NAME":---------- S-CSCF Lists begin --------------\n"); 00481 for(i=0;i<i_hash_size;i++){ 00482 i_lock(i); 00483 l = i_hash_table[i].head; 00484 while(l){ 00485 LOG(log_level,"INF:"M_NAME":[%4d] Call-ID: <%.*s> \n",i, 00486 l->call_id.len,l->call_id.s); 00487 sl = l->list; 00488 while(sl){ 00489 LOG(log_level,"INF:"M_NAME": Score:[%4d] S-CSCF: <%.*s> \n", 00490 sl->score, 00491 sl->scscf_name.len,sl->scscf_name.s); 00492 sl = sl->next; 00493 } 00494 l = l->next; 00495 } 00496 i_unlock(i); 00497 } 00498 LOG(log_level,"INF:"M_NAME":---------- S-CSCF Lists end --------------\n"); 00499 00500 }
| int I_trans_in_processing | ( | struct sip_msg * | msg, | |
| char * | str1, | |||
| char * | str2 | |||
| ) |
Definition at line 502 of file scscf_list.c.
References CSCF_RETURN_FALSE, CSCF_RETURN_TRUE, and tmb.
00503 { 00504 unsigned int hash, label; 00505 if (tmb.t_get_trans_ident(msg,&hash,&label)<0) 00506 return CSCF_RETURN_FALSE; 00507 return CSCF_RETURN_TRUE; 00508 }
| int I_scscf_select | ( | struct sip_msg * | msg, | |
| char * | str1, | |||
| char * | str2 | |||
| ) |
Definition at line 513 of file scscf_list.c.
References cscf_add_header_first(), cscf_get_call_id(), cscf_reply_transactional(), CSCF_RETURN_BREAK, CSCF_RETURN_ERROR, CSCF_RETURN_FALSE, CSCF_RETURN_TRUE, I_scscf_drop(), M_NAME, MSG_600_FORWARDING_FAILED, scscf_name, STR_APPEND, STR_PKG_DUP, and take_scscf_entry().
00514 { 00515 str call_id,scscf_name={0,0}; 00516 struct sip_msg *req; 00517 int result; 00518 str hdr={0,0}; 00519 00520 //print_scscf_list(L_ERR); 00521 00522 call_id = cscf_get_call_id(msg,0); 00523 LOG(L_DBG,"DBG:"M_NAME":I_scscf_select(): <%.*s>\n",call_id.len,call_id.s); 00524 if (!call_id.len) 00525 return CSCF_RETURN_FALSE; 00526 00527 scscf_name = take_scscf_entry(call_id); 00528 if (!scscf_name.len){ 00529 I_scscf_drop(msg,str1,str2); 00530 cscf_reply_transactional(msg,600,MSG_600_FORWARDING_FAILED); 00531 return CSCF_RETURN_BREAK; 00532 } 00533 00534 if (msg->first_line.u.request.method.len==8 && 00535 strncasecmp(msg->first_line.u.request.method.s,"REGISTER",8)==0) { 00536 /* REGISTER fwding */ 00537 if (str1&&str1[0]=='0'){ 00538 /* first time */ 00539 //LOG(L_CRIT,"rewrite uri\n"); 00540 if (rewrite_uri(msg, &(scscf_name)) < 0) { 00541 LOG(L_ERR,"ERR:"M_NAME":I_UAR_forward: Unable to Rewrite URI\n"); 00542 result = CSCF_RETURN_FALSE; 00543 }else 00544 result = CSCF_RETURN_TRUE; 00545 }else{ 00546 /* subsequent */ 00547 //LOG(L_CRIT,"append branch\n"); 00548 req = msg;//cscf_get_request_from_reply(msg); 00549 append_branch(req,scscf_name.s,scscf_name.len,0,0,0,0); 00550 result = CSCF_RETURN_TRUE; 00551 } 00552 }else{ 00553 /* Another request */ 00554 result = CSCF_RETURN_TRUE; 00555 00556 hdr.len = route_hdr_s.len+scscf_name.len+route_hdr_e.len; 00557 hdr.s = pkg_malloc(hdr.len); 00558 if (!hdr.s){ 00559 LOG(L_ERR,"ERR:"M_NAME":Mw_REQUEST_forward: Error allocating %d bytes\n", 00560 hdr.len); 00561 result = CSCF_RETURN_TRUE; 00562 } 00563 hdr.len=0; 00564 STR_APPEND(hdr,route_hdr_s); 00565 STR_APPEND(hdr,scscf_name); 00566 STR_APPEND(hdr,route_hdr_e); 00567 00568 if (!cscf_add_header_first(msg,&hdr,HDR_ROUTE_T)){ 00569 pkg_free(hdr.s); 00570 result = CSCF_RETURN_TRUE; 00571 } 00572 00573 if (msg->dst_uri.s) pkg_free(msg->dst_uri.s); 00574 STR_PKG_DUP(msg->dst_uri,scscf_name,"pkg"); 00575 } 00576 00577 if (scscf_name.s) shm_free(scscf_name.s); 00578 return result; 00579 out_of_memory: 00580 if (scscf_name.s) shm_free(scscf_name.s); 00581 return CSCF_RETURN_ERROR; 00582 }
| int I_scscf_drop | ( | struct sip_msg * | msg, | |
| char * | str1, | |||
| char * | str2 | |||
| ) |
Definition at line 584 of file scscf_list.c.
References cscf_get_call_id(), CSCF_RETURN_FALSE, CSCF_RETURN_TRUE, del_scscf_list(), and M_NAME.
Referenced by I_scscf_select().
00585 { 00586 str call_id; 00587 //print_scscf_list(L_ERR); 00588 call_id = cscf_get_call_id(msg,0); 00589 LOG(L_DBG,"DBG:"M_NAME":I_scscf_drop(): <%.*s>\n",call_id.len,call_id.s); 00590 if (!call_id.len) 00591 return CSCF_RETURN_FALSE; 00592 00593 del_scscf_list(call_id); 00594 return CSCF_RETURN_TRUE; 00595 }
1.5.2