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_notification * | new_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_slot * | registrar |
| The S-CSCF registrar. | |
| r_notification_list * | notification_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 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().
| 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:
| msg | - the SIP SUBSCRIBE message | |
| str1 | - not used | |
| str2 | - not used |
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.
| msg | - the SIP SUBSCRIBE message | |
| str1 | - not used | |
| str2 | - not used |
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.
| 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 |
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.
| 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.
| p | - the r_public to update. |
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.
| pv | - the r_public to create for | |
| event_type | - event type | |
| subsExpires | - subscription expiration |
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.
| pv | - the r_public to create for | |
| pc | - the r_contatct to create for | |
| event_type | - event type | |
| subsExpires | - subscription expiration |
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 =