message.c 16.1 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
static void belle_sip_headers_container_delete(headers_container_t *obj){
	belle_sip_free(obj->name);
jehan's avatar
jehan committed
36
	belle_sip_list_free_with_data(obj->header_list,(void (*)(void*))belle_sip_object_unref);
Simon Morlat's avatar
Simon Morlat committed
37 38 39
	belle_sip_free(obj);
}

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

Simon Morlat's avatar
Simon Morlat committed
47 48 49 50 51
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);
}

52 53
BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(belle_sip_message_t);

Simon Morlat's avatar
Simon Morlat committed
54
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
55

jehan's avatar
jehan committed
56 57 58 59
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
60

61 62 63 64 65 66 67 68 69 70 71 72 73
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
74
/*	if (*message_length < buff_length) {*/
jehan's avatar
jehan committed
75
		/*there is a body*/
jehan's avatar
jehan committed
76
/*		l_parsed_object->body_length=buff_length-*message_length;
jehan's avatar
jehan committed
77 78 79
		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';
jehan's avatar
jehan committed
80
	}*/
81 82 83 84 85 86 87
	parser ->free(parser);
	tokens ->free(tokens);
	lex    ->free(lex);
	input  ->close(input);
	return l_parsed_object;
}

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

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

96 97 98 99 100 101
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
102 103

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

Simon Morlat's avatar
Simon Morlat committed
113 114
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
115
	headers_container->header_list=belle_sip_list_append(headers_container->header_list,belle_sip_object_ref(header));
jehan's avatar
jehan committed
116
}
Simon Morlat's avatar
Simon Morlat committed
117 118 119 120 121 122 123 124 125 126

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
127
		headers_container->header_list=belle_sip_list_append(headers_container->header_list,belle_sip_object_ref(h));
Simon Morlat's avatar
Simon Morlat committed
128 129 130
	}
}

jehan's avatar
jehan committed
131 132 133 134
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
135

jehan's avatar
jehan committed
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 176
/*
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
177 178
struct _belle_sip_request {
	belle_sip_message_t message;
jehan's avatar
jehan committed
179
	const char* method;
jehan's avatar
jehan committed
180
	belle_sip_uri_t* uri;
jehan's avatar
jehan committed
181 182 183
};

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

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
191
int belle_sip_request_marshal(belle_sip_request_t* request, char* buff,unsigned int offset,unsigned int buff_size) {
jehan's avatar
jehan committed
192 193 194 195 196
	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
197 198 199
	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
200
	return current_offset-offset;
jehan's avatar
jehan committed
201
}
jehan's avatar
jehan committed
202 203
BELLE_SIP_NEW(request,message)
BELLE_SIP_PARSE(request)
jehan's avatar
jehan committed
204
GET_SET_STRING(belle_sip_request,method);
jehan's avatar
jehan committed
205 206

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

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

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

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

225 226 227 228
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
229 230
	return NULL;
}
231

Simon Morlat's avatar
Simon Morlat committed
232

233
char *belle_sip_message_to_string(belle_sip_message_t *msg){
jehan's avatar
jehan committed
234 235
	return belle_sip_object_to_string(BELLE_SIP_OBJECT(msg));
}
jehan's avatar
jehan committed
236 237
const char* belle_sip_message_get_body(belle_sip_message_t *msg) {
	return msg->body;
238
}
jehan's avatar
jehan committed
239 240 241 242 243 244 245
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
246
}
Simon Morlat's avatar
Simon Morlat committed
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 331 332
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
333
int belle_sip_response_marshal(belle_sip_response_t *resp, char* buff,unsigned int offset,unsigned int buff_size) {
jehan's avatar
jehan committed
334 335 336 337 338 339 340
	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
341 342 343
	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
344
	return current_offset-offset;
jehan's avatar
jehan committed
345
}
Simon Morlat's avatar
Simon Morlat committed
346
BELLE_SIP_NEW(response,message);
347 348 349
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
350

351 352 353 354 355 356 357 358 359
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();
360 361 362
	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);
363 364 365 366 367 368 369 370

	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));
371
	belle_sip_message_add_header((belle_sip_message_t*)ret,BELLE_SIP_HEADER(mf));
372 373 374
	return ret;
}

Simon Morlat's avatar
Simon Morlat committed
375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395
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;
}

396

Simon Morlat's avatar
Simon Morlat committed
397

398 399 400 401 402 403 404 405 406 407
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);
}