1 /*
2  * Copyright (C) 2005 iptelorg GmbH
3  *
4  * This file is part of ser, a free SIP server.
5  *
6  * ser is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version
10  *
11  * For a license to use the ser software under conditions
12  * other than those described here, or to purchase support for this
13  * software, please contact iptel.org by e-mail at the following addresses:
14  *    info@iptel.org
15  *
16  * ser is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
24  */
25 
26 #include <presence/domain_maintainer.h>
27 #include <cds/ptr_vector.h>
28 #include <cds/memory.h>
29 #include <cds/logger.h>
30 
create_domain_maintainer()31 domain_maintainer_t *create_domain_maintainer()
32 {
33 	domain_maintainer_t *dm;
34 
35 	dm = (domain_maintainer_t*)cds_malloc(sizeof(domain_maintainer_t));
36 	if (dm) {
37 		ptr_vector_init(&dm->registered_domains, 8);
38 		cds_mutex_init(&dm->mutex);
39 		dm->rc_grp = create_reference_counter_group(16);
40 	}
41 	return dm;
42 }
43 
destroy_domain_maintainer(domain_maintainer_t * dm)44 void destroy_domain_maintainer(domain_maintainer_t *dm)
45 {
46 	int i, cnt;
47 	notifier_domain_t *d;
48 
49 	if (!dm) return;
50 
51 	DEBUG_LOG("destroying domain maintainer\n");
52 
53 	cnt = ptr_vector_size(&dm->registered_domains);
54 	for (i = 0; i < cnt; i++) {
55 		d = ptr_vector_get(&dm->registered_domains, i);
56 		if (!d) continue;
57 		if (remove_reference(&d->ref)) {
58 			DEBUG_LOG("freeing domain: \'%.*s\'\n", FMT_STR(d->name));
59 			destroy_notifier_domain(d);
60 		}
61 	}
62 	ptr_vector_destroy(&dm->registered_domains);
63 	cds_mutex_destroy(&dm->mutex);
64 	cds_free(dm);
65 }
66 
find_domain_nolock(domain_maintainer_t * dm,const str_t * name)67 static notifier_domain_t *find_domain_nolock(domain_maintainer_t *dm, const str_t *name)
68 {
69 	notifier_domain_t *d = NULL;
70 	int i, cnt;
71 
72 	cnt = ptr_vector_size(&dm->registered_domains);
73 	for (i = 0; i < cnt; i++) {
74 		d = ptr_vector_get(&dm->registered_domains, i);
75 		if (!d) continue;
76 		if (str_case_equals(&d->name, name) == 0) return d;
77 	}
78 	return NULL;
79 }
80 
add_domain_nolock(domain_maintainer_t * dm,const str_t * name)81 static notifier_domain_t *add_domain_nolock(domain_maintainer_t *dm, const str_t *name)
82 {
83 	notifier_domain_t *d = create_notifier_domain(dm->rc_grp, name);
84 
85 	if (d) {
86 		DEBUG_LOG("created domain: \'%.*s\'\n", FMT_STR(d->name));
87 		ptr_vector_add(&dm->registered_domains, d);
88 		return d;
89 	}
90 	else return NULL;
91 }
92 
93 /* notifier_domain_t *find_notifier_domain(domain_maintainer_t *dm, const str_t *name)
94 {
95 	notifier_domain_t *d = NULL;
96 
97 	if (!dm) return NULL;
98 	cds_mutex_lock(&dm->mutex);
99 	d = find_domain_nolock(dm, name);
100 	cds_mutex_unlock(&dm->mutex);
101 	return d;
102 } */
103 
register_notifier_domain(domain_maintainer_t * dm,const str_t * name)104 notifier_domain_t *register_notifier_domain(domain_maintainer_t *dm, const str_t *name)
105 {
106 	notifier_domain_t *d = NULL;
107 
108 	if (!dm) return NULL;
109 
110 	cds_mutex_lock(&dm->mutex);
111 	d = find_domain_nolock(dm, name);
112 	if (!d) d = add_domain_nolock(dm, name);
113 	if (d) {
114 		add_reference(&d->ref); /* add reference for client */
115 	}
116 	cds_mutex_unlock(&dm->mutex);
117 	return d;
118 }
119 
remove_notifier_domain(domain_maintainer_t * dm,notifier_domain_t * domain)120 static void remove_notifier_domain(domain_maintainer_t *dm, notifier_domain_t *domain)
121 {
122 	notifier_domain_t *d = NULL;
123 	int i, cnt;
124 
125 	cnt = ptr_vector_size(&dm->registered_domains);
126 	for (i = 0; i < cnt; i++) {
127 		d = ptr_vector_get(&dm->registered_domains, i);
128 		if (d == domain) {
129 			ptr_vector_remove(&dm->registered_domains, i);
130 			break;
131 		}
132 	}
133 }
134 
release_notifier_domain(domain_maintainer_t * dm,notifier_domain_t * domain)135 void release_notifier_domain(domain_maintainer_t *dm, notifier_domain_t *domain)
136 {
137 	if ((!dm) || (!domain)) return;
138 
139 	cds_mutex_lock(&dm->mutex);
140 	if (remove_reference(&domain->ref)) {
141 		/* last reference */
142 		DEBUG_LOG("freeing domain: \'%.*s\'\n", FMT_STR(domain->name));
143 		remove_notifier_domain(dm, domain);
144 		destroy_notifier_domain(domain);
145 	}
146 	cds_mutex_unlock(&dm->mutex);
147 }
148 
149