Commit 04d50c98 authored by Simon Morlat's avatar Simon Morlat

* implement streamed body handler, so that http get and post of large files can be implemented.

* implement retry of EWOULDBLOCK returned send()
* rework channel's listener for clarity
* fix various memory leaks.
parent 95dd343e
......@@ -26,6 +26,7 @@ bellesip_HEADERS=\
http-message.h \
http-listener.h \
generic-uri.h \
types.h
types.h \
bodyhandler.h
EXTRA_DIST=$(bellesip_HEADERS)
......@@ -41,6 +41,7 @@
#include "belle-sip/http-listener.h"
#include "belle-sip/http-message.h"
#include "belle-sip/belle-sdp.h"
#include "belle-sip/bodyhandler.h"
#define BELLE_SIP_POINTER_TO_INT(p) ((int)(long)(p))
......
/*
belle-sip - SIP (RFC3261) library.
Copyright (C) 2014 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/>.
*/
#ifndef belle_sip_body_handler_h
#define belle_sip_body_handler_h
BELLE_SIP_BEGIN_DECLS
#define BELLE_SIP_BODY_HANDLER(obj) BELLE_SIP_CAST(obj,belle_sip_body_handler_t)
/*
* Body handler base class.
**/
typedef void (*belle_sip_body_handler_progress_callback_t)(belle_sip_body_handler_t *obj, belle_sip_message_t *msg, void *user_data, size_t transfered, size_t expected_total);
BELLESIP_EXPORT size_t belle_sip_body_handler_get_size(const belle_sip_body_handler_t *obj);
BELLESIP_EXPORT size_t belle_sip_body_handler_get_transfered_size(const belle_sip_body_handler_t *obj);
/*
* body handler that read/write from a memory buffer.
**/
#define BELLE_SIP_MEMORY_BODY_HANDLER(obj) BELLE_SIP_CAST(obj,belle_sip_memory_body_handler_t)
BELLESIP_EXPORT belle_sip_memory_body_handler_t *belle_sip_memory_body_handler_new(belle_sip_body_handler_progress_callback_t progress_cb, void *data);
BELLESIP_EXPORT belle_sip_memory_body_handler_t *belle_sip_memory_body_handler_new_copy_from_buffer(const void *buffer, size_t bufsize,
belle_sip_body_handler_progress_callback_t cb, void *user_data);
BELLESIP_EXPORT belle_sip_memory_body_handler_t *belle_sip_memory_body_handler_new_from_buffer(void *buffer, size_t bufsize,
belle_sip_body_handler_progress_callback_t cb, void *user_data);
BELLESIP_EXPORT const void *belle_sip_memory_body_handler_get_buffer(const belle_sip_memory_body_handler_t *obj);
/*
* body handler that get/puts data from application.
**/
#define BELLE_SIP_USER_BODY_HANDLER(obj) BELLE_SIP_CAST(obj,belle_sip_user_body_handler_t)
typedef void (*belle_sip_user_body_handler_recv_callback_t)(belle_sip_user_body_handler_t *obj, belle_sip_message_t *msg, void *user_data, size_t offset, const void* buffer, size_t size);
typedef int (*belle_sip_user_body_handler_send_callback_t)(belle_sip_user_body_handler_t *obj, belle_sip_message_t *msg, void *user_data, size_t offset, void* buffer, size_t *size);
BELLESIP_EXPORT belle_sip_user_body_handler_t *belle_sip_user_body_handler_new(
size_t total_size,
belle_sip_body_handler_progress_callback_t progress_cb,
belle_sip_user_body_handler_recv_callback_t recv_cb,
belle_sip_user_body_handler_send_callback_t send_cb,
void *data);
/*
* Multipart body handler
*/
#define BELLE_SIP_MULTIPART_BODY_HANDLER(obj) BELLE_SIP_CAST(obj,belle_sip_multipart_body_handler_t)
BELLESIP_EXPORT belle_sip_multipart_body_handler_t *belle_sip_multipart_body_handler_new(belle_sip_body_handler_progress_callback_t progress_cb, void *data, belle_sip_body_handler_t *first_part);
BELLESIP_EXPORT void belle_sip_multipart_body_handler_add_part(belle_sip_multipart_body_handler_t *obj, belle_sip_body_handler_t *part);
BELLE_SIP_END_DECLS
#endif
......@@ -31,6 +31,7 @@ typedef struct belle_http_response_event belle_http_response_event_t;
#define BELLE_HTTP_INTERFACE_FUNCS(argT) \
void (*process_response_headers)(argT *user_ctx, const belle_http_response_event_t *event); \
void (*process_response)(argT *user_ctx, const belle_http_response_event_t *event); \
void (*process_io_error)(argT *user_ctx, const belle_sip_io_error_event_t *event); \
void (*process_timeout)(argT *user_ctx, const belle_sip_timeout_event_t *event); \
......
......@@ -108,9 +108,14 @@ BELLESIP_EXPORT void belle_sip_message_remove_last(belle_sip_message_t *msg, con
BELLESIP_EXPORT void belle_sip_message_remove_header(belle_sip_message_t *msg, const char *header_name);
BELLESIP_EXPORT char *belle_sip_message_to_string(belle_sip_message_t *msg);
BELLESIP_EXPORT belle_sip_body_handler_t *belle_sip_message_get_body_handler(const belle_sip_message_t *msg);
BELLESIP_EXPORT void belle_sip_message_set_body_handler(belle_sip_message_t *msg, belle_sip_body_handler_t *body_handler);
BELLESIP_EXPORT const char* belle_sip_message_get_body(belle_sip_message_t *msg);
BELLESIP_EXPORT unsigned int belle_sip_message_get_body_size(const belle_sip_message_t *msg);
BELLESIP_EXPORT size_t belle_sip_message_get_body_size(const belle_sip_message_t *msg);
BELLESIP_EXPORT void belle_sip_message_set_body(belle_sip_message_t *msg,const char* body,unsigned int size);
......
......@@ -124,7 +124,12 @@ BELLE_SIP_DECLARE_TYPES_BEGIN(belle_sip,1)
BELLE_SIP_TYPE_ID(belle_generic_uri_t),
BELLE_SIP_TYPE_ID(belle_http_callbacks_t),
BELLE_SIP_TYPE_ID(belle_tls_verify_policy_t),
BELLE_SIP_TYPE_ID(belle_http_header_authorization_t)
BELLE_SIP_TYPE_ID(belle_http_header_authorization_t),
BELLE_SIP_TYPE_ID(belle_sip_body_handler_t),
BELLE_SIP_TYPE_ID(belle_sip_memory_body_handler_t),
BELLE_SIP_TYPE_ID(belle_sip_file_body_handler_t),
BELLE_SIP_TYPE_ID(belle_sip_user_body_handler_t),
BELLE_SIP_TYPE_ID(belle_sip_multipart_body_handler_t)
BELLE_SIP_DECLARE_TYPES_END
......@@ -158,6 +163,10 @@ typedef struct _belle_sip_parameters belle_sip_parameters_t;
typedef struct belle_sip_param_pair belle_sip_param_pair_t;
typedef struct _belle_sip_header belle_sip_header_t;
typedef struct belle_tls_verify_policy belle_tls_verify_policy_t;
typedef struct belle_sip_body_handler belle_sip_body_handler_t;
typedef struct belle_sip_memory_body_handler belle_sip_memory_body_handler_t;
typedef struct belle_sip_user_body_handler belle_sip_user_body_handler_t;
typedef struct belle_sip_multipart_body_handler belle_sip_multipart_body_handler_t;
#endif
......
......@@ -49,8 +49,9 @@ libbellesip_la_SOURCES= \
generic-uri.c \
http-provider.c \
http-message.c \
http-listener.c
http-listener.c \
bodyhandler.c
if BUILD_IOS
libbellesip_la_SOURCES+=backgroundtask.m
......
......@@ -72,9 +72,7 @@ belle_sip_signing_key_t* belle_sip_auth_event_get_signing_key(const belle_sip_au
}
void belle_sip_auth_event_set_signing_key(belle_sip_auth_event_t* event, belle_sip_signing_key_t* value) {
if (event->key) belle_sip_object_unref(event->key);
event->key=value;
if (event->key) belle_sip_object_ref(event->key);
SET_OBJECT_PROPERTY(event,key,value);
}
belle_sip_auth_mode_t belle_sip_auth_event_get_mode(const belle_sip_auth_event_t* event) {
......
......@@ -587,12 +587,11 @@ void belle_sip_message_init(belle_sip_message_t *message);
struct _belle_sip_message {
belle_sip_object_t base;
belle_sip_list_t* header_list;
char* body;
unsigned int body_length;
belle_sip_body_handler_t *body_handler;
};
struct _belle_sip_request {
belle_sip_message_t message;
belle_sip_message_t base;
char* method;
belle_sip_uri_t* uri;
belle_sip_dialog_t *dialog;/*set if request was created by a dialog to avoid to search in dialog list*/
......@@ -975,4 +974,30 @@ const char* belle_sip_header_extension_get_value(const belle_sip_header_extensio
void belle_sip_header_extension_set_value(belle_sip_header_extension_t* extension,const char* value);
#define BELLE_SIP_HEADER_EXTENSION(t) BELLE_SIP_CAST(t,belle_sip_header_extension_t)
/****************
* belle_sip_body_handler_t object
***************/
BELLE_SIP_DECLARE_CUSTOM_VPTR_BEGIN(belle_sip_body_handler_t,belle_sip_object_t)
void (*chunk_recv)(belle_sip_body_handler_t *obj, belle_sip_message_t *msg, size_t offset, const uint8_t *buf, size_t size);
int (*chunk_send)(belle_sip_body_handler_t *obj, belle_sip_message_t *msg, size_t offset, uint8_t *buf, size_t * size);
BELLE_SIP_DECLARE_CUSTOM_VPTR_END
void belle_sip_body_handler_begin_transfer(belle_sip_body_handler_t *obj);
void belle_sip_body_handler_recv_chunk(belle_sip_body_handler_t *obj, belle_sip_message_t *msg, const uint8_t *buf, size_t size);
int belle_sip_body_handler_send_chunk(belle_sip_body_handler_t *obj, belle_sip_message_t *msg, uint8_t *buf, size_t *size);
void belle_sip_body_handler_end_transfer(belle_sip_body_handler_t *obj);
BELLE_SIP_DECLARE_CUSTOM_VPTR_BEGIN(belle_sip_memory_body_handler_t,belle_sip_body_handler_t)
BELLE_SIP_DECLARE_CUSTOM_VPTR_END
BELLE_SIP_DECLARE_CUSTOM_VPTR_BEGIN(belle_sip_user_body_handler_t,belle_sip_body_handler_t)
BELLE_SIP_DECLARE_CUSTOM_VPTR_END
BELLE_SIP_DECLARE_CUSTOM_VPTR_BEGIN(belle_sip_multipart_body_handler_t,belle_sip_body_handler_t)
BELLE_SIP_DECLARE_CUSTOM_VPTR_END
#endif
......@@ -242,8 +242,9 @@ static int belle_sip_object_data_find(const void* a, const void* b)
static void belle_sip_object_data_destroy(void* data)
{
struct belle_sip_object_data* da = (struct belle_sip_object_data*)data;
if(da->destroy_func ) da->destroy_func(da->data);
if (da->destroy_func) da->destroy_func(da->data);
belle_sip_free(da->name);
belle_sip_free(da);
}
int belle_sip_object_data_set( belle_sip_object_t *obj, const char* name, void* data, belle_sip_data_destroy destroy_func )
......
......@@ -302,12 +302,14 @@ void belle_sip_list_for_each2(const belle_sip_list_t* list, void (*func)(void *,
}
belle_sip_list_t * belle_sip_list_pop_front(belle_sip_list_t *list, void **front_data){
if (list==NULL){
belle_sip_list_t *front_elem=list;
if (front_elem==NULL){
*front_data=NULL;
return NULL;
}
*front_data=list->data;
list=belle_sip_list_remove_link(list,list);
*front_data=front_elem->data;
list=belle_sip_list_remove_link(list,front_elem);
belle_sip_free(front_elem);
return list;
}
......
This diff is collapsed.
This diff is collapsed.
......@@ -54,27 +54,32 @@ typedef struct belle_sip_channel belle_sip_channel_t;
BELLE_SIP_DECLARE_INTERFACE_BEGIN(belle_sip_channel_listener_t)
void (*on_state_changed)(belle_sip_channel_listener_t *l, belle_sip_channel_t *, belle_sip_channel_state_t state);
int (*on_event)(belle_sip_channel_listener_t *l, belle_sip_channel_t *obj, unsigned revents);
void (*on_message_headers)(belle_sip_channel_listener_t *l, belle_sip_channel_t *obj, belle_sip_message_t *msg);
void (*on_message)(belle_sip_channel_listener_t *l, belle_sip_channel_t *obj, belle_sip_message_t *msg);
void (*on_sending)(belle_sip_channel_listener_t *l, belle_sip_channel_t *obj, belle_sip_message_t *msg);
int (*on_auth_requested)(belle_sip_channel_listener_t *l, belle_sip_channel_t *obj, const char* distinghised_name);
BELLE_SIP_DECLARE_INTERFACE_END
#define BELLE_SIP_CHANNEL_LISTENER(obj) BELLE_SIP_INTERFACE_CAST(obj,belle_sip_channel_listener_t)
#define MAX_CHANNEL_BUFF_SIZE 64000 + 1500 + 1
typedef enum input_stream_state {
WAITING_MESSAGE_START=0
,MESSAGE_AQUISITION=1
,BODY_AQUISITION=2
WAITING_MESSAGE_START,
MESSAGE_AQUISITION,
BODY_AQUISITION
}input_stream_state_t;
typedef enum output_stream_state{
OUTPUT_STREAM_IDLE,
OUTPUT_STREAM_SENDING_HEADERS,
OUTPUT_STREAM_SENDING_BODY
}output_stream_state_t;
typedef struct belle_sip_channel_input_stream{
input_stream_state_t state;
char buff[MAX_CHANNEL_BUFF_SIZE];
char buff[belle_sip_network_buffer_size];
char* read_ptr;
char* write_ptr;
belle_sip_message_t *msg;
unsigned char *body; /*used when receiving a chunked body*/
int content_length;
int chuncked_mode;
int chunk_size;
......@@ -101,8 +106,13 @@ struct belle_sip_channel{
struct addrinfo *peer_list;
struct addrinfo *current_peer;
belle_sip_list_t *outgoing_messages;
belle_sip_list_t* incoming_messages;
belle_sip_message_t *cur_out_message;
output_stream_state_t out_state;
uint8_t *ewouldblock_buffer;
size_t ewouldblock_size;
size_t ewouldblock_offset;
belle_sip_channel_input_stream_t input_stream;
belle_sip_list_t* incoming_messages;
belle_sip_source_t *inactivity_timer;
uint64_t last_recv_time;
int simulated_recv_return; /* used to simulate network error. 0= no data (disconnected) >0= do nothing -1= network error*/
......
......@@ -28,6 +28,12 @@ struct belle_http_callbacks{
void *user_ctx;
};
static void process_response_headers(belle_http_request_listener_t *l, const belle_http_response_event_t *event){
belle_http_callbacks_t *obj=(belle_http_callbacks_t*)l;
if (obj->cbs.process_response_headers)
obj->cbs.process_response_headers(obj->user_ctx,event);
}
static void process_response_event(belle_http_request_listener_t *l, const belle_http_response_event_t *event){
belle_http_callbacks_t *obj=(belle_http_callbacks_t*)l;
if (obj->cbs.process_response)
......@@ -57,6 +63,7 @@ static void process_auth_requested(belle_http_request_listener_t *l, belle_sip_a
/*BELLE_SIP_DECLARE_VPTR(belle_http_callbacks_t);*/
BELLE_SIP_IMPLEMENT_INTERFACE_BEGIN(belle_http_callbacks_t,belle_http_request_listener_t)
process_response_headers,
process_response_event,
process_io_error,
process_timeout,
......
......@@ -33,6 +33,7 @@ static void belle_http_request_destroy(belle_http_request_t *req){
DESTROY_STRING(req,method)
belle_http_request_set_listener(req,NULL);
SET_OBJECT_PROPERTY(req,orig_uri,NULL);
SET_OBJECT_PROPERTY(req,response,NULL);
}
static void belle_http_request_clone(belle_http_request_t *obj, const belle_http_request_t *orig){
......@@ -49,10 +50,7 @@ static belle_sip_error_code belle_http_request_marshal(const belle_http_request_
if (error!=BELLE_SIP_OK) return error;
error=belle_sip_headers_marshal(BELLE_SIP_MESSAGE(request),buff,buff_size,offset);
if (error!=BELLE_SIP_OK) return error;
if (BELLE_SIP_MESSAGE(request)->body) {
error=belle_sip_snprintf(buff,buff_size,offset, "%s",BELLE_SIP_MESSAGE(request)->body);
if (error!=BELLE_SIP_OK) return error;
}
return error;
}
GET_SET_STRING(belle_http_request,method);
......@@ -97,15 +95,11 @@ belle_generic_uri_t *belle_http_request_get_uri(const belle_http_request_t *req)
}
void belle_http_request_set_uri(belle_http_request_t* request, belle_generic_uri_t* uri) {
if (uri) belle_sip_object_ref(uri);
if (request->req_uri) belle_sip_object_unref(request->req_uri);
request->req_uri=uri;
SET_OBJECT_PROPERTY(request,req_uri,uri);
}
void belle_http_request_set_response(belle_http_request_t *req, belle_http_response_t *resp){
if (resp) belle_sip_object_ref(resp);
if (req->response) belle_sip_object_unref(req->response);
req->response=resp;
SET_OBJECT_PROPERTY(req,response,resp);
}
belle_http_response_t *belle_http_request_get_response(belle_http_request_t *req){
......@@ -147,10 +141,7 @@ belle_sip_error_code belle_http_response_marshal(belle_http_response_t *resp, ch
if (error!=BELLE_SIP_OK) return error;
error=belle_sip_headers_marshal(BELLE_SIP_MESSAGE(resp),buff,buff_size,offset);
if (error!=BELLE_SIP_OK) return error;
if (BELLE_SIP_MESSAGE(resp)->body) {
error=belle_sip_snprintf(buff,buff_size,offset, "%s",BELLE_SIP_MESSAGE(resp)->body);
if (error!=BELLE_SIP_OK) return error;
}
return error;
}
......
......@@ -124,7 +124,26 @@ static int http_channel_context_handle_authentication(belle_http_channel_context
if (ev) belle_sip_auth_event_destroy(ev);
return ret;
}
static void http_channel_context_handle_response_headers(belle_http_channel_context_t *ctx , belle_sip_channel_t *chan, belle_http_response_t *response){
belle_http_request_t *req=ctx->pending_requests ? (belle_http_request_t*) ctx->pending_requests->data : NULL;
belle_http_response_event_t ev={0};
int code;
if (req==NULL){
belle_sip_error("Receiving http response headers not matching any request.");
return;
}
code=belle_http_response_get_status_code(response);
if (code!=401 && code!=407){
/*else notify the app about the response headers received*/
ev.source=(belle_sip_object_t*)ctx->provider;
ev.request=req;
ev.response=response;
BELLE_HTTP_REQUEST_INVOKE_LISTENER(req,process_response_headers,&ev);
}
}
static void http_channel_context_handle_response(belle_http_channel_context_t *ctx , belle_sip_channel_t *chan, belle_http_response_t *response){
belle_http_request_t *req=NULL;
belle_http_response_event_t ev={0};
......@@ -173,20 +192,26 @@ static void http_channel_context_handle_io_error(belle_http_channel_context_t *c
ev.transport=belle_sip_channel_get_transport_name(chan);
BELLE_HTTP_REQUEST_INVOKE_LISTENER(req,process_io_error,&ev);
}
}
static int channel_on_event(belle_sip_channel_listener_t *obj, belle_sip_channel_t *chan, unsigned int revents){
/* we are called here by the channel when receiving a message for which a body is expected.
* We can notify the application so that it can setup an appropriate body handler.
*/
static void channel_on_message_headers(belle_sip_channel_listener_t *obj, belle_sip_channel_t *chan, belle_sip_message_t *msg){
belle_http_channel_context_t *ctx=BELLE_HTTP_CHANNEL_CONTEXT(obj);
if (revents & BELLE_SIP_EVENT_READ){
belle_sip_message_t *msg;
while((msg=belle_sip_channel_pick_message(chan))!=NULL){
if (msg && BELLE_SIP_OBJECT_IS_INSTANCE_OF(msg,belle_http_response_t)){
http_channel_context_handle_response(ctx,chan,(belle_http_response_t*)msg);
}
belle_sip_object_unref(msg);
}
}
return 0;
if (BELLE_SIP_OBJECT_IS_INSTANCE_OF(msg,belle_http_response_t)){
http_channel_context_handle_response_headers(ctx,chan,(belle_http_response_t*)msg);
}/*ignore requests*/
}
static void channel_on_message(belle_sip_channel_listener_t *obj, belle_sip_channel_t *chan, belle_sip_message_t *msg){
belle_http_channel_context_t *ctx=BELLE_HTTP_CHANNEL_CONTEXT(obj);
if (BELLE_SIP_OBJECT_IS_INSTANCE_OF(msg,belle_http_response_t)){
http_channel_context_handle_response(ctx,chan,(belle_http_response_t*)msg);
}/*ignore requests*/
}
static int channel_on_auth_requested(belle_sip_channel_listener_t *obj, belle_sip_channel_t *chan, const char* distinguished_name){
......@@ -252,7 +277,8 @@ belle_http_channel_context_t * belle_http_channel_context_new(belle_sip_channel_
BELLE_SIP_IMPLEMENT_INTERFACE_BEGIN(belle_http_channel_context_t,belle_sip_channel_listener_t)
channel_state_changed,
channel_on_event,
channel_on_message_headers,
channel_on_message,
channel_on_sending,
channel_on_auth_requested
BELLE_SIP_IMPLEMENT_INTERFACE_END
......
......@@ -93,8 +93,8 @@ static void belle_sip_headers_container_delete(headers_container_t *obj){
static void belle_sip_message_destroy(belle_sip_message_t *msg){
belle_sip_list_free_with_data(msg->header_list,(void (*)(void*))belle_sip_headers_container_delete);
if (msg->body)
belle_sip_free(msg->body);
if (msg->body_handler)
belle_sip_object_unref(msg->body_handler);
}
/*very sub-optimal clone method */
......@@ -339,6 +339,7 @@ static void belle_sip_request_clone(belle_sip_request_t *request, const belle_si
belle_sip_error_code belle_sip_request_marshal(belle_sip_request_t* request, char* buff, size_t buff_size, size_t *offset) {
belle_sip_error_code error=belle_sip_snprintf(buff,buff_size,offset,"%s ",belle_sip_request_get_method(request));
if (error!=BELLE_SIP_OK) return error;
error=belle_sip_uri_marshal(belle_sip_request_get_uri(request),buff,buff_size,offset);
if (error!=BELLE_SIP_OK) return error;
......@@ -346,10 +347,7 @@ belle_sip_error_code belle_sip_request_marshal(belle_sip_request_t* request, cha
if (error!=BELLE_SIP_OK) return error;
error=belle_sip_headers_marshal(BELLE_SIP_MESSAGE(request),buff,buff_size,offset);
if (error!=BELLE_SIP_OK) return error;
if (BELLE_SIP_MESSAGE(request)->body) {
error=belle_sip_snprintf(buff,buff_size,offset, "%s",BELLE_SIP_MESSAGE(request)->body);
if (error!=BELLE_SIP_OK) return error;
}
return error;
}
......@@ -419,34 +417,39 @@ char *belle_sip_message_to_string(belle_sip_message_t *msg){
return belle_sip_object_to_string(BELLE_SIP_OBJECT(msg));
}
belle_sip_body_handler_t *belle_sip_message_get_body_handler(const belle_sip_message_t *msg){
return msg->body_handler;
}
void belle_sip_message_set_body_handler(belle_sip_message_t *msg, belle_sip_body_handler_t *body_handler){
SET_OBJECT_PROPERTY(msg,body_handler,body_handler);
}
const char* belle_sip_message_get_body(belle_sip_message_t *msg) {
return msg->body;
if (msg->body_handler==NULL) return NULL;
if (BELLE_SIP_OBJECT_IS_INSTANCE_OF(msg->body_handler, belle_sip_memory_body_handler_t)){
return (const char*)belle_sip_memory_body_handler_get_buffer(
BELLE_SIP_MEMORY_BODY_HANDLER(msg->body_handler)
);
}
belle_sip_error("belle_sip_message_get_body(): body cannot be returned as pointer.");
return NULL;
}
unsigned int belle_sip_message_get_body_size(const belle_sip_message_t *msg){
return msg->body_length;
size_t belle_sip_message_get_body_size(const belle_sip_message_t *msg){
if (msg->body_handler==NULL) return 0;
return belle_sip_body_handler_get_size(msg->body_handler);
}
void belle_sip_message_set_body(belle_sip_message_t *msg, const char* body, unsigned int size) {
if (msg->body) {
belle_sip_free(msg->body);
msg->body_length=0;
msg->body=NULL;
}
if (body){
msg->body = belle_sip_malloc(size+1);
msg->body_length=size;
memcpy(msg->body,body,size);
msg->body[size]='\0';
}
belle_sip_body_handler_t *bh=NULL;
if (body && size) bh=(belle_sip_body_handler_t*)belle_sip_memory_body_handler_new_copy_from_buffer(body,size,NULL,NULL);
belle_sip_message_set_body_handler(msg,bh);
}
void belle_sip_message_assign_body(belle_sip_message_t *msg, char* body, unsigned int size) {
if (msg->body) {
belle_sip_free(msg->body);
}
msg->body = body;
msg->body_length = size;
belle_sip_body_handler_t *bh=(belle_sip_body_handler_t*)belle_sip_memory_body_handler_new_from_buffer(body,size,NULL,NULL);
belle_sip_message_set_body_handler(msg,bh);
}
struct _belle_sip_response{
......@@ -541,18 +544,15 @@ static void belle_sip_response_clone(belle_sip_response_t *resp, const belle_sip
belle_sip_error_code belle_sip_response_marshal(belle_sip_response_t *resp, char* buff, size_t buff_size, size_t *offset) {
belle_sip_error_code error=belle_sip_snprintf( buff
,buff_size
,offset
,"SIP/2.0 %i %s\r\n"
,belle_sip_response_get_status_code(resp)
,belle_sip_response_get_reason_phrase(resp)?belle_sip_response_get_reason_phrase(resp):"");
,buff_size
,offset
,"SIP/2.0 %i %s\r\n"
,belle_sip_response_get_status_code(resp)
,belle_sip_response_get_reason_phrase(resp)?belle_sip_response_get_reason_phrase(resp):"");
if (error!=BELLE_SIP_OK) return error;
error=belle_sip_headers_marshal(BELLE_SIP_MESSAGE(resp),buff,buff_size,offset);
if (error!=BELLE_SIP_OK) return error;
if (BELLE_SIP_MESSAGE(resp)->body) {
error=belle_sip_snprintf(buff,buff_size,offset, "%s",BELLE_SIP_MESSAGE(resp)->body);
if (error!=BELLE_SIP_OK) return error;
}
return error;
}
......@@ -782,15 +782,8 @@ int belle_sip_response_fix_contact(const belle_sip_response_t* response,belle_si
belle_sip_request_t * belle_sip_request_clone_with_body(const belle_sip_request_t *initial_req) {
belle_sip_request_t* req=BELLE_SIP_REQUEST(belle_sip_object_clone(BELLE_SIP_OBJECT(initial_req)));
if (belle_sip_message_get_body(BELLE_SIP_MESSAGE(initial_req))) {
belle_sip_header_content_length_t* content_lenth=belle_sip_message_get_header_by_type(initial_req,belle_sip_header_content_length_t);
if (content_lenth)
belle_sip_message_set_body(BELLE_SIP_MESSAGE(req)
,belle_sip_message_get_body(BELLE_SIP_MESSAGE(initial_req))
,belle_sip_header_content_length_get_content_length(content_lenth));
else
belle_sip_error("Cannot clone body from request [%p] because no content lenght header",initial_req);
}
if (initial_req->base.body_handler) req->base.body_handler=BELLE_SIP_BODY_HANDLER(belle_sip_object_clone_and_ref(
(belle_sip_object_t*)initial_req->base.body_handler));
return req;
}
......
......@@ -312,13 +312,13 @@ static void fix_outgoing_via(belle_sip_provider_t *p, belle_sip_channel_t *chan,
}
}
static int channel_on_event(belle_sip_channel_listener_t *obj, belle_sip_channel_t *chan, unsigned int revents){
if (revents & BELLE_SIP_EVENT_READ){
belle_sip_message_t *msg;
while ((msg=belle_sip_channel_pick_message(chan)))
belle_sip_provider_dispatch_message(BELLE_SIP_PROVIDER(obj),msg);
}
return 0;
static void channel_on_message_headers(belle_sip_channel_listener_t *obj, belle_sip_channel_t *chan, belle_sip_message_t *msg){
/*not used*/
}
static void channel_on_message(belle_sip_channel_listener_t *obj, belle_sip_channel_t *chan, belle_sip_message_t *msg){
belle_sip_object_ref(msg);
belle_sip_provider_dispatch_message(BELLE_SIP_PROVIDER(obj),msg);
}
static int channel_on_auth_requested(belle_sip_channel_listener_t *obj, belle_sip_channel_t *chan, const char* distinguished_name){
......@@ -416,7 +416,8 @@ static void channel_on_sending(belle_sip_channel_listener_t *obj, belle_sip_chan
BELLE_SIP_IMPLEMENT_INTERFACE_BEGIN(belle_sip_provider_t,belle_sip_channel_listener_t)
channel_state_changed,
channel_on_event,
channel_on_message_headers,
channel_on_message,
channel_on_sending,
channel_on_auth_requested
BELLE_SIP_IMPLEMENT_INTERFACE_END
......
......@@ -46,8 +46,6 @@ int stream_channel_send(belle_sip_stream_channel_t *obj, const void *buf, size_t
int errnum=get_socket_error();
if (!belle_sip_error_code_is_would_block(errnum)){
belle_sip_error("Could not send stream packet on channel [%p]: %s",obj,belle_sip_get_socket_error_string());
}else{
belle_sip_warning("Channel [%p]: stream_channel_send EWOULDBLOCK",obj);
}
return -errnum;
}
......
......@@ -98,6 +98,8 @@ static void tls_channel_uninit(belle_sip_tls_channel_t *obj){
if (obj->cur_debug_msg)
belle_sip_free(obj->cur_debug_msg);
belle_sip_object_unref(obj->verify_ctx);
if (obj->client_cert_chain) belle_sip_object_unref(obj->client_cert_chain);
if (obj->client_cert_key) belle_sip_object_unref(obj->client_cert_key);
}
static int tls_channel_send(belle_sip_channel_t *obj, const void *buf, size_t buflen){
......@@ -105,6 +107,7 @@ static int tls_channel_send(belle_sip_channel_t *obj, const void *buf, size_t bu
int err = ssl_write(&channel->sslctx,buf,buflen);
if (err<0){
char tmp[256]={0};
if (err==POLARSSL_ERR_NET_WANT_WRITE) return -BELLESIP_EWOULDBLOCK;
error_strerror(err,tmp,sizeof(tmp));
belle_sip_error("Channel [%p]: ssl_write() error [%i]: %s",obj,err,tmp);
}
......@@ -419,16 +422,11 @@ belle_sip_channel_t * belle_sip_channel_new_tls(belle_sip_stack_t *stack, belle_
}
void belle_sip_tls_channel_set_client_certificates_chain(belle_sip_tls_channel_t *channel, belle_sip_certificates_chain_t* cert_chain) {
if (cert_chain) belle_sip_object_ref(cert_chain);
if (channel->client_cert_chain) belle_sip_object_unref(channel->client_cert_chain);
channel->client_cert_chain=cert_chain;
SET_OBJECT_PROPERTY(channel,client_cert_chain,cert_chain);
}
void belle_sip_tls_channel_set_client_certificate_key(belle_sip_tls_channel_t *channel, belle_sip_signing_key_t* key){
if (key) belle_sip_object_ref(key);
if (channel->client_cert_key) belle_sip_object_unref(channel->client_cert_key);
channel->client_cert_key=key;
SET_OBJECT_PROPERTY(channel,client_cert_key,key);
}
......@@ -537,12 +535,12 @@ belle_sip_signing_key_t* belle_sip_signing_key_parse(const char* buff, size_t si
#if POLARSSL_VERSION_NUMBER < 0x01030000
if ((err=x509parse_key(&signing_key->key,(const unsigned char *)buff,size,(const unsigned char*)passwd,passwd?strlen(passwd):0)) <0) {
#else
pk_init(&signing_key->key);
/* for API v1.3 or greater also parses public keys other than RSA */
pk_init(&signing_key->key);
/* for API v1.3 or greater also parses public keys other than RSA */
err=pk_parse_key(&signing_key->key,(const unsigned char *)buff,size,(const unsigned char*)passwd,passwd?strlen(passwd):0);
/* make sure cipher is RSA to be consistent with API v1.2 */
if(err==0 && !pk_can_do(&signing_key->key,POLARSSL_PK_RSA))
err=POLARSSL_ERR_PK_TYPE_MISMATCH;
/* make sure cipher is RSA to be consistent with API v1.2 */
if(err==0 && !pk_can_do(&signing_key->key,POLARSSL_PK_RSA))
err=POLARSSL_ERR_PK_TYPE_MISMATCH;
if (err<0) {
#endif
char tmp[128];
......@@ -567,12 +565,12 @@ belle_sip_signing_key_t* belle_sip_signing_key_parse_file(const char* path,const
#if POLARSSL_VERSION_NUMBER < 0x01030000
if ((err=x509parse_keyfile(&signing_key->key,path, passwd)) <0) {
#else
pk_init(&signing_key->key);
/* for API v1.3 or greater also parses public keys other than RSA */
err=pk_parse_keyfile(&signing_key->key,path, passwd);
/* make sure cipher is RSA to be consistent with API v1.2 */
if(err==0 && !pk_can_do(&signing_key->key,POLARSSL_PK_RSA))
err=POLARSSL_ERR_PK_TYPE_MISMATCH;
pk_init(&signing_key->key);
/* for API v1.3 or greater also parses public keys other than RSA */
err=pk_parse_keyfile(&signing_key->key,path, passwd);
/* make sure cipher is RSA to be consistent with API v1.2 */
if(err==0 && !pk_can_do(&signing_key->key,POLARSSL_PK_RSA))
err=POLARSSL_ERR_PK_TYPE_MISMATCH;
if (err<0) {
#endif
char tmp[128];
......
......@@ -25,6 +25,7 @@
extern const char *root_ca_path;
typedef struct http_counters{
int response_headers_count;
int response_count;
int io_error_count;
int two_hundred;
......@@ -42,20 +43,20 @@ static int wait_for(belle_sip_stack_t*s1,int* counter,int value,int timeout) {
else return TRUE;
}
static void process_response(void *data, const belle_http_response_event_t *event){
http_counters_t *counters=(http_counters_t*)data;
counters->response_count++;
CU_ASSERT_PTR_NOT_NULL(event->response);
if (event->response){
int code=belle_http_response_get_status_code(event->response);
const char *body=belle_sip_message_get_body(BELLE_SIP_MESSAGE(event->response));
belle_sip_body_handler_t *body=belle_sip_message_get_body_handler(BELLE_SIP_MESSAGE(event->response));
if (code>=200 && code <300)
counters->two_hundred++;
else</