Commit 116272af authored by Simon Morlat's avatar Simon Morlat

fix channel for http, when receiving big bodies without Content-Length

parent 208833f8
......@@ -257,11 +257,46 @@ static void belle_sip_channel_message_ready(belle_sip_channel_t *obj){
belle_sip_channel_input_stream_reset(&obj->input_stream);
}
void belle_sip_channel_parse_stream(belle_sip_channel_t *obj){
static int expects_body(belle_sip_message_t *msg){
belle_sip_header_content_length_t* content_length_header;
if ((content_length_header = belle_sip_message_get_header_by_type(msg,belle_sip_header_content_length_t)) != NULL){
return belle_sip_header_content_length_get_content_length(content_length_header)>0;
}
/* content-length is not mandatory in http*/
if (belle_sip_message_get_header_by_type(msg, belle_sip_header_content_type_t)!=NULL)
return TRUE;
return FALSE;
}
static int acquire_body(belle_sip_channel_t *obj, int end_of_stream){
belle_sip_header_content_length_t* content_length_header=belle_sip_message_get_header_by_type(obj->input_stream.msg,belle_sip_header_content_length_t);
int content_length=-1;
if (content_length_header)
content_length=belle_sip_header_content_length_get_content_length(content_length_header);
if (end_of_stream && content_length==-1){
content_length=obj->input_stream.write_ptr-obj->input_stream.read_ptr;
}
if (content_length!=-1 && content_length <= obj->input_stream.write_ptr-obj->input_stream.read_ptr){
/*great body completed
belle_sip_message("channel [%p] read [%i] bytes of body from %s:%i\n%s" ,obj
,content_length
,obj->peer_name
,obj->peer_port
,obj->input_stream.read_ptr);*/
belle_sip_message_set_body(obj->input_stream.msg,obj->input_stream.read_ptr,content_length);
obj->input_stream.read_ptr+=content_length;
belle_sip_channel_message_ready(obj);
return BELLE_SIP_CONTINUE;
}else{
/*body is not finished, we need more data*/
return BELLE_SIP_STOP;
}
}
void belle_sip_channel_parse_stream(belle_sip_channel_t *obj, int end_of_stream){
int offset;
size_t read_size=0;
belle_sip_header_content_length_t* content_length_header;
int content_length;
int num;
while ((num=(obj->input_stream.write_ptr-obj->input_stream.read_ptr))>0){
......@@ -305,9 +340,8 @@ void belle_sip_channel_parse_stream(belle_sip_channel_t *obj){
belle_sip_object_ref(obj->input_stream.msg);
if (belle_sip_message_is_request(obj->input_stream.msg)) fix_incoming_via(BELLE_SIP_REQUEST(obj->input_stream.msg),obj->current_peer);
/*check for body*/
if ((content_length_header = (belle_sip_header_content_length_t*)belle_sip_message_get_header(obj->input_stream.msg,BELLE_SIP_CONTENT_LENGTH)) != NULL
&& belle_sip_header_content_length_get_content_length(content_length_header)>0) {
if (expects_body(obj->input_stream.msg)){
obj->input_stream.state=BODY_AQUISITION;
} else {
/*no body*/
......@@ -326,23 +360,11 @@ void belle_sip_channel_parse_stream(belle_sip_channel_t *obj){
}
if (obj->input_stream.state==BODY_AQUISITION) {
content_length=belle_sip_header_content_length_get_content_length((belle_sip_header_content_length_t*)belle_sip_message_get_header(obj->input_stream.msg,BELLE_SIP_CONTENT_LENGTH));
if (content_length <= obj->input_stream.write_ptr-obj->input_stream.read_ptr) {
/*great body completed
belle_sip_message("channel [%p] read [%i] bytes of body from %s:%i\n%s" ,obj
,content_length
,obj->peer_name
,obj->peer_port
,obj->input_stream.read_ptr);*/
belle_sip_message_set_body(obj->input_stream.msg,obj->input_stream.read_ptr,content_length);
obj->input_stream.read_ptr+=content_length;
belle_sip_channel_message_ready(obj);
}else{
/*body is not finished, we need more data*/
break;
}
if (acquire_body(obj,end_of_stream)==BELLE_SIP_STOP) break;
}
}
if (obj->incoming_messages)
BELLE_SIP_INVOKE_LISTENERS_ARG1_ARG2(obj->listeners,belle_sip_channel_listener_t,on_event,obj,BELLE_SIP_EVENT_READ/*always a read event*/);
}
int belle_sip_channel_process_data(belle_sip_channel_t *obj,unsigned int revents){
......@@ -372,14 +394,16 @@ int belle_sip_channel_process_data(belle_sip_channel_t *obj,unsigned int revents
obj->peer_name,
obj->peer_port,
begin);
belle_sip_channel_parse_stream(obj);
if (obj->incoming_messages)
BELLE_SIP_INVOKE_LISTENERS_ARG1_ARG2(obj->listeners,belle_sip_channel_listener_t,on_event,obj,BELLE_SIP_EVENT_READ/*always a read event*/);
belle_sip_channel_parse_stream(obj,FALSE);
} else if (num == 0) {
/*before closing the channel, check if there was a pending message to receive, whose body acquisition is to be finished.*/
belle_sip_channel_parse_stream(obj,TRUE);
channel_set_state(obj,BELLE_SIP_CHANNEL_DISCONNECTED);
return BELLE_SIP_STOP;
} else {
} else if ( belle_sip_error_code_is_would_block(-num)){
belle_sip_message("EWOULDBLOCK");
return BELLE_SIP_CONTINUE;
}else{
belle_sip_error("Receive error on channel [%p]",obj);
channel_set_state(obj,BELLE_SIP_CHANNEL_ERROR);
return BELLE_SIP_STOP;
......
......@@ -55,5 +55,5 @@ int stream_channel_recv(belle_sip_stream_channel_t *obj, void *buf, size_t bufle
/*for testing purpose*/
void belle_sip_channel_parse_stream(belle_sip_channel_t *obj);
void belle_sip_channel_parse_stream(belle_sip_channel_t *obj, int end_of_stream);
#endif /* STREAM_CHANNEL_H_ */
......@@ -101,6 +101,7 @@ static int tls_channel_recv(belle_sip_channel_t *obj, void *buf, size_t buflen){
int err = ssl_read(&channel->sslctx,buf,buflen);
if (err==POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY) return 0;
if (err<0){
if (err==POLARSSL_ERR_NET_WANT_READ) return -BELLESIP_EWOULDBLOCK;
char tmp[256]={0};
error_strerror(err,tmp,sizeof(tmp));
belle_sip_error("Channel [%p]: ssl_read() error [%i]: %s",obj, err, tmp);
......
......@@ -127,6 +127,12 @@ static void one_https_get(void){
CU_ASSERT_EQUAL(counters.two_hundred,1);
}
static void https_get_long_body(void){
http_counters_t counters={0};
one_get("https://www.linphone.org/eng/features/",&counters);
CU_ASSERT_EQUAL(counters.two_hundred,1);
}
static void https_digest_get(void){
http_counters_t counters={0};
one_get("https://pauline:pouet@smtp.linphone.org/restricted",&counters);
......@@ -147,6 +153,7 @@ static void https_client_cert_connection(void){
test_t http_tests[] = {
{ "One http GET", one_http_get },
{ "One https GET", one_https_get },
{ "https GET with long body", https_get_long_body },
{ "https digest GET", https_digest_get },
{ "https with client certificate", https_client_cert_connection },
};
......
......@@ -378,7 +378,7 @@ void channel_parser_tester_recovery_from_error () {
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);
belle_sip_channel_parse_stream(channel,FALSE);
CU_ASSERT_PTR_NOT_NULL(channel->incoming_messages);
CU_ASSERT_PTR_NOT_NULL(channel->incoming_messages->data);
......@@ -426,7 +426,7 @@ void channel_parser_malformed_start () {
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);
belle_sip_channel_parse_stream(channel,FALSE);
CU_ASSERT_PTR_NOT_NULL(channel->incoming_messages);
CU_ASSERT_PTR_NOT_NULL(channel->incoming_messages->data);
......@@ -664,13 +664,14 @@ void channel_parser_http_response () {
"Content-Encoding: gzip\r\n"
"Vary: Accept-Encoding\r\n"
"Transfer-Encoding: chunked\r\n"
"\r\n";
"\r\n"
"<html></html>\r\n\r\n";
belle_http_response_t* response;
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);
belle_sip_channel_parse_stream(channel,TRUE);
CU_ASSERT_PTR_NOT_NULL(channel->incoming_messages);
CU_ASSERT_PTR_NOT_NULL(channel->incoming_messages->data);
......
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