00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00055 #include "registrar_notify.h"
00056
00057 #include "registrar_storage.h"
00058 #include "mod.h"
00059 #include "../../mem/mem.h"
00060 #include "../../mem/shm_mem.h"
00061 #include "../../parser/parse_uri.h"
00062 #include "../../locking.h"
00063 #include "../tm/tm_load.h"
00064 #include "sip.h"
00065 #include "ims_pm.h"
00066
00067 extern struct tm_binds tmb;
00069 extern str scscf_name_str;
00071 extern int subscription_default_expires;
00072 extern int subscription_min_expires;
00073 extern int subscription_max_expires;
00075 extern time_t time_now;
00077 extern int r_hash_size;
00078 extern r_hash_slot *registrar;
00080 r_notification_list *notification_list=0;
00085 int r_notify_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 }
00095
00099 void r_notify_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 }
00113
00114
00115 static str lookup_sip={"sip:",4};
00128 int S_can_subscribe(struct sip_msg *msg,char *str1,char *str2)
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
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
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
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
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
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 }
00258
00259
00267 int S_subscribe(struct sip_msg *msg,char *str1,char *str2)
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
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
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
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
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
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
00362 s = get_r_subscriber(p,subscriber,event_i);
00363 if (!s){
00364
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
00374 if ((new_s=update_r_subscriber(p,subscriber,event_i,&expires_time,dialog))!=0){
00375
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
00383
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 }
00405
00406
00407
00408 str expires_hdr1={"Expires: ",9};
00409 str expires_hdr2={"\r\n",2};
00410 str contact_hdr1={"Contact: <",10};
00411 str contact_hdr2={">\r\n",3};
00422 int S_SUBSCRIBE_reply(struct sip_msg *msg, int code, char *text,int *expires,str *contact)
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 }
00462
00463
00464
00465
00466 static str ruri_lr={";lr",3};
00467 static str subs_terminated={"terminated",10};
00468 static str subs_active={"active;expires=",15};
00477 static void r_create_notifications(void *pv,void *cv,void *ps,str content,long expires)
00478 {
00479 r_notification *n;
00480 r_public *p=(r_public*)pv;
00481
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
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 }
00530
00532 #define MAX_REGINFO_SIZE 16384
00533
00534
00535
00542 static inline long r_update_subscription_status(r_public *p)
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 }
00569
00570 static str xml_start={"<?xml version=\"1.0\"?>\n",22};
00571
00572 static str r_full={"full",4};
00573 static str r_partial={"partial",7};
00574 static str r_reginfo_s={"<reginfo xmlns=\"urn:ietf:params:xml:ns:reginfo\" version=\"%s\" state=\"%.*s\">\n",74};
00575 static str r_reginfo_e={"</reginfo>\n",11};
00576
00577
00578 static str r_active={"active",6};
00579 static str r_terminated={"terminated",10};
00580 static str registration_s={"\t<registration aor=\"%.*s\" id=\"%p\" state=\"%.*s\">\n",48};
00581 static str registration_e={"\t</registration>\n",17};
00582
00583 static str r_registered={"registered",10};
00584 static str r_created={"created",7};
00585 static str r_refreshed={"refreshed",9};
00586 static str r_shortened={"shortened",9};
00587 static str r_expired={"expired",7};
00588 static str r_deactivated={"deactivated",11};
00589 static str r_probation={"probation",9};
00590 static str r_unregistered={"unregistered",12};
00591 static str r_rejected={"rejected",8};
00592 static str contact_s={"\t\t<contact id=\"%p\" state=\"%.*s\" event=\"%.*s\" expires=\"%d\">\n",59};
00593 static str contact_s_q={"\t\t<contact id=\"%p\" state=\"%.*s\" event=\"%.*s\" expires=\"%d\" q=\"%.3f\">\n",69};
00594 static str contact_e={"\t\t</contact>\n",13};
00595
00596 static str uri_s={"\t\t\t<uri>",8};
00597 static str uri_e={"</uri>\n",7};
00605 str r_get_reginfo_full(void *pv,int event_type,long *subsExpires)
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)
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 }
00681
00682
00691 str r_get_reginfo_partial( void *pv,void *pc,int event_type,long *subsExpires)
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 = r_active;
00744 event = r_shortened;
00745 break;
00746 case IMS_REGISTRAR_CONTACT_EXPIRED:
00747 state = r_terminated;
00748 event = r_expired;
00749 expires = 0;
00750 break;
00751 case IMS_REGISTRAR_CONTACT_DEACTIVATED:
00752 state = r_terminated;
00753 event = r_deactivated;
00754 break;
00755 case IMS_REGISTRAR_CONTACT_PROBATION:
00756 state = r_terminated;
00757 event = r_probation;
00758 break;
00759 case IMS_REGISTRAR_CONTACT_UNREGISTERED:
00760 state = r_terminated;
00761 event = r_unregistered;
00762 expires = 0;
00763 break;
00764 case IMS_REGISTRAR_CONTACT_REJECTED:
00765 state = r_terminated;
00766 event = r_rejected;
00767 break;
00768 default:
00769 state = r_active;
00770 event = r_registered;
00771 }
00772 if(c->qvalue != -1) {
00773 float q = (float)c->qvalue/1000;
00774 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);
00775 }
00776 else
00777 sprintf(pad.s,contact_s.s,c,state.len,state.s,event.len,event.s,expires);
00778 pad.len = strlen(pad.s);
00779 STR_APPEND(buf,pad);
00780 STR_APPEND(buf,uri_s);
00781 STR_APPEND(buf,c->uri);
00782 STR_APPEND(buf,uri_e);
00783 STR_APPEND(buf,contact_e);
00784 STR_APPEND(buf,registration_e);
00785 }
00786 }
00787
00788 STR_APPEND(buf,r_reginfo_e);
00789
00790
00791 x.s = pkg_malloc(buf.len+1);
00792 if (x.s){
00793 x.len = buf.len;
00794 memcpy(x.s,buf.s,buf.len);
00795 x.s[x.len]=0;
00796 }
00797 return x;
00798 }
00799
00810 int S_event_reg(void *pv,void *c,void *ps,int event_type,int send_now)
00811 {
00812 r_public *p=(r_public*)pv;
00813 r_subscriber *s=(r_subscriber*)ps;
00814 str content={0,0};
00815 long subsExpires=-1;
00816
00817 r_act_time();
00818 switch (event_type){
00819 case IMS_REGISTRAR_NONE:
00820 if (send_now) notification_timer(0,0);
00821 return 0;
00822 break;
00823 case IMS_REGISTRAR_SUBSCRIBE:
00824 content = r_get_reginfo_full(p,event_type,&subsExpires);
00825 r_create_notifications(p,0,s,content,subsExpires);
00826 if (content.s) pkg_free(content.s);
00827 if (send_now) notification_timer(0,0);
00828 return 1;
00829 break;
00830 case IMS_REGISTRAR_UNSUBSCRIBE:
00831 subsExpires=0;
00832 r_create_notifications(p,0,s,content,subsExpires);
00833 if (content.s) pkg_free(content.s);
00834 if (send_now) notification_timer(0,0);
00835 return 1;
00836 break;
00837
00838 case IMS_REGISTRAR_CONTACT_REGISTERED:
00839 case IMS_REGISTRAR_CONTACT_CREATED:
00840 case IMS_REGISTRAR_CONTACT_REFRESHED:
00841 case IMS_REGISTRAR_CONTACT_SHORTENED:
00842 case IMS_REGISTRAR_CONTACT_EXPIRED:
00843 case IMS_REGISTRAR_CONTACT_DEACTIVATED:
00844 case IMS_REGISTRAR_CONTACT_PROBATION:
00845 case IMS_REGISTRAR_CONTACT_UNREGISTERED:
00846 case IMS_REGISTRAR_CONTACT_REJECTED:
00847 content = r_get_reginfo_partial(p,c,event_type,&subsExpires);
00848 r_create_notifications(p,c,s,content,subsExpires);
00849 if (content.s) pkg_free(content.s);
00850 if (send_now) notification_timer(0,0);
00851 return 1;
00852 break;
00853
00854 default:
00855 LOG(L_ERR,"ERR:"M_NAME":S_event_reg: Unknown event %d\n",event_type);
00856 if (send_now) notification_timer(0,0);
00857 return 0;
00858 }
00859 }
00860
00861
00862 static str method={"NOTIFY",6};
00863 static str event_hdr ={"Event: reg\r\n",12};
00864 static str maxfwds_hdr ={"Max-Forwards: 70\r\n",18};
00865 static str subss_hdr1={"Subscription-State: ",20};
00866 static str subss_hdr2={"\r\n",2};
00867 static str ctype_hdr1={"Content-Type: ",14};
00868 static str ctype_hdr2={"\r\n",2};
00869
00870 #ifdef WITH_IMS_PM
00871 static str zero={0,0};
00872 #endif
00873
00876 void uac_request_cb(struct cell *t,int type,struct tmcb_params *ps)
00877 {
00878 LOG(L_DBG,"DBG:"M_NAME":uac_request_cb: Type %d\n",type);
00879 #ifdef WITH_IMS_PM
00880 if (((int) *ps->param) && (ps->rpl != (void*)-1) ){
00881 if (ps->code>=200 && ps->code<300) IMS_PM_LOG12(UR_SuccDeRegCscf,cscf_get_call_id(ps->rpl,0),cscf_get_cseq(ps->rpl,0),ps->code);
00882 else if (ps->code>=300) IMS_PM_LOG12(UR_FailDeRegCscf,cscf_get_call_id(ps->rpl,0),cscf_get_cseq(ps->rpl,0),ps->code);
00883 }
00884 #endif
00885 }
00886
00891 void send_notification(r_notification *n)
00892 {
00893 str h={0,0};
00894 int k=0;
00895
00896 LOG(L_DBG,"DBG:"M_NAME":send_notification: NOTIFY about <%.*s>\n",n->uri.len,n->uri.s);
00897
00898
00899
00900 h.len = 0;
00901 h.len += contact_hdr1.len + n->uri.len + contact_hdr2.len ;
00902 if (n->subscription_state.len) h.len += subss_hdr1.len + subss_hdr2.len + n->subscription_state.len;
00903 h.len+=event_hdr.len;
00904 h.len+=maxfwds_hdr.len;
00905 if (n->content_type.len) h.len += ctype_hdr1.len + ctype_hdr2.len + n->content_type.len;
00906 h.s = pkg_malloc(h.len);
00907 if (!h.s){
00908 LOG(L_ERR,"ERR:"M_NAME":send_notification: Error allocating %d bytes\n",h.len);
00909 h.len = 0;
00910 }
00911
00912 h.len = 0;
00913 STR_APPEND(h,contact_hdr1);
00914 STR_APPEND(h,n->uri);
00915 STR_APPEND(h,contact_hdr2);
00916
00917 STR_APPEND(h,event_hdr);
00918 STR_APPEND(h,maxfwds_hdr);
00919 if (n->subscription_state.len) {
00920 STR_APPEND(h,subss_hdr1);
00921 STR_APPEND(h,n->subscription_state);
00922 STR_APPEND(h,subss_hdr2);
00923 }
00924 if (n->content_type.len) {
00925 STR_APPEND(h,ctype_hdr1);
00926 STR_APPEND(h,n->content_type);
00927 STR_APPEND(h,ctype_hdr2);
00928 }
00929
00930
00931 #ifdef WITH_IMS_PM
00932 k = n->is_scscf_dereg;
00933 #endif
00934 if (n->content.len)
00935 tmb.t_request_within(&method, &h, &(n->content), n->dialog, uac_request_cb, (void*)k);
00936 else
00937 tmb.t_request_within(&method, &h, 0, n->dialog, uac_request_cb, (void*)k);
00938 if (h.s) pkg_free(h.s);
00939
00940 #ifdef WITH_IMS_PM
00941 if (n->is_scscf_dereg) IMS_PM_LOG11(UR_AttDeRegCscf,n->dialog->id.call_id,n->dialog->loc_seq.value);
00942 #endif
00943 }
00944
00945
00946
00947
00954 void notification_timer(unsigned int ticks, void* param)
00955 {
00956 r_notification *n;
00957 lock_get(notification_list->lock);
00958 while(notification_list->head){
00959 n = notification_list->head;
00960 notification_list->head = n->next;
00961 if (n->next) n->next->prev=0;
00962 else notification_list->tail=n->next;
00963 lock_release(notification_list->lock);
00964
00965 send_notification(n);
00966 free_r_notification(n);
00967 lock_get(notification_list->lock);
00968 }
00969 lock_release(notification_list->lock);
00970 }
00971
00972
00973
00985 r_notification* new_r_notification(str req_uri,str uri,str subscription_state,str event,
00986 str content_type,str content,dlg_t *dialog,int version)
00987 {
00988 r_notification *n=0;
00989 str buf;
00990 char bufc[MAX_REGINFO_SIZE];
00991
00992 n = shm_malloc(sizeof(r_notification));
00993 if (!n){
00994 LOG(L_ERR,"ERR:"M_NAME":new_r_notification: Error allocating %d bytes\n",
00995 sizeof(r_notification));
00996 goto error;
00997 }
00998 memset(n,0,sizeof(r_notification));
00999
01000 STR_SHM_DUP(n->req_uri,req_uri,"new_r_notification");
01001
01002 STR_SHM_DUP(n->uri,uri,"new_r_notification");
01003
01004 STR_SHM_DUP(n->subscription_state,subscription_state,"new_r_notification");
01005
01006 STR_SHM_DUP(n->event,event,"new_r_notification");
01007
01008 STR_SHM_DUP(n->content_type,content_type,"new_r_notification");
01009
01010 sprintf(bufc,content.s,version);
01011 buf.s = bufc;
01012 buf.len = strlen(bufc);
01013 STR_SHM_DUP(n->content,buf,"new_r_notification");
01014
01015 n->dialog = dialog;
01016
01017