belle_sdp_impl.c 69.6 KB
Newer Older
jehan's avatar
jehan committed
1
/*
2 3
	belle-sip - SIP (RFC3261) library.
	Copyright (C) 2010-2018  Belledonne Communications SARL
jehan's avatar
jehan committed
4

5 6 7 8
	This program is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 2 of the License, or
	(at your option) any later version.
jehan's avatar
jehan committed
9

10 11 12 13
	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.
jehan's avatar
jehan committed
14

15 16
	You should have received a copy of the GNU General Public License
	along with this program.  If not, see <http://www.gnu.org/licenses/>.
jehan's avatar
jehan committed
17
*/
18

jehan's avatar
jehan committed
19
#include "belle-sip/belle-sip.h"
20 21
#include "grammars/belle_sdpParser.h"
#include "grammars/belle_sdpLexer.h"
jehan's avatar
jehan committed
22
#include "belle_sip_internal.h"
23 24 25 26 27 28 29 30 31 32 33 34 35 36


struct _belle_sdp_mime_parameter {
	belle_sip_object_t base;
	int rate;
	int channel_count;
	int ptime;
	int max_ptime;
	int media_format;
	const char* type;
	const char* parameters;

};

37 38 39 40 41 42 43

static void belle_sip_object_freefunc(void* obj) {
	belle_sip_object_unref(BELLE_SIP_OBJECT(obj));
}
static void* belle_sip_object_copyfunc(void* obj) {
	return belle_sip_object_clone_and_ref(BELLE_SIP_OBJECT(obj));
}
44 45 46
static void * belle_sip_string_copyfunc(void *obj) {
	return (void *)belle_sip_strdup((const char *)obj);
}
47 48


jehan's avatar
jehan committed
49 50 51 52
/***************************************************************************************
 * Attribute
 *
 **************************************************************************************/
53 54 55 56 57 58
typedef belle_sdp_attribute_t* (*attribute_parse_func)(const char*) ;
struct attribute_name_func_pair {
	const char* name;
	attribute_parse_func func;
};
static struct attribute_name_func_pair attribute_table[] = {
59
	{ "rtcp-fb", (attribute_parse_func)belle_sdp_rtcp_fb_attribute_parse },
60 61
	{ "rtcp-xr", (attribute_parse_func)belle_sdp_rtcp_xr_attribute_parse }
};
jehan's avatar
jehan committed
62 63 64
struct _belle_sdp_attribute {
	belle_sip_object_t base;
	const char* name;
65
	char *unparsed_value;
jehan's avatar
jehan committed
66 67
};
void belle_sdp_attribute_destroy(belle_sdp_attribute_t* attribute) {
68
	DESTROY_STRING(attribute,name)
Simon Morlat's avatar
Simon Morlat committed
69
	DESTROY_STRING(attribute,unparsed_value)
jehan's avatar
jehan committed
70 71
}
void belle_sdp_attribute_clone(belle_sdp_attribute_t *attribute, const belle_sdp_attribute_t *orig){
72
	CLONE_STRING(belle_sdp_attribute,name,attribute,orig)
jehan's avatar
jehan committed
73
}
74
belle_sip_error_code belle_sdp_attribute_marshal(belle_sdp_attribute_t* attribute, char* buff, size_t buff_size, size_t *offset) {
75 76 77 78
	return belle_sip_snprintf(buff, buff_size, offset, "a=%s", attribute->name);
}
belle_sdp_attribute_t* belle_sdp_attribute_create(const char* name, const char* value) {
	belle_sdp_attribute_t* ret;
79
	size_t i;
80 81 82 83 84 85 86 87 88
	size_t elements = sizeof(attribute_table) / sizeof(attribute_table[0]);

	if (!name || name[0] == '\0') {
		belle_sip_error("Cannot create SDP attribute without name");
		return NULL;
	}

	for (i = 0; i < elements; i++) {
		if (strcasecmp(attribute_table[i].name, name) == 0) {
jehan's avatar
jehan committed
89 90 91 92 93
			char* raw;
			if (value)
				raw = belle_sip_strdup_printf("a=%s:%s", name, value);
			else
				raw = belle_sip_strdup_printf("a=%s", name);
94 95 96 97 98 99 100 101
			ret = attribute_table[i].func(raw);
			belle_sip_free(raw);
			return ret;
		}
	}
	/* Not a specialized SDP attribute */
	return BELLE_SDP_ATTRIBUTE(belle_sdp_raw_attribute_create(name, value));
}
102 103 104 105
const char *belle_sdp_attribute_get_value(belle_sdp_attribute_t *attribute) {
	char *ret;
	char *end;

106

107 108 109 110 111
	if (attribute->unparsed_value) {
		belle_sip_free(attribute->unparsed_value);
		attribute->unparsed_value = NULL;
	}
	attribute->unparsed_value = belle_sip_object_to_string(attribute);
112

113
	ret = attribute->unparsed_value;
114 115 116
	ret += strlen(attribute->name) + 2; /* "a=" + name*/
	if (*ret==':') ret++;
	for (; *ret == ' '; ret++) {}; /* skip eventual spaces */
117 118 119 120 121
	return ret;
}
unsigned int belle_sdp_attribute_has_value(belle_sdp_attribute_t* attribute) {
	return belle_sdp_attribute_get_value(attribute) != NULL;
}
122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
BELLE_SDP_NEW(attribute,belle_sip_object)
BELLE_SDP_PARSE(attribute)
GET_SET_STRING(belle_sdp_attribute,name);
/***************************************************************************************
 * RAW Attribute
 *
 **************************************************************************************/
struct _belle_sdp_raw_attribute {
	belle_sdp_attribute_t base;
	const char* value;
};
void belle_sdp_raw_attribute_destroy(belle_sdp_raw_attribute_t* attribute) {
	DESTROY_STRING(attribute,value)
}
void belle_sdp_raw_attribute_clone(belle_sdp_raw_attribute_t* attribute, const belle_sdp_raw_attribute_t* orig) {
137 138 139
	if (belle_sdp_attribute_get_value(BELLE_SDP_ATTRIBUTE(orig))) {
		belle_sdp_raw_attribute_set_value(attribute, belle_sdp_attribute_get_value(BELLE_SDP_ATTRIBUTE(orig)));
	}
140 141 142 143
}
belle_sip_error_code belle_sdp_raw_attribute_marshal(belle_sdp_raw_attribute_t* attribute, char* buff, size_t buff_size, size_t* offset) {
	belle_sip_error_code error = belle_sdp_attribute_marshal(BELLE_SDP_ATTRIBUTE(attribute), buff, buff_size, offset);
	if (error != BELLE_SIP_OK) return error;
jehan's avatar
jehan committed
144
	if (attribute->value) {
145 146
		error = belle_sip_snprintf(buff, buff_size, offset, ":%s", attribute->value);
		if (error != BELLE_SIP_OK) return error;
jehan's avatar
jehan committed
147
	}
Ghislain MARY's avatar
Ghislain MARY committed
148
	return error;
jehan's avatar
jehan committed
149
}
150 151 152 153 154
BELLE_SDP_NEW(raw_attribute,belle_sdp_attribute)
belle_sdp_raw_attribute_t* belle_sdp_raw_attribute_create(const char* name, const char* value) {
	belle_sdp_raw_attribute_t* attribute = belle_sdp_raw_attribute_new();
	belle_sdp_attribute_set_name(BELLE_SDP_ATTRIBUTE(attribute), name);
	belle_sdp_raw_attribute_set_value(attribute, value);
jehan's avatar
jehan committed
155 156
	return attribute;
}
157 158 159 160 161
void belle_sdp_raw_attribute_set_value(belle_sdp_raw_attribute_t* attribute, const char* value) {
	if (attribute->value != NULL) belle_sip_free((void*)attribute->value);
	if (value) {
		attribute->value = belle_sip_strdup(value);
	} else attribute->value = NULL;
jehan's avatar
jehan committed
162
}
163 164 165 166 167 168 169 170
/***************************************************************************************
 * RTCP-FB Attribute
 *
 **************************************************************************************/
struct _belle_sdp_rtcp_fb_attribute {
	belle_sdp_attribute_t base;
	belle_sdp_rtcp_fb_val_type_t type;
	belle_sdp_rtcp_fb_val_param_t param;
171
	uint32_t smaxpr;
172
	uint16_t trr_int;
173
	int8_t id;
174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189
};
BELLESIP_EXPORT unsigned int belle_sdp_rtcp_fb_attribute_has_pli(const belle_sdp_rtcp_fb_attribute_t* attribute);
BELLESIP_EXPORT void belle_sdp_rtcp_fb_attribute_set_pli(belle_sdp_rtcp_fb_attribute_t* attribute, unsigned int enable);
BELLESIP_EXPORT unsigned int belle_sdp_rtcp_fb_attribute_has_sli(const belle_sdp_rtcp_fb_attribute_t* attribute);
BELLESIP_EXPORT void belle_sdp_rtcp_fb_attribute_set_sli(belle_sdp_rtcp_fb_attribute_t* attribute, unsigned int enable);
BELLESIP_EXPORT unsigned int belle_sdp_rtcp_fb_attribute_has_rpsi(const belle_sdp_rtcp_fb_attribute_t* attribute);
BELLESIP_EXPORT void belle_sdp_rtcp_fb_attribute_set_rpsi(belle_sdp_rtcp_fb_attribute_t* attribute, unsigned int enable);
BELLESIP_EXPORT unsigned int belle_sdp_rtcp_fb_attribute_has_app(const belle_sdp_rtcp_fb_attribute_t* attribute);
BELLESIP_EXPORT void belle_sdp_rtcp_fb_attribute_set_app(belle_sdp_rtcp_fb_attribute_t* attribute, unsigned int enable);
void belle_sdp_rtcp_fb_attribute_destroy(belle_sdp_rtcp_fb_attribute_t* attribute) {
}
void belle_sdp_rtcp_fb_attribute_clone(belle_sdp_rtcp_fb_attribute_t* attribute, const belle_sdp_rtcp_fb_attribute_t *orig) {
	attribute->type = orig->type;
	attribute->param = orig->param;
	attribute->trr_int = orig->trr_int;
	attribute->id = orig->id;
190
	attribute->smaxpr = orig->smaxpr;
191 192
}
belle_sip_error_code belle_sdp_rtcp_fb_attribute_marshal(belle_sdp_rtcp_fb_attribute_t* attribute, char * buff, size_t buff_size, size_t *offset) {
193
	int8_t id = belle_sdp_rtcp_fb_attribute_get_id(attribute);
194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243
	belle_sdp_rtcp_fb_val_type_t type = belle_sdp_rtcp_fb_attribute_get_type(attribute);
	belle_sdp_rtcp_fb_val_param_t param = belle_sdp_rtcp_fb_attribute_get_param(attribute);
	belle_sip_error_code error = belle_sdp_attribute_marshal(BELLE_SDP_ATTRIBUTE(attribute), buff, buff_size, offset);
	if (error != BELLE_SIP_OK) return error;
	if (id < 0) {
		error = belle_sip_snprintf(buff, buff_size, offset, ":* ");
	} else {
		error = belle_sip_snprintf(buff, buff_size, offset, ":%u ", id);
	}
	if (error != BELLE_SIP_OK) return error;
	switch (type) {
		case BELLE_SDP_RTCP_FB_ACK:
			error = belle_sip_snprintf(buff, buff_size, offset, "ack");
			if (error != BELLE_SIP_OK) return error;
			switch (param) {
				default:
				case BELLE_SDP_RTCP_FB_NONE:
					break;
				case BELLE_SDP_RTCP_FB_RPSI:
					error = belle_sip_snprintf(buff, buff_size, offset, " rpsi");
					break;
				case BELLE_SDP_RTCP_FB_APP:
					error = belle_sip_snprintf(buff, buff_size, offset, " app");
					break;
			}
			break;
		case BELLE_SDP_RTCP_FB_NACK:
			error = belle_sip_snprintf(buff, buff_size, offset, "nack");
			if (error != BELLE_SIP_OK) return error;
			switch (param) {
				default:
				case BELLE_SDP_RTCP_FB_NONE:
					break;
				case BELLE_SDP_RTCP_FB_PLI:
					error = belle_sip_snprintf(buff, buff_size, offset, " pli");
					break;
				case BELLE_SDP_RTCP_FB_SLI:
					error = belle_sip_snprintf(buff, buff_size, offset, " sli");
					break;
				case BELLE_SDP_RTCP_FB_RPSI:
					error = belle_sip_snprintf(buff, buff_size, offset, " rpsi");
					break;
				case BELLE_SDP_RTCP_FB_APP:
					error = belle_sip_snprintf(buff, buff_size, offset, " app");
					break;
			}
			break;
		case BELLE_SDP_RTCP_FB_TRR_INT:
			error = belle_sip_snprintf(buff, buff_size, offset, "trr-int %u", belle_sdp_rtcp_fb_attribute_get_trr_int(attribute));
			break;
244 245 246 247 248 249 250
		case BELLE_SDP_RTCP_FB_CCM:
			error = belle_sip_snprintf(buff, buff_size, offset, "ccm");
			if (error != BELLE_SIP_OK) return error;
			switch (param) {
				case BELLE_SDP_RTCP_FB_FIR:
					error = belle_sip_snprintf(buff, buff_size, offset, " fir");
					break;
251 252 253 254 255 256
				case BELLE_SDP_RTCP_FB_TMMBR:
					error = belle_sip_snprintf(buff, buff_size, offset, " tmmbr");
					if (belle_sdp_rtcp_fb_attribute_get_smaxpr(attribute) > 0) {
						error = belle_sip_snprintf(buff, buff_size, offset, " smaxpr=%u", belle_sdp_rtcp_fb_attribute_get_smaxpr(attribute));
					}
					break;
257 258 259 260
				default:
					break;
			}
			break;
261 262 263 264 265 266 267 268 269
	}
	return error;
}
static void belle_sdp_rtcp_fb_attribute_init(belle_sdp_rtcp_fb_attribute_t* attribute) {
	belle_sdp_attribute_set_name(BELLE_SDP_ATTRIBUTE(attribute), "rtcp-fb");
	attribute->id = -1;
	attribute->type = BELLE_SDP_RTCP_FB_TRR_INT;
	attribute->param = BELLE_SDP_RTCP_FB_NONE;
	attribute->trr_int = 0;
270
	attribute->smaxpr = 0;
271 272 273
}
BELLE_SDP_NEW_WITH_CTR(rtcp_fb_attribute,belle_sdp_attribute)
BELLE_SDP_PARSE(rtcp_fb_attribute)
274
GET_SET_INT(belle_sdp_rtcp_fb_attribute,id,int8_t)
275 276
GET_SET_INT(belle_sdp_rtcp_fb_attribute,type,belle_sdp_rtcp_fb_val_type_t)
GET_SET_INT(belle_sdp_rtcp_fb_attribute,param,belle_sdp_rtcp_fb_val_param_t)
277
GET_SET_INT(belle_sdp_rtcp_fb_attribute,trr_int,uint16_t)
278
GET_SET_INT(belle_sdp_rtcp_fb_attribute,smaxpr,uint32_t)
279 280 281 282 283 284 285 286 287 288 289 290
/***************************************************************************************
 * RTCP-XR Attribute
 *
 **************************************************************************************/
struct _belle_sdp_rtcp_xr_attribute {
	belle_sdp_attribute_t base;
	const char* rcvr_rtt_mode;
	int rcvr_rtt_max_size;
	unsigned int stat_summary;
	belle_sip_list_t* stat_summary_flags;
	unsigned int voip_metrics;
};
291
const belle_sip_list_t* belle_sdp_rtcp_xr_attribute_get_stat_summary_flags(const belle_sdp_rtcp_xr_attribute_t* attribute) {
292 293 294 295 296 297 298
	return attribute->stat_summary_flags;
}
void belle_sdp_rtcp_xr_attribute_add_stat_summary_flag(belle_sdp_rtcp_xr_attribute_t* attribute, const char* flag) {
	attribute->stat_summary_flags = belle_sip_list_append(attribute->stat_summary_flags, belle_sip_strdup(flag));
}
void belle_sdp_rtcp_xr_attribute_destroy(belle_sdp_rtcp_xr_attribute_t* attribute) {
	DESTROY_STRING(attribute,rcvr_rtt_mode)
299
	belle_sip_list_free_with_data(attribute->stat_summary_flags, belle_sip_free);
300 301 302 303 304
}
void belle_sdp_rtcp_xr_attribute_clone(belle_sdp_rtcp_xr_attribute_t* attribute, const belle_sdp_rtcp_xr_attribute_t *orig) {
	CLONE_STRING(belle_sdp_rtcp_xr_attribute,rcvr_rtt_mode,attribute,orig)
	attribute->rcvr_rtt_max_size = orig->rcvr_rtt_max_size;
	attribute->stat_summary = orig->stat_summary;
305
	attribute->stat_summary_flags = belle_sip_list_copy_with_data(orig->stat_summary_flags, belle_sip_string_copyfunc);
306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348
	attribute->voip_metrics = orig->voip_metrics;
}
belle_sip_error_code belle_sdp_rtcp_xr_attribute_marshal(belle_sdp_rtcp_xr_attribute_t* attribute, char * buff, size_t buff_size, size_t *offset) {
	const char *rcvr_rtt_mode = NULL;
	int rcvr_rtt_max_size = -1;
	int nb_xr_formats = 0;
	belle_sip_error_code error = belle_sdp_attribute_marshal(BELLE_SDP_ATTRIBUTE(attribute), buff, buff_size, offset);
	if (error != BELLE_SIP_OK) return error;
	rcvr_rtt_mode = belle_sdp_rtcp_xr_attribute_get_rcvr_rtt_mode(attribute);
	if (rcvr_rtt_mode != NULL) {
		error = belle_sip_snprintf(buff, buff_size, offset, "%srcvr-rtt=%s", nb_xr_formats++ == 0 ? ":" : " ", rcvr_rtt_mode);
		if (error != BELLE_SIP_OK) return error;
		rcvr_rtt_max_size = belle_sdp_rtcp_xr_attribute_get_rcvr_rtt_max_size(attribute);
		if (rcvr_rtt_max_size > 0) {
			error = belle_sip_snprintf(buff, buff_size, offset, ":%u", rcvr_rtt_max_size);
			if (error != BELLE_SIP_OK) return error;
		}
	}
	if (belle_sdp_rtcp_xr_attribute_has_stat_summary(attribute)) {
		belle_sip_list_t* list;
		int nb_stat_flags = 0;
		error = belle_sip_snprintf(buff, buff_size, offset, "%sstat-summary", nb_xr_formats++ == 0 ? ":" : " ");
		if (error != BELLE_SIP_OK) return error;
		for (list = attribute->stat_summary_flags; list != NULL; list = list->next) {
			error = belle_sip_snprintf(buff, buff_size, offset, "%s%s", nb_stat_flags++ == 0 ? "=" : ",", (const char*)list->data);
			if (error != BELLE_SIP_OK) return error;
		}
	}
	if (belle_sdp_rtcp_xr_attribute_has_voip_metrics(attribute)) {
		error = belle_sip_snprintf(buff, buff_size, offset, "%svoip-metrics", nb_xr_formats++ == 0 ? ":" : " ");
		if (error != BELLE_SIP_OK) return error;
	}
	return error;
}
static void belle_sdp_rtcp_xr_attribute_init(belle_sdp_rtcp_xr_attribute_t* attribute) {
	belle_sdp_attribute_set_name(BELLE_SDP_ATTRIBUTE(attribute), "rtcp-xr");
}
BELLE_SDP_NEW_WITH_CTR(rtcp_xr_attribute,belle_sdp_attribute)
BELLE_SDP_PARSE(rtcp_xr_attribute)
GET_SET_STRING(belle_sdp_rtcp_xr_attribute,rcvr_rtt_mode)
GET_SET_INT(belle_sdp_rtcp_xr_attribute,rcvr_rtt_max_size,int)
GET_SET_BOOL(belle_sdp_rtcp_xr_attribute,stat_summary,has)
GET_SET_BOOL(belle_sdp_rtcp_xr_attribute,voip_metrics,has)
349 350 351 352 353 354 355 356 357 358
/***************************************************************************************
 * Bandwidth
 *
 **************************************************************************************/
struct _belle_sdp_bandwidth {
	belle_sip_object_t base;
	const char* type;
	int value;
};
void belle_sdp_bandwidth_destroy(belle_sdp_bandwidth_t* bandwidth) {
359
	if (bandwidth->type) belle_sip_free((void*)bandwidth->type);
360 361 362
}

void belle_sdp_bandwidth_clone(belle_sdp_bandwidth_t *bandwidth, const belle_sdp_bandwidth_t *orig){
363 364
	CLONE_STRING(belle_sdp_bandwidth,type,bandwidth,orig)
	bandwidth->value=orig->value;
365
}
Ghislain MARY's avatar
Ghislain MARY committed
366

367
belle_sip_error_code belle_sdp_bandwidth_marshal(belle_sdp_bandwidth_t* bandwidth, char* buff, size_t buff_size, size_t *offset) {
Ghislain MARY's avatar
Ghislain MARY committed
368
	return belle_sip_snprintf(buff,buff_size,offset,"b=%s:%i",bandwidth->type,bandwidth->value);
369
}
Ghislain MARY's avatar
Ghislain MARY committed
370

371 372 373 374
BELLE_SDP_NEW(bandwidth,belle_sip_object)
BELLE_SDP_PARSE(bandwidth)
GET_SET_STRING(belle_sdp_bandwidth,type);
GET_SET_INT(belle_sdp_bandwidth,value,int)
jehan's avatar
jehan committed
375 376 377 378 379 380 381 382 383

/************************
 * connection
 ***********************/
struct _belle_sdp_connection {
	belle_sip_object_t base;
	const char* network_type;
	const char* address_type;
	const char* address;
384 385
	int ttl;
	int range;
jehan's avatar
jehan committed
386 387 388
 };

void belle_sdp_connection_destroy(belle_sdp_connection_t* connection) {
jehan's avatar
jehan committed
389 390 391
	DESTROY_STRING(connection,network_type)
	DESTROY_STRING(connection,address_type)
	DESTROY_STRING(connection,address)
jehan's avatar
jehan committed
392 393 394
}

void belle_sdp_connection_clone(belle_sdp_connection_t *connection, const belle_sdp_connection_t *orig){
jehan's avatar
jehan committed
395 396 397
	CLONE_STRING(belle_sdp_connection,network_type,connection,orig)
	CLONE_STRING(belle_sdp_connection,address_type,connection,orig)
	CLONE_STRING(belle_sdp_connection,address,connection,orig)
398 399
	connection->range=orig->range;
	connection->ttl=orig->ttl;
jehan's avatar
jehan committed
400
}
Ghislain MARY's avatar
Ghislain MARY committed
401

402
belle_sip_error_code belle_sdp_connection_marshal(belle_sdp_connection_t* connection, char* buff, size_t buff_size, size_t *offset) {
403 404 405 406 407 408 409 410
	belle_sip_error_code error = belle_sip_snprintf(buff,buff_size,offset,"c=%s %s %s",connection->network_type,connection->address_type,connection->address);
	if (error!=BELLE_SIP_OK) return error;
	if (connection->ttl>0)
		error = belle_sip_snprintf(buff,buff_size,offset,"/%i",connection->ttl);
	if (error!=BELLE_SIP_OK) return error;
	if (connection->range>0)
		error = belle_sip_snprintf(buff,buff_size,offset,"/%i",connection->range);
	return error;
jehan's avatar
jehan committed
411
}
Ghislain MARY's avatar
Ghislain MARY committed
412

jehan's avatar
jehan committed
413 414
BELLE_SDP_NEW(connection,belle_sip_object)
BELLE_SDP_PARSE(connection)
jehan's avatar
jehan committed
415 416 417 418 419 420 421
belle_sdp_connection_t* belle_sdp_connection_create(const char* net_type, const char* addr_type, const char* addr) {
	belle_sdp_connection_t* connection = belle_sdp_connection_new();
	belle_sdp_connection_set_network_type(connection,net_type);
	belle_sdp_connection_set_address_type(connection,addr_type);
	belle_sdp_connection_set_address(connection,addr);
	return connection;
}
jehan's avatar
jehan committed
422 423 424
GET_SET_STRING(belle_sdp_connection,network_type);
GET_SET_STRING(belle_sdp_connection,address_type);
GET_SET_STRING(belle_sdp_connection,address);
425 426
GET_SET_INT(belle_sdp_connection,ttl,int);
GET_SET_INT(belle_sdp_connection,range,int);
427 428 429 430 431
/************************
 * email
 ***********************/
struct _belle_sdp_email {
	belle_sip_object_t base;
432
	char* value;
433 434 435
 };

void belle_sdp_email_destroy(belle_sdp_email_t* email) {
jehan's avatar
jehan committed
436
	DESTROY_STRING(email,value)
437 438 439
}

void belle_sdp_email_clone(belle_sdp_email_t *email, const belle_sdp_email_t *orig){
jehan's avatar
jehan committed
440
	CLONE_STRING(belle_sdp_email,value,email,orig)
441
}
Ghislain MARY's avatar
Ghislain MARY committed
442

443
belle_sip_error_code belle_sdp_email_marshal(belle_sdp_email_t* email, char* buff, size_t buff_size, size_t *offset) {
Ghislain MARY's avatar
Ghislain MARY committed
444
	return belle_sip_snprintf(buff,buff_size,offset,"e=%s",email->value);
445
}
Ghislain MARY's avatar
Ghislain MARY committed
446

447 448 449 450 451 452 453 454 455 456 457 458
BELLE_SDP_NEW(email,belle_sip_object)
BELLE_SDP_PARSE(email)
GET_SET_STRING(belle_sdp_email,value);
/************************
 * info
 ***********************/
struct _belle_sdp_info {
	belle_sip_object_t base;
	const char* value;
 };

void belle_sdp_info_destroy(belle_sdp_info_t* info) {
jehan's avatar
jehan committed
459
	DESTROY_STRING(info,value)
460 461 462
}

void belle_sdp_info_clone(belle_sdp_info_t *info, const belle_sdp_info_t *orig){
jehan's avatar
jehan committed
463
	CLONE_STRING(belle_sdp_info,value,info,orig)
464
}
Ghislain MARY's avatar
Ghislain MARY committed
465

466
belle_sip_error_code belle_sdp_info_marshal(belle_sdp_info_t* info, char* buff, size_t buff_size, size_t *offset) {
Ghislain MARY's avatar
Ghislain MARY committed
467
	return belle_sip_snprintf(buff,buff_size,offset,"i=%s",info->value);
468
}
Ghislain MARY's avatar
Ghislain MARY committed
469

470 471 472 473 474 475 476 477
BELLE_SDP_NEW(info,belle_sip_object)
BELLE_SDP_PARSE(info)
GET_SET_STRING(belle_sdp_info,value);
/************************
 * media
 ***********************/
struct _belle_sdp_media {
	belle_sip_object_t base;
jehan's avatar
jehan committed
478
	const char* media_type;
479 480 481
	int media_port;
	belle_sip_list_t* media_formats;
	int port_count;
jehan's avatar
jehan committed
482
	const char* protocol;
483
	const char* raw_fmt;
484
 };
jehan's avatar
jehan committed
485 486 487 488
belle_sip_list_t*	belle_sdp_media_get_media_formats(const belle_sdp_media_t* media) {
	return media->media_formats;
}
void belle_sdp_media_set_media_formats( belle_sdp_media_t* media, belle_sip_list_t* formats) {
jehan's avatar
jehan committed
489
	/*belle_sip_list_free(media->media_formats); to allow easy list management might be better to add an append format method*/
jehan's avatar
jehan committed
490 491
	media->media_formats = formats;
}
492
void belle_sdp_media_destroy(belle_sdp_media_t* media) {
jehan's avatar
jehan committed
493 494 495
	DESTROY_STRING(media,media_type)
	belle_sip_list_free(media->media_formats);
	DESTROY_STRING(media,protocol)
496
}
jehan's avatar
jehan committed
497 498 499
static void belle_sdp_media_init(belle_sdp_media_t* media) {
	media->port_count=1;
}
500 501

void belle_sdp_media_clone(belle_sdp_media_t *media, const belle_sdp_media_t *orig){
jehan's avatar
jehan committed
502 503 504 505 506
	CLONE_STRING(belle_sdp_media,media_type,media,orig)
	media->media_port=orig->media_port;
	media->media_formats = belle_sip_list_copy(orig->media_formats);
	media->port_count=orig->port_count;
	CLONE_STRING(belle_sdp_media,protocol,media,orig)
507
}
Ghislain MARY's avatar
Ghislain MARY committed
508

509
belle_sip_error_code belle_sdp_media_marshal(belle_sdp_media_t* media, char* buff, size_t buff_size, size_t *offset) {
jehan's avatar
jehan committed
510
	belle_sip_list_t* list=media->media_formats;
Ghislain MARY's avatar
Ghislain MARY committed
511
	belle_sip_error_code error=belle_sip_snprintf(buff,buff_size,offset,"m=%s %i",media->media_type,media->media_port);
512
	if (error!=BELLE_SIP_OK) return error;
jehan's avatar
jehan committed
513
	if (media->port_count>1) {
Ghislain MARY's avatar
Ghislain MARY committed
514
		error=belle_sip_snprintf(buff,buff_size,offset,"/%i",media->port_count);
515
		if (error!=BELLE_SIP_OK) return error;
jehan's avatar
jehan committed
516
	}
Ghislain MARY's avatar
Ghislain MARY committed
517 518
	error=belle_sip_snprintf(buff,buff_size,offset," %s",media->protocol);
	if (error!=BELLE_SIP_OK) return error;
jehan's avatar
jehan committed
519
	for(;list!=NULL;list=list->next){
520
		error=belle_sip_snprintf(buff,buff_size,offset," %li",(long)(intptr_t)list->data);
521
		if (error!=BELLE_SIP_OK) return error;
jehan's avatar
jehan committed
522
	}
Ghislain MARY's avatar
Ghislain MARY committed
523
	return error;
524
}
Ghislain MARY's avatar
Ghislain MARY committed
525

jehan's avatar
jehan committed
526
BELLE_SDP_NEW_WITH_CTR(media,belle_sip_object)
527
BELLE_SDP_PARSE(media)
jehan's avatar
jehan committed
528
belle_sdp_media_t* belle_sdp_media_create(const char* media_type
529 530 531 532
						 ,int media_port
						 ,int port_count
						 ,const char* protocol
						 ,belle_sip_list_t* static_media_formats) {
jehan's avatar
jehan committed
533 534 535 536 537 538 539 540
	belle_sdp_media_t* media= belle_sdp_media_new();
	belle_sdp_media_set_media_type(media,media_type);
	belle_sdp_media_set_media_port(media,media_port);
	belle_sdp_media_set_port_count(media,port_count);
	belle_sdp_media_set_protocol(media,protocol);
	if (static_media_formats) belle_sdp_media_set_media_formats(media,static_media_formats);
	return media;
}
541
GET_SET_STRING(belle_sdp_media,media_type);
jehan's avatar
jehan committed
542
GET_SET_STRING(belle_sdp_media,protocol);
543 544
GET_SET_INT(belle_sdp_media,media_port,int)
GET_SET_INT(belle_sdp_media,port_count,int)
jehan's avatar
jehan committed
545 546 547 548 549 550 551 552 553 554 555 556

/************************
 * base_description
 ***********************/
typedef struct _belle_sdp_base_description {
	belle_sip_object_t base;
	belle_sdp_info_t* info;
	belle_sdp_connection_t* connection;
	belle_sip_list_t* bandwidths;
	belle_sip_list_t* attributes;
} belle_sdp_base_description_t;

jehan's avatar
jehan committed
557 558 559 560 561
static void belle_sdp_base_description_destroy(belle_sdp_base_description_t* base_description) {
	if (base_description->info) belle_sip_object_unref(BELLE_SIP_OBJECT(base_description->info));
	if (base_description->connection) belle_sip_object_unref(BELLE_SIP_OBJECT(base_description->connection));
	belle_sip_list_free_with_data(base_description->bandwidths,belle_sip_object_freefunc);
	belle_sip_list_free_with_data(base_description->attributes,belle_sip_object_freefunc);
jehan's avatar
jehan committed
562
}
jehan's avatar
jehan committed
563
static void belle_sdp_base_description_init(belle_sdp_base_description_t* base_description) {
jehan's avatar
jehan committed
564
}
jehan's avatar
jehan committed
565
static void belle_sdp_base_description_clone(belle_sdp_base_description_t *base_description, const belle_sdp_base_description_t *orig){
566 567
	if (orig->info) base_description->info = BELLE_SDP_INFO(belle_sip_object_clone_and_ref(BELLE_SIP_OBJECT(orig->info)));
	if (orig->connection) base_description->connection = BELLE_SDP_CONNECTION(belle_sip_object_clone_and_ref(BELLE_SIP_OBJECT(orig->connection)));
jehan's avatar
jehan committed
568 569 570
	base_description->bandwidths = belle_sip_list_copy_with_data(orig->bandwidths,belle_sip_object_copyfunc);
	base_description->attributes = belle_sip_list_copy_with_data(orig->attributes,belle_sip_object_copyfunc);

jehan's avatar
jehan committed
571
}
Ghislain MARY's avatar
Ghislain MARY committed
572

573
belle_sip_error_code belle_sdp_base_description_marshal(belle_sdp_base_description_t* base_description, char* buff, size_t buff_size, size_t *offset) {
Ghislain MARY's avatar
Ghislain MARY committed
574
	belle_sip_error_code error=BELLE_SIP_OK;
jehan's avatar
jehan committed
575
	belle_sip_list_t* bandwidths;
576
//	belle_sip_list_t* attributes;
jehan's avatar
jehan committed
577
	if (base_description->info) {
Ghislain MARY's avatar
Ghislain MARY committed
578 579 580
		error=belle_sip_object_marshal(BELLE_SIP_OBJECT(base_description->info),buff,buff_size,offset);
		if (error!=BELLE_SIP_OK) return error;
		error=belle_sip_snprintf(buff, buff_size, offset, "\r\n");
581
		if (error!=BELLE_SIP_OK) return error;
jehan's avatar
jehan committed
582 583
	}
	if (base_description->connection) {
Ghislain MARY's avatar
Ghislain MARY committed
584 585 586 587
		error=belle_sip_object_marshal(BELLE_SIP_OBJECT(base_description->connection),buff,buff_size,offset);
		if (error!=BELLE_SIP_OK) return error;
		error=belle_sip_snprintf(buff, buff_size, offset, "\r\n");
		if (error!=BELLE_SIP_OK) return error;
jehan's avatar
jehan committed
588 589
	}
	for(bandwidths=base_description->bandwidths;bandwidths!=NULL;bandwidths=bandwidths->next){
Ghislain MARY's avatar
Ghislain MARY committed
590 591 592 593
		error=belle_sip_object_marshal(BELLE_SIP_OBJECT(bandwidths->data),buff,buff_size,offset);
		if (error!=BELLE_SIP_OK) return error;
		error=belle_sip_snprintf(buff, buff_size, offset, "\r\n");
		if (error!=BELLE_SIP_OK) return error;
jehan's avatar
jehan committed
594
	}
595
//	for(attributes=base_description->attributes;attributes!=NULL;attributes=attributes->next){
596 597
//		error=belle_sip_object_marshal(BELLE_SIP_OBJECT(attributes->data),buff,buff_size,offset);
//		error=belle_sip_snprintf(buff, buff_size, offset, "\r\n");
598
//	}
Ghislain MARY's avatar
Ghislain MARY committed
599
	return error;
jehan's avatar
jehan committed
600
}
601 602

BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(belle_sdp_base_description_t);
jehan's avatar
jehan committed
603 604 605 606 607 608
BELLE_SIP_INSTANCIATE_VPTR(belle_sdp_base_description_t
							,belle_sip_object_t
							,belle_sdp_base_description_destroy
							,belle_sdp_base_description_clone
							,belle_sdp_base_description_marshal
							,FALSE);
jehan's avatar
jehan committed
609 610 611 612

static int belle_sdp_base_description_attribute_comp_func(const belle_sdp_attribute_t* a, const char*b) {
	return strcmp(a->name,b);
}
613
belle_sdp_attribute_t*	belle_sdp_base_description_get_attribute(const belle_sdp_base_description_t* base_description, const char* name) {
jehan's avatar
jehan committed
614 615 616
	belle_sip_list_t* attribute;
	attribute = belle_sip_list_find_custom(base_description->attributes, (belle_sip_compare_func)belle_sdp_base_description_attribute_comp_func, name);
	if (attribute) {
jehan's avatar
jehan committed
617
		return ((belle_sdp_attribute_t*)attribute->data);
jehan's avatar
jehan committed
618 619 620 621
	} else {
		return NULL;
	}
}
jehan's avatar
jehan committed
622
const char*	belle_sdp_base_description_get_attribute_value(const belle_sdp_base_description_t* base_description, const char* name) {
623
	belle_sdp_attribute_t* attribute = belle_sdp_base_description_get_attribute(base_description,name);
624
	if (attribute) {
625
		return belle_sdp_attribute_get_value(attribute);
626
	} else return NULL;
jehan's avatar
jehan committed
627 628

}
jehan's avatar
jehan committed
629 630 631 632 633 634 635
belle_sip_list_t* belle_sdp_base_description_get_attributes(const belle_sdp_base_description_t* base_description) {
	return base_description->attributes;
}
static int belle_sdp_base_description_bandwidth_comp_func(const belle_sdp_bandwidth_t* a, const char*b) {
	return strcmp(a->type,b);
}

636 637 638 639 640 641 642 643 644 645 646

belle_sdp_bandwidth_t* belle_sdp_base_description_get_bandwidth(const belle_sdp_base_description_t *base_description, const char *name){
	belle_sip_list_t* found = belle_sip_list_find_custom(base_description->bandwidths, (belle_sip_compare_func)belle_sdp_base_description_bandwidth_comp_func, name);
	if( found ){
		return ((belle_sdp_bandwidth_t*)found->data);
	} else {
		return NULL;
	}
}

int	belle_sdp_base_description_get_bandwidth_value(const belle_sdp_base_description_t* base_description, const char* name) {
jehan's avatar
jehan committed
647 648 649 650 651 652 653 654 655 656 657 658 659
	belle_sip_list_t* bandwidth;
	bandwidth = belle_sip_list_find_custom(base_description->bandwidths, (belle_sip_compare_func)belle_sdp_base_description_bandwidth_comp_func, name);
	if (bandwidth) {
		return ((belle_sdp_bandwidth_t*)bandwidth->data)->value;
	} else {
		return -1;
	}
}
void belle_sdp_base_description_remove_attribute(belle_sdp_base_description_t* base_description,const char* name) {
	belle_sip_list_t* attribute;
	attribute = belle_sip_list_find_custom(base_description->attributes, (belle_sip_compare_func)belle_sdp_base_description_attribute_comp_func, name);
	if (attribute) {
		belle_sip_object_unref(BELLE_SIP_OBJECT(attribute->data));
660
		base_description->attributes = belle_sip_list_delete_link(base_description->attributes,attribute);
jehan's avatar
jehan committed
661 662 663 664 665 666 667 668
	}

}
void belle_sdp_base_description_remove_bandwidth(belle_sdp_base_description_t* base_description,const char* name) {
	belle_sip_list_t* bandwidth;
	bandwidth = belle_sip_list_find_custom(base_description->bandwidths, (belle_sip_compare_func)belle_sdp_base_description_bandwidth_comp_func, name);
	if (bandwidth) {
		belle_sip_object_unref(BELLE_SIP_OBJECT(bandwidth->data));
669
		base_description->bandwidths = belle_sip_list_delete_link(base_description->bandwidths,bandwidth);
jehan's avatar
jehan committed
670 671
	}
}
jehan's avatar
jehan committed
672
void belle_sdp_base_description_set_attribute_value(belle_sdp_base_description_t* base_description, const char* name, const char* value) {
673 674 675
	belle_sdp_raw_attribute_t* attribute = belle_sdp_raw_attribute_new();
	belle_sdp_attribute_set_name(BELLE_SDP_ATTRIBUTE(attribute),name);
	belle_sdp_raw_attribute_set_value(attribute,value);
676
	base_description->attributes = belle_sip_list_append(base_description->attributes,belle_sip_object_ref(attribute));
jehan's avatar
jehan committed
677 678
}
void belle_sdp_base_description_add_attribute(belle_sdp_base_description_t* base_description, const belle_sdp_attribute_t* attribute) {
679
	base_description->attributes = belle_sip_list_append(base_description->attributes,(void*)belle_sip_object_ref(BELLE_SIP_OBJECT(attribute)));
jehan's avatar
jehan committed
680 681 682 683 684
}

#define SET_LIST(list_name,value) \
		belle_sip_list_t* list;\
		if (list_name) {\
685
			belle_sip_list_free_with_data(list_name,belle_sip_object_unref);\
jehan's avatar
jehan committed
686
		} \
687
		for (list=value;list !=NULL; list=list->next) {\
688
			belle_sip_object_ref(BELLE_SIP_OBJECT(list->data));\
689
		}\
jehan's avatar
jehan committed
690 691 692 693 694 695 696
		list_name=value;


void belle_sdp_base_description_set_attributes(belle_sdp_base_description_t* base_description, belle_sip_list_t* attributes) {
	SET_LIST(base_description->attributes,attributes)
}
void belle_sdp_base_description_set_bandwidth(belle_sdp_base_description_t* base_description, const char* type, int value) {
697

698
	belle_sdp_bandwidth_t* bandwidth = BELLE_SDP_BANDWIDTH(belle_sdp_base_description_get_bandwidth(base_description, type));
699 700 701 702 703 704 705 706
	if( bandwidth == NULL ){
		bandwidth= belle_sdp_bandwidth_new();
		belle_sdp_bandwidth_set_type(bandwidth,type);
		belle_sdp_bandwidth_set_value(bandwidth,value);
		base_description->bandwidths = belle_sip_list_append(base_description->bandwidths,belle_sip_object_ref(bandwidth));
	} else {
		belle_sdp_bandwidth_set_value(bandwidth,value);
	}
jehan's avatar
jehan committed
707 708
}
void belle_sdp_base_description_add_bandwidth(belle_sdp_base_description_t* base_description, const belle_sdp_bandwidth_t* bandwidth) {
709

710
	base_description->bandwidths = belle_sip_list_append(base_description->bandwidths,(void *)belle_sip_object_ref((void *)bandwidth));
jehan's avatar
jehan committed
711 712 713 714 715 716 717 718 719 720 721 722 723
}
void belle_sdp_base_description_set_bandwidths(belle_sdp_base_description_t* base_description, belle_sip_list_t* bandwidths) {
	SET_LIST(base_description->bandwidths,bandwidths)
}

/************************
 * media_description
 ***********************/
struct _belle_sdp_media_description {
	belle_sdp_base_description_t base_description;
	belle_sdp_media_t* media;
};
void belle_sdp_media_description_destroy(belle_sdp_media_description_t* media_description) {
jehan's avatar
jehan committed
724
	if (media_description->media) belle_sip_object_unref(BELLE_SIP_OBJECT((media_description->media)));
jehan's avatar
jehan committed
725 726 727
}

void belle_sdp_media_description_clone(belle_sdp_media_description_t *media_description, const belle_sdp_media_description_t *orig){
728
	if (orig->media) media_description->media = BELLE_SDP_MEDIA(belle_sip_object_clone_and_ref(BELLE_SIP_OBJECT((orig->media))));
jehan's avatar
jehan committed
729
}
Ghislain MARY's avatar
Ghislain MARY committed
730

731
belle_sip_error_code belle_sdp_media_description_marshal(belle_sdp_media_description_t* media_description, char* buff, size_t buff_size, size_t *offset) {
732
	belle_sip_list_t* attributes;
Ghislain MARY's avatar
Ghislain MARY committed
733 734 735 736 737 738
	belle_sip_error_code error=belle_sip_object_marshal(BELLE_SIP_OBJECT(media_description->media),buff,buff_size,offset);
	if (error!=BELLE_SIP_OK) return error;
	error=belle_sip_snprintf(buff, buff_size, offset, "\r\n");
	if (error!=BELLE_SIP_OK) return error;
	error=belle_sdp_base_description_marshal(BELLE_SIP_CAST(media_description,belle_sdp_base_description_t),buff,buff_size,offset);
	if (error!=BELLE_SIP_OK) return error;
739 740

	for(attributes=media_description->base_description.attributes;attributes!=NULL;attributes=attributes->next){
Ghislain MARY's avatar
Ghislain MARY committed
741 742 743 744
		error=belle_sip_object_marshal(BELLE_SIP_OBJECT(attributes->data),buff,buff_size,offset);
		if (error!=BELLE_SIP_OK) return error;
		error=belle_sip_snprintf(buff, buff_size, offset, "\r\n");
		if (error!=BELLE_SIP_OK) return error;
745
	}
Ghislain MARY's avatar
Ghislain MARY committed
746
	return error;
jehan's avatar
jehan committed
747
}
748

jehan's avatar
jehan committed
749
BELLE_SDP_NEW(media_description,belle_sdp_base_description)
jehan's avatar
jehan committed
750
belle_sdp_media_description_t* belle_sdp_media_description_create(const char* media_type
751 752 753 754
																 ,int media_port
																 ,int port_count
																 ,const char* protocol
																 ,belle_sip_list_t* static_media_formats) {
jehan's avatar
jehan committed
755 756 757 758
	belle_sdp_media_description_t* media_desc=belle_sdp_media_description_new();
	belle_sdp_media_description_set_media(media_desc,belle_sdp_media_create(media_type,media_port,port_count,protocol,static_media_formats));
	return media_desc;
}
jehan's avatar
jehan committed
759 760
BELLE_SDP_PARSE(media_description)
void belle_sdp_media_description_add_dynamic_payloads(belle_sdp_media_description_t* media_description, belle_sip_list_t* payloadNames, belle_sip_list_t* payloadValues) {
761
	belle_sip_error("belle_sdp_media_description_add_dynamic_payloads not implemented yet");
jehan's avatar
jehan committed
762
}
763
belle_sdp_attribute_t*	belle_sdp_media_description_get_attribute(const belle_sdp_media_description_t* media_description, const char* name) {
jehan's avatar
jehan committed
764 765
	return belle_sdp_base_description_get_attribute(BELLE_SIP_CAST(media_description,belle_sdp_base_description_t),name);
}
jehan's avatar
jehan committed
766 767 768
const char*	belle_sdp_media_description_get_attribute_value(const belle_sdp_media_description_t* media_description, const char* name) {
	return belle_sdp_base_description_get_attribute_value(BELLE_SIP_CAST(media_description,belle_sdp_base_description_t),name);
}
jehan's avatar
jehan committed
769 770 771 772 773
belle_sip_list_t* belle_sdp_media_description_get_attributes(const belle_sdp_media_description_t* media_description) {
	return BELLE_SIP_CAST(media_description,belle_sdp_base_description_t)->attributes;
}

int	belle_sdp_media_description_get_bandwidth(const belle_sdp_media_description_t* media_description, const char* name) {
774
	return belle_sdp_base_description_get_bandwidth_value(BELLE_SIP_CAST(media_description,belle_sdp_base_description_t),name);
jehan's avatar
jehan committed
775 776 777 778 779 780 781 782 783 784 785 786 787 788
}
belle_sip_list_t* belle_sdp_media_description_get_bandwidths(const belle_sdp_media_description_t* media_description) {
	return BELLE_SIP_CAST(media_description,belle_sdp_base_description_t)->bandwidths;
}
belle_sdp_connection_t*	belle_sdp_media_description_get_connection(const belle_sdp_media_description_t* media_description) {
	return BELLE_SIP_CAST(media_description,belle_sdp_base_description_t)->connection;
}
belle_sdp_info_t* belle_sdp_media_description_get_info(const belle_sdp_media_description_t* media_description) {
	return BELLE_SIP_CAST(media_description,belle_sdp_base_description_t)->info;
}
/*belle_sdp_key_t*  belle_sdp_media_description_get_key(const belle_sdp_media_description_t* media_description);*/
belle_sdp_media_t* belle_sdp_media_description_get_media(const belle_sdp_media_description_t* media_description) {
	return media_description->media;
}
789 790 791 792 793 794 795 796

struct static_payload {
	unsigned char number;
	int channel_count;
	const char* type;
	int	rate;
};
#define STATIC_PAYLOAD_LIST_LENTH 8
jehan's avatar
jehan committed
797 798 799
/*
 * rfc 3551
 * PT   encoding    media type  clock rate   channels
800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821
					name                    (Hz)
			   ___________________________________________________
			   0    PCMU        A            8,000       1
			   1    reserved    A
			   2    reserved    A
			   3    GSM         A            8,000       1
			   4    G723        A            8,000       1
			   5    DVI4        A            8,000       1
			   6    DVI4        A           16,000       1
			   7    LPC         A            8,000       1
			   8    PCMA        A            8,000       1
			   9    G722        A            8,000       1
			   10   L16         A           44,100       2
			   11   L16         A           44,100       1
			   12   QCELP       A            8,000       1
			   13   CN          A            8,000       1
			   14   MPA         A           90,000       (see text)
			   15   G728        A            8,000       1
			   16   DVI4        A           11,025       1
			   17   DVI4        A           22,050       1
			   18   G729        A            8,000       1
			   Table 4: Payload types (PT) for audio encodings
jehan's avatar
jehan committed
822 823

  PT      encoding    media type  clock rate
824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839
					   name                    (Hz)
			   _____________________________________________
			   24      unassigned  V
			   25      CelB        V           90,000
			   26      JPEG        V           90,000
			   27      unassigned  V
			   28      nv          V           90,000
			   29      unassigned  V
			   30      unassigned  V
			   31      H261        V           90,000
			   32      MPV         V           90,000
			   33      MP2T        AV          90,000
			   34      H263        V           90,000

			   Table 5: Payload types (PT) for video and combined
						encodings
jehan's avatar
jehan committed
840 841 842 843 844


 *
 * */

845
const struct static_payload static_payload_list [] ={
jehan's avatar
jehan committed
846
	/*audio*/
847 848 849 850 851
	{0,1,"PCMU",8000},
	{3,1,"GSM",8000},
	{4,1,"G723",8000},
	{5,1,"DVI4",8000},
	{6,1,"DVI4",16000},
jehan's avatar
jehan committed
852
	{7,1,"LPC",8000},
853 854
	{8,1,"PCMA",8000},
	{9,1,"G722",8000},
jehan's avatar
jehan committed
855 856 857 858 859 860 861 862 863 864
	{10,2,"L16",44100},
	{11,1,"L16",44100},
	{12,1,"QCELP",8000},
	{13,1,"CN",8000},
	{14,1,"MPA",90000},
	{15,1,"G728",8000},
	{16,1,"DVI4",11025},
	{17,1,"DVI4",22050},
	{18,1,"G729",8000},
	/*video*/
865 866 867 868 869 870 871
	{25,0,"CelB",90000},
	{26,0,"JPEG",90000},
	{28,0,"nv",90000},
	{31,0,"H261",90000},
	{32,0,"MPV",90000},
	{33,0,"MP2T",90000},
	{34,0,"H263",90000}
872
};
873

Simon Morlat's avatar
Simon Morlat committed
874
static const size_t payload_list_elements=sizeof(static_payload_list)/sizeof(struct static_payload);
875 876 877

static int mime_parameter_is_static(const belle_sdp_mime_parameter_t *param){
	const struct static_payload* iterator;
878
	size_t i;
879

Simon Morlat's avatar
Simon Morlat committed
880
	for (iterator = static_payload_list,i=0;i<payload_list_elements;i++,iterator++) {
881 882
		if (iterator->number == param->media_format &&
			strcasecmp(iterator->type,param->type)==0 &&
883 884 885 886 887 888 889 890
			iterator->channel_count==param->channel_count &&
			iterator->rate==param->rate ) {
			return TRUE;
		}
	}
	return FALSE;
}

891
static int mime_parameter_fill_from_static(belle_sdp_mime_parameter_t *mime_parameter,int format) {
892
	const struct static_payload* iterator;
893
	size_t i;
894

Simon Morlat's avatar
Simon Morlat committed
895
	for (iterator = static_payload_list,i=0;i<payload_list_elements;i++,iterator++) {
896 897 898 899
		if (iterator->number == format) {
			belle_sdp_mime_parameter_set_type(mime_parameter,iterator->type);
			belle_sdp_mime_parameter_set_rate(mime_parameter,iterator->rate);
			belle_sdp_mime_parameter_set_channel_count(mime_parameter,iterator->channel_count);
900
			break;
901 902 903 904
		}
	}
	return 0;
}
905

906
static int mime_parameter_fill_from_rtpmap(belle_sdp_mime_parameter_t *mime_parameter, const char *rtpmap, int is_audio){
907 908 909 910 911 912 913 914 915 916 917
	char *mime=belle_sip_strdup(rtpmap);
	char *p=strchr(mime,'/');
	if (p){
		char *chans;
		*p='\0';
		p++;
		chans=strchr(p,'/');
		if (chans){
			*chans='\0';
			chans++;
			belle_sdp_mime_parameter_set_channel_count(mime_parameter,atoi(chans));
918
		}else if (is_audio) belle_sdp_mime_parameter_set_channel_count(mime_parameter,1); /*in absence of channel count, 1 is implicit for audio streams*/
919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936
		belle_sdp_mime_parameter_set_rate(mime_parameter,atoi(p));
	}
	belle_sdp_mime_parameter_set_type(mime_parameter,mime);
	belle_sip_free(mime);
	return 0;
}
/* return the value of attr "field" for payload pt at line pos (field=rtpmap,fmtp...)*/
static const char *belle_sdp_media_description_a_attr_value_get_with_pt(const belle_sdp_media_description_t* media_description,int pt,const char *field)
{
	int tmppt=0,scanned=0;
	const char *tmp;
	belle_sdp_attribute_t *attr;
	belle_sip_list_t* attribute_list;
	for (	attribute_list =belle_sdp_media_description_get_attributes(media_description)
						;attribute_list!=NULL
						;attribute_list=attribute_list->next) {

		attr = BELLE_SDP_ATTRIBUTE(attribute_list->data);
937 938
		if (strcmp(field,belle_sdp_attribute_get_name(attr))==0 && belle_sdp_attribute_get_value(attr)!=NULL){
			int nb = sscanf(belle_sdp_attribute_get_value(attr),"%i %n",&tmppt,&scanned);
939 940 941
			/* the return value may depend on how %n is interpreted by the libc: see manpage*/
			if (nb == 1 || nb==2 ){
				if (pt==tmppt){
942
					tmp=belle_sdp_attribute_get_value(attr)+scanned;
943 944 945
					if (strlen(tmp)>0)
						return tmp;
				}
946
			}else belle_sip_warning("sdp has a strange a= line (%s) nb=%i",belle_sdp_attribute_get_value(attr),nb);
947 948
		}
	}
jehan's avatar
jehan committed
949 950
	return NULL;
}
951 952 953 954 955 956 957 958 959 960 961 962 963

belle_sip_list_t* belle_sdp_media_description_build_mime_parameters(const belle_sdp_media_description_t* media_description) {
	/*First, get media type*/
	belle_sdp_media_t* media = belle_sdp_media_description_get_media(media_description);
	belle_sip_list_t* mime_parameter_list=NULL;
	belle_sip_list_t* media_formats=NULL;
	belle_sdp_mime_parameter_t* mime_parameter;
	const char* rtpmap=NULL;
	const char* fmtp=NULL;
	const char* ptime=NULL;
	const char* max_ptime=NULL;
	int ptime_as_int=-1;
	int max_ptime_as_int=-1;
964
	int is_audio=0;
965

966 967 968 969
	if (!media) {
		belle_sip_error("belle_sdp_media_description_build_mime_parameters: no media");
		return NULL;
	}
970
	if (strcasecmp(belle_sdp_media_get_media_type(media),"audio")==0) is_audio=1;
jehan's avatar
jehan committed
971
	ptime = belle_sdp_media_description_get_attribute_value(media_description,"ptime");
972
	ptime?ptime_as_int=atoi(ptime):-1;
jehan's avatar
jehan committed
973
	max_ptime = belle_sdp_media_description_get_attribute_value(media_description,"maxptime");
974 975 976 977 978 979 980
	max_ptime?max_ptime_as_int=atoi(max_ptime):-1;

	for (media_formats = belle_sdp_media_get_media_formats(media);media_formats!=NULL;media_formats=media_formats->next) {
		/*create mime parameters with format*/
		mime_parameter = belle_sdp_mime_parameter_new();
		belle_sdp_mime_parameter_set_ptime(mime_parameter,ptime_as_int);
		belle_sdp_mime_parameter_set_max_ptime(mime_parameter,max_ptime_as_int);
981
		belle_sdp_mime_parameter_set_media_format(mime_parameter,(int)(intptr_t)media_formats->data);
982

983 984 985 986 987
		/*get rtpmap*/
		rtpmap = belle_sdp_media_description_a_attr_value_get_with_pt(media_description
																		,belle_sdp_mime_parameter_get_media_format(mime_parameter)
																		,"rtpmap");
		if (rtpmap) {
988
			mime_parameter_fill_from_rtpmap(mime_parameter,rtpmap,is_audio);
989 990
		}else{
			mime_parameter_fill_from_static(mime_parameter,belle_sdp_mime_parameter_get_media_format(mime_parameter));
991 992 993 994 995 996 997 998 999 1000 1001 1002
		}
		fmtp = belle_sdp_media_description_a_attr_value_get_with_pt(media_description
																		,belle_sdp_mime_parameter_get_media_format(mime_parameter)
																		,"fmtp");
		if (fmtp) {
			belle_sdp_mime_parameter_set_parameters(mime_parameter,fmtp);
		}

		mime_parameter_list=belle_sip_list_append(mime_parameter_list,mime_parameter);
	}
	return mime_parameter_list;
}
Simon Morlat's avatar
Simon Morlat committed
1003
#define MAX_FMTP_LENGTH 512
1004

1005
void belle_sdp_media_description_append_values_from_mime_parameter(belle_sdp_media_description_t* media_description, const belle_sdp_mime_parameter_t* mime_parameter) {
1006
	belle_sdp_media_t* media = belle_sdp_media_description_get_media(media_description);
Simon Morlat's avatar
Simon Morlat committed
1007
	char atribute_value [MAX_FMTP_LENGTH];
1008 1009 1010
	int current_ptime=0;
	int current_max_ptime=0;

1011
	belle_sdp_media_set_media_formats(media,belle_sip_list_append(belle_sdp_media_get_media_formats(media)
1012
																,(void*)(intptr_t)(belle_sdp_mime_parameter_get_media_format(mime_parameter))));
1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023

	if (belle_sdp_media_description_get_attribute_value(media_description,"ptime")) {
		current_ptime=atoi(belle_sdp_media_description_get_attribute_value(media_description,"ptime"));
		belle_sdp_media_description_remove_attribute(media_description,"ptime");
	}

	if (belle_sdp_media_description_get_attribute_value(media_description,"maxptime")) {
		current_max_ptime=atoi(belle_sdp_media_description_get_attribute_value(media_description,"maxptime"));
		belle_sdp_media_description_remove_attribute(media_description,"maxptime");
	}

1024
#ifndef BELLE_SDP_FORCE_RTP_MAP /* defined to for RTP map even for static codec*/
1025
	if (!mime_parameter_is_static(mime_parameter)) {
1026
		/*dynamic payload*/
1027
#endif
1028
		if (belle_sdp_mime_parameter_get_channel_count(mime_parameter)>1) {
Simon Morlat's avatar
Simon Morlat committed
1029
			snprintf(atribute_value,MAX_FMTP_LENGTH,"%i %s/%i/%i"
1030 1031 1032 1033 1034
					,belle_sdp_mime_parameter_get_media_format(mime_parameter)
					,belle_sdp_mime_parameter_get_type(mime_parameter)
					,belle_sdp_mime_parameter_get_rate(mime_parameter)
					,belle_sdp_mime_parameter_get_channel_count(mime_parameter));
		} else {
Simon Morlat's avatar
Simon Morlat committed
1035
			snprintf(atribute_value,MAX_FMTP_LENGTH,"%i %s/%i"
1036 1037 1038 1039
					,belle_sdp_mime_parameter_get_media_format(mime_parameter)
					,belle_sdp_mime_parameter_get_type(mime_parameter)
					,belle_sdp_mime_parameter_get_rate(mime_parameter));
		}
jehan's avatar
jehan committed
1040
		belle_sdp_media_description_set_attribute_value(media_description,"rtpmap",atribute_value);
1041
#ifndef BELLE_SDP_FORCE_RTP_MAP
1042
	}
1043
#endif
1044 1045 1046

	// always include fmtp parameters if available
	if (belle_sdp_mime_parameter_get_parameters(mime_parameter)) {
Simon Morlat's avatar
Simon Morlat committed
1047
		snprintf(atribute_value,MAX_FMTP_LENGTH,"%i %s"
1048 1049 1050 1051 1052
				,belle_sdp_mime_parameter_get_media_format(mime_parameter)
				,belle_sdp_mime_parameter_get_parameters(mime_parameter));
		belle_sdp_media_description_set_attribute_value(media_description,"fmtp",atribute_value);
	}

1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070
	if (belle_sdp_mime_parameter_get_ptime(mime_parameter)>current_ptime) {
		current_ptime=belle_sdp_mime_parameter_get_ptime(mime_parameter);
	}
	if (current_ptime>0){
		char  ptime[10];
		snprintf(ptime,sizeof(ptime),"%i",current_ptime);
		belle_sdp_media_description_set_attribute_value(media_description,"ptime",ptime);
	}

	if (belle_sdp_mime_parameter_get_max_ptime(mime_parameter)>current_max_ptime) {
		current_max_ptime=belle_sdp_mime_parameter_get_max_ptime(mime_parameter);
	}
	if (current_max_ptime>0){
		char  max_ptime[10];
		snprintf(max_ptime,sizeof(max_ptime),"%i",current_max_ptime);
		belle_sdp_media_description_set_attribute_value(media_description,"maxptime",max_ptime);
	}

1071
}
jehan's avatar
jehan committed
1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082
belle_sip_list_t* belle_sdp_media_description_get_mime_types(const belle_sdp_media_description_t* media_description) {
	belle_sip_error("belle_sdp_media_description_get_mime_types: not implemented yet");
	return NULL;
}

void belle_sdp_media_description_remove_attribute(belle_sdp_media_description_t* media_description,const char* name) {
	belle_sdp_base_description_remove_attribute(BELLE_SIP_CAST(media_description,belle_sdp_base_description_t),name);
}
void belle_sdp_media_description_remove_bandwidth(belle_sdp_media_description_t* media_description,const char* name) {
	belle_sdp_base_description_remove_bandwidth(BELLE_SIP_CAST(media_description,belle_sdp_base_description_t),name);
}
jehan's avatar
jehan committed
1083 1084
void belle_sdp_media_description_set_attribute_value(belle_sdp_media_description_t* media_description, const char* name, const char* value) {
	belle_sdp_base_description_set_attribute_value(BELLE_SIP_CAST(media_description,belle_sdp_base_description_t),name,value);
jehan's avatar
jehan committed
1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101
}
void belle_sdp_media_description_set_attributes(belle_sdp_media_description_t* media_description, belle_sip_list_t* value) {
	belle_sdp_base_description_set_attributes(BELLE_SIP_CAST(media_description,belle_sdp_base_description_t),value);
}

void belle_sdp_media_description_add_attribute(belle_sdp_media_description_t* media_description, const belle_sdp_attribute_t* attribute) {
	belle_sdp_base_description_add_attribute(BELLE_SIP_CAST(media_description,belle_sdp_base_description_t),attribute);
}
void belle_sdp_media_description_set_bandwidth(belle_sdp_media_description_t* media_description, const char* type, int value) {
	belle_sdp_base_description_set_bandwidth(BELLE_SIP_CAST(media_description,belle_sdp_base_description_t),type,value);
}
void belle_sdp_media_description_add_bandwidth(belle_sdp_media_description_t* media_description, const belle_sdp_bandwidth_t* bandwidth) {
	belle_sdp_base_description_add_bandwidth(BELLE_SIP_CAST(media_description,belle_sdp_base_description_t),bandwidth);
}
void belle_sdp_media_description_set_bandwidths(belle_sdp_media_description_t* media_description, belle_sip_list_t* bandwidths) {
	belle_sdp_base_description_set_bandwidths(BELLE_SIP_CAST(media_description,belle_sdp_base_description_t),bandwidths);
}
1102 1103 1104 1105 1106 1107 1108
#define SET_OBJECT(object,param,param_type) \
		param_type** current = &object->param; \
		if (param) belle_sip_object_ref(param); \
		if (*current) { \
			belle_sip_object_unref(BELLE_SIP_OBJECT(*current)); \
		} \
		*current=param; \
jehan's avatar
jehan committed
1109

1110 1111 1112

void belle_sdp_media_description_set_connection(belle_sdp_media_description_t* media_description, belle_sdp_connection_t* connection) {
	SET_OBJECT(BELLE_SIP_CAST(media_description,belle_sdp_base_description_t),connection,belle_sdp_connection_t)
jehan's avatar
jehan committed
1113
}
1114 1115
void belle_sdp_media_description_set_info(belle_sdp_media_description_t* media_description,belle_sdp_info_t* info) {
	SET_OBJECT(BELLE_SIP_CAST(media_description,belle_sdp_base_description_t),info,belle_sdp_info_t)
jehan's avatar
jehan committed
1116 1117 1118
}
/*void belle_sdp_media_description_set_key(belle_sdp_media_description_t* media_description,belle_sdp_key_t* key);*/
void belle_sdp_media_description_set_media(belle_sdp_media_description_t* media_description, belle_sdp_media_t* media) {
1119
	SET_OBJECT(media_description,media,belle_sdp_media_t)
jehan's avatar
jehan committed
1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130
}

/************************
 * origin
 ***********************/
struct _belle_sdp_origin {
	belle_sip_object_t base;
	const char* address;
	const char* address_type;
	const char* network_type;
	const char* username;
jehan's avatar
jehan committed
1131 1132
	unsigned int session_id;
	unsigned int session_version;
jehan's avatar
jehan committed
1133 1134 1135 1136

 };

void belle_sdp_origin_destroy(belle_sdp_origin_t* origin) {
jehan's avatar
jehan committed
1137 1138 1139 1140
	DESTROY_STRING(origin,address)
	DESTROY_STRING(origin,address_type)
	DESTROY_STRING(origin,network_type)
	DESTROY_STRING(origin,username)
jehan's avatar
jehan committed
1141 1142 1143
}

void belle_sdp_origin_clone(belle_sdp_origin_t *origin, const belle_sdp_origin_t *orig){
jehan's avatar
jehan committed
1144 1145 1146 1147 1148 1149
	CLONE_STRING(belle_sdp_origin,username,origin,orig);
	CLONE_STRING(belle_sdp_origin,address,origin,orig);
	CLONE_STRING(belle_sdp_origin,address_type,origin,orig);
	CLONE_STRING(belle_sdp_origin,network_type,origin,orig);
	origin->session_id = orig->session_id;
	origin->session_version = orig->session_version;
jehan's avatar
jehan committed
1150
}
Ghislain MARY's avatar
Ghislain MARY committed
1151

1152
belle_sip_error_code belle_sdp_origin_marshal(belle_sdp_origin_t* origin, char* buff, size_t buff_size, size_t *offset) {
Ghislain MARY's avatar
Ghislain MARY committed
1153 1154 1155
	return belle_sip_snprintf(	buff
								,buff_size
								,offset
1156
								,"o=%s %u %u %s %s %s"
Ghislain MARY's avatar
Ghislain MARY committed
1157 1158 1159 1160 1161 1162
								,origin->username
								,origin->session_id
								,origin->session_version
								,origin->network_type
								,origin->address_type
								,origin->address);
jehan's avatar
jehan committed
1163
}
Ghislain MARY's avatar
Ghislain MARY committed
1164

jehan's avatar
jehan committed
1165
BELLE_SDP_NEW(origin,belle_sip_object)
jehan's avatar
jehan committed
1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180
belle_sdp_origin_t* belle_sdp_origin_create(const char* user_name
											, unsigned int session_id
											, unsigned int session_version
											, const char* network_type
											, const char* addr_type
											, const char* address) {
	belle_sdp_origin_t* origin=belle_sdp_origin_new();
	belle_sdp_origin_set_username(origin,user_name);
	belle_sdp_origin_set_session_id(origin,session_id);
	belle_sdp_origin_set_session_version(origin,session_version);
	belle_sdp_origin_set_network_type(origin,network_type);
	belle_sdp_origin_set_address_type(origin,addr_type);
	belle_sdp_origin_set_address(origin,address);
	return origin;
}
jehan's avatar
jehan committed
1181
BELLE_SDP_PARSE(origin)
1182 1183 1184 1185
GET_SET_STRING(belle_sdp_origin,username);
GET_SET_STRING(belle_sdp_origin,address);
GET_SET_STRING(belle_sdp_origin,address_type);
GET_SET_STRING(belle_sdp_origin,network_type);
jehan's avatar
jehan committed
1186 1187
GET_SET_INT(belle_sdp_origin,session_id,unsigned int);
GET_SET_INT(belle_sdp_origin,session_version,unsigned int);
1188 1189 1190 1191 1192 1193 1194
/************************
 * session_name
 ***********************/
struct _belle_sdp_session_name {
	belle_sip_object_t base;
	const char* value;
 };
jehan's avatar
jehan committed
1195

1196
void belle_sdp_session_name_destroy(belle_sdp_session_name_t* session_name) {
jehan's avatar
jehan committed
1197
	DESTROY_STRING(session_name,value)
1198
}
jehan's avatar
jehan committed
1199

1200
void belle_sdp_session_name_clone(belle_sdp_session_name_t *session_name, const belle_sdp_session_name_t *orig){
jehan's avatar
jehan committed
1201
	CLONE_STRING(belle_sdp_session_name,value,session_name,orig);
1202
}
Ghislain MARY's avatar
Ghislain MARY committed
1203

1204
belle_sip_error_code belle_sdp_session_name_marshal(belle_sdp_session_name_t* session_name, char* buff, size_t buff_size, size_t *offset) {
Ghislain MARY's avatar
Ghislain MARY committed
1205
	return belle_sip_snprintf(buff,buff_size,offset,"s=%s",session_name->value);
1206
}
Ghislain MARY's avatar
Ghislain MARY committed
1207

1208
BELLE_SDP_NEW(session_name,belle_sip_object)
jehan's avatar
jehan committed
1209 1210 1211 1212 1213
belle_sdp_session_name_t* belle_sdp_session_name_create (const char* name) {
	belle_sdp_session_name_t* n=belle_sdp_session_name_new();
	belle_sdp_session_name_set_value(n,name);
	return n;
}
1214 1215
//BELLE_SDP_PARSE(session_name)
GET_SET_STRING(belle_sdp_session_name,value);
jehan's avatar
jehan committed
1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234


/************************
 * session_description
 ***********************/
struct _belle_sdp_session_description {
	belle_sdp_base_description_t base_description;
	belle_sdp_version_t* version;
	belle_sip_list_t* emails;
	belle_sdp_origin_t* origin;
	belle_sdp_session_name_t* session_name;
	belle_sip_list_t* phones;
	belle_sip_list_t* times;
	belle_sdp_uri_t* uri;
	belle_sdp_uri_t* zone_adjustments;
	belle_sip_list_t* media_descriptions;

 };
void belle_sdp_session_description_destroy(belle_sdp_session_description_t* session_description) {
jehan's avatar
jehan committed
1235 1236 1237 1238 1239 1240 1241 1242 1243
	if (session_description->version) belle_sip_object_unref(BELLE_SIP_OBJECT(session_description->version));
	belle_sip_list_free_with_data(session_description->emails,belle_sip_object_freefunc);
	if (session_description->origin) belle_sip_object_unref(BELLE_SIP_OBJECT(session_description->origin));
	if (session_description->session_name) belle_sip_object_unref(BELLE_SIP_OBJECT(session_description->session_name));
	belle_sip_list_free_with_data(session_description->phones,belle_sip_object_freefunc);
	belle_sip_list_free_with_data(session_description->times,belle_sip_object_freefunc);
	if (session_description->uri) belle_sip_object_unref(BELLE_SIP_OBJECT(session_description->uri));
	if (session_description->zone_adjustments) belle_sip_object_unref(BELLE_SIP_OBJECT(session_description->zone_adjustments));
	belle_sip_list_free_with_data(session_description->media_descriptions,belle_sip_object_freefunc);
jehan's avatar
jehan committed
1244 1245 1246
}

void belle_sdp_session_description_clone(belle_sdp_session_description_t *session_description, const belle_sdp_session_description_t *orig){
1247
	if (orig->version) session_description->version = BELLE_SDP_VERSION(belle_sip_object_clone_and_ref(BELLE_SIP_OBJECT(orig->version)));
jehan's avatar
jehan committed
1248
	session_description->emails = belle_sip_list_copy_with_data(orig->emails,belle_sip_object_copyfunc);
1249 1250
	if (orig->origin) session_description->origin = BELLE_SDP_ORIGIN(belle_sip_object_clone_and_ref(BELLE_SIP_OBJECT(orig->origin)));
	if (orig->session_name) session_description->session_name = BELLE_SDP_SESSION_NAME(belle_sip_object_clone_and_ref(BELLE_SIP_OBJECT(orig->session_name)));
jehan's avatar
jehan committed
1251 1252
	session_description->phones = belle_sip_list_copy_with_data(orig->phones,belle_sip_object_copyfunc);
	session_description->times = belle_sip_list_copy_with_data(orig->times,belle_sip_object_copyfunc);
1253 1254
	if (orig->uri) session_description->uri = BELLE_SDP_URI(belle_sip_object_clone_and_ref(BELLE_SIP_OBJECT(orig->uri)));
	if (orig->zone_adjustments) session_description->zone_adjustments = BELLE_SDP_URI(belle_sip_object_clone_and_ref(BELLE_SIP_OBJECT(orig->zone_adjustments)));
jehan's avatar
jehan committed
1255
	session_description->media_descriptions = belle_sip_list_copy_with_data(orig->media_descriptions,belle_sip_object_copyfunc);
jehan's avatar
jehan committed
1256
}
Ghislain MARY's avatar
Ghislain MARY committed
1257

1258
belle_sip_error_code belle_sdp_session_description_marshal(belle_sdp_session_description_t* session_description, char* buff, size_t buff_size, size_t *offset) {
jehan's avatar
jehan committed
1259
/*session_description:   proto_version CR LF
1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273
						 origin_field
						 session_name_field
						 (info CR LF)?
						 uri_field?
						 (email CR LF)*
						 phone_field*
						 (connection CR LF)?
						 (bandwidth CR LF)*
						 time_field
						 (repeat_time CR LF)?
						 (zone_adjustments CR LF)?
						 (key_field CR LF)?
						 (attribute CR LF)*
						 media_descriptions;
jehan's avatar
jehan committed
1274
 */
Ghislain MARY's avatar
Ghislain MARY committed
1275
	belle_sip_error_code error=BELLE_SIP_OK;
1276 1277
	belle_sip_list_t* media_descriptions;
	belle_sip_list_t* times;
1278
	belle_sip_list_t* attributes;
1279

1280 1281 1282 1283 1284 1285
	if (session_description->version) {
		error=belle_sip_object_marshal(BELLE_SIP_OBJECT(session_description->version),buff,buff_size,offset);
		if (error!=BELLE_SIP_OK) return error;
		error=belle_sip_snprintf(buff, buff_size, offset, "\r\n");
		if (error!=BELLE_SIP_OK) return error;
	}
jehan's avatar
jehan committed
1286

1287 1288 1289 1290 1291 1292
	if (session_description->origin) {
		error=belle_sip_object_marshal(BELLE_SIP_OBJECT(session_description->origin),buff,buff_size,offset);
		if (error!=BELLE_SIP_OK) return error;
		error=belle_sip_snprintf(buff, buff_size, offset, "\r\n");
		if (error!=BELLE_SIP_OK) return error;
	}
1293

1294 1295 1296 1297 1298 1299
	if (session_description->session_name) {
		error=belle_sip_object_marshal(BELLE_SIP_OBJECT(session_description->session_name),buff,buff_size,offset);
		if (error!=BELLE_SIP_OK) return error;
		error=belle_sip_snprintf(buff, buff_size, offset, "\r\n");
		if (error!=BELLE_SIP_OK) return error;
	}
1300

Ghislain MARY's avatar
Ghislain MARY committed
1301 1302
	error=belle_sdp_base_description_marshal((belle_sdp_base_description_t*)(&session_description->base_description),buff,buff_size, offset);
	if (error!=BELLE_SIP_OK) return error;
1303

Ghislain MARY's avatar
Ghislain MARY committed
1304 1305
	error=belle_sip_snprintf(buff, buff_size, offset, "t=");
	if (error!=BELLE_SIP_OK) return error;
1306
	for(times=session_description->times;times!=NULL;times=times->next){
Ghislain MARY's avatar
Ghislain MARY committed
1307 1308 1309 1310
		error=belle_sip_object_marshal(BELLE_SIP_OBJECT(times->data),buff,buff_size,offset);
		if (error!=BELLE_SIP_OK) return error;
		error=belle_sip_snprintf(buff, buff_size, offset, "\r\n");
		if (error!=BELLE_SIP_OK) return error;
1311 1312
	}

1313
	for(attributes=session_description->base_description.attributes;attributes!=NULL;attributes=attributes->next){
Ghislain MARY's avatar
Ghislain MARY committed
1314 1315 1316 1317
		error=belle_sip_object_marshal(BELLE_SIP_OBJECT(attributes->data),buff,buff_size,offset);
		if (error!=BELLE_SIP_OK) return error;
		error=belle_sip_snprintf(buff, buff_size, offset, "\r\n");
		if (error!=BELLE_SIP_OK) return error;
1318 1319
	}

1320
	for(media_descriptions=session_description->media_descriptions;media_descriptions!=NULL;media_descriptions=media_descriptions->next){
Ghislain MARY's avatar
Ghislain MARY committed
1321 1322
		error=belle_sip_object_marshal(BELLE_SIP_OBJECT(media_descriptions->data),buff,buff_size,offset);
		if (error!=BELLE_SIP_OK) return error;
1323
	}
Ghislain MARY's avatar
Ghislain MARY committed
1324
	return error;
jehan's avatar
jehan committed
1325
}
Ghislain MARY's avatar
Ghislain MARY committed
1326

jehan's avatar
jehan committed
1327 1328 1329
BELLE_SDP_NEW(session_description,belle_sdp_base_description)
BELLE_SDP_PARSE(session_description)

1330

1331 1332 1333 1334
belle_sip_list_t * belle_sdp_session_description_get_attributes(const belle_sdp_session_description_t *session_description) {
	return belle_sdp_base_description_get_attributes(BELLE_SIP_CAST(session_description, belle_sdp_base_description_t));
}

jehan's avatar
jehan committed
1335 1336
const char*	belle_sdp_session_description_get_attribute_value(const belle_sdp_session_description_t* session_description, const char* name) {
	return belle_sdp_base_description_get_attribute_value(BELLE_SIP_CAST(session_description,belle_sdp_base_description_t),name);
jehan's avatar
jehan committed
1337
}
1338 1339 1340
const belle_sdp_attribute_t*	belle_sdp_session_description_get_attribute(const belle_sdp_session_description_t* session_description, const char* name) {
	return belle_sdp_base_description_get_attribute(BELLE_SIP_CAST(session_description,belle_sdp_base_description_t),name);
}
jehan's avatar
jehan committed
1341
int	belle_sdp_session_description_get_bandwidth(const belle_sdp_session_description_t* session_description, const char* name) {
1342
	return belle_sdp_base_description_get_bandwidth_value(BELLE_SIP_CAST(session_description,belle_sdp_base_description_t),name);
jehan's avatar
jehan committed
1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386
}
belle_sip_list_t*	belle_sdp_session_description_get_bandwidths(const belle_sdp_session_description_t* session_description) {
	return BELLE_SIP_CAST(session_description,belle_sdp_base_description_t)->bandwidths;
}
belle_sdp_connection_t*	belle_sdp_session_description_get_connection(const belle_sdp_session_description_t* session_description) {
	return BELLE_SIP_CAST(session_description,belle_sdp_base_description_t)->connection;
}
belle_sip_list_t* belle_sdp_session_description_get_emails(const belle_sdp_session_description_t* session_description){
	return session_description->emails;
}
belle_sdp_info_t* belle_sdp_session_description_get_info(const belle_sdp_session_description_t* session_description) {
	return BELLE_SIP_CAST(session_description,belle_sdp_base_description_t)->info;
}
/*belle_sdp_key_t*	belle_sdp_session_description_get_key(const belle_sdp_session_description_t* session_description);*/
belle_sip_list_t* belle_sdp_session_description_get_media_descriptions(const belle_sdp_session_description_t* session_description) {
	return session_description->media_descriptions;
}
belle_sdp_origin_t*	belle_sdp_session_description_get_origin(const belle_sdp_session_description_t* session_description){
	return session_description->origin;
}
belle_sip_list_t* belle_sdp_session_description_get_phones(const belle_sdp_session_description_t* session_description) {
	return session_description->phones;
}
belle_sdp_session_name_t* belle_sdp_session_description_get_session_name(const belle_sdp_session_description_t* session_description) {
	return session_description->session_name;
}
belle_sip_list_t* belle_sdp_session_description_get_time_descriptions(const belle_sdp_session_description_t* session_description) {
	return session_description->times;
}
belle_sdp_uri_t* belle_sdp_session_description_get_uri(const belle_sdp_session_description_t* session_description) {
	return session_description->uri;
}
belle_sdp_version_t*	belle_sdp_session_description_get_version(const belle_sdp_session_description_t* session_description) {
	return session_description->version;
}
belle_sdp_uri_t* belle_sdp_session_description_get_zone_adjustments(const belle_sdp_session_description_t* session_description) {
	return session_description->zone_adjustments;
}
void belle_sdp_session_description_remove_attribute(belle_sdp_session_description_t* session_description, const char* name) {
	belle_sdp_base_description_remove_attribute(BELLE_SIP_CAST(session_description,belle_sdp_base_description_t),name);
}
void belle_sdp_session_description_remove_bandwidth(belle_sdp_session_description_t* session_description, const char* name) {
	belle_sdp_base_description_remove_bandwidth(BELLE_SIP_CAST(session_description,belle_sdp_base_description_t),name);
}
jehan's avatar
jehan committed
1387 1388
void belle_sdp_session_description_set_attribute_value(belle_sdp_session_description_t* session_description, const char* name, const char* value) {
	belle_sdp_base_description_set_attribute_value(BELLE_SIP_CAST(session_description,belle_sdp_base_description_t),name,value);
jehan's avatar
jehan committed
1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401
}
void belle_sdp_session_description_set_attributes(belle_sdp_session_description_t* session_description, belle_sip_list_t*