1 /*
2 	belle-sdp - SIP (RFC4566) library.
3 	Copyright (C) 2010  Belledonne Communications SARL
4 
5 	This program is free software: you can redistribute it and/or modify
6 	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
8 	(at your option) any later version.
9 
10 	This program is distributed in the hope that it will be useful,
11 	but WITHOUT ANY WARRANTY; without even the implied warranty of
12 	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 	GNU General Public License for more details.
14 
15 	You should have received a copy of the GNU General Public License
16 	along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 */
18 #include "belle-sip/belle-sip.h"
19 #include "grammars/belle_sdpParser.h"
20 #include "grammars/belle_sdpLexer.h"
21 #include "belle_sip_internal.h"
22 
23 
24 struct _belle_sdp_mime_parameter {
25 	belle_sip_object_t base;
26 	int rate;
27 	int channel_count;
28 	int ptime;
29 	int max_ptime;
30 	int media_format;
31 	const char* type;
32 	const char* parameters;
33 
34 };
35 
36 
belle_sip_object_freefunc(void * obj)37 static void belle_sip_object_freefunc(void* obj) {
38 	belle_sip_object_unref(BELLE_SIP_OBJECT(obj));
39 }
belle_sip_object_copyfunc(void * obj)40 static void* belle_sip_object_copyfunc(void* obj) {
41 	return belle_sip_object_clone_and_ref(BELLE_SIP_OBJECT(obj));
42 }
belle_sip_string_copyfunc(void * obj)43 static void * belle_sip_string_copyfunc(void *obj) {
44 	return (void *)belle_sip_strdup((const char *)obj);
45 }
46 
47 
48 /***************************************************************************************
49  * Attribute
50  *
51  **************************************************************************************/
52 typedef belle_sdp_attribute_t* (*attribute_parse_func)(const char*) ;
53 struct attribute_name_func_pair {
54 	const char* name;
55 	attribute_parse_func func;
56 };
57 static struct attribute_name_func_pair attribute_table[] = {
58 	{ "rtcp-fb", (attribute_parse_func)belle_sdp_rtcp_fb_attribute_parse },
59 	{ "rtcp-xr", (attribute_parse_func)belle_sdp_rtcp_xr_attribute_parse }
60 };
61 struct _belle_sdp_attribute {
62 	belle_sip_object_t base;
63 	const char* name;
64 	char *unparsed_value;
65 };
belle_sdp_attribute_destroy(belle_sdp_attribute_t * attribute)66 void belle_sdp_attribute_destroy(belle_sdp_attribute_t* attribute) {
67 	DESTROY_STRING(attribute,name)
68 	DESTROY_STRING(attribute,unparsed_value)
69 }
belle_sdp_attribute_clone(belle_sdp_attribute_t * attribute,const belle_sdp_attribute_t * orig)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)
72 }
belle_sdp_attribute_marshal(belle_sdp_attribute_t * attribute,char * buff,size_t buff_size,size_t * offset)73 belle_sip_error_code belle_sdp_attribute_marshal(belle_sdp_attribute_t* attribute, char* buff, size_t buff_size, size_t *offset) {
74 	return belle_sip_snprintf(buff, buff_size, offset, "a=%s", attribute->name);
75 }
belle_sdp_attribute_create(const char * name,const char * value)76 belle_sdp_attribute_t* belle_sdp_attribute_create(const char* name, const char* value) {
77 	belle_sdp_attribute_t* ret;
78 	size_t i;
79 	size_t elements = sizeof(attribute_table) / sizeof(attribute_table[0]);
80 
81 	if (!name || name[0] == '\0') {
82 		belle_sip_error("Cannot create SDP attribute without name");
83 		return NULL;
84 	}
85 
86 	for (i = 0; i < elements; i++) {
87 		if (strcasecmp(attribute_table[i].name, name) == 0) {
88 			char* raw;
89 			if (value)
90 				raw = belle_sip_strdup_printf("a=%s:%s", name, value);
91 			else
92 				raw = belle_sip_strdup_printf("a=%s", name);
93 			ret = attribute_table[i].func(raw);
94 			belle_sip_free(raw);
95 			return ret;
96 		}
97 	}
98 	/* Not a specialized SDP attribute */
99 	return BELLE_SDP_ATTRIBUTE(belle_sdp_raw_attribute_create(name, value));
100 }
belle_sdp_attribute_get_value(belle_sdp_attribute_t * attribute)101 const char *belle_sdp_attribute_get_value(belle_sdp_attribute_t *attribute) {
102 	char *ret;
103 	char *end;
104 
105 
106 	if (attribute->unparsed_value) {
107 		belle_sip_free(attribute->unparsed_value);
108 		attribute->unparsed_value = NULL;
109 	}
110 	attribute->unparsed_value = belle_sip_object_to_string(attribute);
111 
112 	ret = attribute->unparsed_value;
113 	ret += strlen(attribute->name) + 2; /* "a=" + name*/
114 	if (*ret==':') ret++;
115 	for (; *ret == ' '; ret++) {}; /* skip eventual spaces */
116 	return ret;
117 }
belle_sdp_attribute_has_value(belle_sdp_attribute_t * attribute)118 unsigned int belle_sdp_attribute_has_value(belle_sdp_attribute_t* attribute) {
119 	return belle_sdp_attribute_get_value(attribute) != NULL;
120 }
121 BELLE_SDP_NEW(attribute,belle_sip_object)
122 BELLE_SDP_PARSE(attribute)
123 GET_SET_STRING(belle_sdp_attribute,name);
124 /***************************************************************************************
125  * RAW Attribute
126  *
127  **************************************************************************************/
128 struct _belle_sdp_raw_attribute {
129 	belle_sdp_attribute_t base;
130 	const char* value;
131 };
belle_sdp_raw_attribute_destroy(belle_sdp_raw_attribute_t * attribute)132 void belle_sdp_raw_attribute_destroy(belle_sdp_raw_attribute_t* attribute) {
133 	DESTROY_STRING(attribute,value)
134 }
belle_sdp_raw_attribute_clone(belle_sdp_raw_attribute_t * attribute,const belle_sdp_raw_attribute_t * orig)135 void belle_sdp_raw_attribute_clone(belle_sdp_raw_attribute_t* attribute, const belle_sdp_raw_attribute_t* orig) {
136 	if (belle_sdp_attribute_get_value(BELLE_SDP_ATTRIBUTE(orig))) {
137 		belle_sdp_raw_attribute_set_value(attribute, belle_sdp_attribute_get_value(BELLE_SDP_ATTRIBUTE(orig)));
138 	}
139 }
belle_sdp_raw_attribute_marshal(belle_sdp_raw_attribute_t * attribute,char * buff,size_t buff_size,size_t * offset)140 belle_sip_error_code belle_sdp_raw_attribute_marshal(belle_sdp_raw_attribute_t* attribute, char* buff, size_t buff_size, size_t* offset) {
141 	belle_sip_error_code error = belle_sdp_attribute_marshal(BELLE_SDP_ATTRIBUTE(attribute), buff, buff_size, offset);
142 	if (error != BELLE_SIP_OK) return error;
143 	if (attribute->value) {
144 		error = belle_sip_snprintf(buff, buff_size, offset, ":%s", attribute->value);
145 		if (error != BELLE_SIP_OK) return error;
146 	}
147 	return error;
148 }
BELLE_SDP_NEW(raw_attribute,belle_sdp_attribute)149 BELLE_SDP_NEW(raw_attribute,belle_sdp_attribute)
150 belle_sdp_raw_attribute_t* belle_sdp_raw_attribute_create(const char* name, const char* value) {
151 	belle_sdp_raw_attribute_t* attribute = belle_sdp_raw_attribute_new();
152 	belle_sdp_attribute_set_name(BELLE_SDP_ATTRIBUTE(attribute), name);
153 	belle_sdp_raw_attribute_set_value(attribute, value);
154 	return attribute;
155 }
belle_sdp_raw_attribute_set_value(belle_sdp_raw_attribute_t * attribute,const char * value)156 void belle_sdp_raw_attribute_set_value(belle_sdp_raw_attribute_t* attribute, const char* value) {
157 	if (attribute->value != NULL) belle_sip_free((void*)attribute->value);
158 	if (value) {
159 		attribute->value = belle_sip_strdup(value);
160 	} else attribute->value = NULL;
161 }
162 /***************************************************************************************
163  * RTCP-FB Attribute
164  *
165  **************************************************************************************/
166 struct _belle_sdp_rtcp_fb_attribute {
167 	belle_sdp_attribute_t base;
168 	belle_sdp_rtcp_fb_val_type_t type;
169 	belle_sdp_rtcp_fb_val_param_t param;
170 	uint32_t smaxpr;
171 	uint16_t trr_int;
172 	int8_t id;
173 };
174 BELLESIP_EXPORT unsigned int belle_sdp_rtcp_fb_attribute_has_pli(const belle_sdp_rtcp_fb_attribute_t* attribute);
175 BELLESIP_EXPORT void belle_sdp_rtcp_fb_attribute_set_pli(belle_sdp_rtcp_fb_attribute_t* attribute, unsigned int enable);
176 BELLESIP_EXPORT unsigned int belle_sdp_rtcp_fb_attribute_has_sli(const belle_sdp_rtcp_fb_attribute_t* attribute);
177 BELLESIP_EXPORT void belle_sdp_rtcp_fb_attribute_set_sli(belle_sdp_rtcp_fb_attribute_t* attribute, unsigned int enable);
178 BELLESIP_EXPORT unsigned int belle_sdp_rtcp_fb_attribute_has_rpsi(const belle_sdp_rtcp_fb_attribute_t* attribute);
179 BELLESIP_EXPORT void belle_sdp_rtcp_fb_attribute_set_rpsi(belle_sdp_rtcp_fb_attribute_t* attribute, unsigned int enable);
180 BELLESIP_EXPORT unsigned int belle_sdp_rtcp_fb_attribute_has_app(const belle_sdp_rtcp_fb_attribute_t* attribute);
181 BELLESIP_EXPORT void belle_sdp_rtcp_fb_attribute_set_app(belle_sdp_rtcp_fb_attribute_t* attribute, unsigned int enable);
belle_sdp_rtcp_fb_attribute_destroy(belle_sdp_rtcp_fb_attribute_t * attribute)182 void belle_sdp_rtcp_fb_attribute_destroy(belle_sdp_rtcp_fb_attribute_t* attribute) {
183 }
belle_sdp_rtcp_fb_attribute_clone(belle_sdp_rtcp_fb_attribute_t * attribute,const belle_sdp_rtcp_fb_attribute_t * orig)184 void belle_sdp_rtcp_fb_attribute_clone(belle_sdp_rtcp_fb_attribute_t* attribute, const belle_sdp_rtcp_fb_attribute_t *orig) {
185 	attribute->type = orig->type;
186 	attribute->param = orig->param;
187 	attribute->trr_int = orig->trr_int;
188 	attribute->id = orig->id;
189 	attribute->smaxpr = orig->smaxpr;
190 }
belle_sdp_rtcp_fb_attribute_marshal(belle_sdp_rtcp_fb_attribute_t * attribute,char * buff,size_t buff_size,size_t * offset)191 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) {
192 	int8_t id = belle_sdp_rtcp_fb_attribute_get_id(attribute);
193 	belle_sdp_rtcp_fb_val_type_t type = belle_sdp_rtcp_fb_attribute_get_type(attribute);
194 	belle_sdp_rtcp_fb_val_param_t param = belle_sdp_rtcp_fb_attribute_get_param(attribute);
195 	belle_sip_error_code error = belle_sdp_attribute_marshal(BELLE_SDP_ATTRIBUTE(attribute), buff, buff_size, offset);
196 	if (error != BELLE_SIP_OK) return error;
197 	if (id < 0) {
198 		error = belle_sip_snprintf(buff, buff_size, offset, ":* ");
199 	} else {
200 		error = belle_sip_snprintf(buff, buff_size, offset, ":%u ", id);
201 	}
202 	if (error != BELLE_SIP_OK) return error;
203 	switch (type) {
204 		case BELLE_SDP_RTCP_FB_ACK:
205 			error = belle_sip_snprintf(buff, buff_size, offset, "ack");
206 			if (error != BELLE_SIP_OK) return error;
207 			switch (param) {
208 				default:
209 				case BELLE_SDP_RTCP_FB_NONE:
210 					break;
211 				case BELLE_SDP_RTCP_FB_RPSI:
212 					error = belle_sip_snprintf(buff, buff_size, offset, " rpsi");
213 					break;
214 				case BELLE_SDP_RTCP_FB_APP:
215 					error = belle_sip_snprintf(buff, buff_size, offset, " app");
216 					break;
217 			}
218 			break;
219 		case BELLE_SDP_RTCP_FB_NACK:
220 			error = belle_sip_snprintf(buff, buff_size, offset, "nack");
221 			if (error != BELLE_SIP_OK) return error;
222 			switch (param) {
223 				default:
224 				case BELLE_SDP_RTCP_FB_NONE:
225 					break;
226 				case BELLE_SDP_RTCP_FB_PLI:
227 					error = belle_sip_snprintf(buff, buff_size, offset, " pli");
228 					break;
229 				case BELLE_SDP_RTCP_FB_SLI:
230 					error = belle_sip_snprintf(buff, buff_size, offset, " sli");
231 					break;
232 				case BELLE_SDP_RTCP_FB_RPSI:
233 					error = belle_sip_snprintf(buff, buff_size, offset, " rpsi");
234 					break;
235 				case BELLE_SDP_RTCP_FB_APP:
236 					error = belle_sip_snprintf(buff, buff_size, offset, " app");
237 					break;
238 			}
239 			break;
240 		case BELLE_SDP_RTCP_FB_TRR_INT:
241 			error = belle_sip_snprintf(buff, buff_size, offset, "trr-int %u", belle_sdp_rtcp_fb_attribute_get_trr_int(attribute));
242 			break;
243 		case BELLE_SDP_RTCP_FB_CCM:
244 			error = belle_sip_snprintf(buff, buff_size, offset, "ccm");
245 			if (error != BELLE_SIP_OK) return error;
246 			switch (param) {
247 				case BELLE_SDP_RTCP_FB_FIR:
248 					error = belle_sip_snprintf(buff, buff_size, offset, " fir");
249 					break;
250 				case BELLE_SDP_RTCP_FB_TMMBR:
251 					error = belle_sip_snprintf(buff, buff_size, offset, " tmmbr");
252 					if (belle_sdp_rtcp_fb_attribute_get_smaxpr(attribute) > 0) {
253 						error = belle_sip_snprintf(buff, buff_size, offset, " smaxpr=%u", belle_sdp_rtcp_fb_attribute_get_smaxpr(attribute));
254 					}
255 					break;
256 				default:
257 					break;
258 			}
259 			break;
260 	}
261 	return error;
262 }
belle_sdp_rtcp_fb_attribute_init(belle_sdp_rtcp_fb_attribute_t * attribute)263 static void belle_sdp_rtcp_fb_attribute_init(belle_sdp_rtcp_fb_attribute_t* attribute) {
264 	belle_sdp_attribute_set_name(BELLE_SDP_ATTRIBUTE(attribute), "rtcp-fb");
265 	attribute->id = -1;
266 	attribute->type = BELLE_SDP_RTCP_FB_TRR_INT;
267 	attribute->param = BELLE_SDP_RTCP_FB_NONE;
268 	attribute->trr_int = 0;
269 	attribute->smaxpr = 0;
270 }
271 BELLE_SDP_NEW_WITH_CTR(rtcp_fb_attribute,belle_sdp_attribute)
272 BELLE_SDP_PARSE(rtcp_fb_attribute)
273 GET_SET_INT(belle_sdp_rtcp_fb_attribute,id,int8_t)
274 GET_SET_INT(belle_sdp_rtcp_fb_attribute,type,belle_sdp_rtcp_fb_val_type_t)
275 GET_SET_INT(belle_sdp_rtcp_fb_attribute,param,belle_sdp_rtcp_fb_val_param_t)
276 GET_SET_INT(belle_sdp_rtcp_fb_attribute,trr_int,uint16_t)
277 GET_SET_INT(belle_sdp_rtcp_fb_attribute,smaxpr,uint32_t)
278 /***************************************************************************************
279  * RTCP-XR Attribute
280  *
281  **************************************************************************************/
282 struct _belle_sdp_rtcp_xr_attribute {
283 	belle_sdp_attribute_t base;
284 	const char* rcvr_rtt_mode;
285 	int rcvr_rtt_max_size;
286 	unsigned int stat_summary;
287 	belle_sip_list_t* stat_summary_flags;
288 	unsigned int voip_metrics;
289 };
belle_sdp_rtcp_xr_attribute_get_stat_summary_flags(const belle_sdp_rtcp_xr_attribute_t * attribute)290 const belle_sip_list_t* belle_sdp_rtcp_xr_attribute_get_stat_summary_flags(const belle_sdp_rtcp_xr_attribute_t* attribute) {
291 	return attribute->stat_summary_flags;
292 }
belle_sdp_rtcp_xr_attribute_add_stat_summary_flag(belle_sdp_rtcp_xr_attribute_t * attribute,const char * flag)293 void belle_sdp_rtcp_xr_attribute_add_stat_summary_flag(belle_sdp_rtcp_xr_attribute_t* attribute, const char* flag) {
294 	attribute->stat_summary_flags = belle_sip_list_append(attribute->stat_summary_flags, belle_sip_strdup(flag));
295 }
belle_sdp_rtcp_xr_attribute_destroy(belle_sdp_rtcp_xr_attribute_t * attribute)296 void belle_sdp_rtcp_xr_attribute_destroy(belle_sdp_rtcp_xr_attribute_t* attribute) {
297 	DESTROY_STRING(attribute,rcvr_rtt_mode)
298 	belle_sip_list_free_with_data(attribute->stat_summary_flags, belle_sip_free);
299 }
belle_sdp_rtcp_xr_attribute_clone(belle_sdp_rtcp_xr_attribute_t * attribute,const belle_sdp_rtcp_xr_attribute_t * orig)300 void belle_sdp_rtcp_xr_attribute_clone(belle_sdp_rtcp_xr_attribute_t* attribute, const belle_sdp_rtcp_xr_attribute_t *orig) {
301 	CLONE_STRING(belle_sdp_rtcp_xr_attribute,rcvr_rtt_mode,attribute,orig)
302 	attribute->rcvr_rtt_max_size = orig->rcvr_rtt_max_size;
303 	attribute->stat_summary = orig->stat_summary;
304 	attribute->stat_summary_flags = belle_sip_list_copy_with_data(orig->stat_summary_flags, belle_sip_string_copyfunc);
305 	attribute->voip_metrics = orig->voip_metrics;
306 }
belle_sdp_rtcp_xr_attribute_marshal(belle_sdp_rtcp_xr_attribute_t * attribute,char * buff,size_t buff_size,size_t * offset)307 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) {
308 	const char *rcvr_rtt_mode = NULL;
309 	int rcvr_rtt_max_size = -1;
310 	int nb_xr_formats = 0;
311 	belle_sip_error_code error = belle_sdp_attribute_marshal(BELLE_SDP_ATTRIBUTE(attribute), buff, buff_size, offset);
312 	if (error != BELLE_SIP_OK) return error;
313 	rcvr_rtt_mode = belle_sdp_rtcp_xr_attribute_get_rcvr_rtt_mode(attribute);
314 	if (rcvr_rtt_mode != NULL) {
315 		error = belle_sip_snprintf(buff, buff_size, offset, "%srcvr-rtt=%s", nb_xr_formats++ == 0 ? ":" : " ", rcvr_rtt_mode);
316 		if (error != BELLE_SIP_OK) return error;
317 		rcvr_rtt_max_size = belle_sdp_rtcp_xr_attribute_get_rcvr_rtt_max_size(attribute);
318 		if (rcvr_rtt_max_size > 0) {
319 			error = belle_sip_snprintf(buff, buff_size, offset, ":%u", rcvr_rtt_max_size);
320 			if (error != BELLE_SIP_OK) return error;
321 		}
322 	}
323 	if (belle_sdp_rtcp_xr_attribute_has_stat_summary(attribute)) {
324 		belle_sip_list_t* list;
325 		int nb_stat_flags = 0;
326 		error = belle_sip_snprintf(buff, buff_size, offset, "%sstat-summary", nb_xr_formats++ == 0 ? ":" : " ");
327 		if (error != BELLE_SIP_OK) return error;
328 		for (list = attribute->stat_summary_flags; list != NULL; list = list->next) {
329 			error = belle_sip_snprintf(buff, buff_size, offset, "%s%s", nb_stat_flags++ == 0 ? "=" : ",", (const char*)list->data);
330 			if (error != BELLE_SIP_OK) return error;
331 		}
332 	}
333 	if (belle_sdp_rtcp_xr_attribute_has_voip_metrics(attribute)) {
334 		error = belle_sip_snprintf(buff, buff_size, offset, "%svoip-metrics", nb_xr_formats++ == 0 ? ":" : " ");
335 		if (error != BELLE_SIP_OK) return error;
336 	}
337 	return error;
338 }
belle_sdp_rtcp_xr_attribute_init(belle_sdp_rtcp_xr_attribute_t * attribute)339 static void belle_sdp_rtcp_xr_attribute_init(belle_sdp_rtcp_xr_attribute_t* attribute) {
340 	belle_sdp_attribute_set_name(BELLE_SDP_ATTRIBUTE(attribute), "rtcp-xr");
341 }
342 BELLE_SDP_NEW_WITH_CTR(rtcp_xr_attribute,belle_sdp_attribute)
343 BELLE_SDP_PARSE(rtcp_xr_attribute)
344 GET_SET_STRING(belle_sdp_rtcp_xr_attribute,rcvr_rtt_mode)
345 GET_SET_INT(belle_sdp_rtcp_xr_attribute,rcvr_rtt_max_size,int)
346 GET_SET_BOOL(belle_sdp_rtcp_xr_attribute,stat_summary,has)
347 GET_SET_BOOL(belle_sdp_rtcp_xr_attribute,voip_metrics,has)
348 /***************************************************************************************
349  * Bandwidth
350  *
351  **************************************************************************************/
352 struct _belle_sdp_bandwidth {
353 	belle_sip_object_t base;
354 	const char* type;
355 	int value;
356 };
belle_sdp_bandwidth_destroy(belle_sdp_bandwidth_t * bandwidth)357 void belle_sdp_bandwidth_destroy(belle_sdp_bandwidth_t* bandwidth) {
358 	if (bandwidth->type) belle_sip_free((void*)bandwidth->type);
359 }
360 
belle_sdp_bandwidth_clone(belle_sdp_bandwidth_t * bandwidth,const belle_sdp_bandwidth_t * orig)361 void belle_sdp_bandwidth_clone(belle_sdp_bandwidth_t *bandwidth, const belle_sdp_bandwidth_t *orig){
362 	CLONE_STRING(belle_sdp_bandwidth,type,bandwidth,orig)
363 	bandwidth->value=orig->value;
364 }
365 
belle_sdp_bandwidth_marshal(belle_sdp_bandwidth_t * bandwidth,char * buff,size_t buff_size,size_t * offset)366 belle_sip_error_code belle_sdp_bandwidth_marshal(belle_sdp_bandwidth_t* bandwidth, char* buff, size_t buff_size, size_t *offset) {
367 	return belle_sip_snprintf(buff,buff_size,offset,"b=%s:%i",bandwidth->type,bandwidth->value);
368 }
369 
370 BELLE_SDP_NEW(bandwidth,belle_sip_object)
371 BELLE_SDP_PARSE(bandwidth)
372 GET_SET_STRING(belle_sdp_bandwidth,type);
373 GET_SET_INT(belle_sdp_bandwidth,value,int)
374 
375 /************************
376  * connection
377  ***********************/
378 struct _belle_sdp_connection {
379 	belle_sip_object_t base;
380 	const char* network_type;
381 	const char* address_type;
382 	const char* address;
383 	int ttl;
384 	int range;
385  };
386 
belle_sdp_connection_destroy(belle_sdp_connection_t * connection)387 void belle_sdp_connection_destroy(belle_sdp_connection_t* connection) {
388 	DESTROY_STRING(connection,network_type)
389 	DESTROY_STRING(connection,address_type)
390 	DESTROY_STRING(connection,address)
391 }
392 
belle_sdp_connection_clone(belle_sdp_connection_t * connection,const belle_sdp_connection_t * orig)393 void belle_sdp_connection_clone(belle_sdp_connection_t *connection, const belle_sdp_connection_t *orig){
394 	CLONE_STRING(belle_sdp_connection,network_type,connection,orig)
395 	CLONE_STRING(belle_sdp_connection,address_type,connection,orig)
396 	CLONE_STRING(belle_sdp_connection,address,connection,orig)
397 	connection->range=orig->range;
398 	connection->ttl=orig->ttl;
399 }
400 
belle_sdp_connection_marshal(belle_sdp_connection_t * connection,char * buff,size_t buff_size,size_t * offset)401 belle_sip_error_code belle_sdp_connection_marshal(belle_sdp_connection_t* connection, char* buff, size_t buff_size, size_t *offset) {
402 	belle_sip_error_code error = belle_sip_snprintf(buff,buff_size,offset,"c=%s %s %s",connection->network_type,connection->address_type,connection->address);
403 	if (error!=BELLE_SIP_OK) return error;
404 	if (connection->ttl>0)
405 		error = belle_sip_snprintf(buff,buff_size,offset,"/%i",connection->ttl);
406 	if (error!=BELLE_SIP_OK) return error;
407 	if (connection->range>0)
408 		error = belle_sip_snprintf(buff,buff_size,offset,"/%i",connection->range);
409 	return error;
410 }
411 
BELLE_SDP_NEW(connection,belle_sip_object)412 BELLE_SDP_NEW(connection,belle_sip_object)
413 BELLE_SDP_PARSE(connection)
414 belle_sdp_connection_t* belle_sdp_connection_create(const char* net_type, const char* addr_type, const char* addr) {
415 	belle_sdp_connection_t* connection = belle_sdp_connection_new();
416 	belle_sdp_connection_set_network_type(connection,net_type);
417 	belle_sdp_connection_set_address_type(connection,addr_type);
418 	belle_sdp_connection_set_address(connection,addr);
419 	return connection;
420 }
421 GET_SET_STRING(belle_sdp_connection,network_type);
422 GET_SET_STRING(belle_sdp_connection,address_type);
423 GET_SET_STRING(belle_sdp_connection,address);
424 GET_SET_INT(belle_sdp_connection,ttl,int);
425 GET_SET_INT(belle_sdp_connection,range,int);
426 /************************
427  * email
428  ***********************/
429 struct _belle_sdp_email {
430 	belle_sip_object_t base;
431 	char* value;
432  };
433 
belle_sdp_email_destroy(belle_sdp_email_t * email)434 void belle_sdp_email_destroy(belle_sdp_email_t* email) {
435 	DESTROY_STRING(email,value)
436 }
437 
belle_sdp_email_clone(belle_sdp_email_t * email,const belle_sdp_email_t * orig)438 void belle_sdp_email_clone(belle_sdp_email_t *email, const belle_sdp_email_t *orig){
439 	CLONE_STRING(belle_sdp_email,value,email,orig)
440 }
441 
belle_sdp_email_marshal(belle_sdp_email_t * email,char * buff,size_t buff_size,size_t * offset)442 belle_sip_error_code belle_sdp_email_marshal(belle_sdp_email_t* email, char* buff, size_t buff_size, size_t *offset) {
443 	return belle_sip_snprintf(buff,buff_size,offset,"e=%s",email->value);
444 }
445 
446 BELLE_SDP_NEW(email,belle_sip_object)
447 BELLE_SDP_PARSE(email)
448 GET_SET_STRING(belle_sdp_email,value);
449 /************************
450  * info
451  ***********************/
452 struct _belle_sdp_info {
453 	belle_sip_object_t base;
454 	const char* value;
455  };
456 
belle_sdp_info_destroy(belle_sdp_info_t * info)457 void belle_sdp_info_destroy(belle_sdp_info_t* info) {
458 	DESTROY_STRING(info,value)
459 }
460 
belle_sdp_info_clone(belle_sdp_info_t * info,const belle_sdp_info_t * orig)461 void belle_sdp_info_clone(belle_sdp_info_t *info, const belle_sdp_info_t *orig){
462 	CLONE_STRING(belle_sdp_info,value,info,orig)
463 }
464 
belle_sdp_info_marshal(belle_sdp_info_t * info,char * buff,size_t buff_size,size_t * offset)465 belle_sip_error_code belle_sdp_info_marshal(belle_sdp_info_t* info, char* buff, size_t buff_size, size_t *offset) {
466 	return belle_sip_snprintf(buff,buff_size,offset,"i=%s",info->value);
467 }
468 
469 BELLE_SDP_NEW(info,belle_sip_object)
470 BELLE_SDP_PARSE(info)
471 GET_SET_STRING(belle_sdp_info,value);
472 /************************
473  * media
474  ***********************/
475 struct _belle_sdp_media {
476 	belle_sip_object_t base;
477 	const char* media_type;
478 	int media_port;
479 	belle_sip_list_t* media_formats;
480 	int port_count;
481 	const char* protocol;
482 	const char* raw_fmt;
483  };
belle_sdp_media_get_media_formats(const belle_sdp_media_t * media)484 belle_sip_list_t*	belle_sdp_media_get_media_formats(const belle_sdp_media_t* media) {
485 	return media->media_formats;
486 }
belle_sdp_media_set_media_formats(belle_sdp_media_t * media,belle_sip_list_t * formats)487 void belle_sdp_media_set_media_formats( belle_sdp_media_t* media, belle_sip_list_t* formats) {
488 	/*belle_sip_list_free(media->media_formats); to allow easy list management might be better to add an append format method*/
489 	media->media_formats = formats;
490 }
belle_sdp_media_destroy(belle_sdp_media_t * media)491 void belle_sdp_media_destroy(belle_sdp_media_t* media) {
492 	DESTROY_STRING(media,media_type)
493 	belle_sip_list_free(media->media_formats);
494 	DESTROY_STRING(media,protocol)
495 }
belle_sdp_media_init(belle_sdp_media_t * media)496 static void belle_sdp_media_init(belle_sdp_media_t* media) {
497 	media->port_count=1;
498 }
499 
belle_sdp_media_clone(belle_sdp_media_t * media,const belle_sdp_media_t * orig)500 void belle_sdp_media_clone(belle_sdp_media_t *media, const belle_sdp_media_t *orig){
501 	CLONE_STRING(belle_sdp_media,media_type,media,orig)
502 	media->media_port=orig->media_port;
503 	media->media_formats = belle_sip_list_copy(orig->media_formats);
504 	media->port_count=orig->port_count;
505 	CLONE_STRING(belle_sdp_media,protocol,media,orig)
506 }
507 
belle_sdp_media_marshal(belle_sdp_media_t * media,char * buff,size_t buff_size,size_t * offset)508 belle_sip_error_code belle_sdp_media_marshal(belle_sdp_media_t* media, char* buff, size_t buff_size, size_t *offset) {
509 	belle_sip_list_t* list=media->media_formats;
510 	belle_sip_error_code error=belle_sip_snprintf(buff,buff_size,offset,"m=%s %i",media->media_type,media->media_port);
511 	if (error!=BELLE_SIP_OK) return error;
512 	if (media->port_count>1) {
513 		error=belle_sip_snprintf(buff,buff_size,offset,"/%i",media->port_count);
514 		if (error!=BELLE_SIP_OK) return error;
515 	}
516 	error=belle_sip_snprintf(buff,buff_size,offset," %s",media->protocol);
517 	if (error!=BELLE_SIP_OK) return error;
518 	for(;list!=NULL;list=list->next){
519 		error=belle_sip_snprintf(buff,buff_size,offset," %li",(long)(intptr_t)list->data);
520 		if (error!=BELLE_SIP_OK) return error;
521 	}
522 	return error;
523 }
524 
BELLE_SDP_NEW_WITH_CTR(media,belle_sip_object)525 BELLE_SDP_NEW_WITH_CTR(media,belle_sip_object)
526 BELLE_SDP_PARSE(media)
527 belle_sdp_media_t* belle_sdp_media_create(const char* media_type
528 						 ,int media_port
529 						 ,int port_count
530 						 ,const char* protocol
531 						 ,belle_sip_list_t* static_media_formats) {
532 	belle_sdp_media_t* media= belle_sdp_media_new();
533 	belle_sdp_media_set_media_type(media,media_type);
534 	belle_sdp_media_set_media_port(media,media_port);
535 	belle_sdp_media_set_port_count(media,port_count);
536 	belle_sdp_media_set_protocol(media,protocol);
537 	if (static_media_formats) belle_sdp_media_set_media_formats(media,static_media_formats);
538 	return media;
539 }
540 GET_SET_STRING(belle_sdp_media,media_type);
541 GET_SET_STRING(belle_sdp_media,protocol);
542 GET_SET_INT(belle_sdp_media,media_port,int)
543 GET_SET_INT(belle_sdp_media,port_count,int)
544 
545 /************************
546  * base_description
547  ***********************/
548 typedef struct _belle_sdp_base_description {
549 	belle_sip_object_t base;
550 	belle_sdp_info_t* info;
551 	belle_sdp_connection_t* connection;
552 	belle_sip_list_t* bandwidths;
553 	belle_sip_list_t* attributes;
554 } belle_sdp_base_description_t;
555 
belle_sdp_base_description_destroy(belle_sdp_base_description_t * base_description)556 static void belle_sdp_base_description_destroy(belle_sdp_base_description_t* base_description) {
557 	if (base_description->info) belle_sip_object_unref(BELLE_SIP_OBJECT(base_description->info));
558 	if (base_description->connection) belle_sip_object_unref(BELLE_SIP_OBJECT(base_description->connection));
559 	belle_sip_list_free_with_data(base_description->bandwidths,belle_sip_object_freefunc);
560 	belle_sip_list_free_with_data(base_description->attributes,belle_sip_object_freefunc);
561 }
belle_sdp_base_description_init(belle_sdp_base_description_t * base_description)562 static void belle_sdp_base_description_init(belle_sdp_base_description_t* base_description) {
563 }
belle_sdp_base_description_clone(belle_sdp_base_description_t * base_description,const belle_sdp_base_description_t * orig)564 static void belle_sdp_base_description_clone(belle_sdp_base_description_t *base_description, const belle_sdp_base_description_t *orig){
565 	if (orig->info) base_description->info = BELLE_SDP_INFO(belle_sip_object_clone_and_ref(BELLE_SIP_OBJECT(orig->info)));
566 	if (orig->connection) base_description->connection = BELLE_SDP_CONNECTION(belle_sip_object_clone_and_ref(BELLE_SIP_OBJECT(orig->connection)));
567 	base_description->bandwidths = belle_sip_list_copy_with_data(orig->bandwidths,belle_sip_object_copyfunc);
568 	base_description->attributes = belle_sip_list_copy_with_data(orig->attributes,belle_sip_object_copyfunc);
569 
570 }
571 
belle_sdp_base_description_marshal(belle_sdp_base_description_t * base_description,char * buff,size_t buff_size,size_t * offset)572 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) {
573 	belle_sip_error_code error=BELLE_SIP_OK;
574 	belle_sip_list_t* bandwidths;
575 //	belle_sip_list_t* attributes;
576 	if (base_description->info) {
577 		error=belle_sip_object_marshal(BELLE_SIP_OBJECT(base_description->info),buff,buff_size,offset);
578 		if (error!=BELLE_SIP_OK) return error;
579 		error=belle_sip_snprintf(buff, buff_size, offset, "\r\n");
580 		if (error!=BELLE_SIP_OK) return error;
581 	}
582 	if (base_description->connection) {
583 		error=belle_sip_object_marshal(BELLE_SIP_OBJECT(base_description->connection),buff,buff_size,offset);
584 		if (error!=BELLE_SIP_OK) return error;
585 		error=belle_sip_snprintf(buff, buff_size, offset, "\r\n");
586 		if (error!=BELLE_SIP_OK) return error;
587 	}
588 	for(bandwidths=base_description->bandwidths;bandwidths!=NULL;bandwidths=bandwidths->next){
589 		error=belle_sip_object_marshal(BELLE_SIP_OBJECT(bandwidths->data),buff,buff_size,offset);
590 		if (error!=BELLE_SIP_OK) return error;
591 		error=belle_sip_snprintf(buff, buff_size, offset, "\r\n");
592 		if (error!=BELLE_SIP_OK) return error;
593 	}
594 //	for(attributes=base_description->attributes;attributes!=NULL;attributes=attributes->next){
595 //		error=belle_sip_object_marshal(BELLE_SIP_OBJECT(attributes->data),buff,buff_size,offset);
596 //		error=belle_sip_snprintf(buff, buff_size, offset, "\r\n");
597 //	}
598 	return error;
599 }
600 
601 BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(belle_sdp_base_description_t);
602 BELLE_SIP_INSTANCIATE_VPTR(belle_sdp_base_description_t
603 							,belle_sip_object_t
604 							,belle_sdp_base_description_destroy
605 							,belle_sdp_base_description_clone
606 							,belle_sdp_base_description_marshal
607 							,FALSE);
608 
belle_sdp_base_description_attribute_comp_func(const belle_sdp_attribute_t * a,const char * b)609 static int belle_sdp_base_description_attribute_comp_func(const belle_sdp_attribute_t* a, const char*b) {
610 	return strcmp(a->name,b);
611 }
belle_sdp_base_description_get_attribute(const belle_sdp_base_description_t * base_description,const char * name)612 belle_sdp_attribute_t*	belle_sdp_base_description_get_attribute(const belle_sdp_base_description_t* base_description, const char* name) {
613 	belle_sip_list_t* attribute;
614 	attribute = belle_sip_list_find_custom(base_description->attributes, (belle_sip_compare_func)belle_sdp_base_description_attribute_comp_func, name);
615 	if (attribute) {
616 		return ((belle_sdp_attribute_t*)attribute->data);
617 	} else {
618 		return NULL;
619 	}
620 }
belle_sdp_base_description_get_attribute_value(const belle_sdp_base_description_t * base_description,const char * name)621 const char*	belle_sdp_base_description_get_attribute_value(const belle_sdp_base_description_t* base_description, const char* name) {
622 	belle_sdp_attribute_t* attribute = belle_sdp_base_description_get_attribute(base_description,name);
623 	if (attribute) {
624 		return belle_sdp_attribute_get_value(attribute);
625 	} else return NULL;
626 
627 }
belle_sdp_base_description_get_attributes(const belle_sdp_base_description_t * base_description)628 belle_sip_list_t* belle_sdp_base_description_get_attributes(const belle_sdp_base_description_t* base_description) {
629 	return base_description->attributes;
630 }
belle_sdp_base_description_bandwidth_comp_func(const belle_sdp_bandwidth_t * a,const char * b)631 static int belle_sdp_base_description_bandwidth_comp_func(const belle_sdp_bandwidth_t* a, const char*b) {
632 	return strcmp(a->type,b);
633 }
634 
635 
belle_sdp_base_description_get_bandwidth(const belle_sdp_base_description_t * base_description,const char * name)636 belle_sdp_bandwidth_t* belle_sdp_base_description_get_bandwidth(const belle_sdp_base_description_t *base_description, const char *name){
637 	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);
638 	if( found ){
639 		return ((belle_sdp_bandwidth_t*)found->data);
640 	} else {
641 		return NULL;
642 	}
643 }
644 
belle_sdp_base_description_get_bandwidth_value(const belle_sdp_base_description_t * base_description,const char * name)645 int	belle_sdp_base_description_get_bandwidth_value(const belle_sdp_base_description_t* base_description, const char* name) {
646 	belle_sip_list_t* bandwidth;
647 	bandwidth = belle_sip_list_find_custom(base_description->bandwidths, (belle_sip_compare_func)belle_sdp_base_description_bandwidth_comp_func, name);
648 	if (bandwidth) {
649 		return ((belle_sdp_bandwidth_t*)bandwidth->data)->value;
650 	} else {
651 		return -1;
652 	}
653 }
belle_sdp_base_description_remove_attribute(belle_sdp_base_description_t * base_description,const char * name)654 void belle_sdp_base_description_remove_attribute(belle_sdp_base_description_t* base_description,const char* name) {
655 	belle_sip_list_t* attribute;
656 	attribute = belle_sip_list_find_custom(base_description->attributes, (belle_sip_compare_func)belle_sdp_base_description_attribute_comp_func, name);
657 	if (attribute) {
658 		belle_sip_object_unref(BELLE_SIP_OBJECT(attribute->data));
659 		base_description->attributes = belle_sip_list_delete_link(base_description->attributes,attribute);
660 	}
661 
662 }
belle_sdp_base_description_remove_bandwidth(belle_sdp_base_description_t * base_description,const char * name)663 void belle_sdp_base_description_remove_bandwidth(belle_sdp_base_description_t* base_description,const char* name) {
664 	belle_sip_list_t* bandwidth;
665 	bandwidth = belle_sip_list_find_custom(base_description->bandwidths, (belle_sip_compare_func)belle_sdp_base_description_bandwidth_comp_func, name);
666 	if (bandwidth) {
667 		belle_sip_object_unref(BELLE_SIP_OBJECT(bandwidth->data));
668 		base_description->bandwidths = belle_sip_list_delete_link(base_description->bandwidths,bandwidth);
669 	}
670 }
belle_sdp_base_description_set_attribute_value(belle_sdp_base_description_t * base_description,const char * name,const char * value)671 void belle_sdp_base_description_set_attribute_value(belle_sdp_base_description_t* base_description, const char* name, const char* value) {
672 	belle_sdp_raw_attribute_t* attribute = belle_sdp_raw_attribute_new();
673 	belle_sdp_attribute_set_name(BELLE_SDP_ATTRIBUTE(attribute),name);
674 	belle_sdp_raw_attribute_set_value(attribute,value);
675 	base_description->attributes = belle_sip_list_append(base_description->attributes,belle_sip_object_ref(attribute));
676 }
belle_sdp_base_description_add_attribute(belle_sdp_base_description_t * base_description,const belle_sdp_attribute_t * attribute)677 void belle_sdp_base_description_add_attribute(belle_sdp_base_description_t* base_description, const belle_sdp_attribute_t* attribute) {
678 	base_description->attributes = belle_sip_list_append(base_description->attributes,(void*)belle_sip_object_ref(BELLE_SIP_OBJECT(attribute)));
679 }
680 
681 #define SET_LIST(list_name,value) \
682 		belle_sip_list_t* list;\
683 		if (list_name) {\
684 			belle_sip_list_free_with_data(list_name,belle_sip_object_unref);\
685 		} \
686 		for (list=value;list !=NULL; list=list->next) {\
687 			belle_sip_object_ref(BELLE_SIP_OBJECT(list->data));\
688 		}\
689 		list_name=value;
690 
691 
belle_sdp_base_description_set_attributes(belle_sdp_base_description_t * base_description,belle_sip_list_t * attributes)692 void belle_sdp_base_description_set_attributes(belle_sdp_base_description_t* base_description, belle_sip_list_t* attributes) {
693 	SET_LIST(base_description->attributes,attributes)
694 }
belle_sdp_base_description_set_bandwidth(belle_sdp_base_description_t * base_description,const char * type,int value)695 void belle_sdp_base_description_set_bandwidth(belle_sdp_base_description_t* base_description, const char* type, int value) {
696 
697 	belle_sdp_bandwidth_t* bandwidth = BELLE_SDP_BANDWIDTH(belle_sdp_base_description_get_bandwidth(base_description, type));
698 	if( bandwidth == NULL ){
699 		bandwidth= belle_sdp_bandwidth_new();
700 		belle_sdp_bandwidth_set_type(bandwidth,type);
701 		belle_sdp_bandwidth_set_value(bandwidth,value);
702 		base_description->bandwidths = belle_sip_list_append(base_description->bandwidths,belle_sip_object_ref(bandwidth));
703 	} else {
704 		belle_sdp_bandwidth_set_value(bandwidth,value);
705 	}
706 }
belle_sdp_base_description_add_bandwidth(belle_sdp_base_description_t * base_description,const belle_sdp_bandwidth_t * bandwidth)707 void belle_sdp_base_description_add_bandwidth(belle_sdp_base_description_t* base_description, const belle_sdp_bandwidth_t* bandwidth) {
708 
709 	base_description->bandwidths = belle_sip_list_append(base_description->bandwidths,(void *)belle_sip_object_ref((void *)bandwidth));
710 }
belle_sdp_base_description_set_bandwidths(belle_sdp_base_description_t * base_description,belle_sip_list_t * bandwidths)711 void belle_sdp_base_description_set_bandwidths(belle_sdp_base_description_t* base_description, belle_sip_list_t* bandwidths) {
712 	SET_LIST(base_description->bandwidths,bandwidths)
713 }
714 
715 /************************
716  * media_description
717  ***********************/
718 struct _belle_sdp_media_description {
719 	belle_sdp_base_description_t base_description;
720 	belle_sdp_media_t* media;
721 };
belle_sdp_media_description_destroy(belle_sdp_media_description_t * media_description)722 void belle_sdp_media_description_destroy(belle_sdp_media_description_t* media_description) {
723 	if (media_description->media) belle_sip_object_unref(BELLE_SIP_OBJECT((media_description->media)));
724 }
725 
belle_sdp_media_description_clone(belle_sdp_media_description_t * media_description,const belle_sdp_media_description_t * orig)726 void belle_sdp_media_description_clone(belle_sdp_media_description_t *media_description, const belle_sdp_media_description_t *orig){
727 	if (orig->media) media_description->media = BELLE_SDP_MEDIA(belle_sip_object_clone_and_ref(BELLE_SIP_OBJECT((orig->media))));
728 }
729 
belle_sdp_media_description_marshal(belle_sdp_media_description_t * media_description,char * buff,size_t buff_size,size_t * offset)730 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) {
731 	belle_sip_list_t* attributes;
732 	belle_sip_error_code error=belle_sip_object_marshal(BELLE_SIP_OBJECT(media_description->media),buff,buff_size,offset);
733 	if (error!=BELLE_SIP_OK) return error;
734 	error=belle_sip_snprintf(buff, buff_size, offset, "\r\n");
735 	if (error!=BELLE_SIP_OK) return error;
736 	error=belle_sdp_base_description_marshal(BELLE_SIP_CAST(media_description,belle_sdp_base_description_t),buff,buff_size,offset);
737 	if (error!=BELLE_SIP_OK) return error;
738 
739 	for(attributes=media_description->base_description.attributes;attributes!=NULL;attributes=attributes->next){
740 		error=belle_sip_object_marshal(BELLE_SIP_OBJECT(attributes->data),buff,buff_size,offset);
741 		if (error!=BELLE_SIP_OK) return error;
742 		error=belle_sip_snprintf(buff, buff_size, offset, "\r\n");
743 		if (error!=BELLE_SIP_OK) return error;
744 	}
745 	return error;
746 }
747 
BELLE_SDP_NEW(media_description,belle_sdp_base_description)748 BELLE_SDP_NEW(media_description,belle_sdp_base_description)
749 belle_sdp_media_description_t* belle_sdp_media_description_create(const char* media_type
750 																 ,int media_port
751 																 ,int port_count
752 																 ,const char* protocol
753 																 ,belle_sip_list_t* static_media_formats) {
754 	belle_sdp_media_description_t* media_desc=belle_sdp_media_description_new();
755 	belle_sdp_media_description_set_media(media_desc,belle_sdp_media_create(media_type,media_port,port_count,protocol,static_media_formats));
756 	return media_desc;
757 }
BELLE_SDP_PARSE(media_description)758 BELLE_SDP_PARSE(media_description)
759 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) {
760 	belle_sip_error("belle_sdp_media_description_add_dynamic_payloads not implemented yet");
761 }
belle_sdp_media_description_get_attribute(const belle_sdp_media_description_t * media_description,const char * name)762 belle_sdp_attribute_t*	belle_sdp_media_description_get_attribute(const belle_sdp_media_description_t* media_description, const char* name) {
763 	return belle_sdp_base_description_get_attribute(BELLE_SIP_CAST(media_description,belle_sdp_base_description_t),name);
764 }
belle_sdp_media_description_get_attribute_value(const belle_sdp_media_description_t * media_description,const char * name)765 const char*	belle_sdp_media_description_get_attribute_value(const belle_sdp_media_description_t* media_description, const char* name) {
766 	return belle_sdp_base_description_get_attribute_value(BELLE_SIP_CAST(media_description,belle_sdp_base_description_t),name);
767 }
belle_sdp_media_description_get_attributes(const belle_sdp_media_description_t * media_description)768 belle_sip_list_t* belle_sdp_media_description_get_attributes(const belle_sdp_media_description_t* media_description) {
769 	return BELLE_SIP_CAST(media_description,belle_sdp_base_description_t)->attributes;
770 }
771 
belle_sdp_media_description_get_bandwidth(const belle_sdp_media_description_t * media_description,const char * name)772 int	belle_sdp_media_description_get_bandwidth(const belle_sdp_media_description_t* media_description, const char* name) {
773 	return belle_sdp_base_description_get_bandwidth_value(BELLE_SIP_CAST(media_description,belle_sdp_base_description_t),name);
774 }
belle_sdp_media_description_get_bandwidths(const belle_sdp_media_description_t * media_description)775 belle_sip_list_t* belle_sdp_media_description_get_bandwidths(const belle_sdp_media_description_t* media_description) {
776 	return BELLE_SIP_CAST(media_description,belle_sdp_base_description_t)->bandwidths;
777 }
belle_sdp_media_description_get_connection(const belle_sdp_media_description_t * media_description)778 belle_sdp_connection_t*	belle_sdp_media_description_get_connection(const belle_sdp_media_description_t* media_description) {
779 	return BELLE_SIP_CAST(media_description,belle_sdp_base_description_t)->connection;
780 }
belle_sdp_media_description_get_info(const belle_sdp_media_description_t * media_description)781 belle_sdp_info_t* belle_sdp_media_description_get_info(const belle_sdp_media_description_t* media_description) {
782 	return BELLE_SIP_CAST(media_description,belle_sdp_base_description_t)->info;
783 }
784 /*belle_sdp_key_t*  belle_sdp_media_description_get_key(const belle_sdp_media_description_t* media_description);*/
belle_sdp_media_description_get_media(const belle_sdp_media_description_t * media_description)785 belle_sdp_media_t* belle_sdp_media_description_get_media(const belle_sdp_media_description_t* media_description) {
786 	return media_description->media;
787 }
788 
789 struct static_payload {
790 	unsigned char number;
791 	int channel_count;
792 	const char* type;
793 	int	rate;
794 };
795 #define STATIC_PAYLOAD_LIST_LENTH 8
796 /*
797  * rfc 3551
798  * PT   encoding    media type  clock rate   channels
799 					name                    (Hz)
800 			   ___________________________________________________
801 			   0    PCMU        A            8,000       1
802 			   1    reserved    A
803 			   2    reserved    A
804 			   3    GSM         A            8,000       1
805 			   4    G723        A            8,000       1
806 			   5    DVI4        A            8,000       1
807 			   6    DVI4        A           16,000       1
808 			   7    LPC         A            8,000       1
809 			   8    PCMA        A            8,000       1
810 			   9    G722        A            8,000       1
811 			   10   L16         A           44,100       2
812 			   11   L16         A           44,100       1
813 			   12   QCELP       A            8,000       1
814 			   13   CN          A            8,000       1
815 			   14   MPA         A           90,000       (see text)
816 			   15   G728        A            8,000       1
817 			   16   DVI4        A           11,025       1
818 			   17   DVI4        A           22,050       1
819 			   18   G729        A            8,000       1
820 			   Table 4: Payload types (PT) for audio encodings
821 
822   PT      encoding    media type  clock rate
823 					   name                    (Hz)
824 			   _____________________________________________
825 			   24      unassigned  V
826 			   25      CelB        V           90,000
827 			   26      JPEG        V           90,000
828 			   27      unassigned  V
829 			   28      nv          V           90,000
830 			   29      unassigned  V
831 			   30      unassigned  V
832 			   31      H261        V           90,000
833 			   32      MPV         V           90,000
834 			   33      MP2T        AV          90,000
835 			   34      H263        V           90,000
836 
837 			   Table 5: Payload types (PT) for video and combined
838 						encodings
839 
840 
841  *
842  * */
843 
844 const struct static_payload static_payload_list [] ={
845 	/*audio*/
846 	{0,1,"PCMU",8000},
847 	{3,1,"GSM",8000},
848 	{4,1,"G723",8000},
849 	{5,1,"DVI4",8000},
850 	{6,1,"DVI4",16000},
851 	{7,1,"LPC",8000},
852 	{8,1,"PCMA",8000},
853 	{9,1,"G722",8000},
854 	{10,2,"L16",44100},
855 	{11,1,"L16",44100},
856 	{12,1,"QCELP",8000},
857 	{13,1,"CN",8000},
858 	{14,1,"MPA",90000},
859 	{15,1,"G728",8000},
860 	{16,1,"DVI4",11025},
861 	{17,1,"DVI4",22050},
862 	{18,1,"G729",8000},
863 	/*video*/
864 	{25,0,"CelB",90000},
865 	{26,0,"JPEG",90000},
866 	{28,0,"nv",90000},
867 	{31,0,"H261",90000},
868 	{32,0,"MPV",90000},
869 	{33,0,"MP2T",90000},
870 	{34,0,"H263",90000}
871 };
872 
873 static const size_t payload_list_elements=sizeof(static_payload_list)/sizeof(struct static_payload);
874 
mime_parameter_is_static(const belle_sdp_mime_parameter_t * param)875 static int mime_parameter_is_static(const belle_sdp_mime_parameter_t *param){
876 	const struct static_payload* iterator;
877 	size_t i;
878 
879 	for (iterator = static_payload_list,i=0;i<payload_list_elements;i++,iterator++) {
880 		if (iterator->number == param->media_format &&
881 			strcasecmp(iterator->type,param->type)==0 &&
882 			iterator->channel_count==param->channel_count &&
883 			iterator->rate==param->rate ) {
884 			return TRUE;
885 		}
886 	}
887 	return FALSE;
888 }
889 
mime_parameter_fill_from_static(belle_sdp_mime_parameter_t * mime_parameter,int format)890 static int mime_parameter_fill_from_static(belle_sdp_mime_parameter_t *mime_parameter,int format) {
891 	const struct static_payload* iterator;
892 	size_t i;
893 
894 	for (iterator = static_payload_list,i=0;i<payload_list_elements;i++,iterator++) {
895 		if (iterator->number == format) {
896 			belle_sdp_mime_parameter_set_type(mime_parameter,iterator->type);
897 			belle_sdp_mime_parameter_set_rate(mime_parameter,iterator->rate);
898 			belle_sdp_mime_parameter_set_channel_count(mime_parameter,iterator->channel_count);
899 			break;
900 		}
901 	}
902 	return 0;
903 }
904 
mime_parameter_fill_from_rtpmap(belle_sdp_mime_parameter_t * mime_parameter,const char * rtpmap,int is_audio)905 static int mime_parameter_fill_from_rtpmap(belle_sdp_mime_parameter_t *mime_parameter, const char *rtpmap, int is_audio){
906 	char *mime=belle_sip_strdup(rtpmap);
907 	char *p=strchr(mime,'/');
908 	if (p){
909 		char *chans;
910 		*p='\0';
911 		p++;
912 		chans=strchr(p,'/');
913 		if (chans){
914 			*chans='\0';
915 			chans++;
916 			belle_sdp_mime_parameter_set_channel_count(mime_parameter,atoi(chans));
917 		}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*/
918 		belle_sdp_mime_parameter_set_rate(mime_parameter,atoi(p));
919 	}
920 	belle_sdp_mime_parameter_set_type(mime_parameter,mime);
921 	belle_sip_free(mime);
922 	return 0;
923 }
924 /* return the value of attr "field" for payload pt at line pos (field=rtpmap,fmtp...)*/
belle_sdp_media_description_a_attr_value_get_with_pt(const belle_sdp_media_description_t * media_description,int pt,const char * field)925 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)
926 {
927 	int tmppt=0,scanned=0;
928 	const char *tmp;
929 	belle_sdp_attribute_t *attr;
930 	belle_sip_list_t* attribute_list;
931 	for (	attribute_list =belle_sdp_media_description_get_attributes(media_description)
932 						;attribute_list!=NULL
933 						;attribute_list=attribute_list->next) {
934 
935 		attr = BELLE_SDP_ATTRIBUTE(attribute_list->data);
936 		if (strcmp(field,belle_sdp_attribute_get_name(attr))==0 && belle_sdp_attribute_get_value(attr)!=NULL){
937 			int nb = sscanf(belle_sdp_attribute_get_value(attr),"%i %n",&tmppt,&scanned);
938 			/* the return value may depend on how %n is interpreted by the libc: see manpage*/
939 			if (nb == 1 || nb==2 ){
940 				if (pt==tmppt){
941 					tmp=belle_sdp_attribute_get_value(attr)+scanned;
942 					if (strlen(tmp)>0)
943 						return tmp;
944 				}
945 			}else belle_sip_warning("sdp has a strange a= line (%s) nb=%i",belle_sdp_attribute_get_value(attr),nb);
946 		}
947 	}
948 	return NULL;
949 }
950 
belle_sdp_media_description_build_mime_parameters(const belle_sdp_media_description_t * media_description)951 belle_sip_list_t* belle_sdp_media_description_build_mime_parameters(const belle_sdp_media_description_t* media_description) {
952 	/*First, get media type*/
953 	belle_sdp_media_t* media = belle_sdp_media_description_get_media(media_description);
954 	belle_sip_list_t* mime_parameter_list=NULL;
955 	belle_sip_list_t* media_formats=NULL;
956 	belle_sdp_mime_parameter_t* mime_parameter;
957 	const char* rtpmap=NULL;
958 	const char* fmtp=NULL;
959 	const char* ptime=NULL;
960 	const char* max_ptime=NULL;
961 	int ptime_as_int=-1;
962 	int max_ptime_as_int=-1;
963 	int is_audio=0;
964 
965 	if (!media) {
966 		belle_sip_error("belle_sdp_media_description_build_mime_parameters: no media");
967 		return NULL;
968 	}
969 	if (strcasecmp(belle_sdp_media_get_media_type(media),"audio")==0) is_audio=1;
970 	ptime = belle_sdp_media_description_get_attribute_value(media_description,"ptime");
971 	ptime?ptime_as_int=atoi(ptime):-1;
972 	max_ptime = belle_sdp_media_description_get_attribute_value(media_description,"maxptime");
973 	max_ptime?max_ptime_as_int=atoi(max_ptime):-1;
974 
975 	for (media_formats = belle_sdp_media_get_media_formats(media);media_formats!=NULL;media_formats=media_formats->next) {
976 		/*create mime parameters with format*/
977 		mime_parameter = belle_sdp_mime_parameter_new();
978 		belle_sdp_mime_parameter_set_ptime(mime_parameter,ptime_as_int);
979 		belle_sdp_mime_parameter_set_max_ptime(mime_parameter,max_ptime_as_int);
980 		belle_sdp_mime_parameter_set_media_format(mime_parameter,(int)(intptr_t)media_formats->data);
981 
982 		/*get rtpmap*/
983 		rtpmap = belle_sdp_media_description_a_attr_value_get_with_pt(media_description
984 																		,belle_sdp_mime_parameter_get_media_format(mime_parameter)
985 																		,"rtpmap");
986 		if (rtpmap) {
987 			mime_parameter_fill_from_rtpmap(mime_parameter,rtpmap,is_audio);
988 		}else{
989 			mime_parameter_fill_from_static(mime_parameter,belle_sdp_mime_parameter_get_media_format(mime_parameter));
990 		}
991 		fmtp = belle_sdp_media_description_a_attr_value_get_with_pt(media_description
992 																		,belle_sdp_mime_parameter_get_media_format(mime_parameter)
993 																		,"fmtp");
994 		if (fmtp) {
995 			belle_sdp_mime_parameter_set_parameters(mime_parameter,fmtp);
996 		}
997 
998 		mime_parameter_list=belle_sip_list_append(mime_parameter_list,mime_parameter);
999 	}
1000 	return mime_parameter_list;
1001 }
1002 #define MAX_FMTP_LENGTH 512
1003 
belle_sdp_media_description_append_values_from_mime_parameter(belle_sdp_media_description_t * media_description,const belle_sdp_mime_parameter_t * mime_parameter)1004 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) {
1005 	belle_sdp_media_t* media = belle_sdp_media_description_get_media(media_description);
1006 	char atribute_value [MAX_FMTP_LENGTH];
1007 	int current_ptime=0;
1008 	int current_max_ptime=0;
1009 
1010 	belle_sdp_media_set_media_formats(media,belle_sip_list_append(belle_sdp_media_get_media_formats(media)
1011 																,(void*)(intptr_t)(belle_sdp_mime_parameter_get_media_format(mime_parameter))));
1012 
1013 	if (belle_sdp_media_description_get_attribute_value(media_description,"ptime")) {
1014 		current_ptime=atoi(belle_sdp_media_description_get_attribute_value(media_description,"ptime"));
1015 		belle_sdp_media_description_remove_attribute(media_description,"ptime");
1016 	}
1017 
1018 	if (belle_sdp_media_description_get_attribute_value(media_description,"maxptime")) {
1019 		current_max_ptime=atoi(belle_sdp_media_description_get_attribute_value(media_description,"maxptime"));
1020 		belle_sdp_media_description_remove_attribute(media_description,"maxptime");
1021 	}
1022 
1023 #ifndef BELLE_SDP_FORCE_RTP_MAP /* defined to for RTP map even for static codec*/
1024 	if (!mime_parameter_is_static(mime_parameter)) {
1025 		/*dynamic payload*/
1026 #endif
1027 		if (belle_sdp_mime_parameter_get_channel_count(mime_parameter)>1) {
1028 			snprintf(atribute_value,MAX_FMTP_LENGTH,"%i %s/%i/%i"
1029 					,belle_sdp_mime_parameter_get_media_format(mime_parameter)
1030 					,belle_sdp_mime_parameter_get_type(mime_parameter)
1031 					,belle_sdp_mime_parameter_get_rate(mime_parameter)
1032 					,belle_sdp_mime_parameter_get_channel_count(mime_parameter));
1033 		} else {
1034 			snprintf(atribute_value,MAX_FMTP_LENGTH,"%i %s/%i"
1035 					,belle_sdp_mime_parameter_get_media_format(mime_parameter)
1036 					,belle_sdp_mime_parameter_get_type(mime_parameter)
1037 					,belle_sdp_mime_parameter_get_rate(mime_parameter));
1038 		}
1039 		belle_sdp_media_description_set_attribute_value(media_description,"rtpmap",atribute_value);
1040 #ifndef BELLE_SDP_FORCE_RTP_MAP
1041 	}
1042 #endif
1043 
1044 	// always include fmtp parameters if available
1045 	if (belle_sdp_mime_parameter_get_parameters(mime_parameter)) {
1046 		snprintf(atribute_value,MAX_FMTP_LENGTH,"%i %s"
1047 				,belle_sdp_mime_parameter_get_media_format(mime_parameter)
1048 				,belle_sdp_mime_parameter_get_parameters(mime_parameter));
1049 		belle_sdp_media_description_set_attribute_value(media_description,"fmtp",atribute_value);
1050 	}
1051 
1052 	if (belle_sdp_mime_parameter_get_ptime(mime_parameter)>current_ptime) {
1053 		current_ptime=belle_sdp_mime_parameter_get_ptime(mime_parameter);
1054 	}
1055 	if (current_ptime>0){
1056 		char  ptime[10];
1057 		snprintf(ptime,sizeof(ptime),"%i",current_ptime);
1058 		belle_sdp_media_description_set_attribute_value(media_description,"ptime",ptime);
1059 	}
1060 
1061 	if (belle_sdp_mime_parameter_get_max_ptime(mime_parameter)>current_max_ptime) {
1062 		current_max_ptime=belle_sdp_mime_parameter_get_max_ptime(mime_parameter);
1063 	}
1064 	if (current_max_ptime>0){
1065 		char  max_ptime[10];
1066 		snprintf(max_ptime,sizeof(max_ptime),"%i",current_max_ptime);
1067 		belle_sdp_media_description_set_attribute_value(media_description,"maxptime",max_ptime);
1068 	}
1069 
1070 }
belle_sdp_media_description_get_mime_types(const belle_sdp_media_description_t * media_description)1071 belle_sip_list_t* belle_sdp_media_description_get_mime_types(const belle_sdp_media_description_t* media_description) {
1072 	belle_sip_error("belle_sdp_media_description_get_mime_types: not implemented yet");
1073 	return NULL;
1074 }
1075 
belle_sdp_media_description_remove_attribute(belle_sdp_media_description_t * media_description,const char * name)1076 void belle_sdp_media_description_remove_attribute(belle_sdp_media_description_t* media_description,const char* name) {
1077 	belle_sdp_base_description_remove_attribute(BELLE_SIP_CAST(media_description,belle_sdp_base_description_t),name);
1078 }
belle_sdp_media_description_remove_bandwidth(belle_sdp_media_description_t * media_description,const char * name)1079 void belle_sdp_media_description_remove_bandwidth(belle_sdp_media_description_t* media_description,const char* name) {
1080 	belle_sdp_base_description_remove_bandwidth(BELLE_SIP_CAST(media_description,belle_sdp_base_description_t),name);
1081 }
belle_sdp_media_description_set_attribute_value(belle_sdp_media_description_t * media_description,const char * name,const char * value)1082 void belle_sdp_media_description_set_attribute_value(belle_sdp_media_description_t* media_description, const char* name, const char* value) {
1083 	belle_sdp_base_description_set_attribute_value(BELLE_SIP_CAST(media_description,belle_sdp_base_description_t),name,value);
1084 }
belle_sdp_media_description_set_attributes(belle_sdp_media_description_t * media_description,belle_sip_list_t * value)1085 void belle_sdp_media_description_set_attributes(belle_sdp_media_description_t* media_description, belle_sip_list_t* value) {
1086 	belle_sdp_base_description_set_attributes(BELLE_SIP_CAST(media_description,belle_sdp_base_description_t),value);
1087 }
1088 
belle_sdp_media_description_add_attribute(belle_sdp_media_description_t * media_description,const belle_sdp_attribute_t * attribute)1089 void belle_sdp_media_description_add_attribute(belle_sdp_media_description_t* media_description, const belle_sdp_attribute_t* attribute) {
1090 	belle_sdp_base_description_add_attribute(BELLE_SIP_CAST(media_description,belle_sdp_base_description_t),attribute);
1091 }
belle_sdp_media_description_set_bandwidth(belle_sdp_media_description_t * media_description,const char * type,int value)1092 void belle_sdp_media_description_set_bandwidth(belle_sdp_media_description_t* media_description, const char* type, int value) {
1093 	belle_sdp_base_description_set_bandwidth(BELLE_SIP_CAST(media_description,belle_sdp_base_description_t),type,value);
1094 }
belle_sdp_media_description_add_bandwidth(belle_sdp_media_description_t * media_description,const belle_sdp_bandwidth_t * bandwidth)1095 void belle_sdp_media_description_add_bandwidth(belle_sdp_media_description_t* media_description, const belle_sdp_bandwidth_t* bandwidth) {
1096 	belle_sdp_base_description_add_bandwidth(BELLE_SIP_CAST(media_description,belle_sdp_base_description_t),bandwidth);
1097 }
belle_sdp_media_description_set_bandwidths(belle_sdp_media_description_t * media_description,belle_sip_list_t * bandwidths)1098 void belle_sdp_media_description_set_bandwidths(belle_sdp_media_description_t* media_description, belle_sip_list_t* bandwidths) {
1099 	belle_sdp_base_description_set_bandwidths(BELLE_SIP_CAST(media_description,belle_sdp_base_description_t),bandwidths);
1100 }
1101 #define SET_OBJECT(object,param,param_type) \
1102 		param_type** current = &object->param; \
1103 		if (param) belle_sip_object_ref(param); \
1104 		if (*current) { \
1105 			belle_sip_object_unref(BELLE_SIP_OBJECT(*current)); \
1106 		} \
1107 		*current=param; \
1108 
1109 
belle_sdp_media_description_set_connection(belle_sdp_media_description_t * media_description,belle_sdp_connection_t * connection)1110 void belle_sdp_media_description_set_connection(belle_sdp_media_description_t* media_description, belle_sdp_connection_t* connection) {
1111 	SET_OBJECT(BELLE_SIP_CAST(media_description,belle_sdp_base_description_t),connection,belle_sdp_connection_t)
1112 }
belle_sdp_media_description_set_info(belle_sdp_media_description_t * media_description,belle_sdp_info_t * info)1113 void belle_sdp_media_description_set_info(belle_sdp_media_description_t* media_description,belle_sdp_info_t* info) {
1114 	SET_OBJECT(BELLE_SIP_CAST(media_description,belle_sdp_base_description_t),info,belle_sdp_info_t)
1115 }
1116 /*void belle_sdp_media_description_set_key(belle_sdp_media_description_t* media_description,belle_sdp_key_t* key);*/
belle_sdp_media_description_set_media(belle_sdp_media_description_t * media_description,belle_sdp_media_t * media)1117 void belle_sdp_media_description_set_media(belle_sdp_media_description_t* media_description, belle_sdp_media_t* media) {
1118 	SET_OBJECT(media_description,media,belle_sdp_media_t)
1119 }
1120 
1121 /************************
1122  * origin
1123  ***********************/
1124 struct _belle_sdp_origin {
1125 	belle_sip_object_t base;
1126 	const char* address;
1127 	const char* address_type;
1128 	const char* network_type;
1129 	const char* username;
1130 	unsigned int session_id;
1131 	unsigned int session_version;
1132 
1133  };
1134 
belle_sdp_origin_destroy(belle_sdp_origin_t * origin)1135 void belle_sdp_origin_destroy(belle_sdp_origin_t* origin) {
1136 	DESTROY_STRING(origin,address)
1137 	DESTROY_STRING(origin,address_type)
1138 	DESTROY_STRING(origin,network_type)
1139 	DESTROY_STRING(origin,username)
1140 }
1141 
belle_sdp_origin_clone(belle_sdp_origin_t * origin,const belle_sdp_origin_t * orig)1142 void belle_sdp_origin_clone(belle_sdp_origin_t *origin, const belle_sdp_origin_t *orig){
1143 	CLONE_STRING(belle_sdp_origin,username,origin,orig);
1144 	CLONE_STRING(belle_sdp_origin,address,origin,orig);
1145 	CLONE_STRING(belle_sdp_origin,address_type,origin,orig);
1146 	CLONE_STRING(belle_sdp_origin,network_type,origin,orig);
1147 	origin->session_id = orig->session_id;
1148 	origin->session_version = orig->session_version;
1149 }
1150 
belle_sdp_origin_marshal(belle_sdp_origin_t * origin,char * buff,size_t buff_size,size_t * offset)1151 belle_sip_error_code belle_sdp_origin_marshal(belle_sdp_origin_t* origin, char* buff, size_t buff_size, size_t *offset) {
1152 	return belle_sip_snprintf(	buff
1153 								,buff_size
1154 								,offset
1155 								,"o=%s %u %u %s %s %s"
1156 								,origin->username
1157 								,origin->session_id
1158 								,origin->session_version
1159 								,origin->network_type
1160 								,origin->address_type
1161 								,origin->address);
1162 }
1163 
BELLE_SDP_NEW(origin,belle_sip_object)1164 BELLE_SDP_NEW(origin,belle_sip_object)
1165 belle_sdp_origin_t* belle_sdp_origin_create(const char* user_name
1166 											, unsigned int session_id
1167 											, unsigned int session_version
1168 											, const char* network_type
1169 											, const char* addr_type
1170 											, const char* address) {
1171 	belle_sdp_origin_t* origin=belle_sdp_origin_new();
1172 	belle_sdp_origin_set_username(origin,user_name);
1173 	belle_sdp_origin_set_session_id(origin,session_id);
1174 	belle_sdp_origin_set_session_version(origin,session_version);
1175 	belle_sdp_origin_set_network_type(origin,network_type);
1176 	belle_sdp_origin_set_address_type(origin,addr_type);
1177 	belle_sdp_origin_set_address(origin,address);
1178 	return origin;
1179 }
1180 BELLE_SDP_PARSE(origin)
1181 GET_SET_STRING(belle_sdp_origin,username);
1182 GET_SET_STRING(belle_sdp_origin,address);
1183 GET_SET_STRING(belle_sdp_origin,address_type);
1184 GET_SET_STRING(belle_sdp_origin,network_type);
1185 GET_SET_INT(belle_sdp_origin,session_id,unsigned int);
1186 GET_SET_INT(belle_sdp_origin,session_version,unsigned int);
1187 /************************
1188  * session_name
1189  ***********************/
1190 struct _belle_sdp_session_name {
1191 	belle_sip_object_t base;
1192 	const char* value;
1193  };
1194 
belle_sdp_session_name_destroy(belle_sdp_session_name_t * session_name)1195 void belle_sdp_session_name_destroy(belle_sdp_session_name_t* session_name) {
1196 	DESTROY_STRING(session_name,value)
1197 }
1198 
belle_sdp_session_name_clone(belle_sdp_session_name_t * session_name,const belle_sdp_session_name_t * orig)1199 void belle_sdp_session_name_clone(belle_sdp_session_name_t *session_name, const belle_sdp_session_name_t *orig){
1200 	CLONE_STRING(belle_sdp_session_name,value,session_name,orig);
1201 }
1202 
belle_sdp_session_name_marshal(belle_sdp_session_name_t * session_name,char * buff,size_t buff_size,size_t * offset)1203 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) {
1204 	return belle_sip_snprintf(buff,buff_size,offset,"s=%s",session_name->value);
1205 }
1206 
BELLE_SDP_NEW(session_name,belle_sip_object)1207 BELLE_SDP_NEW(session_name,belle_sip_object)
1208 belle_sdp_session_name_t* belle_sdp_session_name_create (const char* name) {
1209 	belle_sdp_session_name_t* n=belle_sdp_session_name_new();
1210 	belle_sdp_session_name_set_value(n,name);
1211 	return n;
1212 }
1213 //BELLE_SDP_PARSE(session_name)
1214 GET_SET_STRING(belle_sdp_session_name,value);
1215 
1216 
1217 /************************
1218  * session_description
1219  ***********************/
1220 struct _belle_sdp_session_description {
1221 	belle_sdp_base_description_t base_description;
1222 	belle_sdp_version_t* version;
1223 	belle_sip_list_t* emails;
1224 	belle_sdp_origin_t* origin;
1225 	belle_sdp_session_name_t* session_name;
1226 	belle_sip_list_t* phones;
1227 	belle_sip_list_t* times;
1228 	belle_sdp_uri_t* uri;
1229 	belle_sdp_uri_t* zone_adjustments;
1230 	belle_sip_list_t* media_descriptions;
1231 
1232  };
belle_sdp_session_description_destroy(belle_sdp_session_description_t * session_description)1233 void belle_sdp_session_description_destroy(belle_sdp_session_description_t* session_description) {
1234 	if (session_description->version) belle_sip_object_unref(BELLE_SIP_OBJECT(session_description->version));
1235 	belle_sip_list_free_with_data(session_description->emails,belle_sip_object_freefunc);
1236 	if (session_description->origin) belle_sip_object_unref(BELLE_SIP_OBJECT(session_description->origin));
1237 	if (session_description->session_name) belle_sip_object_unref(BELLE_SIP_OBJECT(session_description->session_name));
1238 	belle_sip_list_free_with_data(session_description->phones,belle_sip_object_freefunc);
1239 	belle_sip_list_free_with_data(session_description->times,belle_sip_object_freefunc);
1240 	if (session_description->uri) belle_sip_object_unref(BELLE_SIP_OBJECT(session_description->uri));
1241 	if (session_description->zone_adjustments) belle_sip_object_unref(BELLE_SIP_OBJECT(session_description->zone_adjustments));
1242 	belle_sip_list_free_with_data(session_description->media_descriptions,belle_sip_object_freefunc);
1243 }
1244 
belle_sdp_session_description_clone(belle_sdp_session_description_t * session_description,const belle_sdp_session_description_t * orig)1245 void belle_sdp_session_description_clone(belle_sdp_session_description_t *session_description, const belle_sdp_session_description_t *orig){
1246 	if (orig->version) session_description->version = BELLE_SDP_VERSION(belle_sip_object_clone_and_ref(BELLE_SIP_OBJECT(orig->version)));
1247 	session_description->emails = belle_sip_list_copy_with_data(orig->emails,belle_sip_object_copyfunc);
1248 	if (orig->origin) session_description->origin = BELLE_SDP_ORIGIN(belle_sip_object_clone_and_ref(BELLE_SIP_OBJECT(orig->origin)));
1249 	if (orig->session_name) session_description->session_name = BELLE_SDP_SESSION_NAME(belle_sip_object_clone_and_ref(BELLE_SIP_OBJECT(orig->session_name)));
1250 	session_description->phones = belle_sip_list_copy_with_data(orig->phones,belle_sip_object_copyfunc);
1251 	session_description->times = belle_sip_list_copy_with_data(orig->times,belle_sip_object_copyfunc);
1252 	if (orig->uri) session_description->uri = BELLE_SDP_URI(belle_sip_object_clone_and_ref(BELLE_SIP_OBJECT(orig->uri)));
1253 	if (orig->zone_adjustments) session_description->zone_adjustments = BELLE_SDP_URI(belle_sip_object_clone_and_ref(BELLE_SIP_OBJECT(orig->zone_adjustments)));
1254 	session_description->media_descriptions = belle_sip_list_copy_with_data(orig->media_descriptions,belle_sip_object_copyfunc);
1255 }
1256 
belle_sdp_session_description_marshal(belle_sdp_session_description_t * session_description,char * buff,size_t buff_size,size_t * offset)1257 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) {
1258 /*session_description:   proto_version CR LF
1259 						 origin_field
1260 						 session_name_field
1261 						 (info CR LF)?
1262 						 uri_field?
1263 						 (email CR LF)*
1264 						 phone_field*
1265 						 (connection CR LF)?
1266 						 (bandwidth CR LF)*
1267 						 time_field
1268 						 (repeat_time CR LF)?
1269 						 (zone_adjustments CR LF)?
1270 						 (key_field CR LF)?
1271 						 (attribute CR LF)*
1272 						 media_descriptions;
1273  */
1274 	belle_sip_error_code error=BELLE_SIP_OK;
1275 	belle_sip_list_t* media_descriptions;
1276 	belle_sip_list_t* times;
1277 	belle_sip_list_t* attributes;
1278 
1279 	if (session_description->version) {
1280 		error=belle_sip_object_marshal(BELLE_SIP_OBJECT(session_description->version),buff,buff_size,offset);
1281 		if (error!=BELLE_SIP_OK) return error;
1282 		error=belle_sip_snprintf(buff, buff_size, offset, "\r\n");
1283 		if (error!=BELLE_SIP_OK) return error;
1284 	}
1285 
1286 	if (session_description->origin) {
1287 		error=belle_sip_object_marshal(BELLE_SIP_OBJECT(session_description->origin),buff,buff_size,offset);
1288 		if (error!=BELLE_SIP_OK) return error;
1289 		error=belle_sip_snprintf(buff, buff_size, offset, "\r\n");
1290 		if (error!=BELLE_SIP_OK) return error;
1291 	}
1292 
1293 	if (session_description->session_name) {
1294 		error=belle_sip_object_marshal(BELLE_SIP_OBJECT(session_description->session_name),buff,buff_size,offset);
1295 		if (error!=BELLE_SIP_OK) return error;
1296 		error=belle_sip_snprintf(buff, buff_size, offset, "\r\n");
1297 		if (error!=BELLE_SIP_OK) return error;
1298 	}
1299 
1300 	error=belle_sdp_base_description_marshal((belle_sdp_base_description_t*)(&session_description->base_description),buff,buff_size, offset);
1301 	if (error!=BELLE_SIP_OK) return error;
1302 
1303 	error=belle_sip_snprintf(buff, buff_size, offset, "t=");
1304 	if (error!=BELLE_SIP_OK) return error;
1305 	for(times=session_description->times;times!=NULL;times=times->next){
1306 		error=belle_sip_object_marshal(BELLE_SIP_OBJECT(times->data),buff,buff_size,offset);
1307 		if (error!=BELLE_SIP_OK) return error;
1308 		error=belle_sip_snprintf(buff, buff_size, offset, "\r\n");
1309 		if (error!=BELLE_SIP_OK) return error;
1310 	}
1311 
1312 	for(attributes=session_description->base_description.attributes;attributes!=NULL;attributes=attributes->next){
1313 		error=belle_sip_object_marshal(BELLE_SIP_OBJECT(attributes->data),buff,buff_size,offset);
1314 		if (error!=BELLE_SIP_OK) return error;
1315 		error=belle_sip_snprintf(buff, buff_size, offset, "\r\n");
1316 		if (error!=BELLE_SIP_OK) return error;
1317 	}
1318 
1319 	for(media_descriptions=session_description->media_descriptions;media_descriptions!=NULL;media_descriptions=media_descriptions->next){
1320 		error=belle_sip_object_marshal(BELLE_SIP_OBJECT(media_descriptions->data),buff,buff_size,offset);
1321 		if (error!=BELLE_SIP_OK) return error;
1322 	}
1323 	return error;
1324 }
1325 
BELLE_SDP_NEW(session_description,belle_sdp_base_description)1326 BELLE_SDP_NEW(session_description,belle_sdp_base_description)
1327 BELLE_SDP_PARSE(session_description)
1328 
1329 
1330 belle_sip_list_t * belle_sdp_session_description_get_attributes(const belle_sdp_session_description_t *session_description) {
1331 	return belle_sdp_base_description_get_attributes(BELLE_SIP_CAST(session_description, belle_sdp_base_description_t));
1332 }
1333 
belle_sdp_session_description_get_attribute_value(const belle_sdp_session_description_t * session_description,const char * name)1334 const char*	belle_sdp_session_description_get_attribute_value(const belle_sdp_session_description_t* session_description, const char* name) {
1335 	return belle_sdp_base_description_get_attribute_value(BELLE_SIP_CAST(session_description,belle_sdp_base_description_t),name);
1336 }
belle_sdp_session_description_get_attribute(const belle_sdp_session_description_t * session_description,const char * name)1337 const belle_sdp_attribute_t*	belle_sdp_session_description_get_attribute(const belle_sdp_session_description_t* session_description, const char* name) {
1338 	return belle_sdp_base_description_get_attribute(BELLE_SIP_CAST(session_description,belle_sdp_base_description_t),name);
1339 }
belle_sdp_session_description_get_bandwidth(const belle_sdp_session_description_t * session_description,const char * name)1340 int	belle_sdp_session_description_get_bandwidth(const belle_sdp_session_description_t* session_description, const char* name) {
1341 	return belle_sdp_base_description_get_bandwidth_value(BELLE_SIP_CAST(session_description,belle_sdp_base_description_t),name);
1342 }
belle_sdp_session_description_get_bandwidths(const belle_sdp_session_description_t * session_description)1343 belle_sip_list_t*	belle_sdp_session_description_get_bandwidths(const belle_sdp_session_description_t* session_description) {
1344 	return BELLE_SIP_CAST(session_description,belle_sdp_base_description_t)->bandwidths;
1345 }
belle_sdp_session_description_get_connection(const belle_sdp_session_description_t * session_description)1346 belle_sdp_connection_t*	belle_sdp_session_description_get_connection(const belle_sdp_session_description_t* session_description) {
1347 	return BELLE_SIP_CAST(session_description,belle_sdp_base_description_t)->connection;
1348 }
belle_sdp_session_description_get_emails(const belle_sdp_session_description_t * session_description)1349 belle_sip_list_t* belle_sdp_session_description_get_emails(const belle_sdp_session_description_t* session_description){
1350 	return session_description->emails;
1351 }
belle_sdp_session_description_get_info(const belle_sdp_session_description_t * session_description)1352 belle_sdp_info_t* belle_sdp_session_description_get_info(const belle_sdp_session_description_t* session_description) {
1353 	return BELLE_SIP_CAST(session_description,belle_sdp_base_description_t)->info;
1354 }
1355 /*belle_sdp_key_t*	belle_sdp_session_description_get_key(const belle_sdp_session_description_t* session_description);*/
belle_sdp_session_description_get_media_descriptions(const belle_sdp_session_description_t * session_description)1356 belle_sip_list_t* belle_sdp_session_description_get_media_descriptions(const belle_sdp_session_description_t* session_description) {
1357 	return session_description->media_descriptions;
1358 }
belle_sdp_session_description_get_origin(const belle_sdp_session_description_t * session_description)1359 belle_sdp_origin_t*	belle_sdp_session_description_get_origin(const belle_sdp_session_description_t* session_description){
1360 	return session_description->origin;
1361 }
belle_sdp_session_description_get_phones(const belle_sdp_session_description_t * session_description)1362 belle_sip_list_t* belle_sdp_session_description_get_phones(const belle_sdp_session_description_t* session_description) {
1363 	return session_description->phones;
1364 }
belle_sdp_session_description_get_session_name(const belle_sdp_session_description_t * session_description)1365 belle_sdp_session_name_t* belle_sdp_session_description_get_session_name(const belle_sdp_session_description_t* session_description) {
1366 	return session_description->session_name;
1367 }
belle_sdp_session_description_get_time_descriptions(const belle_sdp_session_description_t * session_description)1368 belle_sip_list_t* belle_sdp_session_description_get_time_descriptions(const belle_sdp_session_description_t* session_description) {
1369 	return session_description->times;
1370 }
belle_sdp_session_description_get_uri(const belle_sdp_session_description_t * session_description)1371 belle_sdp_uri_t* belle_sdp_session_description_get_uri(const belle_sdp_session_description_t* session_description) {
1372 	return session_description->uri;
1373 }
belle_sdp_session_description_get_version(const belle_sdp_session_description_t * session_description)1374 belle_sdp_version_t*	belle_sdp_session_description_get_version(const belle_sdp_session_description_t* session_description) {
1375 	return session_description->version;
1376 }
belle_sdp_session_description_get_zone_adjustments(const belle_sdp_session_description_t * session_description)1377 belle_sdp_uri_t* belle_sdp_session_description_get_zone_adjustments(const belle_sdp_session_description_t* session_description) {
1378 	return session_description->zone_adjustments;
1379 }
belle_sdp_session_description_remove_attribute(belle_sdp_session_description_t * session_description,const char * name)1380 void belle_sdp_session_description_remove_attribute(belle_sdp_session_description_t* session_description, const char* name) {
1381 	belle_sdp_base_description_remove_attribute(BELLE_SIP_CAST(session_description,belle_sdp_base_description_t),name);
1382 }
belle_sdp_session_description_remove_bandwidth(belle_sdp_session_description_t * session_description,const char * name)1383 void belle_sdp_session_description_remove_bandwidth(belle_sdp_session_description_t* session_description, const char* name) {
1384 	belle_sdp_base_description_remove_bandwidth(BELLE_SIP_CAST(session_description,belle_sdp_base_description_t),name);
1385 }
belle_sdp_session_description_set_attribute_value(belle_sdp_session_description_t * session_description,const char * name,const char * value)1386 void belle_sdp_session_description_set_attribute_value(belle_sdp_session_description_t* session_description, const char* name, const char* value) {
1387 	belle_sdp_base_description_set_attribute_value(BELLE_SIP_CAST(session_description,belle_sdp_base_description_t),name,value);
1388 }
belle_sdp_session_description_set_attributes(belle_sdp_session_description_t * session_description,belle_sip_list_t * attributes)1389 void belle_sdp_session_description_set_attributes(belle_sdp_session_description_t* session_description, belle_sip_list_t* attributes) {
1390 	belle_sdp_base_description_set_attributes(BELLE_SIP_CAST(session_description,belle_sdp_base_description_t),attributes);
1391 }
belle_sdp_session_description_add_attribute(belle_sdp_session_description_t * session_description,const belle_sdp_attribute_t * attribute)1392 void belle_sdp_session_description_add_attribute(belle_sdp_session_description_t* session_description, const belle_sdp_attribute_t* attribute) {
1393 	belle_sdp_base_description_add_attribute(BELLE_SIP_CAST(session_description,belle_sdp_base_description_t),attribute);
1394 }
belle_sdp_session_description_set_bandwidth(belle_sdp_session_description_t * session_description,const char * type,int value)1395 void belle_sdp_session_description_set_bandwidth(belle_sdp_session_description_t* session_description, const char* type, int value) {
1396 	belle_sdp_base_description_set_bandwidth(BELLE_SIP_CAST(session_description,belle_sdp_base_description_t),type,value);
1397 }
belle_sdp_session_description_set_bandwidths(belle_sdp_session_description_t * session_description,belle_sip_list_t * bandwidths)1398 void belle_sdp_session_description_set_bandwidths(belle_sdp_session_description_t* session_description, belle_sip_list_t* bandwidths) {
1399 	belle_sdp_base_description_set_bandwidths(BELLE_SIP_CAST(session_description,belle_sdp_base_description_t),bandwidths);
1400 }
belle_sdp_session_description_add_bandwidth(belle_sdp_session_description_t * session_description,const belle_sdp_bandwidth_t * bandwidth)1401 void belle_sdp_session_description_add_bandwidth(belle_sdp_session_description_t* session_description, const belle_sdp_bandwidth_t* bandwidth) {
1402 	belle_sdp_base_description_add_bandwidth(BELLE_SIP_CAST(session_description,belle_sdp_base_description_t),bandwidth);
1403 }
belle_sdp_session_description_set_connection(belle_sdp_session_description_t * session_description,belle_sdp_connection_t * connection)1404 void belle_sdp_session_description_set_connection(belle_sdp_session_description_t* session_description, belle_sdp_connection_t* connection) {
1405 	SET_OBJECT(BELLE_SIP_CAST(session_description,belle_sdp_base_description_t),connection,belle_sdp_connection_t)
1406 }
belle_sdp_session_description_set_emails(belle_sdp_session_description_t * session_description,belle_sip_list_t * emails)1407 void belle_sdp_session_description_set_emails(belle_sdp_session_description_t* session_description, belle_sip_list_t* emails) {
1408 	SET_LIST(session_description->emails,emails)
1409 }
belle_sdp_session_description_set_info(belle_sdp_session_description_t * session_description,belle_sdp_info_t * info)1410 void belle_sdp_session_description_set_info(belle_sdp_session_description_t* session_description, belle_sdp_info_t* info) {
1411 	SET_OBJECT(BELLE_SIP_CAST(session_description,belle_sdp_base_description_t),info,belle_sdp_info_t)
1412 }
1413 /*void belle_sdp_session_description_set_key(belle_sdp_session_description_t* session_description, belle_sdp_key_t* key);*/
belle_sdp_session_description_set_media_descriptions(belle_sdp_session_description_t * session_description,belle_sip_list_t * media_descriptions)1414 void belle_sdp_session_description_set_media_descriptions(belle_sdp_session_description_t* session_description, belle_sip_list_t* media_descriptions) {
1415 	SET_LIST(session_description->media_descriptions,media_descriptions)
1416 }
belle_sdp_session_description_add_media_description(belle_sdp_session_description_t * session_description,belle_sdp_media_description_t * media_description)1417 void belle_sdp_session_description_add_media_description(belle_sdp_session_description_t* session_description, belle_sdp_media_description_t* media_description) {
1418 	session_description->media_descriptions = belle_sip_list_append(session_description->media_descriptions,belle_sip_object_ref(media_description));
1419 }
1420 
belle_sdp_session_description_set_origin(belle_sdp_session_description_t * session_description,belle_sdp_origin_t * origin)1421 void belle_sdp_session_description_set_origin(belle_sdp_session_description_t* session_description, belle_sdp_origin_t* origin) {
1422 	SET_OBJECT(session_description,origin,belle_sdp_origin_t)
1423 }
belle_sdp_session_description_set_phones(belle_sdp_session_description_t * session_description,belle_sip_list_t * phones)1424 void belle_sdp_session_description_set_phones(belle_sdp_session_description_t* session_description, belle_sip_list_t* phones) {
1425 	SET_LIST(session_description->phones,phones)
1426 }
belle_sdp_session_description_set_session_name(belle_sdp_session_description_t * session_description,belle_sdp_session_name_t * session_name)1427 void belle_sdp_session_description_set_session_name(belle_sdp_session_description_t* session_description, belle_sdp_session_name_t* session_name) {
1428 	SET_OBJECT(session_description,session_name,belle_sdp_session_name_t)
1429 }
belle_sdp_session_description_set_time_descriptions(belle_sdp_session_description_t * session_description,belle_sip_list_t * times)1430 void belle_sdp_session_description_set_time_descriptions(belle_sdp_session_description_t* session_description, belle_sip_list_t* times) {
1431 	SET_LIST(session_description->times,times)
1432 }
belle_sdp_session_description_set_time_description(belle_sdp_session_description_t * session_description,belle_sdp_time_description_t * time_desc)1433 void belle_sdp_session_description_set_time_description(belle_sdp_session_description_t* session_description, belle_sdp_time_description_t* time_desc) {
1434 	belle_sdp_session_description_set_time_descriptions(session_description,belle_sip_list_new(time_desc));
1435 }
belle_sdp_session_description_set_uri(belle_sdp_session_description_t * session_description,belle_sdp_uri_t * uri)1436 void belle_sdp_session_description_set_uri(belle_sdp_session_description_t* session_description, belle_sdp_uri_t* uri) {
1437 	SET_OBJECT(session_description,uri,belle_sdp_uri_t)
1438 }
belle_sdp_session_description_set_version(belle_sdp_session_description_t * session_description,belle_sdp_version_t * version)1439 void belle_sdp_session_description_set_version(belle_sdp_session_description_t* session_description, belle_sdp_version_t* version) {
1440 	SET_OBJECT(session_description,version,belle_sdp_version_t)
1441 }
belle_sdp_session_description_set_zone_adjustments(belle_sdp_session_description_t * session_description,belle_sdp_uri_t * zone_adjustments)1442 void belle_sdp_session_description_set_zone_adjustments(belle_sdp_session_description_t* session_description, belle_sdp_uri_t* zone_adjustments) {
1443 	SET_OBJECT(session_description,zone_adjustments,belle_sdp_uri_t)
1444 }
1445 /************************
1446  * time
1447  ***********************/
1448 struct _belle_sdp_time {
1449 	belle_sip_object_t base;
1450 	int start;
1451 	int stop;
1452  };
1453 
belle_sdp_time_destroy(belle_sdp_time_t * time)1454 void belle_sdp_time_destroy(belle_sdp_time_t* time) {
1455 
1456 }
1457 
belle_sdp_time_clone(belle_sdp_time_t * time,const belle_sdp_time_t * orig)1458 void belle_sdp_time_clone(belle_sdp_time_t *time, const belle_sdp_time_t *orig){
1459 	time->start=orig->start;
1460 	time->stop=orig->stop;
1461 }
1462 
belle_sdp_time_marshal(belle_sdp_time_t * time,char * buff,size_t buff_size,size_t * offset)1463 belle_sip_error_code belle_sdp_time_marshal(belle_sdp_time_t* time, char* buff, size_t buff_size, size_t *offset) {
1464 	return belle_sip_snprintf(buff,buff_size,offset,"%i %i",time->start,time->stop);
1465 }
1466 
1467 BELLE_SDP_NEW(time,belle_sip_object)
1468 //BELLE_SDP_PARSE(version)
1469 GET_SET_INT(belle_sdp_time,start,int);
1470 GET_SET_INT(belle_sdp_time,stop,int);
1471 
1472 /************************
1473  * time description
1474  ***********************/
1475 struct _belle_sdp_time_description {
1476 	belle_sip_object_t base;
1477 	belle_sdp_time_t* time;
1478 
1479  };
1480 
belle_sdp_time_description_destroy(belle_sdp_time_description_t * time_description)1481 void belle_sdp_time_description_destroy(belle_sdp_time_description_t* time_description) {
1482 	if (time_description->time) belle_sip_object_unref(BELLE_SIP_OBJECT(time_description->time));
1483 }
1484 
belle_sdp_time_description_clone(belle_sdp_time_description_t * time_description,const belle_sdp_time_description_t * orig)1485 void belle_sdp_time_description_clone(belle_sdp_time_description_t *time_description, const belle_sdp_time_description_t *orig){
1486 	if (orig->time) time_description->time = BELLE_SDP_TIME(belle_sip_object_clone_and_ref(BELLE_SIP_OBJECT(orig->time)));
1487 }
1488 
belle_sdp_time_description_marshal(belle_sdp_time_description_t * time_description,char * buff,size_t buff_size,size_t * offset)1489 belle_sip_error_code belle_sdp_time_description_marshal(belle_sdp_time_description_t* time_description, char* buff, size_t buff_size, size_t *offset) {
1490 	return belle_sip_object_marshal(BELLE_SIP_OBJECT(time_description->time),buff,buff_size,offset);
1491 }
1492 
BELLE_SDP_NEW(time_description,belle_sip_object)1493 BELLE_SDP_NEW(time_description,belle_sip_object)
1494 
1495 belle_sdp_time_description_t* belle_sdp_time_description_create (int start,int stop) {
1496 	belle_sdp_time_description_t* time_desc= belle_sdp_time_description_new();
1497 	belle_sdp_time_t* time = belle_sdp_time_new();
1498 	belle_sdp_time_set_start(time,start);
1499 	belle_sdp_time_set_stop(time,stop);
1500 	belle_sdp_time_description_set_time(time_desc,time);
1501 	return time_desc;
1502 }
belle_sdp_time_description_get_repeate_times(const belle_sdp_time_description_t * time_description)1503 belle_sip_list_t* belle_sdp_time_description_get_repeate_times(const belle_sdp_time_description_t* time_description) {
1504 	return NULL;
1505 }
belle_sdp_time_description_get_time(const belle_sdp_time_description_t * time_description)1506 belle_sdp_time_t* belle_sdp_time_description_get_time(const belle_sdp_time_description_t* time_description) {
1507 	return time_description->time;
1508 }
belle_sdp_time_description_set_repeate_times(belle_sdp_time_description_t * time_description,belle_sip_list_t * times)1509 void belle_sdp_time_description_set_repeate_times(belle_sdp_time_description_t* time_description, belle_sip_list_t* times) {
1510 	belle_sip_error("time description repeat time not implemented");
1511 }
belle_sdp_time_description_set_time(belle_sdp_time_description_t * time_description,belle_sdp_time_t * time)1512 void belle_sdp_time_description_set_time(belle_sdp_time_description_t* time_description, belle_sdp_time_t* time) {
1513 	SET_OBJECT(time_description,time,belle_sdp_time_t)
1514 }
1515 
1516 /************************
1517  * version
1518  ***********************/
1519 struct _belle_sdp_version {
1520 	belle_sip_object_t base;
1521 	int version;
1522  };
1523 
belle_sdp_version_destroy(belle_sdp_version_t * version)1524 void belle_sdp_version_destroy(belle_sdp_version_t* version) {
1525 
1526 }
1527 
belle_sdp_version_clone(belle_sdp_version_t * version,const belle_sdp_version_t * orig)1528 void belle_sdp_version_clone(belle_sdp_version_t *version, const belle_sdp_version_t *orig){
1529 	version->version = orig->version;
1530 }
1531 
belle_sdp_version_marshal(belle_sdp_version_t * version,char * buff,size_t buff_size,size_t * offset)1532 belle_sip_error_code belle_sdp_version_marshal(belle_sdp_version_t* version, char* buff, size_t buff_size, size_t *offset) {
1533 	return belle_sip_snprintf(buff,buff_size,offset,"v=%i",version->version);
1534 }
1535 
BELLE_SDP_NEW(version,belle_sip_object)1536 BELLE_SDP_NEW(version,belle_sip_object)
1537 belle_sdp_version_t* belle_sdp_version_create(int version) {
1538 	belle_sdp_version_t* v = belle_sdp_version_new();
1539 	belle_sdp_version_set_version(v,version);
1540 	return v;
1541 }
1542 //BELLE_SDP_PARSE(version)
1543 GET_SET_INT(belle_sdp_version,version,int);
1544 
1545 /***************************************************************************************
1546  * mime_parameter
1547  *
1548  **************************************************************************************/
1549 
belle_sdp_mime_parameter_destroy(belle_sdp_mime_parameter_t * mime_parameter)1550 static void belle_sdp_mime_parameter_destroy(belle_sdp_mime_parameter_t *mime_parameter) {
1551 	if (mime_parameter->type) belle_sip_free((void*)mime_parameter->type);
1552 	if (mime_parameter->parameters) belle_sip_free((void*)mime_parameter->parameters);
1553 }
belle_sdp_mime_parameter_clone(belle_sdp_mime_parameter_t * mime_parameter,belle_sdp_mime_parameter_t * orig)1554 static void belle_sdp_mime_parameter_clone(belle_sdp_mime_parameter_t *mime_parameter,belle_sdp_mime_parameter_t *orig) {
1555 	mime_parameter->rate = orig->rate;
1556 	mime_parameter->channel_count = orig->channel_count;
1557 	mime_parameter->ptime = orig->ptime;
1558 	mime_parameter->max_ptime = orig->max_ptime;
1559 	mime_parameter->media_format = orig->media_format;
1560 	CLONE_STRING(belle_sdp_mime_parameter,type,mime_parameter,orig);
1561 	CLONE_STRING(belle_sdp_mime_parameter,parameters,mime_parameter,orig);
1562 }
1563 BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(belle_sdp_mime_parameter_t);
1564 BELLE_SIP_INSTANCIATE_VPTR(belle_sdp_mime_parameter_t
1565 							,belle_sip_object_t
1566 							,belle_sdp_mime_parameter_destroy
1567 							,belle_sdp_mime_parameter_clone
1568 							,NULL
1569 							,TRUE);
1570 
belle_sdp_mime_parameter_new()1571 belle_sdp_mime_parameter_t* belle_sdp_mime_parameter_new() {
1572 	belle_sdp_mime_parameter_t* l_param = belle_sip_object_new(belle_sdp_mime_parameter_t);
1573 	l_param->ptime = -1;
1574 	l_param->max_ptime = -1;
1575 	return l_param;
1576 }
belle_sdp_mime_parameter_create(const char * type,int media_format,int rate,int channel_count)1577 belle_sdp_mime_parameter_t* belle_sdp_mime_parameter_create(const char* type, int media_format, int rate,int channel_count) {
1578 	belle_sdp_mime_parameter_t* mime_param= belle_sdp_mime_parameter_new();
1579 	belle_sdp_mime_parameter_set_type(mime_param,type);
1580 	belle_sdp_mime_parameter_set_media_format(mime_param,media_format);
1581 	belle_sdp_mime_parameter_set_rate(mime_param,rate);
1582 	belle_sdp_mime_parameter_set_channel_count(mime_param,channel_count);
1583 	return mime_param;
1584 }
1585 GET_SET_INT(belle_sdp_mime_parameter,rate,int);
1586 GET_SET_INT(belle_sdp_mime_parameter,channel_count,int);
1587 GET_SET_INT(belle_sdp_mime_parameter,ptime,int);
1588 GET_SET_INT(belle_sdp_mime_parameter,max_ptime,int);
1589 GET_SET_INT(belle_sdp_mime_parameter,media_format,int);
1590 GET_SET_STRING(belle_sdp_mime_parameter,type);
1591 GET_SET_STRING(belle_sdp_mime_parameter,parameters);
1592 
1593