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);
705 * ==============================
706 * in-memory presentity records
707 * ==============================
710 static ps_ptable_t *_ps_ptable = NULL;
712 ps_ptable_t *ps_ptable_get(void)
717 #define PS_PRESENTITY_FIELD_COPY(field) do { \
720 memcpy(ptn->field.s, pt->field.s, pt->field.len); \
722 ptn->field.len = pt->field.len; \
723 p += pt->field.len + 1; \
729 ps_presentity_t *ps_presentity_new(ps_presentity_t *pt, int mtype)
732 ps_presentity_t *ptn = NULL;
738 bsize = sizeof(ps_presentity_t)
747 ptn = (ps_presentity_t*)shm_malloc(bsize);
749 ptn = (ps_presentity_t*)pkg_malloc(bsize);
759 memset(ptn, 0, bsize);
762 ptn->hashid = core_case_hash(&pt->user, &pt->domain, 0);
763 ptn->expires = pt->expires;
764 ptn->received_time = pt->received_time;
765 ptn->priority = pt->priority;
767 p = (char*)ptn + sizeof(ps_presentity_t);
768 PS_PRESENTITY_FIELD_COPY(user);
769 PS_PRESENTITY_FIELD_COPY(domain);
770 PS_PRESENTITY_FIELD_COPY(etag);
771 PS_PRESENTITY_FIELD_COPY(event);
772 PS_PRESENTITY_FIELD_COPY(ruid);
773 PS_PRESENTITY_FIELD_COPY(sender);
774 PS_PRESENTITY_FIELD_COPY(body);
782 void ps_presentity_free(ps_presentity_t *pt, int mtype)
797 void ps_presentity_list_free(ps_presentity_t *pt, int mtype)
799 ps_presentity_t *ptc = NULL;
800 ps_presentity_t *ptn = NULL;
810 ps_presentity_free(ptc, mtype);
814 #define PS_PRESENTITY_FIELD_SHIFT(field) do { \
818 p += pt->field.len + 1; \
824 ps_presentity_t *ps_presentity_dup(ps_presentity_t *pt, int mtype)
826 ps_presentity_t *ptn = NULL;
833 ptn = (ps_presentity_t*)shm_malloc(pt->bsize);
835 ptn = (ps_presentity_t*)pkg_malloc(pt->bsize);
846 memcpy((void*)ptn, pt, pt->bsize);
848 p = (char*)ptn + sizeof(ps_presentity_t);
849 PS_PRESENTITY_FIELD_SHIFT(user);
850 PS_PRESENTITY_FIELD_SHIFT(domain);
851 PS_PRESENTITY_FIELD_SHIFT(etag);
852 PS_PRESENTITY_FIELD_SHIFT(event);
853 PS_PRESENTITY_FIELD_SHIFT(ruid);
854 PS_PRESENTITY_FIELD_SHIFT(sender);
855 PS_PRESENTITY_FIELD_SHIFT(body);
866 int ps_presentity_match(ps_presentity_t *pta, ps_presentity_t *ptb, int mmode)
868 if(pta->hashid != ptb->hashid) {
872 if(pta->user.len != ptb->user.len || pta->domain.len != ptb->domain.len) {
877 if(pta->etag.len != ptb->etag.len || pta->event.len != ptb->event.len) {
882 if(strncmp(pta->user.s, ptb->user.s, pta->user.len)!=0) {
886 if(strncmp(pta->domain.s, ptb->domain.s, pta->domain.len)!=0) {
891 if(strncmp(pta->etag.s, ptb->etag.s, pta->etag.len)!=0) {
895 if(strncmp(pta->event.s, ptb->event.s, pta->event.len)!=0) {
906 int ps_ptable_init(int ssize)
911 if(_ps_ptable!=NULL) {
914 tsize = sizeof(ps_ptable_t) + (ssize * sizeof(ps_pslot_t));
915 _ps_ptable = (ps_ptable_t*)shm_malloc(tsize);
916 if(_ps_ptable==NULL) {
920 memset(_ps_ptable, 0, tsize);
921 _ps_ptable->ssize = ssize;
922 _ps_ptable->slots = (ps_pslot_t*)((char*)_ps_ptable + sizeof(ps_ptable_t));
923 for(i=0; i<ssize; i++) {
924 if(lock_init(&_ps_ptable->slots[i].lock) == 0) {
925 LM_ERR("initializing lock on slot [%d]\n", i);
935 lock_destroy(&_ps_ptable->slots[i].lock);
938 shm_free(_ps_ptable);
946 void ps_ptable_destroy(void)
949 ps_presentity_t *pt = NULL;
950 ps_presentity_t *ptn = NULL;
952 if(_ps_ptable==NULL) {
955 for(i=0; i<_ps_ptable->ssize; i++) {
956 lock_destroy(&_ps_ptable->slots[i].lock);
957 pt = _ps_ptable->slots[i].plist;
960 ps_presentity_free(pt, 0);
964 shm_free(_ps_ptable);
972 int ps_ptable_insert(ps_presentity_t *pt)
975 ps_presentity_t *ptn = NULL;
978 /* copy struct to fill in missing fields */
979 memcpy(&ptc, pt, sizeof(ps_presentity_t));
981 ptc.hashid = core_case_hash(&pt->user, &pt->domain, 0);
983 if(ptc.ruid.s == NULL) {
984 if(sruid_next(&pres_sruid) < 0) {
987 ptc.ruid = pres_sruid.uid;
990 ptn = ps_presentity_new(&ptc, 0);
995 idx = ptn->hashid & (_ps_ptable->ssize - 1);
997 lock_get(&_ps_ptable->slots[idx].lock);
998 if(_ps_ptable->slots[idx].plist == NULL) {
999 _ps_ptable->slots[idx].plist = ptn;
1001 _ps_ptable->slots[idx].plist->prev = ptn;
1002 ptn->next = _ps_ptable->slots[idx].plist;
1003 _ps_ptable->slots[idx].plist = ptn;
1005 lock_release(&_ps_ptable->slots[idx].lock);
1013 int ps_ptable_replace(ps_presentity_t *pt)
1015 ps_presentity_t ptc;
1016 ps_presentity_t *ptn = NULL;
1019 /* copy struct to fill in missing fields */
1020 memcpy(&ptc, pt, sizeof(ps_presentity_t));
1022 ptc.hashid = core_case_hash(&pt->user, &pt->domain, 0);
1024 if(ptc.ruid.s == NULL) {
1025 if(sruid_next(&pres_sruid) < 0) {
1028 ptc.ruid = pres_sruid.uid;
1031 idx = ptc.hashid & (_ps_ptable->ssize - 1);
1033 lock_get(&_ps_ptable->slots[idx].lock);
1034 ptn = _ps_ptable->slots[idx].plist;
1036 if(ps_presentity_match(ptn, &ptc, 0)==1) {
1038 ptn->next->prev = ptn->prev;
1041 ptn->prev->next = ptn->next;
1043 _ps_ptable->slots[idx].plist = ptn->next;
1051 ps_presentity_free(ptn, 0);
1054 ptn = ps_presentity_new(&ptc, 0);
1056 lock_release(&_ps_ptable->slots[idx].lock);
1060 if(_ps_ptable->slots[idx].plist == NULL) {
1061 _ps_ptable->slots[idx].plist = ptn;
1063 _ps_ptable->slots[idx].plist->prev = ptn;
1064 ptn->next = _ps_ptable->slots[idx].plist;
1065 _ps_ptable->slots[idx].plist = ptn;
1067 lock_release(&_ps_ptable->slots[idx].lock);
1075 int ps_ptable_update(ps_presentity_t *pt)
1077 ps_presentity_t ptc;
1078 ps_presentity_t *ptn = NULL;
1081 /* copy struct to fill in missing fields */
1082 memcpy(&ptc, pt, sizeof(ps_presentity_t));
1084 ptc.hashid = core_case_hash(&pt->user, &pt->domain, 0);
1086 if(ptc.ruid.s == NULL) {
1087 if(sruid_next(&pres_sruid) < 0) {
1090 ptc.ruid = pres_sruid.uid;
1093 idx = ptc.hashid & (_ps_ptable->ssize - 1);
1095 lock_get(&_ps_ptable->slots[idx].lock);
1096 ptn = _ps_ptable->slots[idx].plist;
1098 if(ps_presentity_match(ptn, &ptc, 0)==1) {
1100 ptn->next->prev = ptn->prev;
1103 ptn->prev->next = ptn->next;
1105 _ps_ptable->slots[idx].plist = ptn->next;
1113 lock_release(&_ps_ptable->slots[idx].lock);
1114 return 0; /* affected items */
1116 ps_presentity_free(ptn, 0);
1118 ptn = ps_presentity_new(&ptc, 0);
1120 lock_release(&_ps_ptable->slots[idx].lock);
1124 if(_ps_ptable->slots[idx].plist == NULL) {
1125 _ps_ptable->slots[idx].plist = ptn;
1127 _ps_ptable->slots[idx].plist->prev = ptn;
1128 ptn->next = _ps_ptable->slots[idx].plist;
1129 _ps_ptable->slots[idx].plist = ptn;
1131 lock_release(&_ps_ptable->slots[idx].lock);
1133 return 1; /* affected items */
1139 int ps_ptable_remove(ps_presentity_t *pt)
1141 ps_presentity_t ptc;
1142 ps_presentity_t *ptn = NULL;
1145 /* copy struct to fill in missing fields */
1146 memcpy(&ptc, pt, sizeof(ps_presentity_t));
1148 ptc.hashid = core_case_hash(&pt->user, &pt->domain, 0);
1149 idx = ptc.hashid & (_ps_ptable->ssize - 1);
1151 lock_get(&_ps_ptable->slots[idx].lock);
1152 ptn = _ps_ptable->slots[idx].plist;
1154 if(ps_presentity_match(ptn, &ptc, 0)==1) {
1156 ptn->next->prev = ptn->prev;
1159 ptn->prev->next = ptn->next;
1161 _ps_ptable->slots[idx].plist = ptn->next;
1167 lock_release(&_ps_ptable->slots[idx].lock);
1170 ps_presentity_free(ptn, 0);
1178 ps_presentity_t *ps_ptable_get_list(str *user, str *domain)
1180 ps_presentity_t ptc;
1181 ps_presentity_t *ptn = NULL;
1182 ps_presentity_t *ptl = NULL;
1183 ps_presentity_t *ptd = NULL;
1184 ps_presentity_t *pte = NULL;
1187 memset(&ptc, 0, sizeof(ps_presentity_t));
1190 ptc.domain = *domain;
1191 ptc.hashid = core_case_hash(&ptc.user, &ptc.domain, 0);
1192 idx = ptc.hashid & (_ps_ptable->ssize - 1);
1194 lock_get(&_ps_ptable->slots[idx].lock);
1195 ptn = _ps_ptable->slots[idx].plist;
1197 if(ps_presentity_match(ptn, &ptc, 1)==1) {
1198 ptd = ps_presentity_dup(ptn, 1);
1212 lock_release(&_ps_ptable->slots[idx].lock);
1214 if(ptd==NULL && ptl != NULL) {
1215 ps_presentity_list_free(ptl, 1);
1225 ps_presentity_t *ps_ptable_get_item(str *user, str *domain, str *event, str *etag)
1227 ps_presentity_t ptc;
1228 ps_presentity_t *ptn = NULL;
1229 ps_presentity_t *ptd = NULL;
1232 memset(&ptc, 0, sizeof(ps_presentity_t));
1235 ptc.domain = *domain;
1238 ptc.hashid = core_case_hash(&ptc.user, &ptc.domain, 0);
1239 idx = ptc.hashid & (_ps_ptable->ssize - 1);
1241 lock_get(&_ps_ptable->slots[idx].lock);
1242 ptn = _ps_ptable->slots[idx].plist;
1244 if(ps_presentity_match(ptn, &ptc, 0)==1) {
1245 ptd = ps_presentity_dup(ptn, 1);
1250 lock_release(&_ps_ptable->slots[idx].lock);
1258 ps_presentity_t *ps_ptable_get_expired(int eval)
1260 ps_presentity_t *ptn = NULL;
1261 ps_presentity_t *ptl = NULL;
1262 ps_presentity_t *ptd = NULL;
1263 ps_presentity_t *pte = NULL;
1266 for(i=0; i<_ps_ptable->ssize; i++) {
1267 lock_get(&_ps_ptable->slots[i].lock);
1268 ptn = _ps_ptable->slots[i].plist;
1270 if(ptn->expires > 0 && ptn->expires <= eval) {
1271 ptd = ps_presentity_dup(ptn, 1);
1285 lock_release(&_ps_ptable->slots[i].lock);
1288 if(ptd==NULL && ptl != NULL) {
1289 ps_presentity_list_free(ptl, 1);