belle_sip_headers_impl.c 59.6 KB
Newer Older
jehan's avatar
jehan committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
/*
	belle-sip - SIP (RFC3261) library.
    Copyright (C) 2010  Belledonne Communications SARL

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/



#include "belle-sip/headers.h"
jehan's avatar
jehan committed
22
#include "belle-sip/parameters.h"
jehan's avatar
jehan committed
23 24 25 26 27 28
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include "belle_sip_messageParser.h"
#include "belle_sip_messageLexer.h"
#include "belle_sip_internal.h"
jehan's avatar
jehan committed
29
#include "listeningpoint_internal.h"
jehan's avatar
jehan committed
30

jehan's avatar
jehan committed
31 32 33
/************************
 * header
 ***********************/
jehan's avatar
jehan committed
34

jehan's avatar
jehan committed
35
GET_SET_STRING(belle_sip_header,name);
36

jehan's avatar
jehan committed
37 38 39
belle_sip_header_t* belle_sip_header_create (const char* name,const char* value) {
	return BELLE_SIP_HEADER(belle_sip_header_extension_create(name,value));
}
Simon Morlat's avatar
Simon Morlat committed
40

jehan's avatar
jehan committed
41
void belle_sip_header_init(belle_sip_header_t *header) {
Simon Morlat's avatar
Simon Morlat committed
42

jehan's avatar
jehan committed
43
}
Simon Morlat's avatar
Simon Morlat committed
44

45
static void belle_sip_header_clone(belle_sip_header_t *header, const belle_sip_header_t *orig){
46
	CLONE_STRING(belle_sip_header,name,header,orig)
47
	if (belle_sip_header_get_next(orig)) {
48
		belle_sip_header_set_next(header,BELLE_SIP_HEADER(belle_sip_object_clone(BELLE_SIP_OBJECT(belle_sip_header_get_next(orig))))) ;
49 50
	}
}
Simon Morlat's avatar
Simon Morlat committed
51

Simon Morlat's avatar
Simon Morlat committed
52
static void belle_sip_header_destroy(belle_sip_header_t *header){
Simon Morlat's avatar
Simon Morlat committed
53 54
	if (header->name) belle_sip_free(header->name);
	if (header->unparsed_value) belle_sip_free(header->unparsed_value);
jehan's avatar
jehan committed
55 56
	if (header->next) belle_sip_object_unref(BELLE_SIP_OBJECT(header->next));
}
Simon Morlat's avatar
Simon Morlat committed
57

jehan's avatar
jehan committed
58
void belle_sip_header_set_next(belle_sip_header_t* header,belle_sip_header_t* next) {
59 60
	if (next) belle_sip_object_ref(next);
	if(header->next) belle_sip_object_unref(header->next);
jehan's avatar
jehan committed
61 62
	header->next = next;
}
Simon Morlat's avatar
Simon Morlat committed
63

jehan's avatar
jehan committed
64 65
belle_sip_header_t* belle_sip_header_get_next(const belle_sip_header_t* header) {
	return header->next;
jehan's avatar
jehan committed
66
}
jehan's avatar
jehan committed
67

Simon Morlat's avatar
Simon Morlat committed
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84
const char *belle_sip_header_get_unparsed_value(belle_sip_header_t* obj){
	char *tmp=belle_sip_object_to_string(obj);
	char *ret;
	char *end;
	if (obj->unparsed_value){
		belle_sip_free(obj->unparsed_value);
		obj->unparsed_value=NULL;
	}
	obj->unparsed_value=tmp;
	ret=tmp;
	ret+=strlen(obj->name)+1; /* name + semicolon*/
	for(;*ret==' ';ret++){};/*skip spaces*/
	end=strchr(ret,'\r');
	if (end) *end='\0'; /*remove \r\n*/
	return ret;
}

jehan's avatar
jehan committed
85 86
int belle_sip_header_marshal(belle_sip_header_t* header, char* buff,unsigned int offset,unsigned int buff_size) {
	if (header->name) {
87
		return snprintf(buff+offset,buff_size-offset,"%s: ",header->name);
jehan's avatar
jehan committed
88 89 90 91 92
	} else {
		belle_sip_warning("no header name found");
		return 0;
	}
}
93 94 95

BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(belle_sip_header_t);

Simon Morlat's avatar
Simon Morlat committed
96
BELLE_SIP_INSTANCIATE_VPTR(belle_sip_header_t,belle_sip_object_t,belle_sip_header_destroy,belle_sip_header_clone,belle_sip_header_marshal,TRUE);
Simon Morlat's avatar
Simon Morlat committed
97 98


jehan's avatar
jehan committed
99 100 101 102
/************************
 * header_address
 ***********************/
struct _belle_sip_header_address {
Simon Morlat's avatar
Simon Morlat committed
103
	belle_sip_parameters_t base;
Simon Morlat's avatar
Simon Morlat committed
104
	char* displayname;
jehan's avatar
jehan committed
105 106
	belle_sip_uri_t* uri;
};
Simon Morlat's avatar
Simon Morlat committed
107

jehan's avatar
jehan committed
108 109
static void belle_sip_header_address_init(belle_sip_header_address_t* object){
	belle_sip_parameters_init((belle_sip_parameters_t*)object); /*super*/
jehan's avatar
jehan committed
110 111
}

jehan's avatar
jehan committed
112
static void belle_sip_header_address_destroy(belle_sip_header_address_t* address) {
Simon Morlat's avatar
Simon Morlat committed
113 114
	if (address->displayname) belle_sip_free(address->displayname);
	if (address->uri) belle_sip_object_unref(address->uri);
jehan's avatar
jehan committed
115 116
}

117
static void belle_sip_header_address_clone(belle_sip_header_address_t *addr, const belle_sip_header_address_t *orig){
118 119 120 121
	CLONE_STRING(belle_sip_header_address,displayname,addr,orig)
	if (belle_sip_header_address_get_uri(orig)) {
		belle_sip_header_address_set_uri(addr,BELLE_SIP_URI(belle_sip_object_clone(BELLE_SIP_OBJECT(belle_sip_header_address_get_uri(orig)))));
	}
Simon Morlat's avatar
Simon Morlat committed
122
}
123

jehan's avatar
jehan committed
124 125 126 127
int belle_sip_header_address_marshal(belle_sip_header_address_t* header, char* buff,unsigned int offset,unsigned int buff_size) {
	/*1 display name*/
	unsigned int current_offset=offset;
	if (header->displayname) {
128 129
		current_offset+=snprintf(buff+current_offset,buff_size-current_offset,"\"%s\" ",header->displayname);
		if (current_offset>=buff_size) goto end;
jehan's avatar
jehan committed
130 131
	}
	if (header->uri) {
132 133 134 135 136
		/*cases where < is required*/
		if (header->displayname
			|| belle_sip_parameters_get_parameter_names((belle_sip_parameters_t*)header->uri)
			|| belle_sip_uri_get_header_names(header->uri)
			|| belle_sip_parameters_get_parameter_names(&header->base)) {
jehan's avatar
jehan committed
137
			current_offset+=snprintf(buff+current_offset,buff_size-current_offset,"%s","<");
138
			if (current_offset>=buff_size) goto end;
jehan's avatar
jehan committed
139 140
		}
		current_offset+=belle_sip_uri_marshal(header->uri,buff,current_offset,buff_size);
Simon Morlat's avatar
Simon Morlat committed
141
		if (current_offset>=buff_size) goto end;
142 143 144 145
		if (header->displayname
				|| belle_sip_parameters_get_parameter_names((belle_sip_parameters_t*)header->uri)
				|| belle_sip_uri_get_header_names(header->uri)
				|| belle_sip_parameters_get_parameter_names(&header->base)) {
jehan's avatar
jehan committed
146
			current_offset+=snprintf(buff+current_offset,buff_size-current_offset,"%s",">");
147
			if (current_offset>=buff_size) goto end;
jehan's avatar
jehan committed
148 149 150
		}
	}
	current_offset+=belle_sip_parameters_marshal(&header->base,buff,current_offset,buff_size);
151 152
	if (current_offset>=buff_size) goto end;
end:
153
	return MIN(current_offset-offset,buff_size-offset);
jehan's avatar
jehan committed
154
}
Simon Morlat's avatar
Simon Morlat committed
155

156
BELLE_SIP_NEW_HEADER(header_address,parameters,"header_address")
jehan's avatar
jehan committed
157
BELLE_SIP_PARSE(header_address)
jehan's avatar
jehan committed
158 159
GET_SET_STRING(belle_sip_header_address,displayname);

jehan's avatar
jehan committed
160
void belle_sip_header_address_set_quoted_displayname(belle_sip_header_address_t* address,const char* value) {
Simon Morlat's avatar
Simon Morlat committed
161
		if (address->displayname != NULL) belle_sip_free(address->displayname);
jehan's avatar
jehan committed
162 163 164 165
		if (strlen(value)>2)
			address->displayname=_belle_sip_str_dup_and_unquote_string(value);
		else
			address->displayname=NULL;
jehan's avatar
jehan committed
166
}
Simon Morlat's avatar
Simon Morlat committed
167

168
belle_sip_uri_t* belle_sip_header_address_get_uri(const belle_sip_header_address_t* address) {
jehan's avatar
jehan committed
169 170 171 172
	return address->uri;
}

void belle_sip_header_address_set_uri(belle_sip_header_address_t* address, belle_sip_uri_t* uri) {
Simon Morlat's avatar
Simon Morlat committed
173 174 175 176 177
	belle_sip_object_ref(uri);
	if (address->uri){
		belle_sip_object_unref(address->uri);
	}
	address->uri=uri;
jehan's avatar
jehan committed
178 179
}

jehan's avatar
jehan committed
180 181 182 183 184 185
belle_sip_header_address_t* belle_sip_header_address_create(const char* display, belle_sip_uri_t* uri) {
	belle_sip_header_address_t* address = belle_sip_header_address_new();
	belle_sip_header_address_set_displayname(address,display);
	belle_sip_header_address_set_uri(address,uri);
	return address;
}
jehan's avatar
jehan committed
186

jehan's avatar
jehan committed
187
/******************************
188
 * Extension header inherits from header
jehan's avatar
jehan committed
189 190 191 192 193 194
 *
 ******************************/
struct _belle_sip_header_allow  {
	belle_sip_header_t header;
	const char* method;
};
195 196 197
static void belle_sip_header_allow_clone(belle_sip_header_allow_t *allow, const belle_sip_header_allow_t *orig){
	CLONE_STRING(belle_sip_header_allow,method,allow,orig)
}
jehan's avatar
jehan committed
198 199 200 201
static void belle_sip_header_allow_destroy(belle_sip_header_allow_t* allow) {
	if (allow->method) belle_sip_free((void*)allow->method);
}

202

jehan's avatar
jehan committed
203 204 205
int belle_sip_header_allow_marshal(belle_sip_header_allow_t* allow, char* buff,unsigned int offset,unsigned int buff_size) {
	unsigned int current_offset=offset;
	current_offset+=belle_sip_header_marshal(BELLE_SIP_HEADER(allow), buff,current_offset, buff_size);
206
	if (current_offset>=buff_size) goto end;
jehan's avatar
jehan committed
207
	current_offset+=snprintf(buff+current_offset,buff_size-current_offset,"%s",allow->method);
208 209
	if (current_offset>=buff_size) goto end;
end:
210
	return MIN(current_offset-offset,buff_size-offset);
jehan's avatar
jehan committed
211 212 213 214

}
BELLE_SIP_NEW_HEADER(header_allow,header,"Allow")
BELLE_SIP_PARSE(header_allow)
jehan's avatar
jehan committed
215 216 217 218 219
belle_sip_header_allow_t* belle_sip_header_allow_create (const char* methods) {
	belle_sip_header_allow_t* allow = belle_sip_header_allow_new();
	belle_sip_header_allow_set_method(allow,methods);
	return allow;
}
jehan's avatar
jehan committed
220 221 222
GET_SET_STRING(belle_sip_header_allow,method);


jehan's avatar
jehan committed
223 224 225 226 227 228 229 230 231

/************************
 * header_contact
 ***********************/
struct _belle_sip_header_contact {
	belle_sip_header_address_t address;
	unsigned int wildcard;
 };

jehan's avatar
jehan committed
232
void belle_sip_header_contact_destroy(belle_sip_header_contact_t* contact) {
Simon Morlat's avatar
Simon Morlat committed
233 234 235
}

void belle_sip_header_contact_clone(belle_sip_header_contact_t *contact, const belle_sip_header_contact_t *orig){
236
	contact->wildcard=orig->wildcard;
jehan's avatar
jehan committed
237
}
jehan's avatar
jehan committed
238 239 240 241 242 243 244 245
int belle_sip_header_contact_marshal(belle_sip_header_contact_t* contact, char* buff,unsigned int offset,unsigned int buff_size) {
	unsigned int current_offset=offset;
	current_offset+=belle_sip_header_marshal(BELLE_SIP_HEADER(contact), buff,offset, buff_size);
	if (contact->wildcard) {
		current_offset+=snprintf(buff+current_offset,buff_size-current_offset,"%s","*");
	} else {
		current_offset+=belle_sip_header_address_marshal(&contact->address, buff,current_offset, buff_size);
	}
246 247
	if (current_offset>=buff_size) goto end;
end:
248
	return MIN(current_offset-offset,buff_size-offset);
jehan's avatar
jehan committed
249
}
jehan's avatar
jehan committed
250
BELLE_SIP_NEW_HEADER(header_contact,header_address,BELLE_SIP_CONTACT)
jehan's avatar
jehan committed
251
BELLE_SIP_PARSE(header_contact)
jehan's avatar
jehan committed
252 253
belle_sip_header_contact_t* belle_sip_header_contact_create (const belle_sip_header_address_t* contact) {
	belle_sip_header_contact_t* header = belle_sip_header_contact_new();
jehan's avatar
jehan committed
254 255
	_belle_sip_object_copy(BELLE_SIP_OBJECT(header),BELLE_SIP_OBJECT(contact));
	belle_sip_header_set_name(BELLE_SIP_HEADER(header),BELLE_SIP_CONTACT); /*restaure header name*/
jehan's avatar
jehan committed
256 257
	return header;
}
jehan's avatar
jehan committed
258 259
GET_SET_INT_PARAM_PRIVATE(belle_sip_header_contact,expires,int,_)
GET_SET_INT_PARAM_PRIVATE(belle_sip_header_contact,q,float,_);
jehan's avatar
jehan committed
260 261
GET_SET_BOOL(belle_sip_header_contact,wildcard,is);

jehan's avatar
jehan committed
262

jehan's avatar
jehan committed
263 264
int belle_sip_header_contact_set_expires(belle_sip_header_contact_t* contact, int expires) {
	if (expires < 0 ) {
265
		 belle_sip_error("bad expires value [%i] for contact",expires);
jehan's avatar
jehan committed
266 267 268 269 270 271
		return -1;
	}
	_belle_sip_header_contact_set_expires(contact,expires);
	return 0;
 }
int belle_sip_header_contact_set_qvalue(belle_sip_header_contact_t* contact, float qValue) {
jehan's avatar
jehan committed
272
	 if (qValue != -1 && qValue < 0 && qValue >1) {
273
		 belle_sip_error("bad q value [%f] for contact",qValue);
jehan's avatar
jehan committed
274 275
		 return -1;
	 }
jehan's avatar
jehan committed
276
	 _belle_sip_header_contact_set_q(contact,qValue);
jehan's avatar
jehan committed
277 278
	 return 0;
}
279
float	belle_sip_header_contact_get_qvalue(const belle_sip_header_contact_t* contact) {
jehan's avatar
jehan committed
280 281
	return belle_sip_header_contact_get_q(contact);
}
jehan's avatar
jehan committed
282 283
unsigned int belle_sip_header_contact_equals(const belle_sip_header_contact_t* a,const belle_sip_header_contact_t* b) {
	if (!a | !b) return 0;
284
	return belle_sip_uri_equals(belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(a))
jehan's avatar
jehan committed
285 286
								,belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(b)));
}
287 288 289
unsigned int belle_sip_header_contact_not_equals(const belle_sip_header_contact_t* a,const belle_sip_header_contact_t* b) {
	return !belle_sip_header_contact_equals(a,b);
}
jehan's avatar
jehan committed
290
/**************************
jehan's avatar
jehan committed
291
* From header object inherent from header_address
jehan's avatar
jehan committed
292
****************************
jehan's avatar
jehan committed
293
*/
jehan's avatar
jehan committed
294 295 296
#define BELLE_SIP_FROM_LIKE_MARSHAL(header) \
		unsigned int current_offset=offset; \
		current_offset+=belle_sip_##header_marshal(BELLE_SIP_HEADER(header), buff,current_offset, buff_size);\
297
		if (current_offset>=buff_size) goto end;\
jehan's avatar
jehan committed
298
		current_offset+=belle_sip_header_address_marshal(&header->address, buff,current_offset, buff_size); \
299 300
		if (current_offset>=buff_size) goto end;\
		end:\
301
		return MIN(current_offset-offset,buff_size-offset);
302

jehan's avatar
jehan committed
303 304 305 306
struct _belle_sip_header_from  {
	belle_sip_header_address_t address;
};

jehan's avatar
jehan committed
307 308 309
static void belle_sip_header_from_destroy(belle_sip_header_from_t* from) {
}

Simon Morlat's avatar
Simon Morlat committed
310 311
static void belle_sip_header_from_clone(belle_sip_header_from_t* from, const belle_sip_header_from_t* cloned) {
}
Simon Morlat's avatar
Simon Morlat committed
312

jehan's avatar
jehan committed
313 314 315
int belle_sip_header_from_marshal(belle_sip_header_from_t* from, char* buff,unsigned int offset,unsigned int buff_size) {
	BELLE_SIP_FROM_LIKE_MARSHAL(from);
}
Simon Morlat's avatar
Simon Morlat committed
316

jehan's avatar
jehan committed
317
belle_sip_header_from_t* belle_sip_header_from_create2(const char *address, const char *tag){
318 319
	char *tmp=belle_sip_strdup_printf("From: %s",address);
	belle_sip_header_from_t *from=belle_sip_header_from_parse(tmp);
320
	if (from){
321
		if (tag) belle_sip_header_from_set_tag(from,tag);
322
	}
323 324 325
	belle_sip_free(tmp);
	return from;
}
jehan's avatar
jehan committed
326 327
belle_sip_header_from_t* belle_sip_header_from_create(const belle_sip_header_address_t* address, const char *tag) {
	belle_sip_header_from_t* header= belle_sip_header_from_new();
Simon Morlat's avatar
Simon Morlat committed
328
	_belle_sip_object_copy((belle_sip_object_t*)header,(belle_sip_object_t*)address);
Simon Morlat's avatar
Simon Morlat committed
329
	belle_sip_header_set_name(BELLE_SIP_HEADER(header),BELLE_SIP_FROM); /*restore header name*/
330
	if (tag) belle_sip_header_from_set_tag(header,tag);
jehan's avatar
jehan committed
331 332
	return header;
}
jehan's avatar
jehan committed
333
BELLE_SIP_NEW_HEADER(header_from,header_address,BELLE_SIP_FROM)
jehan's avatar
jehan committed
334
BELLE_SIP_PARSE(header_from)
335
GET_SET_STRING_PARAM2(belle_sip_header_from,tag,raw_tag);
jehan's avatar
jehan committed
336

337
void belle_sip_header_from_set_random_tag(belle_sip_header_from_t *obj){
Simon Morlat's avatar
Simon Morlat committed
338
	char tmp[BELLE_SIP_TAG_LENGTH];
339 340 341 342 343 344 345 346 347 348
	belle_sip_header_from_set_raw_tag(obj,belle_sip_random_token(tmp,sizeof(tmp)));
}

void belle_sip_header_from_set_tag(belle_sip_header_from_t *obj, const char *tag){
	if (tag==BELLE_SIP_RANDOM_TAG) belle_sip_header_from_set_random_tag(obj);
	else belle_sip_header_from_set_raw_tag(obj,tag);
}

const char *belle_sip_header_from_get_tag(const belle_sip_header_from_t *obj){
	return belle_sip_header_from_get_raw_tag(obj);
349 350
}

jehan's avatar
jehan committed
351
/**************************
Simon Morlat's avatar
Simon Morlat committed
352
* To header object inherits from header_address
jehan's avatar
jehan committed
353 354 355 356 357
****************************
*/
struct _belle_sip_header_to  {
	belle_sip_header_address_t address;
};
jehan's avatar
jehan committed
358

jehan's avatar
jehan committed
359
static void belle_sip_header_to_destroy(belle_sip_header_to_t* to) {
Simon Morlat's avatar
Simon Morlat committed
360 361 362
}

void belle_sip_header_to_clone(belle_sip_header_to_t *contact, const belle_sip_header_to_t *orig){
jehan's avatar
jehan committed
363
}
jehan's avatar
jehan committed
364 365 366
int belle_sip_header_to_marshal(belle_sip_header_to_t* to, char* buff,unsigned int offset,unsigned int buff_size) {
	BELLE_SIP_FROM_LIKE_MARSHAL(to)
}
jehan's avatar
jehan committed
367

jehan's avatar
fix tag  
jehan committed
368
BELLE_SIP_NEW_HEADER(header_to,header_address,BELLE_SIP_TO)
jehan's avatar
jehan committed
369
BELLE_SIP_PARSE(header_to)
370
GET_SET_STRING_PARAM2(belle_sip_header_to,tag,raw_tag);
371

jehan's avatar
jehan committed
372
belle_sip_header_to_t* belle_sip_header_to_create2(const char *address, const char *tag){
373 374
	char *tmp=belle_sip_strdup_printf("To: %s",address);
	belle_sip_header_to_t *to=belle_sip_header_to_parse(tmp);
375
	if (to){
376
		if (tag) belle_sip_header_to_set_tag(to,tag);
377
	}
378 379 380
	belle_sip_free(tmp);
	return to;
}
jehan's avatar
jehan committed
381 382
belle_sip_header_to_t* belle_sip_header_to_create(const belle_sip_header_address_t* address, const char *tag) {
	belle_sip_header_to_t* header= belle_sip_header_to_new();
Simon Morlat's avatar
Simon Morlat committed
383
	_belle_sip_object_copy((belle_sip_object_t*)header,(belle_sip_object_t*)address);
jehan's avatar
jehan committed
384
	belle_sip_header_set_name(BELLE_SIP_HEADER(header),BELLE_SIP_TO); /*restaure header name*/
jehan's avatar
fix tag  
jehan committed
385
	if (tag) belle_sip_header_to_set_tag(header,tag);
jehan's avatar
jehan committed
386 387
	return header;
}
388 389 390 391 392 393
void belle_sip_header_to_set_random_tag(belle_sip_header_to_t *obj){
	char tmp[8];
	/*not less than 32bit */
	belle_sip_header_to_set_tag(obj,belle_sip_random_token(tmp,sizeof(tmp)));
}

394 395 396 397 398 399 400 401 402 403
void belle_sip_header_to_set_tag(belle_sip_header_to_t *obj, const char *tag){
	if (tag==BELLE_SIP_RANDOM_TAG) belle_sip_header_to_set_random_tag(obj);
	else belle_sip_header_to_set_raw_tag(obj,tag);
}

const char *belle_sip_header_to_get_tag(const belle_sip_header_to_t *obj){
	return belle_sip_header_to_get_raw_tag(obj);
}


jehan's avatar
jehan committed
404
/******************************
405
 * User-Agent header inherits from header
jehan's avatar
jehan committed
406 407 408 409 410 411 412 413 414 415 416 417
 *
 ******************************/
struct _belle_sip_header_user_agent  {
	belle_sip_header_t header;
	belle_sip_list_t* products;
};

static void belle_sip_header_user_agent_destroy(belle_sip_header_user_agent_t* user_agent) {
	belle_sip_header_user_agent_set_products(user_agent,NULL);
}

static void belle_sip_header_user_agent_clone(belle_sip_header_user_agent_t* user_agent, const belle_sip_header_user_agent_t* orig){
418 419 420 421
	belle_sip_list_t* list=orig->products;
	for(;list!=NULL;list=list->next){
		belle_sip_header_user_agent_add_product(user_agent,(const char *)list->data);
	}
jehan's avatar
jehan committed
422 423 424 425 426 427 428 429
}
int belle_sip_header_user_agent_marshal(belle_sip_header_user_agent_t* user_agent, char* buff,unsigned int offset,unsigned int buff_size) {
	unsigned int current_offset=offset;
	belle_sip_list_t* list = user_agent->products;
	current_offset+=belle_sip_header_marshal(BELLE_SIP_HEADER(user_agent), buff,current_offset, buff_size);
	for(;list!=NULL;list=list->next){
		current_offset+=snprintf(	buff+current_offset
									,buff_size-current_offset
Simon Morlat's avatar
Simon Morlat committed
430
									,list==user_agent->products ? "%s" : " %s"
jehan's avatar
jehan committed
431
									,(const char *)list->data);
432
		if (current_offset>=buff_size) goto end;
jehan's avatar
jehan committed
433
	}
434
end:
435
	return MIN(current_offset-offset,buff_size-offset);
jehan's avatar
jehan committed
436 437

}
438
BELLE_SIP_NEW_HEADER(header_user_agent,header,"User-Agent")
jehan's avatar
jehan committed
439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456
BELLE_SIP_PARSE(header_user_agent)
belle_sip_list_t* belle_sip_header_user_agent_get_products(const belle_sip_header_user_agent_t* user_agent) {
	return user_agent->products;
}
void belle_sip_header_user_agent_set_products(belle_sip_header_user_agent_t* user_agent,belle_sip_list_t* products) {
	belle_sip_list_t* list;
	if (user_agent->products) {
		for (list=user_agent->products;list !=NULL; list=list->next) {
			belle_sip_free((void*)list->data);

		}
		belle_sip_list_free(user_agent->products);
	}
	user_agent->products=products;
}
void belle_sip_header_user_agent_add_product(belle_sip_header_user_agent_t* user_agent,const char* product) {
	user_agent->products = belle_sip_list_append(user_agent->products ,belle_sip_strdup(product));
}
jehan's avatar
jehan committed
457 458 459 460 461 462 463 464 465 466 467 468 469
int belle_sip_header_user_agent_get_products_as_string(const belle_sip_header_user_agent_t* user_agent,char* value,unsigned int value_size) {
	int result = 0;
	belle_sip_list_t* list = user_agent->products;
	for(;list!=NULL;list=list->next){
		result+=snprintf(value+result
						,value_size-result
						,"%s "
						,(const char *)list->data);
	}
	if (result>0) value[result]='\0'; /*remove last space */

	return result-1;
}
jehan's avatar
jehan committed
470

jehan's avatar
jehan committed
471
/**************************
Simon Morlat's avatar
Simon Morlat committed
472
* Via header object inherits from parameters
jehan's avatar
jehan committed
473 474 475
****************************
*/
struct _belle_sip_header_via  {
476
	belle_sip_parameters_t params_list;
Simon Morlat's avatar
Simon Morlat committed
477 478 479
	char* protocol;
	char* transport;
	char* host;
480
	int port;
jehan's avatar
jehan committed
481
	char* received;
jehan's avatar
jehan committed
482 483
};

484
static void belle_sip_header_via_destroy(belle_sip_header_via_t* via) {
Simon Morlat's avatar
Simon Morlat committed
485
	if (via->protocol) belle_sip_free(via->protocol);
486 487
	if (via->transport) belle_sip_free(via->transport);
	if (via->host) belle_sip_free(via->host);
jehan's avatar
jehan committed
488
	DESTROY_STRING(via,received)
Simon Morlat's avatar
Simon Morlat committed
489 490 491
}

static void belle_sip_header_via_clone(belle_sip_header_via_t* via, const belle_sip_header_via_t*orig){
492 493 494
	CLONE_STRING(belle_sip_header_via,protocol,via,orig)
	CLONE_STRING(belle_sip_header_via,transport,via,orig)
	CLONE_STRING(belle_sip_header_via,host,via,orig)
jehan's avatar
jehan committed
495
	CLONE_STRING(belle_sip_header_via,received,via,orig)
496
	via->port=orig->port;
jehan's avatar
jehan committed
497
}
498

jehan's avatar
jehan committed
499 500 501
int belle_sip_header_via_marshal(belle_sip_header_via_t* via, char* buff,unsigned int offset,unsigned int buff_size) {
	unsigned int current_offset=offset;
	current_offset+=belle_sip_header_marshal(BELLE_SIP_HEADER(via), buff,current_offset, buff_size);
502
	if (current_offset>=buff_size) goto end;
jehan's avatar
jehan committed
503
	current_offset+=snprintf(buff+current_offset,buff_size-current_offset,"%s/%s",via->protocol,via->transport);
504
	if (current_offset>=buff_size) goto end;
jehan's avatar
jehan committed
505 506 507 508 509 510 511

	if (via->host) {
		if (strchr(via->host,':')) { /*ipv6*/
			current_offset+=snprintf(buff+current_offset,buff_size-current_offset," [%s]",via->host);
		} else {
			current_offset+=snprintf(buff+current_offset,buff_size-current_offset," %s",via->host);
		}
512
		if (current_offset>=buff_size) goto end;
jehan's avatar
jehan committed
513 514 515 516
	} else {
		belle_sip_warning("no host found in this via");
	}

jehan's avatar
jehan committed
517 518
	if (via->port > 0) {
		current_offset+=snprintf(buff+current_offset,buff_size-current_offset,":%i",via->port);
519
		if (current_offset>=buff_size) goto end;
jehan's avatar
jehan committed
520
	}
jehan's avatar
jehan committed
521 522
	if (via->received) {
		current_offset+=snprintf(buff+current_offset,buff_size-current_offset,";received=%s",via->received);
523
		if (current_offset>=buff_size) goto end;
jehan's avatar
jehan committed
524 525
	}

jehan's avatar
jehan committed
526
	current_offset+=belle_sip_parameters_marshal(&via->params_list, buff,current_offset, buff_size);
527 528 529
	if (current_offset>=buff_size) goto end;
	
end:
530
	return MIN(current_offset-offset,buff_size-offset);
jehan's avatar
jehan committed
531
}
jehan's avatar
jehan committed
532

533 534 535 536 537 538 539 540 541 542
belle_sip_header_via_t* belle_sip_header_via_create(const char *host, int port, const char *transport, const char *branch){
	belle_sip_header_via_t *via=belle_sip_header_via_new();
	via->host=belle_sip_strdup(host);
	via->port=port;
	via->transport=belle_sip_strdup(transport);
	via->protocol=belle_sip_strdup("SIP/2.0");
	belle_sip_header_via_set_branch(via,branch);
	return via;
}

jehan's avatar
jehan committed
543
BELLE_SIP_NEW_HEADER(header_via,parameters,BELLE_SIP_VIA)
jehan's avatar
jehan committed
544
BELLE_SIP_PARSE(header_via)
545 546 547
GET_SET_STRING(belle_sip_header_via,protocol);
GET_SET_STRING(belle_sip_header_via,transport);
GET_SET_STRING(belle_sip_header_via,host);
jehan's avatar
jehan committed
548
GET_SET_STRING(belle_sip_header_via,received);
549 550 551 552
GET_SET_INT_PRIVATE(belle_sip_header_via,port,int,_);

GET_SET_STRING_PARAM(belle_sip_header_via,branch);
GET_SET_STRING_PARAM(belle_sip_header_via,maddr);
jehan's avatar
jehan committed
553

554 555 556

GET_SET_INT_PARAM_PRIVATE(belle_sip_header_via,rport,int,_)
GET_SET_INT_PARAM_PRIVATE(belle_sip_header_via,ttl,int,_)
Simon Morlat's avatar
Simon Morlat committed
557

558
int belle_sip_header_via_set_rport (belle_sip_header_via_t* obj,int  value) {
jehan's avatar
jehan committed
559 560 561 562 563
	if (value == -1) {
		belle_sip_parameters_set_parameter(BELLE_SIP_PARAMETERS(obj),"rport",NULL);
		return 0;
	}
	if (value>0 && value<65536) {
564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579
		_belle_sip_header_via_set_rport(obj,value);
		return 0;
	} else {
		belle_sip_error("bad rport value [%i] for via",value);
		return -1;
	}
}
int belle_sip_header_via_set_ttl (belle_sip_header_via_t* obj,int  value) {
	if (value ==-1 || (value>0 && value<=255)) {
		_belle_sip_header_via_set_ttl(obj,value);
		return 0;
	} else {
		belle_sip_error("bad ttl value [%i] for via",value);
		return -1;
	}
}
580

581 582 583 584 585 586 587 588 589
int belle_sip_header_via_set_port (belle_sip_header_via_t* obj,int  value) {
	if (value ==-1 || (value>0 && value<65536)) {
		_belle_sip_header_via_set_port(obj,value);
		return 0;
	} else {
		belle_sip_error("bad port value [%i] for via",value);
		return -1;
	}
}
Simon Morlat's avatar
Simon Morlat committed
590

591
int belle_sip_header_via_get_listening_port(const belle_sip_header_via_t *via){
Simon Morlat's avatar
Simon Morlat committed
592
	int ret=belle_sip_header_via_get_port(via);
593
	if (ret==0) ret=belle_sip_listening_point_get_well_known_port(via->transport);
Simon Morlat's avatar
Simon Morlat committed
594 595
	return ret;
}
596 597

const char* belle_sip_header_via_get_transport_lowercase(const belle_sip_header_via_t* via) {
598 599 600 601 602 603 604 605 606
	if (strcasecmp("udp",via->transport)==0) return "udp";
	else if (strcasecmp("tcp",via->transport)==0) return "tcp";
	else if (strcasecmp("tls",via->transport)==0) return "tls";
	else if (strcasecmp("dtls",via->transport)==0) return "dtls";
	else {
		belle_sip_warning("Cannot convert [%s] to lower case",via->transport);
		return via->transport;
	}
}
607
/**************************
Simon Morlat's avatar
Simon Morlat committed
608
* call_id header object inherits from object
609 610
****************************
*/
jehan's avatar
jehan committed
611
struct _belle_sip_header_call_id  {
jehan's avatar
jehan committed
612
	belle_sip_header_t header;
jehan's avatar
jehan committed
613
	const char* call_id;
614
};
jehan's avatar
jehan committed
615

jehan's avatar
jehan committed
616 617
static void belle_sip_header_call_id_destroy(belle_sip_header_call_id_t* call_id) {
	if (call_id->call_id) belle_sip_free((void*)call_id->call_id);
Simon Morlat's avatar
Simon Morlat committed
618
}
jehan's avatar
jehan committed
619

Simon Morlat's avatar
Simon Morlat committed
620
static void belle_sip_header_call_id_clone(belle_sip_header_call_id_t* call_id,const belle_sip_header_call_id_t *orig){
621
	CLONE_STRING(belle_sip_header_call_id,call_id,call_id,orig);
622
}
jehan's avatar
jehan committed
623 624 625
int belle_sip_header_call_id_marshal(belle_sip_header_call_id_t* call_id, char* buff,unsigned int offset,unsigned int buff_size) {
	unsigned int current_offset=offset;
	current_offset+=belle_sip_header_marshal(BELLE_SIP_HEADER(call_id), buff,current_offset, buff_size);
626
	if (current_offset>=buff_size) goto end;
jehan's avatar
jehan committed
627
	current_offset+=snprintf(buff+current_offset,buff_size-current_offset,"%s",call_id->call_id);
628 629
	if (current_offset>=buff_size) goto end;
end:
630
	return MIN(current_offset-offset,buff_size-offset);
jehan's avatar
jehan committed
631
}
632 633 634
unsigned int belle_sip_header_call_id_equals(const belle_sip_header_call_id_t* a,const belle_sip_header_call_id_t* b) {
	return strcasecmp(a->call_id,b->call_id) == 0;
}
jehan's avatar
fix tag  
jehan committed
635
BELLE_SIP_NEW_HEADER(header_call_id,header,BELLE_SIP_CALL_ID)
jehan's avatar
jehan committed
636 637
BELLE_SIP_PARSE(header_call_id)
GET_SET_STRING(belle_sip_header_call_id,call_id);
638 639 640 641 642
/**************************
* cseq header object inherent from object
****************************
*/
struct _belle_sip_header_cseq  {
jehan's avatar
jehan committed
643
	belle_sip_header_t header;
644
	char* method;
645 646
	unsigned int seq_number;
};
jehan's avatar
jehan committed
647

648
static void belle_sip_header_cseq_destroy(belle_sip_header_cseq_t* cseq) {
649
	if (cseq->method) belle_sip_free(cseq->method);
Simon Morlat's avatar
Simon Morlat committed
650
}
651

Simon Morlat's avatar
Simon Morlat committed
652
static void belle_sip_header_cseq_clone(belle_sip_header_cseq_t* cseq, const belle_sip_header_cseq_t *orig) {
653 654
	CLONE_STRING(belle_sip_header_cseq,method,cseq,orig)
	cseq->seq_number=orig->seq_number;
655
}
jehan's avatar
jehan committed
656 657 658
int belle_sip_header_cseq_marshal(belle_sip_header_cseq_t* cseq, char* buff,unsigned int offset,unsigned int buff_size) {
	unsigned int current_offset=offset;
	current_offset+=belle_sip_header_marshal(BELLE_SIP_HEADER(cseq), buff,current_offset, buff_size);
659
	if (current_offset>=buff_size) goto end;
jehan's avatar
jehan committed
660
	current_offset+=snprintf(buff+current_offset,buff_size-current_offset,"%i %s",cseq->seq_number,cseq->method);
661 662
	if (current_offset>=buff_size) goto end;
end:
663
	return MIN(current_offset-offset,buff_size-offset);
jehan's avatar
jehan committed
664
}
665 666
belle_sip_header_cseq_t * belle_sip_header_cseq_create(unsigned int number, const char *method){
	belle_sip_header_cseq_t *cseq=belle_sip_header_cseq_new();
jehan's avatar
jehan committed
667
	belle_sip_header_cseq_set_method(cseq,method);
668 669 670
	cseq->seq_number=number;
	return cseq;
}
671
BELLE_SIP_NEW_HEADER(header_cseq,header,BELLE_SIP_CSEQ)
672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688
BELLE_SIP_PARSE(header_cseq)
GET_SET_STRING(belle_sip_header_cseq,method);
GET_SET_INT(belle_sip_header_cseq,seq_number,unsigned int)
/**************************
* content type header object inherent from parameters
****************************
*/
struct _belle_sip_header_content_type  {
	belle_sip_parameters_t params_list;
	const char* type;
	const char* subtype;
};

static void belle_sip_header_content_type_destroy(belle_sip_header_content_type_t* content_type) {
	if (content_type->type) belle_sip_free((void*)content_type->type);
	if (content_type->subtype) belle_sip_free((void*)content_type->subtype);
}
jehan's avatar
jehan committed
689

Simon Morlat's avatar
Simon Morlat committed
690
static void belle_sip_header_content_type_clone(belle_sip_header_content_type_t* content_type, const belle_sip_header_content_type_t* orig){
691 692
	CLONE_STRING(belle_sip_header_content_type,type,content_type,orig);
	CLONE_STRING(belle_sip_header_content_type,subtype,content_type,orig);
Simon Morlat's avatar
Simon Morlat committed
693
}
jehan's avatar
jehan committed
694 695 696
int belle_sip_header_content_type_marshal(belle_sip_header_content_type_t* content_type, char* buff,unsigned int offset,unsigned int buff_size) {
	unsigned int current_offset=offset;
	current_offset+=belle_sip_header_marshal(BELLE_SIP_HEADER(content_type), buff,current_offset, buff_size);
697
	if (current_offset>=buff_size) goto end;
jehan's avatar
jehan committed
698
	current_offset+=snprintf(buff+current_offset,buff_size-current_offset,"%s/%s",content_type->type, content_type->subtype);
699
	if (current_offset>=buff_size) goto end;
jehan's avatar
jehan committed
700
	current_offset+=belle_sip_parameters_marshal(&content_type->params_list, buff,current_offset, buff_size);
701 702 703
	if (current_offset>=buff_size) goto end;
	
end:
704
	return MIN(current_offset-offset,buff_size-offset);
jehan's avatar
jehan committed
705
}
jehan's avatar
jehan committed
706
BELLE_SIP_NEW_HEADER(header_content_type,parameters,BELLE_SIP_CONTENT_TYPE)
707
BELLE_SIP_PARSE(header_content_type)
jehan's avatar
jehan committed
708 709 710 711 712 713
belle_sip_header_content_type_t* belle_sip_header_content_type_create (const char* type,const char* sub_type) {
	belle_sip_header_content_type_t* header = belle_sip_header_content_type_new();
	belle_sip_header_content_type_set_type(header,type);
	belle_sip_header_content_type_set_subtype(header,sub_type);
	return header;
}
714 715
GET_SET_STRING(belle_sip_header_content_type,type);
GET_SET_STRING(belle_sip_header_content_type,subtype);
jehan's avatar
jehan committed
716 717 718 719 720 721 722 723 724
/**************************
* Route header object inherent from header_address
****************************
*/
struct _belle_sip_header_route  {
	belle_sip_header_address_t address;
};

static void belle_sip_header_route_destroy(belle_sip_header_route_t* route) {
Simon Morlat's avatar
Simon Morlat committed
725 726 727
}

static void belle_sip_header_route_clone(belle_sip_header_route_t* route, const belle_sip_header_route_t* orig) {
jehan's avatar
jehan committed
728
}
jehan's avatar
jehan committed
729 730 731
int belle_sip_header_route_marshal(belle_sip_header_route_t* route, char* buff,unsigned int offset,unsigned int buff_size) {
	BELLE_SIP_FROM_LIKE_MARSHAL(route)
}
jehan's avatar
jehan committed
732
BELLE_SIP_NEW_HEADER(header_route,header_address,BELLE_SIP_ROUTE)
jehan's avatar
jehan committed
733
BELLE_SIP_PARSE(header_route)
jehan's avatar
jehan committed
734 735
belle_sip_header_route_t* belle_sip_header_route_create(const belle_sip_header_address_t* route) {
	belle_sip_header_route_t* header= belle_sip_header_route_new();
jehan's avatar
jehan committed
736
	_belle_sip_object_copy((belle_sip_object_t*)header,(belle_sip_object_t*)route);
737
	belle_sip_header_set_name(BELLE_SIP_HEADER(header),BELLE_SIP_ROUTE); /*restore header name*/
jehan's avatar
jehan committed
738 739
	return header;
}
jehan's avatar
jehan committed
740 741 742 743 744 745 746 747 748
/**************************
* Record route header object inherent from header_address
****************************
*/
struct _belle_sip_header_record_route  {
	belle_sip_header_address_t address;
};

static void belle_sip_header_record_route_destroy(belle_sip_header_record_route_t* record_route) {
Simon Morlat's avatar
Simon Morlat committed
749 750 751 752
}

static void belle_sip_header_record_route_clone(belle_sip_header_record_route_t* record_route,
                                const belle_sip_header_record_route_t* orig               ) {
jehan's avatar
jehan committed
753
}
jehan's avatar
jehan committed
754 755 756
int belle_sip_header_record_route_marshal(belle_sip_header_record_route_t* record_route, char* buff,unsigned int offset,unsigned int buff_size) {
	BELLE_SIP_FROM_LIKE_MARSHAL(record_route)
}
jehan's avatar
jehan committed
757
BELLE_SIP_NEW_HEADER(header_record_route,header_address,BELLE_SIP_RECORD_ROUTE)
jehan's avatar
jehan committed
758
BELLE_SIP_PARSE(header_record_route)
jehan's avatar
jehan committed
759
/**************************
jehan's avatar
jehan committed
760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778
* Service route header object inherent from header_address
****************************
*/
struct _belle_sip_header_service_route  {
	belle_sip_header_address_t address;
};

static void belle_sip_header_service_route_destroy(belle_sip_header_service_route_t* service_route) {
}

static void belle_sip_header_service_route_clone(belle_sip_header_service_route_t* service_route,
                                const belle_sip_header_service_route_t* orig               ) {
}
int belle_sip_header_service_route_marshal(belle_sip_header_service_route_t* service_route, char* buff,unsigned int offset,unsigned int buff_size) {
	BELLE_SIP_FROM_LIKE_MARSHAL(service_route)
}
BELLE_SIP_NEW_HEADER(header_service_route,header_address,BELLE_SIP_SERVICE_ROUTE)
BELLE_SIP_PARSE(header_service_route)
/**************************
jehan's avatar
jehan committed
779 780 781 782
* content length header object inherent from object
****************************
*/
struct _belle_sip_header_content_length  {
jehan's avatar
jehan committed
783
	belle_sip_header_t header;
jehan's avatar
jehan committed
784 785 786 787
	unsigned int content_length;
};

static void belle_sip_header_content_length_destroy(belle_sip_header_content_length_t* content_length) {
Simon Morlat's avatar
Simon Morlat committed
788
}
jehan's avatar
jehan committed
789

Simon Morlat's avatar
Simon Morlat committed
790 791
static void belle_sip_header_content_length_clone(belle_sip_header_content_length_t* content_length,
                                                 const belle_sip_header_content_length_t *orig ) {
792
	content_length->content_length=orig->content_length;
jehan's avatar
jehan committed
793
}
Simon Morlat's avatar
Simon Morlat committed
794

jehan's avatar
jehan committed
795 796 797
int belle_sip_header_content_length_marshal(belle_sip_header_content_length_t* content_length, char* buff,unsigned int offset,unsigned int buff_size) {
	unsigned int current_offset=offset;
	current_offset+=belle_sip_header_marshal(BELLE_SIP_HEADER(content_length), buff,current_offset, buff_size);
798
	if (current_offset>=buff_size) goto end;
jehan's avatar
jehan committed
799
	current_offset+=snprintf(buff+current_offset,buff_size-current_offset,"%i",content_length->content_length);
800 801
	if (current_offset>=buff_size) goto end;
end:
802
	return MIN(current_offset-offset,buff_size-offset);
jehan's avatar
jehan committed
803
}
jehan's avatar
jehan committed
804
BELLE_SIP_NEW_HEADER(header_content_length,header,BELLE_SIP_CONTENT_LENGTH)
jehan's avatar
jehan committed
805 806
BELLE_SIP_PARSE(header_content_length)
GET_SET_INT(belle_sip_header_content_length,content_length,unsigned int)
jehan's avatar
jehan committed
807 808 809 810 811 812
belle_sip_header_content_length_t* belle_sip_header_content_length_create (int content_length)  {
	belle_sip_header_content_length_t* obj;
	obj = belle_sip_header_content_length_new();
	belle_sip_header_content_length_set_content_length(obj,content_length);
	return obj;
}
jehan's avatar
jehan committed
813 814 815 816 817 818 819 820 821 822 823 824 825 826
/**************************
* Expires header object inherent from header
****************************
*/
struct _belle_sip_header_expires  {
	belle_sip_header_t header;
	int expires;
};

static void belle_sip_header_expires_destroy(belle_sip_header_expires_t* expires) {
}

static void belle_sip_header_expires_clone(belle_sip_header_expires_t* expires,
                                                 const belle_sip_header_expires_t *orig ) {
827
	expires->expires=orig->expires;
jehan's avatar
jehan committed
828 829 830 831 832
}

int belle_sip_header_expires_marshal(belle_sip_header_expires_t* expires, char* buff,unsigned int offset,unsigned int buff_size) {
	unsigned int current_offset=offset;
	current_offset+=belle_sip_header_marshal(BELLE_SIP_HEADER(expires), buff,current_offset, buff_size);
833
	if (current_offset>=buff_size) goto end;
jehan's avatar
jehan committed
834
	current_offset+=snprintf(buff+current_offset,buff_size-current_offset,"%i",expires->expires);
835 836
	if (current_offset>=buff_size) goto end;
end:
837
	return MIN(current_offset-offset,buff_size-offset);
jehan's avatar
jehan committed
838
}
839
BELLE_SIP_NEW_HEADER(header_expires,header,BELLE_SIP_EXPIRES)
jehan's avatar
jehan committed
840 841
BELLE_SIP_PARSE(header_expires)
GET_SET_INT(belle_sip_header_expires,expires,int)
jehan's avatar
jehan committed
842 843 844 845 846
belle_sip_header_expires_t* belle_sip_header_expires_create(int expires) {
	belle_sip_header_expires_t* obj = belle_sip_header_expires_new();
	belle_sip_header_expires_set_expires(obj,expires);
	return obj;
}
jehan's avatar
jehan committed
847 848 849 850 851 852 853 854 855 856 857 858 859 860
/******************************
 * Extension header hinerite from header
 *
 ******************************/
struct _belle_sip_header_extension  {
	belle_sip_header_t header;
	const char* value;
};

static void belle_sip_header_extension_destroy(belle_sip_header_extension_t* extension) {
	if (extension->value) belle_sip_free((void*)extension->value);
}

static void belle_sip_header_extension_clone(belle_sip_header_extension_t* extension, const belle_sip_header_extension_t* orig){
861
	CLONE_STRING(belle_sip_header_extension,value,extension,orig)