Commit 03476a93 authored by Simon Morlat's avatar Simon Morlat

Feature/object++

parent 536c7c30
......@@ -183,10 +183,10 @@ else()
endif()
if(ENABLE_STRICT)
list(APPEND STRICT_OPTIONS_CPP "-Werror" "-Wextra" "-Wno-unused-parameter" "-Wno-error=unknown-pragmas" "-Wuninitialized" "-fno-strict-aliasing")
list(APPEND STRICT_OPTIONS_C "-Wstrict-prototypes -Wno-missing-field-initializers" "-Wno-error=unused-result")
list(APPEND STRICT_OPTIONS_C " -Wno-missing-field-initializers" "-Wno-error=unused-result")
endif()
# this warning is generated by antlr so ignore it for now
list(APPEND STRICT_OPTIONS_C "-Wno-strict-prototypes" "-Wno-error=sign-compare")
list(APPEND STRICT_OPTIONS_C "-Wno-error=sign-compare")
endif()
if(STRICT_OPTIONS_CPP)
list(REMOVE_DUPLICATES STRICT_OPTIONS_CPP)
......
......@@ -167,19 +167,14 @@ BELLE_SIP_END_DECLS
#ifndef BELLE_SIP_USE_STL
#define BELLE_SIP_USE_STL 1
#endif
#if __cplusplus >= 201103L && BELLE_SIP_USE_STL
#if ((defined(WIN32) && defined(__cplusplus)) || __cplusplus >= 201103L) && BELLE_SIP_USE_STL
/*Only Visual Studio 2018 properly defines __cplusplus according to c++ level. */
#include <functional>
typedef std::function<int (unsigned int)> belle_sip_source_cpp_func_t;
BELLESIP_EXPORT inline int belle_sip_source_cpp_func(belle_sip_source_cpp_func_t* user_data, unsigned int events)
{
int result = (*user_data)(events);
return result;
}
BELLESIP_EXPORT inline void belle_sip_source_on_remove(belle_sip_source_t* source)
{
delete static_cast<belle_sip_source_cpp_func_t *>(belle_sip_source_get_user_data(source));
belle_sip_source_set_user_data(source,NULL);
}
/*purpose of this function is to simplify c++ timer integration.
* ex:
......@@ -196,19 +191,13 @@ BELLESIP_EXPORT inline void belle_sip_source_on_remove(belle_sip_source_t* sourc
*
*/
BELLESIP_EXPORT inline belle_sip_source_t * belle_sip_main_loop_create_cpp_timeout(belle_sip_main_loop_t *ml
, belle_sip_source_cpp_func_t *func
, unsigned int timeout_value_ms
, const char* timer_name)
{
belle_sip_source_t* source = belle_sip_main_loop_create_timeout( ml
, (belle_sip_source_func_t)belle_sip_source_cpp_func
, func
, timeout_value_ms
, timer_name);
belle_sip_source_set_remove_cb(source,belle_sip_source_on_remove);
return source;
}
BELLESIP_EXPORT belle_sip_source_t * belle_sip_main_loop_create_cpp_timeout(belle_sip_main_loop_t *ml
, belle_sip_source_cpp_func_t *func
, unsigned int timeout_value_ms
, const char* timer_name);
BELLESIP_EXPORT void belle_sip_main_loop_cpp_do_later(belle_sip_main_loop_t *ml, const std::function<void (void)> &func);
#endif
......
/*
belle-sip - SIP (RFC3261) library.
Copyright (C) 2019 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 2 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/object.h"
#include <memory>
#include <functional>
namespace bellesip{
class ObjectCAccessors;
class BELLESIP_EXPORT Object{
friend ObjectCAccessors;
public:
Object();
Object *ref();
void unref();
virtual belle_sip_error_code marshal(char* buff, size_t buff_size, size_t *offset);
std::string toString()const{
std::string ret(belle_sip_object_to_string(&mObject));
return ret;
}
virtual Object *clone()const;
belle_sip_object_t *getCObject();
const belle_sip_object_t *getCObject()const;
void *getCPtr(){
return static_cast<void*>(getCObject());
}
const void *getCPtr()const{
return static_cast<const void*>(getCObject());
}
static Object *getCppObject(void *);
static const Object *getCppObject(const void *);
protected:
virtual ~Object(); /*the destructor must be kept protected, never public, including for all classes inherting from this*/
Object(const Object &other);
private:
void init();
belle_sip_object_t mObject;
static belle_sip_object_t *sClone(belle_sip_object_t *);
static belle_sip_error_code sMarshal(belle_sip_object_t* obj, char* buff, size_t buff_size, size_t *offset);
};
/**
* Template class to help define an Object usable in both C and C++
* The template arguments are:
* - _CType : the type used to represent this object in C
* - _CppType : the type used in C++ to implement this object. _CppType is used to be set to the type
* of the class inheriting from HybridObject.
* Example:
* typedef struct _CExample CExample;
* class Example : public HybridObject<CExample, Example>{
* ...
* }
* The C object can be obtained with toC() method, directly casted in the expected type.
* The C++ object can be obtained from C object with static method toCpp().
* The destructor must be kept protected so that no one can call delete operator on the object. Instead unref() must be used.
*
* Rational for using this template:
* - You have an existing library in C where all C objects are inheriting from belle_sip_object_t (for refcounting, data_set etc...).
* - You want to use C++ in your library without making any disruption in the API.
* If you don't care about belle_sip_object_t inheritance in your C api, don't use this.
* An usage example is shown in tester/object_tester.cc .
**/
template <typename _CType, typename _CppType>
class BELLESIP_EXPORT HybridObject : public Object{
public:
HybridObject(){
}
_CType *toC(){
return static_cast<_CType*>(getCPtr());
}
const _CType *toC()const{
return static_cast<const _CType*>(getCPtr());
}
static _CppType *toCpp(_CType *ptr){
return static_cast<_CppType *>(getCppObject(ptr));
}
static const _CppType *toCpp(const _CType *ptr){
return static_cast<const _CppType *>(getCppObject(ptr));
}
protected:
virtual ~HybridObject() = default;
HybridObject(const HybridObject<_CType, _CppType> &other) : Object(other){
}
};
/**
* Convenience function to create a std::shared_ptr that calls Object::unref() instead of delete expression.
*/
template <typename _T, typename... _Args>
BELLESIP_EXPORT std::shared_ptr<_T> make_shared(_Args&&... __args){
return std::shared_ptr<_T>(new _T(std::forward<_Args>(__args)...), std::mem_fun(&Object::unref));
}
}//end of namespace
extern "C" {
BELLE_SIP_DECLARE_VPTR(belle_sip_cpp_object_t);
}
......@@ -84,7 +84,7 @@ typedef unsigned int belle_sip_type_id_t;
(belle_sip_object_get_vptr_t)BELLE_SIP_OBJECT_GET_VPTR_FUNC(parent_type), \
(belle_sip_interface_desc_t**)object_type##interfaces_table
#define BELLE_SIP_INSTANCIATE_VPTR2(object_type,parent_type,destroy,clone,marshal,on_first_ref,on_last_ref,unowned) \
#define BELLE_SIP_INSTANCIATE_VPTR3(object_type,parent_type,destroy,clone,marshal,on_first_ref,on_last_ref,unowned,is_cpp) \
static BELLE_SIP_OBJECT_VPTR_TYPE(object_type) BELLE_SIP_OBJECT_VPTR_NAME(object_type)={ \
BELLE_SIP_VPTR_INIT(object_type,parent_type,unowned), \
(belle_sip_object_destroy_t)destroy, \
......@@ -92,12 +92,16 @@ static BELLE_SIP_OBJECT_VPTR_TYPE(object_type) BELLE_SIP_OBJECT_VPTR_NAME(object
(belle_sip_object_marshal_t)marshal,\
(belle_sip_object_on_first_ref_t)on_first_ref,\
(belle_sip_object_on_last_ref_t)on_last_ref,\
BELLE_SIP_DEFAULT_BUFSIZE_HINT\
BELLE_SIP_DEFAULT_BUFSIZE_HINT,\
is_cpp, 0\
}; \
BELLE_SIP_OBJECT_VPTR_TYPE(object_type) * BELLE_SIP_OBJECT_GET_VPTR_FUNC(object_type)(void){\
return &BELLE_SIP_OBJECT_VPTR_NAME(object_type); \
}
#define BELLE_SIP_INSTANCIATE_VPTR2(object_type,parent_type,destroy,clone,marshal,on_first_ref,on_last_ref,unowned) \
BELLE_SIP_INSTANCIATE_VPTR3(object_type,parent_type,destroy,clone,marshal,on_first_ref,on_last_ref,unowned,FALSE)
#define BELLE_SIP_INSTANCIATE_VPTR(object_type,parent_type,destroy,clone,marshal,unowned) \
BELLE_SIP_INSTANCIATE_VPTR2(object_type, parent_type, destroy, clone, marshal, NULL, NULL, unowned)
......@@ -141,6 +145,7 @@ static BELLE_SIP_OBJECT_VPTR_TYPE(object_type) BELLE_SIP_OBJECT_VPTR_NAME(object
* when they no longer need it. This rule must be strictly followed by developers doing things inside belle-sip.
**/
typedef struct _belle_sip_object belle_sip_object_t;
typedef struct _belle_sip_cpp_object belle_sip_cpp_object_t;
typedef void (*belle_sip_object_destroy_t)(belle_sip_object_t*);
......@@ -163,6 +168,8 @@ struct _belle_sip_object_vptr{
belle_sip_object_on_first_ref_t on_first_ref; /*called when object is ref'd for the first time*/
belle_sip_object_on_last_ref_t on_last_ref; /*called in unref() when the last reference of the object remains*/
int tostring_bufsize_hint; /*optimization: you can suggest here the typical size for a to_string() result.*/
int is_cpp; /*indicates whether this object kind is defined in c++*/
int cpp_offset; /*offset to apply to the belle_sip_object_t to find the pointer to the corresponding bellesip::Object, if any*/
};
typedef struct _belle_sip_object_vptr belle_sip_object_vptr_t;
......@@ -369,7 +376,7 @@ BELLESIP_EXPORT void *belle_sip_object_cast(belle_sip_object_t *obj, belle_sip_t
* WHen the object is a sip header, uri or message, this is the textual representation of the header, uri or message.
* This function internally calls belle_sip_object_marshal().
**/
BELLESIP_EXPORT char* belle_sip_object_to_string(void* obj);
BELLESIP_EXPORT char* belle_sip_object_to_string(const void* obj);
/**
* Writes a string representation of the object into the supplied buffer.
......
......@@ -150,7 +150,8 @@ BELLE_SIP_DECLARE_TYPES_BEGIN(belle_sip,1)
BELLE_SIP_TYPE_ID(belle_sip_header_reason_t),
BELLE_SIP_TYPE_ID(belle_sip_header_authentication_info_t),
BELLE_SIP_TYPE_ID(belle_sip_mdns_register_t),
BELLE_SIP_TYPE_ID(belle_sip_resolver_results_t)
BELLE_SIP_TYPE_ID(belle_sip_resolver_results_t),
BELLE_SIP_TYPE_ID(belle_sip_cpp_object_t)
BELLE_SIP_DECLARE_TYPES_END
......
......@@ -160,6 +160,8 @@ if(ANDROID)
endif()
set(BELLE_SIP_SOURCE_FILES_CXX
${TUNNEL_SOURCE_FILES_CXX}
object++.cc
cpp_utils.cc
)
if(APPLE)
set(BELLE_SIP_SOURCE_FILES_OBJC
......@@ -200,6 +202,7 @@ string(REPLACE ";" " " LINK_FLAGS_STR "${LINK_FLAGS}")
if(ENABLE_STATIC)
add_library(bellesip-static STATIC ${BELLE_SIP_HEADER_FILES} ${BELLE_SIP_SOURCE_FILES_C} ${BELLE_SIP_SOURCE_FILES_CXX} ${BELLE_SIP_SOURCE_FILES_OBJC} ${ANTLR3C_SOURCE_FILES})
set_target_properties(bellesip-static PROPERTIES OUTPUT_NAME bellesip)
set_target_properties(bellesip-static PROPERTIES CXX_STANDARD 11 CXX_STANDARD_REQUIRED ON)
target_include_directories(bellesip-static PUBLIC ${PUBLIC_INCLUDE_DIRS} PRIVATE ${PRIVATE_INCLUDE_DIRS})
target_link_libraries(bellesip-static INTERFACE ${LIBS})
if(NOT "${LINK_FLAGS_STR}" STREQUAL "")
......@@ -215,6 +218,7 @@ if(ENABLE_SHARED)
add_library(bellesip SHARED ${BELLE_SIP_HEADER_FILES} ${BELLE_SIP_SOURCE_FILES_C} ${BELLE_SIP_SOURCE_FILES_CXX} ${BELLE_SIP_SOURCE_FILES_OBJC} ${ANTLR3C_SOURCE_FILES})
set_target_properties(bellesip PROPERTIES SOVERSION 0)
set_target_properties(bellesip PROPERTIES LINKER_LANGUAGE CXX)
set_target_properties(bellesip PROPERTIES CXX_STANDARD 11 CXX_STANDARD_REQUIRED ON)
target_include_directories(bellesip PUBLIC ${PUBLIC_INCLUDE_DIRS} PRIVATE ${PRIVATE_INCLUDE_DIRS})
target_link_libraries(bellesip PRIVATE ${LIBS})
if(NOT "${LINK_FLAGS_STR}" STREQUAL "")
......
......@@ -134,6 +134,9 @@ typedef struct weak_ref{
void *userpointer;
}weak_ref_t;
#ifdef __cplusplus
extern "C" {
#endif
void *belle_sip_object_get_interface_methods(belle_sip_object_t *obj, belle_sip_interface_id_t ifid);
/*used internally by unref()*/
......@@ -141,6 +144,11 @@ void belle_sip_object_delete(void *obj);
void belle_sip_object_pool_add(belle_sip_object_pool_t *pool, belle_sip_object_t *obj);
void belle_sip_object_pool_remove(belle_sip_object_pool_t *pool, belle_sip_object_t *obj);
belle_sip_object_t * _belle_sip_object_init(belle_sip_object_t *obj, belle_sip_object_vptr_t *vptr);
void belle_sip_cpp_object_delete(belle_sip_object_t *obj);
void belle_sip_object_uninit(belle_sip_object_t *obj);
#define belle_sip_object_init(obj) /*nothing*/
......@@ -1098,5 +1106,8 @@ belle_sip_list_t *belle_sip_parse_directory(const char *path, const char *file_t
typedef struct authorization_context authorization_context_t;
BELLESIP_EXPORT void belle_sip_authorization_destroy(authorization_context_t* object);
#ifdef __cplusplus
}
#endif
#endif
......@@ -91,9 +91,7 @@ void belle_sip_object_dump_active_objects(void){
}else belle_sip_warning("No objects leaked.");
}
belle_sip_object_t * _belle_sip_object_new(size_t objsize, belle_sip_object_vptr_t *vptr){
belle_sip_object_t *obj=(belle_sip_object_t *)belle_sip_malloc0(vptr->size);
belle_sip_object_t * _belle_sip_object_init(belle_sip_object_t *obj, belle_sip_object_vptr_t *vptr){
obj->vptr = vptr;
obj->ref = vptr->initially_unowned ? 0 : 1;
......@@ -106,6 +104,12 @@ belle_sip_object_t * _belle_sip_object_new(size_t objsize, belle_sip_object_vptr
return obj;
}
belle_sip_object_t * _belle_sip_object_new(size_t objsize, belle_sip_object_vptr_t *vptr){
belle_sip_object_t *obj=(belle_sip_object_t *)belle_sip_malloc0(vptr->size);
return _belle_sip_object_init(obj, vptr);
}
int belle_sip_object_is_initially_unowned(const belle_sip_object_t *obj){
return obj->vptr->initially_unowned;
}
......@@ -245,18 +249,29 @@ belle_sip_object_vptr_t *belle_sip_object_t_vptr_get(void){
return &belle_sip_object_t_vptr;
}
void belle_sip_object_delete(void *ptr){
belle_sip_object_t *obj=BELLE_SIP_OBJECT(ptr);
void belle_sip_object_uninit(belle_sip_object_t *obj){
belle_sip_object_vptr_t *vptr;
belle_sip_object_loose_weak_refs(obj);
belle_sip_object_remove_from_leak_detector(obj);
vptr=obj->vptr;
vptr = obj->vptr;
while(vptr!=NULL){
if (vptr->destroy) vptr->destroy(obj);
vptr=vptr->get_parent();
}
belle_sip_object_data_clear(obj);
}
void belle_sip_object_delete(void *ptr){
belle_sip_object_t *obj=BELLE_SIP_OBJECT(ptr);
if (obj->vptr->is_cpp){
/*This will call delete which calls the destructor chain*/
belle_sip_cpp_object_delete(obj);
return;
}
/*otherwise we're in C, call the destructor chain and free the memory*/
belle_sip_object_uninit(obj);
belle_sip_free(obj);
}
......@@ -553,10 +568,10 @@ belle_sip_error_code belle_sip_object_marshal(belle_sip_object_t* obj, char* buf
}
static char * belle_sip_object_to_alloc_string(belle_sip_object_t *obj, int size_hint){
static char * belle_sip_object_to_alloc_string(const belle_sip_object_t *obj, int size_hint){
char *buf=belle_sip_malloc(size_hint);
size_t offset=0;
belle_sip_error_code error = belle_sip_object_marshal(obj,buf,size_hint-1,&offset);
belle_sip_error_code error = belle_sip_object_marshal((belle_sip_object_t *)obj,buf,size_hint-1,&offset);
obj->vptr->tostring_bufsize_hint=size_hint;
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);
......@@ -574,14 +589,14 @@ static int get_hint_size(int size){
return size;
}
char* belle_sip_object_to_string(void* _obj) {
belle_sip_object_t *obj=BELLE_SIP_OBJECT(_obj);
char* belle_sip_object_to_string(const void* _obj) {
const belle_sip_object_t *obj=BELLE_SIP_OBJECT(_obj);
if (obj->vptr->tostring_bufsize_hint!=0){
return belle_sip_object_to_alloc_string(obj,obj->vptr->tostring_bufsize_hint);
}else{
char buff[BELLE_SIP_MAX_TO_STRING_SIZE];
size_t offset=0;
belle_sip_error_code error = belle_sip_object_marshal(obj,buff,sizeof(buff)-1,&offset);
belle_sip_error_code error = belle_sip_object_marshal((belle_sip_object_t *)obj,buff,sizeof(buff)-1,&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);
return belle_sip_object_to_alloc_string(obj,get_hint_size(2*(int)offset));
......
/*
belle-sip - SIP (RFC3261) library.
Copyright (C) 2010-2018 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 2 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/belle-sip.h"
#ifndef BELLE_SIP_USE_STL
#define BELLE_SIP_USE_STL 1
#endif
#if BELLE_SIP_USE_STL
#include <functional>
typedef std::function<int (unsigned int)> belle_sip_source_cpp_func_t;
static int belle_sip_source_cpp_func(belle_sip_source_cpp_func_t* user_data, unsigned int events)
{
int result = (*user_data)(events);
return result;
}
static void belle_sip_source_on_remove(belle_sip_source_t* source)
{
delete static_cast<belle_sip_source_cpp_func_t *>(belle_sip_source_get_user_data(source));
belle_sip_source_set_user_data(source,NULL);
}
belle_sip_source_t * belle_sip_main_loop_create_cpp_timeout(belle_sip_main_loop_t *ml
, belle_sip_source_cpp_func_t *func
, unsigned int timeout_value_ms
, const char* timer_name)
{
belle_sip_source_t* source = belle_sip_main_loop_create_timeout( ml
, (belle_sip_source_func_t)belle_sip_source_cpp_func
, func
, timeout_value_ms
, timer_name);
belle_sip_source_set_remove_cb(source,belle_sip_source_on_remove);
return source;
}
static void do_later(void *ud){
std::function<void (void)> *func = static_cast<std::function<void (void)> *>(ud);
(*func)();
delete func;
}
void belle_sip_main_loop_cpp_do_later(belle_sip_main_loop_t *ml, const std::function<void (void)> &func){
belle_sip_main_loop_do_later(ml, do_later, new std::function<void (void)>(func));
}
#endif
/*
belle-sip - SIP (RFC3261) library.
Copyright (C) 2019 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 2 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/object++.hh"
#include "belle_sip_internal.h"
struct _belle_sip_cpp_object{
belle_sip_object_t base;
};
namespace bellesip{
class ObjectCAccessors{
public:
static belle_sip_error_code sMarshal(belle_sip_object_t* obj, char* buff, size_t buff_size, size_t *offset){
return Object::getCppObject(obj)->marshal(buff, buff_size, offset);
}
static void doDelete(belle_sip_object_t* obj){
delete Object::getCppObject(obj);
}
};
void Object::init(){
static bool offsetDefined = false;
belle_sip_object_vptr_t *vptr = belle_sip_cpp_object_t_vptr_get();
if (!offsetDefined){
vptr->cpp_offset = (int) ((intptr_t)&mObject - (intptr_t)this);
offsetDefined = true;
}
memset(&mObject, 0, sizeof(mObject)); /*the new allocator does not zero the memory*/
_belle_sip_object_init(&mObject, vptr);
}
Object::Object(){
init();
}
Object::Object(const Object &other){
init();
mObject.vptr->get_parent()->clone(&mObject, &other.mObject); /*belle_sip_object_t own's clone method*/
}
Object::~Object(){
if (mObject.ref != -1){
/*note: throwing an exception here does not work*/
belle_sip_fatal("bellesip::Object [%p] has been destroyed directly with delete operator. This is prohibited, use unref() instead.", this);
}
belle_sip_object_uninit(&mObject);
belle_sip_message("Object destroyed");
}
Object *Object::ref(){
belle_sip_object_ref(&mObject);
return this;
}
void Object::unref(){
belle_sip_object_unref(&mObject);
}
belle_sip_error_code Object::marshal(char* buff, size_t buff_size, size_t *offset){
return mObject.vptr->get_parent()->marshal(&mObject, buff, buff_size, offset); /*default to belle_sip_object_t's implementation*/
}
Object *Object::clone()const{
return new Object(*this);
}
belle_sip_object_t *Object::getCObject(){
return &mObject;
}
const belle_sip_object_t *Object::getCObject()const{
return &mObject;
}
Object *Object::getCppObject(void *ptr){
belle_sip_object_t *obj = BELLE_SIP_OBJECT(ptr);
intptr_t cppaddr = (intptr_t)obj - (intptr_t)obj->vptr->cpp_offset;
return reinterpret_cast<Object*>(cppaddr);
}
const Object *Object::getCppObject(const void *ptr){
return Object::getCppObject((void*)ptr);
}
}//end of namespace
BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(belle_sip_cpp_object_t);
BELLE_SIP_INSTANCIATE_VPTR3(belle_sip_cpp_object_t,belle_sip_object_t,NULL,NULL,bellesip::ObjectCAccessors::sMarshal,NULL,NULL,FALSE,TRUE);
void belle_sip_cpp_object_delete(belle_sip_object_t *obj){
bellesip::ObjectCAccessors::doDelete(obj);
}
......@@ -44,6 +44,7 @@ set(SOURCE_FILES_C
belle_sip_fast_uri_tester.c
cast_test.c
register_tester.h
object_tester.cc
)
set(OTHER_FILES
......@@ -77,6 +78,7 @@ if(CMAKE_SYSTEM_NAME STREQUAL "WindowsStore")
set_target_properties(belle_sip_tester_runtime PROPERTIES VS_WINRT_COMPONENT TRUE)
set_target_properties(belle_sip_tester_runtime PROPERTIES LIBRARY_OUTPUT_NAME "BelledonneCommunications.BelleSip.Tester")
set_target_properties(belle_sip_tester_runtime PROPERTIES LINK_FLAGS "/WINMDFILE:BelledonneCommunications.BelleSip.Tester.winmd")
set_target_properties(belle_sip_tester_runtime PROPERTIES CXX_STANDARD 11 CXX_STANDARD_REQUIRED ON)
install(TARGETS belle_sip_tester_runtime
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
......@@ -99,6 +101,7 @@ else()
add_executable(belle_sip_tester ${USE_BUNDLE} ${SOURCE_FILES_C} ${SOURCE_FILES_OBJC})
set_target_properties(belle_sip_tester PROPERTIES LINKER_LANGUAGE CXX)
set_target_properties(belle_sip_tester PROPERTIES CXX_STANDARD 11 CXX_STANDARD_REQUIRED ON)
if(NOT "${LINK_FLAGS_STR}" STREQUAL "")
set_target_properties(belle_sip_tester PROPERTIES LINK_FLAGS "${LINK_FLAGS_STR}")
......
......@@ -152,6 +152,7 @@ void belle_sip_tester_init(void(*ftester_printf)(int level, const char *fmt, va_
bc_tester_add_suite(&dialog_test_suite);
bc_tester_add_suite(&refresher_test_suite);
bc_tester_add_suite(&http_test_suite);
bc_tester_add_suite(&object_test_suite);
}
void belle_sip_tester_uninit(void) {
......
......@@ -46,6 +46,7 @@ extern test_suite_t register_test_suite;
extern test_suite_t dialog_test_suite;
extern test_suite_t refresher_test_suite;
extern test_suite_t http_test_suite;
extern test_suite_t object_test_suite;
extern const char* belle_sip_tester_client_cert;
extern const char* belle_sip_tester_client_cert_fingerprint;
......
/*
belle-sip - SIP (RFC3261) library.
Copyright (C) 2019 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 2 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/belle-sip.h"
#include "belle_sip_tester.h"
#include "belle-sip/object++.hh"
#include "bctoolbox/exception.hh"
using namespace bellesip;
static void on_object_destroyed(void *userpointer, belle_sip_object_t *obj_being_destroyed){
int *value = static_cast<int*>(userpointer);
*value = TRUE;
}
static void basic_test(void){
int object_destroyed = FALSE;
Object *obj = new Object();
belle_sip_object_t *c_obj = obj->getCObject();
BC_ASSERT_PTR_NOT_NULL(c_obj);
if (c_obj){
belle_sip_object_weak_ref(c_obj, on_object_destroyed, &object_destroyed);
}
/*we put a weak ref to this object in order to know when it is destroyed*/
obj->ref();
Object *clone = obj->clone();
obj->unref();
BC_ASSERT_FALSE(object_destroyed);
obj->unref(); /*this unref will destroy the object*/
BC_ASSERT_TRUE(object_destroyed);
object_destroyed = false;
c_obj = clone->getCObject();
BC_ASSERT_PTR_NOT_NULL(c_obj);
if (c_obj){
belle_sip_object_weak_ref(c_obj, on_object_destroyed, &object_destroyed);
}
clone->unref();
BC_ASSERT_TRUE(object_destroyed);
};
typedef struct _LinphoneEvent LinphoneEvent;
typedef enum _LinphoneEventState{
LinphoneEventIdle,
LinphoneEventSubscribed
}LinphoneEventState;
namespace Linphone{
class Event : public HybridObject<LinphoneEvent, Event>, public std::enable_shared_from_this<Event>{
public:
enum State{
Idle,
Subscribed
};
Event() : mState(Idle){
}
void sendSubscribe(const std::string& dest){
mState = Subscribed;
}
State getState()const{
return mState;
}
void doSomething(){
throw BctbxException("Unimplemented");
}
protected:
//~Event() = default; //we shouls have the destructor private but in order to test the delete exception
//we'll make it public.
private:
State mState;
};
}//end of namespace
extern "C"{
using namespace Linphone;
LinphoneEvent *linphone_event_new(void){
return (new Event())->toC();
}
void linphone_event_send_subscribe(LinphoneEvent *obj, const char *dest){
Event::toCpp(obj)->sendSubscribe(dest);
}
LinphoneEventState linphone_event_get_state(const LinphoneEvent *obj){
return (LinphoneEventState)Event::toCpp(obj)->getState(); /*enum conversion should be performed better*/
}
void linphone_event_ref(LinphoneEvent *obj){
Event::toCpp(obj)->ref();
}
void linphone_event_unref(LinphoneEvent *obj){
Event::toCpp(obj)->unref();
}