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

* 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=\ ...@@ -26,6 +26,7 @@ bellesip_HEADERS=\
http-message.h \ http-message.h \
http-listener.h \ http-listener.h \
generic-uri.h \ generic-uri.h \
types.h types.h \
bodyhandler.h
EXTRA_DIST=$(bellesip_HEADERS) EXTRA_DIST=$(bellesip_HEADERS)
...@@ -41,6 +41,7 @@ ...@@ -41,6 +41,7 @@
#include "belle-sip/http-listener.h" #include "belle-sip/http-listener.h"
#include "belle-sip/http-message.h" #include "belle-sip/http-message.h"
#include "belle-sip/belle-sdp.h" #include "belle-sip/belle-sdp.h"
#include "belle-sip/bodyhandler.h"
#define BELLE_SIP_POINTER_TO_INT(p) ((int)(long)(p)) #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; ...@@ -31,6 +31,7 @@ typedef struct belle_http_response_event belle_http_response_event_t;
#define BELLE_HTTP_INTERFACE_FUNCS(argT) \ #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_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_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); \ 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 ...@@ -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 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 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 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); 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) ...@@ -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_generic_uri_t),
BELLE_SIP_TYPE_ID(belle_http_callbacks_t), BELLE_SIP_TYPE_ID(belle_http_callbacks_t),
BELLE_SIP_TYPE_ID(belle_tls_verify_policy_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 BELLE_SIP_DECLARE_TYPES_END
...@@ -158,6 +163,10 @@ typedef struct _belle_sip_parameters belle_sip_parameters_t; ...@@ -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_param_pair belle_sip_param_pair_t;
typedef struct _belle_sip_header belle_sip_header_t; typedef struct _belle_sip_header belle_sip_header_t;
typedef struct belle_tls_verify_policy belle_tls_verify_policy_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 #endif
......
...@@ -49,7 +49,8 @@ libbellesip_la_SOURCES= \ ...@@ -49,7 +49,8 @@ libbellesip_la_SOURCES= \
generic-uri.c \ generic-uri.c \
http-provider.c \ http-provider.c \
http-message.c \ http-message.c \
http-listener.c http-listener.c \
bodyhandler.c
if BUILD_IOS if BUILD_IOS
......
...@@ -72,9 +72,7 @@ belle_sip_signing_key_t* belle_sip_auth_event_get_signing_key(const belle_sip_au ...@@ -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) { 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); SET_OBJECT_PROPERTY(event,key,value);
event->key=value;
if (event->key) belle_sip_object_ref(event->key);
} }
belle_sip_auth_mode_t belle_sip_auth_event_get_mode(const belle_sip_auth_event_t* event) { 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); ...@@ -587,12 +587,11 @@ void belle_sip_message_init(belle_sip_message_t *message);
struct _belle_sip_message { struct _belle_sip_message {
belle_sip_object_t base; belle_sip_object_t base;
belle_sip_list_t* header_list; belle_sip_list_t* header_list;
char* body; belle_sip_body_handler_t *body_handler;
unsigned int body_length;
}; };
struct _belle_sip_request { struct _belle_sip_request {
belle_sip_message_t message; belle_sip_message_t base;
char* method; char* method;
belle_sip_uri_t* uri; 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*/ 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 ...@@ -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); 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) #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 #endif
...@@ -242,8 +242,9 @@ static int belle_sip_object_data_find(const void* a, const void* b) ...@@ -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) static void belle_sip_object_data_destroy(void* data)
{ {
struct belle_sip_object_data* da = (struct belle_sip_object_data*)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->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 ) 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 *, ...@@ -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){ 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; *front_data=NULL;
return NULL; return NULL;
} }
*front_data=list->data; *front_data=front_elem->data;
list=belle_sip_list_remove_link(list,list); list=belle_sip_list_remove_link(list,front_elem);
belle_sip_free(front_elem);
return list; 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.