1 /*
2  * presence module - presence server implementation
3  *
4  * Copyright (C) 2006 Voice Sistem S.R.L.
5  *
6  * This file is part of Kamailio, a free SIP serves.
7  *
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
12  *
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.
17  *
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
21  *
22  */
23 
24 /*! \file
25  * \brief Kamailio presence module :: Support for SUBSCRIBE handling
26  * \ingroup presence
27  */
28 
29 
30 #include "../../core/ut.h"
31 #include "../../core/usr_avp.h"
32 #include "../../core/data_lump_rpl.h"
33 #include "../../core/parser/parse_expires.h"
34 #include "../../core/parser/parse_event.h"
35 #include "../../core/parser/contact/parse_contact.h"
36 #include "../../core/hashes.h"
37 #include "presence.h"
38 #include "subscribe.h"
39 #include "utils_func.h"
40 #include "notify.h"
41 #include "../pua/hash.h"
42 #include "../../core/mod_fix.h"
43 #include "../../core/dset.h"
44 
45 int get_stored_info(
46 		struct sip_msg *msg, subs_t *subs, int *error_ret, str *reply_str);
47 int get_database_info(
48 		struct sip_msg *msg, subs_t *subs, int *error_ret, str *reply_str);
49 static int ps_get_subs_auth(subs_t *subs, int *found);
50 static int ps_insert_subs_auth(subs_t *subs);
51 
52 static str su_200_rpl = str_init("OK");
53 static str pu_481_rpl = str_init("Subscription does not exist");
54 static str pu_400_rpl = str_init("Bad request");
55 static str pu_500_rpl = str_init("Server Internal Error");
56 static str pu_489_rpl = str_init("Bad Event");
57 static str pu_423_rpl = str_init("Interval Too Brief");
58 
send_2XX_reply(sip_msg_t * msg,int reply_code,unsigned int lexpire,str * local_contact)59 static int send_2XX_reply(sip_msg_t *msg, int reply_code, unsigned int lexpire,
60 		str *local_contact)
61 {
62 	str hdr_append = {0, 0};
63 	str tmp;
64 	char *t = NULL;
65 
66 	tmp.s = int2str((unsigned long)lexpire, &tmp.len);
67 	hdr_append.len =
68 			9 + tmp.len + CRLF_LEN + 10 + local_contact->len + 16 + CRLF_LEN;
69 	hdr_append.s = (char *)pkg_malloc(sizeof(char) * (hdr_append.len + 1));
70 	if(hdr_append.s == NULL) {
71 		ERR_MEM(PKG_MEM_STR);
72 	}
73 	memcpy(hdr_append.s, "Expires: ", 9);
74 	memcpy(hdr_append.s + 9, tmp.s, tmp.len);
75 	tmp.s = hdr_append.s + 9 + tmp.len;
76 	memcpy(tmp.s, CRLF, CRLF_LEN);
77 	tmp.s += CRLF_LEN;
78 	memcpy(tmp.s, "Contact: <", 10);
79 	tmp.s += 10;
80 	memcpy(tmp.s, local_contact->s, local_contact->len);
81 	tmp.s[local_contact->len] = '\0';
82 	t = strstr(tmp.s, ";transport=");
83 	tmp.s += local_contact->len;
84 	if(t == NULL) {
85 		switch(msg->rcv.proto) {
86 			case PROTO_TCP:
87 				memcpy(tmp.s, ";transport=tcp", 14);
88 				tmp.s += 14;
89 				hdr_append.len -= 1;
90 				break;
91 			case PROTO_TLS:
92 				memcpy(tmp.s, ";transport=tls", 14);
93 				tmp.s += 14;
94 				hdr_append.len -= 1;
95 				break;
96 			case PROTO_SCTP:
97 				memcpy(tmp.s, ";transport=sctp", 15);
98 				tmp.s += 15;
99 				break;
100 			case PROTO_WS:
101 			case PROTO_WSS:
102 				memcpy(tmp.s, ";transport=ws", 13);
103 				tmp.s += 13;
104 				hdr_append.len -= 2;
105 				break;
106 			default:
107 				hdr_append.len -= 15;
108 		}
109 	} else {
110 		hdr_append.len -= 15;
111 	}
112 	*tmp.s = '>';
113 	memcpy(tmp.s + 1, CRLF, CRLF_LEN);
114 
115 	hdr_append.s[hdr_append.len] = '\0';
116 
117 	if(add_lump_rpl(msg, hdr_append.s, hdr_append.len, LUMP_RPL_HDR) == 0) {
118 		LM_ERR("unable to add lump_rl\n");
119 		goto error;
120 	}
121 
122 	if(slb.freply(msg, reply_code, &su_200_rpl) < 0) {
123 		LM_ERR("sending reply\n");
124 		goto error;
125 	}
126 
127 	pkg_free(hdr_append.s);
128 	return 0;
129 
130 error:
131 
132 	if(hdr_append.s != NULL)
133 		pkg_free(hdr_append.s);
134 	return -1;
135 }
136 
137 
delete_db_subs(str * to_tag,str * from_tag,str * callid)138 int delete_db_subs(str *to_tag, str *from_tag, str *callid)
139 {
140 	db_key_t query_cols[3];
141 	db_val_t query_vals[3];
142 	int n_query_cols = 0;
143 
144 	query_cols[n_query_cols] = &str_callid_col;
145 	query_vals[n_query_cols].type = DB1_STR;
146 	query_vals[n_query_cols].nul = 0;
147 	query_vals[n_query_cols].val.str_val = *callid;
148 	n_query_cols++;
149 
150 	query_cols[n_query_cols] = &str_to_tag_col;
151 	query_vals[n_query_cols].type = DB1_STR;
152 	query_vals[n_query_cols].nul = 0;
153 	query_vals[n_query_cols].val.str_val = *to_tag;
154 	n_query_cols++;
155 
156 	query_cols[n_query_cols] = &str_from_tag_col;
157 	query_vals[n_query_cols].type = DB1_STR;
158 	query_vals[n_query_cols].nul = 0;
159 	query_vals[n_query_cols].val.str_val = *from_tag;
160 	n_query_cols++;
161 
162 	if(pa_dbf.use_table(pa_db, &active_watchers_table) < 0) {
163 		LM_ERR("in use table sql operation\n");
164 		return -1;
165 	}
166 
167 	if(pa_dbf.delete(pa_db, query_cols, 0, query_vals, n_query_cols) < 0) {
168 		LM_ERR("sql delete failed\n");
169 		return -1;
170 	}
171 
172 	return 0;
173 }
174 
insert_subs_db(subs_t * s,int type)175 int insert_subs_db(subs_t *s, int type)
176 {
177 	db_key_t query_cols[26];
178 	db_val_t query_vals[26];
179 	int n_query_cols = 0;
180 	int pres_uri_col, to_user_col, to_domain_col, from_user_col,
181 			from_domain_col, callid_col, totag_col, fromtag_col, event_col,
182 			status_col, event_id_col, local_cseq_col, remote_cseq_col,
183 			expires_col, record_route_col, contact_col, local_contact_col,
184 			version_col, socket_info_col, reason_col, watcher_user_col,
185 			watcher_domain_col, updated_col, updated_winfo_col, user_agent_col,
186 			flags_col;
187 	str sval_empty = str_init("");
188 
189 	if(pa_dbf.use_table(pa_db, &active_watchers_table) < 0) {
190 		LM_ERR("sql use table failed\n");
191 		return -1;
192 	}
193 
194 	query_cols[pres_uri_col = n_query_cols] = &str_presentity_uri_col;
195 	query_vals[pres_uri_col].type = DB1_STR;
196 	query_vals[pres_uri_col].nul = 0;
197 	n_query_cols++;
198 
199 	query_cols[callid_col = n_query_cols] = &str_callid_col;
200 	query_vals[callid_col].type = DB1_STR;
201 	query_vals[callid_col].nul = 0;
202 	n_query_cols++;
203 
204 	query_cols[totag_col = n_query_cols] = &str_to_tag_col;
205 	query_vals[totag_col].type = DB1_STR;
206 	query_vals[totag_col].nul = 0;
207 	n_query_cols++;
208 
209 	query_cols[fromtag_col = n_query_cols] = &str_from_tag_col;
210 	query_vals[fromtag_col].type = DB1_STR;
211 	query_vals[fromtag_col].nul = 0;
212 	n_query_cols++;
213 
214 	query_cols[to_user_col = n_query_cols] = &str_to_user_col;
215 	query_vals[to_user_col].type = DB1_STR;
216 	query_vals[to_user_col].nul = 0;
217 	n_query_cols++;
218 
219 	query_cols[to_domain_col = n_query_cols] = &str_to_domain_col;
220 	query_vals[to_domain_col].type = DB1_STR;
221 	query_vals[to_domain_col].nul = 0;
222 	n_query_cols++;
223 
224 	query_cols[from_user_col = n_query_cols] = &str_from_user_col;
225 	query_vals[from_user_col].type = DB1_STR;
226 	query_vals[from_user_col].nul = 0;
227 	n_query_cols++;
228 
229 	query_cols[from_domain_col = n_query_cols] = &str_from_domain_col;
230 	query_vals[from_domain_col].type = DB1_STR;
231 	query_vals[from_domain_col].nul = 0;
232 	n_query_cols++;
233 
234 	query_cols[watcher_user_col = n_query_cols] = &str_watcher_username_col;
235 	query_vals[watcher_user_col].type = DB1_STR;
236 	query_vals[watcher_user_col].nul = 0;
237 	n_query_cols++;
238 
239 	query_cols[watcher_domain_col = n_query_cols] = &str_watcher_domain_col;
240 	query_vals[watcher_domain_col].type = DB1_STR;
241 	query_vals[watcher_domain_col].nul = 0;
242 	n_query_cols++;
243 
244 	query_cols[event_col = n_query_cols] = &str_event_col;
245 	query_vals[event_col].type = DB1_STR;
246 	query_vals[event_col].nul = 0;
247 	n_query_cols++;
248 
249 	query_cols[event_id_col = n_query_cols] = &str_event_id_col;
250 	query_vals[event_id_col].type = DB1_STR;
251 	query_vals[event_id_col].nul = 0;
252 	n_query_cols++;
253 
254 	query_cols[local_cseq_col = n_query_cols] = &str_local_cseq_col;
255 	query_vals[local_cseq_col].type = DB1_INT;
256 	query_vals[local_cseq_col].nul = 0;
257 	n_query_cols++;
258 
259 	query_cols[remote_cseq_col = n_query_cols] = &str_remote_cseq_col;
260 	query_vals[remote_cseq_col].type = DB1_INT;
261 	query_vals[remote_cseq_col].nul = 0;
262 	n_query_cols++;
263 
264 	query_cols[expires_col = n_query_cols] = &str_expires_col;
265 	query_vals[expires_col].type = DB1_INT;
266 	query_vals[expires_col].nul = 0;
267 	n_query_cols++;
268 
269 	query_cols[status_col = n_query_cols] = &str_status_col;
270 	query_vals[status_col].type = DB1_INT;
271 	query_vals[status_col].nul = 0;
272 	n_query_cols++;
273 
274 	query_cols[reason_col = n_query_cols] = &str_reason_col;
275 	query_vals[reason_col].type = DB1_STR;
276 	query_vals[reason_col].nul = 0;
277 	n_query_cols++;
278 
279 	query_cols[record_route_col = n_query_cols] = &str_record_route_col;
280 	query_vals[record_route_col].type = DB1_STR;
281 	query_vals[record_route_col].nul = 0;
282 	n_query_cols++;
283 
284 	query_cols[contact_col = n_query_cols] = &str_contact_col;
285 	query_vals[contact_col].type = DB1_STR;
286 	query_vals[contact_col].nul = 0;
287 	n_query_cols++;
288 
289 	query_cols[local_contact_col = n_query_cols] = &str_local_contact_col;
290 	query_vals[local_contact_col].type = DB1_STR;
291 	query_vals[local_contact_col].nul = 0;
292 	n_query_cols++;
293 
294 	query_cols[socket_info_col = n_query_cols] = &str_socket_info_col;
295 	query_vals[socket_info_col].type = DB1_STR;
296 	query_vals[socket_info_col].nul = 0;
297 	n_query_cols++;
298 
299 	query_cols[version_col = n_query_cols] = &str_version_col;
300 	query_vals[version_col].type = DB1_INT;
301 	query_vals[version_col].nul = 0;
302 	n_query_cols++;
303 
304 	query_cols[updated_col = n_query_cols] = &str_updated_col;
305 	query_vals[updated_col].type = DB1_INT;
306 	query_vals[updated_col].nul = 0;
307 	n_query_cols++;
308 
309 	query_cols[updated_winfo_col = n_query_cols] = &str_updated_winfo_col;
310 	query_vals[updated_winfo_col].type = DB1_INT;
311 	query_vals[updated_winfo_col].nul = 0;
312 	n_query_cols++;
313 
314 	query_cols[flags_col = n_query_cols] = &str_flags_col;
315 	query_vals[flags_col].type = DB1_INT;
316 	query_vals[flags_col].nul = 0;
317 	n_query_cols++;
318 
319 	query_cols[user_agent_col = n_query_cols] = &str_user_agent_col;
320 	query_vals[user_agent_col].type = DB1_STR;
321 	query_vals[user_agent_col].nul = 0;
322 	n_query_cols++;
323 
324 	query_vals[pres_uri_col].val.str_val = s->pres_uri;
325 	query_vals[callid_col].val.str_val = s->callid;
326 	query_vals[totag_col].val.str_val = s->to_tag;
327 	query_vals[fromtag_col].val.str_val = s->from_tag;
328 	query_vals[to_user_col].val.str_val = s->to_user;
329 	query_vals[to_domain_col].val.str_val = s->to_domain;
330 	query_vals[from_user_col].val.str_val = s->from_user;
331 	query_vals[from_domain_col].val.str_val = s->from_domain;
332 	query_vals[watcher_user_col].val.str_val = s->watcher_user;
333 	query_vals[watcher_domain_col].val.str_val = s->watcher_domain;
334 	query_vals[event_col].val.str_val = s->event->name;
335 	query_vals[event_id_col].val.str_val = s->event_id;
336 	query_vals[local_cseq_col].val.int_val = s->local_cseq;
337 	query_vals[remote_cseq_col].val.int_val = s->remote_cseq;
338 	query_vals[expires_col].val.int_val = s->expires + (int)time(NULL);
339 	query_vals[record_route_col].val.str_val = s->record_route;
340 	query_vals[contact_col].val.str_val = s->contact;
341 	query_vals[local_contact_col].val.str_val = s->local_contact;
342 	query_vals[version_col].val.int_val = s->version;
343 	query_vals[status_col].val.int_val = s->status;
344 	query_vals[reason_col].val.str_val = s->reason;
345 	query_vals[socket_info_col].val.str_val = s->sockinfo_str;
346 	query_vals[updated_col].val.int_val = s->updated;
347 	query_vals[updated_winfo_col].val.int_val = s->updated_winfo;
348 	query_vals[flags_col].val.int_val = s->flags;
349 	query_vals[user_agent_col].val.str_val =
350 			(s->user_agent.s && s->user_agent.len > 0) ? s->user_agent
351 													   : sval_empty;
352 
353 	if(pa_dbf.use_table(pa_db, &active_watchers_table) < 0) {
354 		LM_ERR("in use table sql operation\n");
355 		return -1;
356 	}
357 
358 	LM_DBG("inserting subscription in active_watchers table\n");
359 	if(pa_dbf.insert(pa_db, query_cols, query_vals, n_query_cols) < 0) {
360 		LM_ERR("unsuccessful sql insert\n");
361 		return -1;
362 	}
363 	return 0;
364 }
365 
update_subs_db(subs_t * subs,int type)366 int update_subs_db(subs_t *subs, int type)
367 {
368 	db_key_t query_cols[3], update_keys[10];
369 	db_val_t query_vals[3], update_vals[10];
370 	int n_update_cols = 0;
371 	int n_query_cols = 0;
372 
373 	query_cols[n_query_cols] = &str_callid_col;
374 	query_vals[n_query_cols].type = DB1_STR;
375 	query_vals[n_query_cols].nul = 0;
376 	query_vals[n_query_cols].val.str_val = subs->callid;
377 	n_query_cols++;
378 
379 	query_cols[n_query_cols] = &str_to_tag_col;
380 	query_vals[n_query_cols].type = DB1_STR;
381 	query_vals[n_query_cols].nul = 0;
382 	query_vals[n_query_cols].val.str_val = subs->to_tag;
383 	n_query_cols++;
384 
385 	query_cols[n_query_cols] = &str_from_tag_col;
386 	query_vals[n_query_cols].type = DB1_STR;
387 	query_vals[n_query_cols].nul = 0;
388 	query_vals[n_query_cols].val.str_val = subs->from_tag;
389 	n_query_cols++;
390 
391 	if(type & REMOTE_TYPE) {
392 		update_keys[n_update_cols] = &str_expires_col;
393 		update_vals[n_update_cols].type = DB1_INT;
394 		update_vals[n_update_cols].nul = 0;
395 		update_vals[n_update_cols].val.int_val =
396 				subs->expires + (int)time(NULL);
397 		n_update_cols++;
398 
399 		update_keys[n_update_cols] = &str_remote_cseq_col;
400 		update_vals[n_update_cols].type = DB1_INT;
401 		update_vals[n_update_cols].nul = 0;
402 		update_vals[n_update_cols].val.int_val = subs->remote_cseq;
403 		n_update_cols++;
404 
405 		update_keys[n_update_cols] = &str_updated_col;
406 		update_vals[n_update_cols].type = DB1_INT;
407 		update_vals[n_update_cols].nul = 0;
408 		update_vals[n_update_cols].val.int_val = subs->updated;
409 		n_update_cols++;
410 
411 		update_keys[n_update_cols] = &str_updated_winfo_col;
412 		update_vals[n_update_cols].type = DB1_INT;
413 		update_vals[n_update_cols].nul = 0;
414 		update_vals[n_update_cols].val.int_val = subs->updated_winfo;
415 		n_update_cols++;
416 
417 		update_keys[n_update_cols] = &str_contact_col;
418 		update_vals[n_update_cols].type = DB1_STR;
419 		update_vals[n_update_cols].nul = 0;
420 		update_vals[n_update_cols].val.str_val = subs->contact;
421 		n_update_cols++;
422 
423 		update_keys[n_update_cols] = &str_record_route_col;
424 		update_vals[n_update_cols].type = DB1_STR;
425 		update_vals[n_update_cols].nul = 0;
426 		update_vals[n_update_cols].val.str_val = subs->record_route;
427 		n_update_cols++;
428 	}
429 	if(type & LOCAL_TYPE) {
430 		update_keys[n_update_cols] = &str_local_cseq_col;
431 		update_vals[n_update_cols].type = DB1_INT;
432 		update_vals[n_update_cols].nul = 0;
433 		update_vals[n_update_cols].val.int_val = subs->local_cseq;
434 		n_update_cols++;
435 
436 		update_keys[n_update_cols] = &str_version_col;
437 		update_vals[n_update_cols].type = DB1_INT;
438 		update_vals[n_update_cols].nul = 0;
439 		update_vals[n_update_cols].val.int_val = subs->version;
440 		n_update_cols++;
441 	}
442 
443 	update_keys[n_update_cols] = &str_status_col;
444 	update_vals[n_update_cols].type = DB1_INT;
445 	update_vals[n_update_cols].nul = 0;
446 	update_vals[n_update_cols].val.int_val = subs->status;
447 	n_update_cols++;
448 
449 	update_keys[n_update_cols] = &str_reason_col;
450 	update_vals[n_update_cols].type = DB1_STR;
451 	update_vals[n_update_cols].nul = 0;
452 	update_vals[n_update_cols].val.str_val = subs->reason;
453 	n_update_cols++;
454 
455 	if(pa_dbf.use_table(pa_db, &active_watchers_table) < 0) {
456 		LM_ERR("in use table sql operation\n");
457 		return -1;
458 	}
459 
460 	if(pa_dbf.update(pa_db, query_cols, 0, query_vals, update_keys, update_vals,
461 			   n_query_cols, n_update_cols)
462 			< 0) {
463 		LM_ERR("updating presence information\n");
464 		return -1;
465 	}
466 	return 0;
467 }
468 
delete_subs(str * pres_uri,str * ev_name,str * to_tag,str * from_tag,str * callid)469 void delete_subs(
470 		str *pres_uri, str *ev_name, str *to_tag, str *from_tag, str *callid)
471 {
472 	subs_t subs;
473 
474 	memset(&subs, 0, sizeof(subs_t));
475 	subs.pres_uri = *pres_uri;
476 	subs.from_tag = *from_tag;
477 	subs.to_tag = *to_tag;
478 	subs.callid = *callid;
479 
480 	/* delete record from hash table also if not in dbonly mode */
481 	if(pres_subs_dbmode != DB_ONLY) {
482 		unsigned int hash_code =
483 				core_case_hash(pres_uri, ev_name, shtable_size);
484 		if(delete_shtable(subs_htable, hash_code, &subs) < 0) {
485 			LM_ERR("Failed to delete subscription from memory"
486 				   " [slot: %u ev: %.*s pu: %.*s ci: %.*s ft: %.*s tt: %.*s]\n",
487 					hash_code, pres_uri->len, pres_uri->s, ev_name->len,
488 					ev_name->s, callid->len, callid->s, from_tag->len,
489 					from_tag->s, to_tag->len, to_tag->s);
490 		}
491 	}
492 
493 	if(pres_subs_dbmode != NO_DB && delete_db_subs(to_tag, from_tag, callid) < 0)
494 		LM_ERR("Failed to delete subscription from database\n");
495 }
496 
update_subscription_notifier(struct sip_msg * msg,subs_t * subs,int to_tag_gen,int * sent_reply)497 int update_subscription_notifier(
498 		struct sip_msg *msg, subs_t *subs, int to_tag_gen, int *sent_reply)
499 {
500 	int num_peers = 0;
501 
502 	*sent_reply = 0;
503 
504 	/* Set the notifier/update fields for the subscription */
505 	subs->updated = core_case_hash(&subs->callid, &subs->from_tag, 0)
506 					% (pres_waitn_time * pres_notifier_poll_rate
507 							  * pres_notifier_processes);
508 	if(subs->event->type & WINFO_TYPE)
509 		subs->updated_winfo = UPDATED_TYPE;
510 	else if(subs->event->wipeer) {
511 		if((num_peers = set_wipeer_subs_updated(
512 					&subs->pres_uri, subs->event->wipeer, subs->expires == 0))
513 				< 0) {
514 			LM_ERR("failed to update database record(s)\n");
515 			goto error;
516 		}
517 
518 		if(num_peers > 0)
519 			subs->updated_winfo = UPDATED_TYPE;
520 	}
521 	if(subs->expires == 0) {
522 		subs->status = TERMINATED_STATUS;
523 		subs->reason.s = "timeout";
524 		subs->reason.len = 7;
525 	}
526 
527 	printf_subs(subs);
528 
529 	if(to_tag_gen == 0) {
530 		if(update_subs_db(subs, REMOTE_TYPE) < 0) {
531 			LM_ERR("updating subscription in database table\n");
532 			goto error;
533 		}
534 	} else {
535 		subs->version = 1;
536 		if(insert_subs_db(subs, REMOTE_TYPE) < 0) {
537 			LM_ERR("failed to insert new record in database\n");
538 			goto error;
539 		}
540 	}
541 
542 	if(send_2XX_reply(msg, subs->event->type & PUBL_TYPE ? 202 : 200,
543 			   subs->expires, &subs->local_contact)
544 			< 0) {
545 		LM_ERR("sending %d response\n",
546 				subs->event->type & PUBL_TYPE ? 202 : 200);
547 		goto error;
548 	}
549 	*sent_reply = 1;
550 
551 	return 1;
552 
553 error:
554 	return -1;
555 }
556 
update_subscription(struct sip_msg * msg,subs_t * subs,int to_tag_gen,int * sent_reply)557 int update_subscription(
558 		struct sip_msg *msg, subs_t *subs, int to_tag_gen, int *sent_reply)
559 {
560 	unsigned int hash_code;
561 
562 	LM_DBG("update subscription\n");
563 	printf_subs(subs);
564 
565 	*sent_reply = 0;
566 
567 	if(to_tag_gen == 0) /*if a SUBSCRIBE within a dialog */
568 	{
569 		if(subs->expires == 0) {
570 			LM_DBG("expires =0 -> deleting record\n");
571 
572 			delete_subs(&subs->pres_uri, &subs->event->name, &subs->to_tag,
573 					&subs->from_tag, &subs->callid);
574 
575 			if(subs->event->type & PUBL_TYPE) {
576 				if(send_2XX_reply(msg, 202, subs->expires, &subs->local_contact)
577 						< 0) {
578 					LM_ERR("sending 202 OK\n");
579 					goto error;
580 				}
581 				*sent_reply = 1;
582 				if(subs->event->wipeer) {
583 					if(query_db_notify(
584 							   &subs->pres_uri, subs->event->wipeer, NULL)
585 							< 0) {
586 						LM_ERR("Could not send notify for winfo\n");
587 						goto error;
588 					}
589 				}
590 
591 			} else /* if unsubscribe for winfo */
592 			{
593 				if(send_2XX_reply(msg, 200, subs->expires, &subs->local_contact)
594 						< 0) {
595 					LM_ERR("sending 200 OK reply\n");
596 					goto error;
597 				}
598 				*sent_reply = 1;
599 			}
600 
601 			if(notify(subs, NULL, NULL, 0, 0) < 0) {
602 				LM_ERR("Could not send notify\n");
603 				goto error;
604 			}
605 			return 1;
606 		}
607 		/* if subscriptions are stored in memory, update them */
608 		if(pres_subs_dbmode != DB_ONLY) {
609 			hash_code = core_case_hash(
610 					&subs->pres_uri, &subs->event->name, shtable_size);
611 			if(update_shtable(subs_htable, hash_code, subs, REMOTE_TYPE) < 0) {
612 				LM_ERR("failed to update subscription in memory\n");
613 				goto error;
614 			}
615 		}
616 		/* for modes that update the subscription synchronously in database, write in db */
617 		if(pres_subs_dbmode == DB_ONLY || pres_subs_dbmode == WRITE_THROUGH) {
618 			/* update in database table */
619 			if(update_subs_db(subs, REMOTE_TYPE | LOCAL_TYPE) < 0) {
620 				LM_ERR("updating subscription in database table\n");
621 				goto error;
622 			}
623 		}
624 	} else {
625 		LM_DBG("subscription not in dialog\n");
626 		if(subs->expires != 0) {
627 			if(pres_subs_dbmode != DB_ONLY) {
628 				LM_DBG("inserting in shtable\n");
629 				subs->db_flag = (pres_subs_dbmode == WRITE_THROUGH) ? WTHROUGHDB_FLAG
630 															   : INSERTDB_FLAG;
631 				hash_code = core_case_hash(
632 						&subs->pres_uri, &subs->event->name, shtable_size);
633 				subs->version = 0;
634 				if(insert_shtable(subs_htable, hash_code, subs) < 0) {
635 					LM_ERR("failed to insert new record in subs htable\n");
636 					goto error;
637 				}
638 			}
639 
640 			if(pres_subs_dbmode == DB_ONLY || pres_subs_dbmode == WRITE_THROUGH) {
641 				subs->version = 1;
642 				if(insert_subs_db(subs, REMOTE_TYPE) < 0) {
643 					LM_ERR("failed to insert new record in database\n");
644 					goto error;
645 				}
646 			}
647 			/* TODO if req_auth, the subscription was in the watcher table first, we must delete it */
648 		}
649 		/*otherwise there is a subscription outside a dialog with expires= 0
650 		 * no update in database, but should try to send Notify */
651 		else {
652 			LM_DBG("subscription request with expiry=0 not in dialog\n");
653 		}
654 	}
655 
656 	/* reply_and_notify  */
657 
658 	if(subs->event->type & PUBL_TYPE) {
659 		if(send_2XX_reply(msg, 202, subs->expires, &subs->local_contact) < 0) {
660 			LM_ERR("sending 202 OK reply\n");
661 			goto error;
662 		}
663 		*sent_reply = 1;
664 
665 		if(subs->expires != 0 && subs->event->wipeer) {
666 			LM_DBG("send Notify with winfo\n");
667 			if(query_db_notify(&subs->pres_uri, subs->event->wipeer, subs)
668 					< 0) {
669 				LM_ERR("Could not send notify winfo\n");
670 				goto error;
671 			}
672 			if(subs->send_on_cback == 0) {
673 				if(notify(subs, NULL, NULL, 0, 0) < 0) {
674 					LM_ERR("Could not send notify\n");
675 					goto error;
676 				}
677 			}
678 		} else {
679 			if(pres_send_fast_notify && (notify(subs, NULL, NULL, 0, 0) < 0)) {
680 				LM_ERR("Could not send notify\n");
681 				goto error;
682 			}
683 		}
684 
685 	} else {
686 		if(send_2XX_reply(msg, 200, subs->expires, &subs->local_contact) < 0) {
687 			LM_ERR("sending 200 OK reply\n");
688 			goto error;
689 		}
690 		*sent_reply = 1;
691 
692 		if(pres_send_fast_notify && (notify(subs, NULL, NULL, 0, 0) < 0)) {
693 			LM_ERR("sending notify request\n");
694 			goto error;
695 		}
696 	}
697 	return 0;
698 
699 error:
700 
701 	LM_ERR("occurred\n");
702 	return -1;
703 }
704 
ps_watchers_db_timer_clean(unsigned int ticks,void * param)705 void ps_watchers_db_timer_clean(unsigned int ticks, void *param)
706 {
707 	db_key_t db_keys[2];
708 	db_val_t db_vals[2];
709 	db_op_t db_ops[2];
710 
711 	if(pa_db == NULL) {
712 		return;
713 	}
714 
715 	LM_DBG("cleaning pending subscriptions\n");
716 
717 	db_keys[0] = &str_inserted_time_col;
718 	db_ops[0] = OP_LT;
719 	db_vals[0].type = DB1_INT;
720 	db_vals[0].nul = 0;
721 	db_vals[0].val.int_val = (int)time(NULL) - 24 * 3600;
722 
723 	db_keys[1] = &str_status_col;
724 	db_ops[1] = OP_EQ;
725 	db_vals[1].type = DB1_INT;
726 	db_vals[1].nul = 0;
727 	db_vals[1].val.int_val = PENDING_STATUS;
728 
729 	if(pa_dbf.use_table(pa_db, &watchers_table) < 0) {
730 		LM_ERR("unsuccessful use table sql operation\n");
731 		return;
732 	}
733 
734 	if(pa_dbf.delete(pa_db, db_keys, db_ops, db_vals, 2) < 0)
735 		LM_ERR("cleaning pending subscriptions\n");
736 }
737 
738 extern int _pres_subs_mode;
739 subs_t *_pres_subs_last_sub = NULL;
740 
741 /*
742  * Map between $subs(idxname) and subs_t
743  *
744  * uri (pres_uri) 1
745  * pres_uri 1
746  * to_user 2
747  * to_domain 3
748  * from_user 4
749  * from_domain 5
750  * watcher_username 6
751  * watcher_domain 7
752  * event (event->name) 8
753  * event_id 9
754  * to_tag 10
755  * from_tag 11
756  * callid 12
757  * remote_cseq 13
758  * local_cseq 14
759  * contact 15
760  * local_contact 16
761  * record_route 17
762  * expires 18
763  * status 19
764  * reason 20
765  * version 21
766  * flags 22
767  * user_agent 23
768  * sockinfo 24
769  */
770 
pv_parse_subscription_name(pv_spec_p sp,str * in)771 int pv_parse_subscription_name(pv_spec_p sp, str *in)
772 {
773 	if(sp == NULL || in == NULL || in->len <= 0)
774 		return -1;
775 
776 	switch(in->len) {
777 		case 3:
778 			if(strncmp(in->s, "uri", 3) == 0) {
779 				sp->pvp.pvn.u.isname.name.n = 1;
780 			} else {
781 				goto error;
782 			};
783 			break;
784 
785 		case 5:
786 			if(strncmp(in->s, "event", 5) == 0) {
787 				sp->pvp.pvn.u.isname.name.n = 8;
788 			} else if(strncmp(in->s, "flags", 5) == 0) {
789 				sp->pvp.pvn.u.isname.name.n = 22;
790 			} else {
791 				goto error;
792 			};
793 			break;
794 
795 		case 6:
796 			if(strncmp(in->s, "to_tag", 6) == 0) {
797 				sp->pvp.pvn.u.isname.name.n = 10;
798 			} else if(strncmp(in->s, "callid", 6) == 0) {
799 				sp->pvp.pvn.u.isname.name.n = 12;
800 			} else if(strncmp(in->s, "status", 6) == 0) {
801 				sp->pvp.pvn.u.isname.name.n = 19;
802 			} else if(strncmp(in->s, "reason", 6) == 0) {
803 				sp->pvp.pvn.u.isname.name.n = 20;
804 			} else {
805 				goto error;
806 			};
807 			break;
808 
809 		case 7:
810 			if(strncmp(in->s, "to_user", 7) == 0) {
811 				sp->pvp.pvn.u.isname.name.n = 2;
812 			} else if(strncmp(in->s, "contact", 7) == 0) {
813 				sp->pvp.pvn.u.isname.name.n = 15;
814 			} else if(strncmp(in->s, "expires", 7) == 0) {
815 				sp->pvp.pvn.u.isname.name.n = 18;
816 			} else if(strncmp(in->s, "version", 7) == 0) {
817 				sp->pvp.pvn.u.isname.name.n = 21;
818 			} else {
819 				goto error;
820 			};
821 			break;
822 
823 		case 8:
824 			if(strncmp(in->s, "pres_uri", 8) == 0) {
825 				sp->pvp.pvn.u.isname.name.n = 1;
826 			} else if(strncmp(in->s, "event_id", 8) == 0) {
827 				sp->pvp.pvn.u.isname.name.n = 9;
828 			} else if(strncmp(in->s, "from_tag", 8) == 0) {
829 				sp->pvp.pvn.u.isname.name.n = 11;
830 			} else if(strncmp(in->s, "sockinfo", 8) == 0) {
831 				sp->pvp.pvn.u.isname.name.n = 24;
832 			} else {
833 				goto error;
834 			};
835 			break;
836 
837 		case 9:
838 			if(strncmp(in->s, "to_domain", 9) == 0) {
839 				sp->pvp.pvn.u.isname.name.n = 3;
840 			} else if(strncmp(in->s, "from_user", 9) == 0) {
841 				sp->pvp.pvn.u.isname.name.n = 4;
842 			} else {
843 				goto error;
844 			};
845 			break;
846 
847 		case 10:
848 			if(strncmp(in->s, "local_cseq", 10) == 0) {
849 				sp->pvp.pvn.u.isname.name.n = 14;
850 			} else if(strncmp(in->s, "user_agent", 10) == 0) {
851 				sp->pvp.pvn.u.isname.name.n = 23;
852 			} else {
853 				goto error;
854 			};
855 			break;
856 
857 		case 11:
858 			if(strncmp(in->s, "from_domain", 11) == 0) {
859 				sp->pvp.pvn.u.isname.name.n = 5;
860 			} else if(strncmp(in->s, "remote_cseq", 11) == 0) {
861 				sp->pvp.pvn.u.isname.name.n = 13;
862 			} else {
863 				goto error;
864 			};
865 			break;
866 
867 		case 12:
868 			if(strncmp(in->s, "record_route", 12) == 0) {
869 				sp->pvp.pvn.u.isname.name.n = 17;
870 			} else {
871 				goto error;
872 			};
873 			break;
874 
875 		case 13:
876 			if(strncmp(in->s, "local_contact", 13) == 0) {
877 				sp->pvp.pvn.u.isname.name.n = 16;
878 			} else {
879 				goto error;
880 			};
881 			break;
882 
883 		case 14:
884 			if(strncmp(in->s, "watcher_domain", 14) == 0) {
885 				sp->pvp.pvn.u.isname.name.n = 7;
886 			} else {
887 				goto error;
888 			};
889 			break;
890 
891 		case 16:
892 			if(strncmp(in->s, "watcher_username", 16) == 0) {
893 				sp->pvp.pvn.u.isname.name.n = 6;
894 			} else {
895 				goto error;
896 			};
897 			break;
898 
899 		default:
900 			goto error;
901 	}
902 	sp->pvp.pvn.type = PV_NAME_INTSTR;
903 	sp->pvp.pvn.u.isname.type = 0;
904 
905 	return 0;
906 
907 error:
908 	LM_ERR("unknown PV subscription name %.*s\n", in->len, in->s);
909 	return -1;
910 }
911 
pv_get_subscription(struct sip_msg * msg,pv_param_t * param,pv_value_t * res)912 int pv_get_subscription(struct sip_msg *msg, pv_param_t *param, pv_value_t *res)
913 {
914 	if(_pres_subs_last_sub == NULL) {
915 		return pv_get_null(msg, param, res);
916 	}
917 
918 	if(param->pvn.u.isname.name.n == 1) {
919 		return pv_get_strval(msg, param, res, &_pres_subs_last_sub->pres_uri);
920 	} else if(param->pvn.u.isname.name.n == 2) {
921 		return pv_get_strval(msg, param, res, &_pres_subs_last_sub->to_user);
922 	} else if(param->pvn.u.isname.name.n == 3) {
923 		return pv_get_strval(msg, param, res, &_pres_subs_last_sub->to_domain);
924 	} else if(param->pvn.u.isname.name.n == 4) {
925 		return pv_get_strval(msg, param, res, &_pres_subs_last_sub->from_user);
926 	} else if(param->pvn.u.isname.name.n == 5) {
927 		return pv_get_strval(
928 				msg, param, res, &_pres_subs_last_sub->from_domain);
929 	} else if(param->pvn.u.isname.name.n == 6) {
930 		return pv_get_strval(
931 				msg, param, res, &_pres_subs_last_sub->watcher_user);
932 	} else if(param->pvn.u.isname.name.n == 7) {
933 		return pv_get_strval(
934 				msg, param, res, &_pres_subs_last_sub->watcher_domain);
935 	} else if(param->pvn.u.isname.name.n == 8) {
936 		return pv_get_strval(
937 				msg, param, res, &_pres_subs_last_sub->event->name);
938 	} else if(param->pvn.u.isname.name.n == 9) {
939 		return pv_get_strval(msg, param, res, &_pres_subs_last_sub->event_id);
940 	} else if(param->pvn.u.isname.name.n == 10) {
941 		return pv_get_strval(msg, param, res, &_pres_subs_last_sub->to_tag);
942 	} else if(param->pvn.u.isname.name.n == 11) {
943 		return pv_get_strval(msg, param, res, &_pres_subs_last_sub->from_tag);
944 	} else if(param->pvn.u.isname.name.n == 12) {
945 		return pv_get_strval(msg, param, res, &_pres_subs_last_sub->callid);
946 	} else if(param->pvn.u.isname.name.n == 13) {
947 		return pv_get_uintval(
948 				msg, param, res, _pres_subs_last_sub->remote_cseq);
949 	} else if(param->pvn.u.isname.name.n == 14) {
950 		return pv_get_uintval(msg, param, res, _pres_subs_last_sub->local_cseq);
951 	} else if(param->pvn.u.isname.name.n == 15) {
952 		return pv_get_strval(msg, param, res, &_pres_subs_last_sub->contact);
953 	} else if(param->pvn.u.isname.name.n == 16) {
954 		return pv_get_strval(
955 				msg, param, res, &_pres_subs_last_sub->local_contact);
956 	} else if(param->pvn.u.isname.name.n == 17) {
957 		return pv_get_strval(
958 				msg, param, res, &_pres_subs_last_sub->record_route);
959 	} else if(param->pvn.u.isname.name.n == 18) {
960 		return pv_get_uintval(msg, param, res, _pres_subs_last_sub->expires);
961 	} else if(param->pvn.u.isname.name.n == 19) {
962 		return pv_get_uintval(msg, param, res, _pres_subs_last_sub->status);
963 	} else if(param->pvn.u.isname.name.n == 20) {
964 		return pv_get_strval(msg, param, res, &_pres_subs_last_sub->reason);
965 	} else if(param->pvn.u.isname.name.n == 21) {
966 		return pv_get_sintval(msg, param, res, _pres_subs_last_sub->version);
967 	} else if(param->pvn.u.isname.name.n == 22) {
968 		return pv_get_sintval(msg, param, res, _pres_subs_last_sub->flags);
969 	} else if(param->pvn.u.isname.name.n == 23) {
970 		return pv_get_strval(msg, param, res, &_pres_subs_last_sub->user_agent);
971 	} else if(param->pvn.u.isname.name.n == 24) {
972 		return pv_get_strval(msg, param, res, &_pres_subs_last_sub->sockinfo_str);
973 	}
974 
975 	LM_ERR("unknown specifier\n");
976 	return pv_get_null(msg, param, res);
977 }
978 
handle_subscribe0(struct sip_msg * msg)979 int handle_subscribe0(struct sip_msg *msg)
980 {
981 	struct to_body *pfrom;
982 
983 	if(parse_from_uri(msg) == NULL) {
984 		LM_ERR("failed to find From header\n");
985 		if(slb.freply(msg, 400, &pu_400_rpl) < 0) {
986 			LM_ERR("while sending 400 reply\n");
987 			return -1;
988 		}
989 		return 0;
990 	}
991 	pfrom = (struct to_body *)msg->from->parsed;
992 
993 	return handle_subscribe(
994 			msg, pfrom->parsed_uri.user, pfrom->parsed_uri.host);
995 }
996 
w_handle_subscribe0(struct sip_msg * msg,char * p1,char * p2)997 int w_handle_subscribe0(struct sip_msg *msg, char *p1, char *p2)
998 {
999 	return handle_subscribe0(msg);
1000 }
1001 
handle_subscribe_uri(struct sip_msg * msg,str * wuri)1002 int handle_subscribe_uri(struct sip_msg *msg, str *wuri)
1003 {
1004 	struct sip_uri parsed_wuri;
1005 
1006 	if(parse_uri(wuri->s, wuri->len, &parsed_wuri) < 0) {
1007 		LM_ERR("failed to parse watcher URI\n");
1008 		return -1;
1009 	}
1010 
1011 	return handle_subscribe(msg, parsed_wuri.user, parsed_wuri.host);
1012 }
1013 
w_handle_subscribe(struct sip_msg * msg,char * watcher_uri,char * p2)1014 int w_handle_subscribe(struct sip_msg *msg, char *watcher_uri, char *p2)
1015 {
1016 	str wuri;
1017 
1018 	if(fixup_get_svalue(msg, (gparam_p)watcher_uri, &wuri) != 0) {
1019 		LM_ERR("invalid uri parameter\n");
1020 		return -1;
1021 	}
1022 	return handle_subscribe_uri(msg, &wuri);
1023 }
1024 
w_handle_subscribe1(struct sip_msg * msg,char * watcher_uri)1025 int w_handle_subscribe1(struct sip_msg *msg, char *watcher_uri)
1026 {
1027 	return w_handle_subscribe(msg, watcher_uri, NULL);
1028 }
1029 
handle_subscribe(struct sip_msg * msg,str watcher_user,str watcher_domain)1030 int handle_subscribe(struct sip_msg *msg, str watcher_user, str watcher_domain)
1031 {
1032 	int to_tag_gen = 0;
1033 	subs_t subs;
1034 	pres_ev_t *event = NULL;
1035 	event_t *parsed_event = NULL;
1036 	param_t *ev_param = NULL;
1037 	int found = 0;
1038 	str reason = {0, 0};
1039 	struct sip_uri uri;
1040 	int reply_code;
1041 	str reply_str;
1042 	int sent_reply = 0;
1043 
1044 	if(_pres_subs_mode==1) {
1045 		if(_pres_subs_last_sub) {
1046 			pkg_free(_pres_subs_last_sub);
1047 			_pres_subs_last_sub = NULL;
1048 		}
1049 	}
1050 
1051 	pres_counter++;
1052 
1053 	memset(&subs, 0, sizeof(subs_t));
1054 
1055 	reply_code = 500;
1056 	reply_str = pu_500_rpl;
1057 
1058 	if(parse_headers(msg, HDR_EOH_F, 0) == -1) {
1059 		LM_ERR("parsing headers\n");
1060 		reply_code = 400;
1061 		reply_str = pu_400_rpl;
1062 		goto error;
1063 	}
1064 
1065 	/* inspecting the Event header field */
1066 	if(msg->event && msg->event->body.len > 0) {
1067 		if(!msg->event->parsed && (parse_event(msg->event) < 0)) {
1068 			reply_code = 400;
1069 			reply_str = pu_400_rpl;
1070 			goto error;
1071 		}
1072 	} else {
1073 		goto bad_event;
1074 	}
1075 
1076 	/* search event in the list */
1077 	parsed_event = (event_t *)msg->event->parsed;
1078 	event = search_event(parsed_event);
1079 	if(event == NULL) {
1080 		goto bad_event;
1081 	}
1082 	subs.event = event;
1083 
1084 	/* extract the id if any*/
1085 	ev_param = parsed_event->params.list;
1086 	while(ev_param) {
1087 		if(ev_param->name.len == 2 && strncmp(ev_param->name.s, "id", 2) == 0) {
1088 			subs.event_id = ev_param->body;
1089 			break;
1090 		}
1091 		ev_param = ev_param->next;
1092 	}
1093 
1094 	if(extract_sdialog_info_ex(&subs, msg, pres_min_expires, pres_max_expires,
1095 			   &to_tag_gen, pres_server_address, watcher_user, watcher_domain,
1096 			   &reply_code, &reply_str)
1097 			< 0) {
1098 		goto error;
1099 	}
1100 
1101 	if(pres_notifier_processes > 0 && !pres_send_fast_notify
1102 			&& pa_dbf.start_transaction) {
1103 		if(pa_dbf.use_table(pa_db, &active_watchers_table) < 0) {
1104 			LM_ERR("unsuccessful use_table sql operation\n");
1105 			goto error;
1106 		}
1107 		if(pa_dbf.start_transaction(pa_db, pres_db_table_lock) < 0) {
1108 			LM_ERR("in start_transaction\n");
1109 			goto error;
1110 		}
1111 	}
1112 
1113 	/* getting presentity uri from Request-URI if initial subscribe - or else from database*/
1114 	if(to_tag_gen) {
1115 		if(!EVENT_DIALOG_SLA(parsed_event)) {
1116 			if(parse_sip_msg_uri(msg) < 0) {
1117 				LM_ERR("failed to parse R-URI\n");
1118 				return -1;
1119 			}
1120 			if(uandd_to_uri(msg->parsed_uri.user, msg->parsed_uri.host,
1121 					   &subs.pres_uri)
1122 					< 0) {
1123 				LM_ERR("failed to construct uri from user and domain\n");
1124 				goto error;
1125 			}
1126 		}
1127 	} else {
1128 		if(get_stored_info(msg, &subs, &reply_code, &reply_str) < 0) {
1129 			LM_INFO("getting stored info\n");
1130 			goto error;
1131 		}
1132 		found = 1;
1133 		reason = subs.reason;
1134 	}
1135 
1136 	/* mark that the received event is a SUBSCRIBE message */
1137 	subs.recv_event = PRES_SUBSCRIBE_RECV;
1138 
1139 	/* call event specific subscription handling */
1140 	if(event->evs_subs_handl) {
1141 		if(event->evs_subs_handl(msg) < 0) {
1142 			LM_ERR("in event specific subscription handling\n");
1143 			goto error;
1144 		}
1145 	}
1146 
1147 
1148 	/* if dialog initiation Subscribe - get subscription state */
1149 	if(to_tag_gen) {
1150 		subs.updated = NO_UPDATE_TYPE;
1151 		subs.updated_winfo = NO_UPDATE_TYPE;
1152 
1153 		if(!event->req_auth) {
1154 			subs.status = ACTIVE_STATUS;
1155 		} else {
1156 			/* query in watchers_table */
1157 			if(ps_get_subs_auth(&subs, &found) < 0) {
1158 				LM_ERR("getting subscription status from watchers table\n");
1159 				goto error;
1160 			}
1161 			if(found == 0) {
1162 				/*default 'pending' status */
1163 				subs.status = PENDING_STATUS;
1164 				subs.reason.s = NULL;
1165 				subs.reason.len = 0;
1166 				/* here a query to xcap server must be done -> new process maybe */
1167 
1168 				if(parse_uri(subs.pres_uri.s, subs.pres_uri.len, &uri) < 0) {
1169 					LM_ERR("parsing uri\n");
1170 					goto error;
1171 				}
1172 				if(subs.event->get_rules_doc(
1173 						   &uri.user, &uri.host, &subs.auth_rules_doc)
1174 						< 0) {
1175 					LM_ERR("getting rules doc\n");
1176 					goto error;
1177 				}
1178 
1179 				if(subs.event->get_auth_status(&subs) < 0) {
1180 					LM_ERR("in event specific function is_watcher_allowed\n");
1181 					goto error;
1182 				}
1183 				if(get_status_str(subs.status) == NULL) {
1184 					LM_ERR("wrong status= %d\n", subs.status);
1185 					goto error;
1186 				}
1187 
1188 				if(ps_insert_subs_auth(&subs) < 0) {
1189 					LM_ERR("while inserting record in watchers table\n");
1190 					goto error;
1191 				}
1192 			} else {
1193 				reason = subs.reason;
1194 			}
1195 		}
1196 	}
1197 
1198 	if(_pres_subs_mode==1) {
1199 		_pres_subs_last_sub = mem_copy_subs(&subs, PKG_MEM_TYPE);
1200 	}
1201 
1202 	/* check if correct status */
1203 	if(get_status_str(subs.status) == NULL) {
1204 		LM_ERR("wrong status\n");
1205 		goto error;
1206 	}
1207 	LM_DBG("subscription status= %s - %s\n", get_status_str(subs.status),
1208 			(found == 0) ? "inserted" : "found in watcher table");
1209 
1210 	if(pres_notifier_processes > 0 && !pres_send_fast_notify) {
1211 		if(update_subscription_notifier(msg, &subs, to_tag_gen, &sent_reply)
1212 				< 0) {
1213 			LM_ERR("in update_subscription_notifier\n");
1214 			goto error;
1215 		}
1216 	} else if(update_subscription(msg, &subs, to_tag_gen, &sent_reply) < 0) {
1217 		LM_ERR("in update_subscription\n");
1218 		goto error;
1219 	}
1220 
1221 	if(pres_notifier_processes > 0 && !pres_send_fast_notify
1222 			&& pa_dbf.end_transaction) {
1223 		if(pa_dbf.end_transaction(pa_db) < 0) {
1224 			LM_ERR("in end_transaction\n");
1225 			goto error;
1226 		}
1227 	}
1228 
1229 	if(subs.auth_rules_doc) {
1230 		pkg_free(subs.auth_rules_doc->s);
1231 		pkg_free(subs.auth_rules_doc);
1232 	}
1233 	if(reason.s)
1234 		pkg_free(reason.s);
1235 
1236 	if(subs.pres_uri.s)
1237 		pkg_free(subs.pres_uri.s);
1238 
1239 	if((!pres_server_address.s) || (pres_server_address.len == 0)) {
1240 		pkg_free(subs.local_contact.s);
1241 	}
1242 	if(subs.record_route.s)
1243 		pkg_free(subs.record_route.s);
1244 
1245 	return 1;
1246 
1247 bad_event:
1248 
1249 	if(parsed_event && parsed_event->name.s)
1250 		LM_NOTICE("Unsupported presence event %.*s\n", parsed_event->name.len,
1251 				parsed_event->name.s);
1252 	else
1253 		LM_ERR("Missing event header field value\n");
1254 
1255 	reply_code = BAD_EVENT_CODE;
1256 	reply_str = pu_489_rpl;
1257 
1258 error:
1259 
1260 	if(sent_reply == 0) {
1261 		if(send_error_reply(msg, reply_code, reply_str) < 0) {
1262 			LM_ERR("failed to send reply on error case\n");
1263 		}
1264 	}
1265 
1266 	if(subs.pres_uri.s)
1267 		pkg_free(subs.pres_uri.s);
1268 
1269 	if(subs.auth_rules_doc) {
1270 		if(subs.auth_rules_doc->s)
1271 			pkg_free(subs.auth_rules_doc->s);
1272 		pkg_free(subs.auth_rules_doc);
1273 	}
1274 	if(reason.s)
1275 		pkg_free(reason.s);
1276 
1277 	if(((!pres_server_address.s) || (pres_server_address.len == 0))
1278 			&& subs.local_contact.s) {
1279 		pkg_free(subs.local_contact.s);
1280 	}
1281 	if(subs.record_route.s)
1282 		pkg_free(subs.record_route.s);
1283 
1284 	if(pres_notifier_processes > 0 && pa_dbf.abort_transaction) {
1285 		if(pa_dbf.abort_transaction(pa_db) < 0)
1286 			LM_ERR("in abort_transaction\n");
1287 	}
1288 
1289 	return -1;
1290 }
1291 
1292 
extract_sdialog_info_ex(subs_t * subs,struct sip_msg * msg,uint32_t miexp,uint32_t mexp,int * to_tag_gen,str scontact,str watcher_user,str watcher_domain,int * reply_code,str * reply_str)1293 int extract_sdialog_info_ex(subs_t *subs, struct sip_msg *msg, uint32_t miexp,
1294 		uint32_t mexp, int *to_tag_gen, str scontact, str watcher_user,
1295 		str watcher_domain, int *reply_code, str *reply_str)
1296 {
1297 	str rec_route = {0, 0};
1298 	int rt = 0;
1299 	contact_body_t *b;
1300 	struct to_body *pto, TO = {0}, *pfrom = NULL;
1301 	uint32_t lexpire;
1302 	str rtag_value;
1303 	struct sip_uri uri;
1304 
1305 	/* examine the expire header field */
1306 	if(msg->expires && msg->expires->body.len > 0) {
1307 		if(!msg->expires->parsed && (parse_expires(msg->expires) < 0)) {
1308 			LM_ERR("cannot parse Expires header\n");
1309 			goto error;
1310 		}
1311 		lexpire = ((exp_body_t *)msg->expires->parsed)->val;
1312 		LM_DBG("'Expires' header found, value= %u\n", lexpire);
1313 	} else {
1314 		LM_DBG("'expires' not found; default=%u\n",
1315 				subs->event->default_expires);
1316 		lexpire = subs->event->default_expires;
1317 	}
1318 	if(lexpire > mexp)
1319 		lexpire = mexp;
1320 
1321 	if(lexpire && miexp && lexpire < miexp) {
1322 		if(pres_min_expires_action == 1) {
1323 			LM_DBG("subscription expiration invalid , requested=%u, minimum=%u,"
1324 				   " returning error \"423 Interval Too brief\"\n",
1325 					lexpire, miexp);
1326 			*reply_code = INTERVAL_TOO_BRIEF;
1327 			*reply_str = pu_423_rpl;
1328 			goto error;
1329 		} else {
1330 			LM_DBG("subscription expiration set to minimum (%u) for requested"
1331 				   " (%u)\n",
1332 					lexpire, miexp);
1333 			lexpire = miexp;
1334 		}
1335 	}
1336 
1337 	subs->expires = lexpire;
1338 
1339 	if(msg->to == NULL || msg->to->body.s == NULL) {
1340 		LM_ERR("cannot parse TO header\n");
1341 		goto error;
1342 	}
1343 	/* examine the to header */
1344 	if(msg->to->parsed != NULL) {
1345 		pto = (struct to_body *)msg->to->parsed;
1346 		LM_DBG("'To' header ALREADY PARSED: <%.*s>\n", pto->uri.len,
1347 				pto->uri.s);
1348 	} else {
1349 		parse_to(msg->to->body.s, msg->to->body.s + msg->to->body.len + 1, &TO);
1350 		if(TO.uri.len <= 0) {
1351 			LM_DBG("'To' header NOT parsed\n");
1352 			goto error;
1353 		}
1354 		pto = &TO;
1355 	}
1356 
1357 	if(pto->parsed_uri.user.s && pto->parsed_uri.host.s
1358 			&& pto->parsed_uri.user.len && pto->parsed_uri.host.len) {
1359 		subs->to_user = pto->parsed_uri.user;
1360 		subs->to_domain = pto->parsed_uri.host;
1361 	} else {
1362 		if(parse_uri(pto->uri.s, pto->uri.len, &uri) < 0) {
1363 			LM_ERR("while parsing uri\n");
1364 			goto error;
1365 		}
1366 		subs->to_user = uri.user;
1367 		subs->to_domain = uri.host;
1368 	}
1369 
1370 	/* examine the from header */
1371 	if(!msg->from || !msg->from->body.s) {
1372 		LM_DBG("cannot find 'from' header!\n");
1373 		goto error;
1374 	}
1375 	if(msg->from->parsed == NULL) {
1376 		LM_DBG("'From' header not parsed\n");
1377 		/* parsing from header */
1378 		if(parse_from_header(msg) < 0) {
1379 			LM_DBG("cannot parse From header\n");
1380 			goto error;
1381 		}
1382 	}
1383 	pfrom = (struct to_body *)msg->from->parsed;
1384 
1385 	if(pfrom->parsed_uri.user.s && pfrom->parsed_uri.host.s
1386 			&& pfrom->parsed_uri.user.len && pfrom->parsed_uri.host.len) {
1387 		subs->from_user = pfrom->parsed_uri.user;
1388 		subs->from_domain = pfrom->parsed_uri.host;
1389 	} else {
1390 		if(parse_uri(pfrom->uri.s, pfrom->uri.len, &uri) < 0) {
1391 			LM_ERR("while parsing uri\n");
1392 			goto error;
1393 		}
1394 		subs->from_user = uri.user;
1395 		subs->from_domain = uri.host;
1396 	}
1397 
1398 	subs->watcher_user = watcher_user;
1399 	subs->watcher_domain = watcher_domain;
1400 
1401 	/* get to_tag if the message does not have a to_tag*/
1402 	if(pto->tag_value.s == NULL || pto->tag_value.len == 0) {
1403 		LM_DBG("generating to_tag\n");
1404 		*to_tag_gen = 1;
1405 		rtag_value.len = 0;
1406 		if(slb.get_reply_totag(msg, &rtag_value) < 0 || rtag_value.len <= 0) {
1407 			LM_ERR("while creating to_tag\n");
1408 			goto error;
1409 		}
1410 	} else {
1411 		*to_tag_gen = 0;
1412 		rtag_value = pto->tag_value;
1413 	}
1414 	subs->to_tag = rtag_value;
1415 
1416 	if(msg->callid == NULL || msg->callid->body.s == NULL) {
1417 		LM_ERR("cannot parse callid header\n");
1418 		goto error;
1419 	}
1420 	subs->callid = msg->callid->body;
1421 
1422 	if(msg->cseq == NULL || msg->cseq->body.s == NULL) {
1423 		LM_ERR("cannot parse cseq header\n");
1424 		goto error;
1425 	}
1426 	if(str2int(&(get_cseq(msg)->number), &subs->remote_cseq) != 0) {
1427 		LM_ERR("cannot parse cseq number\n");
1428 		goto error;
1429 	}
1430 	if(msg->contact == NULL || msg->contact->body.s == NULL) {
1431 		LM_ERR("cannot parse contact header\n");
1432 		goto error;
1433 	}
1434 	if(parse_contact(msg->contact) < 0) {
1435 		LM_ERR(" cannot parse contact"
1436 			   " header\n");
1437 		goto error;
1438 	}
1439 	b = (contact_body_t *)msg->contact->parsed;
1440 
1441 	if(b == NULL) {
1442 		LM_ERR("cannot parse contact header\n");
1443 		goto error;
1444 	}
1445 	if(b->star || b->contacts == NULL) {
1446 		LM_ERR("Wrong contact header\n");
1447 		goto error;
1448 	}
1449 
1450 	subs->contact = b->contacts->uri;
1451 
1452 	LM_DBG("subs->contact= %.*s - len = %d\n", subs->contact.len,
1453 			subs->contact.s, subs->contact.len);
1454 
1455 	if(EVENT_DIALOG_SLA(subs->event->evp)) {
1456 		/* user_contact@from_domain */
1457 		if(parse_uri(subs->contact.s, subs->contact.len, &uri) < 0) {
1458 			LM_ERR("failed to parse contact uri\n");
1459 			goto error;
1460 		}
1461 		if(uandd_to_uri(uri.user, subs->from_domain, &subs->pres_uri) < 0) {
1462 			LM_ERR("failed to construct uri\n");
1463 			goto error;
1464 		}
1465 		LM_DBG("dialog pres_uri= %.*s\n", subs->pres_uri.len, subs->pres_uri.s);
1466 	}
1467 
1468 	/*process record route and add it to a string*/
1469 	if(*to_tag_gen && msg->record_route != NULL) {
1470 		rt = print_rr_body(msg->record_route, &rec_route, 0, 0);
1471 		if(rt != 0) {
1472 			LM_ERR("processing the record route [%d]\n", rt);
1473 			rec_route.s = NULL;
1474 			rec_route.len = 0;
1475 			//	goto error;
1476 		}
1477 	}
1478 	subs->record_route = rec_route;
1479 
1480 	subs->sockinfo_str = msg->rcv.bind_address->sock_str;
1481 
1482 	if(pfrom->tag_value.s == NULL || pfrom->tag_value.len == 0) {
1483 		LM_ERR("no from tag value present\n");
1484 		goto error;
1485 	}
1486 	subs->from_tag = pfrom->tag_value;
1487 
1488 	subs->version = 1;
1489 
1490 	if((!scontact.s) || (scontact.len == 0)) {
1491 		if(ps_fill_local_contact(msg, &subs->local_contact) < 0) {
1492 			LM_ERR("cannot get local contact address\n");
1493 			goto error;
1494 		}
1495 	} else {
1496 		subs->local_contact = scontact;
1497 	}
1498 
1499 	if(parse_headers(msg, HDR_USERAGENT_F, 0) != -1 && msg->user_agent
1500 			&& msg->user_agent->body.len > 0
1501 			&& msg->user_agent->body.len < MAX_UA_SIZE) {
1502 		subs->user_agent = msg->user_agent->body;
1503 	}
1504 	getbflagsval(0, &subs->flags);
1505 
1506 	free_to_params(&TO);
1507 	return 0;
1508 
1509 error:
1510 	free_to_params(&TO);
1511 	return -1;
1512 }
1513 
extract_sdialog_info(subs_t * subs,struct sip_msg * msg,int mexp,int * to_tag_gen,str scontact,str watcher_user,str watcher_domain)1514 int extract_sdialog_info(subs_t *subs, struct sip_msg *msg, int mexp,
1515 		int *to_tag_gen, str scontact, str watcher_user, str watcher_domain)
1516 {
1517 	int reply_code = 500;
1518 	str reply_str = pu_500_rpl;
1519 	return extract_sdialog_info_ex(subs, msg, pres_min_expires, mexp, to_tag_gen,
1520 			scontact, watcher_user, watcher_domain, &reply_code, &reply_str);
1521 }
1522 
get_stored_info(struct sip_msg * msg,subs_t * subs,int * reply_code,str * reply_str)1523 int get_stored_info(
1524 		struct sip_msg *msg, subs_t *subs, int *reply_code, str *reply_str)
1525 {
1526 	str pres_uri = {0, 0}, reason = {0, 0};
1527 	subs_t *s;
1528 	int i;
1529 	unsigned int hash_code;
1530 
1531 	if(pres_subs_dbmode == DB_ONLY) {
1532 		return get_database_info(msg, subs, reply_code, reply_str);
1533 	}
1534 
1535 	/* first try to_user== pres_user and to_domain== pres_domain */
1536 	if(subs->pres_uri.s == NULL) {
1537 		uandd_to_uri(subs->to_user, subs->to_domain, &pres_uri);
1538 		if(pres_uri.s == NULL) {
1539 			LM_ERR("creating uri from user and domain\n");
1540 			return -1;
1541 		}
1542 	} else
1543 		pres_uri = subs->pres_uri;
1544 
1545 	hash_code = core_case_hash(&pres_uri, &subs->event->name, shtable_size);
1546 	lock_get(&subs_htable[hash_code].lock);
1547 	s = search_shtable(
1548 			subs_htable, subs->callid, subs->to_tag, subs->from_tag, hash_code);
1549 	if(s)
1550 		goto found_rec;
1551 
1552 	lock_release(&subs_htable[hash_code].lock);
1553 
1554 	if(subs->pres_uri.s)
1555 		goto not_found;
1556 
1557 	pkg_free(pres_uri.s);
1558 	pres_uri.s = NULL;
1559 
1560 	LM_DBG("record not found using R-URI search iteratively\n");
1561 	/* take one row at a time */
1562 	for(i = 0; i < shtable_size; i++) {
1563 		lock_get(&subs_htable[i].lock);
1564 		s = search_shtable(
1565 				subs_htable, subs->callid, subs->to_tag, subs->from_tag, i);
1566 		if(s) {
1567 			pres_uri.s = (char *)pkg_malloc(s->pres_uri.len * sizeof(char));
1568 			if(pres_uri.s == NULL) {
1569 				lock_release(&subs_htable[i].lock);
1570 				ERR_MEM(PKG_MEM_STR);
1571 			}
1572 			memcpy(pres_uri.s, s->pres_uri.s, s->pres_uri.len);
1573 			pres_uri.len = s->pres_uri.len;
1574 
1575 			hash_code = i;
1576 			break;
1577 		}
1578 		lock_release(&subs_htable[i].lock);
1579 	}
1580 
1581 	if(!s)
1582 		goto not_found;
1583 
1584 found_rec:
1585 
1586 	LM_DBG("Record found in hash_table\n");
1587 
1588 	if(subs->pres_uri.s == NULL)
1589 		subs->pres_uri = pres_uri;
1590 
1591 	subs->version = s->version + 1;
1592 	subs->status = s->status;
1593 	if(s->reason.s && s->reason.len) {
1594 		reason.s = (char *)pkg_malloc(s->reason.len * sizeof(char));
1595 		if(reason.s == NULL) {
1596 			lock_release(&subs_htable[hash_code].lock);
1597 			ERR_MEM(PKG_MEM_STR);
1598 		}
1599 		memcpy(reason.s, s->reason.s, s->reason.len);
1600 		reason.len = s->reason.len;
1601 		subs->reason = reason;
1602 	}
1603 	if(s->record_route.s && s->record_route.len) {
1604 		subs->record_route.s =
1605 				(char *)pkg_malloc(s->record_route.len * sizeof(char));
1606 		if(subs->record_route.s == NULL) {
1607 			lock_release(&subs_htable[hash_code].lock);
1608 			ERR_MEM(PKG_MEM_STR);
1609 		}
1610 		memcpy(subs->record_route.s, s->record_route.s, s->record_route.len);
1611 		subs->record_route.len = s->record_route.len;
1612 	}
1613 
1614 	subs->local_cseq = s->local_cseq + 1;
1615 
1616 	if(subs->remote_cseq + pres_cseq_offset <= s->remote_cseq) {
1617 		LM_ERR("wrong sequence number;received: %d - stored: %d\n",
1618 				subs->remote_cseq, s->remote_cseq);
1619 
1620 		*reply_code = 400;
1621 		*reply_str = pu_400_rpl;
1622 
1623 		lock_release(&subs_htable[hash_code].lock);
1624 		goto error;
1625 	}
1626 	lock_release(&subs_htable[hash_code].lock);
1627 
1628 	return 0;
1629 
1630 not_found:
1631 
1632 	LM_INFO("record not found in hash_table\n");
1633 	*reply_code = 481;
1634 	*reply_str = pu_481_rpl;
1635 
1636 	return -1;
1637 
1638 error:
1639 	if(subs->reason.s)
1640 		pkg_free(subs->reason.s);
1641 	subs->reason.s = NULL;
1642 	if(subs->record_route.s)
1643 		pkg_free(subs->record_route.s);
1644 	subs->record_route.s = NULL;
1645 	return -1;
1646 }
1647 
get_database_info(struct sip_msg * msg,subs_t * subs,int * reply_code,str * reply_str)1648 int get_database_info(
1649 		struct sip_msg *msg, subs_t *subs, int *reply_code, str *reply_str)
1650 {
1651 	db_key_t query_cols[3];
1652 	db_val_t query_vals[3];
1653 	db_key_t result_cols[10];
1654 	db1_res_t *result = NULL;
1655 	db_row_t *row;
1656 	db_val_t *row_vals;
1657 	int n_query_cols = 0;
1658 	int n_result_cols = 0;
1659 	int remote_cseq_col = 0, local_cseq_col = 0, status_col, reason_col;
1660 	int record_route_col, version_col, pres_uri_col;
1661 	int updated_col, updated_winfo_col;
1662 	int flags_col;
1663 	unsigned int remote_cseq;
1664 	str pres_uri, record_route;
1665 	str reason;
1666 	db_query_f query_fn = pa_dbf.query;
1667 
1668 	query_cols[n_query_cols] = &str_callid_col;
1669 	query_vals[n_query_cols].type = DB1_STR;
1670 	query_vals[n_query_cols].nul = 0;
1671 	query_vals[n_query_cols].val.str_val = subs->callid;
1672 	n_query_cols++;
1673 
1674 	query_cols[n_query_cols] = &str_to_tag_col;
1675 	query_vals[n_query_cols].type = DB1_STR;
1676 	query_vals[n_query_cols].nul = 0;
1677 	query_vals[n_query_cols].val.str_val = subs->to_tag;
1678 	n_query_cols++;
1679 
1680 	query_cols[n_query_cols] = &str_from_tag_col;
1681 	query_vals[n_query_cols].type = DB1_STR;
1682 	query_vals[n_query_cols].nul = 0;
1683 	query_vals[n_query_cols].val.str_val = subs->from_tag;
1684 	n_query_cols++;
1685 
1686 	result_cols[pres_uri_col = n_result_cols++] = &str_presentity_uri_col;
1687 	result_cols[remote_cseq_col = n_result_cols++] = &str_remote_cseq_col;
1688 	result_cols[local_cseq_col = n_result_cols++] = &str_local_cseq_col;
1689 	result_cols[status_col = n_result_cols++] = &str_status_col;
1690 	result_cols[reason_col = n_result_cols++] = &str_reason_col;
1691 	result_cols[record_route_col = n_result_cols++] = &str_record_route_col;
1692 	result_cols[version_col = n_result_cols++] = &str_version_col;
1693 	result_cols[updated_col = n_result_cols++] = &str_updated_col;
1694 	result_cols[updated_winfo_col = n_result_cols++] = &str_updated_winfo_col;
1695 	result_cols[flags_col = n_result_cols++] = &str_flags_col;
1696 
1697 	if(pa_dbf.use_table(pa_db, &active_watchers_table) < 0) {
1698 		LM_ERR("unsuccessful use_table sql operation\n");
1699 		return -1;
1700 	}
1701 
1702 	if(pres_notifier_processes > 0 && pa_dbf.start_transaction)
1703 		query_fn = pa_dbf.query_lock ? pa_dbf.query_lock : pa_dbf.query;
1704 
1705 	if(query_fn(pa_db, query_cols, 0, query_vals, result_cols, n_query_cols,
1706 			   n_result_cols, 0, &result)
1707 			< 0) {
1708 		LM_ERR("querying subscription dialog\n");
1709 		if(result)
1710 			pa_dbf.free_result(pa_db, result);
1711 		return -1;
1712 	}
1713 	if(result == NULL)
1714 		return -1;
1715 
1716 	if(result && result->n <= 0) {
1717 		LM_INFO("No matching subscription dialog found in database\n");
1718 
1719 		pa_dbf.free_result(pa_db, result);
1720 		*reply_code = 481;
1721 		*reply_str = pu_481_rpl;
1722 
1723 		return -1;
1724 	}
1725 
1726 	row = &result->rows[0];
1727 	row_vals = ROW_VALUES(row);
1728 	remote_cseq = row_vals[remote_cseq_col].val.int_val;
1729 
1730 	if(subs->remote_cseq + pres_cseq_offset <= remote_cseq) {
1731 		LM_ERR("wrong sequence number received: %d - stored: %d\n",
1732 				subs->remote_cseq, remote_cseq);
1733 		*reply_code = 400;
1734 		*reply_str = pu_400_rpl;
1735 		pa_dbf.free_result(pa_db, result);
1736 		return -1;
1737 	}
1738 
1739 	subs->status = row_vals[status_col].val.int_val;
1740 	reason.s = (char *)row_vals[reason_col].val.string_val;
1741 	if(reason.s) {
1742 		reason.len = strlen(reason.s);
1743 		if(reason.len > 0) {
1744 			subs->reason.s = (char *)pkg_malloc(reason.len * sizeof(char));
1745 			if(subs->reason.s == NULL) {
1746 				ERR_MEM(PKG_MEM_STR);
1747 			}
1748 			memcpy(subs->reason.s, reason.s, reason.len);
1749 			subs->reason.len = reason.len;
1750 		}
1751 	}
1752 
1753 	subs->local_cseq = row_vals[local_cseq_col].val.int_val + 1;
1754 	subs->version = row_vals[version_col].val.int_val + 1;
1755 
1756 	if(!EVENT_DIALOG_SLA(subs->event->evp)) {
1757 		pres_uri.s = (char *)row_vals[pres_uri_col].val.string_val;
1758 		pres_uri.len = strlen(pres_uri.s);
1759 		if(pres_uri.len > 0) {
1760 			subs->pres_uri.s = (char *)pkg_malloc(pres_uri.len * sizeof(char));
1761 			if(subs->pres_uri.s == NULL) {
1762 				if(subs->reason.s)
1763 					pkg_free(subs->reason.s);
1764 				ERR_MEM(PKG_MEM_STR);
1765 			}
1766 			memcpy(subs->pres_uri.s, pres_uri.s, pres_uri.len);
1767 			subs->pres_uri.len = pres_uri.len;
1768 		}
1769 	}
1770 
1771 	record_route.s = (char *)row_vals[record_route_col].val.string_val;
1772 	if(record_route.s) {
1773 		record_route.len = strlen(record_route.s);
1774 		if(record_route.len > 0) {
1775 			subs->record_route.s =
1776 					(char *)pkg_malloc(record_route.len * sizeof(char));
1777 			if(subs->record_route.s == NULL) {
1778 				ERR_MEM(PKG_MEM_STR);
1779 			}
1780 			memcpy(subs->record_route.s, record_route.s, record_route.len);
1781 			subs->record_route.len = record_route.len;
1782 		}
1783 	}
1784 
1785 	subs->updated = row_vals[updated_col].val.int_val;
1786 	subs->updated_winfo = row_vals[updated_winfo_col].val.int_val;
1787 	subs->flags = row_vals[flags_col].val.int_val;
1788 
1789 	pa_dbf.free_result(pa_db, result);
1790 	result = NULL;
1791 
1792 	return 0;
1793 error:
1794 	if(result)
1795 		pa_dbf.free_result(pa_db, result);
1796 
1797 	return -1;
1798 }
1799 
1800 
handle_expired_subs(subs_t * s)1801 int handle_expired_subs(subs_t *s)
1802 {
1803 	/* send Notify with state=terminated;reason=timeout */
1804 
1805 	s->status = TERMINATED_STATUS;
1806 	s->reason.s = "timeout";
1807 	s->reason.len = 7;
1808 	s->expires = 0;
1809 	s->local_cseq++;
1810 
1811 	if(send_notify_request(s, NULL, NULL, 1) < 0) {
1812 		LM_ERR("send Notify not successful\n");
1813 		return -1;
1814 	}
1815 
1816 	return 0;
1817 }
1818 
update_db_subs_timer_notifier(void)1819 void update_db_subs_timer_notifier(void)
1820 {
1821 	db_key_t query_cols[2], result_cols[3];
1822 	db_val_t query_vals[2], *values;
1823 	db_op_t query_ops[2];
1824 	db_row_t *rows;
1825 	db1_res_t *result = NULL;
1826 	int n_query_cols = 0, n_result_cols = 0;
1827 	int r_callid_col = 0, r_to_tag_col = 0, r_from_tag_col = 0;
1828 	int i, res;
1829 	subs_t subs;
1830 
1831 	if(pa_db == NULL) {
1832 		LM_ERR("null database connection\n");
1833 		goto error;
1834 	}
1835 
1836 	if(pa_dbf.use_table(pa_db, &active_watchers_table) < 0) {
1837 		LM_ERR("use table failed\n");
1838 		goto error;
1839 	}
1840 
1841 	query_cols[n_query_cols] = &str_expires_col;
1842 	query_vals[n_query_cols].type = DB1_INT;
1843 	query_vals[n_query_cols].nul = 0;
1844 	query_vals[n_query_cols].val.int_val = (int)time(NULL) - pres_expires_offset;
1845 	query_ops[n_query_cols] = OP_LT;
1846 	n_query_cols++;
1847 
1848 	query_cols[n_query_cols] = &str_updated_col;
1849 	query_vals[n_query_cols].type = DB1_INT;
1850 	query_vals[n_query_cols].nul = 0;
1851 	query_vals[n_query_cols].val.int_val = NO_UPDATE_TYPE;
1852 	query_ops[n_query_cols] = OP_EQ;
1853 	n_query_cols++;
1854 
1855 	result_cols[r_callid_col = n_result_cols++] = &str_callid_col;
1856 	result_cols[r_to_tag_col = n_result_cols++] = &str_to_tag_col;
1857 	result_cols[r_from_tag_col = n_result_cols++] = &str_from_tag_col;
1858 
1859 	if(pa_dbf.start_transaction) {
1860 		if(pa_dbf.start_transaction(pa_db, pres_db_table_lock) < 0) {
1861 			LM_ERR("in start_transaction\n");
1862 			goto error;
1863 		}
1864 	}
1865 
1866 	if(pa_dbf.query_lock)
1867 		res = db_fetch_query_lock(&pa_dbf, pres_fetch_rows, pa_db, query_cols,
1868 				query_ops, query_vals, result_cols, n_query_cols, n_result_cols,
1869 				0, &result);
1870 	else
1871 		res = db_fetch_query(&pa_dbf, pres_fetch_rows, pa_db, query_cols,
1872 				query_ops, query_vals, result_cols, n_query_cols, n_result_cols,
1873 				0, &result);
1874 	if(res < 0) {
1875 		LM_ERR("Can't query db\n");
1876 		goto error;
1877 	}
1878 
1879 	if(result == NULL) {
1880 		LM_ERR("bad result\n");
1881 		goto error;
1882 	}
1883 
1884 	do {
1885 		rows = RES_ROWS(result);
1886 
1887 		for(i = 0; i < RES_ROW_N(result); i++) {
1888 			values = ROW_VALUES(&rows[i]);
1889 			memset(&subs, 0, sizeof(subs_t));
1890 
1891 			subs.callid.s = (char *)VAL_STRING(&values[r_callid_col]);
1892 			subs.callid.len = strlen(subs.callid.s);
1893 			subs.to_tag.s = (char *)VAL_STRING(&values[r_to_tag_col]);
1894 			subs.to_tag.len = strlen(subs.to_tag.s);
1895 			subs.from_tag.s = (char *)VAL_STRING(&values[r_from_tag_col]);
1896 			subs.from_tag.len = strlen(subs.from_tag.s);
1897 
1898 			set_updated(&subs);
1899 		}
1900 	} while(db_fetch_next(&pa_dbf, pres_fetch_rows, pa_db, &result) == 1
1901 			&& RES_ROW_N(result) > 0);
1902 
1903 	if(pa_dbf.end_transaction) {
1904 		if(pa_dbf.end_transaction(pa_db) < 0) {
1905 			LM_ERR("in end_transaction\n");
1906 			goto error;
1907 		}
1908 	}
1909 
1910 error:
1911 	if(result)
1912 		pa_dbf.free_result(pa_db, result);
1913 
1914 	if(pa_dbf.abort_transaction) {
1915 		if(pa_dbf.abort_transaction(pa_db) < 0)
1916 			LM_ERR("in abort_transaction\n");
1917 	}
1918 }
1919 
update_db_subs_timer_dbonly(void)1920 void update_db_subs_timer_dbonly(void)
1921 {
1922 	db_op_t qops[1];
1923 	db_key_t qcols[1];
1924 	db_val_t qvals[1];
1925 	db_key_t result_cols[18];
1926 	int pres_uri_col, to_user_col, to_domain_col, from_user_col,
1927 			from_domain_col, callid_col, totag_col, fromtag_col, event_col,
1928 			event_id_col, local_cseq_col, expires_col, rr_col, sockinfo_col,
1929 			contact_col, lcontact_col, watcher_user_col, watcher_domain_col;
1930 	int n_result_cols = 0;
1931 	db1_res_t *result = NULL;
1932 	db_row_t *rows;
1933 	db_val_t *row_vals = NULL;
1934 	int i, res;
1935 	subs_t s, *s_new, *s_array = NULL, *s_del;
1936 	str ev_name;
1937 	pres_ev_t *event;
1938 
1939 	LM_DBG("update_db_subs_timer_dbonly: start\n");
1940 
1941 	qcols[0] = &str_expires_col;
1942 	qvals[0].type = DB1_INT;
1943 	qvals[0].nul = 0;
1944 	qvals[0].val.int_val = (int)time(NULL) - pres_expires_offset;
1945 	qops[0] = OP_LT;
1946 
1947 	/* query the expired subscriptions */
1948 	result_cols[pres_uri_col = n_result_cols++] = &str_presentity_uri_col;
1949 	result_cols[expires_col = n_result_cols++] = &str_expires_col;
1950 	result_cols[event_col = n_result_cols++] = &str_event_col;
1951 	result_cols[event_id_col = n_result_cols++] = &str_event_id_col;
1952 	result_cols[to_user_col = n_result_cols++] = &str_to_user_col;
1953 	result_cols[to_domain_col = n_result_cols++] = &str_to_domain_col;
1954 	result_cols[from_user_col = n_result_cols++] = &str_from_user_col;
1955 	result_cols[from_domain_col = n_result_cols++] = &str_from_domain_col;
1956 	result_cols[watcher_user_col = n_result_cols++] = &str_watcher_username_col;
1957 	result_cols[watcher_domain_col = n_result_cols++] = &str_watcher_domain_col;
1958 	result_cols[callid_col = n_result_cols++] = &str_callid_col;
1959 	result_cols[totag_col = n_result_cols++] = &str_to_tag_col;
1960 	result_cols[fromtag_col = n_result_cols++] = &str_from_tag_col;
1961 	result_cols[local_cseq_col = n_result_cols++] = &str_local_cseq_col;
1962 	result_cols[rr_col = n_result_cols++] = &str_record_route_col;
1963 	result_cols[sockinfo_col = n_result_cols++] = &str_socket_info_col;
1964 	result_cols[contact_col = n_result_cols++] = &str_contact_col;
1965 	result_cols[lcontact_col = n_result_cols++] = &str_local_contact_col;
1966 
1967 	if(pa_dbf.use_table(pa_db, &active_watchers_table) < 0) {
1968 		LM_ERR("sql use table failed\n");
1969 		return;
1970 	}
1971 
1972 	res = db_fetch_query(&pa_dbf, pres_fetch_rows, pa_db, qcols, qops, qvals,
1973 			result_cols, 1, n_result_cols, 0, &result);
1974 	if(res < 0) {
1975 		LM_ERR("failed to query database for expired subscriptions\n");
1976 		if(result) {
1977 			pa_dbf.free_result(pa_db, result);
1978 		}
1979 		return;
1980 	}
1981 
1982 	if(result == NULL) {
1983 		LM_DBG("no results returned\n");
1984 		return;
1985 	}
1986 
1987 	LM_DBG("processing %d dialogs\n", RES_ROW_N(result));
1988 	s_array = NULL;
1989 	rows = RES_ROWS(result);
1990 	for(i = 0; i < RES_ROW_N(result); i++) {
1991 		row_vals = ROW_VALUES(&rows[i]);
1992 
1993 		memset(&s, 0, sizeof(subs_t));
1994 
1995 		s.pres_uri.s = (char *)row_vals[pres_uri_col].val.string_val;
1996 		s.pres_uri.len = strlen(s.pres_uri.s);
1997 
1998 		s.to_user.s = (char *)row_vals[to_user_col].val.string_val;
1999 		s.to_user.len = strlen(s.to_user.s);
2000 
2001 		s.to_domain.s = (char *)row_vals[to_domain_col].val.string_val;
2002 		s.to_domain.len = strlen(s.to_domain.s);
2003 
2004 		s.from_user.s = (char *)row_vals[from_user_col].val.string_val;
2005 		s.from_user.len = strlen(s.from_user.s);
2006 
2007 		s.from_domain.s = (char *)row_vals[from_domain_col].val.string_val;
2008 		s.from_domain.len = strlen(s.from_domain.s);
2009 
2010 		s.watcher_user.s = (char *)row_vals[watcher_user_col].val.string_val;
2011 		s.watcher_user.len = strlen(s.watcher_user.s);
2012 
2013 		s.watcher_domain.s =
2014 				(char *)row_vals[watcher_domain_col].val.string_val;
2015 		s.watcher_domain.len = strlen(s.watcher_domain.s);
2016 
2017 		s.event_id.s = (char *)row_vals[event_id_col].val.string_val;
2018 		s.event_id.len = (s.event_id.s) ? strlen(s.event_id.s) : 0;
2019 
2020 		s.to_tag.s = (char *)row_vals[totag_col].val.string_val;
2021 		s.to_tag.len = strlen(s.to_tag.s);
2022 
2023 		s.from_tag.s = (char *)row_vals[fromtag_col].val.string_val;
2024 		s.from_tag.len = strlen(s.from_tag.s);
2025 
2026 		s.callid.s = (char *)row_vals[callid_col].val.string_val;
2027 		s.callid.len = strlen(s.callid.s);
2028 
2029 		s.record_route.s = (char *)row_vals[rr_col].val.string_val;
2030 		s.record_route.len = (s.record_route.s) ? strlen(s.record_route.s) : 0;
2031 
2032 		s.contact.s = (char *)row_vals[contact_col].val.string_val;
2033 		s.contact.len = strlen(s.contact.s);
2034 
2035 		s.sockinfo_str.s = (char *)row_vals[sockinfo_col].val.string_val;
2036 		s.sockinfo_str.len = s.sockinfo_str.s ? strlen(s.sockinfo_str.s) : 0;
2037 
2038 		s.local_contact.s = (char *)row_vals[lcontact_col].val.string_val;
2039 		s.local_contact.len = s.local_contact.s ? strlen(s.local_contact.s) : 0;
2040 
2041 		ev_name.s = (char *)row_vals[event_col].val.string_val;
2042 		ev_name.len = strlen(ev_name.s);
2043 
2044 		event = contains_event(&ev_name, 0);
2045 		if(event == NULL) {
2046 			LM_ERR("Wrong event in database %.*s\n", ev_name.len, ev_name.s);
2047 			continue;
2048 		}
2049 		s.event = event;
2050 
2051 		s.local_cseq = row_vals[local_cseq_col].val.int_val + 1;
2052 		s.expires = 0;
2053 
2054 		s_new = mem_copy_subs(&s, PKG_MEM_TYPE);
2055 		if(s_new == NULL) {
2056 			LM_ERR("while copying subs_t structure\n");
2057 			continue;
2058 		}
2059 		s_new->next = s_array;
2060 		s_array = s_new;
2061 		printf_subs(s_new);
2062 	}
2063 	pa_dbf.free_result(pa_db, result);
2064 
2065 	s_new = s_array;
2066 	while(s_new) {
2067 		handle_expired_subs(s_new);
2068 		s_del = s_new;
2069 		s_new = s_new->next;
2070 		pkg_free(s_del);
2071 	}
2072 }
2073 
update_db_subs_timer_dbnone(int no_lock)2074 void update_db_subs_timer_dbnone(int no_lock)
2075 {
2076 	int i;
2077 	int now = (int)time(NULL);
2078 	subs_t *s = NULL, *prev_s = NULL, *del_s;
2079 
2080 	LM_DBG("update_db_subs_timer_dbnone: start\n");
2081 
2082 	for(i = 0; i < shtable_size; i++) {
2083 		if(!no_lock)
2084 			lock_get(&subs_htable[i].lock);
2085 
2086 		prev_s = subs_htable[i].entries;
2087 		s = prev_s->next;
2088 
2089 		while(s) {
2090 			printf_subs(s);
2091 			if(s->expires < now - pres_expires_offset) {
2092 				LM_DBG("Found expired record\n");
2093 				if(!no_lock) {
2094 					if(handle_expired_subs(s) < 0) {
2095 						LM_ERR("in function handle_expired_record\n");
2096 					}
2097 				}
2098 				del_s = s;
2099 				s = s->next;
2100 				prev_s->next = s;
2101 
2102 				if(del_s->contact.s)
2103 					shm_free(del_s->contact.s);
2104 				shm_free(del_s);
2105 				continue;
2106 			}
2107 			prev_s = s;
2108 			s = s->next;
2109 		}
2110 		if(!no_lock)
2111 			lock_release(&subs_htable[i].lock);
2112 	}
2113 }
2114 
2115 
update_db_subs_timer(db1_con_t * db,db_func_t * dbf,shtable_t hash_table,int htable_size,int no_lock,handle_expired_func_t handle_expired_func)2116 void update_db_subs_timer(db1_con_t *db, db_func_t *dbf, shtable_t hash_table,
2117 		int htable_size, int no_lock, handle_expired_func_t handle_expired_func)
2118 {
2119 	db_key_t query_cols[25], update_cols[8];
2120 	db_val_t query_vals[25], update_vals[8];
2121 	db_op_t update_ops[1];
2122 	subs_t *del_s;
2123 	int pres_uri_col, to_user_col, to_domain_col, from_user_col,
2124 			from_domain_col, callid_col, totag_col, fromtag_col, event_col,
2125 			status_col, event_id_col, local_cseq_col, remote_cseq_col,
2126 			expires_col, record_route_col, contact_col, local_contact_col,
2127 			version_col, socket_info_col, reason_col, watcher_user_col,
2128 			watcher_domain_col, updated_col, updated_winfo_col, user_agent_col;
2129 	int u_expires_col, u_local_cseq_col, u_remote_cseq_col, u_version_col,
2130 			u_reason_col, u_status_col, u_contact_col, u_record_route_col;
2131 	int i;
2132 	subs_t *s = NULL, *prev_s = NULL;
2133 	int n_query_cols = 0, n_update_cols = 0;
2134 	int n_query_update;
2135 	int now = (int)time(NULL);
2136 
2137 	LM_DBG("update_db_subs_timer: start\n");
2138 
2139 	query_cols[pres_uri_col = n_query_cols] = &str_presentity_uri_col;
2140 	query_vals[pres_uri_col].type = DB1_STR;
2141 	query_vals[pres_uri_col].nul = 0;
2142 	n_query_cols++;
2143 
2144 	query_cols[callid_col = n_query_cols] = &str_callid_col;
2145 	query_vals[callid_col].type = DB1_STR;
2146 	query_vals[callid_col].nul = 0;
2147 	n_query_cols++;
2148 
2149 	query_cols[totag_col = n_query_cols] = &str_to_tag_col;
2150 	query_vals[totag_col].type = DB1_STR;
2151 	query_vals[totag_col].nul = 0;
2152 	n_query_cols++;
2153 
2154 	query_cols[fromtag_col = n_query_cols] = &str_from_tag_col;
2155 	query_vals[fromtag_col].type = DB1_STR;
2156 	query_vals[fromtag_col].nul = 0;
2157 	n_query_cols++;
2158 
2159 	n_query_update = n_query_cols;
2160 
2161 	query_cols[to_user_col = n_query_cols] = &str_to_user_col;
2162 	query_vals[to_user_col].type = DB1_STR;
2163 	query_vals[to_user_col].nul = 0;
2164 	n_query_cols++;
2165 
2166 	query_cols[to_domain_col = n_query_cols] = &str_to_domain_col;
2167 	query_vals[to_domain_col].type = DB1_STR;
2168 	query_vals[to_domain_col].nul = 0;
2169 	n_query_cols++;
2170 
2171 	query_cols[from_user_col = n_query_cols] = &str_from_user_col;
2172 	query_vals[from_user_col].type = DB1_STR;
2173 	query_vals[from_user_col].nul = 0;
2174 	n_query_cols++;
2175 
2176 	query_cols[from_domain_col = n_query_cols] = &str_from_domain_col;
2177 	query_vals[from_domain_col].type = DB1_STR;
2178 	query_vals[from_domain_col].nul = 0;
2179 	n_query_cols++;
2180 
2181 	query_cols[watcher_user_col = n_query_cols] = &str_watcher_username_col;
2182 	query_vals[watcher_user_col].type = DB1_STR;
2183 	query_vals[watcher_user_col].nul = 0;
2184 	n_query_cols++;
2185 
2186 	query_cols[watcher_domain_col = n_query_cols] = &str_watcher_domain_col;
2187 	query_vals[watcher_domain_col].type = DB1_STR;
2188 	query_vals[watcher_domain_col].nul = 0;
2189 	n_query_cols++;
2190 
2191 	query_cols[event_col = n_query_cols] = &str_event_col;
2192 	query_vals[event_col].type = DB1_STR;
2193 	query_vals[event_col].nul = 0;
2194 	n_query_cols++;
2195 
2196 	query_cols[event_id_col = n_query_cols] = &str_event_id_col;
2197 	query_vals[event_id_col].type = DB1_STR;
2198 	query_vals[event_id_col].nul = 0;
2199 	n_query_cols++;
2200 
2201 	query_cols[local_cseq_col = n_query_cols] = &str_local_cseq_col;
2202 	query_vals[local_cseq_col].type = DB1_INT;
2203 	query_vals[local_cseq_col].nul = 0;
2204 	n_query_cols++;
2205 
2206 	query_cols[remote_cseq_col = n_query_cols] = &str_remote_cseq_col;
2207 	query_vals[remote_cseq_col].type = DB1_INT;
2208 	query_vals[remote_cseq_col].nul = 0;
2209 	n_query_cols++;
2210 
2211 	query_cols[expires_col = n_query_cols] = &str_expires_col;
2212 	query_vals[expires_col].type = DB1_INT;
2213 	query_vals[expires_col].nul = 0;
2214 	n_query_cols++;
2215 
2216 	query_cols[status_col = n_query_cols] = &str_status_col;
2217 	query_vals[status_col].type = DB1_INT;
2218 	query_vals[status_col].nul = 0;
2219 	n_query_cols++;
2220 
2221 	query_cols[reason_col = n_query_cols] = &str_reason_col;
2222 	query_vals[reason_col].type = DB1_STR;
2223 	query_vals[reason_col].nul = 0;
2224 	n_query_cols++;
2225 
2226 	query_cols[record_route_col = n_query_cols] = &str_record_route_col;
2227 	query_vals[record_route_col].type = DB1_STR;
2228 	query_vals[record_route_col].nul = 0;
2229 	n_query_cols++;
2230 
2231 	query_cols[contact_col = n_query_cols] = &str_contact_col;
2232 	query_vals[contact_col].type = DB1_STR;
2233 	query_vals[contact_col].nul = 0;
2234 	n_query_cols++;
2235 
2236 	query_cols[local_contact_col = n_query_cols] = &str_local_contact_col;
2237 	query_vals[local_contact_col].type = DB1_STR;
2238 	query_vals[local_contact_col].nul = 0;
2239 	n_query_cols++;
2240 
2241 	query_cols[socket_info_col = n_query_cols] = &str_socket_info_col;
2242 	query_vals[socket_info_col].type = DB1_STR;
2243 	query_vals[socket_info_col].nul = 0;
2244 	n_query_cols++;
2245 
2246 	query_cols[version_col = n_query_cols] = &str_version_col;
2247 	query_vals[version_col].type = DB1_INT;
2248 	query_vals[version_col].nul = 0;
2249 	n_query_cols++;
2250 
2251 	query_cols[updated_col = n_query_cols] = &str_updated_col;
2252 	query_vals[updated_col].type = DB1_INT;
2253 	query_vals[updated_col].nul = 0;
2254 	n_query_cols++;
2255 
2256 	query_cols[updated_winfo_col = n_query_cols] = &str_updated_winfo_col;
2257 	query_vals[updated_winfo_col].type = DB1_INT;
2258 	query_vals[updated_winfo_col].nul = 0;
2259 	n_query_cols++;
2260 
2261 	query_cols[user_agent_col = n_query_cols] = &str_user_agent_col;
2262 	query_vals[user_agent_col].type = DB1_STR;
2263 	query_vals[user_agent_col].nul = 0;
2264 	n_query_cols++;
2265 
2266 	/* cols and values used for update */
2267 	update_cols[u_expires_col = n_update_cols] = &str_expires_col;
2268 	update_vals[u_expires_col].type = DB1_INT;
2269 	update_vals[u_expires_col].nul = 0;
2270 	n_update_cols++;
2271 
2272 	update_cols[u_status_col = n_update_cols] = &str_status_col;
2273 	update_vals[u_status_col].type = DB1_INT;
2274 	update_vals[u_status_col].nul = 0;
2275 	n_update_cols++;
2276 
2277 	update_cols[u_reason_col = n_update_cols] = &str_reason_col;
2278 	update_vals[u_reason_col].type = DB1_STR;
2279 	update_vals[u_reason_col].nul = 0;
2280 	n_update_cols++;
2281 
2282 	update_cols[u_remote_cseq_col = n_update_cols] = &str_remote_cseq_col;
2283 	update_vals[u_remote_cseq_col].type = DB1_INT;
2284 	update_vals[u_remote_cseq_col].nul = 0;
2285 	n_update_cols++;
2286 
2287 	update_cols[u_local_cseq_col = n_update_cols] = &str_local_cseq_col;
2288 	update_vals[u_local_cseq_col].type = DB1_INT;
2289 	update_vals[u_local_cseq_col].nul = 0;
2290 	n_update_cols++;
2291 
2292 	update_cols[u_version_col = n_update_cols] = &str_version_col;
2293 	update_vals[u_version_col].type = DB1_INT;
2294 	update_vals[u_version_col].nul = 0;
2295 	n_update_cols++;
2296 
2297 	update_cols[u_contact_col = n_update_cols] = &str_contact_col;
2298 	update_vals[u_contact_col].type = DB1_STR;
2299 	update_vals[u_contact_col].nul = 0;
2300 	n_update_cols++;
2301 
2302 	update_cols[u_record_route_col = n_update_cols] = &str_record_route_col;
2303 	update_vals[u_record_route_col].type = DB1_STR;
2304 	update_vals[u_record_route_col].nul = 0;
2305 	n_update_cols++;
2306 
2307 	for(i = 0; i < htable_size; i++) {
2308 		if(!no_lock)
2309 			lock_get(&hash_table[i].lock);
2310 
2311 		prev_s = hash_table[i].entries;
2312 		s = prev_s->next;
2313 
2314 		while(s) {
2315 			printf_subs(s);
2316 			if(s->expires < now - pres_expires_offset) {
2317 				LM_DBG("Found expired record\n");
2318 				if(!no_lock) {
2319 					if(handle_expired_func(s) < 0)
2320 						LM_ERR("in function handle_expired_record\n");
2321 				}
2322 				del_s = s;
2323 				s = s->next;
2324 				prev_s->next = s;
2325 
2326 				/* need for a struct free/destroy? */
2327 				if(del_s->contact.s)
2328 					shm_free(del_s->contact.s);
2329 				if(del_s->record_route.s)
2330 					shm_free(del_s->record_route.s);
2331 				shm_free(del_s);
2332 				continue;
2333 			}
2334 			switch(s->db_flag) {
2335 				case NO_UPDATEDB_FLAG:
2336 				case WTHROUGHDB_FLAG:
2337 					LM_DBG("%s\n", (s->db_flag == NO_UPDATEDB_FLAG)
2338 										   ? "NO_UPDATEDB_FLAG"
2339 										   : "WTHROUGHDB_FLAG");
2340 					break;
2341 
2342 				case UPDATEDB_FLAG:
2343 					LM_DBG("UPDATEDB_FLAG\n");
2344 
2345 					query_vals[pres_uri_col].val.str_val = s->pres_uri;
2346 					query_vals[callid_col].val.str_val = s->callid;
2347 					query_vals[totag_col].val.str_val = s->to_tag;
2348 					query_vals[fromtag_col].val.str_val = s->from_tag;
2349 
2350 					update_vals[u_expires_col].val.int_val = s->expires;
2351 					update_vals[u_local_cseq_col].val.int_val = s->local_cseq;
2352 					update_vals[u_remote_cseq_col].val.int_val = s->remote_cseq;
2353 					update_vals[u_version_col].val.int_val = s->version;
2354 					update_vals[u_status_col].val.int_val = s->status;
2355 					update_vals[u_reason_col].val.str_val = s->reason;
2356 					update_vals[u_contact_col].val.str_val = s->contact;
2357 					update_vals[u_record_route_col].val.str_val =
2358 							s->record_route;
2359 
2360 					if(dbf->update(db, query_cols, 0, query_vals, update_cols,
2361 							   update_vals, n_query_update, n_update_cols)
2362 							< 0) {
2363 						LM_ERR("updating in database\n");
2364 					} else {
2365 						s->db_flag = NO_UPDATEDB_FLAG;
2366 					}
2367 					break;
2368 
2369 				case INSERTDB_FLAG:
2370 					LM_DBG("INSERTDB_FLAG\n");
2371 
2372 					query_vals[pres_uri_col].val.str_val = s->pres_uri;
2373 					query_vals[callid_col].val.str_val = s->callid;
2374 					query_vals[totag_col].val.str_val = s->to_tag;
2375 					query_vals[fromtag_col].val.str_val = s->from_tag;
2376 					query_vals[to_user_col].val.str_val = s->to_user;
2377 					query_vals[to_domain_col].val.str_val = s->to_domain;
2378 					query_vals[from_user_col].val.str_val = s->from_user;
2379 					query_vals[from_domain_col].val.str_val = s->from_domain;
2380 					query_vals[watcher_user_col].val.str_val = s->watcher_user;
2381 					query_vals[watcher_domain_col].val.str_val =
2382 							s->watcher_domain;
2383 					query_vals[event_col].val.str_val = s->event->name;
2384 					query_vals[event_id_col].val.str_val = s->event_id;
2385 					query_vals[local_cseq_col].val.int_val = s->local_cseq;
2386 					query_vals[remote_cseq_col].val.int_val = s->remote_cseq;
2387 					query_vals[expires_col].val.int_val = s->expires;
2388 					query_vals[record_route_col].val.str_val = s->record_route;
2389 					query_vals[contact_col].val.str_val = s->contact;
2390 					query_vals[local_contact_col].val.str_val =
2391 							s->local_contact;
2392 					query_vals[version_col].val.int_val = s->version;
2393 					query_vals[status_col].val.int_val = s->status;
2394 					query_vals[reason_col].val.str_val = s->reason;
2395 					query_vals[socket_info_col].val.str_val = s->sockinfo_str;
2396 					query_vals[updated_col].val.int_val = -1;
2397 					query_vals[updated_winfo_col].val.int_val = -1;
2398 					query_vals[user_agent_col].val.str_val = s->user_agent;
2399 
2400 
2401 					if(dbf->insert(db, query_cols, query_vals, n_query_cols)
2402 							< 0) {
2403 						LM_ERR("unsuccessful sql insert\n");
2404 					} else {
2405 						s->db_flag = NO_UPDATEDB_FLAG;
2406 					}
2407 					break;
2408 			} /* switch */
2409 			prev_s = s;
2410 			s = s->next;
2411 		}
2412 		if(!no_lock)
2413 			lock_release(&hash_table[i].lock);
2414 	}
2415 
2416 	update_vals[0].val.int_val = (int)time(NULL) - pres_expires_offset;
2417 	update_ops[0] = OP_LT;
2418 	if(dbf->delete(db, update_cols, update_ops, update_vals, 1) < 0) {
2419 		LM_ERR("deleting expired information from database\n");
2420 	}
2421 }
2422 
2423 /**
2424  * timer_db_update function does the following tasks:
2425  *	1. checks for expires subscriptions and does the corresponding processing
2426  *		- if db_mode != DB_ONLY : checks by traversing the hash table
2427  *		- if db_mode == DB_ONLY : checks by querying database
2428  *	2. if db_mode == WRITE_BACK : updates the subscriptions in database
2429  */
timer_db_update(unsigned int ticks,void * param)2430 void timer_db_update(unsigned int ticks, void *param)
2431 {
2432 	int no_lock = 0;
2433 	LM_DBG("db_update timer\n");
2434 	if(ticks == 0 && param == NULL)
2435 		no_lock = 1;
2436 
2437 
2438 	switch(pres_subs_dbmode) {
2439 		case DB_ONLY:
2440 			if(pres_notifier_processes > 0)
2441 				update_db_subs_timer_notifier();
2442 			else
2443 				update_db_subs_timer_dbonly();
2444 			break;
2445 		case NO_DB:
2446 			update_db_subs_timer_dbnone(no_lock);
2447 			break;
2448 		default:
2449 			if(pa_dbf.use_table(pa_db, &active_watchers_table) < 0) {
2450 				LM_ERR("sql use table failed\n");
2451 				return;
2452 			}
2453 			update_db_subs_timer(pa_db, &pa_dbf, subs_htable, shtable_size,
2454 					no_lock, handle_expired_subs);
2455 	}
2456 }
2457 
2458 
restore_db_subs(void)2459 int restore_db_subs(void)
2460 {
2461 	db_key_t result_cols[22];
2462 	db1_res_t *result = NULL;
2463 	db_row_t *rows = NULL;
2464 	db_val_t *row_vals = NULL;
2465 	int i;
2466 	int n_result_cols = 0;
2467 	int pres_uri_col, expires_col, from_user_col, from_domain_col, to_user_col;
2468 	int callid_col, totag_col, fromtag_col, to_domain_col, sockinfo_col,
2469 			reason_col;
2470 	int event_col, contact_col, record_route_col, event_id_col, status_col;
2471 	int remote_cseq_col, local_cseq_col, local_contact_col, version_col;
2472 	int watcher_user_col, watcher_domain_col;
2473 	subs_t s;
2474 	str ev_sname;
2475 	pres_ev_t *event = NULL;
2476 	event_t parsed_event;
2477 	unsigned int expires;
2478 	unsigned int hash_code;
2479 	int nr_rows;
2480 
2481 	result_cols[pres_uri_col = n_result_cols++] = &str_presentity_uri_col;
2482 	result_cols[expires_col = n_result_cols++] = &str_expires_col;
2483 	result_cols[event_col = n_result_cols++] = &str_event_col;
2484 	result_cols[event_id_col = n_result_cols++] = &str_event_id_col;
2485 	result_cols[to_user_col = n_result_cols++] = &str_to_user_col;
2486 	result_cols[to_domain_col = n_result_cols++] = &str_to_domain_col;
2487 	result_cols[from_user_col = n_result_cols++] = &str_from_user_col;
2488 	result_cols[from_domain_col = n_result_cols++] = &str_from_domain_col;
2489 	result_cols[watcher_user_col = n_result_cols++] = &str_watcher_username_col;
2490 	result_cols[watcher_domain_col = n_result_cols++] = &str_watcher_domain_col;
2491 	result_cols[callid_col = n_result_cols++] = &str_callid_col;
2492 	result_cols[totag_col = n_result_cols++] = &str_to_tag_col;
2493 	result_cols[fromtag_col = n_result_cols++] = &str_from_tag_col;
2494 	result_cols[local_cseq_col = n_result_cols++] = &str_local_cseq_col;
2495 	result_cols[remote_cseq_col = n_result_cols++] = &str_remote_cseq_col;
2496 	result_cols[record_route_col = n_result_cols++] = &str_record_route_col;
2497 	result_cols[sockinfo_col = n_result_cols++] = &str_socket_info_col;
2498 	result_cols[contact_col = n_result_cols++] = &str_contact_col;
2499 	result_cols[local_contact_col = n_result_cols++] = &str_local_contact_col;
2500 	result_cols[version_col = n_result_cols++] = &str_version_col;
2501 	result_cols[status_col = n_result_cols++] = &str_status_col;
2502 	result_cols[reason_col = n_result_cols++] = &str_reason_col;
2503 
2504 	if(!pa_db) {
2505 		LM_ERR("null database connection\n");
2506 		return -1;
2507 	}
2508 
2509 	if(pa_dbf.use_table(pa_db, &active_watchers_table) < 0) {
2510 		LM_ERR("in use table\n");
2511 		return -1;
2512 	}
2513 
2514 	/* select the whole table and all the columns */
2515 	if(db_fetch_query(&pa_dbf, pres_fetch_rows, pa_db, 0, 0, 0, result_cols, 0,
2516 			   n_result_cols, 0, &result)
2517 			< 0) {
2518 		LM_ERR("querying presentity\n");
2519 		goto error;
2520 	}
2521 
2522 	if(result == NULL) {
2523 		LM_ERR("bad result\n");
2524 		goto error;
2525 	}
2526 
2527 	do {
2528 		nr_rows = RES_ROW_N(result);
2529 		LM_DBG("loading information from database %i records\n", nr_rows);
2530 
2531 		rows = RES_ROWS(result);
2532 
2533 		/* for every row */
2534 		for(i = 0; i < nr_rows; i++) {
2535 
2536 			row_vals = ROW_VALUES(rows + i);
2537 			memset(&s, 0, sizeof(subs_t));
2538 
2539 			expires = row_vals[expires_col].val.int_val;
2540 
2541 			if(expires < (int)time(NULL))
2542 				continue;
2543 
2544 			s.pres_uri.s = (char *)row_vals[pres_uri_col].val.string_val;
2545 			s.pres_uri.len = strlen(s.pres_uri.s);
2546 
2547 			s.to_user.s = (char *)row_vals[to_user_col].val.string_val;
2548 			s.to_user.len = strlen(s.to_user.s);
2549 
2550 			s.to_domain.s = (char *)row_vals[to_domain_col].val.string_val;
2551 			s.to_domain.len = strlen(s.to_domain.s);
2552 
2553 			s.from_user.s = (char *)row_vals[from_user_col].val.string_val;
2554 			s.from_user.len = strlen(s.from_user.s);
2555 
2556 			s.from_domain.s = (char *)row_vals[from_domain_col].val.string_val;
2557 			s.from_domain.len = strlen(s.from_domain.s);
2558 
2559 			s.watcher_user.s =
2560 					(char *)row_vals[watcher_user_col].val.string_val;
2561 			s.watcher_user.len = strlen(s.watcher_user.s);
2562 
2563 			s.watcher_domain.s =
2564 					(char *)row_vals[watcher_domain_col].val.string_val;
2565 			s.watcher_domain.len = strlen(s.watcher_domain.s);
2566 
2567 			s.to_tag.s = (char *)row_vals[totag_col].val.string_val;
2568 			s.to_tag.len = strlen(s.to_tag.s);
2569 
2570 			s.from_tag.s = (char *)row_vals[fromtag_col].val.string_val;
2571 			s.from_tag.len = strlen(s.from_tag.s);
2572 
2573 			s.callid.s = (char *)row_vals[callid_col].val.string_val;
2574 			s.callid.len = strlen(s.callid.s);
2575 
2576 			ev_sname.s = (char *)row_vals[event_col].val.string_val;
2577 			ev_sname.len = strlen(ev_sname.s);
2578 
2579 			event = contains_event(&ev_sname, &parsed_event);
2580 			if(event == NULL) {
2581 				LM_DBG("insert a new event structure in the list waiting"
2582 					   " to be filled in\n");
2583 
2584 				/*insert a new event structure in the list waiting to be filled in*/
2585 				event = (pres_ev_t *)shm_malloc(sizeof(pres_ev_t));
2586 				if(event == NULL) {
2587 					free_event_params(parsed_event.params.list, PKG_MEM_TYPE);
2588 					ERR_MEM("shm");
2589 				}
2590 				memset(event, 0, sizeof(pres_ev_t));
2591 				event->name.s = (char *)shm_malloc(ev_sname.len * sizeof(char));
2592 				if(event->name.s == NULL) {
2593 					free_event_params(parsed_event.params.list, PKG_MEM_TYPE);
2594 					ERR_MEM("shm");
2595 				}
2596 				memcpy(event->name.s, ev_sname.s, ev_sname.len);
2597 				event->name.len = ev_sname.len;
2598 
2599 				event->evp = shm_copy_event(&parsed_event);
2600 				if(event->evp == NULL) {
2601 					LM_ERR("ERROR copying event_t structure\n");
2602 					free_event_params(parsed_event.params.list, PKG_MEM_TYPE);
2603 					goto error;
2604 				}
2605 				event->next = pres_evlist->events;
2606 				pres_evlist->events = event;
2607 			}
2608 
2609 			free_event_params(parsed_event.params.list, PKG_MEM_TYPE);
2610 
2611 			s.event = event;
2612 
2613 			s.event_id.s = (char *)row_vals[event_id_col].val.string_val;
2614 			if(s.event_id.s)
2615 				s.event_id.len = strlen(s.event_id.s);
2616 
2617 			s.remote_cseq = row_vals[remote_cseq_col].val.int_val;
2618 			s.local_cseq = row_vals[local_cseq_col].val.int_val;
2619 			s.version = row_vals[version_col].val.int_val;
2620 
2621 			s.expires = expires - (int)time(NULL);
2622 			s.status = row_vals[status_col].val.int_val;
2623 
2624 			s.reason.s = (char *)row_vals[reason_col].val.string_val;
2625 			if(s.reason.s)
2626 				s.reason.len = strlen(s.reason.s);
2627 
2628 			s.contact.s = (char *)row_vals[contact_col].val.string_val;
2629 			s.contact.len = strlen(s.contact.s);
2630 
2631 			s.local_contact.s =
2632 					(char *)row_vals[local_contact_col].val.string_val;
2633 			s.local_contact.len = strlen(s.local_contact.s);
2634 
2635 			s.record_route.s =
2636 					(char *)row_vals[record_route_col].val.string_val;
2637 			if(s.record_route.s)
2638 				s.record_route.len = strlen(s.record_route.s);
2639 
2640 			s.sockinfo_str.s = (char *)row_vals[sockinfo_col].val.string_val;
2641 			s.sockinfo_str.len = strlen(s.sockinfo_str.s);
2642 			s.db_flag = (pres_subs_dbmode == WRITE_THROUGH) ? WTHROUGHDB_FLAG
2643 													   : NO_UPDATEDB_FLAG;
2644 			hash_code =
2645 					core_case_hash(&s.pres_uri, &s.event->name, shtable_size);
2646 			if(insert_shtable(subs_htable, hash_code, &s) < 0) {
2647 				LM_ERR("adding new record in hash table\n");
2648 				goto error;
2649 			}
2650 		}
2651 
2652 	} while((db_fetch_next(&pa_dbf, pres_fetch_rows, pa_db, &result) == 1)
2653 			&& (RES_ROW_N(result) > 0));
2654 
2655 	pa_dbf.free_result(pa_db, result);
2656 
2657 	/* delete all records  only if in memory mode */
2658 	if(pres_subs_dbmode == NO_DB) {
2659 		if(pa_dbf.delete(pa_db, 0, 0, 0, 0) < 0) {
2660 			LM_ERR("deleting all records from database table\n");
2661 			return -1;
2662 		}
2663 	}
2664 	return 0;
2665 
2666 error:
2667 	if(result)
2668 		pa_dbf.free_result(pa_db, result);
2669 	return -1;
2670 }
2671 
ps_get_db_subs_auth(subs_t * subs,int * found)2672 static int ps_get_db_subs_auth(subs_t *subs, int *found)
2673 {
2674 	db_key_t db_keys[5];
2675 	db_val_t db_vals[5];
2676 	int n_query_cols = 0;
2677 	db_key_t result_cols[3];
2678 	db1_res_t *result = NULL;
2679 	db_row_t *row;
2680 	db_val_t *row_vals;
2681 
2682 	db_keys[n_query_cols] = &str_presentity_uri_col;
2683 	db_vals[n_query_cols].type = DB1_STR;
2684 	db_vals[n_query_cols].nul = 0;
2685 	db_vals[n_query_cols].val.str_val = subs->pres_uri;
2686 	n_query_cols++;
2687 
2688 	db_keys[n_query_cols] = &str_watcher_username_col;
2689 	db_vals[n_query_cols].type = DB1_STR;
2690 	db_vals[n_query_cols].nul = 0;
2691 	db_vals[n_query_cols].val.str_val = subs->watcher_user;
2692 	n_query_cols++;
2693 
2694 	db_keys[n_query_cols] = &str_watcher_domain_col;
2695 	db_vals[n_query_cols].type = DB1_STR;
2696 	db_vals[n_query_cols].nul = 0;
2697 	db_vals[n_query_cols].val.str_val = subs->watcher_domain;
2698 	n_query_cols++;
2699 
2700 	db_keys[n_query_cols] = &str_event_col;
2701 	db_vals[n_query_cols].type = DB1_STR;
2702 	db_vals[n_query_cols].nul = 0;
2703 	db_vals[n_query_cols].val.str_val = subs->event->name;
2704 	n_query_cols++;
2705 
2706 	result_cols[0] = &str_status_col;
2707 	result_cols[1] = &str_reason_col;
2708 
2709 	if(pa_dbf.use_table(pa_db, &watchers_table) < 0) {
2710 		LM_ERR("in use table\n");
2711 		return -1;
2712 	}
2713 
2714 	if(pa_dbf.query(pa_db, db_keys, 0, db_vals, result_cols, n_query_cols, 2, 0,
2715 			   &result)
2716 			< 0) {
2717 		LM_ERR("while querying watchers table\n");
2718 		if(result)
2719 			pa_dbf.free_result(pa_db, result);
2720 		return -1;
2721 	}
2722 	if(result == NULL)
2723 		return -1;
2724 
2725 	if(result->n <= 0) {
2726 		*found = 0;
2727 		pa_dbf.free_result(pa_db, result);
2728 		return 0;
2729 	}
2730 
2731 	*found = 1;
2732 	row = &result->rows[0];
2733 	row_vals = ROW_VALUES(row);
2734 	subs->status = row_vals[0].val.int_val;
2735 
2736 	if(row_vals[1].val.string_val) {
2737 
2738 		subs->reason.len = strlen(row_vals[1].val.string_val);
2739 		if(subs->reason.len == 0)
2740 			subs->reason.s = NULL;
2741 		else {
2742 			subs->reason.s =
2743 					(char *)pkg_malloc(subs->reason.len * sizeof(char));
2744 			if(subs->reason.s == NULL) {
2745 				pa_dbf.free_result(pa_db, result);
2746 				ERR_MEM(PKG_MEM_STR);
2747 			}
2748 			memcpy(subs->reason.s, row_vals[1].val.string_val,
2749 					subs->reason.len);
2750 		}
2751 	}
2752 
2753 	pa_dbf.free_result(pa_db, result);
2754 	return 0;
2755 error:
2756 	return -1;
2757 }
2758 
ps_get_subs_auth(subs_t * subs,int * found)2759 static int ps_get_subs_auth(subs_t *subs, int *found)
2760 {
2761 	if(pa_db==NULL) {
2762 		/* expecting the cache only mode -- watchers considered active */
2763 		subs->reason.s = NULL;
2764 		subs->status = ACTIVE_STATUS;
2765 		*found = 1;
2766 		return 0;
2767 	} else {
2768 		return ps_get_db_subs_auth(subs, found);
2769 	}
2770 }
2771 
ps_insert_db_subs_auth(subs_t * subs)2772 static int ps_insert_db_subs_auth(subs_t *subs)
2773 {
2774 	db_key_t db_keys[10];
2775 	db_val_t db_vals[10];
2776 	int n_query_cols = 0;
2777 
2778 	db_keys[n_query_cols] = &str_presentity_uri_col;
2779 	db_vals[n_query_cols].type = DB1_STR;
2780 	db_vals[n_query_cols].nul = 0;
2781 	db_vals[n_query_cols].val.str_val = subs->pres_uri;
2782 	n_query_cols++;
2783 
2784 	db_keys[n_query_cols] = &str_watcher_username_col;
2785 	db_vals[n_query_cols].type = DB1_STR;
2786 	db_vals[n_query_cols].nul = 0;
2787 	db_vals[n_query_cols].val.str_val = subs->watcher_user;
2788 	n_query_cols++;
2789 
2790 	db_keys[n_query_cols] = &str_watcher_domain_col;
2791 	db_vals[n_query_cols].type = DB1_STR;
2792 	db_vals[n_query_cols].nul = 0;
2793 	db_vals[n_query_cols].val.str_val = subs->watcher_domain;
2794 	n_query_cols++;
2795 
2796 	db_keys[n_query_cols] = &str_event_col;
2797 	db_vals[n_query_cols].type = DB1_STR;
2798 	db_vals[n_query_cols].nul = 0;
2799 	db_vals[n_query_cols].val.str_val = subs->event->name;
2800 	n_query_cols++;
2801 
2802 	db_keys[n_query_cols] = &str_status_col;
2803 	db_vals[n_query_cols].type = DB1_INT;
2804 	db_vals[n_query_cols].nul = 0;
2805 	db_vals[n_query_cols].val.int_val = subs->status;
2806 	n_query_cols++;
2807 
2808 	db_keys[n_query_cols] = &str_inserted_time_col;
2809 	db_vals[n_query_cols].type = DB1_INT;
2810 	db_vals[n_query_cols].nul = 0;
2811 	db_vals[n_query_cols].val.int_val = (int)time(NULL);
2812 	n_query_cols++;
2813 
2814 	db_keys[n_query_cols] = &str_reason_col;
2815 	db_vals[n_query_cols].type = DB1_STR;
2816 	db_vals[n_query_cols].nul = 0;
2817 	if(subs->reason.s && subs->reason.len)
2818 		db_vals[n_query_cols].val.str_val = subs->reason;
2819 	else {
2820 		db_vals[n_query_cols].val.str_val.s = "";
2821 		db_vals[n_query_cols].val.str_val.len = 0;
2822 	}
2823 	n_query_cols++;
2824 
2825 	if(pa_dbf.use_table(pa_db, &watchers_table) < 0) {
2826 		LM_ERR("in use_table\n");
2827 		return -1;
2828 	}
2829 
2830 	if(pa_dbf.replace != NULL) {
2831 		if(pa_dbf.replace(pa_db, db_keys, db_vals, n_query_cols, 2, 0) < 0) {
2832 			LM_ERR("in sql replace\n");
2833 			goto error;
2834 		}
2835 	} else {
2836 		/* If you use insert() instead of replace() be prepared for some
2837 		 * DB error messages.  There is a lot of time between the
2838 		 * query() that indicated there was no matching entry in the DB
2839 		 * and this insert(), so on a multi-user system it is entirely
2840 		 * possible (even likely) that a record will be added after the
2841 		 * query() but before this insert(). */
2842 		if(pa_dbf.insert(pa_db, db_keys, db_vals, n_query_cols) < 0) {
2843 			LM_ERR("in sql insert\n");
2844 			goto error;
2845 		}
2846 	}
2847 
2848 	return 0;
2849 
2850 error:
2851 	return -1;
2852 }
2853 
ps_insert_subs_auth(subs_t * subs)2854 static int ps_insert_subs_auth(subs_t *subs)
2855 {
2856 	if(pa_db==NULL) {
2857 		/* expecting the cache only mode
2858 		 * - no insert, watchers considered active */
2859 		return 0;
2860 	} else {
2861 		return ps_insert_db_subs_auth(subs);
2862 	}
2863 }
2864 
get_subscribers_count_from_mem(struct sip_msg * msg,str pres_uri,str event)2865 int get_subscribers_count_from_mem(struct sip_msg *msg, str pres_uri, str event)
2866 {
2867 	subs_t *s;
2868 	unsigned int hash_code;
2869 	int found = 0;
2870 
2871 	hash_code = core_case_hash(&pres_uri, &event, shtable_size);
2872 	lock_get(&subs_htable[hash_code].lock);
2873 	s = subs_htable[hash_code].entries->next;
2874 	while(s) {
2875 		if(s->pres_uri.len == pres_uri.len
2876 				&& strncmp(s->pres_uri.s, pres_uri.s, pres_uri.len) == 0)
2877 			found++;
2878 		s = s->next;
2879 	}
2880 	lock_release(&subs_htable[hash_code].lock);
2881 	return found;
2882 }
2883 
get_subscribers_count_from_db(struct sip_msg * msg,str pres_uri,str event)2884 int get_subscribers_count_from_db(struct sip_msg *msg, str pres_uri, str event)
2885 {
2886 	db_key_t query_cols[2];
2887 	db_val_t query_vals[2];
2888 	db_key_t result_cols[1];
2889 	db1_res_t *result = NULL;
2890 	int n_query_cols = 0;
2891 	int n_result_cols = 0;
2892 	int found = 0;
2893 
2894 	query_cols[n_query_cols] = &str_presentity_uri_col;
2895 	query_vals[n_query_cols].type = DB1_STR;
2896 	query_vals[n_query_cols].nul = 0;
2897 	query_vals[n_query_cols].val.str_val = pres_uri;
2898 	n_query_cols++;
2899 
2900 	query_cols[n_query_cols] = &str_event_col;
2901 	query_vals[n_query_cols].type = DB1_STR;
2902 	query_vals[n_query_cols].nul = 0;
2903 	query_vals[n_query_cols].val.str_val = event;
2904 	n_query_cols++;
2905 
2906 	result_cols[n_result_cols++] = &str_callid_col;
2907 
2908 	if(pa_dbf.use_table(pa_db, &active_watchers_table) < 0) {
2909 		LM_ERR("unsuccessful use_table sql operation\n");
2910 		return 0;
2911 	}
2912 
2913 	if(!pa_dbf.query(pa_db, query_cols, 0, query_vals, result_cols,
2914 			   n_query_cols, n_result_cols, 0, &result)) {
2915 		if(result != NULL)
2916 			found = result->n;
2917 	}
2918 
2919 	pa_dbf.free_result(pa_db, result);
2920 
2921 	return found;
2922 }
2923 
get_subscribers_count(struct sip_msg * msg,str pres_uri,str event)2924 int get_subscribers_count(struct sip_msg *msg, str pres_uri, str event)
2925 {
2926 	if(pres_subs_dbmode == DB_ONLY) {
2927 		return get_subscribers_count_from_db(msg, pres_uri, event);
2928 	} else {
2929 		return get_subscribers_count_from_mem(msg, pres_uri, event);
2930 	}
2931 }
2932