2 * presence module - presence server implementation
4 * Copyright (C) 2007 Voice Sistem S.R.L.
6 * This file is part of Kamailio, a free SIP server.
8 * Kamailio is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version
13 * Kamailio is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
25 * \brief Kamailio presence module
32 #include "../../core/mem/shm_mem.h"
33 #include "../../core/hashes.h"
34 #include "../../core/dprint.h"
35 #include "../../core/str.h"
36 #include "../pua/hash.h"
41 /* matching mode when removing subscriptions from memory */
42 extern int pres_subs_remove_match;
45 * create the subscription hash table in shared memory
46 * - hash_size: number of slots
48 shtable_t new_shtable(int hash_size)
50 shtable_t htable = NULL;
54 htable = (subs_entry_t *)shm_malloc(hash_size * sizeof(subs_entry_t));
58 memset(htable, 0, hash_size * sizeof(subs_entry_t));
59 for(i = 0; i < hash_size; i++) {
60 if(lock_init(&htable[i].lock) == 0) {
61 LM_ERR("initializing lock [%d]\n", i);
64 htable[i].entries = (subs_t *)shm_malloc(sizeof(subs_t));
65 if(htable[i].entries == NULL) {
66 lock_destroy(&htable[i].lock);
69 memset(htable[i].entries, 0, sizeof(subs_t));
70 htable[i].entries->next = NULL;
77 for(j = 0; j < i; j++) {
78 lock_destroy(&htable[j].lock);
79 shm_free(htable[j].entries);
86 void destroy_shtable(shtable_t htable, int hash_size)
93 for(i = 0; i < hash_size; i++) {
94 lock_destroy(&htable[i].lock);
95 free_subs_list(htable[i].entries->next, SHM_MEM_TYPE, 1);
96 shm_free(htable[i].entries);
97 htable[i].entries = NULL;
103 subs_t *search_shtable(shtable_t htable, str callid, str to_tag, str from_tag,
104 unsigned int hash_code)
108 s = htable[hash_code].entries ? htable[hash_code].entries->next : NULL;
111 if(s->callid.len == callid.len
112 && strncmp(s->callid.s, callid.s, callid.len) == 0
113 && s->to_tag.len == to_tag.len
114 && strncmp(s->to_tag.s, to_tag.s, to_tag.len) == 0
115 && s->from_tag.len == from_tag.len
116 && strncmp(s->from_tag.s, from_tag.s, from_tag.len) == 0)
124 subs_t *mem_copy_subs(subs_t *s, int mem_type)
129 size = sizeof(subs_t)
130 + (s->pres_uri.len + s->to_user.len + s->to_domain.len
131 + s->from_user.len + s->from_domain.len + s->callid.len
132 + s->to_tag.len + s->from_tag.len + s->sockinfo_str.len
133 + s->event_id.len + s->local_contact.len + s->contact.len
134 + s->record_route.len + s->reason.len + s->watcher_user.len
135 + s->watcher_domain.len + s->user_agent.len + 1)
138 if(mem_type & PKG_MEM_TYPE)
139 dest = (subs_t *)pkg_malloc(size);
141 dest = (subs_t *)shm_malloc(size);
144 ERR_MEM((mem_type == PKG_MEM_TYPE) ? PKG_MEM_STR : SHARE_MEM);
146 memset(dest, 0, size);
147 size = sizeof(subs_t);
149 CONT_COPY(dest, dest->pres_uri, s->pres_uri);
150 CONT_COPY(dest, dest->to_user, s->to_user);
151 CONT_COPY(dest, dest->to_domain, s->to_domain);
152 CONT_COPY(dest, dest->from_user, s->from_user);
153 CONT_COPY(dest, dest->from_domain, s->from_domain);
154 CONT_COPY(dest, dest->watcher_user, s->watcher_user);
155 CONT_COPY(dest, dest->watcher_domain, s->watcher_domain);
156 CONT_COPY(dest, dest->to_tag, s->to_tag);
157 CONT_COPY(dest, dest->from_tag, s->from_tag);
158 CONT_COPY(dest, dest->callid, s->callid);
159 CONT_COPY(dest, dest->sockinfo_str, s->sockinfo_str);
160 CONT_COPY(dest, dest->local_contact, s->local_contact);
161 CONT_COPY(dest, dest->contact, s->contact);
162 CONT_COPY(dest, dest->record_route, s->record_route);
163 CONT_COPY(dest, dest->user_agent, s->user_agent);
165 CONT_COPY(dest, dest->event_id, s->event_id);
167 CONT_COPY(dest, dest->reason, s->reason);
169 dest->event = s->event;
170 dest->local_cseq = s->local_cseq;
171 dest->remote_cseq = s->remote_cseq;
172 dest->status = s->status;
173 dest->version = s->version;
174 dest->send_on_cback = s->send_on_cback;
175 dest->expires = s->expires;
176 dest->db_flag = s->db_flag;
177 dest->flags = s->flags;
186 subs_t *mem_copy_subs_noc(subs_t *s)
191 size = sizeof(subs_t)
192 + (s->pres_uri.len + s->to_user.len + s->to_domain.len
193 + s->from_user.len + s->from_domain.len + s->callid.len
194 + s->to_tag.len + s->from_tag.len + s->sockinfo_str.len
195 + s->event_id.len + s->local_contact.len + s->reason.len
196 + s->watcher_user.len + s->watcher_domain.len
197 + s->user_agent.len + 1)
200 dest = (subs_t *)shm_malloc(size);
204 memset(dest, 0, size);
205 size = sizeof(subs_t);
207 CONT_COPY(dest, dest->pres_uri, s->pres_uri);
208 CONT_COPY(dest, dest->to_user, s->to_user);
209 CONT_COPY(dest, dest->to_domain, s->to_domain);
210 CONT_COPY(dest, dest->from_user, s->from_user);
211 CONT_COPY(dest, dest->from_domain, s->from_domain);
212 CONT_COPY(dest, dest->watcher_user, s->watcher_user);
213 CONT_COPY(dest, dest->watcher_domain, s->watcher_domain);
214 CONT_COPY(dest, dest->to_tag, s->to_tag);
215 CONT_COPY(dest, dest->from_tag, s->from_tag);
216 CONT_COPY(dest, dest->callid, s->callid);
217 CONT_COPY(dest, dest->sockinfo_str, s->sockinfo_str);
218 CONT_COPY(dest, dest->local_contact, s->local_contact);
219 CONT_COPY(dest, dest->user_agent, s->user_agent);
221 CONT_COPY(dest, dest->event_id, s->event_id);
223 CONT_COPY(dest, dest->reason, s->reason);
225 dest->event = s->event;
226 dest->local_cseq = s->local_cseq;
227 dest->remote_cseq = s->remote_cseq;
228 dest->status = s->status;
229 dest->version = s->version;
230 dest->send_on_cback = s->send_on_cback;
231 dest->expires = s->expires;
232 dest->db_flag = s->db_flag;
233 dest->flags = s->flags;
235 dest->contact.s = (char *)shm_malloc(s->contact.len * sizeof(char));
236 if(dest->contact.s == NULL) {
239 memcpy(dest->contact.s, s->contact.s, s->contact.len);
240 dest->contact.len = s->contact.len;
242 dest->record_route.s =
243 (char *)shm_malloc((s->record_route.len + 1) * sizeof(char));
244 if(dest->record_route.s == NULL) {
247 memcpy(dest->record_route.s, s->record_route.s, s->record_route.len);
248 dest->record_route.len = s->record_route.len;
258 int insert_shtable(shtable_t htable, unsigned int hash_code, subs_t *subs)
260 subs_t *new_rec = NULL;
262 if (pres_delete_same_subs) {
263 subs_t* rec = NULL, *prev_rec = NULL;
265 lock_get(&htable[hash_code].lock);
266 /* search if there is another record with the same pres_uri & callid */
267 rec = htable[hash_code].entries->next;
269 if (subs->pres_uri.len == rec->pres_uri.len && subs->callid.len == rec->callid.len &&
270 memcmp(subs->pres_uri.s, rec->pres_uri.s, subs->pres_uri.len) == 0 &&
271 memcmp(subs->callid.s, rec->callid.s, subs->callid.len) == 0) {
272 LM_NOTICE("Found another record with the same pres_uri[%.*s] and callid[%.*s]\n",
273 subs->pres_uri.len, subs->pres_uri.s, subs->callid.len, subs->callid.s);
274 /* delete this record */
277 prev_rec->next = rec->next;
279 htable[hash_code].entries->next = rec->next;
282 if (pres_subs_dbmode != NO_DB) {
283 delete_db_subs(&rec->to_tag, &rec->from_tag, &rec->callid);
286 if (rec->contact.s!=NULL) {
287 shm_free(rec->contact.s);
296 lock_release(&htable[hash_code].lock);
299 new_rec = mem_copy_subs_noc(subs);
300 if(new_rec == NULL) {
301 LM_ERR("copying in share memory a subs_t structure\n");
304 new_rec->expires += (int)time(NULL);
306 lock_get(&htable[hash_code].lock);
307 new_rec->next = htable[hash_code].entries->next;
308 htable[hash_code].entries->next = new_rec;
309 lock_release(&htable[hash_code].lock);
314 int delete_shtable(shtable_t htable, unsigned int hash_code, subs_t *subs)
316 subs_t *s = NULL, *ps = NULL;
319 lock_get(&htable[hash_code].lock);
321 ps = htable[hash_code].entries;
322 s = ps ? ps->next : NULL;
325 if(pres_subs_remove_match == 0) {
326 /* match on to-tag only (unique, local generated - faster) */
327 if(s->to_tag.len == subs->to_tag.len
328 && strncmp(s->to_tag.s, subs->to_tag.s, subs->to_tag.len)
333 /* match on all dialog attributes (distributed systems) */
334 if(s->callid.len == subs->callid.len
335 && s->to_tag.len == subs->to_tag.len
336 && s->from_tag.len == subs->from_tag.len
337 && strncmp(s->callid.s, subs->callid.s, subs->callid.len)
339 && strncmp(s->to_tag.s, subs->to_tag.s, subs->to_tag.len)
341 && strncmp(s->from_tag.s, subs->from_tag.s,
348 found = s->local_cseq + 1;
350 if(s->contact.s != NULL) {
351 shm_free(s->contact.s);
354 if(s->record_route.s != NULL) {
355 shm_free(s->record_route.s);
356 s->record_route.s = NULL;
367 lock_release(&htable[hash_code].lock);
371 void free_subs_list(subs_t *s_array, int mem_type, int ic)
377 s_array = s_array->next;
378 if(mem_type & PKG_MEM_TYPE) {
380 pkg_free(s->contact.s);
387 shm_free(s->contact.s);
397 shtable_t htable, unsigned int hash_code, subs_t *subs, int type)
401 lock_get(&htable[hash_code].lock);
404 htable, subs->callid, subs->to_tag, subs->from_tag, hash_code);
406 LM_DBG("record not found in hash table\n");
407 lock_release(&htable[hash_code].lock);
411 if(type & REMOTE_TYPE) {
412 s->expires = subs->expires + (int)time(NULL);
413 s->remote_cseq = subs->remote_cseq;
415 subs->local_cseq = ++s->local_cseq;
416 subs->version = ++s->version;
419 if(presence_sip_uri_match(&s->contact, &subs->contact)) {
420 shm_free(s->contact.s);
421 s->contact.s = (char *)shm_malloc(subs->contact.len * sizeof(char));
422 if(s->contact.s == NULL) {
423 lock_release(&htable[hash_code].lock);
424 LM_ERR("no more shared memory\n");
427 memcpy(s->contact.s, subs->contact.s, subs->contact.len);
428 s->contact.len = subs->contact.len;
431 shm_free(s->record_route.s);
433 (char *)shm_malloc(subs->record_route.len * sizeof(char));
434 if(s->record_route.s == NULL) {
435 lock_release(&htable[hash_code].lock);
436 LM_ERR("no more shared memory\n");
439 memcpy(s->record_route.s, subs->record_route.s, subs->record_route.len);
440 s->record_route.len = subs->record_route.len;
442 s->status = subs->status;
443 s->event = subs->event;
444 subs->db_flag = s->db_flag;
446 if(s->db_flag & NO_UPDATEDB_FLAG)
447 s->db_flag = UPDATEDB_FLAG;
449 lock_release(&htable[hash_code].lock);
454 phtable_t *new_phtable(void)
456 phtable_t *htable = NULL;
460 htable = (phtable_t *)shm_malloc(phtable_size * sizeof(phtable_t));
464 memset(htable, 0, phtable_size * sizeof(phtable_t));
466 for(i = 0; i < phtable_size; i++) {
467 if(lock_init(&htable[i].lock) == 0) {
468 LM_ERR("initializing lock [%d]\n", i);
471 htable[i].entries = (pres_entry_t *)shm_malloc(sizeof(pres_entry_t));
472 if(htable[i].entries == NULL) {
475 memset(htable[i].entries, 0, sizeof(pres_entry_t));
476 htable[i].entries->next = NULL;
483 for(j = 0; j < i; j++) {
484 if(htable[i].entries)
485 shm_free(htable[i].entries);
488 lock_destroy(&htable[i].lock);
495 void destroy_phtable(void)
498 pres_entry_t *p, *prev_p;
500 if(pres_htable == NULL)
503 for(i = 0; i < phtable_size; i++) {
504 lock_destroy(&pres_htable[i].lock);
505 p = pres_htable[i].entries;
510 shm_free(prev_p->sphere);
514 shm_free(pres_htable);
516 /* entry must be locked before calling this function */
518 pres_entry_t *search_phtable(str *pres_uri, int event, unsigned int hash_code)
522 LM_DBG("pres_uri= %.*s\n", pres_uri->len, pres_uri->s);
523 p = pres_htable[hash_code].entries->next;
525 if(p->event == event && p->pres_uri.len == pres_uri->len
526 && presence_sip_uri_match(&p->pres_uri, pres_uri) == 0)
533 int insert_phtable(str *pres_uri, int event, char *sphere)
535 unsigned int hash_code;
536 pres_entry_t *p = NULL;
539 hash_code = core_case_hash(pres_uri, NULL, phtable_size);
541 lock_get(&pres_htable[hash_code].lock);
543 p = search_phtable(pres_uri, event, hash_code);
546 lock_release(&pres_htable[hash_code].lock);
549 size = sizeof(pres_entry_t) + pres_uri->len * sizeof(char);
551 p = (pres_entry_t *)shm_malloc(size);
553 lock_release(&pres_htable[hash_code].lock);
558 size = sizeof(pres_entry_t);
559 p->pres_uri.s = (char *)p + size;
560 memcpy(p->pres_uri.s, pres_uri->s, pres_uri->len);
561 p->pres_uri.len = pres_uri->len;
564 p->sphere = (char *)shm_malloc((strlen(sphere) + 1) * sizeof(char));
565 if(p->sphere == NULL) {
566 lock_release(&pres_htable[hash_code].lock);
570 strcpy(p->sphere, sphere);
576 /* link the item in the hash table */
577 p->next = pres_htable[hash_code].entries->next;
578 pres_htable[hash_code].entries->next = p;
580 lock_release(&pres_htable[hash_code].lock);
588 int delete_phtable(str *pres_uri, int event)
590 unsigned int hash_code;
591 pres_entry_t *p = NULL, *prev_p = NULL;
593 hash_code = core_case_hash(pres_uri, NULL, phtable_size);
595 lock_get(&pres_htable[hash_code].lock);
597 p = search_phtable(pres_uri, event, hash_code);
599 LM_DBG("record not found\n");
600 lock_release(&pres_htable[hash_code].lock);
605 if(p->publ_count == 0) {
607 prev_p = pres_htable[hash_code].entries;
608 while(prev_p->next) {
609 if(prev_p->next == p)
611 prev_p = prev_p->next;
613 if(prev_p->next == NULL) {
614 LM_ERR("record not found\n");
615 lock_release(&pres_htable[hash_code].lock);
618 prev_p->next = p->next;
624 lock_release(&pres_htable[hash_code].lock);
629 int update_phtable(presentity_t *presentity, str *pres_uri, str *body)
632 unsigned int hash_code;
635 str *xcap_doc = NULL;
638 sphere = extract_sphere(body);
640 LM_DBG("no sphere defined in new body\n");
644 /* search for record in hash table */
645 hash_code = core_case_hash(pres_uri, NULL, phtable_size);
647 lock_get(&pres_htable[hash_code].lock);
649 p = search_phtable(pres_uri, presentity->event->evp->type, hash_code);
651 lock_release(&pres_htable[hash_code].lock);
656 if(strcmp(p->sphere, sphere) != 0) {
657 /* new sphere definition */
660 /* no change in sphere definition */
661 lock_release(&pres_htable[hash_code].lock);
668 p->sphere = (char *)shm_malloc((strlen(sphere) + 1) * sizeof(char));
669 if(p->sphere == NULL) {
670 lock_release(&pres_htable[hash_code].lock);
674 strcpy(p->sphere, sphere);
676 lock_release(&pres_htable[hash_code].lock);
678 /* call for watchers status update */
680 if(presentity->event->get_rules_doc(
681 &presentity->user, &presentity->domain, &xcap_doc)
683 LM_ERR("failed to retrieve xcap document\n");
688 update_watchers_status(pres_uri, presentity->event, xcap_doc);
695 pkg_free(xcap_doc->s);
704 /* in-memory presentity records */
706 static ps_ptable_t *_ps_ptable = NULL;
708 ps_ptable_t *ps_ptable_get(void)
713 #define PS_PRESENTITY_FIELD_COPY(field) do { \
716 memcpy(ptn->field.s, pt->field.s, pt->field.len); \
718 ptn->field.len = pt->field.len; \
719 p += pt->field.len + 1; \
725 ps_presentity_t *ps_presentity_new(ps_presentity_t *pt, int mtype)
728 ps_presentity_t *ptn = NULL;
734 bsize = sizeof(ps_presentity_t)
743 ptn = (ps_presentity_t*)shm_malloc(bsize);
745 ptn = (ps_presentity_t*)pkg_malloc(bsize);
755 memset(ptn, 0, bsize);
758 ptn->hashid = core_case_hash(&pt->user, &pt->domain, 0);
759 ptn->expires = pt->expires;
760 ptn->received_time = pt->received_time;
761 ptn->priority = pt->priority;
763 p = (char*)ptn + sizeof(ps_presentity_t);
764 PS_PRESENTITY_FIELD_COPY(user);
765 PS_PRESENTITY_FIELD_COPY(domain);
766 PS_PRESENTITY_FIELD_COPY(etag);
767 PS_PRESENTITY_FIELD_COPY(event);
768 PS_PRESENTITY_FIELD_COPY(ruid);
769 PS_PRESENTITY_FIELD_COPY(sender);
770 PS_PRESENTITY_FIELD_COPY(body);
778 void ps_presentity_free(ps_presentity_t *pt, int mtype)
793 void ps_presentity_list_free(ps_presentity_t *pt, int mtype)
795 ps_presentity_t *ptc = NULL;
796 ps_presentity_t *ptn = NULL;
806 ps_presentity_free(ptc, mtype);
810 #define PS_PRESENTITY_FIELD_SHIFT(field) do { \
814 p += pt->field.len + 1; \
820 ps_presentity_t *ps_presentity_dup(ps_presentity_t *pt, int mtype)
822 ps_presentity_t *ptn = NULL;
829 ptn = (ps_presentity_t*)shm_malloc(pt->bsize);
831 ptn = (ps_presentity_t*)pkg_malloc(pt->bsize);
842 memcpy((void*)ptn, pt, pt->bsize);
844 p = (char*)ptn + sizeof(ps_presentity_t);
845 PS_PRESENTITY_FIELD_SHIFT(user);
846 PS_PRESENTITY_FIELD_SHIFT(domain);
847 PS_PRESENTITY_FIELD_SHIFT(etag);
848 PS_PRESENTITY_FIELD_SHIFT(event);
849 PS_PRESENTITY_FIELD_SHIFT(ruid);
850 PS_PRESENTITY_FIELD_SHIFT(sender);
851 PS_PRESENTITY_FIELD_SHIFT(body);
862 int ps_presentity_match(ps_presentity_t *pta, ps_presentity_t *ptb, int mmode)
864 if(pta->hashid != ptb->hashid) {
868 if(pta->user.len != ptb->user.len || pta->domain.len != ptb->domain.len) {
873 if(pta->etag.len != ptb->etag.len || pta->event.len != ptb->event.len) {
878 if(strncmp(pta->user.s, ptb->user.s, pta->user.len)!=0) {
882 if(strncmp(pta->domain.s, ptb->domain.s, pta->domain.len)!=0) {
887 if(strncmp(pta->etag.s, ptb->etag.s, pta->etag.len)!=0) {
891 if(strncmp(pta->event.s, ptb->event.s, pta->event.len)!=0) {
902 int ps_ptable_init(int ssize)
907 if(_ps_ptable!=NULL) {
910 tsize = sizeof(ps_ptable_t) + (ssize * sizeof(ps_pslot_t));
911 _ps_ptable = (ps_ptable_t*)shm_malloc(tsize);
912 if(_ps_ptable==NULL) {
916 memset(_ps_ptable, 0, tsize);
917 _ps_ptable->ssize = ssize;
918 _ps_ptable->slots = (ps_pslot_t*)((char*)_ps_ptable + sizeof(ps_ptable_t));
919 for(i=0; i<ssize; i++) {
920 if(lock_init(&_ps_ptable->slots[i].lock) == 0) {
921 LM_ERR("initializing lock on slot [%d]\n", i);
931 lock_destroy(&_ps_ptable->slots[i].lock);
934 shm_free(_ps_ptable);
942 void ps_ptable_destroy(void)
945 ps_presentity_t *pt = NULL;
946 ps_presentity_t *ptn = NULL;
948 if(_ps_ptable==NULL) {
951 for(i=0; i<_ps_ptable->ssize; i++) {
952 lock_destroy(&_ps_ptable->slots[i].lock);
953 pt = _ps_ptable->slots[i].plist;
956 ps_presentity_free(pt, 0);
960 shm_free(_ps_ptable);
968 int ps_ptable_insert(ps_presentity_t *pt)
971 ps_presentity_t *ptn = NULL;
974 /* copy struct to fill in missing fields */
975 memcpy(&ptc, pt, sizeof(ps_presentity_t));
977 ptc.hashid = core_case_hash(&pt->user, &pt->domain, 0);
979 if(ptc.ruid.s == NULL) {
980 if(sruid_next(&pres_sruid) < 0) {
983 ptc.ruid = pres_sruid.uid;
986 ptn = ps_presentity_new(&ptc, 0);
991 idx = ptn->hashid % _ps_ptable->ssize;
993 lock_get(&_ps_ptable->slots[idx].lock);
994 if(_ps_ptable->slots[idx].plist == NULL) {
995 _ps_ptable->slots[idx].plist = ptn;
997 _ps_ptable->slots[idx].plist->prev = ptn;
998 ptn->next = _ps_ptable->slots[idx].plist;
999 _ps_ptable->slots[idx].plist = ptn;
1001 lock_release(&_ps_ptable->slots[idx].lock);
1009 int ps_ptable_replace(ps_presentity_t *pt)
1011 ps_presentity_t ptc;
1012 ps_presentity_t *ptn = NULL;
1015 /* copy struct to fill in missing fields */
1016 memcpy(&ptc, pt, sizeof(ps_presentity_t));
1018 ptc.hashid = core_case_hash(&pt->user, &pt->domain, 0);
1020 if(ptc.ruid.s == NULL) {
1021 if(sruid_next(&pres_sruid) < 0) {
1024 ptc.ruid = pres_sruid.uid;
1027 idx = ptc.hashid % _ps_ptable->ssize;
1029 lock_get(&_ps_ptable->slots[idx].lock);
1030 ptn = _ps_ptable->slots[idx].plist;
1032 if(ps_presentity_match(ptn, &ptc, 0)==1) {
1034 ptn->next->prev = ptn->prev;
1037 ptn->prev->next = ptn->next;
1039 _ps_ptable->slots[idx].plist = ptn->next;
1046 ptn = ps_presentity_new(&ptc, 0);
1048 lock_release(&_ps_ptable->slots[idx].lock);
1052 if(_ps_ptable->slots[idx].plist == NULL) {
1053 _ps_ptable->slots[idx].plist = ptn;
1055 _ps_ptable->slots[idx].plist->prev = ptn;
1056 ptn->next = _ps_ptable->slots[idx].plist;
1057 _ps_ptable->slots[idx].plist = ptn;
1059 lock_release(&_ps_ptable->slots[idx].lock);
1067 int ps_ptable_update(ps_presentity_t *pt)
1069 ps_presentity_t ptc;
1070 ps_presentity_t *ptn = NULL;
1073 /* copy struct to fill in missing fields */
1074 memcpy(&ptc, pt, sizeof(ps_presentity_t));
1076 ptc.hashid = core_case_hash(&pt->user, &pt->domain, 0);
1078 if(ptc.ruid.s == NULL) {
1079 if(sruid_next(&pres_sruid) < 0) {
1082 ptc.ruid = pres_sruid.uid;
1085 idx = ptc.hashid % _ps_ptable->ssize;
1087 lock_get(&_ps_ptable->slots[idx].lock);
1088 ptn = _ps_ptable->slots[idx].plist;
1090 if(ps_presentity_match(ptn, &ptc, 0)==1) {
1092 ptn->next->prev = ptn->prev;
1095 ptn->prev->next = ptn->next;
1097 _ps_ptable->slots[idx].plist = ptn->next;
1105 lock_release(&_ps_ptable->slots[idx].lock);
1106 return 0; /* affected items */
1108 ps_presentity_free(ptn, 0);
1110 ptn = ps_presentity_new(&ptc, 0);
1112 lock_release(&_ps_ptable->slots[idx].lock);
1116 if(_ps_ptable->slots[idx].plist == NULL) {
1117 _ps_ptable->slots[idx].plist = ptn;
1119 _ps_ptable->slots[idx].plist->prev = ptn;
1120 ptn->next = _ps_ptable->slots[idx].plist;
1121 _ps_ptable->slots[idx].plist = ptn;
1123 lock_release(&_ps_ptable->slots[idx].lock);
1125 return 1; /* affected items */
1131 int ps_ptable_remove(ps_presentity_t *pt)
1133 ps_presentity_t ptc;
1134 ps_presentity_t *ptn = NULL;
1137 /* copy struct to fill in missing fields */
1138 memcpy(&ptc, pt, sizeof(ps_presentity_t));
1140 ptc.hashid = core_case_hash(&pt->user, &pt->domain, 0);
1141 idx = ptc.hashid % _ps_ptable->ssize;
1143 lock_get(&_ps_ptable->slots[idx].lock);
1144 ptn = _ps_ptable->slots[idx].plist;
1146 if(ps_presentity_match(ptn, &ptc, 0)==1) {
1148 ptn->next->prev = ptn->prev;
1151 ptn->prev->next = ptn->next;
1153 _ps_ptable->slots[idx].plist = ptn->next;
1159 lock_release(&_ps_ptable->slots[idx].lock);
1162 ps_presentity_free(ptn, 0);
1170 ps_presentity_t *ps_ptable_get_list(str *user, str *domain)
1172 ps_presentity_t ptc;
1173 ps_presentity_t *ptn = NULL;
1174 ps_presentity_t *ptl = NULL;
1175 ps_presentity_t *ptd = NULL;
1176 ps_presentity_t *pte = NULL;
1179 memset(&ptc, 0, sizeof(ps_presentity_t));
1182 ptc.domain = *domain;
1183 ptc.hashid = core_case_hash(&ptc.user, &ptc.domain, 0);
1184 idx = ptc.hashid % _ps_ptable->ssize;
1186 lock_get(&_ps_ptable->slots[idx].lock);
1187 ptn = _ps_ptable->slots[idx].plist;
1189 if(ps_presentity_match(ptn, &ptc, 1)==1) {
1190 ptd = ps_presentity_dup(ptn, 1);
1204 lock_release(&_ps_ptable->slots[idx].lock);
1206 if(ptd==NULL && ptl != NULL) {
1207 ps_presentity_list_free(ptl, 1);
1217 ps_presentity_t *ps_ptable_get_item(str *user, str *domain, str *event, str *etag)
1219 ps_presentity_t ptc;
1220 ps_presentity_t *ptn = NULL;
1221 ps_presentity_t *ptd = NULL;
1224 memset(&ptc, 0, sizeof(ps_presentity_t));
1227 ptc.domain = *domain;
1230 ptc.hashid = core_case_hash(&ptc.user, &ptc.domain, 0);
1231 idx = ptc.hashid % _ps_ptable->ssize;
1233 lock_get(&_ps_ptable->slots[idx].lock);
1234 ptn = _ps_ptable->slots[idx].plist;
1236 if(ps_presentity_match(ptn, &ptc, 0)==1) {
1237 ptd = ps_presentity_dup(ptn, 1);
1242 lock_release(&_ps_ptable->slots[idx].lock);
1250 ps_presentity_t *ps_ptable_get_expired(int eval)
1252 ps_presentity_t *ptn = NULL;
1253 ps_presentity_t *ptl = NULL;
1254 ps_presentity_t *ptd = NULL;
1255 ps_presentity_t *pte = NULL;
1258 for(i=0; i<_ps_ptable->ssize; i++) {
1259 lock_get(&_ps_ptable->slots[i].lock);
1260 ptn = _ps_ptable->slots[i].plist;
1262 if(ptn->expires > 0 && ptn->expires <= eval) {
1263 ptd = ps_presentity_dup(ptn, 1);
1277 lock_release(&_ps_ptable->slots[i].lock);
1280 if(ptd==NULL && ptl != NULL) {
1281 ps_presentity_list_free(ptl, 1);