belle_sdp_impl.c 68.5 KB
Newer Older
jehan's avatar
jehan committed
1 2 3 4 5 6
/*
	belle-sdp - SIP (RFC4566) library.
    Copyright (C) 2010  Belledonne Communications SARL

    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
7
    the Free Software Foundation, either version 2 of the License, or
jehan's avatar
jehan committed
8 9 10 11 12 13 14 15 16 17
    (at your option) any later version.

    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.

    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
18
#include "belle-sip/belle-sip.h"
Guillaume Beraudo's avatar
Guillaume Beraudo committed
19 20
#include "grammars/belle_sdpParser.h"
#include "grammars/belle_sdpLexer.h"
jehan's avatar
jehan committed
21
#include "belle_sip_internal.h"
22 23 24 25 26 27 28 29 30 31 32 33 34 35


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;

};

36 37 38 39 40 41 42

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));
}
Ghislain MARY's avatar
Ghislain MARY committed
43 44 45
static void * belle_sip_string_copyfunc(void *obj) {
	return (void *)belle_sip_strdup((const char *)obj);
}
46 47


jehan's avatar
jehan committed
48 49 50 51
/***************************************************************************************
 * Attribute
 *
 **************************************************************************************/
52 53 54 55 56 57
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[] = {
58
	{ "rtcp-fb", (attribute_parse_func)belle_sdp_rtcp_fb_attribute_parse },
59 60
	{ "rtcp-xr", (attribute_parse_func)belle_sdp_rtcp_xr_attribute_parse }
};
jehan's avatar
jehan committed
61 62 63
struct _belle_sdp_attribute {
	belle_sip_object_t base;
	const char* name;
64
	char *unparsed_value;
jehan's avatar
jehan committed
65 66
};
void belle_sdp_attribute_destroy(belle_sdp_attribute_t* attribute) {
67
	DESTROY_STRING(attribute,name)
Simon Morlat's avatar
Simon Morlat committed
68
	DESTROY_STRING(attribute,unparsed_value)
jehan's avatar
jehan committed
69 70
}
void belle_sdp_attribute_clone(belle_sdp_attribute_t *attribute, const belle_sdp_attribute_t *orig){
71
	CLONE_STRING(belle_sdp_attribute,name,attribute,orig)
jehan's avatar
jehan committed
72
}
73
belle_sip_error_code belle_sdp_attribute_marshal(belle_sdp_attribute_t* attribute, char* buff, size_t buff_size, size_t *offset) {
74 75 76 77 78 79 80 81 82 83 84 85 86 87
	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;
	int i;
	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
88 89 90 91 92
			char* raw;
			if (value)
				raw = belle_sip_strdup_printf("a=%s:%s", name, value);
			else
				raw = belle_sip_strdup_printf("a=%s", name);
93 94 95 96 97 98 99 100
			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));
}
101 102 103 104
const char *belle_sdp_attribute_get_value(belle_sdp_attribute_t *attribute) {
	char *ret;
	char *end;

105
	
106 107 108 109 110
	if (attribute->unparsed_value) {
		belle_sip_free(attribute->unparsed_value);
		attribute->unparsed_value = NULL;
	}
	attribute->unparsed_value = belle_sip_object_to_string(attribute);
111
	
112
	ret = attribute->unparsed_value;
113 114 115
	ret += strlen(attribute->name) + 2; /* "a=" + name*/
	if (*ret==':') ret++;
	for (; *ret == ' '; ret++) {}; /* skip eventual spaces */
116 117 118 119 120
	return ret;
}
unsigned int belle_sdp_attribute_has_value(belle_sdp_attribute_t* attribute) {
	return belle_sdp_attribute_get_value(attribute) != NULL;
}
121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
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) {
136 137 138
	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)));
	}
139 140 141 142
}
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
143
	if (attribute->value) {
144 145
		error = belle_sip_snprintf(buff, buff_size, offset, ":%s", attribute->value);
		if (error != BELLE_SIP_OK) return error;
jehan's avatar
jehan committed
146
	}
Ghislain MARY's avatar
Ghislain MARY committed
147
	return error;
jehan's avatar
jehan committed
148
}
149 150 151 152 153
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
154 155
	return attribute;
}
156 157 158 159 160
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
161
}
162 163 164 165 166 167 168 169
/***************************************************************************************
 * 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;
170
	uint16_t trr_int;
171
	int8_t id;
172 173 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;
}
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) {
190
	int8_t id = belle_sdp_rtcp_fb_attribute_get_id(attribute);
191 192 193 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
	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;
241 242 243 244 245 246 247 248 249 250 251
		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;
				default:
					break;
			}
			break;
252 253 254 255 256 257 258 259 260 261 262 263
	}
	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;
}
BELLE_SDP_NEW_WITH_CTR(rtcp_fb_attribute,belle_sdp_attribute)
BELLE_SDP_PARSE(rtcp_fb_attribute)
264
GET_SET_INT(belle_sdp_rtcp_fb_attribute,id,int8_t)
265 266
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)
267
GET_SET_INT(belle_sdp_rtcp_fb_attribute,trr_int,uint16_t)
268 269 270 271 272 273 274 275 276 277 278 279
/***************************************************************************************
 * 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;
};
Ghislain MARY's avatar
Ghislain MARY committed
280
const belle_sip_list_t* belle_sdp_rtcp_xr_attribute_get_stat_summary_flags(const belle_sdp_rtcp_xr_attribute_t* attribute) {
281 282 283 284 285 286 287
	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)
Ghislain MARY's avatar
Ghislain MARY committed
288
	belle_sip_list_free_with_data(attribute->stat_summary_flags, belle_sip_free);
289 290 291 292 293
}
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;
Ghislain MARY's avatar
Ghislain MARY committed
294
	attribute->stat_summary_flags = belle_sip_list_copy_with_data(orig->stat_summary_flags, belle_sip_string_copyfunc);
295 296 297 298 299 300 301 302 303 304 305 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
	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)
338 339 340 341 342 343 344 345 346 347
/***************************************************************************************
 * 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) {
348
	if (bandwidth->type) belle_sip_free((void*)bandwidth->type);
349 350 351
}

void belle_sdp_bandwidth_clone(belle_sdp_bandwidth_t *bandwidth, const belle_sdp_bandwidth_t *orig){
352 353
	CLONE_STRING(belle_sdp_bandwidth,type,bandwidth,orig)
	bandwidth->value=orig->value;
354
}
Ghislain MARY's avatar
Ghislain MARY committed
355

356
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
357
	return belle_sip_snprintf(buff,buff_size,offset,"b=%s:%i",bandwidth->type,bandwidth->value);
358
}
Ghislain MARY's avatar
Ghislain MARY committed
359

360 361 362 363
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
364 365 366 367 368 369 370 371 372 373 374 375

/************************
 * connection
 ***********************/
struct _belle_sdp_connection {
	belle_sip_object_t base;
	const char* network_type;
	const char* address_type;
	const char* address;
 };

void belle_sdp_connection_destroy(belle_sdp_connection_t* connection) {
jehan's avatar
jehan committed
376 377 378
	DESTROY_STRING(connection,network_type)
	DESTROY_STRING(connection,address_type)
	DESTROY_STRING(connection,address)
jehan's avatar
jehan committed
379 380 381
}

void belle_sdp_connection_clone(belle_sdp_connection_t *connection, const belle_sdp_connection_t *orig){
jehan's avatar
jehan committed
382 383 384 385
	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)

jehan's avatar
jehan committed
386
}
Ghislain MARY's avatar
Ghislain MARY committed
387

388
belle_sip_error_code belle_sdp_connection_marshal(belle_sdp_connection_t* connection, char* buff, size_t buff_size, size_t *offset) {
Ghislain MARY's avatar
Ghislain MARY committed
389
	return belle_sip_snprintf(buff,buff_size,offset,"c=%s %s %s",connection->network_type,connection->address_type,connection->address);
jehan's avatar
jehan committed
390
}
Ghislain MARY's avatar
Ghislain MARY committed
391

jehan's avatar
jehan committed
392 393
BELLE_SDP_NEW(connection,belle_sip_object)
BELLE_SDP_PARSE(connection)
jehan's avatar
jehan committed
394 395 396 397 398 399 400
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
401 402 403
GET_SET_STRING(belle_sdp_connection,network_type);
GET_SET_STRING(belle_sdp_connection,address_type);
GET_SET_STRING(belle_sdp_connection,address);
404 405 406 407 408
/************************
 * email
 ***********************/
struct _belle_sdp_email {
	belle_sip_object_t base;
409
	char* value;
410 411 412
 };

void belle_sdp_email_destroy(belle_sdp_email_t* email) {
jehan's avatar
jehan committed
413
	DESTROY_STRING(email,value)
414 415 416
}

void belle_sdp_email_clone(belle_sdp_email_t *email, const belle_sdp_email_t *orig){
jehan's avatar
jehan committed
417
	CLONE_STRING(belle_sdp_email,value,email,orig)
418
}
Ghislain MARY's avatar
Ghislain MARY committed
419

420
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
421
	return belle_sip_snprintf(buff,buff_size,offset,"e=%s",email->value);
422
}
Ghislain MARY's avatar
Ghislain MARY committed
423

424 425 426 427 428 429 430 431 432 433 434 435
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
436
	DESTROY_STRING(info,value)
437 438 439
}

void belle_sdp_info_clone(belle_sdp_info_t *info, const belle_sdp_info_t *orig){
jehan's avatar
jehan committed
440
	CLONE_STRING(belle_sdp_info,value,info,orig)
441
}
Ghislain MARY's avatar
Ghislain MARY committed
442

443
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
444
	return belle_sip_snprintf(buff,buff_size,offset,"i=%s",info->value);
445
}
Ghislain MARY's avatar
Ghislain MARY committed
446

447 448 449 450 451 452 453 454
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
455
	const char* media_type;
456 457 458
	int media_port;
	belle_sip_list_t* media_formats;
	int port_count;
jehan's avatar
jehan committed
459
	const char* protocol;
460
	const char* raw_fmt;
461
 };
jehan's avatar
jehan committed
462 463 464 465
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
466
	/*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
467 468
	media->media_formats = formats;
}
469
void belle_sdp_media_destroy(belle_sdp_media_t* media) {
jehan's avatar
jehan committed
470 471 472
	DESTROY_STRING(media,media_type)
	belle_sip_list_free(media->media_formats);
	DESTROY_STRING(media,protocol)
473
}
jehan's avatar
jehan committed
474 475 476
static void belle_sdp_media_init(belle_sdp_media_t* media) {
	media->port_count=1;
}
477 478

void belle_sdp_media_clone(belle_sdp_media_t *media, const belle_sdp_media_t *orig){
jehan's avatar
jehan committed
479 480 481 482 483
	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)
484
}
Ghislain MARY's avatar
Ghislain MARY committed
485

486
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
487
	belle_sip_list_t* list=media->media_formats;
Ghislain MARY's avatar
Ghislain MARY committed
488 489
	belle_sip_error_code error=belle_sip_snprintf(buff,buff_size,offset,"m=%s %i",media->media_type,media->media_port);
	if (error!=BELLE_SIP_OK) return error; 
jehan's avatar
jehan committed
490
	if (media->port_count>1) {
Ghislain MARY's avatar
Ghislain MARY committed
491 492
		error=belle_sip_snprintf(buff,buff_size,offset,"/%i",media->port_count);
		if (error!=BELLE_SIP_OK) return error; 
jehan's avatar
jehan committed
493
	}
Ghislain MARY's avatar
Ghislain MARY committed
494 495
	error=belle_sip_snprintf(buff,buff_size,offset," %s",media->protocol);
	if (error!=BELLE_SIP_OK) return error;
jehan's avatar
jehan committed
496
	for(;list!=NULL;list=list->next){
Ghislain MARY's avatar
Ghislain MARY committed
497 498
		error=belle_sip_snprintf(buff,buff_size,offset," %li",(long)list->data);
		if (error!=BELLE_SIP_OK) return error; 
jehan's avatar
jehan committed
499
	}
Ghislain MARY's avatar
Ghislain MARY committed
500
	return error;
501
}
Ghislain MARY's avatar
Ghislain MARY committed
502

jehan's avatar
jehan committed
503
BELLE_SDP_NEW_WITH_CTR(media,belle_sip_object)
504
BELLE_SDP_PARSE(media)
jehan's avatar
jehan committed
505 506 507 508 509 510 511 512 513 514 515 516 517
belle_sdp_media_t* belle_sdp_media_create(const char* media_type
                         ,int media_port
                         ,int port_count
                         ,const char* protocol
                         ,belle_sip_list_t* static_media_formats) {
	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;
}
518
GET_SET_STRING(belle_sdp_media,media_type);
jehan's avatar
jehan committed
519
GET_SET_STRING(belle_sdp_media,protocol);
520 521
GET_SET_INT(belle_sdp_media,media_port,int)
GET_SET_INT(belle_sdp_media,port_count,int)
jehan's avatar
jehan committed
522 523 524 525 526 527 528 529 530 531 532 533

/************************
 * 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
534 535 536 537 538
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
539
}
jehan's avatar
jehan committed
540
static void belle_sdp_base_description_init(belle_sdp_base_description_t* base_description) {
jehan's avatar
jehan committed
541
}
jehan's avatar
jehan committed
542
static void belle_sdp_base_description_clone(belle_sdp_base_description_t *base_description, const belle_sdp_base_description_t *orig){
543 544
	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
545 546 547
	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
548
}
Ghislain MARY's avatar
Ghislain MARY committed
549

550
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
551
	belle_sip_error_code error=BELLE_SIP_OK;
jehan's avatar
jehan committed
552
	belle_sip_list_t* bandwidths;
553
//	belle_sip_list_t* attributes;
jehan's avatar
jehan committed
554
	if (base_description->info) {
Ghislain MARY's avatar
Ghislain MARY committed
555 556 557 558
		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");
		if (error!=BELLE_SIP_OK) return error; 
jehan's avatar
jehan committed
559 560
	}
	if (base_description->connection) {
Ghislain MARY's avatar
Ghislain MARY committed
561 562 563 564
		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
565 566
	}
	for(bandwidths=base_description->bandwidths;bandwidths!=NULL;bandwidths=bandwidths->next){
Ghislain MARY's avatar
Ghislain MARY committed
567 568 569 570
		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
571
	}
572
//	for(attributes=base_description->attributes;attributes!=NULL;attributes=attributes->next){
573 574
//		error=belle_sip_object_marshal(BELLE_SIP_OBJECT(attributes->data),buff,buff_size,offset);
//		error=belle_sip_snprintf(buff, buff_size, offset, "\r\n");
575
//	}
Ghislain MARY's avatar
Ghislain MARY committed
576
	return error;
jehan's avatar
jehan committed
577
}
578 579

BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(belle_sdp_base_description_t);
jehan's avatar
jehan committed
580 581 582 583 584 585
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
586 587 588 589

static int belle_sdp_base_description_attribute_comp_func(const belle_sdp_attribute_t* a, const char*b) {
	return strcmp(a->name,b);
}
590
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
591 592 593
	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
594
		return ((belle_sdp_attribute_t*)attribute->data);
jehan's avatar
jehan committed
595 596 597 598
	} else {
		return NULL;
	}
}
jehan's avatar
jehan committed
599
const char*	belle_sdp_base_description_get_attribute_value(const belle_sdp_base_description_t* base_description, const char* name) {
600
	belle_sdp_attribute_t* attribute = belle_sdp_base_description_get_attribute(base_description,name);
601
	if (attribute) {
602
		return belle_sdp_attribute_get_value(attribute);
603
	} else return NULL;
jehan's avatar
jehan committed
604 605

}
jehan's avatar
jehan committed
606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626
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);
}

int	belle_sdp_base_description_get_bandwidth(const 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) {
		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));
627
		base_description->attributes = belle_sip_list_delete_link(base_description->attributes,attribute);
jehan's avatar
jehan committed
628 629 630 631 632 633 634 635
	}

}
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));
636
		base_description->bandwidths = belle_sip_list_delete_link(base_description->bandwidths,bandwidth);
jehan's avatar
jehan committed
637 638
	}
}
jehan's avatar
jehan committed
639
void belle_sdp_base_description_set_attribute_value(belle_sdp_base_description_t* base_description, const char* name, const char* value) {
640 641 642
	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);
643
	base_description->attributes = belle_sip_list_append(base_description->attributes,belle_sip_object_ref(attribute));
jehan's avatar
jehan committed
644 645
}
void belle_sdp_base_description_add_attribute(belle_sdp_base_description_t* base_description, const belle_sdp_attribute_t* attribute) {
646
	base_description->attributes = belle_sip_list_append(base_description->attributes,(void*)belle_sip_object_ref(BELLE_SIP_OBJECT(attribute)));
jehan's avatar
jehan committed
647 648 649 650 651
}

#define SET_LIST(list_name,value) \
		belle_sip_list_t* list;\
		if (list_name) {\
652
			belle_sip_list_free_with_data(list_name,belle_sip_object_unref);\
jehan's avatar
jehan committed
653
		} \
654
		for (list=value;list !=NULL; list=list->next) {\
655
			belle_sip_object_ref(BELLE_SIP_OBJECT(list->data));\
656
		}\
jehan's avatar
jehan committed
657 658 659 660 661 662 663 664 665 666
		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) {
	belle_sdp_bandwidth_t* bandwidth = belle_sdp_bandwidth_new();
	belle_sdp_bandwidth_set_type(bandwidth,type);
	belle_sdp_bandwidth_set_value(bandwidth,value);
667
	base_description->bandwidths = belle_sip_list_append(base_description->bandwidths,belle_sip_object_ref(bandwidth));
jehan's avatar
jehan committed
668 669
}
void belle_sdp_base_description_add_bandwidth(belle_sdp_base_description_t* base_description, const belle_sdp_bandwidth_t* bandwidth) {
670
	base_description->bandwidths = belle_sip_list_append(base_description->bandwidths,(void *)belle_sip_object_ref((void *)bandwidth));
jehan's avatar
jehan committed
671 672 673 674 675 676 677 678 679 680 681 682 683
}
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
684
	if (media_description->media) belle_sip_object_unref(BELLE_SIP_OBJECT((media_description->media)));
jehan's avatar
jehan committed
685 686 687
}

void belle_sdp_media_description_clone(belle_sdp_media_description_t *media_description, const belle_sdp_media_description_t *orig){
688
	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
689
}
Ghislain MARY's avatar
Ghislain MARY committed
690

691
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) {
692
	belle_sip_list_t* attributes;
Ghislain MARY's avatar
Ghislain MARY committed
693 694 695 696 697 698
	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;
699 700

	for(attributes=media_description->base_description.attributes;attributes!=NULL;attributes=attributes->next){
Ghislain MARY's avatar
Ghislain MARY committed
701 702 703 704
		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;
705
	}
Ghislain MARY's avatar
Ghislain MARY committed
706
	return error;
jehan's avatar
jehan committed
707
}
708

jehan's avatar
jehan committed
709
BELLE_SDP_NEW(media_description,belle_sdp_base_description)
jehan's avatar
jehan committed
710 711 712 713 714 715 716 717 718
belle_sdp_media_description_t* belle_sdp_media_description_create(const char* media_type
                         	 	 	 	 	 	 	 	 	 	 ,int media_port
                         	 	 	 	 	 	 	 	 	 	 ,int port_count
                         	 	 	 	 	 	 	 	 	 	 ,const char* protocol
                         	 	 	 	 	 	 	 	 	 	 ,belle_sip_list_t* static_media_formats) {
	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
719 720
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) {
721
	belle_sip_error("belle_sdp_media_description_add_dynamic_payloads not implemented yet");
jehan's avatar
jehan committed
722
}
723
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
724 725
	return belle_sdp_base_description_get_attribute(BELLE_SIP_CAST(media_description,belle_sdp_base_description_t),name);
}
jehan's avatar
jehan committed
726 727 728
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
729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748
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) {
	return belle_sdp_base_description_get_bandwidth(BELLE_SIP_CAST(media_description,belle_sdp_base_description_t),name);
}
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;
}
749 750 751 752 753 754 755 756

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
757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804
/*
 * rfc 3551
 * PT   encoding    media type  clock rate   channels
                    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

  PT      encoding    media type  clock rate
                       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


 *
 * */

805
const struct static_payload static_payload_list [] ={
jehan's avatar
jehan committed
806
	/*audio*/
807 808 809 810 811
	{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
812
	{7,1,"LPC",8000},
813 814
	{8,1,"PCMA",8000},
	{9,1,"G722",8000},
jehan's avatar
jehan committed
815 816 817 818 819 820 821 822 823 824
	{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*/
825 826 827 828 829 830 831
	{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}
832
};
833

Simon Morlat's avatar
Simon Morlat committed
834
static const size_t payload_list_elements=sizeof(static_payload_list)/sizeof(struct static_payload);
835 836 837 838 839

static int mime_parameter_is_static(const belle_sdp_mime_parameter_t *param){
	const struct static_payload* iterator;
	int i;
	
Simon Morlat's avatar
Simon Morlat committed
840
	for (iterator = static_payload_list,i=0;i<payload_list_elements;i++,iterator++) {
841 842 843 844 845 846 847 848 849 850
		if (iterator->number == param->media_format && 
			strcasecmp(iterator->type,param->type)==0 && 
			iterator->channel_count==param->channel_count &&
			iterator->rate==param->rate ) {
			return TRUE;
		}
	}
	return FALSE;
}

851
static int mime_parameter_fill_from_static(belle_sdp_mime_parameter_t *mime_parameter,int format) {
852
	const struct static_payload* iterator;
853
	int i;
854
	
Simon Morlat's avatar
Simon Morlat committed
855
	for (iterator = static_payload_list,i=0;i<payload_list_elements;i++,iterator++) {
856 857 858 859
		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);
860
			break;
861 862 863 864
		}
	}
	return 0;
}
865

866
static int mime_parameter_fill_from_rtpmap(belle_sdp_mime_parameter_t *mime_parameter, const char *rtpmap, int is_audio){
867 868 869 870 871 872 873 874 875 876 877
	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));
878
		}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*/
879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896
		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);
897 898
		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);
899 900 901
			/* the return value may depend on how %n is interpreted by the libc: see manpage*/
			if (nb == 1 || nb==2 ){
				if (pt==tmppt){
902
					tmp=belle_sdp_attribute_get_value(attr)+scanned;
903 904 905
					if (strlen(tmp)>0)
						return tmp;
				}
906
			}else belle_sip_warning("sdp has a strange a= line (%s) nb=%i",belle_sdp_attribute_get_value(attr),nb);
907 908
		}
	}
jehan's avatar
jehan committed
909 910
	return NULL;
}
911 912 913 914 915 916 917 918 919 920 921 922 923

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;
924 925
	int is_audio=0;
	
926 927 928 929
	if (!media) {
		belle_sip_error("belle_sdp_media_description_build_mime_parameters: no media");
		return NULL;
	}
930
	if (strcasecmp(belle_sdp_media_get_media_type(media),"audio")==0) is_audio=1;
jehan's avatar
jehan committed
931
	ptime = belle_sdp_media_description_get_attribute_value(media_description,"ptime");
932
	ptime?ptime_as_int=atoi(ptime):-1;
jehan's avatar
jehan committed
933
	max_ptime = belle_sdp_media_description_get_attribute_value(media_description,"maxptime");
934 935 936 937 938 939 940 941
	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);
		belle_sdp_mime_parameter_set_media_format(mime_parameter,(int)(long)media_formats->data);
942
		
943 944 945 946 947
		/*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) {
948
			mime_parameter_fill_from_rtpmap(mime_parameter,rtpmap,is_audio);
949 950
		}else{
			mime_parameter_fill_from_static(mime_parameter,belle_sdp_mime_parameter_get_media_format(mime_parameter));
951 952 953 954 955 956 957 958 959 960 961 962
		}
		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
963
#define MAX_FMTP_LENGTH 512
964

Simon Morlat's avatar
Simon Morlat committed
965
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) {
966
	belle_sdp_media_t* media = belle_sdp_media_description_get_media(media_description);
Simon Morlat's avatar
Simon Morlat committed
967
	char atribute_value [MAX_FMTP_LENGTH];
968 969 970
	int current_ptime=0;
	int current_max_ptime=0;

971 972
	belle_sdp_media_set_media_formats(media,belle_sip_list_append(belle_sdp_media_get_media_formats(media)
																,(void*)(long)(belle_sdp_mime_parameter_get_media_format(mime_parameter))));
973 974 975 976 977 978 979 980 981 982 983

	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");
	}

984
#ifndef BELLE_SDP_FORCE_RTP_MAP /* defined to for RTP map even for static codec*/
985
	if (!mime_parameter_is_static(mime_parameter)) {
986
		/*dynamic payload*/
987
#endif
988
		if (belle_sdp_mime_parameter_get_channel_count(mime_parameter)>1) {
Simon Morlat's avatar
Simon Morlat committed
989
			snprintf(atribute_value,MAX_FMTP_LENGTH,"%i %s/%i/%i"
990 991 992 993 994
					,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
995
			snprintf(atribute_value,MAX_FMTP_LENGTH,"%i %s/%i"
996 997 998 999
					,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
1000
		belle_sdp_media_description_set_attribute_value(media_description,"rtpmap",atribute_value);
1001
#ifndef BELLE_SDP_FORCE_RTP_MAP
1002
	}
1003
#endif
1004 1005 1006

	// always include fmtp parameters if available
	if (belle_sdp_mime_parameter_get_parameters(mime_parameter)) {
Simon Morlat's avatar
Simon Morlat committed
1007
		snprintf(atribute_value,MAX_FMTP_LENGTH,"%i %s"
1008 1009 1010 1011 1012
				,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);
	}

1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030
	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);
	}

1031
}
jehan's avatar
jehan committed
1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042
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
1043 1044
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
1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061
}
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_att