belle_sip_headers_impl.c 57.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));
}
jehan's avatar
jehan committed
40
void belle_sip_header_init(belle_sip_header_t *header) {
Simon Morlat's avatar
Simon Morlat committed
41

jehan's avatar
jehan committed
42
}
43
static void belle_sip_header_clone(belle_sip_header_t *header, const belle_sip_header_t *orig){
44
	CLONE_STRING(belle_sip_header,name,header,orig)
45
	if (belle_sip_header_get_next(orig)) {
46
		belle_sip_header_set_next(header,BELLE_SIP_HEADER(belle_sip_object_clone(BELLE_SIP_OBJECT(belle_sip_header_get_next(orig))))) ;
47 48
	}
}
Simon Morlat's avatar
Simon Morlat committed
49
static void belle_sip_header_destroy(belle_sip_header_t *header){
jehan's avatar
jehan committed
50
	if (header->name) belle_sip_free((void*)header->name);
jehan's avatar
jehan committed
51 52 53
	if (header->next) belle_sip_object_unref(BELLE_SIP_OBJECT(header->next));
}
void belle_sip_header_set_next(belle_sip_header_t* header,belle_sip_header_t* next) {
54 55
	if (next) belle_sip_object_ref(next);
	if(header->next) belle_sip_object_unref(header->next);
jehan's avatar
jehan committed
56 57 58 59
	header->next = next;
}
belle_sip_header_t* belle_sip_header_get_next(const belle_sip_header_t* header) {
	return header->next;
jehan's avatar
jehan committed
60
}
jehan's avatar
jehan committed
61

jehan's avatar
jehan committed
62 63
int belle_sip_header_marshal(belle_sip_header_t* header, char* buff,unsigned int offset,unsigned int buff_size) {
	if (header->name) {
64
		return snprintf(buff+offset,buff_size-offset,"%s: ",header->name);
jehan's avatar
jehan committed
65 66 67 68 69
	} else {
		belle_sip_warning("no header name found");
		return 0;
	}
}
70 71 72

BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(belle_sip_header_t);

Simon Morlat's avatar
Simon Morlat committed
73
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
74 75


jehan's avatar
jehan committed
76 77 78 79
/************************
 * header_address
 ***********************/
struct _belle_sip_header_address {
Simon Morlat's avatar
Simon Morlat committed
80
	belle_sip_parameters_t base;
Simon Morlat's avatar
Simon Morlat committed
81
	char* displayname;
jehan's avatar
jehan committed
82 83
	belle_sip_uri_t* uri;
};
Simon Morlat's avatar
Simon Morlat committed
84

jehan's avatar
jehan committed
85 86
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
87 88
}

jehan's avatar
jehan committed
89
static void belle_sip_header_address_destroy(belle_sip_header_address_t* address) {
Simon Morlat's avatar
Simon Morlat committed
90 91
	if (address->displayname) belle_sip_free(address->displayname);
	if (address->uri) belle_sip_object_unref(address->uri);
jehan's avatar
jehan committed
92 93
}

94
static void belle_sip_header_address_clone(belle_sip_header_address_t *addr, const belle_sip_header_address_t *orig){
95 96 97 98
	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
99
}
100

jehan's avatar
jehan committed
101 102 103 104
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) {
105 106
		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
107 108
	}
	if (header->uri) {
109 110 111 112 113
		/*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
114
			current_offset+=snprintf(buff+current_offset,buff_size-current_offset,"%s","<");
115
			if (current_offset>=buff_size) goto end;
jehan's avatar
jehan committed
116 117
		}
		current_offset+=belle_sip_uri_marshal(header->uri,buff,current_offset,buff_size);
Simon Morlat's avatar
Simon Morlat committed
118
		if (current_offset>=buff_size) goto end;
119 120 121 122
		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
123
			current_offset+=snprintf(buff+current_offset,buff_size-current_offset,"%s",">");
124
			if (current_offset>=buff_size) goto end;
jehan's avatar
jehan committed
125 126 127
		}
	}
	current_offset+=belle_sip_parameters_marshal(&header->base,buff,current_offset,buff_size);
128 129
	if (current_offset>=buff_size) goto end;
end:
130
	return MIN(current_offset-offset,buff_size-offset);
jehan's avatar
jehan committed
131
}
Simon Morlat's avatar
Simon Morlat committed
132

133
BELLE_SIP_NEW_HEADER(header_address,parameters,"header_address")
jehan's avatar
jehan committed
134
BELLE_SIP_PARSE(header_address)
jehan's avatar
jehan committed
135 136
GET_SET_STRING(belle_sip_header_address,displayname);

jehan's avatar
jehan committed
137
void belle_sip_header_address_set_quoted_displayname(belle_sip_header_address_t* address,const char* value) {
Simon Morlat's avatar
Simon Morlat committed
138
		if (address->displayname != NULL) belle_sip_free(address->displayname);
jehan's avatar
jehan committed
139 140 141 142
		if (strlen(value)>2)
			address->displayname=_belle_sip_str_dup_and_unquote_string(value);
		else
			address->displayname=NULL;
jehan's avatar
jehan committed
143
}
Simon Morlat's avatar
Simon Morlat committed
144

145
belle_sip_uri_t* belle_sip_header_address_get_uri(const belle_sip_header_address_t* address) {
jehan's avatar
jehan committed
146 147 148 149
	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
150 151 152 153 154
	belle_sip_object_ref(uri);
	if (address->uri){
		belle_sip_object_unref(address->uri);
	}
	address->uri=uri;
jehan's avatar
jehan committed
155 156
}

jehan's avatar
jehan committed
157 158 159 160 161 162
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
163

jehan's avatar
jehan committed
164
/******************************
165
 * Extension header inherits from header
jehan's avatar
jehan committed
166 167 168 169 170 171
 *
 ******************************/
struct _belle_sip_header_allow  {
	belle_sip_header_t header;
	const char* method;
};
172 173 174
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
175 176 177 178
static void belle_sip_header_allow_destroy(belle_sip_header_allow_t* allow) {
	if (allow->method) belle_sip_free((void*)allow->method);
}

179

jehan's avatar
jehan committed
180 181 182
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);
183
	if (current_offset>=buff_size) goto end;
jehan's avatar
jehan committed
184
	current_offset+=snprintf(buff+current_offset,buff_size-current_offset,"%s",allow->method);
185 186
	if (current_offset>=buff_size) goto end;
end:
187
	return MIN(current_offset-offset,buff_size-offset);
jehan's avatar
jehan committed
188 189 190 191

}
BELLE_SIP_NEW_HEADER(header_allow,header,"Allow")
BELLE_SIP_PARSE(header_allow)
jehan's avatar
jehan committed
192 193 194 195 196
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
197 198 199
GET_SET_STRING(belle_sip_header_allow,method);


jehan's avatar
jehan committed
200 201 202 203 204 205 206 207 208

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

jehan's avatar
jehan committed
209
void belle_sip_header_contact_destroy(belle_sip_header_contact_t* contact) {
Simon Morlat's avatar
Simon Morlat committed
210 211 212
}

void belle_sip_header_contact_clone(belle_sip_header_contact_t *contact, const belle_sip_header_contact_t *orig){
213
	contact->wildcard=orig->wildcard;
jehan's avatar
jehan committed
214
}
jehan's avatar
jehan committed
215 216 217 218 219 220 221 222
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);
	}
223 224
	if (current_offset>=buff_size) goto end;
end:
225
	return MIN(current_offset-offset,buff_size-offset);
jehan's avatar
jehan committed
226
}
jehan's avatar
jehan committed
227
BELLE_SIP_NEW_HEADER(header_contact,header_address,BELLE_SIP_CONTACT)
jehan's avatar
jehan committed
228
BELLE_SIP_PARSE(header_contact)
jehan's avatar
jehan committed
229 230
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
231 232
	_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
233 234
	return header;
}
jehan's avatar
jehan committed
235 236
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
237 238
GET_SET_BOOL(belle_sip_header_contact,wildcard,is);

jehan's avatar
jehan committed
239

jehan's avatar
jehan committed
240 241
int belle_sip_header_contact_set_expires(belle_sip_header_contact_t* contact, int expires) {
	if (expires < 0 ) {
242
		 belle_sip_error("bad expires value [%i] for contact",expires);
jehan's avatar
jehan committed
243 244 245 246 247 248
		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
249
	 if (qValue != -1 && qValue < 0 && qValue >1) {
250
		 belle_sip_error("bad q value [%f] for contact",qValue);
jehan's avatar
jehan committed
251 252
		 return -1;
	 }
jehan's avatar
jehan committed
253
	 _belle_sip_header_contact_set_q(contact,qValue);
jehan's avatar
jehan committed
254 255
	 return 0;
}
256
float	belle_sip_header_contact_get_qvalue(const belle_sip_header_contact_t* contact) {
jehan's avatar
jehan committed
257 258
	return belle_sip_header_contact_get_q(contact);
}
jehan's avatar
jehan committed
259 260
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;
261
	return belle_sip_uri_equals(belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(a))
jehan's avatar
jehan committed
262 263
								,belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(b)));
}
264 265 266
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
267
/**************************
jehan's avatar
jehan committed
268
* From header object inherent from header_address
jehan's avatar
jehan committed
269
****************************
jehan's avatar
jehan committed
270
*/
jehan's avatar
jehan committed
271 272 273
#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);\
274
		if (current_offset>=buff_size) goto end;\
jehan's avatar
jehan committed
275
		current_offset+=belle_sip_header_address_marshal(&header->address, buff,current_offset, buff_size); \
276 277
		if (current_offset>=buff_size) goto end;\
		end:\
278
		return MIN(current_offset-offset,buff_size-offset);
279

jehan's avatar
jehan committed
280 281 282 283
struct _belle_sip_header_from  {
	belle_sip_header_address_t address;
};

jehan's avatar
jehan committed
284 285 286
static void belle_sip_header_from_destroy(belle_sip_header_from_t* from) {
}

Simon Morlat's avatar
Simon Morlat committed
287 288
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
289

jehan's avatar
jehan committed
290 291 292
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
293

jehan's avatar
jehan committed
294
belle_sip_header_from_t* belle_sip_header_from_create2(const char *address, const char *tag){
295 296
	char *tmp=belle_sip_strdup_printf("From: %s",address);
	belle_sip_header_from_t *from=belle_sip_header_from_parse(tmp);
297
	if (from){
298
		if (tag) belle_sip_header_from_set_tag(from,tag);
299
	}
300 301 302
	belle_sip_free(tmp);
	return from;
}
jehan's avatar
jehan committed
303 304
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
305
	_belle_sip_object_copy((belle_sip_object_t*)header,(belle_sip_object_t*)address);
Simon Morlat's avatar
Simon Morlat committed
306
	belle_sip_header_set_name(BELLE_SIP_HEADER(header),BELLE_SIP_FROM); /*restore header name*/
307
	if (tag) belle_sip_header_from_set_tag(header,tag);
jehan's avatar
jehan committed
308 309
	return header;
}
jehan's avatar
jehan committed
310
BELLE_SIP_NEW_HEADER(header_from,header_address,BELLE_SIP_FROM)
jehan's avatar
jehan committed
311
BELLE_SIP_PARSE(header_from)
312
GET_SET_STRING_PARAM2(belle_sip_header_from,tag,raw_tag);
jehan's avatar
jehan committed
313

314
void belle_sip_header_from_set_random_tag(belle_sip_header_from_t *obj){
Simon Morlat's avatar
Simon Morlat committed
315
	char tmp[BELLE_SIP_TAG_LENGTH];
316 317 318 319 320 321 322 323 324 325
	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);
326 327
}

jehan's avatar
jehan committed
328
/**************************
Simon Morlat's avatar
Simon Morlat committed
329
* To header object inherits from header_address
jehan's avatar
jehan committed
330 331 332 333 334
****************************
*/
struct _belle_sip_header_to  {
	belle_sip_header_address_t address;
};
jehan's avatar
jehan committed
335

jehan's avatar
jehan committed
336
static void belle_sip_header_to_destroy(belle_sip_header_to_t* to) {
Simon Morlat's avatar
Simon Morlat committed
337 338 339
}

void belle_sip_header_to_clone(belle_sip_header_to_t *contact, const belle_sip_header_to_t *orig){
jehan's avatar
jehan committed
340
}
jehan's avatar
jehan committed
341 342 343
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
344

jehan's avatar
fix tag  
jehan committed
345
BELLE_SIP_NEW_HEADER(header_to,header_address,BELLE_SIP_TO)
jehan's avatar
jehan committed
346
BELLE_SIP_PARSE(header_to)
347
GET_SET_STRING_PARAM2(belle_sip_header_to,tag,raw_tag);
348

jehan's avatar
jehan committed
349
belle_sip_header_to_t* belle_sip_header_to_create2(const char *address, const char *tag){
350 351
	char *tmp=belle_sip_strdup_printf("To: %s",address);
	belle_sip_header_to_t *to=belle_sip_header_to_parse(tmp);
352
	if (to){
353
		if (tag) belle_sip_header_to_set_tag(to,tag);
354
	}
355 356 357
	belle_sip_free(tmp);
	return to;
}
jehan's avatar
jehan committed
358 359
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
360
	_belle_sip_object_copy((belle_sip_object_t*)header,(belle_sip_object_t*)address);
jehan's avatar
jehan committed
361
	belle_sip_header_set_name(BELLE_SIP_HEADER(header),BELLE_SIP_TO); /*restaure header name*/
jehan's avatar
fix tag  
jehan committed
362
	if (tag) belle_sip_header_to_set_tag(header,tag);
jehan's avatar
jehan committed
363 364
	return header;
}
365 366 367 368 369 370
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)));
}

371 372 373 374 375 376 377 378 379 380
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
381
/******************************
382
 * User-Agent header inherits from header
jehan's avatar
jehan committed
383 384 385 386 387 388 389 390 391 392 393 394
 *
 ******************************/
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){
395 396 397 398
	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
399 400 401 402 403 404 405 406
}
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
407
									,list==user_agent->products ? "%s" : " %s"
jehan's avatar
jehan committed
408
									,(const char *)list->data);
409
		if (current_offset>=buff_size) goto end;
jehan's avatar
jehan committed
410
	}
411
end:
412
	return MIN(current_offset-offset,buff_size-offset);
jehan's avatar
jehan committed
413 414

}
415
BELLE_SIP_NEW_HEADER(header_user_agent,header,"User-Agent")
jehan's avatar
jehan committed
416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433
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
434 435 436 437 438 439 440 441 442 443 444 445 446
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
447

jehan's avatar
jehan committed
448
/**************************
Simon Morlat's avatar
Simon Morlat committed
449
* Via header object inherits from parameters
jehan's avatar
jehan committed
450 451 452
****************************
*/
struct _belle_sip_header_via  {
453
	belle_sip_parameters_t params_list;
Simon Morlat's avatar
Simon Morlat committed
454 455 456
	char* protocol;
	char* transport;
	char* host;
457
	int port;
jehan's avatar
jehan committed
458
	char* received;
jehan's avatar
jehan committed
459 460
};

461
static void belle_sip_header_via_destroy(belle_sip_header_via_t* via) {
Simon Morlat's avatar
Simon Morlat committed
462
	if (via->protocol) belle_sip_free(via->protocol);
463 464
	if (via->transport) belle_sip_free(via->transport);
	if (via->host) belle_sip_free(via->host);
jehan's avatar
jehan committed
465
	DESTROY_STRING(via,received)
Simon Morlat's avatar
Simon Morlat committed
466 467 468
}

static void belle_sip_header_via_clone(belle_sip_header_via_t* via, const belle_sip_header_via_t*orig){
469 470 471
	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
472
	CLONE_STRING(belle_sip_header_via,received,via,orig)
473
	via->port=orig->port;
jehan's avatar
jehan committed
474
}
475

jehan's avatar
jehan committed
476 477 478
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);
479
	if (current_offset>=buff_size) goto end;
jehan's avatar
jehan committed
480
	current_offset+=snprintf(buff+current_offset,buff_size-current_offset,"%s/%s",via->protocol,via->transport);
481
	if (current_offset>=buff_size) goto end;
jehan's avatar
jehan committed
482 483 484 485 486 487 488

	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);
		}
489
		if (current_offset>=buff_size) goto end;
jehan's avatar
jehan committed
490 491 492 493
	} else {
		belle_sip_warning("no host found in this via");
	}

jehan's avatar
jehan committed
494 495
	if (via->port > 0) {
		current_offset+=snprintf(buff+current_offset,buff_size-current_offset,":%i",via->port);
496
		if (current_offset>=buff_size) goto end;
jehan's avatar
jehan committed
497
	}
jehan's avatar
jehan committed
498 499
	if (via->received) {
		current_offset+=snprintf(buff+current_offset,buff_size-current_offset,";received=%s",via->received);
500
		if (current_offset>=buff_size) goto end;
jehan's avatar
jehan committed
501 502
	}

jehan's avatar
jehan committed
503
	current_offset+=belle_sip_parameters_marshal(&via->params_list, buff,current_offset, buff_size);
504 505 506
	if (current_offset>=buff_size) goto end;
	
end:
507
	return MIN(current_offset-offset,buff_size-offset);
jehan's avatar
jehan committed
508
}
jehan's avatar
jehan committed
509

510 511 512 513 514 515 516 517 518 519
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
520
BELLE_SIP_NEW_HEADER(header_via,parameters,BELLE_SIP_VIA)
jehan's avatar
jehan committed
521
BELLE_SIP_PARSE(header_via)
522 523 524
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
525
GET_SET_STRING(belle_sip_header_via,received);
526 527 528 529
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
530

531 532 533

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
534

535
int belle_sip_header_via_set_rport (belle_sip_header_via_t* obj,int  value) {
jehan's avatar
jehan committed
536 537 538 539 540
	if (value == -1) {
		belle_sip_parameters_set_parameter(BELLE_SIP_PARAMETERS(obj),"rport",NULL);
		return 0;
	}
	if (value>0 && value<65536) {
541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556
		_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;
	}
}
557

558 559 560 561 562 563 564 565 566
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
567

568
int belle_sip_header_via_get_listening_port(const belle_sip_header_via_t *via){
Simon Morlat's avatar
Simon Morlat committed
569
	int ret=belle_sip_header_via_get_port(via);
570
	if (ret==0) ret=belle_sip_listening_point_get_well_known_port(via->transport);
Simon Morlat's avatar
Simon Morlat committed
571 572
	return ret;
}
573 574

const char* belle_sip_header_via_get_transport_lowercase(const belle_sip_header_via_t* via) {
575 576 577 578 579 580 581 582 583
	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;
	}
}
584
/**************************
Simon Morlat's avatar
Simon Morlat committed
585
* call_id header object inherits from object
586 587
****************************
*/
jehan's avatar
jehan committed
588
struct _belle_sip_header_call_id  {
jehan's avatar
jehan committed
589
	belle_sip_header_t header;
jehan's avatar
jehan committed
590
	const char* call_id;
591
};
jehan's avatar
jehan committed
592

jehan's avatar
jehan committed
593 594
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
595
}
jehan's avatar
jehan committed
596

Simon Morlat's avatar
Simon Morlat committed
597
static void belle_sip_header_call_id_clone(belle_sip_header_call_id_t* call_id,const belle_sip_header_call_id_t *orig){
598
	CLONE_STRING(belle_sip_header_call_id,call_id,call_id,orig);
599
}
jehan's avatar
jehan committed
600 601 602
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);
603
	if (current_offset>=buff_size) goto end;
jehan's avatar
jehan committed
604
	current_offset+=snprintf(buff+current_offset,buff_size-current_offset,"%s",call_id->call_id);
605 606
	if (current_offset>=buff_size) goto end;
end:
607
	return MIN(current_offset-offset,buff_size-offset);
jehan's avatar
jehan committed
608
}
609 610 611
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
612
BELLE_SIP_NEW_HEADER(header_call_id,header,BELLE_SIP_CALL_ID)
jehan's avatar
jehan committed
613 614
BELLE_SIP_PARSE(header_call_id)
GET_SET_STRING(belle_sip_header_call_id,call_id);
615 616 617 618 619
/**************************
* cseq header object inherent from object
****************************
*/
struct _belle_sip_header_cseq  {
jehan's avatar
jehan committed
620
	belle_sip_header_t header;
621
	char* method;
622 623
	unsigned int seq_number;
};
jehan's avatar
jehan committed
624

625
static void belle_sip_header_cseq_destroy(belle_sip_header_cseq_t* cseq) {
626
	if (cseq->method) belle_sip_free(cseq->method);
Simon Morlat's avatar
Simon Morlat committed
627
}
628

Simon Morlat's avatar
Simon Morlat committed
629
static void belle_sip_header_cseq_clone(belle_sip_header_cseq_t* cseq, const belle_sip_header_cseq_t *orig) {
630 631
	CLONE_STRING(belle_sip_header_cseq,method,cseq,orig)
	cseq->seq_number=orig->seq_number;
632
}
jehan's avatar
jehan committed
633 634 635
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);
636
	if (current_offset>=buff_size) goto end;
jehan's avatar
jehan committed
637
	current_offset+=snprintf(buff+current_offset,buff_size-current_offset,"%i %s",cseq->seq_number,cseq->method);
638 639
	if (current_offset>=buff_size) goto end;
end:
640
	return MIN(current_offset-offset,buff_size-offset);
jehan's avatar
jehan committed
641
}
642 643
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
644
	belle_sip_header_cseq_set_method(cseq,method);
645 646 647
	cseq->seq_number=number;
	return cseq;
}
648
BELLE_SIP_NEW_HEADER(header_cseq,header,BELLE_SIP_CSEQ)
649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665
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
666

Simon Morlat's avatar
Simon Morlat committed
667
static void belle_sip_header_content_type_clone(belle_sip_header_content_type_t* content_type, const belle_sip_header_content_type_t* orig){
668 669
	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
670
}
jehan's avatar
jehan committed
671 672 673
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);
674
	if (current_offset>=buff_size) goto end;
jehan's avatar
jehan committed
675
	current_offset+=snprintf(buff+current_offset,buff_size-current_offset,"%s/%s",content_type->type, content_type->subtype);
676
	if (current_offset>=buff_size) goto end;
jehan's avatar
jehan committed
677
	current_offset+=belle_sip_parameters_marshal(&content_type->params_list, buff,current_offset, buff_size);
678 679 680
	if (current_offset>=buff_size) goto end;
	
end:
681
	return MIN(current_offset-offset,buff_size-offset);
jehan's avatar
jehan committed
682
}
jehan's avatar
jehan committed
683
BELLE_SIP_NEW_HEADER(header_content_type,parameters,BELLE_SIP_CONTENT_TYPE)
684
BELLE_SIP_PARSE(header_content_type)
jehan's avatar
jehan committed
685 686 687 688 689 690
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;
}
691 692
GET_SET_STRING(belle_sip_header_content_type,type);
GET_SET_STRING(belle_sip_header_content_type,subtype);
jehan's avatar
jehan committed
693 694 695 696 697 698 699 700 701
/**************************
* 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
702 703 704
}

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
705
}
jehan's avatar
jehan committed
706 707 708
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
709
BELLE_SIP_NEW_HEADER(header_route,header_address,BELLE_SIP_ROUTE)
jehan's avatar
jehan committed
710
BELLE_SIP_PARSE(header_route)
jehan's avatar
jehan committed
711 712
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
713
	_belle_sip_object_copy((belle_sip_object_t*)header,(belle_sip_object_t*)route);
714
	belle_sip_header_set_name(BELLE_SIP_HEADER(header),BELLE_SIP_ROUTE); /*restore header name*/
jehan's avatar
jehan committed
715 716
	return header;
}
jehan's avatar
jehan committed
717 718 719 720 721 722 723 724 725
/**************************
* 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
726 727 728 729
}

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
730
}
jehan's avatar
jehan committed
731 732 733
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
734
BELLE_SIP_NEW_HEADER(header_record_route,header_address,BELLE_SIP_RECORD_ROUTE)
jehan's avatar
jehan committed
735
BELLE_SIP_PARSE(header_record_route)
jehan's avatar
jehan committed
736
/**************************
jehan's avatar
jehan committed
737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755
* 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
756 757 758 759
* content length header object inherent from object
****************************
*/
struct _belle_sip_header_content_length  {
jehan's avatar
jehan committed
760
	belle_sip_header_t header;
jehan's avatar
jehan committed
761 762 763 764
	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
765
}
jehan's avatar
jehan committed
766

Simon Morlat's avatar
Simon Morlat committed
767 768
static void belle_sip_header_content_length_clone(belle_sip_header_content_length_t* content_length,
                                                 const belle_sip_header_content_length_t *orig ) {
769
	content_length->content_length=orig->content_length;
jehan's avatar
jehan committed
770
}
Simon Morlat's avatar
Simon Morlat committed
771

jehan's avatar
jehan committed
772 773 774
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);
775
	if (current_offset>=buff_size) goto end;
jehan's avatar
jehan committed
776
	current_offset+=snprintf(buff+current_offset,buff_size-current_offset,"%i",content_length->content_length);
777 778
	if (current_offset>=buff_size) goto end;
end:
779
	return MIN(current_offset-offset,buff_size-offset);
jehan's avatar
jehan committed
780
}
jehan's avatar
jehan committed
781
BELLE_SIP_NEW_HEADER(header_content_length,header,BELLE_SIP_CONTENT_LENGTH)
jehan's avatar
jehan committed
782 783
BELLE_SIP_PARSE(header_content_length)
GET_SET_INT(belle_sip_header_content_length,content_length,unsigned int)
jehan's avatar
jehan committed
784 785 786 787 788 789
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
790 791 792 793 794 795 796 797 798 799 800 801 802 803
/**************************
* 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 ) {
804
	expires->expires=orig->expires;
jehan's avatar
jehan committed
805 806 807 808 809
}

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);
810
	if (current_offset>=buff_size) goto end;
jehan's avatar
jehan committed
811
	current_offset+=snprintf(buff+current_offset,buff_size-current_offset,"%i",expires->expires);
812 813
	if (current_offset>=buff_size) goto end;
end:
814
	return MIN(current_offset-offset,buff_size-offset);
jehan's avatar
jehan committed
815
}
816
BELLE_SIP_NEW_HEADER(header_expires,header,BELLE_SIP_EXPIRES)
jehan's avatar
jehan committed
817 818
BELLE_SIP_PARSE(header_expires)
GET_SET_INT(belle_sip_header_expires,expires,int)
jehan's avatar
jehan committed
819 820 821 822 823
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
824 825 826 827 828 829 830 831 832 833 834 835 836 837
/******************************
 * 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){
838
	CLONE_STRING(belle_sip_header_extension,value,extension,orig)
jehan's avatar
jehan committed
839
}
jehan's avatar
jehan committed
840 841 842
int belle_sip_header_extension_marshal(belle_sip_header_extension_t* extension, char* buff,unsigned int offset,unsigned int buff_size) {
	unsigned int current_offset=offset;
	current_offset+=belle_sip_header_marshal(BELLE_SIP_HEADER(extension), buff,current_offset, buff_size);
843
	if (current_offset>=buff_size) goto end;
jehan's avatar
jehan committed
844
	current_offset+=snprintf(buff+current_offset,buff_size-current_offset,"%s",extension->value);
845 846
	if (current_offset>=buff_size) goto end;
end:
847
	return MIN(current_offset-offset,buff_size-offset);
jehan's avatar
jehan committed
848

jehan's avatar
jehan committed
849
}
jehan's avatar
jehan committed
850 851
BELLE_SIP_NEW_HEADER(header_extension,header,NULL)

jehan's avatar
jehan committed
852 853 854