registrar_notify.c File Reference


Detailed Description

Serving-CSCF - "reg" Event Operations.

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

Definition in file registrar_notify.c.

#include "registrar_notify.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 "sip.h"
#include "ims_pm.h"

Go to the source code of this file.

Defines

#define MAX_REGINFO_SIZE   16384
 Maximum reginfo XML size.

Functions

int r_notify_init ()
 Initializes the reg notifications list.
void r_notify_destroy ()
 Destroys the reg notifications list.
int S_can_subscribe (struct sip_msg *msg, char *str1, char *str2)
 Check if this message quallifies for a subscription.
int S_subscribe (struct sip_msg *msg, char *str1, char *str2)
 Save this subscription.
int S_SUBSCRIBE_reply (struct sip_msg *msg, int code, char *text, int *expires, str *contact)
 Replies to a SUBSCRIBE and also adds the need headers.
static void r_create_notifications (void *pv, void *cv, void *ps, str content, long expires)
 Creates notifications with the given content for all of the subscribers.
static long r_update_subscription_status (r_public *p)
 Look if there are no more public ids or contacts registered and expires the subscription.
str r_get_reginfo_full (void *pv, int event_type, long *subsExpires)
 Creates the full reginfo XML.
str r_get_reginfo_partial (void *pv, void *pc, int event_type, long *subsExpires)
 Creates the partial reginfo XML.
int S_event_reg (void *pv, void *c, void *ps, int event_type, int send_now)
 Generate notifications and put them in the notification queue to be sent.
void uac_request_cb (struct cell *t, int type, struct tmcb_params *ps)
 Callback for the UAC response to NOTIFY.
void send_notification (r_notification *n)
 Creates a NOTIFY message and sends it.
void notification_timer (unsigned int ticks, void *param)
 The Notification timer looks for unsent notifications and sends them.
r_notificationnew_r_notification (str req_uri, str uri, str subscription_state, str event, str content_type, str content, dlg_t *dialog, int version)
 Creates a notification based on the given parameters.
void add_r_notification (r_notification *n)
 Adds a notification to the list of notifications at the end (FIFO).
void free_r_notification (r_notification *n)
 Frees up space taken by a notification.

Variables

tm_binds tmb
 Structure with pointers to tm funcs.
str scscf_name_str
 fixed name of the S-CSCF
int subscription_default_expires
 the default value for expires if none found
int subscription_min_expires
 minimum subscription expiration time
int subscription_max_expires
 maximum subscription expiration time
time_t time_now
 Current time of the S-CSCF registrar.
int r_hash_size
 Size of S-CSCF registrar hash table.
r_hash_slotregistrar
 The S-CSCF registrar.
r_notification_listnotification_list = 0
 list of notifications for reg to be sent
static str lookup_sip = {"sip:",4}
str expires_hdr1 = {"Expires: ",9}
str expires_hdr2 = {"\r\n",2}
str contact_hdr1 = {"Contact: <",10}
str contact_hdr2 = {">\r\n",3}
static str ruri_lr = {";lr",3}
static str subs_terminated = {"terminated",10}
static str subs_active = {"active;expires=",15}
static str xml_start = {"<?xml version=\"1.0\"?>\n",22}
static str r_full = {"full",4}
static str r_partial = {"partial",7}
static str r_reginfo_s = {"<reginfo xmlns=\"urn:ietf:params:xml:ns:reginfo\" version=\"%s\" state=\"%.*s\">\n",74}
static str r_reginfo_e = {"</reginfo>\n",11}
static str r_active = {"active",6}
static str r_terminated = {"terminated",10}
static str registration_s = {"\t<registration aor=\"%.*s\" id=\"%p\" state=\"%.*s\">\n",48}
static str registration_e = {"\t</registration>\n",17}
static str r_registered = {"registered",10}
static str r_created = {"created",7}
static str r_refreshed = {"refreshed",9}
static str r_shortened = {"shortened",9}
static str r_expired = {"expired",7}
static str r_deactivated = {"deactivated",11}
static str r_probation = {"probation",9}
static str r_unregistered = {"unregistered",12}
static str r_rejected = {"rejected",8}
static str contact_s = {"\t\t<contact id=\"%p\" state=\"%.*s\" event=\"%.*s\" expires=\"%d\">\n",59}
static str contact_s_q = {"\t\t<contact id=\"%p\" state=\"%.*s\" event=\"%.*s\" expires=\"%d\" q=\"%.3f\">\n",69}
static str contact_e = {"\t\t</contact>\n",13}
static str uri_s = {"\t\t\t<uri>",8}
static str uri_e = {"</uri>\n",7}
static str method = {"NOTIFY",6}
static str event_hdr = {"Event: reg\r\n",12}
static str maxfwds_hdr = {"Max-Forwards: 70\r\n",18}
static str subss_hdr1 = {"Subscription-State: ",20}
static str subss_hdr2 = {"\r\n",2}
static str ctype_hdr1 = {"Content-Type: ",14}
static str ctype_hdr2 = {"\r\n",2}


Define Documentation

#define MAX_REGINFO_SIZE   16384

Maximum reginfo XML size.

Definition at line 532 of file registrar_notify.c.

Referenced by new_r_notification(), r_get_reginfo_full(), and r_get_reginfo_partial().


Function Documentation

int r_notify_init (  ) 

Initializes the reg notifications list.

Definition at line 85 of file registrar_notify.c.

References r_notification_list::lock, and notification_list.

Referenced by mod_init().

00086 {
00087     notification_list = shm_malloc(sizeof(r_notification_list));
00088     if (!notification_list) return 0;
00089     memset(notification_list,0,sizeof(r_notification_list));
00090     notification_list->lock = lock_alloc();
00091     if (!notification_list->lock) return 0;
00092     notification_list->lock = lock_init(notification_list->lock);
00093     return 1;
00094 }

void r_notify_destroy (  ) 

Destroys the reg notifications list.

Definition at line 99 of file registrar_notify.c.

References free_r_notification(), r_notification_list::head, r_notification_list::lock, and notification_list.

Referenced by mod_destroy().

00100 {
00101     r_notification *n,*nn;
00102     lock_get(notification_list->lock);
00103     n = notification_list->head;
00104     while(n){
00105         nn = n->next;
00106         free_r_notification(n);
00107         n = nn;
00108     }
00109     lock_destroy(notification_list->lock);
00110     lock_dealloc(notification_list->lock);  
00111     shm_free(notification_list);
00112 }

int S_can_subscribe ( struct sip_msg *  msg,
char *  str1,
char *  str2 
)

Check if this message quallifies for a subscription.

Only 3 entities can subscribe:

Definition at line 128 of file registrar_notify.c.

References _r_public::aor, ims_public_identity::barring, cscf_get_asserted_identity(), cscf_get_event(), CSCF_RETURN_FALSE, CSCF_RETURN_TRUE, get_r_public(), if, lookup_sip, M_NAME, ims_service_profile::public_identities, ims_service_profile::public_identities_cnt, ims_public_identity::public_identity, _r_public::s, ims_subscription::service_profiles, and ims_subscription::service_profiles_cnt.

00129 {
00130     int ret=CSCF_RETURN_FALSE;
00131     struct sip_uri puri;
00132     str uri={0,0};
00133     str event;
00134     str asserted_id;
00135     r_public *p=0;
00136     r_contact *c=0;
00137     ims_public_identity *pi=0;
00138     int i,j;
00139 
00140     LOG(L_DBG,"DBG:"M_NAME":S_can_subscribe: Checking if allowed to SUBSCRIBE\n");
00141 
00142     /* First check the parameters */
00143     if (msg->first_line.type!=SIP_REQUEST)
00144     {
00145         LOG(L_ERR,"ERR:"M_NAME":S_can_subscribe: This message is not a request\n");
00146         goto error;
00147     }       
00148     if (msg->first_line.u.request.method.len != 9 ||
00149         memcmp(msg->first_line.u.request.method.s,"SUBSCRIBE",9)!=0)
00150     {
00151         LOG(L_ERR,"ERR:"M_NAME":S_can_subscribe: This message is not a SUBSCRIBE\n");
00152         goto error;
00153     }
00154 
00155     /* 1. Get the event     */
00156     event = cscf_get_event(msg);
00157     if (event.len!=3||strncasecmp(event.s,"reg",3)!=0){
00158         LOG(L_ERR,"ERR:"M_NAME":S_can_subscribe: Accepting only <Event: reg>. Found: <%.*s>\n",
00159             event.len,event.s);
00160         ret = CSCF_RETURN_FALSE;    
00161         goto done;
00162     } 
00163     
00164     /* 2. Get the target of the SUBSCRIBE from RequestURI */
00165     if (msg->new_uri.s) uri = msg->new_uri;
00166     else uri = msg->first_line.u.request.uri;
00167     
00168     if (parse_uri(uri.s, uri.len, &puri) < 0) {
00169         LOG(L_ERR,"ERR:"M_NAME":S_can_subscribe: Error parsing uri <%.*s>\n",
00170             uri.len,uri.s);
00171         goto error;
00172     }
00173     uri.len = lookup_sip.len+puri.user.len+1+puri.host.len;
00174     uri.s = pkg_malloc(uri.len);
00175     if (!uri.s){
00176         LOG(L_ERR,"ERR:"M_NAME":S_can_subscribe: Error allocating %d bytes\n",uri.len);
00177         goto error;
00178     }
00179     uri.len=0;
00180     memcpy(uri.s,lookup_sip.s,lookup_sip.len);
00181     uri.len+=lookup_sip.len;
00182     memcpy(uri.s+uri.len,puri.user.s,puri.user.len);
00183     uri.len+=puri.user.len;
00184     uri.s[uri.len++]='@';
00185     memcpy(uri.s+uri.len,puri.host.s,puri.host.len);
00186     uri.len+=puri.host.len;
00187 
00188     /* 3. Check if the asserted identity is in the same group with the ReqURI */
00189     asserted_id = cscf_get_asserted_identity(msg);
00190     if (!asserted_id.len){
00191         LOG(L_ERR,"ERR:"M_NAME":S_can_subscribe: P-Asserted-Identity empty.\n");
00192         ret =  CSCF_RETURN_FALSE;
00193         goto done;      
00194     }
00195     LOG(L_DBG,"DBG:"M_NAME":S_can_subscribe: P-Asserted-Identity <%.*s>.\n",
00196         asserted_id.len,asserted_id.s);
00197     
00198     p = get_r_public(uri);
00199     
00200     if (!p){
00201         LOG(L_ERR,"ERR:"M_NAME":S_can_subscribe: Identity not found <%.*s>\n",
00202             uri.len,uri.s);
00203         ret =  CSCF_RETURN_FALSE;
00204         goto done;
00205     }
00206     if (p->aor.len == asserted_id.len &&
00207         strncasecmp(p->aor.s,asserted_id.s,asserted_id.len)==0)
00208     {
00209         LOG(L_DBG,"DBG:"M_NAME":S_can_subscribe: Identity found as AOR <%.*s>\n",
00210             uri.len,uri.s);
00211         ret = CSCF_RETURN_TRUE;
00212         goto done;
00213     }
00214     if (p->s){
00215         for(i=0;i<p->s->service_profiles_cnt;i++)
00216             for(j=0;j<p->s->service_profiles[i].public_identities_cnt;j++)
00217             {
00218                 pi = &(p->s->service_profiles[i].public_identities[j]);
00219                 if (!pi->barring &&
00220                     pi->public_identity.len == asserted_id.len &&
00221                     strncasecmp(pi->public_identity.s,asserted_id.s,asserted_id.len)==0)
00222                 {
00223                     LOG(L_DBG,"DBG:"M_NAME":S_can_subscribe: Identity found in SP[%d][%d]\n",
00224                         i,j);
00225                     ret = CSCF_RETURN_TRUE;
00226                     goto done;
00227                 }   
00228             }
00229     }
00230     
00231     /* 4. Check if it present in any of the Path headers */
00232     c=p->head;
00233 
00234     while(c){
00235         if (c->path.len){
00236             for(i=0;i<c->path.len-asserted_id.len;i++)
00237                 if (strncasecmp(c->path.s+i,asserted_id.s,asserted_id.len)==0){
00238                     LOG(L_DBG,"DBG:"M_NAME":S_can_subscribe: Identity found in Path <%.*s>\n",
00239                         c->path.len,c->path.s);
00240                     ret = CSCF_RETURN_TRUE;
00241                     goto done;
00242                 }
00243         }
00244         c = c->next;
00245     }
00246     
00247     
00248 done:
00249     if (p) r_unlock(p->hash);
00250     if (uri.s) pkg_free(uri.s);
00251     return ret;
00252 error:
00253     if (p) r_unlock(p->hash);
00254     if (uri.s) pkg_free(uri.s);
00255     ret=CSCF_RETURN_ERROR;
00256     return ret; 
00257 }

int S_subscribe ( struct sip_msg *  msg,
char *  str1,
char *  str2 
)

Save this subscription.

Parameters:
msg - the SIP SUBSCRIBE message
str1 - not used
str2 - not used
Returns:
CSCF_RETURN_TRUE if allowed, CSCF_RETURN_FALSE if not, CSCF_RETURN_ERROR on error

Definition at line 267 of file registrar_notify.c.

References add_r_public(), cscf_get_contact(), cscf_get_event(), cscf_get_expires_hdr(), CSCF_RETURN_FALSE, CSCF_RETURN_TRUE, del_r_subscriber(), _r_subscriber::dialog, _r_subscriber::expires, get_r_public(), get_r_subscriber(), _r_public::hash, IMS_EVENT_NONE, IMS_EVENT_REG, IMS_REGISTRAR_SUBSCRIBE, IMS_REGISTRAR_UNSUBSCRIBE, lookup_sip, M_NAME, MSG_REG_SUBSCRIBE_OK, MSG_REG_UNSUBSCRIBE_OK, r_act_time(), r_unlock(), S_event_reg(), S_SUBSCRIBE_reply(), subscription_default_expires, subscription_max_expires, subscription_min_expires, time_now, tmb, and update_r_subscriber().

00268 {
00269     int ret=CSCF_RETURN_FALSE;
00270     struct sip_uri puri;
00271     str uri={0,0};
00272     str event;
00273     int event_i=IMS_EVENT_NONE;
00274     int expires=0,expires_time=0;
00275     str subscriber;
00276     r_public *p=0;
00277     r_subscriber *s=0,*new_s=0;
00278     dlg_t *dialog=0;
00279 
00280     LOG(L_DBG,"DBG:"M_NAME":S_subscribe: Saving SUBSCRIBE\n");
00281 
00282     /* First check the parameters */
00283     if (msg->first_line.type!=SIP_REQUEST)
00284     {
00285         LOG(L_ERR,"ERR:"M_NAME":S_subscribe: This message is not a request\n");
00286         goto error;
00287     }       
00288     if (msg->first_line.u.request.method.len != 9 ||
00289         memcmp(msg->first_line.u.request.method.s,"SUBSCRIBE",9)!=0)
00290     {
00291         LOG(L_ERR,"ERR:"M_NAME":S_subscribe: This message is not a SUBSCRIBE\n");
00292         goto error;
00293     }
00294 
00295     /* 1. Get the event     */
00296     event = cscf_get_event(msg);
00297     if (event.len!=3||strncasecmp(event.s,"reg",3)!=0){
00298         LOG(L_ERR,"ERR:"M_NAME":S_subscribe: Accepting only <Event: reg>. Found: <%.*s>\n",
00299             event.len,event.s);
00300         ret = CSCF_RETURN_FALSE;    
00301         goto done;
00302     } 
00303     if (event.len==0 && strncasecmp(event.s,"reg",3)==0)
00304         event_i = IMS_EVENT_REG;
00305     
00306     /* 2. Get the target of the SUBSCRIBE from RequestURI */
00307     if (msg->new_uri.s) uri = msg->new_uri;
00308     else uri = msg->first_line.u.request.uri;
00309     
00310     if (parse_uri(uri.s, uri.len, &puri) < 0) {
00311         LOG(L_ERR,"ERR:"M_NAME":S_subscribe: Error parsing uri <%.*s>\n",
00312             uri.len,uri.s);
00313         goto error;
00314     }
00315     uri.len = lookup_sip.len+puri.user.len+1+puri.host.len;
00316     uri.s = pkg_malloc(uri.len);
00317     if (!uri.s){
00318         LOG(L_ERR,"ERR:"M_NAME":S_subscribe: Error allocating %d bytes\n",uri.len);
00319         goto error;
00320     }
00321     uri.len=0;
00322     memcpy(uri.s,lookup_sip.s,lookup_sip.len);
00323     uri.len+=lookup_sip.len;
00324     memcpy(uri.s+uri.len,puri.user.s,puri.user.len);
00325     uri.len+=puri.user.len;
00326     uri.s[uri.len++]='@';
00327     memcpy(uri.s+uri.len,puri.host.s,puri.host.len);
00328     uri.len+=puri.host.len;
00329 
00330     /* 3. Get the Subscriber's Identity */
00331     subscriber = cscf_get_contact(msg);
00332     if (!subscriber.len){
00333         LOG(L_ERR,"ERR:"M_NAME":S_subscribe: Contact empty.\n");
00334         ret =  CSCF_RETURN_FALSE;
00335         goto done;      
00336     }
00337     LOG(L_DBG,"DBG:"M_NAME":S_subscribe: Contact <%.*s>.\n",
00338         subscriber.len,subscriber.s);
00339     
00340     p = get_r_public(uri);
00341 
00342     /* Registration is possible even if the user is not registered... so just create one */
00343     if (!p){
00344         p = add_r_public(uri,0,0);
00345     }
00346     if (!p){        
00347         LOG(L_ERR,"ERR:"M_NAME":S_subscribe: Identity not found and error on creation <%.*s>\n",
00348             uri.len,uri.s);
00349         ret =  CSCF_RETURN_FALSE;
00350         goto done;
00351     }
00352         
00353     expires = cscf_get_expires_hdr(msg);
00354     if (expires == -1) expires = subscription_default_expires;
00355     if (expires > 0) {
00356         if (expires < subscription_min_expires) expires = subscription_min_expires;
00357         if (expires > subscription_max_expires) expires = subscription_max_expires;
00358         r_act_time();
00359         expires_time = expires + time_now;
00360         
00361         /* get the old subscriber - if any */
00362         s = get_r_subscriber(p,subscriber,event_i); 
00363         if (!s){
00364             /* create a new dialog */
00365             if (tmb.new_dlg_uas(msg, 200, &dialog) < 0) {       
00366                 LOG(L_ERR,"ERR:"M_NAME":S_subscribe:  Error while creating dialog state\n");
00367                 ret = CSCF_RETURN_FALSE;
00368                 goto error;
00369             }
00370         }else
00371             dialog = s->dialog;
00372         
00373         /* update the subscriber */
00374         if ((new_s=update_r_subscriber(p,subscriber,event_i,&expires_time,dialog))!=0){     
00375             //if (!s)   /* Only on first subscription, not on refreshes, send a notify */
00376                 S_event_reg(p,0,new_s,IMS_REGISTRAR_SUBSCRIBE,0);
00377             ret = CSCF_RETURN_TRUE;
00378         }
00379         else
00380             ret = CSCF_RETURN_FALSE;    
00381     }else{
00382         /* Unsubscribe */
00383         /* get the old subscriber - if any */
00384         r_act_time();
00385         s = get_r_subscriber(p,subscriber,event_i); 
00386         if (s) {
00387             s->expires = time_now;
00388             S_event_reg(p,0,s,IMS_REGISTRAR_UNSUBSCRIBE,1);
00389             del_r_subscriber(p,s);
00390         }
00391         ret = CSCF_RETURN_TRUE;
00392     }
00393 done:   
00394     r_unlock(p->hash);
00395     if (expires ==0 )S_SUBSCRIBE_reply(msg,200,MSG_REG_UNSUBSCRIBE_OK,&expires,&uri);
00396     else S_SUBSCRIBE_reply(msg,200,MSG_REG_SUBSCRIBE_OK,&expires,&uri);
00397     if (uri.s) pkg_free(uri.s);
00398     return ret;
00399 error:
00400     if (p) r_unlock(p->hash);
00401     if (uri.s) pkg_free(uri.s);
00402     ret=CSCF_RETURN_FALSE;
00403     return ret; 
00404 }

int S_SUBSCRIBE_reply ( struct sip_msg *  msg,
int  code,
char *  text,
int *  expires,
str *  contact 
)

Replies to a SUBSCRIBE and also adds the need headers.

Path for example.

Parameters:
msg - the SIP SUBSCRIBE message
code - response code to send
text - response phrase to send
expires - expiration interval in seconds
contact - contact to add to reply
Returns:
the tmn.r_reply returned value value

Definition at line 422 of file registrar_notify.c.

References cscf_add_header_rpl(), M_NAME, STR_APPEND, and tmb.

Referenced by S_subscribe().

00423 {
00424     str hdr={0,0};
00425     tmb.t_newtran(msg);
00426     
00427     if (expires){
00428         hdr.len = expires_hdr1.len+12+expires_hdr1.len;
00429         hdr.s = pkg_malloc(hdr.len);
00430         if (!hdr.s){
00431             LOG(L_ERR,"ERR:"M_NAME":S_SUBSCRIBE_reply: Error allocating %d bytes.\n",
00432                 hdr.len);           
00433         }else{
00434             hdr.len=0;
00435             STR_APPEND(hdr,expires_hdr1);
00436             sprintf(hdr.s+hdr.len,"%d",*expires);
00437             hdr.len += strlen(hdr.s+hdr.len);
00438             STR_APPEND(hdr,expires_hdr2);
00439             cscf_add_header_rpl(msg,&hdr);      
00440             pkg_free(hdr.s);
00441         }
00442     }
00443 
00444     if (contact){
00445         hdr.len = contact_hdr1.len+contact->len+contact_hdr2.len;
00446         hdr.s = pkg_malloc(hdr.len);
00447         if (!hdr.s){
00448             LOG(L_ERR,"ERR:"M_NAME":S_SUBSCRIBE_reply: Error allocating %d bytes.\n",
00449                 hdr.len);           
00450         }else{
00451             hdr.len=0;
00452             STR_APPEND(hdr,contact_hdr1);
00453             STR_APPEND(hdr,*contact);
00454             STR_APPEND(hdr,contact_hdr2);
00455             cscf_add_header_rpl(msg,&hdr);      
00456             pkg_free(hdr.s);
00457         }
00458     }
00459     
00460     return tmb.t_reply(msg,code,text);
00461 }

static void r_create_notifications ( void *  pv,
void *  cv,
void *  ps,
str  content,
long  expires 
) [static]

Creates notifications with the given content for all of the subscribers.

Parameters:
pv - r_public* to which it refers
cv - the r_contact* to which it refers or NULL if for all
ps - the r_subscriber* to which it refers or NULL if for all
content - the body content
expires - the remaining subcription expiration time in seconds

Definition at line 477 of file registrar_notify.c.

References add_r_notification(), _r_public::aor, _r_subscriber::dialog, _r_subscriber::expires, M_NAME, new_r_notification(), _r_subscriber::next, _r_public::shead, STR_PKG_DUP, _r_subscriber::subscriber, time_now, and _r_subscriber::version.

Referenced by S_event_reg().

00478 {
00479     r_notification *n;
00480     r_public *p=(r_public*)pv;
00481 //  r_contact *c;
00482     r_subscriber *for_s=(r_subscriber*)ps;
00483     r_subscriber *s;    
00484     str uri={0,0},req_uri={0,0},subscription_state={"active;expires=10000000000",26},
00485         event={0,0},content_type={"application/reginfo+xml",23};
00486         
00487     uri = p->aor;
00488     if (!for_s) s = p->shead;
00489     else s = for_s;
00490     
00491     while(s){
00492         req_uri.len = s->subscriber.len+ruri_lr.len;
00493         req_uri.s = pkg_malloc(req_uri.len);
00494         if (!req_uri.s) {
00495             LOG(L_ERR,"ERR:"M_NAME":r_create_notifications: Error allocating %d bytes.\n",req_uri.len);
00496             return;         
00497         }
00498         memcpy(req_uri.s,s->subscriber.s,s->subscriber.len);
00499         memcpy(req_uri.s+s->subscriber.len,ruri_lr.s,ruri_lr.len);
00500         //route = s->path;
00501         if (s->expires>time_now) {
00502             subscription_state.s = pkg_malloc(32);
00503             subscription_state.len=0;
00504             if (subscription_state.s){
00505                 sprintf(subscription_state.s,"%.*s%ld",subs_active.len,subs_active.s,expires);
00506                 subscription_state.len=strlen(subscription_state.s);
00507             }                   
00508         }else {                 
00509             STR_PKG_DUP(subscription_state,subs_terminated,"pkg subs state");
00510         }
00511         n = new_r_notification(req_uri,uri,subscription_state,event,
00512             content_type,content,s->dialog,s->version++);                       
00513         if (req_uri.s) pkg_free(req_uri.s);
00514         if (subscription_state.s) pkg_free(subscription_state.s);   
00515         if (n) {
00516             #ifdef WITH_IMS_PM
00517                 n->is_scscf_dereg=(expires==0);
00518             #endif 
00519             add_r_notification(n);
00520         }       
00521         
00522         if (!for_s) s = s->next;                
00523         else s = 0;
00524     }
00525     return;
00526 out_of_memory:
00527     if (req_uri.s) pkg_free(req_uri.s);
00528     return; 
00529 }

static long r_update_subscription_status ( r_public p  )  [inline, static]

Look if there are no more public ids or contacts registered and expires the subscription.

Note:
must be called with lock on the domain
Parameters:
p - the r_public to update.
Returns:
the expiration is seconds

Definition at line 542 of file registrar_notify.c.

References _r_subscriber::expires, _r_contact::expires, _r_public::head, _r_subscriber::next, r_act_time(), r_valid_contact(), _r_public::shead, and time_now.

Referenced by r_get_reginfo_full(), and r_get_reginfo_partial().

00543 {
00544     r_subscriber *s;
00545     r_contact *c;
00546     long expires=0;
00547     int cnt=0;
00548     
00549     r_act_time();
00550     
00551     c = p->head;
00552     while(c){
00553         if (r_valid_contact(c)){
00554             if (c->expires-time_now+30>expires)
00555                 expires = c->expires-time_now+30;
00556             cnt++;
00557         }
00558         c = c->next;
00559     }       
00560     if (!cnt){
00561         s = p->shead;
00562         while(s){
00563             s->expires = time_now-1;
00564             s = s->next;
00565         }   
00566     }
00567     return expires;
00568 }

str r_get_reginfo_full ( void *  pv,
int  event_type,
long *  subsExpires 
)

Creates the full reginfo XML.

Parameters:
pv - the r_public to create for
event_type - event type
subsExpires - subscription expiration
Returns:
the str with the XML content

Definition at line 605 of file registrar_notify.c.

References ims_public_identity::barring, _r_contact::expires, get_aor_hash(), get_r_public(), get_r_public_nolock(), _r_public::hash, _r_contact::head, MAX_REGINFO_SIZE, _r_contact::next, ims_service_profile::public_identities, ims_service_profile::public_identities_cnt, ims_public_identity::public_identity, _r_contact::qvalue, r_hash_size, r_unlock(), r_update_subscription_status(), REGISTERED, _r_public::s, ims_subscription::service_profiles, ims_subscription::service_profiles_cnt, STR_APPEND, time_now, and _r_contact::uri.

Referenced by S_event_reg().

00606 {       
00607     str x={0,0};
00608     str buf,pad;    
00609     char bufc[MAX_REGINFO_SIZE],padc[MAX_REGINFO_SIZE];
00610 
00611     r_public *p=(r_public*)pv,*p2;
00612     r_contact *c;
00613     ims_public_identity *pi;
00614     int i,j;
00615     unsigned int hash;
00616     
00617     buf.s = bufc;
00618     buf.len=0;
00619     pad.s = padc;
00620     pad.len=0;
00621     
00622     *subsExpires = r_update_subscription_status(p);
00623     
00624     STR_APPEND(buf,xml_start);
00625     sprintf(pad.s,r_reginfo_s.s,"%d",r_full.len,r_full.s);
00626     pad.len = strlen(pad.s);
00627     STR_APPEND(buf,pad);
00628     
00629     
00630     if (p->s){
00631         for(i=0;i<p->s->service_profiles_cnt;i++)
00632             for(j=0;j<p->s->service_profiles[i].public_identities_cnt;j++){
00633                 pi = &(p->s->service_profiles[i].public_identities[j]);
00634                 if (!pi->barring){
00635                     hash = get_aor_hash(pi->public_identity,r_hash_size);
00636                     if (hash == p->hash) /* because we already have the lock on p->hash */
00637                         p2 = get_r_public_nolock(pi->public_identity);
00638                     else 
00639                         p2 = get_r_public(pi->public_identity);
00640                     if (p2){
00641                         if (p2->reg_state==REGISTERED)
00642                             sprintf(pad.s,registration_s.s,p2->aor.len,p2->aor.s,p2,r_active.len,r_active.s);
00643                         else 
00644                             sprintf(pad.s,registration_s.s,p2->aor.len,p2->aor.s,p2,r_terminated.len,r_terminated.s);
00645                         pad.len = strlen(pad.s);
00646                         STR_APPEND(buf,pad);
00647                         c = p2->head;
00648                         while(c){
00649                             if(c->qvalue != -1) {
00650                                 float q = (float)c->qvalue/1000;
00651                                 sprintf(pad.s,contact_s_q.s,c,r_active.len,r_active.s,r_registered.len,r_registered.s,c->expires-time_now, q);
00652                             }
00653                             else
00654                                 sprintf(pad.s,contact_s.s,c,r_active.len,r_active.s,r_registered.len,r_registered.s,c->expires-time_now);
00655                             pad.len = strlen(pad.s);
00656                             STR_APPEND(buf,pad);                            
00657                             STR_APPEND(buf,uri_s);
00658                             STR_APPEND(buf,c->uri);
00659                             STR_APPEND(buf,uri_e);
00660                             STR_APPEND(buf,contact_e);
00661                             c = c->next;
00662                         }
00663                         STR_APPEND(buf,registration_e);
00664                         if (p2->hash != p->hash) r_unlock(p2->hash);
00665                     }
00666                 }
00667             }               
00668     }
00669 
00670     STR_APPEND(buf,r_reginfo_e);
00671 
00672     
00673     x.s = pkg_malloc(buf.len+1);
00674     if (x.s){
00675         x.len = buf.len;
00676         memcpy(x.s,buf.s,buf.len);
00677         x.s[x.len]=0;
00678     }
00679     return x;
00680 }

str r_get_reginfo_partial ( void *  pv,
void *  pc,
int  event_type,
long *  subsExpires 
)

Creates the partial reginfo XML.

Parameters:
pv - the r_public to create for
pc - the r_contatct to create for
event_type - event type
subsExpires - subscription expiration
Returns:
the str with the XML content

Definition at line 691 of file registrar_notify.c.

References _r_public::aor, contact_e, contact_s, contact_s_q, _r_contact::expires, _r_public::head, IMS_REGISTRAR_CONTACT_CREATED, IMS_REGISTRAR_CONTACT_DEACTIVATED, IMS_REGISTRAR_CONTACT_EXPIRED, IMS_REGISTRAR_CONTACT_PROBATION, IMS_REGISTRAR_CONTACT_REFRESHED, IMS_REGISTRAR_CONTACT_REGISTERED, IMS_REGISTRAR_CONTACT_REJECTED, IMS_REGISTRAR_CONTACT_SHORTENED, IMS_REGISTRAR_CONTACT_UNREGISTERED, MAX_REGINFO_SIZE, _r_contact::qvalue, r_active, r_created, r_deactivated, r_expired, r_partial, r_probation, r_refreshed, r_reginfo_e, r_reginfo_s, r_registered, r_rejected, r_shortened, r_terminated, r_unregistered, r_update_subscription_status(), registration_e, registration_s, STR_APPEND, _r_public::tail, time_now, _r_contact::uri, uri_e, uri_s, and xml_start.

Referenced by S_event_reg().

00692 {       
00693     str x={0,0};
00694     str buf,pad;    
00695     char bufc[MAX_REGINFO_SIZE],padc[MAX_REGINFO_SIZE];
00696     int expires=-1;
00697 
00698     r_public *p=(r_public*)pv;
00699     r_contact *c=(r_contact*)pc;
00700     str state,event;
00701     
00702     buf.s = bufc;
00703     buf.len=0;
00704     pad.s = padc;
00705     pad.len=0;
00706 
00707     *subsExpires = r_update_subscription_status(p);
00708     
00709     STR_APPEND(buf,xml_start);
00710     sprintf(pad.s,r_reginfo_s.s,"%d",r_partial.len,r_partial.s);
00711     pad.len = strlen(pad.s);
00712     STR_APPEND(buf,pad);
00713     
00714     
00715     if (p){
00716         expires = c->expires-time_now;
00717         if (p->head == c && p->tail == c && 
00718             (event_type==IMS_REGISTRAR_CONTACT_EXPIRED ||
00719              event_type==IMS_REGISTRAR_CONTACT_DEACTIVATED||
00720              event_type==IMS_REGISTRAR_CONTACT_UNREGISTERED||
00721              event_type==IMS_REGISTRAR_CONTACT_REJECTED)
00722            )
00723             sprintf(pad.s,registration_s.s,p->aor.len,p->aor.s,p,r_terminated.len,r_terminated.s);
00724         else 
00725             sprintf(pad.s,registration_s.s,p->aor.len,p->aor.s,p,r_active.len,r_active.s);
00726         pad.len = strlen(pad.s);
00727         STR_APPEND(buf,pad);
00728         if (c){
00729             switch(event_type){
00730                 case IMS_REGISTRAR_CONTACT_REGISTERED:
00731                     state = r_active;
00732                     event = r_registered;
00733                     break;
00734                 case IMS_REGISTRAR_CONTACT_CREATED:
00735                     state = r_active;
00736                     event = r_created;
00737                     break;
00738                 case IMS_REGISTRAR_CONTACT_REFRESHED:
00739                     state = r_active;
00740                     event = r_refreshed;
00741                     break;
00742                 case IMS_REGISTRAR_CONTACT_SHORTENED:
00743                     state =