Browse code

core: relocated some folders from root and utils to misc

- utils keeps only the applications related to kamailio c code
- the other are now in misc/tools
- utils/misc/vim moved to misc/extra/
- obsolete and scripts folders moved to misc/

Daniel-Constantin Mierla authored on 07/12/2016 11:46:38
Showing 1 changed files
1 1
deleted file mode 100644
... ...
@@ -1,613 +0,0 @@
1
-/*
2
- * Presence Agent, notifications
3
- *
4
- * $Id$
5
- *
6
- * Copyright (C) 2001-2003 FhG Fokus
7
- *
8
- * This file is part of ser, a free SIP server.
9
- *
10
- * ser is free software; you can redistribute it and/or modify
11
- * it under the terms of the GNU General Public License as published by
12
- * the Free Software Foundation; either version 2 of the License, or
13
- * (at your option) any later version
14
- *
15
- * For a license to use the ser software under conditions
16
- * other than those described here, or to purchase support for this
17
- * software, please contact iptel.org by e-mail at the following addresses:
18
- *    info@iptel.org
19
- *
20
- * ser is distributed in the hope that it will be useful,
21
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
22
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23
- * GNU General Public License for more details.
24
- *
25
- * You should have received a copy of the GNU General Public License 
26
- * along with this program; if not, write to the Free Software 
27
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
28
- *
29
- * History:
30
- * --------
31
- * 2003-02-28 protocolization of t_uac_dlg completed (jiri)
32
- */
33
-
34
-#include "../../str.h"
35
-#include "../../dprint.h"
36
-#include "../../trim.h"
37
-#include "../../parser/parse_event.h"
38
-#include "pa_mod.h"
39
-#include "presentity.h"
40
-#include "paerrno.h"
41
-#include "notify.h"
42
-#include "watcher.h"
43
-#include "qsa_interface.h"
44
-
45
-#include <presence/pidf.h>
46
-#include <presence/xpidf.h>
47
-#include <presence/lpidf.h>
48
-#include "winfo_doc.h"
49
-#include "dlist.h"
50
-
51
-
52
-static str notify = STR_STATIC_INIT("NOTIFY");
53
-
54
-/* TM callback processing */
55
-
56
-typedef struct {
57
-	dlg_id_t id;
58
-	str uid;
59
-	struct pdomain *domain; /* replace with domain name for safe stop */
60
-	char buf[1];
61
-} pa_notify_cb_param_t;
62
-
63
-static pa_notify_cb_param_t *create_notify_cb_param(presentity_t *p, watcher_t *w)
64
-{
65
-	pa_notify_cb_param_t *cbd;
66
-	int size;
67
-
68
-	if ((!p) || (!w)) return NULL;
69
-	if (!w->dialog) return NULL;
70
-
71
-	size = sizeof(*cbd) + p->uuid.len +
72
-			w->dialog->id.call_id.len +
73
-			w->dialog->id.rem_tag.len +
74
-			w->dialog->id.loc_tag.len;
75
-	
76
-	cbd = (pa_notify_cb_param_t*)mem_alloc(size);
77
-	if (!cbd) {
78
-		ERR("can't allocate memory (%d bytes)\n", size);
79
-		return NULL;
80
-	}
81
-
82
-	cbd->domain = p->pdomain;
83
-
84
-	cbd->uid.s = cbd->buf;
85
-	cbd->uid.len = p->uuid.len;
86
-	
87
-	cbd->id.call_id.s = cbd->uid.s + cbd->uid.len;
88
-	cbd->id.call_id.len = w->dialog->id.call_id.len;
89
-	
90
-	cbd->id.rem_tag.s = cbd->id.call_id.s + cbd->id.call_id.len;
91
-	cbd->id.rem_tag.len = w->dialog->id.rem_tag.len;
92
-	
93
-	cbd->id.loc_tag.s = cbd->id.rem_tag.s + cbd->id.rem_tag.len;
94
-	cbd->id.loc_tag.len = w->dialog->id.loc_tag.len;
95
-	
96
-	/* copy data */
97
-	if (p->uuid.s) memcpy(cbd->uid.s, p->uuid.s, p->uuid.len); 
98
-	if (w->dialog->id.call_id.s) memcpy(cbd->id.call_id.s, 
99
-			w->dialog->id.call_id.s, w->dialog->id.call_id.len); 
100
-	if (w->dialog->id.rem_tag.s) memcpy(cbd->id.rem_tag.s, 
101
-			w->dialog->id.rem_tag.s, w->dialog->id.rem_tag.len); 
102
-	if (w->dialog->id.loc_tag.s) memcpy(cbd->id.loc_tag.s, 
103
-			w->dialog->id.loc_tag.s, w->dialog->id.loc_tag.len); 
104
-	
105
-	return cbd;
106
-}
107
-
108
-static int get_watcher(pa_notify_cb_param_t *cbd, 
109
-		watcher_t **w, presentity_t **p)
110
-{
111
-	int et = EVENT_PRESENCE;
112
-	
113
-	if (find_presentity_uid(cbd->domain, &cbd->uid, p) != 0) {
114
-		return -1;
115
-	}
116
-	
117
-	if (find_watcher_dlg(*p, &cbd->id, et, w) != 0) {
118
-		/* presence watcher NOT found */
119
-		
120
-		et = EVENT_PRESENCE_WINFO;
121
-		if (find_watcher_dlg(*p, &cbd->id, et, w) != 0) {
122
-			/* presence.winfo watcher NOT found */
123
-			return -1;
124
-		}
125
-	}
126
-	return 0;
127
-}
128
-
129
-static void destroy_subscription(pa_notify_cb_param_t *cbd)
130
-{
131
-	presentity_t *p = NULL;
132
-	watcher_t *w = NULL;
133
-	
134
-/*	if (find_pdomain(cbd->domain, &domain) != 0) {
135
-		ERR("can't find PA domain\n");
136
-		return;
137
-	} */
138
-	lock_pdomain(cbd->domain);
139
-	
140
-	if (get_watcher(cbd, &w, &p) != 0) {
141
-		unlock_pdomain(cbd->domain);
142
-		return;
143
-	}
144
-	
145
-	remove_watcher(p, w);
146
-	free_watcher(w);
147
-
148
-	unlock_pdomain(cbd->domain);
149
-	
150
-}
151
-
152
-static void refresh_dialog(pa_notify_cb_param_t *cbd, struct sip_msg *m)
153
-{
154
-	watcher_t *w;
155
-	presentity_t *p;
156
-	
157
-	lock_pdomain(cbd->domain);
158
-	if (get_watcher(cbd, &w, &p) >= 0)
159
-		tmb.dlg_response_uac(w->dialog, m, notify_is_refresh != 0 ? IS_TARGET_REFRESH : IS_NOT_TARGET_REFRESH);
160
-	unlock_pdomain(cbd->domain);
161
-}
162
-
163
-static void pa_notify_cb(struct cell* t, int type, struct tmcb_params* params)
164
-{
165
-	pa_notify_cb_param_t *cbd = NULL;
166
-	
167
-	if (!params) return;
168
-
169
-	/* Possible problems - see subscribe_cb in presence_b2b/euac_funcs.c */
170
-
171
-	if (params->param) cbd = (pa_notify_cb_param_t *)*(params->param);
172
-	if (!cbd) {
173
-		ERR("BUG empty cbd parameter given to callback function\n");
174
-		return;
175
-	}
176
-
177
-	if ((params->code >= 200) && (params->code < 300)) {
178
-		if (params->rpl && (params->rpl != FAKED_REPLY)) 
179
-			refresh_dialog(cbd, params->rpl);
180
-	}
181
-	if ((params->code >= 300)) {
182
-		int ignore = 0;
183
-		
184
-		switch (params->code) {
185
-			case 408: 
186
-				if (ignore_408_on_notify) ignore = 1;
187
-				/* due to eyeBeam's problems with processing more NOTIFY
188
-				 * requests sent consequently without big delay */
189
-				break;
190
-		}
191
-	
192
-		if (!ignore) {
193
-			WARN("destroying subscription from callback due to %d response on NOTIFY\n", params->code);
194
-			destroy_subscription(cbd);
195
-			TRACE("subscription destroyed!!!\n");
196
-		}
197
-	}
198
-	
199
-	shm_free(cbd);
200
-}
201
-
202
-/* helper functions */
203
-
204
-static inline int add_event_hf(dstring_t *buf, int event_package)
205
-{
206
-	dstr_append_zt(buf, "Event: ");
207
-	dstr_append_zt(buf, event_package2str(event_package));
208
-	dstr_append_zt(buf, "\r\n");
209
-	
210
-	return 0;
211
-}
212
-
213
-
214
-static inline int add_cont_type_hf(dstring_t *buf, str *content_type)
215
-{
216
-	/* content types can have dynamical parameters (multipart/related)
217
-	 * => don't generate them "staticaly"; use values created in the
218
-	 * time of document creation */
219
-	
220
-	if (is_str_empty(content_type)) return 0; /* documents without body doesn't need it */
221
-	
222
-	dstr_append_zt(buf, "Content-Type: ");
223
-	
224
-	dstr_append_str(buf, content_type);
225
-	dstr_append_zt(buf, "\r\n");
226
-	
227
-	return 0;
228
-}
229
-
230
-
231
-static inline int add_subs_state_hf(dstring_t *buf, watcher_status_t _s, time_t _e)
232
-{
233
-	char* num;
234
-	int len;
235
-	str s = STR_NULL;
236
-	static str timeout = STR_STATIC_INIT("timeout");
237
-	static str rejected = STR_STATIC_INIT("rejected");
238
-	
239
-	switch(_s) {
240
-		case WS_ACTIVE: ;
241
-			s = watcher_status_names[WS_ACTIVE];
242
-			break;
243
-		case WS_REJECTED:
244
-		case WS_PENDING_TERMINATED:
245
-		case WS_TERMINATED:
246
-			s = watcher_status_names[WS_TERMINATED];
247
-			break;
248
-		case WS_PENDING: 
249
-			s = watcher_status_names[WS_PENDING];
250
-			break;
251
-	}
252
-	
253
-	dstr_append_zt(buf, "Subscription-State: ");
254
-	dstr_append_str(buf, &s);
255
-	
256
-	switch(_s) {
257
-		case WS_PENDING:;
258
-		case WS_ACTIVE:
259
-			dstr_append_zt(buf, ";expires=");
260
-			num = int2str((unsigned int)_e, &len);
261
-			dstr_append(buf, num, len);
262
-			break;
263
-
264
-		case WS_REJECTED:
265
-		case WS_PENDING_TERMINATED:
266
-		case WS_TERMINATED:
267
-			dstr_append_zt(buf, ";reason=");
268
-			if (_e <= 0) dstr_append_str(buf, &timeout);
269
-			else dstr_append_str(buf, &rejected);
270
-			break;
271
-
272
-	}
273
-
274
-	dstr_append_zt(buf, "\r\n");
275
-	return 0;
276
-}
277
-
278
-static inline int create_headers(struct watcher* _w, str *dst, str *content_type)
279
-{
280
-	dstring_t buf;
281
-	time_t t;
282
-	int err = 0;
283
-	
284
-	dstr_init(&buf, 256);
285
-	str_clear(dst);
286
-
287
-	/* required by RFC 3261 */
288
-	dstr_append_zt(&buf, "Max-Forwards: 70\r\n"); 
289
-	
290
-	/* Event header */
291
-
292
-	dstr_append_zt(&buf, "Event: ");
293
-	dstr_append_zt(&buf, event_package2str(_w->event_package));
294
-	dstr_append_zt(&buf, "\r\n");
295
-	
296
-	/* Content-Type header */
297
-	
298
-	/* content types can have dynamical parameters (multipart/related)
299
-	 * => don't generate them "staticaly"; use values created in the
300
-	 * time of document creation */
301
-	if (!is_str_empty(content_type)) { /* documents without body doesn't need it */
302
-		dstr_append_zt(&buf, "Content-Type: ");
303
-		dstr_append_str(&buf, content_type);
304
-		dstr_append_zt(&buf, "\r\n");
305
-	}
306
-	
307
-	/* Contact header */
308
-	
309
-	if (is_str_empty(&_w->server_contact)) {
310
-		LOG(L_WARN, "add_contact_hf(): Can't add empty contact to NOTIFY.\n");
311
-	}
312
-	else {
313
-		dstr_append_zt(&buf, "Contact: ");
314
-		dstr_append_str(&buf, &_w->server_contact);
315
-		dstr_append_zt(&buf, "\r\n");
316
-	}
317
-
318
-	/* Subscription-State header */
319
-	
320
-	if (_w->expires) t = _w->expires - time(0);
321
-	else t = 0;
322
-
323
-	if (add_subs_state_hf(&buf, _w->status, t) < 0) {
324
-		LOG(L_ERR, "create_headers(): Error while adding Subscription-State\n");
325
-		dstr_destroy(&buf);
326
-		return -3;
327
-	}
328
-
329
-	err = dstr_get_str(&buf, dst);
330
-	dstr_destroy(&buf);
331
-
332
-	return err;
333
-}
334
-
335
-/* NOTIFY creation functions for specific events/state */
336
-
337
-static int prepare_presence_notify(struct retr_buf **dst, 
338
-		struct presentity* _p, struct watcher* _w,
339
-		pa_notify_cb_param_t *cbd)
340
-{
341
-	/* Send a notify, saved Contact will be put in
342
-	 * Request-URI, To will be put in from and new tag
343
-	 * will be generated, callid will be callid,
344
-	 * from will be put in to including tag
345
-	 */
346
-	str doc = STR_NULL;
347
-	str content_type = STR_NULL;
348
-	str headers = STR_NULL;
349
-	str body = STR_STATIC_INIT("");
350
-	int res = 0;
351
-	uac_req_t	uac_r;
352
-	
353
-	switch(_w->preferred_mimetype) {
354
-		case DOC_XPIDF:
355
-			res = create_xpidf_document(&_p->data, &doc, &content_type);
356
-			break;
357
-
358
-		case DOC_LPIDF:
359
-			res = create_lpidf_document(&_p->data, &doc, &content_type);
360
-			break;
361
-		
362
-		case DOC_CPIM_PIDF:
363
-			res = create_cpim_pidf_document(&_p->data, &doc, &content_type);
364
-			break;
365
-
366
-		case DOC_MSRTC_PIDF:
367
-		case DOC_PIDF:
368
-		default:
369
-			res = create_pidf_document(&_p->data, &doc, &content_type);
370
-	}
371
-	
372
-	if (res != 0) {
373
-		LOG(L_ERR, "can't create presence document (%d)\n", _w->preferred_mimetype);
374
-		return -2;
375
-	}
376
-	
377
-	if (create_headers(_w, &headers, &content_type) < 0) {
378
-		LOG(L_ERR, "send_presence_notify(): Error while adding headers\n");
379
-		str_free_content(&doc);
380
-		str_free_content(&content_type);
381
-		
382
-		return -7;
383
-	}
384
-	
385
-	if (!is_str_empty(&doc)) body = doc;
386
-/*	res = tmb.t_request_within(&notify, &headers, &body, 
387
-			_w->dialog, pa_notify_cb, cbd);*/
388
-	set_uac_req(&uac_r,
389
-			&notify,
390
-			&headers,
391
-			&body, 
392
-			_w->dialog,
393
-			TMCB_LOCAL_COMPLETED,
394
-			pa_notify_cb,
395
-			cbd
396
-		);
397
-	res = tmb.prepare_request_within(&uac_r, dst);
398
-	if (res < 0) {
399
-		ERR("Can't send NOTIFY (%d) in dlg %.*s, %.*s, %.*s\n", res, 
400
-			FMT_STR(_w->dialog->id.call_id), 
401
-			FMT_STR(_w->dialog->id.rem_tag), 
402
-			FMT_STR(_w->dialog->id.loc_tag));
403
-	}
404
-
405
-	str_free_content(&doc);
406
-	str_free_content(&headers);
407
-	str_free_content(&content_type);	
408
-	
409
-	return res;
410
-}
411
-
412
-static int prepare_winfo_notify(struct retr_buf **dst,
413
-		struct presentity* _p, struct watcher* _w,
414
-		pa_notify_cb_param_t *cbd)
415
-{
416
-	str doc = STR_NULL;
417
-	str content_type = STR_NULL;
418
-	str headers = STR_NULL;
419
-	int res = 0;
420
-	str body = STR_STATIC_INIT("");
421
-	uac_req_t	uac_r;
422
-	
423
-	switch (_w->preferred_mimetype) {
424
-		case DOC_WINFO:
425
-			create_winfo_document(_p, _w, &doc, &content_type);
426
-			DEBUG("winfo document created\n");
427
-			break;
428
-		/* other formats ? */
429
-		default:
430
-			ERR("unknow doctype\n");
431
-			return -1;
432
-	}
433
-
434
-	if (create_headers(_w, &headers, &content_type) < 0) {
435
-		ERR("Error while adding headers\n");
436
-		str_free_content(&doc);
437
-		str_free_content(&content_type);
438
-		return -7;
439
-	}
440
-
441
-	if (!is_str_empty(&doc)) body = doc;
442
-	/* res = tmb.t_request_within(&notify, &headers, &body, _w->dialog, 0, 0); */
443
-	set_uac_req(&uac_r,
444
-			&notify,
445
-			&headers,
446
-			&body, 
447
-			_w->dialog,
448
-			TMCB_LOCAL_COMPLETED,
449
-			pa_notify_cb,
450
-			cbd
451
-		);
452
-	res = tmb.prepare_request_within(&uac_r, dst);
453
-	if (res < 0) {
454
-		ERR("Can't send watcherinfo notification (%d)\n", res);
455
-	}
456
-	else {
457
-		_w->document_index++; /* increment index for next document */
458
-	}
459
-
460
-	str_free_content(&doc);
461
-	str_free_content(&headers);
462
-	str_free_content(&content_type);
463
-
464
-	return res;
465
-}
466
-
467
-int prepare_unauthorized_notify(struct retr_buf **dst, 
468
-		struct presentity* _p, struct watcher* _w,
469
-		pa_notify_cb_param_t *cbd)
470
-{
471
-	str headers = STR_NULL;
472
-	str body = STR_STATIC_INIT("");
473
-	int res;
474
-	unc_req_t	uac_r;
475
-
476
-	/* send notifications to unauthorized (pending) watchers */
477
-	if (create_headers(_w, &headers, NULL) < 0) {
478
-		LOG(L_ERR, "notify_unauthorized_watcher(): Error while adding headers\n");
479
-		return -7;
480
-	}
481
-
482
-	set_uac_req(&uac_r,
483
-			&notify,
484
-			&headers,
485
-			&body, 
486
-			_w->dialog,
487
-			TMCB_LOCAL_COMPLETED,
488
-			pa_notify_cb,
489
-			cbd
490
-		);
491
-	res = tmb.prepare_request_within(&uac_r, dst);
492
-	if (res < 0) {
493
-		ERR("Can't send NOTIFY (%d) in dlg %.*s, %.*s, %.*s\n", res, 
494
-			FMT_STR(_w->dialog->id.call_id), 
495
-			FMT_STR(_w->dialog->id.rem_tag), 
496
-			FMT_STR(_w->dialog->id.loc_tag));
497
-	}
498
-
499
-	str_free_content(&headers);
500
-		
501
-	
502
-	return res;
503
-}
504
-
505
-int prepare_notify(struct retr_buf **dst, 
506
-		struct presentity* _p, struct watcher* _w)
507
-{
508
-	int rc = 0;
509
-	pa_notify_cb_param_t *cbd = NULL;
510
-
511
-	/* alloc data for callback */
512
-	cbd = create_notify_cb_param(_p, _w);
513
-	if (!cbd) {
514
-		ERR("can't allocate data for callback\n");
515
-		/* FIXME: destroy subscription? */
516
-		return -1;
517
-	}	
518
-	
519
-	LOG(L_DBG, "notifying %.*s _p->flags=%x _w->event_package=%d _w->preferred_mimetype=%d _w->status=%d\n", 
520
-	    _w->uri.len, _w->uri.s, _p->flags, _w->event_package, _w->preferred_mimetype, _w->status);
521
-
522
-	if ((_w->status == WS_PENDING) || 
523
-			(_w->status == WS_PENDING_TERMINATED) ||
524
-			(_w->status == WS_REJECTED)) {
525
-		rc = prepare_unauthorized_notify(dst, _p, _w, cbd);
526
-	}
527
-	else {
528
-		switch (_w->event_package) {
529
-			case EVENT_PRESENCE:
530
-				rc = prepare_presence_notify(dst, _p, _w, cbd);
531
-				break;
532
-			case EVENT_PRESENCE_WINFO:
533
-				rc = prepare_winfo_notify(dst, _p, _w, cbd);
534
-				break;
535
-			default: 
536
-				LOG(L_ERR, "sending notify for unknow package\n");
537
-				rc = -1;
538
-		}
539
-	}
540
-	if ((rc < 0) && cbd) shm_free(cbd); /* ??? or not ??? */
541
-	else {
542
-		 /* At least dialog has changed (sometimes more - for example
543
-		  * version counter for winfo)! 
544
-		  * Ignore errors there because the watcher need NOT to be in DB
545
-		  * (polling). */
546
-		if (use_db) db_update_watcher(_p, _w);
547
-		/* if (use_db && (!is_watcher_terminated(_w)))
548
-				db_update_watcher(_p, _w);	 */
549
-	}
550
-
551
-	return rc;
552
-}
553
-
554
-int send_notify(struct presentity* _p, struct watcher* _w)
555
-{
556
-	struct retr_buf *request;
557
-	int res = prepare_notify(&request, _p, _w);
558
-	if (res < 0) return res;
559
-	tmb.send_prepared_request(request);
560
-	return res;
561
-}
562
-
563
-int send_winfo_notify_offline(struct presentity* _p, 
564
-		struct watcher* _w, 
565
-		offline_winfo_t *info, 
566
-		transaction_cb completion_cb, void* cbp)
567
-{
568
-	str doc = STR_NULL;
569
-	str content_type = STR_NULL;
570
-	str headers = STR_NULL;
571
-	str body = STR_STATIC_INIT("");
572
-	uac_req_t	uac_r;
573
-	
574
-	switch (_w->preferred_mimetype) {
575
-		case DOC_WINFO:
576
-			create_winfo_document_offline(_p, _w, info, &doc, &content_type);
577
-			break;
578
-		/* other formats ? */
579
-		default:
580
-			ERR("send_winfo_notify: unknow doctype\n");
581
-			return -1;
582
-	}
583
-
584
-	if (create_headers(_w, &headers, &content_type) < 0) {
585
-		ERR("send_winfo_notify(): Error while adding headers\n");
586
-		str_free_content(&doc);
587
-		str_free_content(&content_type);
588
-		return -7;
589
-	}
590
-
591
-	if (!is_str_empty(&doc)) body = doc;
592
-	set_uac_req(&uac_r,
593
-			&notify,
594
-			&headers,
595
-			&body, 
596
-			_w->dialog,
597
-			TMCB_LOCAL_COMPLETED,
598
-			completion_cb,
599
-			cbp
600
-		);
601
-	tmb.t_request_within(&uac_r);
602
-
603
-	str_free_content(&doc);
604
-	str_free_content(&headers);
605
-	str_free_content(&content_type);
606
-
607
-	_w->document_index++; /* increment index for next document */
608
-	
609
-	if (use_db) db_update_watcher(_p, _w); /* dialog and index have changed */
610
-
611
-	return 0;
612
-}
613
-
Browse code

all: updated FSF address in GPL text

Anthony Messina authored on 04/07/2014 09:36:37 • Daniel-Constantin Mierla committed on 04/07/2014 09:37:36
Showing 1 changed files
... ...
@@ -24,7 +24,7 @@
24 24
  *
25 25
  * You should have received a copy of the GNU General Public License 
26 26
  * along with this program; if not, write to the Free Software 
27
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
27
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
28 28
  *
29 29
  * History:
30 30
  * --------
Browse code

pa(s): obsoleted

Moved pa to obsolete/ because it does not compile (needs upgrade
to the current DB libs) and it does not have a maintainer.

Andrei Pelinescu-Onciul authored on 09/12/2009 09:53:51
Showing 1 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,613 @@
1
+/*
2
+ * Presence Agent, notifications
3
+ *
4
+ * $Id$
5
+ *
6
+ * Copyright (C) 2001-2003 FhG Fokus
7
+ *
8
+ * This file is part of ser, a free SIP server.
9
+ *
10
+ * ser is free software; you can redistribute it and/or modify
11
+ * it under the terms of the GNU General Public License as published by
12
+ * the Free Software Foundation; either version 2 of the License, or
13
+ * (at your option) any later version
14
+ *
15
+ * For a license to use the ser software under conditions
16
+ * other than those described here, or to purchase support for this
17
+ * software, please contact iptel.org by e-mail at the following addresses:
18
+ *    info@iptel.org
19
+ *
20
+ * ser is distributed in the hope that it will be useful,
21
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
22
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23
+ * GNU General Public License for more details.
24
+ *
25
+ * You should have received a copy of the GNU General Public License 
26
+ * along with this program; if not, write to the Free Software 
27
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
28
+ *
29
+ * History:
30
+ * --------
31
+ * 2003-02-28 protocolization of t_uac_dlg completed (jiri)
32
+ */
33
+
34
+#include "../../str.h"
35
+#include "../../dprint.h"
36
+#include "../../trim.h"
37
+#include "../../parser/parse_event.h"
38
+#include "pa_mod.h"
39
+#include "presentity.h"
40
+#include "paerrno.h"
41
+#include "notify.h"
42
+#include "watcher.h"
43
+#include "qsa_interface.h"
44
+
45
+#include <presence/pidf.h>
46
+#include <presence/xpidf.h>
47
+#include <presence/lpidf.h>
48
+#include "winfo_doc.h"
49
+#include "dlist.h"
50
+
51
+
52
+static str notify = STR_STATIC_INIT("NOTIFY");
53
+
54
+/* TM callback processing */
55
+
56
+typedef struct {
57
+	dlg_id_t id;
58
+	str uid;
59
+	struct pdomain *domain; /* replace with domain name for safe stop */
60
+	char buf[1];
61
+} pa_notify_cb_param_t;
62
+
63
+static pa_notify_cb_param_t *create_notify_cb_param(presentity_t *p, watcher_t *w)
64
+{
65
+	pa_notify_cb_param_t *cbd;
66
+	int size;
67
+
68
+	if ((!p) || (!w)) return NULL;
69
+	if (!w->dialog) return NULL;
70
+
71
+	size = sizeof(*cbd) + p->uuid.len +
72
+			w->dialog->id.call_id.len +
73
+			w->dialog->id.rem_tag.len +
74
+			w->dialog->id.loc_tag.len;
75
+	
76
+	cbd = (pa_notify_cb_param_t*)mem_alloc(size);
77
+	if (!cbd) {
78
+		ERR("can't allocate memory (%d bytes)\n", size);
79
+		return NULL;
80
+	}
81
+
82
+	cbd->domain = p->pdomain;
83
+
84
+	cbd->uid.s = cbd->buf;
85
+	cbd->uid.len = p->uuid.len;
86
+	
87
+	cbd->id.call_id.s = cbd->uid.s + cbd->uid.len;
88
+	cbd->id.call_id.len = w->dialog->id.call_id.len;
89
+	
90
+	cbd->id.rem_tag.s = cbd->id.call_id.s + cbd->id.call_id.len;
91
+	cbd->id.rem_tag.len = w->dialog->id.rem_tag.len;
92
+	
93
+	cbd->id.loc_tag.s = cbd->id.rem_tag.s + cbd->id.rem_tag.len;
94
+	cbd->id.loc_tag.len = w->dialog->id.loc_tag.len;
95
+	
96
+	/* copy data */
97
+	if (p->uuid.s) memcpy(cbd->uid.s, p->uuid.s, p->uuid.len); 
98
+	if (w->dialog->id.call_id.s) memcpy(cbd->id.call_id.s, 
99
+			w->dialog->id.call_id.s, w->dialog->id.call_id.len); 
100
+	if (w->dialog->id.rem_tag.s) memcpy(cbd->id.rem_tag.s, 
101
+			w->dialog->id.rem_tag.s, w->dialog->id.rem_tag.len); 
102
+	if (w->dialog->id.loc_tag.s) memcpy(cbd->id.loc_tag.s, 
103
+			w->dialog->id.loc_tag.s, w->dialog->id.loc_tag.len); 
104
+	
105
+	return cbd;
106
+}
107
+
108
+static int get_watcher(pa_notify_cb_param_t *cbd, 
109
+		watcher_t **w, presentity_t **p)
110
+{
111
+	int et = EVENT_PRESENCE;
112
+	
113
+	if (find_presentity_uid(cbd->domain, &cbd->uid, p) != 0) {
114
+		return -1;
115
+	}
116
+	
117
+	if (find_watcher_dlg(*p, &cbd->id, et, w) != 0) {
118
+		/* presence watcher NOT found */
119
+		
120
+		et = EVENT_PRESENCE_WINFO;
121
+		if (find_watcher_dlg(*p, &cbd->id, et, w) != 0) {
122
+			/* presence.winfo watcher NOT found */
123
+			return -1;
124
+		}
125
+	}
126
+	return 0;
127
+}
128
+
129
+static void destroy_subscription(pa_notify_cb_param_t *cbd)
130
+{
131
+	presentity_t *p = NULL;
132
+	watcher_t *w = NULL;
133
+	
134
+/*	if (find_pdomain(cbd->domain, &domain) != 0) {
135
+		ERR("can't find PA domain\n");
136
+		return;
137
+	} */
138
+	lock_pdomain(cbd->domain);
139
+	
140
+	if (get_watcher(cbd, &w, &p) != 0) {
141
+		unlock_pdomain(cbd->domain);
142
+		return;
143
+	}
144
+	
145
+	remove_watcher(p, w);
146
+	free_watcher(w);
147
+
148
+	unlock_pdomain(cbd->domain);
149
+	
150
+}
151
+
152
+static void refresh_dialog(pa_notify_cb_param_t *cbd, struct sip_msg *m)
153
+{
154
+	watcher_t *w;
155
+	presentity_t *p;
156
+	
157
+	lock_pdomain(cbd->domain);
158
+	if (get_watcher(cbd, &w, &p) >= 0)
159
+		tmb.dlg_response_uac(w->dialog, m, notify_is_refresh != 0 ? IS_TARGET_REFRESH : IS_NOT_TARGET_REFRESH);
160
+	unlock_pdomain(cbd->domain);
161
+}
162
+
163
+static void pa_notify_cb(struct cell* t, int type, struct tmcb_params* params)
164
+{
165
+	pa_notify_cb_param_t *cbd = NULL;
166
+	
167
+	if (!params) return;
168
+
169
+	/* Possible problems - see subscribe_cb in presence_b2b/euac_funcs.c */
170
+
171
+	if (params->param) cbd = (pa_notify_cb_param_t *)*(params->param);
172
+	if (!cbd) {
173
+		ERR("BUG empty cbd parameter given to callback function\n");
174
+		return;
175
+	}
176
+
177
+	if ((params->code >= 200) && (params->code < 300)) {
178
+		if (params->rpl && (params->rpl != FAKED_REPLY)) 
179
+			refresh_dialog(cbd, params->rpl);
180
+	}
181
+	if ((params->code >= 300)) {
182
+		int ignore = 0;
183
+		
184
+		switch (params->code) {
185
+			case 408: 
186
+				if (ignore_408_on_notify) ignore = 1;
187
+				/* due to eyeBeam's problems with processing more NOTIFY
188
+				 * requests sent consequently without big delay */
189
+				break;
190
+		}
191
+	
192
+		if (!ignore) {
193
+			WARN("destroying subscription from callback due to %d response on NOTIFY\n", params->code);
194
+			destroy_subscription(cbd);
195
+			TRACE("subscription destroyed!!!\n");
196
+		}
197
+	}
198
+	
199
+	shm_free(cbd);
200
+}
201
+
202
+/* helper functions */
203
+
204
+static inline int add_event_hf(dstring_t *buf, int event_package)
205
+{
206
+	dstr_append_zt(buf, "Event: ");
207
+	dstr_append_zt(buf, event_package2str(event_package));
208
+	dstr_append_zt(buf, "\r\n");
209
+	
210
+	return 0;
211
+}
212
+
213
+
214
+static inline int add_cont_type_hf(dstring_t *buf, str *content_type)
215
+{
216
+	/* content types can have dynamical parameters (multipart/related)
217
+	 * => don't generate them "staticaly"; use values created in the
218
+	 * time of document creation */
219
+	
220
+	if (is_str_empty(content_type)) return 0; /* documents without body doesn't need it */
221
+	
222
+	dstr_append_zt(buf, "Content-Type: ");
223
+	
224
+	dstr_append_str(buf, content_type);
225
+	dstr_append_zt(buf, "\r\n");
226
+	
227
+	return 0;
228
+}
229
+
230
+
231
+static inline int add_subs_state_hf(dstring_t *buf, watcher_status_t _s, time_t _e)
232
+{
233
+	char* num;
234
+	int len;
235
+	str s = STR_NULL;
236
+	static str timeout = STR_STATIC_INIT("timeout");
237
+	static str rejected = STR_STATIC_INIT("rejected");
238
+	
239
+	switch(_s) {
240
+		case WS_ACTIVE: ;
241
+			s = watcher_status_names[WS_ACTIVE];
242
+			break;
243
+		case WS_REJECTED:
244
+		case WS_PENDING_TERMINATED:
245
+		case WS_TERMINATED:
246
+			s = watcher_status_names[WS_TERMINATED];
247
+			break;
248
+		case WS_PENDING: 
249
+			s = watcher_status_names[WS_PENDING];
250
+			break;
251
+	}
252
+	
253
+	dstr_append_zt(buf, "Subscription-State: ");
254
+	dstr_append_str(buf, &s);
255
+	
256
+	switch(_s) {
257
+		case WS_PENDING:;
258
+		case WS_ACTIVE:
259
+			dstr_append_zt(buf, ";expires=");
260
+			num = int2str((unsigned int)_e, &len);
261
+			dstr_append(buf, num, len);
262
+			break;
263
+
264
+		case WS_REJECTED:
265
+		case WS_PENDING_TERMINATED:
266
+		case WS_TERMINATED:
267
+			dstr_append_zt(buf, ";reason=");
268
+			if (_e <= 0) dstr_append_str(buf, &timeout);
269
+			else dstr_append_str(buf, &rejected);
270
+			break;
271
+
272
+	}
273
+
274
+	dstr_append_zt(buf, "\r\n");
275
+	return 0;
276
+}
277
+
278
+static inline int create_headers(struct watcher* _w, str *dst, str *content_type)
279
+{