registrar_subscribe.c File Reference


Detailed Description

Proxy-CSCF - Registrar Refreshment Through SUBSCRIBE to reg event at the S-CSCF.

Author:
Dragos Vingarzan vingarzan -at- fokus dot fraunhofer dot de

Definition in file registrar_subscribe.c.

#include "registrar_subscribe.h"
#include <libxml/xmlschemas.h>
#include <libxml/parser.h>
#include "registrar_storage.h"
#include "mod.h"
#include "../../mem/mem.h"
#include "../../mem/shm_mem.h"
#include "../../parser/parse_uri.h"
#include "../../locking.h"
#include "../tm/tm_load.h"
#include "../dialog/dlg_mod.h"
#include "sip.h"
#include "ims_pm.h"

Go to the source code of this file.

Defines

#define h_inc   h+=v^(v>>3)

Functions

unsigned int get_subscription_hash (str uri)
 Computes the hash for a contact.
void subs_lock (unsigned int hash)
 Lock a subscription hash slot.
void subs_unlock (unsigned int hash)
 UnLock a subscriptions hash slot.
int r_subscription_init ()
 Initialize the subscription list.
void r_subscription_destroy ()
 Destroys the subscription list.
int P_subscribe (struct sip_msg *rpl, char *str1, char *str2)
 Subscribe to the reg event to the S-CSCF.
int r_subscribe (str uri, int duration)
 Creates a subcription and starts the timer resubscription for the given contact.
int r_send_subscribe (r_subscription *s, int duration)
 Send a subscription.
void r_subscribe_response (struct cell *t, int type, struct tmcb_params *ps)
 Response callback for subscribe.
void subscription_timer (unsigned int ticks, void *param)
 The Subscription timer looks for almost expired subscriptions and subscribes again.
r_subscriptionnew_r_subscription (str req_uri, int duration)
 Creates a subscription based on the given parameters.
void add_r_subscription (r_subscription *s)
 Adds a subscription to the list of subscriptions at the end (FIFO).
int update_r_subscription (r_subscription *s, int expires)
 Updates the expiration time of a subscription.
r_subscriptionget_r_subscription (str aor)
 Returns a subscription if it exists.
int is_r_subscription (str aor)
 Finds out if a subscription exists.
void del_r_subscription (r_subscription *s)
 Deletes a subscription from the list of subscriptions.
void del_r_subscription_nolock (r_subscription *s)
 Deletes a subscription from the list of subscriptions.
void free_r_subscription (r_subscription *s)
 Frees up space taken by a subscription.
void print_subs (int log_level)
int parser_init (char *dtd_filename)
 Initializes the libxml parser.
void parser_destroy ()
 Destroys the parser.
static void space_trim_dup (str *dest, char *src)
 Trims spaces and duplicate content into pkg.
r_notificationr_notification_parse (str xml)
 Parses a notification and creates the r_notification object.
int r_notification_process (r_notification *n, int expires)
 Processes a notification and updates the registrar info.
void r_notification_print (r_notification *n)
 Prints the content of a notification.
void r_notification_free (r_notification *n)
 Frees up the space taken by a notification.

Variables

tm_binds tmb
 Structure with pointers to tm funcs.
dlg_func_t dialogb
 Structure with pointers to dialog funcs.
str pcscf_name_str
 fixed SIP URI of this P-CSCF
str pcscf_path_str
 fixed Path URI
time_t time_now
 current time
r_hash_slotregistrar
 the actual registrar
int r_hash_size
 number of hash slots in the registrar
int pcscf_subscribe_retries
 times to retry subscribe to reg on failure
r_subscription_hash_slotsubscriptions = 0
 The P-CSCF subscriptions.
int subscriptions_hash_size
 the size of the hash table for subscriptions
static str method = {"SUBSCRIBE",9}
static str event_hdr = {"Event: reg\r\n",12}
static str accept_hdr = {"Accept: application/reginfo+xml\r\n",33}
static str content_len_hdr = {"Content-Length: 0\r\n",19}
static str max_fwds_hdr = {"Max-Forwards: 10\r\n",18}
static str expires_s = {"Expires: ",9}
static str expires_e = {"\r\n",2}
static str contact_s = {"Contact: <",10}
static str contact_e = {">\r\n",3}
static str p_asserted_identity_s = {"P-Asserted-Identity: <",22}
static str p_asserted_identity_e = {">\r\n",3}
char * pcscf_reginfo_dtd
 DTD to check the reginfo/xml in the NOTIFY to reg.
static xmlDtdPtr dtd = 0
 DTD file.
static xmlValidCtxt cvp
 XML Validating context.


Define Documentation

#define h_inc   h+=v^(v>>3)


Function Documentation

unsigned int get_subscription_hash ( str  uri  )  [inline]

Computes the hash for a contact.

Parameters:
aor - the string of the contact
port - the port of the contact
transport - transport for the contact - ignored for now
hash_size - size of the hash, to % with
Returns:
the hash for the contact

Definition at line 98 of file registrar_subscribe.c.

References h_inc, and subscriptions_hash_size.

Referenced by add_r_subscription(), bin_decode_r_subscription(), get_r_subscription(), and is_r_subscription().

00099 {
00100 #define h_inc h+=v^(v>>3)
00101    char* p;
00102    register unsigned v;
00103    register unsigned h;
00104    h=0;
00105    for (p=uri.s; p<=(uri.s+uri.len-4); p+=4){
00106        v=(*p<<24)+(p[1]<<16)+(p[2]<<8)+p[3];
00107        h_inc;
00108    }
00109    v=0;
00110    for (;p<(uri.s+uri.len); p++) {
00111        v<<=8;
00112        v+=*p;
00113    }
00114    h_inc;
00115    h=((h)+(h>>11))+((h>>13)+(h>>23));
00116    return (h)%subscriptions_hash_size;
00117 #undef h_inc 
00118 }

void subs_lock ( unsigned int  hash  )  [inline]

Lock a subscription hash slot.

Parameters:
hash - index to lock

Definition at line 124 of file registrar_subscribe.c.

References subscriptions.

Referenced by add_r_subscription(), bin_cache_dump_subs_to_table(), bin_cache_load_subscriptions_from_table(), del_r_subscription(), get_r_subscription(), is_r_subscription(), load_snapshot_subscriptions(), make_snapshot_subscriptions(), print_subs(), r_subscription_destroy(), and subscription_timer().

00125 {
00126 //  LOG(L_CRIT,"GET %d\n",hash);
00127     lock_get(subscriptions[hash].lock);
00128 //  LOG(L_CRIT,"GOT %d\n",hash);
00129 }

void subs_unlock ( unsigned int  hash  )  [inline]

UnLock a subscriptions hash slot.

Parameters:
hash - index to unlock

Definition at line 134 of file registrar_subscribe.c.

References subscriptions.

Referenced by add_r_subscription(), bin_cache_dump_subs_to_table(), bin_cache_load_subscriptions_from_table(), del_r_subscription(), get_r_subscription(), is_r_subscription(), load_snapshot_subscriptions(), make_snapshot_subscriptions(), print_subs(), r_notification_process(), r_subscribe(), r_subscribe_response(), subscription_timer(), and update_r_subscription().

00135 {
00136 //  LOG(L_CRIT,"REL %d\n",hash);    
00137     lock_release(subscriptions[hash].lock);
00138 }

int r_subscription_init (  ) 

Initialize the subscription list.

Returns:
1 if ok, 0 on error

Definition at line 143 of file registrar_subscribe.c.

References r_subscription_hash_slot::lock, subscriptions, and subscriptions_hash_size.

Referenced by mod_init().

00144 {
00145     int i;
00146     subscriptions = shm_malloc(sizeof(r_subscription_hash_slot)*subscriptions_hash_size);
00147     if (!subscriptions) return 0;
00148     memset(subscriptions,0,sizeof(r_subscription_hash_slot)*subscriptions_hash_size);
00149     for(i=0;i<subscriptions_hash_size;i++){
00150         subscriptions[i].lock = lock_alloc();
00151         if (!subscriptions[i].lock) return 0;
00152         subscriptions[i].lock = lock_init(subscriptions[i].lock);
00153     }
00154     return 1;
00155 }

void r_subscription_destroy (  ) 

Destroys the subscription list.

Definition at line 160 of file registrar_subscribe.c.

References free_r_subscription(), r_subscription_hash_slot::head, _r_subscription::next, subs_lock(), subscriptions, and subscriptions_hash_size.

Referenced by mod_destroy().

00161 {
00162     int i;
00163     r_subscription *s,*ns;
00164     for(i=0;i<subscriptions_hash_size;i++){
00165         subs_lock(i);
00166         s = subscriptions[i].head;
00167         while(s){
00168             ns = s->next;
00169             //TODO send out unSUBSCRIBE
00170             free_r_subscription(s);
00171             s = ns;
00172         }
00173         lock_destroy(subscriptions[i].lock);
00174         lock_dealloc(subscriptions[i].lock);
00175     }   
00176     shm_free(subscriptions);
00177 }

int P_subscribe ( struct sip_msg *  rpl,
char *  str1,
char *  str2 
)

Subscribe to the reg event to the S-CSCF.

Parameters:
rpl - 200 OK response to REGISTER containing contacts and Service-Route header
str1 - not used
str2 - not used
Returns:
CSCF_RETURN_TRUE if subscribed, CSCF_RETURN_FALSE if not or CSCF_RETURN_ERROR on error

Definition at line 187 of file registrar_subscribe.c.

References cscf_get_expires_hdr(), cscf_get_first_p_associated_uri(), cscf_parse_contacts(), CSCF_RETURN_ERROR, CSCF_RETURN_FALSE, CSCF_RETURN_TRUE, M_NAME, and r_subscribe().

00188 {
00189     int expires_hdr=0,r,max_expires;
00190     str public_id={0,0};
00191     contact_t* c=0;
00192     contact_body_t* b=0;    
00193     
00194     cscf_get_first_p_associated_uri(rpl,&public_id);
00195     
00196     expires_hdr = cscf_get_expires_hdr(rpl);
00197     
00198     if (parse_headers(rpl, HDR_EOH_F, 0) <0) {
00199         LOG(L_ERR,"ERR:"M_NAME":P_subscribe: error parsing headers\n");
00200         return CSCF_RETURN_ERROR;
00201     }   
00202     
00203     b = cscf_parse_contacts(rpl);
00204     
00205     if (!b||!b->contacts) {
00206         LOG(L_DBG,"DBG:"M_NAME":P_subscribe: No contacts found\n");
00207         return CSCF_RETURN_FALSE;
00208     }
00209     
00210     if (b) c = b->contacts;
00211     
00212     max_expires = expires_hdr;
00213     while(c){
00214         r = expires_hdr;
00215         if (str2int(&(c->expires->body), (unsigned int*)&r) < 0) {
00216             r = 0;
00217         }
00218         if (r>max_expires) max_expires = r;
00219         c = c->next;
00220     }
00221     if (max_expires<=0){
00222         LOG(L_INFO,"DBG:"M_NAME":P_subscribe: skipped because de-register\n");      
00223         return CSCF_RETURN_FALSE;       
00224     }
00225     
00226     if (public_id.s){
00227 //      if (max_expires==0)
00228 //          r_subscribe(public_id,0);
00229 //      else
00230         r_subscribe(public_id,max_expires+30);
00231         return CSCF_RETURN_TRUE;
00232     }else{
00233         return CSCF_RETURN_FALSE;
00234     }
00235 }

int r_subscribe ( str  uri,
int  duration 
)

Creates a subcription and starts the timer resubscription for the given contact.

Parameters:
uri - the contact to subscribe to (actually to its default public id)
duration - SUBCRIBE expires
Returns:
1 on success, 0 on failure

Definition at line 243 of file registrar_subscribe.c.

References add_r_subscription(), _r_subscription::attempts_left, _r_subscription::duration, get_r_subscription(), _r_subscription::hash, M_NAME, new_r_subscription(), pcscf_subscribe_retries, and subs_unlock().

Referenced by P_subscribe().

00244 {
00245     r_subscription *s;
00246     /* first we try to update. if not found, add it */
00247     s = get_r_subscription(uri);    
00248     if (s){
00249         s->duration = duration;
00250         s->attempts_left=pcscf_subscribe_retries;
00251         subs_unlock(s->hash);
00252     }else{          
00253         s = new_r_subscription(uri,duration);
00254         if (!s){
00255             LOG(L_ERR,"ERR:"M_NAME":r_subscribe: Error creating new subscription\n");
00256             return 0;
00257         }
00258         add_r_subscription(s);
00259         s->attempts_left=pcscf_subscribe_retries;
00260     }
00261         
00262     return 1;
00263 }

int r_send_subscribe ( r_subscription s,
int  duration 
)

Send a subscription.

Parameters:
s - the subsription to send for
duration - expires time
Returns:
true if OK, false if not, error on failure
Todo:
store the dialog and reSubscribe on the same dialog

Definition at line 284 of file registrar_subscribe.c.

References accept_hdr, contact_e, contact_s, content_len_hdr, _r_subscription::dialog, dialogb, event_hdr, expires_e, expires_s, M_NAME, max_fwds_hdr, method, p_asserted_identity_e, p_asserted_identity_s, pcscf_name_str, pcscf_path_str, r_subscribe_response(), _r_subscription::req_uri, STR_APPEND, and tmb.

Referenced by subscription_timer().

00285 {
00286     str h={0,0};
00287 
00288     LOG(L_DBG,"DBG:"M_NAME":r_send_subscribe: SUBSCRIBE to <%.*s>\n",
00289         s->req_uri.len,s->req_uri.s);
00290     
00291     h.len = event_hdr.len+accept_hdr.len+content_len_hdr.len+max_fwds_hdr.len;
00292     h.len += expires_s.len + 12 + expires_e.len;
00293 
00294     h.len += contact_s.len + pcscf_name_str.len + contact_e.len;
00295     if (pcscf_path_str.len) h.len += p_asserted_identity_s.len + 
00296         p_asserted_identity_e.len + pcscf_path_str.len;
00297 
00298     h.s = pkg_malloc(h.len);
00299     if (!h.s){
00300         LOG(L_ERR,"ERR:"M_NAME":r_send_subscribe: Error allocating %d bytes\n",h.len);
00301         h.len = 0;
00302         return 0;
00303     }
00304 
00305     h.len = 0;
00306     STR_APPEND(h,event_hdr);
00307     STR_APPEND(h,accept_hdr);
00308     STR_APPEND(h,content_len_hdr);
00309     STR_APPEND(h,max_fwds_hdr);
00310 
00311     STR_APPEND(h,expires_s);
00312     sprintf(h.s+h.len,"%d",duration);
00313     h.len += strlen(h.s+h.len);
00314     STR_APPEND(h,expires_e);
00315 
00316     STR_APPEND(h,contact_s);
00317     STR_APPEND(h,pcscf_name_str);
00318     STR_APPEND(h,contact_e);
00319     
00320     if (pcscf_path_str.len) {
00321         STR_APPEND(h,p_asserted_identity_s);
00322         STR_APPEND(h,pcscf_path_str);
00323         STR_APPEND(h,p_asserted_identity_e);
00324     }
00325     
00326     if (!s->dialog){
00327         /* this is the first request in the dialog */
00328         if (tmb.new_dlg_uac(0,0,1,&pcscf_name_str,&s->req_uri,&s->dialog)<0){
00329             LOG(L_ERR,"ERR:"M_NAME":r_send_subscribe: Error creating a dialog for SUBSCRIBE\n");
00330             goto error;
00331         }
00332         if (dialogb.request_outside(&method, &h, 0, s->dialog, r_subscribe_response,  0) < 0){
00333             LOG(L_ERR,"ERR:"M_NAME":r_send_subscribe: Error sending initial request in a SUBSCRIBE dialog\n");
00334             goto error;
00335         }       
00336     }else{
00337         /* this is a subsequent subscribe */
00338         if (dialogb.request_inside(&method, &h, 0, s->dialog, r_subscribe_response,  0) < 0){
00339             LOG(L_ERR,"ERR:"M_NAME":r_send_subscribe: Error sending subsequent request in a SUBSCRIBE dialog\n");
00340             goto error;
00341         }               
00342     }
00343 
00344     if (h.s) pkg_free(h.s);
00345     return 1;
00346 
00347 error:
00348     if (h.s) pkg_free(h.s);
00349     return 0;
00350 }

void r_subscribe_response ( struct cell *  t,
int  type,
struct tmcb_params *  ps 
)

Response callback for subscribe.

Definition at line 355 of file registrar_subscribe.c.

References cscf_get_expires_hdr(), cscf_get_to_uri(), _r_subscription::dialog, get_r_subscription(), _r_subscription::hash, M_NAME, subs_unlock(), tmb, and update_r_subscription().

Referenced by r_send_subscribe().

00356 {
00357     str req_uri;
00358     int expires;
00359     r_subscription *s=0;
00360     LOG(L_DBG,"DBG:"M_NAME":r_subscribe_response: code %d\n",ps->code);
00361     if (!ps->rpl || ps->rpl==(void*) -1) {
00362         LOG(L_ERR,"INF:"M_NAME":r_subscribe_response: No reply\n");
00363         return; 
00364     }
00365     if (!cscf_get_to_uri(ps->rpl,&req_uri)){
00366         LOG(L_ERR,"INF:"M_NAME":r_subscribe_response: Error extracting the original Req-URI from To header\n");
00367         return;
00368     }       
00369     s = get_r_subscription(req_uri);
00370     if (!s){
00371         LOG(L_ERR,"INF:"M_NAME":r_subscribe_response: received a SUBSCRIBE response but no subscription for <%.*s>\n",
00372             req_uri.len,req_uri.s);
00373         return;
00374     }
00375     if (ps->code>=200 && ps->code<300){
00376         expires = cscf_get_expires_hdr(ps->rpl);
00377         update_r_subscription(s,expires);
00378         tmb.dlg_response_uac(s->dialog, ps->rpl, IS_TARGET_REFRESH);
00379     }else
00380         if (ps->code==404){
00381             update_r_subscription(s,0);         
00382             //tmb.dlg_response_uac(s->dialog, ps->rpl, IS_TARGET_REFRESH);
00383         }else{
00384             LOG(L_INFO,"INF:"M_NAME":r_subscribe_response: SUBSCRIRE response code %d ignored\n",ps->code);             
00385         }   
00386     if (s) subs_unlock(s->hash);        
00387 }

void subscription_timer ( unsigned int  ticks,
void *  param 
)

The Subscription timer looks for almost expired subscriptions and subscribes again.

Parameters:
ticks - the current time
param - the generic parameter

Definition at line 399 of file registrar_subscribe.c.

References _r_subscription::attempts_left, del_r_subscription_nolock(), _r_subscription::duration, _r_subscription::expires, r_subscription_hash_slot::head, IMS_PM_LOG01, M_NAME, _r_subscription::next, pcscf_subscribe_retries, print_subs(), r_act_time(), r_send_subscribe(), subs_lock(), subs_unlock(), subscriptions, subscriptions_hash_size, and time_now.

Referenced by mod_init().

00400 {
00401     r_subscription *s,*ns;
00402     int i;
00403     #ifdef WITH_IMS_PM
00404         int subs_cnt=0;
00405     #endif
00406     for(i=0;i<subscriptions_hash_size;i++){
00407         subs_lock(i);
00408         s = subscriptions[i].head;
00409         r_act_time();
00410         while(s){
00411             ns = s->next;           
00412             if (s->attempts_left > 0 ){
00413                 /* attempt to send a subscribe */
00414                 if (!r_send_subscribe(s,s->duration)){
00415                     LOG(L_ERR,"ERR:"M_NAME":subscription_timer: Error on SUBSCRIBE (%d times)... droping\n",
00416                         pcscf_subscribe_retries);
00417                     del_r_subscription_nolock(s);
00418                 }else{
00419                     s->attempts_left--;
00420                     #ifdef WITH_IMS_PM
00421                         subs_cnt++;
00422                     #endif
00423                 }
00424             }else if (s->attempts_left==0) {
00425                 /* we failed to many times, drop the subscription */
00426                 LOG(L_ERR,"ERR:"M_NAME":subscription_timer: Error on SUBSCRIBE for %d times... aborting\n",pcscf_subscribe_retries);
00427                 del_r_subscription_nolock(s);                                       
00428             }else{
00429                 /* we are subscribed already */
00430                 /* if expired, drop it */
00431                 if (s->expires<time_now) 
00432                     del_r_subscription_nolock(s);
00433                 #ifdef WITH_IMS_PM
00434                     else subs_cnt++;
00435                 #endif
00436                     
00437                 /* if not expired, check for renewal */
00438 //      Commented as the S-CSCF should adjust the subscription time accordingly             
00439 //              if ((s->duration<1200 && s->expires-time_now<s->duration/2)||
00440 //                  (s->duration>=1200 && s->expires-time_now<600))
00441 //              {
00442 //                  /* if we need a resubscribe, we mark it as such and try to subscribe again */                   
00443 //                  s->attempts_left = pcscf_subscribe_retries;
00444 //                  ns = s;
00445 //              }
00446             }
00447             s = ns;
00448         }   
00449         subs_unlock(i);
00450     }
00451     print_subs(L_INFO);
00452     #ifdef WITH_IMS_PM
00453         IMS_PM_LOG01(RD_NbrSubs,subs_cnt);
00454     #endif  
00455 }

r_subscription* new_r_subscription ( str  req_uri,
int  duration 
)

Creates a subscription based on the given parameters.

Parameters:
req_uri - the AOR of the user to subcribe to
from - the From header
duration - expires time in seconds
asserted_identity - P-Asserted-Identity-Header to use
Returns:
the r_notification or NULL on error

Definition at line 469 of file registrar_subscribe.c.

References _r_subscription::duration, _r_subscription::expires, M_NAME, _r_subscription::req_uri, and STR_SHM_DUP.

Referenced by r_subscribe().

00470 {
00471     r_subscription *s=0;
00472     
00473     s = shm_malloc(sizeof(r_subscription));
00474     if (!s){
00475         LOG(L_ERR,"ERR:"M_NAME":new_r_subscription: Error allocating %d bytes\n",
00476             sizeof(r_subscription));
00477         goto error;
00478     }
00479     memset(s,0,sizeof(r_subscription));
00480     
00481     STR_SHM_DUP(s->req_uri,req_uri,"new_r_subscription");
00482     if (!s->req_uri.s) goto error;
00483         
00484     s->duration = duration;
00485     s->expires = 0;
00486     
00487     return s;
00488 error:
00489 out_of_memory:
00490     if (s->req_uri.s) shm_free(s->req_uri.s);
00491     if (s) shm_free(s); 
00492     return 0;
00493 }

void add_r_subscription ( r_subscription s  ) 

Adds a subscription to the list of subscriptions at the end (FIFO).

Parameters:
s - the subscription to be added

Definition at line 499 of file registrar_subscribe.c.

References get_subscription_hash(), _r_subscription::hash, r_subscription_hash_slot::head, _r_subscription::next, _r_subscription::prev, _r_subscription::req_uri, subs_lock(), subs_unlock(), subscriptions, and r_subscription_hash_slot::tail.

Referenced by r_subscribe().

00500 {
00501     if (!s) return;
00502     s->hash = get_subscription_hash(s->req_uri);
00503     subs_lock(s->hash);
00504         s->next = 0;
00505         s->prev = subscriptions[s->hash].tail;
00506         if (subscriptions[s->hash].tail) subscriptions[s->hash].tail->next = s;         
00507         subscriptions[s->hash].tail = s;
00508         if (!subscriptions[s->hash].head) subscriptions[s->hash].head = s;      
00509     subs_unlock(s->hash);
00510 }

int update_r_subscription ( r_subscription s,
int  expires 
)

Updates the expiration time of a subscription.

Todo:
Maybe we should use a hash here to index it as this is called for every notification
Parameters:
aor - aor to look for
expires - new expiration time
Returns:
1 if found, 0 if not

Definition at line 519 of file registrar_subscribe.c.

References _r_subscription::attempts_left, del_r_subscription_nolock(), _r_subscription::expires, _r_subscription::hash, M_NAME, _r_subscription::req_uri, subs_unlock(), and time_now.

Referenced by r_notification_process(), and r_subscribe_response().

00520 {
00521     LOG(L_DBG,"DBG:"M_NAME":update_r_subscription: refreshing subscription for <%.*s> [%d]\n",
00522         s->req_uri.len,s->req_uri.s,expires);
00523     s->attempts_left = -1;
00524     if (expires == 0) del_r_subscription_nolock(s);
00525     else s->expires = expires+time_now;;
00526     subs_unlock(s->hash);   
00527     return 1;
00528 }

r_subscription* get_r_subscription ( str  aor  ) 

Returns a subscription if it exists.

Note:
- this returns with a lock on the subscriptions[s->hash] if found. Don't forget to unlock when done!!!
Parameters:
aor - AOR to look for
Returns:
1 if found, 0 if not

Definition at line 536 of file registrar_subscribe.c.

References get_subscription_hash(), r_subscription_hash_slot::head, _r_subscription::next, _r_subscription::req_uri, subs_lock(), subs_unlock(), and subscriptions.

Referenced by r_notification_process(), r_subscribe(), and r_subscribe_response().

00537 {
00538     r_subscription *s;
00539     unsigned int hash = get_subscription_hash(aor);
00540     subs_lock(hash);
00541         s = subscriptions[hash].head;
00542         while(s){
00543             if (s->req_uri.len == aor.len &&
00544                 strncasecmp(s->req_uri.s,aor.s,aor.len)==0)
00545             {
00546                 return s;
00547             }
00548             s = s->next;
00549         }
00550     subs_unlock(hash);  
00551     return 0;
00552 }

int is_r_subscription ( str  aor  ) 

Finds out if a subscription exists.

Parameters:
aor - AOR to look for
Returns:
1 if found, 0 if not

Definition at line 559 of file registrar_subscribe.c.

References get_subscription_hash(), r_subscription_hash_slot::head, _r_subscription::next, _r_subscription::req_uri, subs_lock(), subs_unlock(), and subscriptions.

00560 {
00561     r_subscription *s;
00562     unsigned int hash = get_subscription_hash(aor);
00563     subs_lock(hash);
00564         s = subscriptions[hash].head;
00565         while(s){
00566             if (s->req_uri.len == aor.len &&
00567                 strncasecmp(s->req_uri.s,aor.s,aor.len)==0)
00568             {
00569                 subs_unlock(hash);  
00570                 return 1;
00571             }
00572             s = s->next;
00573         }
00574     subs_unlock(hash);  
00575     return 0;
00576 }

void del_r_subscription ( r_subscription s  ) 

Deletes a subscription from the list of subscriptions.

Parameters:
s - the subscription to be deleted

Definition at line 582 of file registrar_subscribe.c.

References free_r_subscription(), _r_subscription::hash, r_subscription_hash_slot::head, _r_subscription::next, _r_subscription::prev, subs_lock(), subs_unlock(), subscriptions, and r_subscription_hash_slot::tail.

00583 {
00584     if (!s) return;
00585     subs_lock(s->hash);
00586         if (subscriptions[s->hash].head == s) subscriptions[s->hash].head = s->next;
00587         else s->prev->next = s->next;
00588         if (subscriptions[s->hash].tail == s) subscriptions[s->hash].tail = s->prev;
00589         else s->next->prev = s->prev;
00590     subs_unlock(s->hash);
00591     free_r_subscription(s);
00592 }

void del_r_subscription_nolock ( r_subscription s  ) 

Deletes a subscription from the list of subscriptions.

Note:
Must have the lock to do this
Parameters:
s - the subscription to be deleted

Definition at line 599 of file registrar_subscribe.c.

References free_r_subscription(), _r_subscription::hash, r_subscription_hash_slot::head, _r_subscription::next, _r_subscription::prev, subscriptions, and r_subscription_hash_slot::tail.

Referenced by subscription_timer(), and update_r_subscription().

00600 {
00601     if (!s) return;
00602     if (subscriptions[s->hash].head == s) subscriptions[s->hash].head = s->next;
00603     else s->prev->next = s->next;
00604     if (subscriptions[s->hash].tail == s) subscriptions[s->hash].tail = s->prev;
00605     else s->next->prev = s->prev;
00606     free_r_subscription(s);
00607 }

void free_r_subscription ( r_subscription s  ) 

Frees up space taken by a subscription.

Parameters:
s - the subscription to free

Definition at line 613 of file registrar_subscribe.c.

References _r_subscription::dialog, _r_subscription::req_uri, and tmb.

Referenced by del_r_subscription(), del_r_subscription_nolock(), and r_subscription_destroy().

00614 {
00615     if (s){
00616         if (s->req_uri.s) shm_free(s->req_uri.s);
00617         if (s->dialog) tmb.free_dlg(s->dialog);
00618         shm_free(s);
00619     }
00620 }

void print_subs ( int  log_level  ) 

Definition at line 622 of file registrar_subscribe.c.

References ANSI_BLUE, ANSI_CYAN, ANSI_GREEN, ANSI_MAGENTA, _r_subscription::attempts_left, _r_subscription::duration, _r_subscription::expires, _r_subscription::hash, r_subscription_hash_slot::head, M_NAME, _r_subscription::next, r_act_time(), _r_subscription::req_uri, subs_lock(), subs_unlock(), subscriptions, subscriptions_hash_size, and time_now.

Referenced by subscription_timer().

00623 {
00624     r_subscription *s;
00625     int i;
00626     if (debug<log_level) return; /* to avoid useless calls when nothing will be printed */  
00627     LOG(log_level,ANSI_GREEN"INF:"M_NAME":----------  Subscription list begin ---------\n");
00628     for(i=0;i<subscriptions_hash_size;i++){
00629         subs_lock(i);
00630         s = subscriptions[i].head;
00631         r_act_time();
00632         while(s){
00633             LOG(log_level,ANSI_GREEN"INF:"M_NAME":[%4u]\tP: <"ANSI_BLUE"%.*s"ANSI_GREEN"> D:["ANSI_CYAN"%5d"ANSI_GREEN"] E:["ANSI_MAGENTA"%5d"ANSI_GREEN"] Att:[%2d]\n",
00634                 s->hash,s->req_uri.len,s->req_uri.s,s->duration,(int)(s->expires-time_now),s->attempts_left);
00635             s = s->next;            
</