Commit 581a80f8 authored by jehan's avatar jehan

add channel parser tests

better management of partial SIP message
parent f311b807
......@@ -84,6 +84,10 @@ static void fix_incoming_via(belle_sip_request_t *msg, const struct addrinfo* or
char received[NI_MAXHOST];
char rport[NI_MAXSERV];
belle_sip_header_via_t *via;
if (!origin) {
belle_sip_warning("cannot fix via for message [%p], probably a test",msg);
return;
}
int err=getnameinfo(origin->ai_addr,origin->ai_addrlen,received,sizeof(received),
rport,sizeof(rport),NI_NUMERICHOST|NI_NUMERICSERV);
if (err!=0){
......@@ -105,6 +109,37 @@ static void fix_incoming_via(belle_sip_request_t *msg, const struct addrinfo* or
}
}
/*token = 1*(alphanum / "-" / "." / "!" / "%" / "*"
/ "_" / "+" / "`" / "'" / "~" )
*
* */
static int is_token(const char* buff,size_t bufflen ) {
int i;
for (i=0; i<bufflen && buff[i]!='\0';i++) {
switch(buff[i]) {
case '-' :
case '.' :
case '!' :
case '%' :
case '*' :
case '_' :
case '+' :
case '`' :
case '\'' :
case '~' :
break;
default:
if ((buff[i]>='0' && buff[i]<='9')
|| (buff[i]>='A' && buff[i]<='Z')
|| (buff[i]>='a' && buff[i]<='z')
|| (buff[i]=='\0'))
continue;
else
return 0;
}
}
return 1;
}
static int get_message_start_pos(char *buff, size_t bufflen) {
/*FIXME still to optimize an better tested, specially REQUEST PATH and error path*/
int i;
......@@ -116,12 +151,20 @@ static int get_message_start_pos(char *buff, size_t bufflen) {
int saved_char1_index;
for(i=0; i<(int)bufflen-12;i++) { /*9=strlen( SIP/2.0\r\n)*/
switch (buff[i]) { /*to avoid this character to be ignored by scanf*/
case '\r':
case '\n':
continue;
default:
break;
}
saved_char1_index=bufflen-1;
saved_char1=buff[saved_char1_index]; /*make sure buff is null terminated*/
buff[saved_char1_index]='\0';
res=sscanf(buff+i,"SIP/2.0 %d ",&status_code);
if (res!=1) {
res= sscanf(buff+i,"%16s %*s %9s\r\n",method,sip_version)==2
&& is_token(method,sizeof(method))
&& strcmp("SIP/2.0",sip_version)==0 ;
}
buff[saved_char1_index]=saved_char1;
......@@ -150,7 +193,7 @@ static void belle_sip_channel_message_ready(belle_sip_channel_t *obj){
}
}
static void belle_sip_channel_parse_stream(belle_sip_channel_t *obj){
void belle_sip_channel_parse_stream(belle_sip_channel_t *obj){
int offset;
size_t read_size=0;
belle_sip_header_content_length_t* content_length_header;
......@@ -177,11 +220,13 @@ static void belle_sip_channel_parse_stream(belle_sip_channel_t *obj){
if (obj->input_stream.state==MESSAGE_AQUISITION) {
/*search for \r\n\r\n*/
if (strstr(obj->input_stream.read_ptr,"\r\n\r\n")){
char* end_of_message=NULL;
if ((end_of_message=strstr(obj->input_stream.read_ptr,"\r\n\r\n"))){
/*end of message found*/
end_of_message+=4;/*add \r\n\r\n*/
belle_sip_message("channel [%p] read message from %s:%i\n%s",obj, obj->peer_name,obj->peer_port,obj->input_stream.read_ptr);
obj->input_stream.msg=belle_sip_message_parse_raw(obj->input_stream.read_ptr
,obj->input_stream.write_ptr-obj->input_stream.read_ptr
,end_of_message-obj->input_stream.read_ptr
,&read_size);
obj->input_stream.read_ptr+=read_size;
if (obj->input_stream.msg && read_size > 0){
......@@ -199,8 +244,11 @@ static void belle_sip_channel_parse_stream(belle_sip_channel_t *obj){
continue;
}
}else{
belle_sip_error("Could not parse [%s], resetting channel [%p]",obj->input_stream.read_ptr,obj);
belle_sip_channel_input_stream_reset(&obj->input_stream);
belle_sip_error("Could not parse [%s], on channel [%p] skipping to [%s]",obj->input_stream.read_ptr
,obj
,end_of_message);
obj->input_stream.read_ptr=end_of_message;
obj->input_stream.state=WAITING_MESSAGE_START;
continue;
}
}else break; /*The message isn't finished to be receive, we need more data*/
......
......@@ -18,7 +18,9 @@
#ifndef STREAM_CHANNEL_H_
#define STREAM_CHANNEL_H_
#ifdef __APPLE_
#include "TargetConditionals.h"
#endif
#if TARGET_OS_IPHONE
#include <CoreFoundation/CFStream.h>
......@@ -50,4 +52,8 @@ int stream_channel_connect(belle_sip_stream_channel_t *obj, const struct addrinf
int finalize_stream_connection(belle_sip_stream_channel_t *obj, struct sockaddr *addr, socklen_t* slen);
int stream_channel_send(belle_sip_stream_channel_t *obj, const void *buf, size_t buflen);
int stream_channel_recv(belle_sip_stream_channel_t *obj, void *buf, size_t buflen);
/*for testing purpose*/
void belle_sip_channel_parse_stream(belle_sip_channel_t *obj);
#endif /* STREAM_CHANNEL_H_ */
......@@ -328,7 +328,120 @@ static void testMalformedMessageWithWrongStart(void) {
belle_sip_message_t* message = belle_sip_message_parse(raw_message);
CU_ASSERT_PTR_NULL(message);
}
#include "belle_sip_internal.h"
void channel_parser_tester_recovery_from_error () {
belle_sip_stack_t* stack = belle_sip_stack_new(NULL);
belle_sip_channel_t* channel = belle_sip_stream_channel_new_client(stack
, NULL
, 45421
, NULL
, "127.0.0.1"
, 45421);
const char * raw_message= "debut de stream tout pourrit\r\n"
"INVITE je_suis_une_fause_request_uri_hihihi SIP/2.0\r\n"
"Via: SIP/2.0/UDP 192.168.1.12:15060;rport=15060;branch=z9hG4bK1596944937;received=81.56.113.2\r\n"
"Via: SIP/2.0/TCP 37.59.129.73;branch=z9hG4bK.SKvK9U327e8mU68XUv5rt144pg\r\n"
"Record-Route: <sip:37.59.129.73;lr;transport=tcp>\r\n"
"Record-Route: <sip:37.59.129.73;lr>\r\n"
"Max-Forwards: 70\r\n"
"From: <sip:jehan@sip.linphone.org>;tag=711138653\r\n"
"To: <sip:jehan@sip.linphone.org>\r\n"
"Call-ID: 977107319\r\n"
"CSeq: 21 INVITE\r\n"
"Contact: <sip:jehan-mac@192.168.1.8:5062>\r\n"
"Subject: Phone call\r\n"
"User-Agent: Linphone/3.5.2 (eXosip2/3.6.0)\r\n"
"Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, NOTIFY, MESSAGE, SUBSCRIBE, INFO\r\n"
"Content-Length: 0\r\n"
"\r\n"
"REGISTER sip:192.168.0.20 SIP/2.0\r\n"\
"Via: SIP/2.0/UDP 192.168.1.8:5062;rport;branch=z9hG4bK1439638806\r\n"\
"From: <sip:jehan-mac@sip.linphone.org>;tag=465687829\r\n"\
"To: <sip:jehan-mac@sip.linphone.org>\r\n"\
"Call-ID: 1053183492\r\n"\
"CSeq: 1 REGISTER\r\n"\
"Contact: <sip:jehan-mac@192.168.1.8:5062>\r\n" \
"Max-Forwards: 70\r\n"\
"User-Agent: Linphone/3.3.99.10 (eXosip2/3.3.0)\r\n"\
"Expires: 3600\r\n"\
"Proxy-Authorization: Digest username=\"8117396\", realm=\"Realm\", nonce=\"MTMwNDAwMjIxMjA4NzVkODY4ZmZhODMzMzU4ZDJkOTA1NzM2NTQ2NDZlNmIz"\
", uri=\"sip:linphone.net\", response=\"eed376ff7c963441255ec66594e470e7\", algorithm=MD5, cnonce=\"0a4f113b\", qop=auth, nc=00000001\r\n"\
"Content-Length: 0\r\n"
"\r\n";
belle_sip_request_t* request;
belle_sip_message_t* message;
channel->input_stream.write_ptr = strcpy(channel->input_stream.write_ptr,raw_message);
channel->input_stream.write_ptr+=strlen(raw_message);
belle_sip_channel_parse_stream(channel);
CU_ASSERT_PTR_NOT_NULL(channel->incoming_messages);
CU_ASSERT_PTR_NOT_NULL(channel->incoming_messages->data);
message=BELLE_SIP_MESSAGE(channel->incoming_messages->data);
CU_ASSERT_TRUE(belle_sip_object_is_instance_of(BELLE_SIP_OBJECT(message),belle_sip_request_t_id));
request = BELLE_SIP_REQUEST(message);
CU_ASSERT_STRING_EQUAL(belle_sip_request_get_method(request),"REGISTER");
CU_ASSERT_PTR_NOT_NULL(belle_sip_message_get_header(message,"Expires"));
CU_ASSERT_PTR_NOT_NULL(BELLE_SIP_HEADER_EXPIRES(belle_sip_message_get_header(message,"Expires")));
CU_ASSERT_PTR_NOT_NULL(belle_sip_message_get_header(message,"Proxy-Authorization"));
check_uri_and_headers(message);
belle_sip_object_unref(BELLE_SIP_OBJECT(message));
belle_sip_object_unref(stack);
}
void channel_parser_malformed_start () {
belle_sip_stack_t* stack = belle_sip_stack_new(NULL);
belle_sip_channel_t* channel = belle_sip_stream_channel_new_client(stack
, NULL
, 45421
, NULL
, "127.0.0.1"
, 45421);
const char * raw_message= "debut de stream tout pourrit\r\n"
"REGISTER sip:192.168.0.20 SIP/2.0\r\n"
"Via: SIP/2.0/UDP 192.168.1.8:5062;rport;branch=z9hG4bK1439638806\r\n"
"From: <sip:jehan-mac@sip.linphone.org>;tag=465687829\r\n"
"To: <sip:jehan-mac@sip.linphone.org>\r\n"
"Call-ID: 1053183492\r\n"
"CSeq: 1 REGISTER\r\n"
"Contact: <sip:jehan-mac@192.168.1.8:5062>\r\n"
"Max-Forwards: 70\r\n"
"User-Agent: Linphone/3.3.99.10 (eXosip2/3.3.0)\r\n"
"Expires: 3600\r\n"
"Proxy-Authorization: Digest username=\"8117396\", realm=\"Realm\", nonce=\"MTMwNDAwMjIxMjA4NzVkODY4ZmZhODMzMzU4ZDJkOTA1NzM2NTQ2NDZlNmIz"
", uri=\"sip:linphone.net\", response=\"eed376ff7c963441255ec66594e470e7\", algorithm=MD5, cnonce=\"0a4f113b\", qop=auth, nc=00000001\r\n"
"Content-Length: 0\r\n"
"\r\n";
belle_sip_request_t* request;
belle_sip_message_t* message;
channel->input_stream.write_ptr = strcpy(channel->input_stream.write_ptr,raw_message);
channel->input_stream.write_ptr+=strlen(raw_message);
belle_sip_channel_parse_stream(channel);
CU_ASSERT_PTR_NOT_NULL(channel->incoming_messages);
CU_ASSERT_PTR_NOT_NULL(channel->incoming_messages->data);
message=BELLE_SIP_MESSAGE(channel->incoming_messages->data);
CU_ASSERT_TRUE(belle_sip_object_is_instance_of(BELLE_SIP_OBJECT(message),belle_sip_request_t_id));
request = BELLE_SIP_REQUEST(message);
CU_ASSERT_STRING_EQUAL(belle_sip_request_get_method(request),"REGISTER");
CU_ASSERT_PTR_NOT_NULL(belle_sip_message_get_header(message,"Expires"));
CU_ASSERT_PTR_NOT_NULL(BELLE_SIP_HEADER_EXPIRES(belle_sip_message_get_header(message,"Expires")));
CU_ASSERT_PTR_NOT_NULL(belle_sip_message_get_header(message,"Proxy-Authorization"));
check_uri_and_headers(message);
belle_sip_object_unref(BELLE_SIP_OBJECT(message));
belle_sip_object_unref(stack);
}
/* NOTE - ORDER IS IMPORTANT - MUST TEST fread() AFTER fprintf() */
test_t message_tests[] = {
......@@ -342,6 +455,8 @@ test_t message_tests[] = {
{ "Malformed invite", testMalformedMessage },
{ "Malformed invite with bad begin", testMalformedMessageWithWrongStart },
{ "Malformed register", testMalformedOptionnalHeaderInMessage },
{ "Channel parser error recovery", channel_parser_tester_recovery_from_error},
{ "Channel parser malformed start", channel_parser_malformed_start}
};
test_suite_t message_test_suite = {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment