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
00056 #include "registrar_subscribe.h"
00057
00058 #include <libxml/xmlschemas.h>
00059 #include <libxml/parser.h>
00060
00061
00062 #include "registrar_storage.h"
00063 #include "mod.h"
00064 #include "../../mem/mem.h"
00065 #include "../../mem/shm_mem.h"
00066 #include "../../parser/parse_uri.h"
00067 #include "../../locking.h"
00068 #include "../tm/tm_load.h"
00069 #include "../dialog/dlg_mod.h"
00070 #include "sip.h"
00071 #include "ims_pm.h"
00072
00073 extern struct tm_binds tmb;
00074 extern dlg_func_t dialogb;
00076 extern str pcscf_name_str;
00077 extern str pcscf_path_str;
00079 extern time_t time_now;
00081 extern r_hash_slot *registrar;
00082 extern int r_hash_size;
00084 extern int pcscf_subscribe_retries;
00086 r_subscription_hash_slot *subscriptions=0;
00087 extern int subscriptions_hash_size;
00098 inline unsigned int get_subscription_hash(str uri)
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 }
00119
00124 inline void subs_lock(unsigned int hash)
00125 {
00126
00127 lock_get(subscriptions[hash].lock);
00128
00129 }
00134 inline void subs_unlock(unsigned int hash)
00135 {
00136
00137 lock_release(subscriptions[hash].lock);
00138 }
00143 int r_subscription_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 }
00156
00160 void r_subscription_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
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 }
00178
00179
00187 int P_subscribe(struct sip_msg *rpl, char* str1, char* str2)
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
00228
00229
00230 r_subscribe(public_id,max_expires+30);
00231 return CSCF_RETURN_TRUE;
00232 }else{
00233 return CSCF_RETURN_FALSE;
00234 }
00235 }
00236
00243 int r_subscribe(str uri,int duration)
00244 {
00245 r_subscription *s;
00246
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 }
00264
00265
00266 static str method={"SUBSCRIBE",9};
00267 static str event_hdr={"Event: reg\r\n",12};
00268 static str accept_hdr={"Accept: application/reginfo+xml\r\n",33};
00269 static str content_len_hdr={"Content-Length: 0\r\n",19};
00270 static str max_fwds_hdr={"Max-Forwards: 10\r\n",18};
00271 static str expires_s={"Expires: ",9};
00272 static str expires_e={"\r\n",2};
00273 static str contact_s={"Contact: <",10};
00274 static str contact_e={">\r\n",3};
00275 static str p_asserted_identity_s={"P-Asserted-Identity: <",22};
00276 static str p_asserted_identity_e={">\r\n",3};
00284 int r_send_subscribe(r_subscription *s,int duration)
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
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
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 }
00351
00355 void r_subscribe_response(struct cell *t,int type,struct tmcb_params *ps)
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
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 }
00388
00389
00390 #ifdef WITH_IMS_PM
00391 static str zero={0,0};
00392 #endif
00393
00399 void subscription_timer(unsigned int ticks, void* param)
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
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
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
00430
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
00438
00439
00440
00441
00442
00443
00444
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 }
00456
00457
00458
00459
00460
00469 r_subscription* new_r_subscription(str req_uri,int duration)
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 }
00494
00499 void add_r_subscription(r_subscription *s)
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 }
00511
00519 int update_r_subscription(r_subscription *s,int expires)
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 }
00529
00536 r_subscription* get_r_subscription(str aor)
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 }
00553
00559 int is_r_subscription(str aor)
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 }
00577
00582 void del_r_subscription(r_subscription *s)
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 }
00593
00599 void del_r_subscription_nolock(r_subscription *s)
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 }
00608
00613 void free_r_subscription(r_subscription *s)
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 }
00621
00622 void print_subs(int log_level)
00623 {
00624 r_subscription *s;
00625 int i;
00626 if (debug<log_level) return;
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;
00636 }
00637 subs_unlock(i);
00638 }
00639 LOG(log_level,ANSI_GREEN"INF:"M_NAME":---------- Subscription list end -----------\n");
00640 }
00641
00642
00643
00644
00645
00646
00647
00648
00649 char *pcscf_reginfo_dtd;
00651 static xmlDtdPtr dtd=0;
00652 static xmlValidCtxt cvp;
00659 int parser_init(char *dtd_filename)
00660 {
00661 dtd = xmlParseDTD(NULL,(unsigned char*)dtd_filename);
00662 if (!dtd){
00663 LOG(L_ERR,"ERR:"M_NAME":parser_init: unsuccesful DTD parsing from file <%s>\n",
00664 dtd_filename);
00665 return 0;
00666 }
00667 cvp.userData = (void*)stderr;
00668 cvp.error = (xmlValidityErrorFunc) fprintf;
00669 cvp.warning = (xmlValidityWarningFunc) fprintf;
00670 return 1;
00671 }
00672
00676 void parser_destroy()
00677 {
00678 xmlCleanupParser();
00679 }
00680
00681
00682
00688 static inline void space_trim_dup(str *dest, char *src)
00689 {
00690 int i;
00691 dest->s=0;
00692 dest->len=0;
00693 if (!src) return;
00694 dest->len = strlen(src);
00695 i = dest->len-1;
00696 while((src[i]==' '||src[i]=='\t') && i>0)
00697 i--;
00698 i=0;
00699 while((src[i]==' '||src[i]=='\t') && i<dest->len)
00700 i++;
00701 dest->len -= i;
00702 dest->s = pkg_malloc(dest->len);
00703 if (!dest->s) {
00704 LOG(L_ERR,"ERR:"M_NAME":space_trim_dup: Out of memory allocating %d bytes\n",dest->len);
00705 dest->len=0;
00706 return;
00707 }
00708 memcpy(dest->s,src+i,dest->len);
00709 }
00710
00716 r_notification* r_notification_parse(str xml)
00717 {
00718 r_notification *n;
00719 r_registration *r;
00720 r_regcontact *rc;
00721 xmlDocPtr doc=0;
00722 xmlNodePtr root=0,child=0,nephew=0,node=0;
00723 xmlChar *reginfo_state=0,*x;
00724 char c=0;
00725
00726 n = pkg_malloc(sizeof(r_notification));
00727 if (!n) {
00728 LOG(L_ERR,"ERR:"M_NAME":r_notification_parse: Error allocating %d bytes\n",
00729 sizeof(r_notification));
00730 goto error;
00731 }
00732 memset(n,0,sizeof(r_notification));
00733
00734 if (!dtd) parser_init(pcscf_reginfo_dtd);
00735 doc=0;
00736 c = xml.s[xml.len];
00737 xml.s[xml.len]=0;
00738 doc = xmlParseDoc((unsigned char *)xml.s);
00739 if (!doc){
00740 LOG(L_ERR,"ERR:"M_NAME":r_notification_parse: This is not a valid XML <%.*s>\n",
00741 xml.len,xml.s);
00742 goto error;
00743 }
00744 if (xmlValidateDtd(&cvp,doc,dtd)!=1){
00745 LOG(L_ERR,"ERR:"M_NAME":r_notification_parse: Verification of XML against DTD failed <%.*s>\n",
00746 xml.len,xml.s);
00747 goto error;
00748 }
00749 root = xmlDocGetRootElement(doc);
00750 if (!root){
00751 LOG(L_ERR,"ERR:"M_NAME":r_notification_parse: Empty XML <%.*s>\n",
00752 xml.len,xml.s);
00753 goto error;
00754 }
00755
00756 reginfo_state = xmlGetProp(root,(xmlChar*)"state");
00757 LOG(L_DBG,"DBG:"M_NAME":r_notification_parse: reginfo_state <%s>\n",
00758 reginfo_state);
00759 if (reginfo_state[0]=='f'||reginfo_state[0]=='F')
00760 n->state = IMS_REGINFO_FULL;
00761 else
00762 n->state = IMS_REGINFO_PARTIAL;
00763
00764 for(child = root->children; child; child = child->next)
00765 if (child->type == XML_ELEMENT_NODE)
00766 {
00767 r = pkg_malloc(sizeof(r_registration));
00768 if (!r){
00769 LOG(L_ERR,"ERR:"M_NAME":r_notification_parse: Error allocating %d bytes\n",
00770 sizeof(r_registration));
00771 goto error;
00772 }
00773 memset(r,0,sizeof(r_registration));
00774
00775 x = xmlGetProp(child,(xmlChar*)"id");
00776 space_trim_dup(&(r->id),(char*)x);
00777 xmlFree(x);
00778
00779 x = xmlGetProp(child,(xmlChar*)"aor");
00780 space_trim_dup(&(r->aor),(char*)x);
00781 xmlFree(x);
00782
00783 x = xmlGetProp(child,(xmlChar*)"state");
00784
00785 if (x[0]=='a'||x[0]=='A')
00786 r->state = IMS_REGINFO_ACTIVE;
00787 else
00788 r->state = IMS_REGINFO_TERMINATED;
00789 xmlFree(x);
00790
00791 for(nephew = child->children; nephew; nephew = nephew->next)
00792 if (nephew->type == XML_ELEMENT_NODE)
00793 {
00794 rc = pkg_malloc(sizeof(r_regcontact));
00795 if (!rc){
00796 LOG(L_ERR,"ERR:"M_NAME":r_notification_parse: Error allocating %d bytes\n",
00797 sizeof(r_regcontact));
00798 goto error;
00799 }
00800 memset(rc,0,sizeof(r_regcontact));
00801
00802 x = xmlGetProp(nephew,(xmlChar*)"id");
00803 space_trim_dup(&(rc->id),(char*)x);
00804 xmlFree(x);
00805
00806 x = xmlGetProp(nephew,(xmlChar*)"state");
00807 if (x[0]=='a'||x[0]=='A')
00808 rc->state = IMS_REGINFO_ACTIVE;
00809 else
00810 rc->state = IMS_REGINFO_TERMINATED;
00811 xmlFree(x);
00812
00813 x = xmlGetProp(nephew,(xmlChar*)"event");
00814 switch(x[0]){
00815 case 'r':case 'R':
00816 switch (x[2]){
00817 case 'g': case 'G':
00818 rc->event = IMS_REGINFO_CONTACT_REGISTERED;
00819 break;
00820 case 'f': case 'F':
00821 rc->event = IMS_REGINFO_CONTACT_REFRESHED;
00822 break;
00823 case 'j': case 'J':
00824 rc->event = IMS_REGINFO_CONTACT_REJECTED;
00825 break;
00826 default:
00827 rc->event = IMS_REGINFO_NONE;
00828 }
00829 break;
00830 case 'c':case 'C':
00831 rc->event = IMS_REGINFO_CONTACT_CREATED;
00832 break;
00833 case 's':case 'S':
00834 rc->event = IMS_REGINFO_CONTACT_SHORTENED;
00835 break;
00836 case 'e':case 'E':
00837 rc->event = IMS_REGINFO_CONTACT_EXPIRED;
00838 break;
00839 case 'd':case 'D':
00840 rc->event = IMS_REGINFO_CONTACT_DEACTIVATED;
00841 break;
00842 case 'p':case 'P':
00843 rc->event = IMS_REGINFO_CONTACT_PROBATION;
00844 break;
00845 case 'u':case 'U':
00846 rc->event = IMS_REGINFO_CONTACT_UNREGISTERED;
00847 break;
00848 default:
00849 rc->event = IMS_REGINFO_NONE;
00850 }
00851 xmlFree(x);
00852
00853 x = xmlGetProp(nephew,(xmlChar*)"expires");
00854 if (x) {
00855 rc->expires = atoi((char*)x);
00856 xmlFree(x);
00857 }
00858
00859 node = nephew->children;
00860 while(node && node->type!=XML_ELEMENT_NODE)
00861 node =node->next;
00862 if (node) {
00863 x = xmlNodeGetContent(node);
00864 space_trim_dup(&(rc->uri),(char*)x);
00865 xmlFree(x);
00866 }
00867
00868 rc->next = r->contact;
00869 r->contact = rc;
00870 }
00871
00872 r->next = n->registration;
00873 n->registration = r;
00874
00875 }
00876
00877 if (reginfo_state) xmlFree(reginfo_state);
00878
00879 if (doc) xmlFreeDoc(doc);
00880 xml.s[xml.len]=c;
00881 return n;
00882 error:
00883 if (reginfo_state) xmlFree(reginfo_state);
00884
00885 if (doc) xmlFreeDoc(doc);
00886 xml.s[xml.len]=c;
00887 if (n) r_notification_free(n);
00888 return 0;
00889 }
00890
00891
00892
00899 int r_notification_process(r_notification *n,int expires)
00900 {
00901 r_registration *r;
00902 r_regcontact *rc;
00903 r_contact *c;
00904 struct sip_uri puri;
00905 enum Reg_States reg_state;
00906 int expires2;
00907 r_subscription *s=0;
00908
00909 r_notification_print(n);
00910 if (!n) return 0;
00911
00912 r_act_time();
00913 r = n->registration;
00914 while(r){
00915
00916 rc = r->contact;
00917 while(rc){
00918 if (parse_uri(rc->uri.s,rc->uri.len,&puri)<0){
00919 LOG(L_ERR,"ERR:"M_NAME":r_notification_process: Error parsing Contact URI <%.*s>\n",
00920 rc->uri.len,rc->uri.s);
00921 goto next;
00922 }
00923
00924 if (rc->state==IMS_REGINFO_TERMINATED){
00925 reg_state = DEREGISTERED;
00926 expires2 = time_now+30;
00927 c = update_r_contact(puri.host,puri.port_no,puri.proto,
00928 0,®_state,&expires2,0,0,0);
00929 if (c) {
00930 LOG(L_DBG,"DBG:"M_NAME":r_notification_process: expired contact <%.*s>\n",
00931 c->uri.len,c->uri.s);
00932 r_unlock(c->hash);
00933 }
00934 }else{
00935 reg_state = REGISTERED;
00936 expires2 = rc->expires+time_now;
00937 c = update_r_contact(puri.host,puri.port_no,puri.proto,
00938 0,®_state,&expires2,0,0,0);
00939 if (c) {
00940 LOG(L_DBG,"DBG:"M_NAME":r_notification_process: refreshing contact <%.*s> [%d]\n",
00941 c->uri.len,c->uri.s,rc->expires);
00942 r_unlock(c->hash);
00943 }
00944
00945 }
00946 next:
00947 rc = rc->next;
00948 }
00949 s = get_r_subscription(r->aor);
00950 if (s){
00951 update_r_subscription(s,expires);
00952 subs_unlock(s->hash);
00953 }
00954 r = r->next;
00955 }
00956
00957 return 1;
00958 }
00959
00964 void r_notification_print(r_notification *n)
00965 {
00966 r_registration *r;
00967 r_regcontact *c;
00968
00969 if (!n) return;
00970 LOG(L_DBG,"DBG:"M_NAME":r_notification_print: State %d\n",n->state);
00971 r = n->registration;
00972 while(r){
00973 LOG(L_DBG,"DBG:"M_NAME":r_notification_print: \tR [%d] ID<%.*s> AOR<%.*s>\n",r->state,
00974 r->id.len,r->id.s,r->aor.len,r->aor.s);
00975 c = r->contact;
00976 while(c){
00977 LOG(L_DBG,"DBG:"M_NAME":r_notification_print: \t\tC [%d]>[%d] ID<%.*s> URI<%.*s>\n",c->state,
00978 c->event,c->id.len,c->id.s,c->uri.len,c->uri.s);
00979 c = c->next;
00980 }
00981 r = r->next;
00982 }
00983 }
00984
00989 void r_notification_free(r_notification *n)
00990 {
00991 r_registration *r,*nr;
00992 r_regcontact *c,*nc;
00993 r = n->registration;
00994 while(r){
00995 nr = r->next;
00996 if (r->id.s) pkg_free(r->id.s);
00997 if (r->aor.s) pkg_free(r->aor.s);
00998 c = r->contact;
00999 while(c){
01000 nc = c->next;
01001 if (c->id.s) pkg_free(c->id.s);
01002 if (c->uri.s) pkg_free(c->uri.s);
01003 pkg_free(c);
01004 c = c->next;
01005 }
01006 pkg_free(r);
01007 r = nr;
01008 }
01009 if (n) pkg_free(n);
01010 }
01011
01012
01013
01014
01015
01016