Commit 43764778 authored by Ghislain MARY's avatar Ghislain MARY
Browse files

Improve marshalling.

 - Use our own implementation of snprintf() called belle_sip_snprintf() to handle the various native implementations whose return values are not consistent.
 - Simplify error handling in marshalling.
parent 1c7e3e47
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include "belle-sip/defs.h" #include "belle-sip/defs.h"
#include "belle-sip/uri.h" #include "belle-sip/uri.h"
#include "belle-sip/utils.h"
#include <time.h> #include <time.h>
...@@ -75,7 +76,7 @@ typedef struct _belle_sip_header belle_sip_header_t; ...@@ -75,7 +76,7 @@ typedef struct _belle_sip_header belle_sip_header_t;
BELLESIP_EXPORT belle_sip_header_t* belle_sip_header_create (const char* name,const char* value); BELLESIP_EXPORT belle_sip_header_t* belle_sip_header_create (const char* name,const char* value);
BELLESIP_EXPORT const char* belle_sip_header_get_name (const belle_sip_header_t* obj); BELLESIP_EXPORT const char* belle_sip_header_get_name (const belle_sip_header_t* obj);
BELLESIP_EXPORT void belle_sip_header_set_name (belle_sip_header_t* obj,const char* value); BELLESIP_EXPORT void belle_sip_header_set_name (belle_sip_header_t* obj,const char* value);
BELLESIP_EXPORT int belle_sip_header_marshal(belle_sip_header_t* header, char* buff, unsigned int offset,unsigned int buff_size); BELLESIP_EXPORT belle_sip_error_code belle_sip_header_marshal(belle_sip_header_t* header, char* buff, size_t buff_size, unsigned int *offset);
BELLESIP_EXPORT const char *belle_sip_header_get_unparsed_value(belle_sip_header_t* obj); BELLESIP_EXPORT const char *belle_sip_header_get_unparsed_value(belle_sip_header_t* obj);
#define BELLE_SIP_HEADER(t) BELLE_SIP_CAST(t,belle_sip_header_t) #define BELLE_SIP_HEADER(t) BELLE_SIP_CAST(t,belle_sip_header_t)
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#define belle_sip_object_h #define belle_sip_object_h
#include "belle-sip/defs.h" #include "belle-sip/defs.h"
#include "belle-sip/utils.h"
/* /*
* typedefs, macros and functions for object definition and manipulation. * typedefs, macros and functions for object definition and manipulation.
...@@ -113,7 +114,7 @@ typedef struct _belle_sip_object belle_sip_object_t; ...@@ -113,7 +114,7 @@ typedef struct _belle_sip_object belle_sip_object_t;
typedef void (*belle_sip_object_destroy_t)(belle_sip_object_t*); typedef void (*belle_sip_object_destroy_t)(belle_sip_object_t*);
typedef void (*belle_sip_object_clone_t)(belle_sip_object_t* obj, const belle_sip_object_t *orig); typedef void (*belle_sip_object_clone_t)(belle_sip_object_t* obj, const belle_sip_object_t *orig);
typedef int (*belle_sip_object_marshal_t)(belle_sip_object_t* obj, char* buff,unsigned int offset,size_t buff_size); typedef int (*belle_sip_object_marshal_t)(belle_sip_object_t* obj, char* buff, size_t buff_size, unsigned int *offset);
struct _belle_sip_object_vptr{ struct _belle_sip_object_vptr{
belle_sip_type_id_t id; belle_sip_type_id_t id;
...@@ -230,7 +231,7 @@ BELLESIP_EXPORT char* belle_sip_object_to_string(void* obj); ...@@ -230,7 +231,7 @@ BELLESIP_EXPORT char* belle_sip_object_to_string(void* obj);
* Writes a string representation of the object into the supplied buffer. * Writes a string representation of the object into the supplied buffer.
* Same as belle_sip_object_to_string(), but without allocating space for the output string. * Same as belle_sip_object_to_string(), but without allocating space for the output string.
**/ **/
BELLESIP_EXPORT int belle_sip_object_marshal(belle_sip_object_t* obj, char* buff,unsigned int offset,size_t buff_size); BELLESIP_EXPORT belle_sip_error_code belle_sip_object_marshal(belle_sip_object_t* obj, char* buff, size_t buff_size, unsigned int *offset);
BELLESIP_EXPORT int belle_sip_object_is_instance_of(belle_sip_object_t * obj,belle_sip_type_id_t id); BELLESIP_EXPORT int belle_sip_object_is_instance_of(belle_sip_object_t * obj,belle_sip_type_id_t id);
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#ifndef PARAMETERS_H_ #ifndef PARAMETERS_H_
#define PARAMETERS_H_ #define PARAMETERS_H_
#include "belle-sip/utils.h"
#include "belle-sip/list.h" #include "belle-sip/list.h"
/*** /***
* parameters * parameters
...@@ -51,7 +52,7 @@ BELLESIP_EXPORT const belle_sip_list_t * belle_sip_parameters_get_parameters(con ...@@ -51,7 +52,7 @@ BELLESIP_EXPORT const belle_sip_list_t * belle_sip_parameters_get_parameters(con
BELLESIP_EXPORT void belle_sip_parameters_remove_parameter(belle_sip_parameters_t* obj,const char* name); BELLESIP_EXPORT void belle_sip_parameters_remove_parameter(belle_sip_parameters_t* obj,const char* name);
BELLESIP_EXPORT int belle_sip_parameters_marshal(const belle_sip_parameters_t* obj, char* buff,unsigned int offset,unsigned int buff_size); BELLESIP_EXPORT belle_sip_error_code belle_sip_parameters_marshal(const belle_sip_parameters_t* obj, char* buff, size_t buff_size, unsigned int *offset);
#define BELLE_SIP_PARAMETERS(obj) BELLE_SIP_CAST(obj,belle_sip_parameters_t) #define BELLE_SIP_PARAMETERS(obj) BELLE_SIP_CAST(obj,belle_sip_parameters_t)
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "belle-sip/defs.h" #include "belle-sip/defs.h"
#include "belle-sip/list.h" #include "belle-sip/list.h"
#include "belle-sip/utils.h"
/*inherite from belle_sip_parameters_t*/ /*inherite from belle_sip_parameters_t*/
typedef struct _belle_sip_uri belle_sip_uri_t; typedef struct _belle_sip_uri belle_sip_uri_t;
...@@ -184,7 +185,7 @@ BELLESIP_EXPORT void belle_sip_uri_fix(belle_sip_uri_t *uri); ...@@ -184,7 +185,7 @@ BELLESIP_EXPORT void belle_sip_uri_fix(belle_sip_uri_t *uri);
*/ */
BELLESIP_EXPORT char* belle_sip_uri_to_string(belle_sip_uri_t* uri) ; BELLESIP_EXPORT char* belle_sip_uri_to_string(belle_sip_uri_t* uri) ;
int belle_sip_uri_marshal(const belle_sip_uri_t* uri, char* buff,unsigned int offset,unsigned int buff_size); belle_sip_error_code belle_sip_uri_marshal(const belle_sip_uri_t* uri, char* buff, size_t buff_size, unsigned int *offset);
#define BELLE_SIP_URI(obj) BELLE_SIP_CAST(obj,belle_sip_uri_t) #define BELLE_SIP_URI(obj) BELLE_SIP_CAST(obj,belle_sip_uri_t)
......
...@@ -41,6 +41,13 @@ typedef enum { ...@@ -41,6 +41,13 @@ typedef enum {
typedef void (*belle_sip_log_function_t)(belle_sip_log_level lev, const char *fmt, va_list args); typedef void (*belle_sip_log_function_t)(belle_sip_log_level lev, const char *fmt, va_list args);
typedef enum {
BELLE_SIP_NOT_IMPLEMENTED = -2,
BELLE_SIP_BUFFER_OVERFLOW = -1,
BELLE_SIP_OK = 0
} belle_sip_error_code;
#ifdef __GNUC__ #ifdef __GNUC__
#define BELLE_SIP_CHECK_FORMAT_ARGS(m,n) __attribute__((format(printf,m,n))) #define BELLE_SIP_CHECK_FORMAT_ARGS(m,n) __attribute__((format(printf,m,n)))
#else #else
...@@ -137,6 +144,8 @@ BELLESIP_EXPORT void belle_sip_set_log_handler(belle_sip_log_function_t func); ...@@ -137,6 +144,8 @@ BELLESIP_EXPORT void belle_sip_set_log_handler(belle_sip_log_function_t func);
BELLESIP_EXPORT char * BELLE_SIP_CHECK_FORMAT_ARGS(1,2) belle_sip_strdup_printf(const char *fmt,...); BELLESIP_EXPORT char * BELLE_SIP_CHECK_FORMAT_ARGS(1,2) belle_sip_strdup_printf(const char *fmt,...);
BELLESIP_EXPORT belle_sip_error_code belle_sip_snprintf(char *buff, unsigned int buff_size, unsigned int *offset, const char *fmt, ...);
BELLESIP_EXPORT void belle_sip_set_log_level(int level); BELLESIP_EXPORT void belle_sip_set_log_level(int level);
BELLESIP_EXPORT char * belle_sip_random_token(char *ret, size_t size); BELLESIP_EXPORT char * belle_sip_random_token(char *ret, size_t size);
......
This diff is collapsed.
This diff is collapsed.
...@@ -129,8 +129,8 @@ static void _belle_sip_object_clone(belle_sip_object_t *obj, const belle_sip_obj ...@@ -129,8 +129,8 @@ static void _belle_sip_object_clone(belle_sip_object_t *obj, const belle_sip_obj
if (orig->name!=NULL) obj->name=belle_sip_strdup(obj->name); if (orig->name!=NULL) obj->name=belle_sip_strdup(obj->name);
} }
static int _belle_object_marshall(belle_sip_object_t* obj, char* buff,unsigned int offset,size_t buff_size) { static belle_sip_error_code _belle_object_marshal(belle_sip_object_t* obj, char* buff, size_t buff_size, unsigned int *offset) {
return snprintf(buff+offset,buff_size,"{%s::%s %p}",obj->vptr->type_name,obj->name ? obj->name : "(no name)",obj); return belle_sip_snprintf(buff,buff_size,offset,"{%s::%s %p}",obj->vptr->type_name,obj->name ? obj->name : "(no name)",obj);
} }
belle_sip_object_vptr_t belle_sip_object_t_vptr={ belle_sip_object_vptr_t belle_sip_object_t_vptr={
...@@ -141,7 +141,7 @@ belle_sip_object_vptr_t belle_sip_object_t_vptr={ ...@@ -141,7 +141,7 @@ belle_sip_object_vptr_t belle_sip_object_t_vptr={
NULL, NULL,
_belle_sip_object_uninit, _belle_sip_object_uninit,
_belle_sip_object_clone, _belle_sip_object_clone,
_belle_object_marshall _belle_object_marshal
}; };
void belle_sip_object_delete(void *ptr){ void belle_sip_object_delete(void *ptr){
...@@ -264,60 +264,57 @@ const char* belle_sip_object_get_name(belle_sip_object_t* object) { ...@@ -264,60 +264,57 @@ const char* belle_sip_object_get_name(belle_sip_object_t* object) {
#if CHECKED_MARSHAL #if CHECKED_MARSHAL
static int checked_marshal(belle_sip_object_vptr_t *vptr, belle_sip_object_t* obj, char* buff,unsigned int offset,size_t buff_size){ static belle_sip_error_code checked_marshal(belle_sip_object_vptr_t *vptr, belle_sip_object_t* obj, char* buff, size_t buff_size, unsigned int *offset){
int tmp_buf_size=buff_size*2; int tmp_buf_size=buff_size*2;
char *p=(char*)belle_sip_malloc0(tmp_buf_size); char *p=(char*)belle_sip_malloc0(tmp_buf_size);
int i; int i;
int ret=vptr->marshal(obj,p,offset,buff_size); unsigned int initial_offset=*offset;
belle_sip_error_code error=vptr->marshal(obj,p,buff_size,offset);
int written; int written;
for (i=offset;i<buff_size;++i){ if (error==BELLE_SIP_BUFFER_OVERFLOW){
if (p[i]=='\0') break; belle_sip_fatal("Object of type %s commited a buffer overflow by marshalling %i bytes",
} vptr->type_name,*offset-initial_offset);
written=i-offset; } else if (error!=BELLE_SIP_OK){
if (written>(buff_size-offset)){ belle_sip_fatal("Object of type %s produced an error during marshalling: %i",
belle_sip_fatal("Object of type %s commited a buffer overflow by marshalling %i bytes ", vptr->type_name,error);
vptr->type_name,written); }
} memcpy(buff+initial_offset,p,*offset-initial_offset);
if (written!=ret && written!=(buff_size-offset-1)){ /*this is because snprintf won't allow you to write a non null character at the end of the buffer*/
belle_sip_fatal("Object of type %s marshalled %i bytes but said it marshalled %i bytes !",
vptr->type_name,written,ret);
}
memcpy(buff+offset,p+offset,ret);
belle_sip_free(p); belle_sip_free(p);
return ret; return ret;
} }
#endif #endif
int belle_sip_object_marshal(belle_sip_object_t* obj, char* buff,unsigned int offset,size_t buff_size) { belle_sip_error_code belle_sip_object_marshal(belle_sip_object_t* obj, char* buff, size_t buff_size, unsigned int *offset) {
belle_sip_object_vptr_t *vptr=obj->vptr; belle_sip_object_vptr_t *vptr=obj->vptr;
while (vptr != NULL) { while (vptr != NULL) {
if (vptr->marshal != NULL) { if (vptr->marshal != NULL) {
#if CHECKED_MARSHAL #if CHECKED_MARSHAL
return checked_marshal(vptr,obj,buff,offset,buff_size); return checked_marshal(vptr,obj,buff,buff_size,offset);
#else #else
return vptr->marshal(obj,buff,offset,buff_size); return vptr->marshal(obj,buff,buff_size,offset);
#endif #endif
} else { } else {
vptr=vptr->parent; vptr=vptr->parent;
} }
} }
return -1; /*no implementation found*/ return BELLE_SIP_NOT_IMPLEMENTED; /*no implementation found*/
} }
static char * belle_sip_object_to_alloc_string(belle_sip_object_t *obj, int size_hint){ static char * belle_sip_object_to_alloc_string(belle_sip_object_t *obj, int size_hint){
char *buf=belle_sip_malloc(size_hint); char *buf=belle_sip_malloc(size_hint);
int size = belle_sip_object_marshal(obj,buf,0,size_hint-1); unsigned int offset=0;
belle_sip_error_code error = belle_sip_object_marshal(obj,buf,size_hint-1,&offset);
obj->vptr->tostring_bufsize_hint=size_hint; obj->vptr->tostring_bufsize_hint=size_hint;
if (size>=size_hint-1){ if (error==BELLE_SIP_BUFFER_OVERFLOW){
belle_sip_message("belle_sip_object_to_alloc_string(): hint buffer was too short while doing to_string() for %s, retrying", obj->vptr->type_name); belle_sip_message("belle_sip_object_to_alloc_string(): hint buffer was too short while doing to_string() for %s, retrying", obj->vptr->type_name);
belle_sip_free(buf); belle_sip_free(buf);
return belle_sip_object_to_alloc_string(obj,2*size_hint); return belle_sip_object_to_alloc_string(obj,2*size_hint);
} }
buf[size]='\0'; buf=belle_sip_realloc(buf,offset+1);
buf=belle_sip_realloc(buf,size+1); buf[offset]='\0';
return buf; return buf;
} }
...@@ -333,13 +330,14 @@ char* belle_sip_object_to_string(void* _obj) { ...@@ -333,13 +330,14 @@ char* belle_sip_object_to_string(void* _obj) {
return belle_sip_object_to_alloc_string(obj,obj->vptr->tostring_bufsize_hint); return belle_sip_object_to_alloc_string(obj,obj->vptr->tostring_bufsize_hint);
}else{ }else{
char buff[BELLE_SIP_MAX_TO_STRING_SIZE]; char buff[BELLE_SIP_MAX_TO_STRING_SIZE];
int size = belle_sip_object_marshal(obj,buff,0,sizeof(buff)); unsigned int offset=0;
if (size>=sizeof(buff)-1){ belle_sip_error_code error = belle_sip_object_marshal(obj,buff,sizeof(buff),&offset);
if (error==BELLE_SIP_BUFFER_OVERFLOW){
belle_sip_message("belle_sip_object_to_string(): temporary buffer is too short while doing to_string() for %s, retrying", obj->vptr->type_name); belle_sip_message("belle_sip_object_to_string(): temporary buffer is too short while doing to_string() for %s, retrying", obj->vptr->type_name);
return belle_sip_object_to_alloc_string(obj,get_hint_size(2*size)); return belle_sip_object_to_alloc_string(obj,get_hint_size(2*offset));
} }
buff[size]='\0'; buff[offset]='\0';
obj->vptr->tostring_bufsize_hint=get_hint_size(2*size); obj->vptr->tostring_bufsize_hint=get_hint_size(2*offset);
return belle_sip_strdup(buff); return belle_sip_strdup(buff);
} }
} }
...@@ -350,26 +348,26 @@ char * _belle_sip_object_describe_type(belle_sip_object_vptr_t *vptr){ ...@@ -350,26 +348,26 @@ char * _belle_sip_object_describe_type(belle_sip_object_vptr_t *vptr){
belle_sip_object_vptr_t *it; belle_sip_object_vptr_t *it;
int pos=0; int pos=0;
belle_sip_list_t *l=NULL,*elem; belle_sip_list_t *l=NULL,*elem;
pos+=snprintf(ret+pos,maxbufsize-pos,"Ownership:\n"); belle_sip_snprintf(ret,maxbufsize,&pos,"Ownership:\n");
pos+=snprintf(ret+pos,maxbufsize-pos,"\t%s is created initially %s\n",vptr->type_name, belle_sip_snprintf(ret,maxbufsize,&pos,"\t%s is created initially %s\n",vptr->type_name,
vptr->initially_unowned ? "unowned" : "owned"); vptr->initially_unowned ? "unowned" : "owned");
pos+=snprintf(ret+pos,maxbufsize-pos,"\nInheritance diagram:\n"); belle_sip_snprintf(ret,maxbufsize,&pos,"\nInheritance diagram:\n");
for(it=vptr;it!=NULL;it=it->parent){ for(it=vptr;it!=NULL;it=it->parent){
l=belle_sip_list_prepend(l,it); l=belle_sip_list_prepend(l,it);
} }
for(elem=l;elem!=NULL;elem=elem->next){ for(elem=l;elem!=NULL;elem=elem->next){
it=(belle_sip_object_vptr_t*)elem->data; it=(belle_sip_object_vptr_t*)elem->data;
pos+=snprintf(ret+pos,maxbufsize-pos,"\t%s\n",it->type_name); belle_sip_snprintf(ret,maxbufsize,&pos,"\t%s\n",it->type_name);
if (elem->next) if (elem->next)
pos+=snprintf(ret+pos,maxbufsize-pos,"\t |\n"); belle_sip_snprintf(ret,maxbufsize,&pos,"\t |\n");
} }
belle_sip_list_free(l); belle_sip_list_free(l);
pos+=snprintf(ret+pos,maxbufsize-pos,"\nImplemented interfaces:\n"); belle_sip_snprintf(ret,maxbufsize,&pos,"\nImplemented interfaces:\n");
for(it=vptr;it!=NULL;it=it->parent){ for(it=vptr;it!=NULL;it=it->parent){
belle_sip_interface_desc_t **desc=it->interfaces; belle_sip_interface_desc_t **desc=it->interfaces;
if (desc!=NULL){ if (desc!=NULL){
for(;*desc!=NULL;desc++){ for(;*desc!=NULL;desc++){
pos+=snprintf(ret+pos,maxbufsize-pos,"\t* %s\n",(*desc)->ifname); belle_sip_snprintf(ret,maxbufsize,&pos,"\t* %s\n",(*desc)->ifname);
} }
} }
} }
......
...@@ -41,19 +41,19 @@ static void belle_sip_parameters_clone(belle_sip_parameters_t *params, const bel ...@@ -41,19 +41,19 @@ static void belle_sip_parameters_clone(belle_sip_parameters_t *params, const bel
} }
} }
int belle_sip_parameters_marshal(const belle_sip_parameters_t* params, char* buff,unsigned int offset,unsigned int buff_size) { belle_sip_error_code belle_sip_parameters_marshal(const belle_sip_parameters_t* params, char* buff,unsigned int buff_size,unsigned int *offset) {
belle_sip_list_t* list=params->param_list; belle_sip_list_t* list=params->param_list;
unsigned int current_offset=offset; belle_sip_error_code error=BELLE_SIP_OK;
for(;list!=NULL;list=list->next){ for(;list!=NULL;list=list->next){
belle_sip_param_pair_t* container = (belle_sip_param_pair_t* )(list->data); belle_sip_param_pair_t* container = (belle_sip_param_pair_t* )(list->data);
if (container->value) { if (container->value) {
current_offset+=snprintf(buff+current_offset,buff_size-current_offset,";%s=%s",container->name,container->value); error=belle_sip_snprintf(buff,buff_size,offset,";%s=%s",container->name,container->value);
} else { } else {
current_offset+=snprintf(buff+current_offset,buff_size-current_offset,";%s",container->name); error=belle_sip_snprintf(buff,buff_size,offset,";%s",container->name);
} }
if (current_offset>=buff_size) return buff_size-offset; if (error!=BELLE_SIP_OK) return error;
} }
return current_offset-offset; return error;
} }
BELLE_SIP_NEW_HEADER(parameters,header,"parameters") BELLE_SIP_NEW_HEADER(parameters,header,"parameters")
const belle_sip_list_t * belle_sip_parameters_get_parameters(const belle_sip_parameters_t* obj) { const belle_sip_list_t * belle_sip_parameters_get_parameters(const belle_sip_parameters_t* obj) {
......
...@@ -69,48 +69,48 @@ static void belle_sip_uri_clone(belle_sip_uri_t* uri, const belle_sip_uri_t *ori ...@@ -69,48 +69,48 @@ static void belle_sip_uri_clone(belle_sip_uri_t* uri, const belle_sip_uri_t *ori
} }
int belle_sip_uri_marshal(const belle_sip_uri_t* uri, char* buff,unsigned int offset,unsigned int buff_size) { belle_sip_error_code belle_sip_uri_marshal(const belle_sip_uri_t* uri, char* buff, size_t buff_size, unsigned int *offset) {
unsigned int current_offset=offset;
const belle_sip_list_t* list=belle_sip_parameters_get_parameters(uri->header_list); const belle_sip_list_t* list=belle_sip_parameters_get_parameters(uri->header_list);
belle_sip_error_code error=BELLE_SIP_OK;
current_offset+=snprintf(buff+current_offset,buff_size-current_offset,"%s:",uri->secure?"sips":"sip"); error=belle_sip_snprintf(buff,buff_size,offset,"%s:",uri->secure?"sips":"sip");
if (current_offset>=buff_size) return buff_size-offset; if (error!=BELLE_SIP_OK) return error;
if (uri->user) { if (uri->user) {
char* escaped_username=belle_sip_to_escaped_string(uri->user); char* escaped_username=belle_sip_to_escaped_string(uri->user);
current_offset+=snprintf(buff+current_offset,buff_size-current_offset,"%s@",escaped_username); error=belle_sip_snprintf(buff,buff_size,offset,"%s@",escaped_username);
belle_sip_free(escaped_username); belle_sip_free(escaped_username);
if (current_offset>=buff_size) return buff_size-offset; if (error!=BELLE_SIP_OK) return error;
} }
if (uri->host) { if (uri->host) {
if (strchr(uri->host,':')) { /*ipv6*/ if (strchr(uri->host,':')) { /*ipv6*/
current_offset+=snprintf(buff+current_offset,buff_size-current_offset,"[%s]",uri->host); error=belle_sip_snprintf(buff,buff_size,offset,"[%s]",uri->host);
} else { } else {
current_offset+=snprintf(buff+current_offset,buff_size-current_offset,"%s",uri->host); error=belle_sip_snprintf(buff,buff_size,offset,"%s",uri->host);
} }
if (current_offset>=buff_size) return buff_size-offset; if (error!=BELLE_SIP_OK) return error;
} else { } else {
belle_sip_warning("no host found in this uri"); belle_sip_warning("no host found in this uri");
} }
if (uri->port>0) { if (uri->port>0) {
current_offset+=snprintf(buff+current_offset,buff_size-current_offset,":%i",uri->port); error=belle_sip_snprintf(buff,buff_size,offset,":%i",uri->port);
if (current_offset>=buff_size) return buff_size-offset; if (error!=BELLE_SIP_OK) return error;
} }
current_offset+=belle_sip_parameters_marshal(&uri->params,buff,current_offset,buff_size); error=belle_sip_parameters_marshal(&uri->params,buff,buff_size,offset);
if (current_offset>=buff_size) return buff_size-offset; if (error!=BELLE_SIP_OK) return error;
for(;list!=NULL;list=list->next){ for(;list!=NULL;list=list->next){
belle_sip_param_pair_t* container = list->data; belle_sip_param_pair_t* container = list->data;
if (list == belle_sip_parameters_get_parameters(uri->header_list)) { if (list == belle_sip_parameters_get_parameters(uri->header_list)) {
//first case //first case
current_offset+=snprintf(buff+current_offset,buff_size-current_offset,"?%s=%s",container->name,container->value); error=belle_sip_snprintf(buff,buff_size,offset,"?%s=%s",container->name,container->value);
} else { } else {
//subsequent headers //subsequent headers
current_offset+=snprintf(buff+current_offset,buff_size-current_offset,"&%s=%s",container->name,container->value); error=belle_sip_snprintf(buff,buff_size,offset,"&%s=%s",container->name,container->value);
} }
if (current_offset>=buff_size) return buff_size-offset; if (error!=BELLE_SIP_OK) return error;
} }
return current_offset-offset; return error;
} }
BELLE_SIP_PARSE(uri); BELLE_SIP_PARSE(uri);
......
...@@ -106,6 +106,23 @@ char *belle_sip_strdup_printf(const char *fmt,...){ ...@@ -106,6 +106,23 @@ char *belle_sip_strdup_printf(const char *fmt,...){
return ret; return ret;
} }
belle_sip_error_code belle_sip_snprintf(char *buff, unsigned int buff_size, unsigned int *offset, const char *fmt, ...) {
int ret;
belle_sip_error_code error = BELLE_SIP_OK;
va_list args;
va_start(args, fmt);
ret = vsnprintf(buff + *offset, buff_size - *offset, fmt, args);
if ((ret < 0)
|| (ret >= (buff_size - *offset))) {
error = BELLE_SIP_BUFFER_OVERFLOW;
*offset = buff_size;
} else {
*offset += ret;
}
va_end(args);
return error;
}
#if defined(WIN32) || defined(_WIN32_WCE) #if defined(WIN32) || defined(_WIN32_WCE)
#define ENDLINE "\r\n" #define ENDLINE "\r\n"
#else #else
......
...@@ -458,12 +458,13 @@ void channel_set_state(belle_sip_channel_t *obj, belle_sip_channel_state_t state ...@@ -458,12 +458,13 @@ void channel_set_state(belle_sip_channel_t *obj, belle_sip_channel_state_t state
static void _send_message(belle_sip_channel_t *obj, belle_sip_message_t *msg){ static void _send_message(belle_sip_channel_t *obj, belle_sip_message_t *msg){
char buffer[belle_sip_network_buffer_size]; char buffer[belle_sip_network_buffer_size];
int len; unsigned int len=0;
int ret=0; int ret=0;
belle_sip_error_code error=BELLE_SIP_OK;
BELLE_SIP_INVOKE_LISTENERS_ARG1_ARG2(obj->listeners,belle_sip_channel_listener_t,on_sending,obj,msg); BELLE_SIP_INVOKE_LISTENERS_ARG1_ARG2(obj->listeners,belle_sip_channel_listener_t,on_sending,obj,msg);
len=belle_sip_object_marshal((belle_sip_object_t*)msg,buffer,0,sizeof(buffer)); error=belle_sip_object_marshal((belle_sip_object_t*)msg,buffer,sizeof(buffer),&len);
if (len>0){ if ((error==BELLE_SIP_OK) && (len>0)){
if (!obj->stack->send_error) if (!obj->stack->send_error)
ret=belle_sip_channel_send(obj,buffer,len); ret=belle_sip_channel_send(obj,buffer,len);
else else
......
...@@ -197,8 +197,8 @@ void belle_sip_message_remove_header(belle_sip_message_t *msg, const char *heade ...@@ -197,8 +197,8 @@ void belle_sip_message_remove_header(belle_sip_message_t *msg, const char *heade
/* /*
int belle_sip_message_named_headers_marshal(belle_sip_message_t *message, const char* header_name, char* buff,unsigned int offset,unsigned int buff_size) { belle_sip_error_code belle_sip_message_named_headers_marshal(belle_sip_message_t *message, const char* header_name, char* buff, size_t buff_size, unsigned int *offset) {
unsigned int current_offset=offset; belle_sip_error_code error=BELLE_SIP_OK;
belle_sip_list_t* header_list = belle_sip_message_get_headers(message,header_name); belle_sip_list_t* header_list = belle_sip_message_get_headers(message,header_name);
if (!header_list) { if (!header_list) {
belle_sip_error("headers [%s] not found",header_name); belle_sip_error("headers [%s] not found",header_name);
...@@ -206,10 +206,12 @@ int belle_sip_message_named_headers_marshal(belle_sip_message_t *message, const ...@@ -206,10 +206,12 @@ int belle_sip_message_named_headers_marshal(belle_sip_message_t *message, const
} }
for(;header_list!=NULL;header_list=header_list->next){ for(;header_list!=NULL;header_list=header_list->next){
belle_sip_header_t *h=BELLE_SIP_HEADER(header_list->data); belle_sip_header_t *h=BELLE_SIP_HEADER(header_list->data);
current_offset+=belle_sip_object_marshal(BELLE_SIP_OBJECT(h),buff,current_offset,buff_size); error=belle_sip_object_marshal(BELLE_SIP_OBJECT(h),buff,buff_size,offset);
current_offset+=snprintf(buff+current_offset,buff_size-current_offset,"%s","\r\n"); if (error!=BELLE_SIP_OK) return error;
error=belle_sip_snprintf(buff,buff_size,offset,"%s","\r\n");
if (error!=BELLE_SIP_OK) return error;
} }
return current_offset-offset; return error;
} }
#define MARSHAL_AND_CHECK_HEADER(header) \ #define MARSHAL_AND_CHECK_HEADER(header) \
...@@ -244,25 +246,25 @@ belle_sip_list_t* belle_sip_message_get_all_headers(const belle_sip_message_t *m ...@@ -244,25 +246,25 @@ belle_sip_list_t* belle_sip_message_get_all_headers(const belle_sip_message_t *m
return headers; return headers;
} }
in