Browse code

obsolete: moved modules purple and iptrtpproxy

- they are no longer working, not being updated to use latest libs for a
very long time

Daniel-Constantin Mierla authored on 05/12/2016 13:39:51
Showing 1 changed files
1 1
deleted file mode 100644
... ...
@@ -1,3106 +0,0 @@
1
-/* $Id: iptrtpproxy.c 30494 2010-07-20 15:05:24Z tma $
2
- *
3
- * Copyright (C) 2007 Tomas Mandys
4
- *
5
- * This file is part of ser, a free SIP server.
6
- *
7
- * ser is free software; you can redistribute it and/or modify
8
- * it under the terms of the GNU General Public License as published by
9
- * the Free Software Foundation; either version 2 of the License, or
10
- * (at your option) any later version
11
- *
12
- * For a license to use the ser software under conditions
13
- * other than those described here, or to purchase support for this
14
- * software, please contact iptel.org by e-mail at the following addresses:
15
- *    info@iptel.org
16
- *
17
- * ser is distributed in the hope that it will be useful,
18
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
19
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20
- * GNU General Public License for more details.
21
- *
22
- * You should have received a copy of the GNU General Public License
23
- * along with this program; if not, write to the Free Software
24
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
25
- *
26
- */
27
-
28
-// #include <linux/compiler.h>   will be needed to define __user macro
29
-#include "../../sr_module.h"
30
-#include "../../dprint.h"
31
-#include "../../data_lump.h"
32
-#include "../../data_lump_rpl.h"
33
-#include "../../error.h"
34
-#include "../../forward.h"
35
-#include "../../mem/mem.h"
36
-#include "../../mem/shm_mem.h"
37
-#include "../../atomic_ops.h"
38
-#include "../../parser/parse_content.h"
39
-#include "../../parser/parse_uri.h"
40
-#include "../../parser/parser_f.h"
41
-#include "../../parser/parse_body.h"
42
-#include "../../resolve.h"
43
-#include "../../trim.h"
44
-#include "../../ut.h"
45
-#include "../../msg_translator.h"
46
-#include "../../socket_info.h"
47
-#include "../../select.h"
48
-#include "../../select_buf.h"
49
-#include "../../script_cb.h"
50
-#include "../../cfg_parser.h"
51
-#include "../../rand/kam_rand.h"
52
-#include <sys/types.h>
53
-#include <sys/socket.h>
54
-#include <sys/time.h>
55
-#include <netinet/in.h>
56
-#include <arpa/inet.h>
57
-#include <sys/uio.h>
58
-#include <sys/un.h>
59
-#include <ctype.h>
60
-#include <errno.h>
61
-#include <netdb.h>
62
-#include <poll.h>
63
-#include <stdio.h>
64
-#include <stdlib.h>
65
-#include <string.h>
66
-#include <unistd.h>
67
-#include <linux/netfilter/xt_RTPPROXY.h>
68
-#include <arpa/inet.h>
69
-
70
-MODULE_VERSION
71
-
72
-#define MODULE_NAME "iptrtpproxy"
73
-
74
-/* max.number of RTP streams per session */
75
-#define MAX_MEDIA_NUMBER XT_RTPPROXY_MAX_ALLOC_SESSION
76
-#define MAX_CODEC_NUMBER MAX_MEDIA_NUMBER*5
77
-#define MAX_SWITCHBOARD_NAME_LEN 20
78
-#define MAX_AGGREGATED_NUMBER 30
79
-
80
-/* warningless cast at 64-bit */
81
-#define PTR2INT(v) (int)(long) (v)
82
-#define INT2PTR(v) (void*)(long) (v)
83
-
84
-struct host_item_stat {
85
-	int last_error_stamp;
86
-	int last_ok_stamp;
87
-};
88
-
89
-struct host_item {
90
-	str name;
91
-	struct xt_rtpproxy_connection_rpc_params rpc_params;
92
-	int local;
93
-	struct xt_rtpproxy_handle handle;
94
-	int handle_is_opened;
95
-
96
-	struct host_item_stat *stat;
97
-	struct host_item *next;
98
-};
99
-
100
-struct switchboard_item_stat {
101
-	atomic_t free;
102
-	atomic_t alloc;
103
-};
104
-
105
-struct switchboard_item {
106
-	str name;
107
-	struct xt_rtpproxy_switchboard_id switchboard_addr;
108
-	unsigned int sip_ip;
109
-	str hostname;
110
-	struct host_item *host;
111
-	unsigned int weight;
112
-
113
-	struct switchboard_item_stat *stat;
114
-
115
-	struct switchboard_item *next;
116
-};
117
-
118
-enum sdp_media_type {
119
-	sdpmtUnknown = 0, 
120
-	sdpmtAudio, 
121
-	sdpmtVideo, 
122
-	sdpmtApplication, 
123
-	sdpmtText, 
124
-	sdpmtMessage,
125
-	sdpmtData,  /* not recommended in RFC4566 */
126
-	sdpmtControl   /* dtto */
127
-};
128
-
129
-#define NUM_MEDIA_TYPES (sdpmtControl+1)
130
-static str sdp_media_types_str[NUM_MEDIA_TYPES] = {
131
-	STR_STATIC_INIT("unknown"),
132
-	STR_STATIC_INIT("audio"),
133
-	STR_STATIC_INIT("video"),
134
-	STR_STATIC_INIT("application"),
135
-	STR_STATIC_INIT("text"),
136
-	STR_STATIC_INIT("message"),
137
-	STR_STATIC_INIT("data"),
138
-	STR_STATIC_INIT("control")
139
-};
140
-
141
-struct aggregation_item {
142
-	str name;
143
-	unsigned int switchboard_count;
144
-	unsigned int sip_ip;
145
-	struct switchboard_item *(*switchboards)[];
146
-	struct aggregation_item *next;
147
-};
148
-
149
-struct codec_set_item_throttle {
150
-	int max_streams;
151
-	struct xt_rtpproxy_throttle_stat bandwidth[2];   /* RTP, RTCP */
152
-};
153
-
154
-struct codec_set_item {
155
-	str name;
156
-	struct {
157
-		struct codec_set_item_throttle throttle;
158
-		unsigned int (*codec_rights)[];
159
-	} media_types[NUM_MEDIA_TYPES];
160
-	struct codec_set_item *next;
161
-};
162
-
163
-struct ipt_session {
164
-
165
-	unsigned int session_count;
166
-	struct xt_rtpproxy_sockopt_session sessions[MAX_MEDIA_NUMBER];
167
-	unsigned int sdp_media_count;
168
-	int sdp_media[MAX_MEDIA_NUMBER];
169
-
170
-	struct switchboard_item *switchboard;
171
-};
172
-
173
-static struct {
174
-	str session_ids;
175
-	str sdp_ip;
176
-	str oline_user;
177
-	str oline_addr;
178
-	struct switchboard_item *switchboard[2];
179
-	struct aggregation_item *aggregation[2];
180
-	int learning_timeout;
181
-	int expiration_timeout;
182
-	int ttl;
183
-	int always_learn;
184
-	struct {
185
-		u_int32_t mark;
186
-		struct xt_rtpproxy_throttle_stat bandwidth[2];
187
-	} throttle;
188
-	struct codec_set_item *codec_set;
189
-	int remove_codec_mask;
190
-	unsigned int auth_rights;
191
-	struct ipt_session protected_sess;
192
-} global_params;
193
-
194
-static struct switchboard_item *switchboards = NULL;
195
-static struct host_item *hosts = NULL;
196
-static struct aggregation_item *aggregations = NULL;
197
-static struct codec_set_item *codec_sets = NULL;
198
-static int switchboard_count = 0;
199
-static str iptrtpproxy_cfg_filename = STR_STATIC_INIT("/etc/iptrtpproxy.cfg");
200
-static int iptrtpproxy_cfg_flag = 0;
201
-static char* iptrtpproxy_cfg_hostname = NULL;
202
-static int rpc_heartbeat_timeout = 30;
203
-static int sdp_parsed = 999;   /* we need share parsed SDP between authorize_media & alloc/update * get_param */
204
-static struct sdp_session global_sdp_sess;
205
-
206
-#define declare_find_function(x) \
207
-static struct x##_item* find_##x(str *name, struct x##_item*** prev) { \
208
-	struct x##_item* p;\
209
-	struct x##_item** dummy;\
210
-	if (!prev) \
211
-		prev = &dummy;\
212
-	for (p = x##s, *prev = &x##s; p; *prev = &(**prev)->next, p=p->next) {\
213
-		int len, n;\
214
-		len = (name->len < p->name.len) ? name->len : p->name.len;\
215
-		n = strncasecmp(name->s, p->name.s, len);\
216
-		if (n == 0) {\
217
-			if (name->len == p->name.len) \
218
-				return p;\
219
-			else if (name->len < p->name.len)\
220
-				return NULL;\
221
-		}\
222
-		else if (n < 0) { \
223
-			return NULL;\
224
-		}\
225
-	}\
226
-	return NULL;\
227
-}
228
-
229
-declare_find_function(host)
230
-declare_find_function(switchboard)
231
-declare_find_function(aggregation)
232
-declare_find_function(codec_set)
233
-
234
-static struct switchboard_item* find_switchboard_by_addr(struct xt_rtpproxy_switchboard_id *addr) {
235
-	struct switchboard_item* p;
236
-	for (p = switchboards; p; p=p->next) {
237
-		if (addr->ip == p->switchboard_addr.ip && addr->port == p->switchboard_addr.port) break;
238
-	}
239
-	return p;
240
-}
241
-
242
-enum {
243
-	PAR_EXPIRATION_TIMEOUT, 
244
-	PAR_TTL, 
245
-	PAR_LEARNING_TIMEOUT, 
246
-	PAR_ALWAYS_LEARN,
247
-	PAR_AGGREGATION_A, PAR_AGGREGATION_B, 
248
-	PAR_SWITCHBOARD_A, PAR_SWITCHBOARD_B,
249
-	PAR_AGGREGATION_BY_SIP_IP_A, PAR_AGGREGATION_BY_SIP_IP_B,
250
-	PAR_SWITCHBOARD_BY_SIP_IP_A, PAR_SWITCHBOARD_BY_SIP_IP_B,
251
-	PAR_SESSION_IDS, PAR_PROTECTED_SESSION_IDS,
252
-	PAR_SDP_IP, PAR_ACTIVE_MEDIA_NUM,
253
-	PAR_OLINE_USER, PAR_OLINE_ADDR,
254
-	PAR_THROTTLE_MARK, 
255
-	PAR_THROTTLE_RTP_MAX_BYTES, PAR_THROTTLE_RTP_MAX_PACKETS, 
256
-	PAR_THROTTLE_RTCP_MAX_BYTES, PAR_THROTTLE_RTCP_MAX_PACKETS,
257
-	PAR_CODEC_SET, PAR_AUTH_RIGHTS, PAR_REMOVE_CODEC_MASK
258
-};
259
-
260
-enum {
261
-	PAR_READ=0x01, PAR_WRITE=0x02, PAR_INT=0x04, PAR_STR=0x08, PAR_DIR=0x10
262
-};
263
-
264
-static struct {
265
-	char *name;
266
-	int  id;
267
-	int flags;
268
-} param_list[] = { 
269
-	{"expiration_timeout", PAR_EXPIRATION_TIMEOUT, PAR_READ|PAR_WRITE|PAR_INT},
270
-	{"ttl", PAR_TTL, PAR_READ|PAR_WRITE|PAR_INT},
271
-	{"learning_timeout", PAR_LEARNING_TIMEOUT, PAR_READ|PAR_WRITE|PAR_INT},
272
-	{"always_learn", PAR_ALWAYS_LEARN, PAR_READ|PAR_WRITE|PAR_INT},
273
-	{"aggregation_a", PAR_AGGREGATION_A, PAR_READ|PAR_WRITE|PAR_STR},
274
-	{"aggregation_b", PAR_AGGREGATION_B, PAR_READ|PAR_WRITE|PAR_STR|PAR_DIR},
275
-	{"switchboard_a", PAR_SWITCHBOARD_A, PAR_READ|PAR_WRITE|PAR_STR},
276
-	{"switchboard_b", PAR_SWITCHBOARD_B, PAR_READ|PAR_WRITE|PAR_STR|PAR_DIR},
277
-	{"aggregation_by_sip_ip_a", PAR_AGGREGATION_BY_SIP_IP_A, PAR_WRITE|PAR_STR},
278
-	{"aggregation_by_sip_ip_b", PAR_AGGREGATION_BY_SIP_IP_B, PAR_WRITE|PAR_STR|PAR_DIR},
279
-	{"switchboard_by_sip_ip_a", PAR_SWITCHBOARD_BY_SIP_IP_A, PAR_WRITE|PAR_STR},
280
-	{"switchboard_by_sip_ip_b", PAR_SWITCHBOARD_BY_SIP_IP_B, PAR_WRITE|PAR_STR|PAR_DIR},
281
-	{"session_ids", PAR_SESSION_IDS, PAR_READ|PAR_STR},
282
-	{"protected_session_ids", PAR_PROTECTED_SESSION_IDS, PAR_WRITE|PAR_STR},
283
-	{"sdp_ip", PAR_SDP_IP, PAR_READ|PAR_INT},
284
-	{"active_media_num", PAR_ACTIVE_MEDIA_NUM, PAR_READ|PAR_INT},
285
-	{"o_user", PAR_OLINE_USER, PAR_READ|PAR_WRITE|PAR_STR},
286
-	{"o_addr", PAR_OLINE_ADDR, PAR_READ|PAR_WRITE|PAR_STR},
287
-	{"throttle_mark", PAR_THROTTLE_MARK, PAR_READ|PAR_WRITE|PAR_INT},
288
-	{"throttle_rtp_max_bytes", PAR_THROTTLE_RTP_MAX_BYTES, PAR_READ|PAR_WRITE|PAR_INT},
289
-	{"throttle_rtp_max_packets", PAR_THROTTLE_RTP_MAX_PACKETS, PAR_READ|PAR_WRITE|PAR_INT},
290
-	{"throttle_rtcp_max_bytes", PAR_THROTTLE_RTCP_MAX_BYTES, PAR_READ|PAR_WRITE|PAR_INT},
291
-	{"throttle_rtcp_max_packets", PAR_THROTTLE_RTCP_MAX_PACKETS, PAR_READ|PAR_WRITE|PAR_INT},
292
-	{"codec_set", PAR_CODEC_SET, PAR_READ|PAR_WRITE|PAR_STR},
293
-	{"remove_codec_mask", PAR_REMOVE_CODEC_MASK, PAR_READ|PAR_WRITE|PAR_INT},
294
-	{"auth_rights", PAR_AUTH_RIGHTS, PAR_READ|PAR_INT},
295
-	{ NULL }
296
-};
297
-
298
-static int param2idx(str *name, int rw) {
299
-	int i;
300
-	for (i=0; param_list[i].name; i++) {
301
-		if (strlen(param_list[i].name)==name->len && 
302
-		    strncasecmp(param_list[i].name, name->s, name->len) == 0 && 
303
-		    (rw & param_list[i].flags)) {
304
-			return i;
305
-		}
306
-	}
307
-	ERR(MODULE_NAME": param2idx: unknown param '%.*s', rw:0x%0x\n", STR_FMT(name), rw);
308
-	return -1;
309
-}
310
-
311
-/** if succesfull allocated sessions available @rtpproxy.session_ids
312
- */
313
-
314
-static int rtpproxy_alloc_update_fixup(void** param, int param_no) {
315
-	switch (param_no) {
316
-		case 1:
317
-			return fixup_var_int_12(param, param_no);
318
-		case 2:
319
-			return fixup_var_str_12(param, param_no);
320
-		default:
321
-			return 0;
322
-	}
323
-}
324
-
325
-static int rtpproxy_delete_fixup(void** param, int param_no) {
326
-	switch (param_no) {
327
-		case 1:
328
-			return fixup_var_str_12(param, param_no);
329
-		default:
330
-			return 0;
331
-	}
332
-}
333
-
334
-static int rtpproxy_set_param_fixup(void** param, int param_no) {
335
-	int idx;
336
-	action_u_t *a;
337
-	str s;
338
-	switch (param_no) {
339
-		case 1:
340
-			s.s = (char*)*param;
341
-			s.len = strlen(s.s);
342
-			idx = param2idx(&s, PAR_WRITE);
343
-			if (idx < 0) {
344
-				return E_CFG;
345
-			}
346
-			*param = INT2PTR(idx);
347
-			break;
348
-		case 2:
349
-			a = fixup_get_param(param, param_no, 1);
350
-			idx = a->u.number;
351
-			if (param_list[idx].flags & PAR_STR) {
352
-				return fixup_var_str_12(param, param_no);
353
-
354
-			} else if (param_list[idx].flags & PAR_INT) {
355
-				return fixup_var_int_12(param, param_no);
356
-			}
357
-			break;
358
-	}
359
-	return 0;
360
-}
361
-
362
-static int name2media_type(str *name) {
363
-	int i;
364
-	for (i = 1; i<NUM_MEDIA_TYPES; i++) {
365
-		if (name->len == sdp_media_types_str[i].len &&
366
-			strncasecmp(name->s, sdp_media_types_str[i].s, name->len) == 0) {
367
-				return i;
368
-		}
369
-	}
370
-	return sdpmtUnknown;
371
-}
372
-
373
-struct codec_entry {
374
-	str name;
375
-	/* bandwidth */
376
-	int payload_type;  /* -1 .. dynamic */
377
-};
378
-
379
-#define MAX_FIXED_PAYLOAD_TYPES 96
380
-
381
-static struct codec_entry(*reg_codecs)[] = NULL;
382
-static int reg_codec_count = 0;
383
-static int reg_codec_alloc_count = 0;
384
-static struct {
385
-	int codec_id;
386
-} fixed_payload_types[MAX_FIXED_PAYLOAD_TYPES];
387
-
388
-
389
-/* unregistered codec .. 0 */
390
-static int name2codec_id(str *name, int *new_codec_id) {
391
-	int i, j;
392
-	i = 0;
393
-	j = reg_codec_count - 1;
394
-	while (i <= j) {	
395
-		int k, r;
396
-		k = (i + j)/2;
397
-		r = strncasecmp((*reg_codecs)[k].name.s, name->s, ((*reg_codecs)[k].name.len < name->len)?(*reg_codecs)[k].name.len:name->len);
398
-		if (r == 0 && (*reg_codecs)[k].name.len == name->len) {
399
-			return k+1;
400
-		} else if (r > 0 || (r == 0 && (*reg_codecs)[k].name.len > name->len)) {
401
-			j = k - 1;
402
-		}
403
-		else {
404
-			i = k + 1;
405
-		}
406
-	}
407
-	if (new_codec_id) {
408
-		*new_codec_id = i + 1;
409
-	}
410
-	return 0;
411
-}
412
-
413
-/* return <0 if error, otherwise codec_id */
414
-static int register_codec(str *name) {
415
-	int codec_id, new_codec_id = 0;
416
-	if (!(codec_id = name2codec_id(name, &new_codec_id))) {
417
-		int i;
418
-		if (reg_codec_count + 1 > reg_codec_alloc_count) {
419
-			void *p;
420
-			reg_codec_alloc_count += 10;
421
-			p = pkg_realloc(reg_codecs, sizeof((*reg_codecs)[0])*reg_codec_alloc_count);
422
-			if (!p) {
423
-				return E_OUT_OF_MEM;
424
-			}
425
-			reg_codecs = p;
426
-		}
427
-
428
-		/* do not count codec_id == 0 (unknown) */
429
-		for (i=reg_codec_count-1; i >= new_codec_id-1; i--) {
430
-			(*reg_codecs)[i+1] = (*reg_codecs)[i];
431
-		}
432
-		reg_codec_count++;
433
-		(*reg_codecs)[new_codec_id-1].name = *name; 
434
-		codec_id = new_codec_id;
435
-
436
-	}
437
-	return codec_id;
438
-}
439
-
440
-enum send_rec_modifier {
441
-	sdpaattr_sendonly = 1,
442
-	sdpaattr_recvonly = 2,
443
-	sdpaattr_sendrecv = 3,
444
-	sdpaattr_inactive = 4
445
-};
446
-
447
-static str send_rec_modifiers[] = {
448
-	STR_STATIC_INIT(""),
449
-	STR_STATIC_INIT("sendonly"),
450
-	STR_STATIC_INIT("recvonly"),
451
-	STR_STATIC_INIT("sendrecv"),
452
-	STR_STATIC_INIT("inactive"),
453
-};
454
-
455
-struct sdp_codec {
456
-	unsigned int payload_type;
457
-	unsigned int codec_id;
458
-	str mline_payload_type_s;
459
-	str a_rtpmap_line_s;
460
-	str a_fmtp_line_s;
461
-};
462
-
463
-struct sdp_session {
464
-	str oline_user_s;
465
-	str oline_addr_s;
466
-	unsigned int media_count;
467
-	struct {
468
-		int active;  /* if SDP has been parsed correctly, has a IP (even 0.0.0.0), port!=0 and has supported params */
469
-		unsigned short port;
470
-		unsigned int ip;
471
-		str ip_s;
472
-		str port_s;
473
-		enum sdp_media_type media_type;
474
-		enum send_rec_modifier send_rec_modifier;
475
-		str send_rec_modifier_line_s;
476
-		int codec_count;
477
-		struct sdp_codec (*codecs)[];
478
-	} media[MAX_MEDIA_NUMBER];
479
-};
480
-
481
-static unsigned int s2ip4(str *s) {
482
-	struct in_addr res;
483
-	char c2;
484
-	c2 = s->s[s->len];
485
-	s->s[s->len] = '\0';
486
-	if (!inet_aton(s->s, &res)) {
487
-		s->s[s->len] = c2;
488
-		return 0;
489
-	}
490
-	s->s[s->len] = c2;
491
-	return res.s_addr;
492
-}
493
-
494
-static void ip42s(unsigned int ip, str *s) {
495
-	struct in_addr ip2 = { ip };
496
-	s->s = inet_ntoa(ip2);
497
-	s->len = strlen(s->s);
498
-}
499
-
500
-#define is_alpha(_c) (((_c) >= 'a' && (_c) <= 'z') || ((_c) >= 'A' && (_c) <= 'Z') || ((_c) >= '0' && (_c) <= '9') || ((_c) == '_') || ((_c) == '-'))
501
-
502
-inline static int next_sdp_line(char** p, char* pend, char *ltype, str* lvalue, str* line) {
503
-	char *cp;
504
-	while (*p < pend) {
505
-		while (*p < pend && (**p == '\n' || **p == '\r')) (*p)++;
506
-		for (cp = *p; cp < pend && *cp != '\n' && *cp != '\r'; cp++);
507
-
508
-		if (cp-*p > 2 && (*p)[1] == '=') {
509
-			*ltype = **p;
510
-			lvalue->s = (*p)+2;
511
-			lvalue->len = cp-lvalue->s;
512
-			while (cp < pend && (*cp == '\n' || *cp == '\r')) cp++;
513
-			line->s = (*p);
514
-			line->len = cp-line->s;
515
-			*p = cp;
516
-			return 0;
517
-		}
518
-		*p = cp;
519
-	}
520
-	return -1;
521
-};
522
-
523
-static int name2enum(str *name, str (*list)[]) {
524
-	int i;
525
-	for (i = 0; (*list)[i].s != NULL; i++) {
526
-		if (name->len == (*list)[i].len &&
527
-			strncasecmp(name->s, (*list)[i].s, name->len) == 0) {
528
-			return i;
529
-		}
530
-	}
531
-	return -1;
532
-}
533
-
534
-static int prefix2enum(str *line, str (*list)[]) {
535
-	int i;
536
-	for (i = 0; (*list)[i].s != NULL; i++) {
537
-		if (line->len > (*list)[i].len &&
538
-			strncmp(line->s, (*list)[i].s, (*list)[i].len) == 0) {
539
-			return i;
540
-		}
541
-	}
542
-	return -1;
543
-}
544
-
545
-/* SDP RFC2327 */
546
-static int parse_sdp_content(struct sip_msg* msg, struct sdp_session *sess) {
547
-	char *p, *pend, *cp, *cp2, *lend;
548
-	str line, lvalue, cline_ip_s, body;
549
-	int sess_fl, i, cline_count, codec_count;
550
-	char ltype, savec;
551
-	unsigned int cline_ip;
552
-	enum send_rec_modifier sess_send_rec_modifier;
553
-
554
-	static struct sdp_codec codecs[MAX_CODEC_NUMBER];
555
-
556
-	static str supported_protocols[] = {
557
-		STR_STATIC_INIT("rtp/avp"),
558
-		STR_STATIC_INIT("rtp/savp"),
559
-		STR_STATIC_INIT("rtp/avpf"),
560
-		STR_STATIC_INIT("rtp/savpf"),
561
-		STR_STATIC_INIT("udp"),
562
-		STR_STATIC_INIT("udptl"),
563
-		STR_NULL
564
-	};
565
-
566
-	enum a_attr {sdpaattr_rtpmap, sdpaattr_fmtp, sdpaattr_rtcp};
567
-	static str a_attrs[] = {
568
-		STR_STATIC_INIT("rtpmap:"),
569
-		STR_STATIC_INIT("fmtp:"),
570
-		STR_STATIC_INIT("rtcp:"),
571
-		STR_NULL
572
-	};
573
-
574
-	memset(sess, 0, sizeof(*sess));
575
-	/* try to get the body part with application/sdp */
576
-	body.s = get_body_part(msg, TYPE_APPLICATION, SUBTYPE_SDP, &body.len);
577
-	if (!body.s) {
578
-		ERR(MODULE_NAME": parse_sdp_content: failed to get the application/sdp body\n");
579
-		return -1;
580
-	}
581
-	
582
-	#if 0
583
-	body.s = get_body(msg);
584
-	if (body.s==0) {
585
-		ERR(MODULE_NAME": parse_sdp_content: failed to get the message body\n");
586
-		return -1;
587
-	}
588
-	body.len = msg->len -(int)(body.s - msg->buf);
589
-	if (body.len==0) {
590
-		ERR(MODULE_NAME": parse_sdp_content: message body has length zero\n");
591
-		return -1;
592
-	}
593
-
594
-	/* no need for parse_headers(msg, EOH), get_body will parse everything */
595
-	if (!msg->content_type)
596
-	{
597
-		WARN(MODULE_NAME": parse_sdp_content: Content-TYPE header absent!"
598
-			"let's assume the content is text/plain\n");
599
-	}
600
-	else {
601
-		trim_len(line.len, line.s, msg->content_type->body);
602
-		if (line.len != sizeof("application/sdp")-1 || strncasecmp(line.s, "application/sdp", line.len) != 0) {
603
-			ERR(MODULE_NAME": parse_sdp_content: bad content type '%.*s'\n", STR_FMT(&line));
604
-			return -1;
605
-		}
606
-	}
607
-	#endif
608
-	/*
609
-	 * Parsing of SDP body.
610
-	 * It can contain a few session descriptions (each starts with
611
-	 * v-line), and each session may contain a few media descriptions
612
-	 * (each starts with m-line).
613
-	 * We have to change ports in m-lines, and also change IP addresses in
614
-	 * c-lines which can be placed either in session header (fallback for
615
-	 * all medias) or media description.
616
-	 * Ports should be allocated for any media. IPs all should be changed
617
-	 * to the same value (RTP proxy IP), so we can change all c-lines
618
-	 * unconditionally.
619
-	 * There are sendonly,recvonly modifiers which signalize one-way
620
-	 * streaming, it probably won't work but it's handled the same way,
621
-	 * RTCP commands are still bi-directional. "Inactive" modifier
622
-	 * is not handled anyway. See RFC3264
623
-	 */
624
-
625
-	p = body.s;
626
-	pend = body.s + body.len;
627
-	sess_fl = 0;
628
-	sess->media_count = 0;
629
-	cline_ip_s.s = NULL;  /* make gcc happy */
630
-	cline_ip_s.len = 0;
631
-	cline_ip = 0;
632
-	cline_count = 0;
633
-	codec_count = 0;
634
-	memset(&codecs, 0, sizeof(codecs));
635
-	sess_send_rec_modifier = 0;
636
-	while (p < pend) {
637
-		if (next_sdp_line(&p, pend, &ltype, &lvalue, &line) < 0) break;
638
-		lend = lvalue.s + lvalue.len;
639
-		switch (ltype) {
640
-			case 'v':
641
-				/* Protocol Version: v=0 */
642
-				if (sess_fl != 0) {
643
-					ERR(MODULE_NAME": parse_sdp_content: only one session allowed\n");  /* RFC3264 */
644
-					return -1;
645
-				}
646
-				sess_fl = 1;
647
-				break;
648
-			case 'o': 
649
-				/* originator & session description: o=<username> <sess-id> <sess-version> <nettype> <addrtype> <unicast-address> */
650
-				if (sess_fl != 1) {
651
-					ERR(MODULE_NAME": parse_sdp_content: o= line is not in session section\n"); 
652
-					return -1;
653
-				}
654
-				for (i=0; i<6; i++) 
655
-				if (sess->oline_addr_s.s) {
656
-					ERR(MODULE_NAME": parse_sdp_content: only one o= line allowed\n"); 
657
-					return -1;
658
-				}
659
-				cp = eat_token_end(lvalue.s, lend);
660
-				sess->oline_user_s.len = cp-lvalue.s;
661
-				if (!sess->oline_user_s.len) goto invalid_o;
662
-				sess->oline_user_s.s = lvalue.s;
663
-				lvalue.s = eat_space_end(cp, lend);
664
-				for (i=0; i<4; i++) {
665
-						cp = eat_token_end(lvalue.s, lend);
666
-						if (cp-lvalue.s == 0) goto invalid_o;
667
-						lvalue.s = eat_space_end(cp, lend);
668
-				}
669
-				cp = eat_token_end(lvalue.s, lend);
670
-				sess->oline_addr_s.len = cp-lvalue.s;
671
-				if (!sess->oline_addr_s.len) goto invalid_o;
672
-				sess->oline_addr_s.s = lvalue.s;
673
-				break;
674
-			invalid_o:
675
-				ERR(MODULE_NAME": parse_sdp_content: invalid o= line '%.*s'\n", (int) (lend-line.s), line.s);
676
-				return -1;
677
-			case 'c':
678
-				/* Connection Data: c=<network type> <address type> <connection address>, ex. c=IN IP4 224.2.17.12/127 */
679
-				switch (sess_fl) {
680
-					case 0:
681
-						ERR(MODULE_NAME": parse_sdp_content: c= line is not in session section\n");
682
-						return -1;
683
-					case 1:
684
-					case 2:
685
-						cline_count++;
686
-						if (cline_count > 1) {
687
-							/* multicast not supported */
688
-							if (sess_fl == 2) {
689
-								goto invalidate;
690
-							}
691
-							else {
692
-								cline_ip_s.len = 0;
693
-							}
694
-							break;
695
-						}
696
-						cp = eat_token_end(lvalue.s, lend);
697
-						if (cp-lvalue.s != 2 || memcmp(lvalue.s, "IN", 2) != 0) {
698
-							goto invalidate;
699
-						}
700
-						cp = eat_space_end(cp, lend);
701
-						lvalue.s = cp;
702
-						cp = eat_token_end(cp, lend);
703
-						if (cp-lvalue.s != 3 || memcmp(lvalue.s, "IP4", 3) != 0) {
704
-							goto invalidate;
705
-						}
706
-						cp = eat_space_end(cp, lend);
707
-						lvalue.s = cp;
708
-						cp = eat_token_end(cp, lend);
709
-						lvalue.len = cp-lvalue.s;
710
-						if (lvalue.len == 0 || q_memchr(lvalue.s, '/', lvalue.len)) {
711
-							/* multicast address not supported */
712
-							goto invalidate;
713
-						}
714
-						if (sess_fl == 1) {
715
-							cline_ip_s = lvalue;
716
-							cline_ip = s2ip4(&lvalue);
717
-						}
718
-						else {
719
-							sess->media[sess->media_count-1].ip = s2ip4(&lvalue);
720
-							sess->media[sess->media_count-1].active = sess->media[sess->media_count-1].port != 0;  /* IP may by specified by hostname */
721
-							sess->media[sess->media_count-1].ip_s = lvalue;
722
-						}
723
-						break;
724
-					default:
725
-						;
726
-				}
727
-				break;
728
-			invalidate:
729
-				if (sess_fl == 2) {
730
-					sess->media[sess->media_count-1].active = 0;
731
-				}
732
-				break;
733
-			case 'm':
734
-				/* Media Announcements: m=<media> <port>[/<number of ports>] <transport> <fmt list>, eg. m=audio 49170 RTP/AVP 0 */
735
-				/* media: "audio", "video", "application", "data" and "control" */
736
-				switch (sess_fl) {
737
-					case 0:
738
-						ERR(MODULE_NAME": parse_sdp_content: m= line is not in session section\n");
739
-						return -1;
740
-					case 1:
741
-					case 2:
742
-						if (sess->media_count >= MAX_MEDIA_NUMBER) {
743
-							ERR(MODULE_NAME": parse_sdp_content: max.number of medias (%d) exceeded\n", MAX_MEDIA_NUMBER);
744
-							return -1;
745
-						}
746
-						cline_count = 0;
747
-						sess_fl = 2;
748
-						sess->media_count++;
749
-						sess->media[sess->media_count-1].active = 0;
750
-						sess->media[sess->media_count-1].port = 0;
751
-						sess->media[sess->media_count-1].send_rec_modifier = sess_send_rec_modifier;
752
-						cp = eat_token_end(lvalue.s, lend);
753
-						lvalue.len = cp-lvalue.s;
754
-						sess->media[sess->media_count-1].media_type = name2media_type(&lvalue);;
755
-						if (!lvalue.len) {
756
-							break;
757
-						}
758
-						cp = eat_space_end(cp, lend);
759
-						lvalue.s = cp;
760
-						cp = eat_token_end(cp, lend);
761
-						lvalue.len = cp-lvalue.s;
762
-						
763
-						cp2 = q_memchr(lvalue.s, '/', lvalue.len);
764
-						if (cp2) {
765
-							/* strip optional number of ports, if present should be 2 */
766
-							lvalue.len = cp2-lvalue.s;
767
-						}
768
-						sess->media[sess->media_count-1].port_s = lvalue;
769
-						if (lvalue.len == 0) { /* invalid port? */
770
-							break;
771
-						}
772
-						savec = lvalue.s[lvalue.len];
773
-						lvalue.s[lvalue.len] = '\0';
774
-						sess->media[sess->media_count-1].port = atol(lvalue.s);
775
-						lvalue.s[lvalue.len] = savec;
776
-						if (sess->media[sess->media_count-1].port == 0) {
777
-							break;
778
-						}
779
-						cp = eat_space_end(cp, lend);
780
-						
781
-						lvalue.s = cp;
782
-						cp = eat_token_end(cp, lend);
783
-						lvalue.len = cp-lvalue.s;
784
-						if (name2enum(&lvalue, &supported_protocols) >= 0) {
785
-							sess->media[sess->media_count-1].active = cline_ip_s.len != 0;  /* IP may by specified by hostname */
786
-							sess->media[sess->media_count-1].ip_s = cline_ip_s;
787
-							sess->media[sess->media_count-1].ip = cline_ip;
788
-						}
789
-						/* get payload types */
790
-						sess->media[sess->media_count-1].codecs = (struct sdp_codec (*)[]) (codecs + codec_count);
791
-						while (cp < lend) {
792
-							if (codec_count >= MAX_CODEC_NUMBER) {
793
-								ERR(MODULE_NAME": parse_sdp_content: max.number of codecs (%d) exceeded\n", MAX_CODEC_NUMBER);
794
-								return -1;
795
-							}
796
-							codecs[codec_count].mline_payload_type_s.s = cp;
797
-							cp = eat_space_end(cp, lend);
798
-							lvalue.s = cp;
799
-							cp = eat_token_end(cp, lend);
800
-							codecs[codec_count].mline_payload_type_s.len = cp - codecs[codec_count].mline_payload_type_s.s;
801
-							lvalue.len = cp-lvalue.s;
802
-							savec = lvalue.s[lvalue.len];
803
-							lvalue.s[lvalue.len] = '\0';
804
-							codecs[codec_count].payload_type = atol(lvalue.s);
805
-							if (codecs[codec_count].payload_type < MAX_FIXED_PAYLOAD_TYPES) {
806
-								codecs[codec_count].codec_id = fixed_payload_types[codecs[codec_count].payload_type].codec_id;
807
-							}
808
-							lvalue.s[lvalue.len] = savec;
809
-							for (i=0; i < sess->media[sess->media_count-1].codec_count; i++) {
810
-								if (codecs[codec_count].payload_type == (*sess->media[sess->media_count-1].codecs)[i].payload_type) {
811
-									ERR(MODULE_NAME": parse_sdp_content: duplicate payload type in '%.*s'\n", (int) (lend-line.s), line.s);
812
-									return -1;
813
-								}
814
-							}
815
-							codec_count++;
816
-							sess->media[sess->media_count-1].codec_count++;							
817
-						}
818
-						if (!sess->media[sess->media_count-1].codec_count) {
819
-							ERR(MODULE_NAME": parse_sdp_content: no codec declared '%.*s'\n", (int) (lend-line.s), line.s);
820
-							return -1;
821
-						}
822
-						break;
823
-					default:
824
-						;
825
-				}
826
-
827
-				break;
828
-			case 'a':
829
-				i = name2enum(&lvalue, &send_rec_modifiers);
830
-				if (i > 0) {
831
-					switch (sess_fl) {
832
-						case 1:
833
-							if (sess_send_rec_modifier) {
834
-								ERR(MODULE_NAME": parse_sdp_content: duplicate send/recv modifier in session '%.*s'\n", (int) (lend-line.s), line.s);
835
-								return -1;
836
-							}
837
-							sess_send_rec_modifier = i;
838
-							break;
839
-						case 2:
840
-							if (sess->media[sess->media_count-1].send_rec_modifier_line_s.s) {
841
-								ERR(MODULE_NAME": parse_sdp_content: duplicate send/recv modifier in stream '%.*s'\n", (int) (lend-line.s), line.s);
842
-								return -1;
843
-							}
844
-							sess->media[sess->media_count-1].send_rec_modifier = i;
845
-							sess->media[sess->media_count-1].send_rec_modifier_line_s = line;
846
-						default:
847
-							;
848
-					}
849
-				}
850
-				else if (sess_fl == 2) {
851
-					int payload_type;
852
-					int a_attr;
853
-					a_attr = prefix2enum(&lvalue, &a_attrs);
854
-					if (a_attr < 0) {
855
-						break;
856
-					}
857
-					lend = lvalue.s + lvalue.len;
858
-					lvalue.s += a_attrs[a_attr].len;
859
-					switch (a_attr) {
860
-						case sdpaattr_rtpmap:
861
-							/* a=rtpmap:<payload type> <encoding name>/<clock rate>[/<encoding parameters>] , max.one a=rtpmap: per codec */
862
-						case sdpaattr_fmtp:
863
-							/* a=fmtp:<format/payload type> <format specific params>, max.one a=fmtp: per codec */
864
-
865
-							/* we validate only things important for us. Other thinkgs not important we leave up to UA. Not tested:
866
-							   - payload order of a:rtpmap corresponds to m= line
867
-							   - all dynamic payloads have cooresponding a:rtpmap line (for us it's unknown codec)
868
-							   - if static payload type corresponds to codec, i.e. e.g. if 0 is PCMU
869
-							 */
870
-							cp = eat_token_end(lvalue.s, lend);
871
-							lvalue.len = cp-lvalue.s;
872
-							savec = lvalue.s[lvalue.len];
873
-							lvalue.s[lvalue.len] = '\0';
874
-							payload_type = atol(lvalue.s);
875
-							lvalue.s[lvalue.len] = savec;
876
-							for (i=0; i < sess->media[sess->media_count-1].codec_count; i++) {
877
-								if ((*sess->media[sess->media_count-1].codecs)[i].payload_type == payload_type) {
878
-									goto found;
879
-								}
880
-							}
881
-							ERR(MODULE_NAME": parse_sdp_content: '%.*s' payload type (%d) has not been mentioned at m= line\n", (int) (lend-line.s), line.s, payload_type);
882
-							return -1;
883
-						found:
884
-							cp = eat_space_end(cp, lend);
885
-							switch (a_attr) {
886
-								case sdpaattr_rtpmap:
887
-									if ((*sess->media[sess->media_count-1].codecs)[i].a_rtpmap_line_s.s) {
888
-										ERR(MODULE_NAME": parse_sdp_content: '%.*s' multiple a=rtpmap lines for payload type (%d)\n", (int) (lend-line.s), line.s, payload_type);
889
-										return -1;
890
-
891
-									}
892
-									(*sess->media[sess->media_count-1].codecs)[i].a_rtpmap_line_s = line;
893
-									lvalue.s = cp;
894
-									cp = eat_token2_end(cp, lend, '/');
895
-									lvalue.len = cp-lvalue.s;
896
-									(*sess->media[sess->media_count-1].codecs)[i].codec_id = name2codec_id(&lvalue, NULL);
897
-									break;
898
-								case sdpaattr_fmtp:
899
-									if ((*sess->media[sess->media_count-1].codecs)[i].a_fmtp_line_s.s) {
900
-										ERR(MODULE_NAME": parse_sdp_content: '%.*s' multiple a=fmtp lines for payload type (%d)\n", (int) (lend-line.s), line.s, payload_type);