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