message.c 15.9 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
/*
	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/>.
*/
jehan's avatar
jehan committed
18 19
#include "belle_sip_messageParser.h"
#include "belle_sip_messageLexer.h"
20
#include "belle_sip_internal.h"
Simon Morlat's avatar
Simon Morlat committed
21 22


23
typedef struct _headers_container {
Simon Morlat's avatar
Simon Morlat committed
24
	char* name;
jehan's avatar
jehan committed
25
	belle_sip_list_t* header_list;
26 27 28 29 30
} headers_container_t;

static headers_container_t* belle_sip_message_headers_container_new(const char* name) {
	headers_container_t* headers_container = belle_sip_new0(headers_container_t);
	headers_container->name= belle_sip_strdup(name);
jehan's avatar
jehan committed
31
	return  headers_container;
jehan's avatar
jehan committed
32
}
33

Simon Morlat's avatar
Simon Morlat committed
34 35 36 37 38
static void belle_sip_headers_container_delete(headers_container_t *obj){
	belle_sip_free(obj->name);
	belle_sip_free(obj);
}

jehan's avatar
jehan committed
39 40 41
struct _belle_sip_message {
	belle_sip_object_t base;
	belle_sip_list_t* header_list;
jehan's avatar
jehan committed
42 43
	char* body;
	unsigned int body_length;
jehan's avatar
jehan committed
44 45
};

Simon Morlat's avatar
Simon Morlat committed
46 47 48 49 50
static void belle_sip_message_destroy(belle_sip_message_t *msg){
	belle_sip_list_for_each (msg->header_list,(void (*)(void*))belle_sip_headers_container_delete);
	belle_sip_list_free(msg->header_list);
}

51 52
BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(belle_sip_message_t);

Simon Morlat's avatar
Simon Morlat committed
53
BELLE_SIP_INSTANCIATE_VPTR(belle_sip_message_t,belle_sip_object_t,belle_sip_message_destroy,NULL,NULL,FALSE);
Simon Morlat's avatar
Simon Morlat committed
54

jehan's avatar
jehan committed
55 56 57 58
belle_sip_message_t* belle_sip_message_parse (const char* value) {
	size_t message_length;
	return belle_sip_message_parse_raw(value,strlen(value),&message_length);
}
jehan's avatar
jehan committed
59

60 61 62 63 64 65 66 67 68 69 70 71 72
belle_sip_message_t* belle_sip_message_parse_raw (const char* buff, size_t buff_length,size_t* message_length ) { \
	pANTLR3_INPUT_STREAM           input;
	pbelle_sip_messageLexer               lex;
	pANTLR3_COMMON_TOKEN_STREAM    tokens;
	pbelle_sip_messageParser              parser;
	input  = antlr3NewAsciiStringCopyStream	(
			(pANTLR3_UINT8)buff,
			(ANTLR3_UINT32)buff_length,
			((void *)0));
	lex    = belle_sip_messageLexerNew                (input);
	tokens = antlr3CommonTokenStreamSourceNew  (1025, lex->pLexer->rec->state->tokSource);
	parser = belle_sip_messageParserNew               (tokens);
	belle_sip_message_t* l_parsed_object = parser->message_raw(parser,message_length);
jehan's avatar
jehan committed
73 74 75 76 77 78 79
	if (*message_length < buff_length) {
		/*there is a body*/
		l_parsed_object->body_length=buff_length-*message_length;
		l_parsed_object->body = belle_sip_malloc(l_parsed_object->body_length+1);
		memcpy(l_parsed_object->body,buff+*message_length,l_parsed_object->body_length);
		l_parsed_object->body[l_parsed_object->body_length]='\0';
	}
80 81 82 83 84 85 86
	parser ->free(parser);
	tokens ->free(tokens);
	lex    ->free(lex);
	input  ->close(input);
	return l_parsed_object;
}

87
static int belle_sip_headers_container_comp_func(const headers_container_t *a, const char*b) {
Simon Morlat's avatar
Simon Morlat committed
88
	return strcasecmp(a->name,b);
89
}
Simon Morlat's avatar
Simon Morlat committed
90

jehan's avatar
jehan committed
91
static void belle_sip_message_init(belle_sip_message_t *message){
Simon Morlat's avatar
Simon Morlat committed
92
	
jehan's avatar
jehan committed
93 94
}

95 96 97 98 99 100
headers_container_t* belle_sip_headers_container_get(belle_sip_message_t* message,const char* header_name) {
	belle_sip_list_t *  result = belle_sip_list_find_custom(	message->header_list
															, (belle_sip_compare_func)belle_sip_headers_container_comp_func
															, header_name);
	return result?(headers_container_t*)(result->data):NULL;
}
Simon Morlat's avatar
Simon Morlat committed
101 102

headers_container_t * get_or_create_container(belle_sip_message_t *message, const char *header_name){
jehan's avatar
jehan committed
103
	// first check if already exist
Simon Morlat's avatar
Simon Morlat committed
104
	headers_container_t* headers_container = belle_sip_headers_container_get(message,header_name);
jehan's avatar
jehan committed
105
	if (headers_container == NULL) {
Simon Morlat's avatar
Simon Morlat committed
106
		headers_container = belle_sip_message_headers_container_new(header_name);
jehan's avatar
jehan committed
107
		message->header_list=belle_sip_list_append(message->header_list,headers_container);
jehan's avatar
jehan committed
108
	}
Simon Morlat's avatar
Simon Morlat committed
109 110
	return headers_container;
}
jehan's avatar
jehan committed
111

Simon Morlat's avatar
Simon Morlat committed
112 113
void belle_sip_message_add_header(belle_sip_message_t *message,belle_sip_header_t* header) {
	headers_container_t *headers_container=get_or_create_container(message,belle_sip_header_get_name(header));
jehan's avatar
jehan committed
114
	headers_container->header_list=belle_sip_list_append(headers_container->header_list,belle_sip_object_ref(header));
jehan's avatar
jehan committed
115
}
Simon Morlat's avatar
Simon Morlat committed
116 117 118 119 120 121 122 123 124 125

void belle_sip_message_add_headers(belle_sip_message_t *message, const belle_sip_list_t *header_list){
	const char *hname=belle_sip_header_get_name(BELLE_SIP_HEADER((header_list->data)));
	headers_container_t *headers_container=get_or_create_container(message,hname);
	for(;header_list!=NULL;header_list=header_list->next){
		belle_sip_header_t *h=BELLE_SIP_HEADER(header_list->data);
		if (strcmp(belle_sip_header_get_name(h),hname)!=0){
			belle_sip_fatal("Bad use of belle_sip_message_add_headers(): all headers of the list must be of the same type.");
			return ;
		}
jehan's avatar
jehan committed
126
		headers_container->header_list=belle_sip_list_append(headers_container->header_list,belle_sip_object_ref(h));
Simon Morlat's avatar
Simon Morlat committed
127 128 129
	}
}

jehan's avatar
jehan committed
130 131 132 133
const belle_sip_list_t* belle_sip_message_get_headers(belle_sip_message_t *message,const char* header_name) {
	headers_container_t* headers_container = belle_sip_headers_container_get(message,header_name);
	return headers_container ? headers_container->header_list:NULL;
}
Simon Morlat's avatar
Simon Morlat committed
134

jehan's avatar
jehan committed
135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175
/*
int belle_sip_message_named_headers_marshal(belle_sip_message_t *message, const char* header_name, char* buff,unsigned int offset,unsigned int buff_size) {
	unsigned int current_offset=offset;
	belle_sip_list_t* header_list = belle_sip_message_get_headers(message,header_name);
	if (!header_list) {
		belle_sip_error("headers [%s] not found",header_name);
		return 0;
	}
	for(;header_list!=NULL;header_list=header_list->next){
		belle_sip_header_t *h=BELLE_SIP_HEADER(header_list->data);
		current_offset+=belle_sip_object_marshal(BELLE_SIP_OBJECT(h),buff,current_offset,buff_size);
		current_offset+=snprintf(buff+current_offset,buff_size-current_offset,"%s","\r\n");
	}
	return current_offset-offset;
}

#define MARSHAL_AND_CHECK_HEADER(header) \
		if (current_offset == (current_offset+=(header))) {\
			belle_sip_error("missing mandatory header");\
			return current_offset;\
		} else {\
		current_offset+=snprintf(buff+current_offset,buff_size-current_offset,"%s","\r\n");\
		}
*/
int belle_sip_headers_marshal(belle_sip_message_t *message, char* buff,unsigned int offset,unsigned int buff_size) {
	unsigned int current_offset=offset;
	belle_sip_list_t* headers_list;
	belle_sip_list_t* header_list;
	for(headers_list=message->header_list;headers_list!=NULL;headers_list=headers_list->next){
		for(header_list=((headers_container_t*)(headers_list->data))->header_list
				;header_list!=NULL
				;header_list=header_list->next)	{
			belle_sip_header_t *h=BELLE_SIP_HEADER(header_list->data);
			current_offset+=belle_sip_object_marshal(BELLE_SIP_OBJECT(h),buff,current_offset,buff_size);
			current_offset+=snprintf(buff+current_offset,buff_size-current_offset,"%s","\r\n");
		}
	}
	current_offset+=snprintf(buff+current_offset,buff_size-current_offset,"%s","\r\n");
	return current_offset-offset;
}

jehan's avatar
jehan committed
176 177
struct _belle_sip_request {
	belle_sip_message_t message;
jehan's avatar
jehan committed
178
	const char* method;
jehan's avatar
jehan committed
179
	belle_sip_uri_t* uri;
jehan's avatar
jehan committed
180 181 182
};

static void belle_sip_request_destroy(belle_sip_request_t* request) {
jehan's avatar
jehan committed
183
	if (request->method) belle_sip_free((void*)(request->method));
jehan's avatar
jehan committed
184
}
Simon Morlat's avatar
Simon Morlat committed
185 186 187 188

static void belle_sip_request_clone(belle_sip_request_t *request, const belle_sip_request_t *orig){
		if (orig->method) request->method=belle_sip_strdup(orig->method);
}
jehan's avatar
jehan committed
189
int belle_sip_request_marshal(belle_sip_request_t* request, char* buff,unsigned int offset,unsigned int buff_size) {
jehan's avatar
jehan committed
190 191 192 193 194
	unsigned int current_offset=offset;
	current_offset+=snprintf(buff+current_offset,buff_size-current_offset,"%s ",belle_sip_request_get_method(request));
	current_offset+=belle_sip_uri_marshal(belle_sip_request_get_uri(request),buff,current_offset,buff_size);
	current_offset+=snprintf(buff+current_offset,buff_size-current_offset," %s","SIP/2.0\r\n");
	current_offset+=belle_sip_headers_marshal(BELLE_SIP_MESSAGE(request),buff,current_offset,buff_size);
jehan's avatar
jehan committed
195 196 197
	if (BELLE_SIP_MESSAGE(request)->body) {
		current_offset+=snprintf(buff+current_offset,buff_size-current_offset, "%s",BELLE_SIP_MESSAGE(request)->body);
	}
jehan's avatar
jehan committed
198
	return current_offset-offset;
jehan's avatar
jehan committed
199
}
jehan's avatar
jehan committed
200 201
BELLE_SIP_NEW(request,message)
BELLE_SIP_PARSE(request)
jehan's avatar
jehan committed
202
GET_SET_STRING(belle_sip_request,method);
jehan's avatar
jehan committed
203 204

void belle_sip_request_set_uri(belle_sip_request_t* request,belle_sip_uri_t* uri) {
jehan's avatar
jehan committed
205 206 207 208
	if (request->uri) {
		belle_sip_object_unref(request->uri);
	}
	request->uri=BELLE_SIP_URI(belle_sip_object_ref(uri));
jehan's avatar
jehan committed
209 210
}

211
belle_sip_uri_t * belle_sip_request_get_uri(belle_sip_request_t *request){
jehan's avatar
jehan committed
212
	return request->uri;
213 214
}

Simon Morlat's avatar
wip  
Simon Morlat committed
215
int belle_sip_message_is_request(belle_sip_message_t *msg){
216
	return BELLE_SIP_IS_INSTANCE_OF(BELLE_SIP_OBJECT(msg),belle_sip_request_t);
Simon Morlat's avatar
wip  
Simon Morlat committed
217 218 219
}

int belle_sip_message_is_response(belle_sip_message_t *msg){
220
	return BELLE_SIP_IS_INSTANCE_OF(BELLE_SIP_OBJECT(msg),belle_sip_response_t);
Simon Morlat's avatar
wip  
Simon Morlat committed
221 222
}

223 224 225 226
belle_sip_header_t *belle_sip_message_get_header(belle_sip_message_t *msg, const char *header_name){
	const belle_sip_list_t *l=belle_sip_message_get_headers(msg,header_name);
	if (l!=NULL)
		return (belle_sip_header_t*)l->data;
Simon Morlat's avatar
wip  
Simon Morlat committed
227 228
	return NULL;
}
229

Simon Morlat's avatar
Simon Morlat committed
230

231
char *belle_sip_message_to_string(belle_sip_message_t *msg){
jehan's avatar
jehan committed
232 233
	return belle_sip_object_to_string(BELLE_SIP_OBJECT(msg));
}
jehan's avatar
jehan committed
234 235
const char* belle_sip_message_get_body(belle_sip_message_t *msg) {
	return msg->body;
236
}
jehan's avatar
jehan committed
237 238 239 240 241 242 243
void belle_sip_message_set_body(belle_sip_message_t *msg,char* body,unsigned int size) {
	if (msg->body) {
		belle_sip_free((void*)body);
	}
	msg->body = belle_sip_malloc(size+1);
	memcpy(msg->body,body,size);
	msg->body[size]='\0';
jehan's avatar
jehan committed
244
}
Simon Morlat's avatar
Simon Morlat committed
245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330
struct _belle_sip_response{
	belle_sip_message_t base;
	char *sip_version;
	int status_code;
	char *reason_phrase;
};

typedef struct code_phrase{
	int code;
	const char *phrase;
} code_phrase_t;

static code_phrase_t well_known_codes[]={
	{	100		,		"Trying"	},
	{	101		,		"Dialog establishment"	},
	{	180		,		"Ringing"				},
	{	181		,		"Call is being forwarded"	},
	{	182		,		"Queued"	},
	{	183		,		"Session progress"	},
	{	200		,		"Ok"				},
	{	202		,		"Accepted"	},
	{	300		,		"Multiple choices"	},
	{	301		,		"Moved permanently"	},
	{	302		,		"Moved temporarily"	},
	{	305		,		"Use proxy"	},
	{	380		,		"Alternate contact"	},
	{	400		,		"Bad request"		},
	{	401		,		"Unauthorized"		},
	{	402		,		"Payment required"	},
	{	403		,		"Forbidden"	},
	{	404		,		"Not found"	},
	{	405		,		"Method not allowed"	},
	{	406		,		"Not acceptable"	},
	{	407		,		"Proxy authentication required"	},
	{	408		,		"Request timeout"	},
	{	410		,		"Gone"	},
	{	413		,		"Request entity too large"	},
	{	414		,		"Request-URI too long"	},
	{	415		,		"Unsupported media type"	},
	{	416		,		"Unsupported URI scheme"	},
	{	420		,		"Bad extension"	},
	{	421		,		"Extension required"	},
	{	423		,		"Interval too brief"	},
	{	480		,		"Temporarily unavailable"	},
	{	481		,		"Call/transaction does not exist"	},
	{	482		,		"Loop detected"	},
	{	483		,		"Too many hops"	},
	{	484		,		"Address incomplete"	},
	{	485		,		"Ambiguous"	},
	{	486		,		"Busy here"	},
	{	487		,		"Request terminated"	},
	{	488		,		"Not acceptable here"	},
	{	491		,		"Request pending"	},
	{	493		,		"Undecipherable"	},
	{	500		,		"Server internal error"	},
	{	501		,		"Not implemented"	},
	{	502		,		"Bad gateway"	},
	{	503		,		"Service unavailable"	},
	{	504		,		"Server time-out"	},
	{	505		,		"Version not supported"	},
	{	513		,		"Message too large"	},
	{	600		,		"Busy everywhere"	},
	{	603		,		"Decline"	},
	{	604		,		"Does not exist anywhere"	},
	{	606		,		"Not acceptable"	},
	{	0			,		NULL	}
};

const char *belle_sip_get_well_known_reason_phrase(int status_code){
	int i;
	for(i=0;well_known_codes[i].code!=0;++i){
		if (well_known_codes[i].code==status_code)
			return well_known_codes[i].phrase;
	}
	return "Unknown reason";
}

void belle_sip_response_destroy(belle_sip_response_t *resp){
	if (resp->sip_version) belle_sip_free(resp->sip_version);
	if (resp->reason_phrase) belle_sip_free(resp->reason_phrase);
}

static void belle_sip_response_clone(belle_sip_response_t *resp, const belle_sip_response_t *orig){
	if (orig->sip_version) resp->sip_version=belle_sip_strdup(orig->sip_version);
	if (orig->reason_phrase) resp->reason_phrase=belle_sip_strdup(orig->reason_phrase);
}
jehan's avatar
jehan committed
331
int belle_sip_response_marshal(belle_sip_response_t *resp, char* buff,unsigned int offset,unsigned int buff_size) {
jehan's avatar
jehan committed
332 333 334 335 336 337 338
	unsigned int current_offset=offset;
	current_offset+=snprintf(	buff+current_offset
								,buff_size-current_offset
								,"SIP/2.0 %i %s\r\n"
								,belle_sip_response_get_status_code(resp)
								,belle_sip_response_get_reason_phrase(resp));
	current_offset+=belle_sip_headers_marshal(BELLE_SIP_MESSAGE(resp),buff,current_offset,buff_size);
jehan's avatar
jehan committed
339 340 341
	if (BELLE_SIP_MESSAGE(resp)->body) {
		current_offset+=snprintf(buff+current_offset,buff_size-current_offset, "%s",BELLE_SIP_MESSAGE(resp)->body);
	}
jehan's avatar
jehan committed
342
	return current_offset-offset;
jehan's avatar
jehan committed
343
}
Simon Morlat's avatar
Simon Morlat committed
344
BELLE_SIP_NEW(response,message);
345 346 347
BELLE_SIP_PARSE(response)
GET_SET_STRING(belle_sip_response,reason_phrase);
GET_SET_INT(belle_sip_response,status_code,int)
Simon Morlat's avatar
Simon Morlat committed
348

349 350 351 352 353 354 355 356 357
belle_sip_request_t* belle_sip_request_create(belle_sip_uri_t *requri, const char* method,
                                         belle_sip_header_call_id_t *callid,
                                         belle_sip_header_cseq_t * cseq,
                                         belle_sip_header_from_t *from,
                                         belle_sip_header_to_t *to,
                                         belle_sip_header_via_t *via,
                                         int max_forward /*FIXME*/)
{
	belle_sip_request_t *ret=belle_sip_request_new();
358 359 360
	belle_sip_header_max_forwards_t *mf=belle_sip_header_max_forwards_new();
	if (max_forward==0) max_forward=70;
	belle_sip_header_max_forwards_set_max_forwards(mf,max_forward);
361 362 363 364 365 366 367 368

	belle_sip_request_set_uri(ret,requri);
	belle_sip_request_set_method(ret,method);
	belle_sip_message_add_header((belle_sip_message_t*)ret,BELLE_SIP_HEADER(via));
	belle_sip_message_add_header((belle_sip_message_t*)ret,BELLE_SIP_HEADER(from));
	belle_sip_message_add_header((belle_sip_message_t*)ret,BELLE_SIP_HEADER(to));
	belle_sip_message_add_header((belle_sip_message_t*)ret,BELLE_SIP_HEADER(cseq));
	belle_sip_message_add_header((belle_sip_message_t*)ret,BELLE_SIP_HEADER(callid));
369
	belle_sip_message_add_header((belle_sip_message_t*)ret,BELLE_SIP_HEADER(mf));
370 371 372
	return ret;
}

Simon Morlat's avatar
Simon Morlat committed
373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393
static void belle_sip_response_init_default(belle_sip_response_t *resp, int status_code, const char *phrase){
	resp->status_code=status_code;
	resp->sip_version=belle_sip_strdup("SIP/2.0");
	if (phrase==NULL) phrase=belle_sip_get_well_known_reason_phrase(status_code);
	resp->reason_phrase=belle_sip_strdup(phrase);
}

belle_sip_response_t *belle_sip_response_new_from_request(belle_sip_request_t *req, int status_code){
	belle_sip_response_t *resp=belle_sip_response_new();
	belle_sip_header_t *h;
	belle_sip_response_init_default(resp,status_code,NULL);
	belle_sip_message_add_headers((belle_sip_message_t*)resp,belle_sip_message_get_headers ((belle_sip_message_t*)req,"via"));
	belle_sip_message_add_header((belle_sip_message_t*)resp,belle_sip_message_get_header((belle_sip_message_t*)req,"from"));
	belle_sip_message_add_header((belle_sip_message_t*)resp,belle_sip_message_get_header((belle_sip_message_t*)req,"to"));
	belle_sip_message_add_header((belle_sip_message_t*)resp,belle_sip_message_get_header((belle_sip_message_t*)req,"cseq"));
	h=belle_sip_message_get_header((belle_sip_message_t*)req,"call-id");
	if (h) belle_sip_message_add_header((belle_sip_message_t*)resp,h);
	
	return resp;
}

394

Simon Morlat's avatar
Simon Morlat committed
395

396 397 398 399 400 401 402 403 404 405
void belle_sip_response_get_return_hop(belle_sip_response_t *msg, belle_sip_hop_t *hop){
	belle_sip_header_via_t *via=BELLE_SIP_HEADER_VIA(belle_sip_message_get_header(BELLE_SIP_MESSAGE(msg),"via"));
	hop->transport=belle_sip_header_via_get_protocol(via);
	hop->host=belle_sip_header_via_get_received(via);
	if (hop->host==NULL)
		hop->host=belle_sip_header_via_get_host(via);
	hop->port=belle_sip_header_via_get_rport(via);
	if (hop->port==-1)
		hop->port=belle_sip_header_via_get_listening_port(via);
}