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;
}
......
/*
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/>.
*/
#include "belle_sip_internal.h"
/*
* Body handler base class implementation
*/
struct belle_sip_body_handler{
belle_sip_object_t base;
belle_sip_body_handler_progress_callback_t progress_cb;
size_t expected_size; /* 0 if unknown*/
size_t transfered_size;
void *user_data;
};
static void belle_sip_body_handler_clone(belle_sip_body_handler_t *obj, const belle_sip_body_handler_t *orig){
obj->progress_cb=orig->progress_cb;
obj->user_data=orig->user_data;
obj->expected_size=orig->expected_size;
obj->transfered_size=orig->transfered_size;
}
BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(belle_sip_body_handler_t);
BELLE_SIP_INSTANCIATE_CUSTOM_VPTR_BEGIN(belle_sip_body_handler_t)
{
BELLE_SIP_VPTR_INIT(belle_sip_body_handler_t,belle_sip_object_t,TRUE),
(belle_sip_object_destroy_t) NULL,
(belle_sip_object_clone_t) belle_sip_body_handler_clone,
NULL,/*no marshal*/
},
NULL, /*chunk_recv*/
NULL /*chunk_send*/
BELLE_SIP_INSTANCIATE_CUSTOM_VPTR_END
void belle_sip_body_handler_init(belle_sip_body_handler_t *obj, belle_sip_body_handler_progress_callback_t progress_cb, void *user_data){
obj->user_data=user_data;
obj->progress_cb=progress_cb;
}
size_t belle_sip_body_handler_get_size(const belle_sip_body_handler_t *obj){
return obj->expected_size;
}
size_t belle_sip_body_handler_get_transfered_size(const belle_sip_body_handler_t *obj){
return obj->transfered_size;
}
static void update_progress(belle_sip_body_handler_t *obj, belle_sip_message_t *msg){
if (obj->progress_cb)
obj->progress_cb(obj,msg,obj->user_data,obj->transfered_size,obj->expected_size);
}
void belle_sip_body_handler_begin_transfer(belle_sip_body_handler_t *obj){
obj->transfered_size=0;
}
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){
BELLE_SIP_OBJECT_VPTR(obj,belle_sip_body_handler_t)->chunk_recv(obj,msg,obj->transfered_size,buf,size);
obj->transfered_size+=size;
update_progress(obj,msg);
}
int belle_sip_body_handler_send_chunk(belle_sip_body_handler_t *obj, belle_sip_message_t *msg, uint8_t *buf, size_t *size){
int ret;
if (obj->expected_size!=0){
*size=MIN(*size,obj->expected_size-obj->transfered_size);
}
ret=BELLE_SIP_OBJECT_VPTR(obj,belle_sip_body_handler_t)->chunk_send(obj,msg,obj->transfered_size,buf,size);
obj->transfered_size+=*size;
update_progress(obj,msg);
if (obj->expected_size!=0){
if (obj->transfered_size==obj->expected_size)
return BELLE_SIP_STOP;
if (ret==BELLE_SIP_STOP && obj->transfered_size<obj->expected_size){
belle_sip_error("body handler [%p] transfered only [%i] bytes while [%i] were expected",obj,
(int)obj->transfered_size,(int)obj->expected_size);
}
}
return ret;
}
void belle_sip_body_handler_end_transfer(belle_sip_body_handler_t *obj){
if (obj->expected_size==0)
obj->expected_size=obj->transfered_size;
}
/*
* memory body handler implementation.
**/
struct belle_sip_memory_body_handler{
belle_sip_body_handler_t base;
uint8_t *buffer;
size_t size;
};
static void belle_sip_memory_body_handler_destroy(belle_sip_memory_body_handler_t *obj){
if (obj->buffer) belle_sip_free(obj->buffer);
}
static void belle_sip_memory_body_handler_clone(belle_sip_memory_body_handler_t *obj, const belle_sip_memory_body_handler_t *orig){
if (orig->buffer) {
obj->buffer=belle_sip_malloc(orig->size+1);
memcpy(obj->buffer,orig->buffer,orig->size);
obj->buffer[orig->size]='\0';
}
obj->size=orig->size;
}
static void belle_sip_memory_body_handler_recv_chunk(belle_sip_body_handler_t *base, belle_sip_message_t *msg, size_t offset, const uint8_t *buf, size_t size){
belle_sip_memory_body_handler_t *obj=(belle_sip_memory_body_handler_t*)base;
obj->buffer=belle_sip_realloc(obj->buffer,offset+size+1);
memcpy(obj->buffer+offset,buf,size);
obj->buffer[offset+size]='\0';
}
static int belle_sip_memory_body_handler_send_chunk(belle_sip_body_handler_t *base, belle_sip_message_t *msg, size_t offset, uint8_t *buf, size_t *size){
belle_sip_memory_body_handler_t *obj=(belle_sip_memory_body_handler_t*)base;
size_t to_send=MIN(*size,obj->size-offset);
memcpy(buf,obj->buffer+offset,to_send);
*size=to_send;
return (obj->size-offset==*size) ? BELLE_SIP_STOP : BELLE_SIP_CONTINUE;
}
BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(belle_sip_memory_body_handler_t);
BELLE_SIP_INSTANCIATE_CUSTOM_VPTR_BEGIN(belle_sip_memory_body_handler_t)
{
{
BELLE_SIP_VPTR_INIT(belle_sip_memory_body_handler_t,belle_sip_body_handler_t,TRUE),
(belle_sip_object_destroy_t) belle_sip_memory_body_handler_destroy,
(belle_sip_object_clone_t)belle_sip_memory_body_handler_clone,
NULL
},
belle_sip_memory_body_handler_recv_chunk,
belle_sip_memory_body_handler_send_chunk
}
BELLE_SIP_INSTANCIATE_CUSTOM_VPTR_END
const void *belle_sip_memory_body_handler_get_buffer(const belle_sip_memory_body_handler_t *obj){
return obj->buffer;
}
belle_sip_memory_body_handler_t *belle_sip_memory_body_handler_new(belle_sip_body_handler_progress_callback_t cb, void *user_data){
belle_sip_memory_body_handler_t *obj=belle_sip_object_new(belle_sip_memory_body_handler_t);
belle_sip_body_handler_init((belle_sip_body_handler_t*)obj,cb,user_data);
return obj;
}
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){
belle_sip_memory_body_handler_t *obj=belle_sip_object_new(belle_sip_memory_body_handler_t);
belle_sip_body_handler_init((belle_sip_body_handler_t*)obj,cb,user_data);
obj->buffer=(uint8_t*)buffer;
obj->base.expected_size=obj->size=bufsize;
return obj;
}
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){
belle_sip_memory_body_handler_t *obj=belle_sip_object_new(belle_sip_memory_body_handler_t);
belle_sip_body_handler_init((belle_sip_body_handler_t*)obj,cb,user_data);
obj->buffer=(uint8_t*)belle_sip_malloc(bufsize+1);
obj->buffer[bufsize]='\0';
obj->base.expected_size=obj->size=bufsize;
memcpy(obj->buffer,buffer,bufsize);
return obj;
}
/*
* User body handler implementation
*/
struct belle_sip_user_body_handler{
belle_sip_body_handler_t base;
belle_sip_user_body_handler_recv_callback_t recv_cb;
belle_sip_user_body_handler_send_callback_t send_cb;
};
static void belle_sip_user_body_handler_recv_chunk(belle_sip_body_handler_t *base, belle_sip_message_t *msg, size_t offset, const uint8_t *buf, size_t size){
belle_sip_user_body_handler_t *obj=(belle_sip_user_body_handler_t*)base;
if (obj->recv_cb)
obj->recv_cb((belle_sip_user_body_handler_t*)base, msg, base->user_data, offset, buf, size);
else belle_sip_warning("belle_sip_user_body_handler_t ignoring received chunk.");
}
static int belle_sip_user_body_handler_send_chunk(belle_sip_body_handler_t *base, belle_sip_message_t *msg, size_t offset, uint8_t *buf, size_t *size){
belle_sip_user_body_handler_t *obj=(belle_sip_user_body_handler_t*)base;
if (obj->send_cb)
return obj->send_cb((belle_sip_user_body_handler_t*)base, msg, base->user_data, offset, buf, size);
else belle_sip_warning("belle_sip_user_body_handler_t ignoring send chunk.");
*size=0;
return BELLE_SIP_STOP;
}
static void belle_sip_user_body_handler_clone(belle_sip_user_body_handler_t *obj, const belle_sip_user_body_handler_t *orig){
obj->recv_cb=orig->recv_cb;
obj->send_cb=orig->send_cb;
}
BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(belle_sip_user_body_handler_t);
BELLE_SIP_INSTANCIATE_CUSTOM_VPTR_BEGIN(belle_sip_user_body_handler_t)
{
{
BELLE_SIP_VPTR_INIT(belle_sip_user_body_handler_t,belle_sip_body_handler_t,TRUE),
(belle_sip_object_destroy_t) NULL,
(belle_sip_object_clone_t)belle_sip_user_body_handler_clone,
NULL
},
belle_sip_user_body_handler_recv_chunk,
belle_sip_user_body_handler_send_chunk
}
BELLE_SIP_INSTANCIATE_CUSTOM_VPTR_END
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){
belle_sip_user_body_handler_t * obj=belle_sip_object_new(belle_sip_user_body_handler_t);
belle_sip_body_handler_init((belle_sip_body_handler_t*)obj,progress_cb,data);
obj->base.expected_size=total_size;
obj->recv_cb=recv_cb;
obj->send_cb=send_cb;
return obj;
}
/*
* Multipart body handler implementation
* TODO
**/
struct belle_sip_multipart_body_handler{
belle_sip_body_handler_t base;
belle_sip_list_t *parts;
};
static void belle_sip_multipart_body_handler_destroy(belle_sip_multipart_body_handler_t *obj){
belle_sip_list_free_with_data(obj->parts,belle_sip_object_unref);
}
static void belle_sip_multipart_body_handler_clone(belle_sip_multipart_body_handler_t *obj){
obj->parts=belle_sip_list_copy_with_data(obj->parts,(void *(*)(void*))belle_sip_object_clone_and_ref);
}
static void belle_sip_multipart_body_handler_recv_chunk(belle_sip_body_handler_t *obj, belle_sip_message_t *msg, size_t offset,
const uint8_t *buffer, size_t size){
/*TODO*/
}
static int belle_sip_multipart_body_handler_send_chunk(belle_sip_body_handler_t *obj, belle_sip_message_t *msg, size_t offset,
uint8_t *buffer, size_t *size){
/*TODO*/
return BELLE_SIP_STOP;
}
BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(belle_sip_multipart_body_handler_t);
BELLE_SIP_INSTANCIATE_CUSTOM_VPTR_BEGIN(belle_sip_multipart_body_handler_t)
{
{
BELLE_SIP_VPTR_INIT(belle_sip_multipart_body_handler_t,belle_sip_body_handler_t,TRUE),
(belle_sip_object_destroy_t) belle_sip_multipart_body_handler_destroy,
(belle_sip_object_clone_t)belle_sip_multipart_body_handler_clone,
NULL
},
belle_sip_multipart_body_handler_recv_chunk,
belle_sip_multipart_body_handler_send_chunk
}
BELLE_SIP_INSTANCIATE_CUSTOM_VPTR_END
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){
belle_sip_multipart_body_handler_t *obj=belle_sip_object_new(belle_sip_multipart_body_handler_t);
belle_sip_body_handler_init((belle_sip_body_handler_t*)obj,progress_cb,data);
if (first_part) belle_sip_multipart_body_handler_add_part(obj,first_part);
return obj;
}
void belle_sip_multipart_body_handler_add_part(belle_sip_multipart_body_handler_t *obj, belle_sip_body_handler_t *part){
obj->parts=belle_sip_list_append(obj->parts,belle_sip_object_ref(part));
}
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{