From 933081e72f724afb223cfd63ef239c43e237bbe2 Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Wed, 7 Feb 2018 17:50:37 +0100 Subject: [PATCH 01/67] Started to remove old LinphoneContent and use a C wrapper above C++ Content --- coreapi/CMakeLists.txt | 1 - coreapi/Makefile.am | 1 - coreapi/private_structs.h | 11 -- include/CMakeLists.txt | 2 +- include/linphone/Makefile.am | 1 - .../linphone/{content.h => api/c-content.h} | 54 +++--- include/linphone/api/c-types.h | 6 + include/linphone/types.h | 6 - src/CMakeLists.txt | 1 + src/c-wrapper/api/c-content.cpp | 177 ++++++++++++++++++ src/c-wrapper/c-wrapper.h | 2 +- 11 files changed, 212 insertions(+), 50 deletions(-) rename include/linphone/{content.h => api/c-content.h} (87%) create mode 100644 src/c-wrapper/api/c-content.cpp diff --git a/coreapi/CMakeLists.txt b/coreapi/CMakeLists.txt index 03600de80..76a35259c 100644 --- a/coreapi/CMakeLists.txt +++ b/coreapi/CMakeLists.txt @@ -64,7 +64,6 @@ set(LINPHONE_SOURCE_FILES_C carddav.c chat.c contactprovider.c - content.c dial_plan.c dict.c ec-calibrator.c diff --git a/coreapi/Makefile.am b/coreapi/Makefile.am index 4e63d8879..c2b2ee53b 100644 --- a/coreapi/Makefile.am +++ b/coreapi/Makefile.am @@ -39,7 +39,6 @@ liblinphone_la_SOURCES=\ chat_file_transfer.c \ conference.cc conference_private.h \ contactprovider.c contact_providers_priv.h \ - content.c \ dial_plan.c \ dict.c \ ec-calibrator.c \ diff --git a/coreapi/private_structs.h b/coreapi/private_structs.h index 449609ba9..f7c6faba0 100644 --- a/coreapi/private_structs.h +++ b/coreapi/private_structs.h @@ -444,17 +444,6 @@ struct _EchoTester { unsigned int rate; }; -struct _LinphoneContent { - belle_sip_object_t base; - void *user_data; - SalBodyHandler *body_handler; - char *name; /**< used by RCS File transfer messages to store the original filename of the file to be downloaded from server */ - char *key; /**< used by RCS File transfer messages to store the key to encrypt file if needed */ - size_t keyLength; /**< Length of key in bytes */ - void *cryptoContext; /**< crypto context used to encrypt file for RCS file transfer */ - bool_t owned_fields; -}; - BELLE_SIP_DECLARE_VPTR_NO_EXPORT(LinphoneContent); struct _LinphoneBuffer { diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt index 055f1840d..90cba8715 100644 --- a/include/CMakeLists.txt +++ b/include/CMakeLists.txt @@ -33,7 +33,6 @@ set(ROOT_HEADER_FILES chat.h conference.h contactprovider.h - content.h core_utils.h core.h defs.h @@ -84,6 +83,7 @@ set(C_API_HEADER_FILES c-chat-message.h c-chat-room-cbs.h c-chat-room.h + c-content.h c-dial-plan.h c-event-log.h c-participant.h diff --git a/include/linphone/Makefile.am b/include/linphone/Makefile.am index dc9488e0b..56c2c3dda 100644 --- a/include/linphone/Makefile.am +++ b/include/linphone/Makefile.am @@ -14,7 +14,6 @@ linphone_include_HEADERS=\ chat.h \ conference.h \ contactprovider.h \ - content.h \ core.h \ core_utils.h \ defs.h \ diff --git a/include/linphone/content.h b/include/linphone/api/c-content.h similarity index 87% rename from include/linphone/content.h rename to include/linphone/api/c-content.h index 78ebc3114..fa030a309 100644 --- a/include/linphone/content.h +++ b/include/linphone/api/c-content.h @@ -1,33 +1,32 @@ /* -content.h -Copyright (C) 2010-2014 Belledonne Communications SARL + * c-content.h + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ -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. +#ifndef _L_C_CONTENT_H_ +#define _L_C_CONTENT_H_ -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, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef LINPHONE_CONTENT_H_ -#define LINPHONE_CONTENT_H_ - - -#include "linphone/types.h" +#include "linphone/api/c-types.h" +// ============================================================================= #ifdef __cplusplus -extern "C" { -#endif - + extern "C" { +#endif // ifdef __cplusplus /** * @addtogroup misc @@ -218,9 +217,8 @@ LINPHONE_PUBLIC void linphone_content_set_key(LinphoneContent *content, const ch * @} */ - #ifdef __cplusplus -} -#endif + } +#endif // ifdef __cplusplus -#endif /* LINPHONE_CONTENT_H_ */ +#endif // ifndef _L_C_CONTENT_H_ \ No newline at end of file diff --git a/include/linphone/api/c-types.h b/include/linphone/api/c-types.h index 6c109375f..30594f8ab 100644 --- a/include/linphone/api/c-types.h +++ b/include/linphone/api/c-types.h @@ -156,6 +156,12 @@ typedef struct _LinphoneDialPlan LinphoneDialPlan; **/ typedef struct _LinphoneParticipant LinphoneParticipant; +/** + * The LinphoneContent object holds data that can be embedded in a signaling message. + * @ingroup misc +**/ +typedef struct _LinphoneContent LinphoneContent; + // ============================================================================= // C Enums. // ============================================================================= diff --git a/include/linphone/types.h b/include/linphone/types.h index d3b03ce25..90a48c1ca 100644 --- a/include/linphone/types.h +++ b/include/linphone/types.h @@ -367,12 +367,6 @@ typedef unsigned int LinphoneContactSearchID; */ LINPHONE_DEPRECATED typedef LinphoneContactSearchID ContactSearchID; -/** - * The LinphoneContent object holds data that can be embedded in a signaling message. - * @ingroup misc -**/ -typedef struct _LinphoneContent LinphoneContent; - /** * Linphone core main object created by function linphone_core_new() . * @ingroup initializing diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 59ddaffc1..35634fd09 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -164,6 +164,7 @@ set(LINPHONE_CXX_OBJECTS_SOURCE_FILES c-wrapper/api/c-chat-room-cbs.cpp c-wrapper/api/c-chat-room.cpp c-wrapper/api/c-core.cpp + c-wrapper/api/c-content.cpp c-wrapper/api/c-dial-plan.cpp c-wrapper/api/c-event-log.cpp c-wrapper/api/c-participant.cpp diff --git a/src/c-wrapper/api/c-content.cpp b/src/c-wrapper/api/c-content.cpp new file mode 100644 index 000000000..cfb569732 --- /dev/null +++ b/src/c-wrapper/api/c-content.cpp @@ -0,0 +1,177 @@ +/* + * c-content.cpp + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "linphone/api/c-content.h" +#include "linphone/wrapper_utils.h" + +#include "c-wrapper/c-wrapper.h" + +#include "content/content.h" + +// ============================================================================= + +using namespace std; + +L_DECLARE_C_CLONABLE_OBJECT_IMPL(Content, + SalBodyHandler *body_handler; + void *cryptoContext; /**< crypto context used to encrypt file for RCS file transfer */ +) + +// ============================================================================= +// Reference and user data handling functions. +// ============================================================================= + +LinphoneContent * linphone_content_ref(LinphoneContent *content) { + belle_sip_object_ref(content); + return content; +} + +void linphone_content_unref(LinphoneContent *content) { + belle_sip_object_unref(content); +} + +void *linphone_content_get_user_data(const LinphoneContent *content) { + return L_GET_USER_DATA_FROM_C_OBJECT(content); +} + +void linphone_content_set_user_data(LinphoneContent *content, void *ud) { + return L_SET_USER_DATA_FROM_C_OBJECT(content, ud); +} + +// ============================================================================= + +const char * linphone_content_get_type(const LinphoneContent *content) { + return NULL; +} + +void linphone_content_set_type(LinphoneContent *content, const char *type) { + +} + +const char * linphone_content_get_subtype(const LinphoneContent *content) { + return NULL; +} + +void linphone_content_set_subtype(LinphoneContent *content, const char *subtype) { + +} + +uint8_t * linphone_content_get_buffer(const LinphoneContent *content) { + return NULL; +} + +void linphone_content_set_buffer(LinphoneContent *content, const uint8_t *buffer, size_t size) { + +} + +const char * linphone_content_get_string_buffer(const LinphoneContent *content) { + return NULL; +} + +void linphone_content_set_string_buffer(LinphoneContent *content, const char *buffer) { + +} + +size_t linphone_content_get_size(const LinphoneContent *content) { + return 0; +} + +void linphone_content_set_size(LinphoneContent *content, size_t size) { + +} + +const char * linphone_content_get_encoding(const LinphoneContent *content) { + return NULL; +} + +void linphone_content_set_encoding(LinphoneContent *content, const char *encoding) { + +} + +const char * linphone_content_get_name(const LinphoneContent *content) { + return NULL; +} + +void linphone_content_set_name(LinphoneContent *content, const char *name) { + +} + +bool_t linphone_content_is_multipart(const LinphoneContent *content) { + return FALSE; +} + +LinphoneContent * linphone_content_get_part(const LinphoneContent *content, int idx) { + return NULL; +} + +LinphoneContent * linphone_content_find_part_by_header(const LinphoneContent *content, const char *header_name, const char *header_value) { + return NULL; +} + +const char * linphone_content_get_custom_header(const LinphoneContent *content, const char *header_name) { + return NULL; +} + +const char *linphone_content_get_key(const LinphoneContent *content) { + return NULL; +} + +size_t linphone_content_get_key_size(const LinphoneContent *content) { + return 0; +} + +void linphone_content_set_key(LinphoneContent *content, const char *key, const size_t keyLength) { + +} + +// ============================================================================= +// Private functions. +// ============================================================================= + +LinphoneContent * linphone_content_new(void) { + return NULL; +} + +LinphoneContent * linphone_content_copy(const LinphoneContent *ref) { + return NULL; +} + +static LinphoneContent * linphone_content_new_with_body_handler(SalBodyHandler *body_handler) { + return NULL; +} + +LinphoneContent * linphone_core_create_content(LinphoneCore *lc) { + return NULL; +} + +/* crypto context is managed(allocated/freed) by the encryption function, so provide the address of field in the private structure */ +void ** linphone_content_get_cryptoContext_address(LinphoneContent *content) { + return &(content->cryptoContext);; +} + +LinphoneContent * linphone_content_from_sal_body_handler(SalBodyHandler *body_handler) { + if (body_handler) { + return linphone_content_new_with_body_handler(body_handler); + } + return NULL; +} + +SalBodyHandler * sal_body_handler_from_content(const LinphoneContent *content) { + return NULL; +} \ No newline at end of file diff --git a/src/c-wrapper/c-wrapper.h b/src/c-wrapper/c-wrapper.h index 2e1260e5e..b3bf0c8e0 100644 --- a/src/c-wrapper/c-wrapper.h +++ b/src/c-wrapper/c-wrapper.h @@ -37,6 +37,7 @@ F(ChatMessage, ChatMessage) \ F(AbstractChatRoom, ChatRoom) \ F(Core, Core) \ + F(Content, Content) \ F(DialPlan, DialPlan) \ F(EventLog, EventLog) \ F(MediaSessionParams, CallParams) \ @@ -83,7 +84,6 @@ BELLE_SIP_TYPE_ID(LinphoneConferenceParams), BELLE_SIP_TYPE_ID(LinphoneConfig), BELLE_SIP_TYPE_ID(LinphoneContactProvider), BELLE_SIP_TYPE_ID(LinphoneContactSearch), -BELLE_SIP_TYPE_ID(LinphoneContent), BELLE_SIP_TYPE_ID(LinphoneCoreCbs), BELLE_SIP_TYPE_ID(LinphoneErrorInfo), BELLE_SIP_TYPE_ID(LinphoneEvent), From 122098ac04ffb0549fd6c6ab18c1035d4f5e6276 Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Thu, 8 Feb 2018 11:24:30 +0100 Subject: [PATCH 02/67] More work on C/C++ Contents --- include/linphone/api/c-chat-room.h | 2 +- src/c-wrapper/api/c-chat-message.cpp | 4 +- src/c-wrapper/api/c-chat-room.cpp | 4 +- src/c-wrapper/api/c-content.cpp | 127 ++++++++++++++---- src/chat/chat-message/chat-message-p.h | 4 +- src/chat/chat-message/chat-message.cpp | 31 +++-- src/chat/chat-room/abstract-chat-room.h | 3 +- src/chat/chat-room/chat-room.cpp | 2 +- src/chat/chat-room/chat-room.h | 3 +- src/chat/chat-room/proxy-chat-room.cpp | 2 +- src/chat/chat-room/proxy-chat-room.h | 3 +- .../file-transfer-chat-message-modifier.cpp | 8 +- src/content/content.cpp | 7 - src/content/content.h | 3 - src/content/file-content.cpp | 10 -- src/content/file-content.h | 3 - src/content/file-transfer-content.cpp | 9 -- src/content/file-transfer-content.h | 3 - 18 files changed, 132 insertions(+), 96 deletions(-) diff --git a/include/linphone/api/c-chat-room.h b/include/linphone/api/c-chat-room.h index 392bce10f..aea3a7f61 100644 --- a/include/linphone/api/c-chat-room.h +++ b/include/linphone/api/c-chat-room.h @@ -90,7 +90,7 @@ LINPHONE_PUBLIC LinphoneChatMessage* linphone_chat_room_create_message_2(Linphon * @param initial_content #LinphoneContent initial content. #LinphoneCoreVTable.file_transfer_send is invoked later to notify file transfer progress and collect next chunk of the message if LinphoneContent.data is NULL. * @return a new #LinphoneChatMessage */ -LINPHONE_PUBLIC LinphoneChatMessage* linphone_chat_room_create_file_transfer_message(LinphoneChatRoom *cr, const LinphoneContent* initial_content); +LINPHONE_PUBLIC LinphoneChatMessage* linphone_chat_room_create_file_transfer_message(LinphoneChatRoom *cr, LinphoneContent* initial_content); /** * get peer address \link linphone_core_get_chat_room() associated to \endlink this #LinphoneChatRoom diff --git a/src/c-wrapper/api/c-chat-message.cpp b/src/c-wrapper/api/c-chat-message.cpp index da453b39c..59bffa2d9 100644 --- a/src/c-wrapper/api/c-chat-message.cpp +++ b/src/c-wrapper/api/c-chat-message.cpp @@ -283,7 +283,9 @@ int linphone_chat_message_set_text(LinphoneChatMessage *msg, const char* text) { } LinphoneContent *linphone_chat_message_get_file_transfer_information(LinphoneChatMessage *msg) { - return L_GET_PRIVATE_FROM_C_OBJECT(msg)->getFileTransferInformation(); + const LinphonePrivate::Content *content = L_GET_PRIVATE_FROM_C_OBJECT(msg)->getFileTransferInformation(); + if (content) return L_GET_C_BACK_PTR(content); + return NULL; } // ============================================================================= diff --git a/src/c-wrapper/api/c-chat-room.cpp b/src/c-wrapper/api/c-chat-room.cpp index 3288f1073..11f89e053 100644 --- a/src/c-wrapper/api/c-chat-room.cpp +++ b/src/c-wrapper/api/c-chat-room.cpp @@ -350,8 +350,8 @@ const bctbx_list_t *linphone_chat_room_get_composing_addresses (LinphoneChatRoom return cr->composingAddresses; } -LinphoneChatMessage *linphone_chat_room_create_file_transfer_message(LinphoneChatRoom *cr, const LinphoneContent *initial_content) { - shared_ptr cppPtr = L_GET_CPP_PTR_FROM_C_OBJECT(cr)->createFileTransferMessage(initial_content); +LinphoneChatMessage *linphone_chat_room_create_file_transfer_message(LinphoneChatRoom *cr, LinphoneContent *initial_content) { + shared_ptr cppPtr = L_GET_CPP_PTR_FROM_C_OBJECT(cr)->createFileTransferMessage(L_GET_CPP_PTR_FROM_C_OBJECT(initial_content)); LinphoneChatMessage *object = L_INIT(ChatMessage); L_SET_CPP_PTR_FROM_C_OBJECT(object, cppPtr); return object; diff --git a/src/c-wrapper/api/c-content.cpp b/src/c-wrapper/api/c-content.cpp index cfb569732..7af4b4073 100644 --- a/src/c-wrapper/api/c-content.cpp +++ b/src/c-wrapper/api/c-content.cpp @@ -23,6 +23,9 @@ #include "c-wrapper/c-wrapper.h" #include "content/content.h" +#include "content/content-type.h" +#include "content/file-content.h" +#include "content/file-transfer-content.h" // ============================================================================= @@ -31,6 +34,7 @@ using namespace std; L_DECLARE_C_CLONABLE_OBJECT_IMPL(Content, SalBodyHandler *body_handler; void *cryptoContext; /**< crypto context used to encrypt file for RCS file transfer */ + mutable char *name; ) // ============================================================================= @@ -57,112 +61,176 @@ void linphone_content_set_user_data(LinphoneContent *content, void *ud) { // ============================================================================= const char * linphone_content_get_type(const LinphoneContent *content) { - return NULL; + return L_STRING_TO_C(L_GET_CPP_PTR_FROM_C_OBJECT(content)->getContentType().getType()); } void linphone_content_set_type(LinphoneContent *content, const char *type) { - + LinphonePrivate::ContentType ct = L_GET_CPP_PTR_FROM_C_OBJECT(content)->getContentType(); + ct.setType(L_C_TO_STRING(type)); + L_GET_CPP_PTR_FROM_C_OBJECT(content)->setContentType(ct); } const char * linphone_content_get_subtype(const LinphoneContent *content) { - return NULL; + return L_STRING_TO_C(L_GET_CPP_PTR_FROM_C_OBJECT(content)->getContentType().getSubType()); } void linphone_content_set_subtype(LinphoneContent *content, const char *subtype) { - + LinphonePrivate::ContentType ct = L_GET_CPP_PTR_FROM_C_OBJECT(content)->getContentType(); + ct.setSubType(L_C_TO_STRING(subtype)); + L_GET_CPP_PTR_FROM_C_OBJECT(content)->setContentType(ct); } uint8_t * linphone_content_get_buffer(const LinphoneContent *content) { - return NULL; + return (uint8_t *)L_STRING_TO_C(L_GET_CPP_PTR_FROM_C_OBJECT(content)->getBodyAsString()); } void linphone_content_set_buffer(LinphoneContent *content, const uint8_t *buffer, size_t size) { - + L_GET_CPP_PTR_FROM_C_OBJECT(content)->setBody(buffer, size); } const char * linphone_content_get_string_buffer(const LinphoneContent *content) { - return NULL; + return L_STRING_TO_C(L_GET_CPP_PTR_FROM_C_OBJECT(content)->getBodyAsString()); } void linphone_content_set_string_buffer(LinphoneContent *content, const char *buffer) { - + L_GET_CPP_PTR_FROM_C_OBJECT(content)->setBody(L_C_TO_STRING(buffer)); } size_t linphone_content_get_size(const LinphoneContent *content) { - return 0; + size_t size = L_GET_CPP_PTR_FROM_C_OBJECT(content)->getSize(); + if (size == 0) { + size = sal_body_handler_get_size(content->body_handler); + } + return size; } void linphone_content_set_size(LinphoneContent *content, size_t size) { - + sal_body_handler_set_size(content->body_handler, size); } const char * linphone_content_get_encoding(const LinphoneContent *content) { - return NULL; + return sal_body_handler_get_encoding(content->body_handler); } void linphone_content_set_encoding(LinphoneContent *content, const char *encoding) { - + sal_body_handler_set_encoding(content->body_handler, encoding); } const char * linphone_content_get_name(const LinphoneContent *content) { - return NULL; + const LinphonePrivate::Content *c = L_GET_CPP_PTR_FROM_C_OBJECT(content); + if (c->isFile()) { + const LinphonePrivate::FileContent *fc = static_cast(c); + if (content->name) ms_free(content->name); + content->name = ms_strdup(L_STRING_TO_C(fc->getFileName())); + } else if (c->getContentType() == LinphonePrivate::ContentType::FileTransfer) { + const LinphonePrivate::FileTransferContent *ftc = static_cast(c); + if (content->name) ms_free(content->name); + content->name = ms_strdup(L_STRING_TO_C(ftc->getFileName())); + } + return content->name; } void linphone_content_set_name(LinphoneContent *content, const char *name) { - + LinphonePrivate::Content *c = L_GET_CPP_PTR_FROM_C_OBJECT(content); + if (c->isFile()) { + LinphonePrivate::FileContent *fc = static_cast(c); + fc->setFileName(L_C_TO_STRING(name)); + } else if (c->getContentType() == LinphonePrivate::ContentType::FileTransfer) { + LinphonePrivate::FileTransferContent *ftc = static_cast(c); + ftc->setFileName(L_C_TO_STRING(name)); + } + content->name = ms_strdup(name); } bool_t linphone_content_is_multipart(const LinphoneContent *content) { - return FALSE; + return sal_body_handler_is_multipart(content->body_handler); } LinphoneContent * linphone_content_get_part(const LinphoneContent *content, int idx) { - return NULL; + SalBodyHandler *part_body_handler; + if (!linphone_content_is_multipart(content)) return NULL; + part_body_handler = sal_body_handler_get_part(content->body_handler, idx); + return linphone_content_from_sal_body_handler(part_body_handler); } LinphoneContent * linphone_content_find_part_by_header(const LinphoneContent *content, const char *header_name, const char *header_value) { - return NULL; + SalBodyHandler *part_body_handler; + if (!linphone_content_is_multipart(content)) return NULL; + part_body_handler = sal_body_handler_find_part_by_header(content->body_handler, header_name, header_value); + return linphone_content_from_sal_body_handler(part_body_handler); } const char * linphone_content_get_custom_header(const LinphoneContent *content, const char *header_name) { - return NULL; + return sal_body_handler_get_header(content->body_handler, header_name); } const char *linphone_content_get_key(const LinphoneContent *content) { + const LinphonePrivate::Content *c = L_GET_CPP_PTR_FROM_C_OBJECT(content); + if (c->isFile()) { + const LinphonePrivate::FileContent *fc = static_cast(c); + return L_STRING_TO_C(fc->getFileKey()); + } return NULL; } size_t linphone_content_get_key_size(const LinphoneContent *content) { + const LinphonePrivate::Content *c = L_GET_CPP_PTR_FROM_C_OBJECT(content); + if (c->isFile()) { + const LinphonePrivate::FileContent *fc = static_cast(c); + return fc->getFileKey().length(); + } return 0; } void linphone_content_set_key(LinphoneContent *content, const char *key, const size_t keyLength) { - + LinphonePrivate::Content *c = L_GET_CPP_PTR_FROM_C_OBJECT(content); + if (c->isFile()) { + LinphonePrivate::FileContent *fc = static_cast(c); + fc->setFileKey(L_C_TO_STRING(key)); + } } // ============================================================================= // Private functions. // ============================================================================= -LinphoneContent * linphone_content_new(void) { - return NULL; -} - -LinphoneContent * linphone_content_copy(const LinphoneContent *ref) { - return NULL; +static void linphone_content_set_sal_body_handler(LinphoneContent *content, SalBodyHandler *body_handler) { + if (content->body_handler != NULL) { + sal_body_handler_unref(content->body_handler); + content->body_handler = NULL; + } + content->body_handler = sal_body_handler_ref(body_handler); } static LinphoneContent * linphone_content_new_with_body_handler(SalBodyHandler *body_handler) { - return NULL; + LinphoneContent *content = L_INIT(Content); + content->cryptoContext = NULL; + if (body_handler == NULL) { + linphone_content_set_sal_body_handler(content, sal_body_handler_new()); + } else { + linphone_content_set_sal_body_handler(content, body_handler); + } + LinphonePrivate::Content *c = new LinphonePrivate::Content(); + L_SET_CPP_PTR_FROM_C_OBJECT(content, c); + return content; +} + +LinphoneContent * linphone_content_new(void) { + return linphone_content_new_with_body_handler(NULL); +} + +LinphoneContent * linphone_content_copy(const LinphoneContent *ref) { + //TODO + return (LinphoneContent *)belle_sip_object_ref(belle_sip_object_clone(BELLE_SIP_OBJECT(ref))); } LinphoneContent * linphone_core_create_content(LinphoneCore *lc) { - return NULL; + return linphone_content_new(); } /* crypto context is managed(allocated/freed) by the encryption function, so provide the address of field in the private structure */ void ** linphone_content_get_cryptoContext_address(LinphoneContent *content) { - return &(content->cryptoContext);; + return &(content->cryptoContext); } LinphoneContent * linphone_content_from_sal_body_handler(SalBodyHandler *body_handler) { @@ -173,5 +241,6 @@ LinphoneContent * linphone_content_from_sal_body_handler(SalBodyHandler *body_ha } SalBodyHandler * sal_body_handler_from_content(const LinphoneContent *content) { - return NULL; + if (content == NULL) return NULL; + return content->body_handler; } \ No newline at end of file diff --git a/src/chat/chat-message/chat-message-p.h b/src/chat/chat-message/chat-message-p.h index 0eae6c24e..b47355e3b 100644 --- a/src/chat/chat-message/chat-message-p.h +++ b/src/chat/chat-message/chat-message-p.h @@ -119,8 +119,8 @@ public: bool hasFileTransferContent () const; const Content* getFileTransferContent () const; - LinphoneContent *getFileTransferInformation () const; - void setFileTransferInformation (const LinphoneContent *content); + const Content* getFileTransferInformation () const; + void setFileTransferInformation (Content *content); bool downloadFile (); diff --git a/src/chat/chat-message/chat-message.cpp b/src/chat/chat-message/chat-message.cpp index d6f7d3f95..855dbd902 100644 --- a/src/chat/chat-message/chat-message.cpp +++ b/src/chat/chat-message/chat-message.cpp @@ -284,33 +284,36 @@ void ChatMessagePrivate::setText (const string &text) { } } -LinphoneContent *ChatMessagePrivate::getFileTransferInformation () const { +const Content *ChatMessagePrivate::getFileTransferInformation () const { if (hasFileTransferContent()) { - return getFileTransferContent()->toLinphoneContent(); + return getFileTransferContent(); } for (const Content *c : contents) { if (c->isFile()) { FileContent *fileContent = (FileContent *)c; - return fileContent->toLinphoneContent(); + return fileContent; } } return NULL; } -void ChatMessagePrivate::setFileTransferInformation (const LinphoneContent *c_content) { +void ChatMessagePrivate::setFileTransferInformation (Content *content) { L_Q(); - // Create a FileContent, it will create the FileTransferContent at upload time - FileContent *fileContent = new FileContent(); - ContentType contentType(linphone_content_get_type(c_content), linphone_content_get_subtype(c_content)); - fileContent->setContentType(contentType); - fileContent->setFileSize(linphone_content_get_size(c_content)); - fileContent->setFileName(linphone_content_get_name(c_content)); - if (linphone_content_get_string_buffer(c_content) != NULL) { - fileContent->setBody(linphone_content_get_string_buffer(c_content)); + if (content->isFile()) { + q->addContent(*content); + } else { + // This scenario is more likely to happen because the caller is using the C API + LinphoneContent *c_content = L_GET_C_BACK_PTR(content); + FileContent *fileContent = new FileContent(); + fileContent->setContentType(content->getContentType()); + fileContent->setFileSize(linphone_content_get_size(c_content)); // This information is only available from C Content if it was created from C API + fileContent->setFileName(linphone_content_get_name(c_content)); // This information is only available from C Content if it was created from C API + if (!content->isEmpty()) { + fileContent->setBody(content->getBody()); + } + q->addContent(*fileContent); } - - q->addContent(*fileContent); } bool ChatMessagePrivate::downloadFile () { diff --git a/src/chat/chat-room/abstract-chat-room.h b/src/chat/chat-room/abstract-chat-room.h index 46f5aec29..6cd260a82 100644 --- a/src/chat/chat-room/abstract-chat-room.h +++ b/src/chat/chat-room/abstract-chat-room.h @@ -87,8 +87,7 @@ public: virtual std::shared_ptr createChatMessage () = 0; virtual std::shared_ptr createChatMessage (const std::string &text) = 0; - // TODO: Remove LinphoneContent by LinphonePrivate::Content. - virtual std::shared_ptr createFileTransferMessage (const LinphoneContent *initialContent) = 0; + virtual std::shared_ptr createFileTransferMessage (Content *initialContent) = 0; virtual std::shared_ptr findChatMessage (const std::string &messageId) const = 0; virtual std::shared_ptr findChatMessage ( diff --git a/src/chat/chat-room/chat-room.cpp b/src/chat/chat-room/chat-room.cpp index 14e92cf85..03b8cd079 100644 --- a/src/chat/chat-room/chat-room.cpp +++ b/src/chat/chat-room/chat-room.cpp @@ -393,7 +393,7 @@ shared_ptr ChatRoom::createChatMessage (const string &text) { return chatMessage; } -shared_ptr ChatRoom::createFileTransferMessage (const LinphoneContent *initialContent) { +shared_ptr ChatRoom::createFileTransferMessage (Content *initialContent) { shared_ptr chatMessage = createChatMessage(); chatMessage->getPrivate()->setFileTransferInformation(initialContent); return chatMessage; diff --git a/src/chat/chat-room/chat-room.h b/src/chat/chat-room/chat-room.h index 35d887e59..9c6dbb999 100644 --- a/src/chat/chat-room/chat-room.h +++ b/src/chat/chat-room/chat-room.h @@ -61,8 +61,7 @@ public: std::shared_ptr createChatMessage () override; std::shared_ptr createChatMessage (const std::string &text) override; - // TODO: Remove LinphoneContent by LinphonePrivate::Content. - std::shared_ptr createFileTransferMessage (const LinphoneContent *initialContent) override; + std::shared_ptr createFileTransferMessage (Content *initialContent) override; std::shared_ptr findChatMessage (const std::string &messageId) const override; std::shared_ptr findChatMessage ( diff --git a/src/chat/chat-room/proxy-chat-room.cpp b/src/chat/chat-room/proxy-chat-room.cpp index bf984d2a1..29a9ddb80 100644 --- a/src/chat/chat-room/proxy-chat-room.cpp +++ b/src/chat/chat-room/proxy-chat-room.cpp @@ -264,7 +264,7 @@ shared_ptr ProxyChatRoom::createChatMessage (const string &text) { return d->chatRoom->createChatMessage(text); } -shared_ptr ProxyChatRoom::createFileTransferMessage (const LinphoneContent *initialContent) { +shared_ptr ProxyChatRoom::createFileTransferMessage (Content *initialContent) { L_D(); return d->chatRoom->createFileTransferMessage(initialContent); } diff --git a/src/chat/chat-room/proxy-chat-room.h b/src/chat/chat-room/proxy-chat-room.h index 16a5c49aa..6b9a75428 100644 --- a/src/chat/chat-room/proxy-chat-room.h +++ b/src/chat/chat-room/proxy-chat-room.h @@ -62,8 +62,7 @@ public: std::shared_ptr createChatMessage () override; std::shared_ptr createChatMessage (const std::string &text) override; - // TODO: Remove LinphoneContent by LinphonePrivate::Content. - std::shared_ptr createFileTransferMessage (const LinphoneContent *initialContent) override; + std::shared_ptr createFileTransferMessage (Content *initialContent) override; std::shared_ptr findChatMessage (const std::string &messageId) const override; std::shared_ptr findChatMessage ( diff --git a/src/chat/modifier/file-transfer-chat-message-modifier.cpp b/src/chat/modifier/file-transfer-chat-message-modifier.cpp index 30d088d2c..ac99d2201 100644 --- a/src/chat/modifier/file-transfer-chat-message-modifier.cpp +++ b/src/chat/modifier/file-transfer-chat-message-modifier.cpp @@ -100,7 +100,7 @@ void FileTransferChatMessageModifier::fileTransferOnProgress ( LinphoneChatMessage *msg = L_GET_C_BACK_PTR(message); LinphoneChatMessageCbs *cbs = linphone_chat_message_get_callbacks(msg); - LinphoneContent *content = currentFileContentToTransfer->toLinphoneContent(); + LinphoneContent *content = L_GET_C_BACK_PTR((Content *)currentFileContentToTransfer); if (linphone_chat_message_cbs_get_file_transfer_progress_indication(cbs)) { linphone_chat_message_cbs_get_file_transfer_progress_indication(cbs)(msg, content, offset, total); } else { @@ -150,7 +150,7 @@ int FileTransferChatMessageModifier::onSendBody ( LinphoneChatMessageCbs *cbs = linphone_chat_message_get_callbacks(msg); LinphoneChatMessageCbsFileTransferSendCb file_transfer_send_cb = linphone_chat_message_cbs_get_file_transfer_send(cbs); - LinphoneContent *content = currentFileContentToTransfer->toLinphoneContent(); + LinphoneContent *content = L_GET_C_BACK_PTR((Content *)currentFileContentToTransfer); if (file_transfer_send_cb) { LinphoneBuffer *lb = file_transfer_send_cb(msg, content, offset, *size); if (lb) { @@ -706,7 +706,7 @@ void FileTransferChatMessageModifier::onRecvBody (belle_sip_user_body_handler_t if (currentFileContentToTransfer->getFilePath().empty()) { LinphoneChatMessage *msg = L_GET_C_BACK_PTR(message); LinphoneChatMessageCbs *cbs = linphone_chat_message_get_callbacks(msg); - LinphoneContent *content = currentFileContentToTransfer->toLinphoneContent(); + LinphoneContent *content = L_GET_C_BACK_PTR((Content *)currentFileContentToTransfer); if (linphone_chat_message_cbs_get_file_transfer_recv(cbs)) { LinphoneBuffer *lb = linphone_buffer_new_from_data(buffer, size); linphone_chat_message_cbs_get_file_transfer_recv(cbs)(msg, content, lb); @@ -747,7 +747,7 @@ void FileTransferChatMessageModifier::onRecvEnd (belle_sip_user_body_handler_t * if (currentFileContentToTransfer->getFilePath().empty()) { LinphoneChatMessage *msg = L_GET_C_BACK_PTR(message); LinphoneChatMessageCbs *cbs = linphone_chat_message_get_callbacks(msg); - LinphoneContent *content = currentFileContentToTransfer->toLinphoneContent(); + LinphoneContent *content = L_GET_C_BACK_PTR((Content *)currentFileContentToTransfer); if (linphone_chat_message_cbs_get_file_transfer_recv(cbs)) { LinphoneBuffer *lb = linphone_buffer_new(); linphone_chat_message_cbs_get_file_transfer_recv(cbs)(msg, content, lb); diff --git a/src/content/content.cpp b/src/content/content.cpp index 732996494..93fd2f6e4 100644 --- a/src/content/content.cpp +++ b/src/content/content.cpp @@ -172,11 +172,4 @@ bool Content::isFile () const { return false; } -LinphoneContent *Content::toLinphoneContent () const { - LinphoneContent *content = linphone_core_create_content(nullptr); - linphone_content_set_type(content, getContentType().getType().c_str()); - linphone_content_set_subtype(content, getContentType().getSubType().c_str()); - return content; -} - LINPHONE_END_NAMESPACE diff --git a/src/content/content.h b/src/content/content.h index 4885feadf..da3c9e055 100644 --- a/src/content/content.h +++ b/src/content/content.h @@ -71,9 +71,6 @@ public: virtual bool isFile () const; - // TODO: Remove me later. - virtual LinphoneContent *toLinphoneContent () const; - protected: explicit Content (ContentPrivate &p); diff --git a/src/content/file-content.cpp b/src/content/file-content.cpp index 09de486b6..a2d1df851 100644 --- a/src/content/file-content.cpp +++ b/src/content/file-content.cpp @@ -135,14 +135,4 @@ bool FileContent::isFile () const { return true; } -LinphoneContent *FileContent::toLinphoneContent () const { - LinphoneContent *content = linphone_core_create_content(nullptr); - linphone_content_set_type(content, getContentType().getType().c_str()); - linphone_content_set_subtype(content, getContentType().getSubType().c_str()); - linphone_content_set_name(content, getFileName().c_str()); - linphone_content_set_size(content, getFileSize()); - linphone_content_set_key(content, getFileKey().c_str(), getFileKey().size()); - return content; -} - LINPHONE_END_NAMESPACE diff --git a/src/content/file-content.h b/src/content/file-content.h index 4876370fb..79dfe5629 100644 --- a/src/content/file-content.h +++ b/src/content/file-content.h @@ -53,9 +53,6 @@ public: bool isFile () const override; - // TODO: Remove me later. - LinphoneContent *toLinphoneContent () const override; - private: L_DECLARE_PRIVATE(FileContent); }; diff --git a/src/content/file-transfer-content.cpp b/src/content/file-transfer-content.cpp index 4ce62bc19..628080c7c 100644 --- a/src/content/file-transfer-content.cpp +++ b/src/content/file-transfer-content.cpp @@ -146,15 +146,6 @@ size_t FileTransferContent::getFileSize () const { return d->fileSize; } -LinphoneContent *FileTransferContent::toLinphoneContent () const { - LinphoneContent *content = linphone_core_create_content(nullptr); - linphone_content_set_type(content, getContentType().getType().c_str()); - linphone_content_set_subtype(content, getContentType().getSubType().c_str()); - linphone_content_set_name(content, getFileName().c_str()); - linphone_content_set_size(content, getFileSize()); - return content; -} - bool FileTransferContent::isFile () const { return false; } diff --git a/src/content/file-transfer-content.h b/src/content/file-transfer-content.h index 4b668a0ac..4abc4369f 100644 --- a/src/content/file-transfer-content.h +++ b/src/content/file-transfer-content.h @@ -57,9 +57,6 @@ public: bool isFile () const override; - // TODO: Remove me later. - LinphoneContent *toLinphoneContent () const override; - private: L_DECLARE_PRIVATE(FileTransferContent); }; From 96c01f70525159610edd4f7ee9fb1d8233c4fc35 Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Thu, 8 Feb 2018 13:06:39 +0100 Subject: [PATCH 03/67] More work --- src/c-wrapper/api/c-chat-message.cpp | 4 +- src/c-wrapper/api/c-content.cpp | 18 +++---- src/chat/chat-message/chat-message.cpp | 16 +++--- src/chat/chat-message/chat-message.h | 4 +- src/chat/chat-room/chat-room.cpp | 4 +- .../file-transfer-chat-message-modifier.cpp | 54 +++++++++++-------- .../multipart-chat-message-modifier.cpp | 2 +- src/content/file-content.cpp | 18 +------ src/content/file-content.h | 3 -- src/content/file-transfer-content.cpp | 20 +++++++ src/content/file-transfer-content.h | 6 +++ src/db/main-db.cpp | 2 +- tester/cpim-tester.cpp | 2 +- tester/multipart-tester.cpp | 8 +-- 14 files changed, 90 insertions(+), 71 deletions(-) diff --git a/src/c-wrapper/api/c-chat-message.cpp b/src/c-wrapper/api/c-chat-message.cpp index 59bffa2d9..1bf1faee5 100644 --- a/src/c-wrapper/api/c-chat-message.cpp +++ b/src/c-wrapper/api/c-chat-message.cpp @@ -222,7 +222,7 @@ void linphone_chat_message_add_text_content(LinphoneChatMessage *msg, const char LinphonePrivate::ContentType contentType = LinphonePrivate::ContentType::PlainText; content->setContentType(contentType); content->setBody(L_C_TO_STRING(c_content)); - L_GET_CPP_PTR_FROM_C_OBJECT(msg)->addContent(*content); + L_GET_CPP_PTR_FROM_C_OBJECT(msg)->addContent(content); } bool_t linphone_chat_message_has_text_content(const LinphoneChatMessage *msg) { @@ -284,7 +284,7 @@ int linphone_chat_message_set_text(LinphoneChatMessage *msg, const char* text) { LinphoneContent *linphone_chat_message_get_file_transfer_information(LinphoneChatMessage *msg) { const LinphonePrivate::Content *content = L_GET_PRIVATE_FROM_C_OBJECT(msg)->getFileTransferInformation(); - if (content) return L_GET_C_BACK_PTR(content); + if (content) return linphone_content_ref(L_GET_C_BACK_PTR(content)); return NULL; } diff --git a/src/c-wrapper/api/c-content.cpp b/src/c-wrapper/api/c-content.cpp index 7af4b4073..6691ec9da 100644 --- a/src/c-wrapper/api/c-content.cpp +++ b/src/c-wrapper/api/c-content.cpp @@ -166,27 +166,27 @@ const char * linphone_content_get_custom_header(const LinphoneContent *content, const char *linphone_content_get_key(const LinphoneContent *content) { const LinphonePrivate::Content *c = L_GET_CPP_PTR_FROM_C_OBJECT(content); - if (c->isFile()) { - const LinphonePrivate::FileContent *fc = static_cast(c); - return L_STRING_TO_C(fc->getFileKey()); + if (c->getContentType() == LinphonePrivate::ContentType::FileTransfer) { + const LinphonePrivate::FileTransferContent *ftc = static_cast(c); + return ftc->getFileKeyAsString(); } return NULL; } size_t linphone_content_get_key_size(const LinphoneContent *content) { const LinphonePrivate::Content *c = L_GET_CPP_PTR_FROM_C_OBJECT(content); - if (c->isFile()) { - const LinphonePrivate::FileContent *fc = static_cast(c); - return fc->getFileKey().length(); + if (c->getContentType() == LinphonePrivate::ContentType::FileTransfer) { + const LinphonePrivate::FileTransferContent *ftc = static_cast(c); + return ftc->getFileKey().size(); } return 0; } void linphone_content_set_key(LinphoneContent *content, const char *key, const size_t keyLength) { LinphonePrivate::Content *c = L_GET_CPP_PTR_FROM_C_OBJECT(content); - if (c->isFile()) { - LinphonePrivate::FileContent *fc = static_cast(c); - fc->setFileKey(L_C_TO_STRING(key)); + if (c->getContentType() == LinphonePrivate::ContentType::FileTransfer) { + LinphonePrivate::FileTransferContent *ftc = static_cast(c); + ftc->setFileKey(key, keyLength); } } diff --git a/src/chat/chat-message/chat-message.cpp b/src/chat/chat-message/chat-message.cpp index 855dbd902..2c5130802 100644 --- a/src/chat/chat-message/chat-message.cpp +++ b/src/chat/chat-message/chat-message.cpp @@ -301,7 +301,7 @@ void ChatMessagePrivate::setFileTransferInformation (Content *content) { L_Q(); if (content->isFile()) { - q->addContent(*content); + q->addContent(content); } else { // This scenario is more likely to happen because the caller is using the C API LinphoneContent *c_content = L_GET_C_BACK_PTR(content); @@ -312,7 +312,7 @@ void ChatMessagePrivate::setFileTransferInformation (Content *content) { if (!content->isEmpty()) { fileContent->setBody(content->getBody()); } - q->addContent(*fileContent); + q->addContent(fileContent); } } @@ -354,7 +354,7 @@ void ChatMessagePrivate::sendImdn (Imdn::Type imdnType, LinphoneReason reason) { Content *content = new Content(); content->setContentType("message/imdn+xml"); content->setBody(Imdn::createXml(imdnId, time, imdnType, reason)); - msg->addContent(*content); + msg->addContent(content); if (reason != LinphoneReasonNone) msg->getPrivate()->setEncryptionPrevented(true); @@ -676,7 +676,7 @@ void ChatMessagePrivate::send () { if (content->getContentType() == ContentType::FileTransfer) { FileTransferContent *fileTransferContent = (FileTransferContent *)content; it = contents.erase(it); - q->addContent(*fileTransferContent->getFileContent()); + q->addContent(fileTransferContent->getFileContent()); delete fileTransferContent; } else { it++; @@ -881,18 +881,18 @@ const list &ChatMessage::getContents () const { return d->contents; } -void ChatMessage::addContent (Content &content) { +void ChatMessage::addContent (Content *content) { L_D(); if (d->isReadOnly) return; - d->contents.push_back(&content); + d->contents.push_back(content); } -void ChatMessage::removeContent (const Content &content) { +void ChatMessage::removeContent (const Content *content) { L_D(); if (d->isReadOnly) return; - d->contents.remove(&const_cast(content)); + d->contents.remove(const_cast(content)); } const Content &ChatMessage::getInternalContent () const { diff --git a/src/chat/chat-message/chat-message.h b/src/chat/chat-message/chat-message.h index af7623b77..3b0b26417 100644 --- a/src/chat/chat-message/chat-message.h +++ b/src/chat/chat-message/chat-message.h @@ -94,8 +94,8 @@ public: void setToBeStored (bool value); const std::list &getContents () const; - void addContent (Content &content); - void removeContent (const Content &content); + void addContent (Content *content); + void removeContent (const Content *content); const Content &getInternalContent () const; void setInternalContent (const Content &content); diff --git a/src/chat/chat-room/chat-room.cpp b/src/chat/chat-room/chat-room.cpp index 03b8cd079..2c1e0054a 100644 --- a/src/chat/chat-room/chat-room.cpp +++ b/src/chat/chat-room/chat-room.cpp @@ -82,7 +82,7 @@ void ChatRoomPrivate::sendIsComposingNotification () { Content *content = new Content(); content->setContentType(ContentType::ImIsComposing); content->setBody(payload); - chatMessage->addContent(*content); + chatMessage->addContent(content); chatMessage->getPrivate()->send(); } } @@ -389,7 +389,7 @@ shared_ptr ChatRoom::createChatMessage (const string &text) { Content *content = new Content(); content->setContentType(ContentType::PlainText); content->setBody(text); - chatMessage->addContent(*content); + chatMessage->addContent(content); return chatMessage; } diff --git a/src/chat/modifier/file-transfer-chat-message-modifier.cpp b/src/chat/modifier/file-transfer-chat-message-modifier.cpp index ac99d2201..674ddb308 100644 --- a/src/chat/modifier/file-transfer-chat-message-modifier.cpp +++ b/src/chat/modifier/file-transfer-chat-message-modifier.cpp @@ -246,12 +246,6 @@ void FileTransferChatMessageModifier::processResponseFromPostFile (const belle_h } // shall we encrypt the file if (is_file_encryption_enabled && message->getChatRoom()) { - LinphoneImEncryptionEngineCbs *imee_cbs = linphone_im_encryption_engine_get_callbacks(imee); - LinphoneImEncryptionEngineCbsGenerateFileTransferKeyCb generate_file_transfer_key_cb = - linphone_im_encryption_engine_cbs_get_generate_file_transfer_key(imee_cbs); - if (generate_file_transfer_key_cb) { - generate_file_transfer_key_cb(imee, L_GET_C_BACK_PTR(message->getChatRoom()), L_GET_C_BACK_PTR(message)); - } // temporary storage for the Content-disposition header value : use a generic filename to not leak it // Actual filename stored in msg->file_transfer_information->name will be set in encrypted msg // sended to the @@ -294,9 +288,32 @@ void FileTransferChatMessageModifier::processResponseFromPostFile (const belle_h const char *body = belle_sip_message_get_body((belle_sip_message_t *)event->response); if (body && strlen(body) > 0) { FileTransferContent *fileTransferContent = new FileTransferContent(); + fileTransferContent->setContentType(ContentType::FileTransfer); + message->addContent(fileTransferContent); + + LinphoneImEncryptionEngine *imee = linphone_core_get_im_encryption_engine(message->getCore()->getCCore()); + bool_t is_file_encryption_enabled = FALSE; + if (imee && message->getChatRoom()) { + LinphoneImEncryptionEngineCbs *imee_cbs = linphone_im_encryption_engine_get_callbacks(imee); + LinphoneImEncryptionEngineCbsIsEncryptionEnabledForFileTransferCb is_encryption_enabled_for_file_transfer_cb = + linphone_im_encryption_engine_cbs_get_is_encryption_enabled_for_file_transfer(imee_cbs); + if (is_encryption_enabled_for_file_transfer_cb) { + is_file_encryption_enabled = is_encryption_enabled_for_file_transfer_cb(imee, L_GET_C_BACK_PTR(message->getChatRoom())); + } + } + if (is_file_encryption_enabled && message->getChatRoom()) { + LinphoneImEncryptionEngineCbs *imee_cbs = linphone_im_encryption_engine_get_callbacks(imee); + LinphoneImEncryptionEngineCbsGenerateFileTransferKeyCb generate_file_transfer_key_cb = + linphone_im_encryption_engine_cbs_get_generate_file_transfer_key(imee_cbs); + if (generate_file_transfer_key_cb) { + generate_file_transfer_key_cb(imee, L_GET_C_BACK_PTR(message->getChatRoom()), L_GET_C_BACK_PTR(message)); + } + } + // if we have an encryption key for the file, we must insert it into the msg and restore the correct filename - string content_key = currentFileContentToTransfer->getFileKey(); - if (!content_key.empty()) { + const char *content_key = fileTransferContent->getFileKeyAsString(); + size_t content_key_size = fileTransferContent->getFileKey().size(); + if (content_key_size > 0) { // parse the msg body xmlDocPtr xmlMessageBody = xmlParseDoc((const xmlChar *)body); @@ -309,16 +326,15 @@ void FileTransferChatMessageModifier::processResponseFromPostFile (const belle_h xmlChar *typeAttribute = xmlGetProp(cur, (const xmlChar *)"type"); // this is the node we are looking for : add a file-key children node if (!xmlStrcmp(typeAttribute, (const xmlChar *)"file")) { - size_t content_key_size = content_key.length(); // need to parse the children node to update the file-name one xmlNodePtr fileInfoNodeChildren = cur->xmlChildrenNode; // convert key to base64 size_t b64Size; - bctbx_base64_encode(nullptr, &b64Size, (unsigned char *)content_key.c_str(), content_key_size); + bctbx_base64_encode(nullptr, &b64Size, (unsigned char *)content_key, content_key_size); unsigned char *keyb64 = (unsigned char *)ms_malloc0(b64Size + 1); int xmlStringLength; - bctbx_base64_encode(keyb64, &b64Size, (unsigned char *)content_key.c_str(), content_key_size); + bctbx_base64_encode(keyb64, &b64Size, (unsigned char *)content_key, content_key_size); keyb64[b64Size] = '\0'; // libxml need a null terminated string // add the node containing the key to the file-info node @@ -354,11 +370,9 @@ void FileTransferChatMessageModifier::processResponseFromPostFile (const belle_h } FileContent *fileContent = currentFileContentToTransfer; - fileTransferContent->setContentType(ContentType::FileTransfer); fileTransferContent->setFileContent(fileContent); - message->removeContent(*fileContent); - message->addContent(*fileTransferContent); + message->removeContent(fileContent); message->updateState(ChatMessage::State::FileTransferDone); releaseHttpRequest(); @@ -566,7 +580,7 @@ ChatMessageModifier::Result FileTransferChatMessageModifier::decode (const share fileTransferContent->setContentType(internalContent.getContentType()); fileTransferContent->setBody(internalContent.getBody()); fillFileTransferContentInformationsFromVndGsmaRcsFtHttpXml(fileTransferContent); - message->addContent(*fileTransferContent); + message->addContent(fileTransferContent); return ChatMessageModifier::Result::Done; } @@ -641,8 +655,7 @@ static void createFileTransferInformationsFromVndGsmaRcsFtHttpXml (FileTransferC uint8_t *keyBuffer = (uint8_t *)malloc(keyLength); // decode the key into local key buffer bctbx_base64_decode(keyBuffer, &keyLength, (unsigned char *)keyb64, strlen((const char *)keyb64)); - string key = string((const char *)keyBuffer); - fileContent->setFileKey(key); + fileTransferContent->setFileKey((const char *)keyBuffer, keyLength); // duplicate key value into the linphone content private structure xmlFree(keyb64); free(keyBuffer); @@ -715,7 +728,6 @@ void FileTransferChatMessageModifier::onRecvBody (belle_sip_user_body_handler_t // Legacy: call back given by application level linphone_core_notify_file_transfer_recv(message->getCore()->getCCore(), msg, content, (const char *)buffer, size); } - linphone_content_unref(content); } } else { lWarning() << "File transfer decrypt failed with code " << (int)retval; @@ -763,12 +775,12 @@ void FileTransferChatMessageModifier::onRecvEnd (belle_sip_user_body_handler_t * if (retval <= 0 && message->getState() != ChatMessage::State::FileTransferError) { // Remove the FileTransferContent from the message and store the FileContent FileContent *fileContent = currentFileContentToTransfer; - message->addContent(*fileContent); + message->addContent(fileContent); for (Content *content : message->getContents()) { if (content->getContentType() == ContentType::FileTransfer) { FileTransferContent *fileTransferContent = (FileTransferContent*)content; if (fileTransferContent->getFileContent() == fileContent) { - message->removeContent(*content); + message->removeContent(content); delete fileTransferContent; break; } @@ -821,7 +833,7 @@ void FileTransferChatMessageModifier::processResponseHeadersFromGetFile (const b } else { lWarning() << "No file transfer information for msg [" << this << "]: creating..."; FileContent *content = createFileTransferInformationFromHeaders(response); - message->addContent(*content); + message->addContent(content); } size_t body_size = 0; diff --git a/src/chat/modifier/multipart-chat-message-modifier.cpp b/src/chat/modifier/multipart-chat-message-modifier.cpp index 4abf91210..97081a4d0 100644 --- a/src/chat/modifier/multipart-chat-message-modifier.cpp +++ b/src/chat/modifier/multipart-chat-message-modifier.cpp @@ -120,7 +120,7 @@ ChatMessageModifier::Result MultipartChatMessageModifier::decode (const shared_p } content->setContentType(contentType); content->setBody(contentBody); - message->addContent(*content); + message->addContent(content); lInfo() << "Parsed and added content with type " << contentType.asString(); } diff --git a/src/content/file-content.cpp b/src/content/file-content.cpp index a2d1df851..8f6425474 100644 --- a/src/content/file-content.cpp +++ b/src/content/file-content.cpp @@ -36,7 +36,6 @@ public: string fileName; string filePath; size_t fileSize = 0; - string fileKey; }; // ----------------------------------------------------------------------------- @@ -48,7 +47,6 @@ FileContent::FileContent (const FileContent &src) : Content(*new FileContentPriv d->fileName = src.getFileName(); d->filePath = src.getFilePath(); d->fileSize = src.getFileSize(); - d->fileKey = src.getFileKey(); } FileContent::FileContent (FileContent &&src) : Content(*new FileContentPrivate) { @@ -56,7 +54,6 @@ FileContent::FileContent (FileContent &&src) : Content(*new FileContentPrivate) d->fileName = move(src.getPrivate()->fileName); d->filePath = move(src.getPrivate()->filePath); d->fileSize = move(src.getPrivate()->fileSize); - d->fileKey = move(src.getPrivate()->fileKey); } FileContent &FileContent::operator= (const FileContent &src) { @@ -66,7 +63,6 @@ FileContent &FileContent::operator= (const FileContent &src) { d->fileName = src.getFileName(); d->filePath = src.getFilePath(); d->fileSize = src.getFileSize(); - d->fileKey = src.getFileKey(); } return *this; @@ -78,7 +74,6 @@ FileContent &FileContent::operator= (FileContent &&src) { d->fileName = move(src.getPrivate()->fileName); d->filePath = move(src.getPrivate()->filePath); d->fileSize = move(src.getPrivate()->fileSize); - d->fileKey = move(src.getPrivate()->fileKey); return *this; } @@ -87,8 +82,7 @@ bool FileContent::operator== (const FileContent &content) const { return Content::operator==(content) && d->fileName == content.getFileName() && d->filePath == content.getFilePath() && - d->fileSize == content.getFileSize() && - d->fileKey == content.getFileKey(); + d->fileSize == content.getFileSize(); } void FileContent::setFileSize (size_t size) { @@ -121,16 +115,6 @@ const string &FileContent::getFilePath () const { return d->filePath; } -void FileContent::setFileKey (const string &key) { - L_D(); - d->fileKey = key; -} - -const string &FileContent::getFileKey () const { - L_D(); - return d->fileKey; -} - bool FileContent::isFile () const { return true; } diff --git a/src/content/file-content.h b/src/content/file-content.h index 79dfe5629..c46786dd5 100644 --- a/src/content/file-content.h +++ b/src/content/file-content.h @@ -48,9 +48,6 @@ public: void setFilePath (const std::string &path); const std::string &getFilePath () const; - void setFileKey (const std::string &key); - const std::string &getFileKey () const; - bool isFile () const override; private: diff --git a/src/content/file-transfer-content.cpp b/src/content/file-transfer-content.cpp index 628080c7c..d1d67c00d 100644 --- a/src/content/file-transfer-content.cpp +++ b/src/content/file-transfer-content.cpp @@ -38,6 +38,7 @@ public: string filePath; FileContent *fileContent = nullptr; size_t fileSize = 0; + std::vector fileKey; }; // ----------------------------------------------------------------------------- @@ -51,6 +52,7 @@ FileTransferContent::FileTransferContent (const FileTransferContent &src) : Cont d->filePath = src.getFilePath(); d->fileContent = src.getFileContent(); d->fileSize = src.getFileSize(); + d->fileKey = src.getFileKey(); } FileTransferContent::FileTransferContent (FileTransferContent &&src) : Content(*new FileTransferContentPrivate) { @@ -60,6 +62,7 @@ FileTransferContent::FileTransferContent (FileTransferContent &&src) : Content(* d->filePath = move(src.getPrivate()->filePath); d->fileContent = move(src.getPrivate()->fileContent); d->fileSize = move(src.getPrivate()->fileSize); + d->fileKey = move(src.getPrivate()->fileKey); } FileTransferContent &FileTransferContent::operator= (const FileTransferContent &src) { @@ -71,6 +74,7 @@ FileTransferContent &FileTransferContent::operator= (const FileTransferContent & d->filePath = src.getFilePath(); d->fileContent = src.getFileContent(); d->fileSize = src.getFileSize(); + d->fileKey = src.getFileKey(); } return *this; @@ -84,6 +88,7 @@ FileTransferContent &FileTransferContent::operator= (FileTransferContent &&src) d->filePath = move(src.getPrivate()->filePath); d->fileContent = move(src.getPrivate()->fileContent); d->fileSize = move(src.getPrivate()->fileSize); + d->fileKey = move(src.getPrivate()->fileKey); return *this; } @@ -146,6 +151,21 @@ size_t FileTransferContent::getFileSize () const { return d->fileSize; } +void FileTransferContent::setFileKey (const char *key, size_t size) { + L_D(); + d->fileKey = vector(key, key + size); +} + +const vector &FileTransferContent::getFileKey () const { + L_D(); + return d->fileKey; +} + +const char *FileTransferContent::getFileKeyAsString() const { + L_D(); + return d->fileKey.data(); +} + bool FileTransferContent::isFile () const { return false; } diff --git a/src/content/file-transfer-content.h b/src/content/file-transfer-content.h index 4abc4369f..da23053cb 100644 --- a/src/content/file-transfer-content.h +++ b/src/content/file-transfer-content.h @@ -20,6 +20,8 @@ #ifndef _L_FILE_TRANSFER_CONTENT_H_ #define _L_FILE_TRANSFER_CONTENT_H_ +#include + #include "content.h" // ============================================================================= @@ -55,6 +57,10 @@ public: void setFileSize (size_t size); size_t getFileSize () const; + void setFileKey (const char *key, size_t size); + const std::vector &getFileKey () const; + const char *getFileKeyAsString () const; + bool isFile () const override; private: diff --git a/src/db/main-db.cpp b/src/db/main-db.cpp index 1e76e96ae..943426029 100644 --- a/src/db/main-db.cpp +++ b/src/db/main-db.cpp @@ -708,7 +708,7 @@ shared_ptr MainDbPrivate::selectConferenceChatMessageEvent ( string data; fetchContentAppData(session, *content, contentId, data); } - chatMessage->addContent(*content); + chatMessage->addContent(content); } } diff --git a/tester/cpim-tester.cpp b/tester/cpim-tester.cpp index a98ca133d..54a36b568 100644 --- a/tester/cpim-tester.cpp +++ b/tester/cpim-tester.cpp @@ -426,7 +426,7 @@ static void cpim_chat_message_modifier_base(bool_t use_multipart) { Content *content = new Content(); content->setContentType(ContentType::PlainText); content->setBody("Hello Part 2"); - marieMessage->addContent(*content); + marieMessage->addContent(content); } marieMessage->send(); diff --git a/tester/multipart-tester.cpp b/tester/multipart-tester.cpp index ad5d731f3..0472df0eb 100644 --- a/tester/multipart-tester.cpp +++ b/tester/multipart-tester.cpp @@ -53,13 +53,13 @@ static void chat_message_multipart_modifier_base(bool first_file_transfer, bool content->setContentType("video/mkv"); content->setFilePath(send_filepath); content->setFileName("sintel_trailer_opus_h264.mkv"); - marieMessage->addContent(*content); + marieMessage->addContent(content); bc_free(send_filepath); } else { Content *content = new Content(); content->setContentType(ContentType::PlainText); content->setBody("Hello Part 1"); - marieMessage->addContent(*content); + marieMessage->addContent(content); } if (second_file_transfer) { @@ -68,13 +68,13 @@ static void chat_message_multipart_modifier_base(bool first_file_transfer, bool content->setContentType("file/vcf"); content->setFilePath(send_filepath); content->setFileName("vcards.vcf"); - marieMessage->addContent(*content); + marieMessage->addContent(content); bc_free(send_filepath); } else { Content *content = new Content(); content->setContentType(ContentType::PlainText); content->setBody("Hello Part 2"); - marieMessage->addContent(*content); + marieMessage->addContent(content); } linphone_core_set_file_transfer_server(marie->lc,"https://www.linphone.org:444/lft.php"); From 450548f612d3d547c3eb3ad8d65502f0659674ed Mon Sep 17 00:00:00 2001 From: Ronan Abhamon Date: Thu, 8 Feb 2018 16:28:48 +0100 Subject: [PATCH 04/67] fix(core): add missing content.h include --- coreapi/callbacks.c | 3 ++- coreapi/friendlist.c | 1 + coreapi/info.c | 1 + coreapi/lime.c | 6 ++++-- coreapi/linphonecore.c | 6 ++++-- coreapi/proxy.c | 2 ++ coreapi/quality_reporting.c | 2 ++ include/linphone/core.h | 1 - src/c-wrapper/api/c-chat-message.cpp | 1 + src/c-wrapper/api/c-content.cpp | 2 +- src/chat/chat-message/chat-message.cpp | 3 ++- src/chat/modifier/file-transfer-chat-message-modifier.cpp | 8 +++++--- .../handlers/local-conference-event-handler.cpp | 1 + src/conference/session/call-session.cpp | 7 +++---- 14 files changed, 29 insertions(+), 15 deletions(-) diff --git a/coreapi/callbacks.c b/coreapi/callbacks.c index 25967bcb8..e99f02e17 100644 --- a/coreapi/callbacks.c +++ b/coreapi/callbacks.c @@ -17,14 +17,15 @@ along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - #include "c-wrapper/internal/c-sal.h" #include "sal/call-op.h" #include "sal/message-op.h" #include "sal/refer-op.h" +#include "linphone/api/c-content.h" #include "linphone/core.h" #include "linphone/utils/utils.h" + #include "private.h" #include "mediastreamer2/mediastream.h" #include "linphone/lpconfig.h" diff --git a/coreapi/friendlist.c b/coreapi/friendlist.c index 159409449..9475b877c 100644 --- a/coreapi/friendlist.c +++ b/coreapi/friendlist.c @@ -19,6 +19,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include +#include "linphone/api/c-content.h" #include "linphone/core.h" #include "c-wrapper/c-wrapper.h" diff --git a/coreapi/info.c b/coreapi/info.c index 5b12089bb..f68bb4522 100644 --- a/coreapi/info.c +++ b/coreapi/info.c @@ -23,6 +23,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +#include "linphone/api/c-content.h" #include "linphone/core.h" #include "linphone/lpconfig.h" diff --git a/coreapi/lime.c b/coreapi/lime.c index 4270f9d2a..965ccd10c 100644 --- a/coreapi/lime.c +++ b/coreapi/lime.c @@ -17,6 +17,8 @@ along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +#include "linphone/api/c-content.h" + #include "lime.h" #ifdef HAVE_CONFIG_H #include "config.h" @@ -787,8 +789,8 @@ int lime_im_encryption_engine_process_incoming_message_cb(LinphoneImEncryptionEn LinphoneCore *lc = linphone_im_encryption_engine_get_core(engine); int errcode = -1; /* check if we have a xml/cipher message to be decrypted */ - if (linphone_chat_message_get_content_type(msg) && - (strcmp("xml/cipher", linphone_chat_message_get_content_type(msg)) == 0 || + if (linphone_chat_message_get_content_type(msg) && + (strcmp("xml/cipher", linphone_chat_message_get_content_type(msg)) == 0 || strcmp("application/cipher.vnd.gsma.rcs-ft-http+xml", linphone_chat_message_get_content_type(msg)) == 0)) { errcode = 0; int retval; diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index 114749d3a..9e01822e1 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -18,9 +18,11 @@ along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +#include "linphone/api/c-content.h" #include "linphone/core.h" -#include "linphone/sipsetup.h" #include "linphone/lpconfig.h" +#include "linphone/sipsetup.h" + #include "private.h" #include "quality_reporting.h" #include "lime.h" @@ -2320,7 +2322,7 @@ void linphone_core_start (LinphoneCore *lc) { lp_config_set_string(lc->config,"misc","uuid",tmp); }else if (strcmp(uuid,"0")!=0) /*to allow to disable sip.instance*/ lc->sal->set_uuid(uuid); - + if (lc->sal->get_root_ca()) { belle_tls_crypto_config_set_root_ca(lc->http_crypto_config, lc->sal->get_root_ca()); belle_http_provider_set_tls_crypto_config(lc->http_provider, lc->http_crypto_config); diff --git a/coreapi/proxy.c b/coreapi/proxy.c index d5f3ea5ad..1f7d88519 100644 --- a/coreapi/proxy.c +++ b/coreapi/proxy.c @@ -20,10 +20,12 @@ Copyright (C) 2000 Simon MORLAT (simon.morlat@linphone.org) #include +#include "linphone/api/c-content.h" #include "linphone/core_utils.h" #include "linphone/core.h" #include "linphone/lpconfig.h" #include "linphone/sipsetup.h" + #include "mediastreamer2/mediastream.h" #include "enum.h" diff --git a/coreapi/quality_reporting.c b/coreapi/quality_reporting.c index 571a8faa0..a20b03b8e 100644 --- a/coreapi/quality_reporting.c +++ b/coreapi/quality_reporting.c @@ -21,7 +21,9 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "config.h" #endif +#include "linphone/api/c-content.h" #include "linphone/core.h" + #include "private.h" #include "c-wrapper/internal/c-sal.h" #include "sal/sal.h" diff --git a/include/linphone/core.h b/include/linphone/core.h index d2efdce47..d1ebbeb53 100644 --- a/include/linphone/core.h +++ b/include/linphone/core.h @@ -42,7 +42,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "linphone/call_stats.h" #include "linphone/chat.h" #include "linphone/conference.h" -#include "linphone/content.h" #include "linphone/dictionary.h" #include "linphone/error_info.h" #include "linphone/event.h" diff --git a/src/c-wrapper/api/c-chat-message.cpp b/src/c-wrapper/api/c-chat-message.cpp index 1bf1faee5..7f8e1b8c6 100644 --- a/src/c-wrapper/api/c-chat-message.cpp +++ b/src/c-wrapper/api/c-chat-message.cpp @@ -18,6 +18,7 @@ */ #include "linphone/api/c-chat-message.h" +#include "linphone/api/c-content.h" #include "linphone/utils/utils.h" #include "linphone/wrapper_utils.h" diff --git a/src/c-wrapper/api/c-content.cpp b/src/c-wrapper/api/c-content.cpp index 6691ec9da..b4f77a316 100644 --- a/src/c-wrapper/api/c-content.cpp +++ b/src/c-wrapper/api/c-content.cpp @@ -243,4 +243,4 @@ LinphoneContent * linphone_content_from_sal_body_handler(SalBodyHandler *body_ha SalBodyHandler * sal_body_handler_from_content(const LinphoneContent *content) { if (content == NULL) return NULL; return content->body_handler; -} \ No newline at end of file +} diff --git a/src/chat/chat-message/chat-message.cpp b/src/chat/chat-message/chat-message.cpp index 2c5130802..fd3157614 100644 --- a/src/chat/chat-message/chat-message.cpp +++ b/src/chat/chat-message/chat-message.cpp @@ -19,6 +19,7 @@ #include "object/object-p.h" +#include "linphone/api/c-content.h" #include "linphone/core.h" #include "linphone/lpconfig.h" #include "linphone/utils/utils.h" @@ -668,7 +669,7 @@ void ChatMessagePrivate::send () { } else { msgOp->send_message(ContentType::PlainText.asString().c_str(), internalContent.getBodyAsUtf8String().c_str()); } - + // Restore FileContents and remove FileTransferContents list::iterator it = contents.begin(); while (it != contents.end()) { diff --git a/src/chat/modifier/file-transfer-chat-message-modifier.cpp b/src/chat/modifier/file-transfer-chat-message-modifier.cpp index 674ddb308..ec04c61f0 100644 --- a/src/chat/modifier/file-transfer-chat-message-modifier.cpp +++ b/src/chat/modifier/file-transfer-chat-message-modifier.cpp @@ -17,15 +17,17 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#include "c-wrapper/c-wrapper.h" +#include "linphone/api/c-content.h" + #include "address/address.h" +#include "bctoolbox/crypto.h" +#include "c-wrapper/c-wrapper.h" #include "chat/chat-message/chat-message-p.h" +#include "chat/chat-room/chat-room-p.h" #include "content/content-type.h" #include "content/content.h" -#include "chat/chat-room/chat-room-p.h" #include "core/core.h" #include "logger/logger.h" -#include "bctoolbox/crypto.h" #include "file-transfer-chat-message-modifier.h" diff --git a/src/conference/handlers/local-conference-event-handler.cpp b/src/conference/handlers/local-conference-event-handler.cpp index 7b3989b72..96da99d07 100644 --- a/src/conference/handlers/local-conference-event-handler.cpp +++ b/src/conference/handlers/local-conference-event-handler.cpp @@ -19,6 +19,7 @@ #include +#include "linphone/api/c-content.h" #include "linphone/utils/utils.h" #include "conference/local-conference.h" diff --git a/src/conference/session/call-session.cpp b/src/conference/session/call-session.cpp index 97aa06f6f..bb3ac773e 100644 --- a/src/conference/session/call-session.cpp +++ b/src/conference/session/call-session.cpp @@ -19,19 +19,18 @@ #include -#include "c-wrapper/c-wrapper.h" +#include "linphone/api/c-content.h" +#include "linphone/core.h" #include "address/address-p.h" +#include "c-wrapper/c-wrapper.h" #include "call/call-p.h" #include "conference/params/call-session-params-p.h" #include "conference/session/call-session-p.h" #include "conference/session/call-session.h" #include "core/core-p.h" - #include "logger/logger.h" -#include "linphone/core.h" - #include "private.h" using namespace std; From bfe175f85310148804d1682252b0141b838f05f6 Mon Sep 17 00:00:00 2001 From: Ronan Abhamon Date: Thu, 8 Feb 2018 16:30:28 +0100 Subject: [PATCH 05/67] fix(c-api): add missing content include --- include/linphone/api/c-api.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/include/linphone/api/c-api.h b/include/linphone/api/c-api.h index 0b671d6ee..c37f7549a 100644 --- a/include/linphone/api/c-api.h +++ b/include/linphone/api/c-api.h @@ -23,14 +23,15 @@ #include "linphone/utils/general.h" #include "linphone/api/c-address.h" -#include "linphone/api/c-call.h" #include "linphone/api/c-call-cbs.h" #include "linphone/api/c-call-stats.h" +#include "linphone/api/c-call.h" #include "linphone/api/c-callbacks.h" -#include "linphone/api/c-chat-message.h" #include "linphone/api/c-chat-message-cbs.h" -#include "linphone/api/c-chat-room.h" +#include "linphone/api/c-chat-message.h" #include "linphone/api/c-chat-room-cbs.h" +#include "linphone/api/c-chat-room.h" +#include "linphone/api/c-content.h" #include "linphone/api/c-dial-plan.h" #include "linphone/api/c-event-log.h" #include "linphone/api/c-participant.h" From 1b74fdadefef9c721b35687b7528473b3c92a358 Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Thu, 8 Feb 2018 17:25:35 +0100 Subject: [PATCH 06/67] Do not crash if key is NULL --- coreapi/lime.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/coreapi/lime.c b/coreapi/lime.c index 965ccd10c..cdf697b95 100644 --- a/coreapi/lime.c +++ b/coreapi/lime.c @@ -421,6 +421,8 @@ int lime_encryptFile(void **cryptoContext, unsigned char *key, size_t length, ch int lime_decryptFile(void **cryptoContext, unsigned char *key, size_t length, char *plain, char *cipher) { bctbx_aes_gcm_context_t *gcmContext; + if (key == NULL) return -1; + if (*cryptoContext == NULL) { /* first call to the function, allocate a crypto context and initialise it */ /* key contains 192bits of key || 64 bits of Initialisation Vector, no additional data */ gcmContext = bctbx_aes_gcm_context_new(key, 24, NULL, 0, key+24, 8, BCTBX_GCM_DECRYPT); @@ -895,6 +897,7 @@ int lime_im_encryption_engine_process_downloading_file_cb(LinphoneImEncryptionEn LinphoneContent *content = linphone_chat_message_get_file_transfer_information(msg); if (!content) return -1; + if (!linphone_content_get_key(content)) { linphone_content_unref(content); return -1; From dbdbeaa46f426b6efdabc24ffdbb5c2f20adaa66 Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Thu, 8 Feb 2018 17:38:16 +0100 Subject: [PATCH 07/67] Added and using isFileTransfer --- src/chat/chat-message/chat-message.cpp | 16 ++++++++-------- src/chat/chat-message/chat-message.h | 2 +- .../file-transfer-chat-message-modifier.cpp | 8 ++++---- src/content/content.cpp | 4 ++++ src/content/content.h | 1 + src/content/file-content.cpp | 4 ++++ src/content/file-content.h | 1 + src/content/file-transfer-content.cpp | 4 ++++ src/content/file-transfer-content.h | 1 + 9 files changed, 28 insertions(+), 13 deletions(-) diff --git a/src/chat/chat-message/chat-message.cpp b/src/chat/chat-message/chat-message.cpp index fd3157614..df72a1b46 100644 --- a/src/chat/chat-message/chat-message.cpp +++ b/src/chat/chat-message/chat-message.cpp @@ -162,7 +162,7 @@ const Content* ChatMessagePrivate::getTextContent() const { bool ChatMessagePrivate::hasFileTransferContent() const { for (const Content *c : contents) { - if (c->getContentType() == ContentType::FileTransfer) { + if (c->isFileTransfer()) { return true; } } @@ -171,7 +171,7 @@ bool ChatMessagePrivate::hasFileTransferContent() const { const Content* ChatMessagePrivate::getFileTransferContent() const { for (const Content *c : contents) { - if (c->getContentType() == ContentType::FileTransfer) { + if (c->isFileTransfer()) { return c; } } @@ -321,8 +321,8 @@ bool ChatMessagePrivate::downloadFile () { L_Q(); for (auto &content : contents) - if (content->getContentType() == ContentType::FileTransfer) - return q->downloadFile(*static_cast(content)); + if (content->isFileTransfer()) + return q->downloadFile(static_cast(content)); return false; } @@ -674,8 +674,8 @@ void ChatMessagePrivate::send () { list::iterator it = contents.begin(); while (it != contents.end()) { Content *content = *it; - if (content->getContentType() == ContentType::FileTransfer) { - FileTransferContent *fileTransferContent = (FileTransferContent *)content; + if (content->isFileTransfer()) { + FileTransferContent *fileTransferContent = static_cast(content); it = contents.erase(it); q->addContent(fileTransferContent->getFileContent()); delete fileTransferContent; @@ -965,9 +965,9 @@ void ChatMessage::sendDisplayNotification () { d->sendImdn(Imdn::Type::Display, LinphoneReasonNone); } -bool ChatMessage::downloadFile(FileTransferContent &fileTransferContent) { +bool ChatMessage::downloadFile(FileTransferContent *fileTransferContent) { L_D(); - return d->fileTransferChatMessageModifier.downloadFile(getSharedFromThis(), &fileTransferContent); + return d->fileTransferChatMessageModifier.downloadFile(getSharedFromThis(), fileTransferContent); } void ChatMessage::cancelFileTransfer () { diff --git a/src/chat/chat-message/chat-message.h b/src/chat/chat-message/chat-message.h index 3b0b26417..47d8c365a 100644 --- a/src/chat/chat-message/chat-message.h +++ b/src/chat/chat-message/chat-message.h @@ -104,7 +104,7 @@ public: void addCustomHeader (const std::string &headerName, const std::string &headerValue); void removeCustomHeader (const std::string &headerName); - bool downloadFile (FileTransferContent &content); + bool downloadFile (FileTransferContent *content); private: ChatMessage (const std::shared_ptr &chatRoom, ChatMessage::Direction direction); diff --git a/src/chat/modifier/file-transfer-chat-message-modifier.cpp b/src/chat/modifier/file-transfer-chat-message-modifier.cpp index ec04c61f0..1032c5af8 100644 --- a/src/chat/modifier/file-transfer-chat-message-modifier.cpp +++ b/src/chat/modifier/file-transfer-chat-message-modifier.cpp @@ -587,8 +587,8 @@ ChatMessageModifier::Result FileTransferChatMessageModifier::decode (const share } for (Content *content : message->getContents()) { - if (content->getContentType() == ContentType::FileTransfer) { - FileTransferContent *fileTransferContent = (FileTransferContent *)content; + if (content->isFileTransfer()) { + FileTransferContent *fileTransferContent = static_cast(content); fillFileTransferContentInformationsFromVndGsmaRcsFtHttpXml(fileTransferContent); } } @@ -779,8 +779,8 @@ void FileTransferChatMessageModifier::onRecvEnd (belle_sip_user_body_handler_t * FileContent *fileContent = currentFileContentToTransfer; message->addContent(fileContent); for (Content *content : message->getContents()) { - if (content->getContentType() == ContentType::FileTransfer) { - FileTransferContent *fileTransferContent = (FileTransferContent*)content; + if (content->isFileTransfer()) { + FileTransferContent *fileTransferContent = static_cast(content); if (fileTransferContent->getFileContent() == fileContent) { message->removeContent(content); delete fileTransferContent; diff --git a/src/content/content.cpp b/src/content/content.cpp index 93fd2f6e4..786c9be8d 100644 --- a/src/content/content.cpp +++ b/src/content/content.cpp @@ -172,4 +172,8 @@ bool Content::isFile () const { return false; } +bool Content::isFileTransfer () const { + return false; +} + LINPHONE_END_NAMESPACE diff --git a/src/content/content.h b/src/content/content.h index da3c9e055..281ad78d2 100644 --- a/src/content/content.h +++ b/src/content/content.h @@ -70,6 +70,7 @@ public: bool isEmpty () const; virtual bool isFile () const; + virtual bool isFileTransfer () const; protected: explicit Content (ContentPrivate &p); diff --git a/src/content/file-content.cpp b/src/content/file-content.cpp index 8f6425474..63c727dc6 100644 --- a/src/content/file-content.cpp +++ b/src/content/file-content.cpp @@ -119,4 +119,8 @@ bool FileContent::isFile () const { return true; } +bool FileContent::isFileTransfer () const { + return false; +} + LINPHONE_END_NAMESPACE diff --git a/src/content/file-content.h b/src/content/file-content.h index c46786dd5..82bc1bcff 100644 --- a/src/content/file-content.h +++ b/src/content/file-content.h @@ -49,6 +49,7 @@ public: const std::string &getFilePath () const; bool isFile () const override; + bool isFileTransfer () const override; private: L_DECLARE_PRIVATE(FileContent); diff --git a/src/content/file-transfer-content.cpp b/src/content/file-transfer-content.cpp index d1d67c00d..57ecff245 100644 --- a/src/content/file-transfer-content.cpp +++ b/src/content/file-transfer-content.cpp @@ -170,4 +170,8 @@ bool FileTransferContent::isFile () const { return false; } +bool FileTransferContent::isFileTransfer () const { + return true; +} + LINPHONE_END_NAMESPACE diff --git a/src/content/file-transfer-content.h b/src/content/file-transfer-content.h index da23053cb..d107fcd52 100644 --- a/src/content/file-transfer-content.h +++ b/src/content/file-transfer-content.h @@ -62,6 +62,7 @@ public: const char *getFileKeyAsString () const; bool isFile () const override; + bool isFileTransfer () const override; private: L_DECLARE_PRIVATE(FileTransferContent); From 1024c1942bddfc584c59811839b12035433d86ce Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Thu, 8 Feb 2018 17:50:25 +0100 Subject: [PATCH 08/67] Some invalid read fixes --- src/c-wrapper/api/c-content.cpp | 12 ++++++------ src/content/file-transfer-content.cpp | 5 +++++ src/content/file-transfer-content.h | 1 + 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/c-wrapper/api/c-content.cpp b/src/c-wrapper/api/c-content.cpp index b4f77a316..3b7e009bd 100644 --- a/src/c-wrapper/api/c-content.cpp +++ b/src/c-wrapper/api/c-content.cpp @@ -122,7 +122,7 @@ const char * linphone_content_get_name(const LinphoneContent *content) { const LinphonePrivate::FileContent *fc = static_cast(c); if (content->name) ms_free(content->name); content->name = ms_strdup(L_STRING_TO_C(fc->getFileName())); - } else if (c->getContentType() == LinphonePrivate::ContentType::FileTransfer) { + } else if (c->isFileTransfer()) { const LinphonePrivate::FileTransferContent *ftc = static_cast(c); if (content->name) ms_free(content->name); content->name = ms_strdup(L_STRING_TO_C(ftc->getFileName())); @@ -135,7 +135,7 @@ void linphone_content_set_name(LinphoneContent *content, const char *name) { if (c->isFile()) { LinphonePrivate::FileContent *fc = static_cast(c); fc->setFileName(L_C_TO_STRING(name)); - } else if (c->getContentType() == LinphonePrivate::ContentType::FileTransfer) { + } else if (c->isFileTransfer()) { LinphonePrivate::FileTransferContent *ftc = static_cast(c); ftc->setFileName(L_C_TO_STRING(name)); } @@ -166,7 +166,7 @@ const char * linphone_content_get_custom_header(const LinphoneContent *content, const char *linphone_content_get_key(const LinphoneContent *content) { const LinphonePrivate::Content *c = L_GET_CPP_PTR_FROM_C_OBJECT(content); - if (c->getContentType() == LinphonePrivate::ContentType::FileTransfer) { + if (c->isFileTransfer()) { const LinphonePrivate::FileTransferContent *ftc = static_cast(c); return ftc->getFileKeyAsString(); } @@ -175,16 +175,16 @@ const char *linphone_content_get_key(const LinphoneContent *content) { size_t linphone_content_get_key_size(const LinphoneContent *content) { const LinphonePrivate::Content *c = L_GET_CPP_PTR_FROM_C_OBJECT(content); - if (c->getContentType() == LinphonePrivate::ContentType::FileTransfer) { + if (c->isFileTransfer()) { const LinphonePrivate::FileTransferContent *ftc = static_cast(c); - return ftc->getFileKey().size(); + return ftc->getFileKeySize(); } return 0; } void linphone_content_set_key(LinphoneContent *content, const char *key, const size_t keyLength) { LinphonePrivate::Content *c = L_GET_CPP_PTR_FROM_C_OBJECT(content); - if (c->getContentType() == LinphonePrivate::ContentType::FileTransfer) { + if (c->isFileTransfer()) { LinphonePrivate::FileTransferContent *ftc = static_cast(c); ftc->setFileKey(key, keyLength); } diff --git a/src/content/file-transfer-content.cpp b/src/content/file-transfer-content.cpp index 57ecff245..6dffb441d 100644 --- a/src/content/file-transfer-content.cpp +++ b/src/content/file-transfer-content.cpp @@ -166,6 +166,11 @@ const char *FileTransferContent::getFileKeyAsString() const { return d->fileKey.data(); } +size_t FileTransferContent::getFileKeySize() const { + L_D(); + return d->fileKey.size(); +} + bool FileTransferContent::isFile () const { return false; } diff --git a/src/content/file-transfer-content.h b/src/content/file-transfer-content.h index d107fcd52..0f29dc489 100644 --- a/src/content/file-transfer-content.h +++ b/src/content/file-transfer-content.h @@ -60,6 +60,7 @@ public: void setFileKey (const char *key, size_t size); const std::vector &getFileKey () const; const char *getFileKeyAsString () const; + size_t getFileKeySize() const; bool isFile () const override; bool isFileTransfer () const override; From b9b2ca63119127b2d59be2b2110d83e8bba85f50 Mon Sep 17 00:00:00 2001 From: Ronan Abhamon Date: Fri, 9 Feb 2018 10:57:25 +0100 Subject: [PATCH 09/67] feat(MainDb): add a security to delete basic chat room on migration when peer sip address is a server sip address chat room --- src/db/main-db.cpp | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/src/db/main-db.cpp b/src/db/main-db.cpp index 943426029..4b507cb6e 100644 --- a/src/db/main-db.cpp +++ b/src/db/main-db.cpp @@ -89,8 +89,10 @@ public: } catch (const soci::soci_error &e) { lWarning() << "Catched exception in MainDb::" << info.name << "."; soci::soci_error::error_category category = e.get_error_category(); - if ((category == soci::soci_error::connection_error - || category == soci::soci_error::unknown) && info.mainDb->forceReconnect()) { + if ( + (category == soci::soci_error::connection_error || category == soci::soci_error::unknown) && + info.mainDb->forceReconnect() + ) { mResult = mFunction(); return; } @@ -2528,6 +2530,19 @@ void MainDb::migrateBasicToClientGroupChatRoom ( const long long &localSipAddressId = d->insertSipAddress(newChatRoomId.getLocalAddress().asString()); const int &capabilities = clientGroupChatRoom->getCapabilities(); + { + shared_ptr buggyChatRoom = getCore()->findChatRoom(newChatRoomId); + if (buggyChatRoom) { + lError() << "Chat room was found with the same chat room id of a new migrated ClientGroupChatRoom!!!"; + AbstractChatRoom::CapabilitiesMask capabilities = buggyChatRoom->getCapabilities(); + if (capabilities & AbstractChatRoom::Capabilities::Basic) { + lError() << "Delete invalid basic chat room..."; + Core::deleteChatRoom(buggyChatRoom); + } else + lError() << "Unable to delete invalid chat room with capabilities: " << capabilities << "."; + } + } + *session << "UPDATE chat_room" " SET capabilities = :capabilities," " peer_sip_address_id = :peerSipAddressId," From 575370919d140cc2041ad50da21afd84a3608c07 Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Fri, 9 Feb 2018 13:41:27 +0100 Subject: [PATCH 10/67] More work on c-content.cpp --- src/c-wrapper/api/c-content.cpp | 94 ++++++++++++++++++++++----------- 1 file changed, 63 insertions(+), 31 deletions(-) diff --git a/src/c-wrapper/api/c-content.cpp b/src/c-wrapper/api/c-content.cpp index 3b7e009bd..99318aa23 100644 --- a/src/c-wrapper/api/c-content.cpp +++ b/src/c-wrapper/api/c-content.cpp @@ -32,9 +32,14 @@ using namespace std; L_DECLARE_C_CLONABLE_OBJECT_IMPL(Content, - SalBodyHandler *body_handler; void *cryptoContext; /**< crypto context used to encrypt file for RCS file transfer */ mutable char *name; + mutable char *type; + mutable char *subtype; + mutable char *body; + mutable size_t size; + mutable char *encoding; + mutable char *key; ) // ============================================================================= @@ -61,7 +66,9 @@ void linphone_content_set_user_data(LinphoneContent *content, void *ud) { // ============================================================================= const char * linphone_content_get_type(const LinphoneContent *content) { - return L_STRING_TO_C(L_GET_CPP_PTR_FROM_C_OBJECT(content)->getContentType().getType()); + if (content->type) ms_free(content->type); + content->type = ms_strdup(L_STRING_TO_C(L_GET_CPP_PTR_FROM_C_OBJECT(content)->getContentType().getType())); + return content->type; } void linphone_content_set_type(LinphoneContent *content, const char *type) { @@ -71,7 +78,9 @@ void linphone_content_set_type(LinphoneContent *content, const char *type) { } const char * linphone_content_get_subtype(const LinphoneContent *content) { - return L_STRING_TO_C(L_GET_CPP_PTR_FROM_C_OBJECT(content)->getContentType().getSubType()); + if (content->subtype) ms_free(content->subtype); + content->subtype = ms_strdup(L_STRING_TO_C(L_GET_CPP_PTR_FROM_C_OBJECT(content)->getContentType().getSubType())); + return content->subtype; } void linphone_content_set_subtype(LinphoneContent *content, const char *subtype) { @@ -89,7 +98,9 @@ void linphone_content_set_buffer(LinphoneContent *content, const uint8_t *buffer } const char * linphone_content_get_string_buffer(const LinphoneContent *content) { - return L_STRING_TO_C(L_GET_CPP_PTR_FROM_C_OBJECT(content)->getBodyAsString()); + if (content->body) ms_free(content->body); + content->body = ms_strdup(L_STRING_TO_C(L_GET_CPP_PTR_FROM_C_OBJECT(content)->getBodyAsString())); + return content->body; } void linphone_content_set_string_buffer(LinphoneContent *content, const char *buffer) { @@ -99,21 +110,22 @@ void linphone_content_set_string_buffer(LinphoneContent *content, const char *bu size_t linphone_content_get_size(const LinphoneContent *content) { size_t size = L_GET_CPP_PTR_FROM_C_OBJECT(content)->getSize(); if (size == 0) { - size = sal_body_handler_get_size(content->body_handler); + size = content->size; } return size; } void linphone_content_set_size(LinphoneContent *content, size_t size) { - sal_body_handler_set_size(content->body_handler, size); + content->size = size; } const char * linphone_content_get_encoding(const LinphoneContent *content) { - return sal_body_handler_get_encoding(content->body_handler); + return content->encoding; } void linphone_content_set_encoding(LinphoneContent *content, const char *encoding) { - sal_body_handler_set_encoding(content->body_handler, encoding); + if (content->encoding) ms_free(content->encoding); + content->encoding = ms_strdup(encoding); } const char * linphone_content_get_name(const LinphoneContent *content) { @@ -131,6 +143,8 @@ const char * linphone_content_get_name(const LinphoneContent *content) { } void linphone_content_set_name(LinphoneContent *content, const char *name) { + if (content->name) ms_free(content->name); + LinphonePrivate::Content *c = L_GET_CPP_PTR_FROM_C_OBJECT(content); if (c->isFile()) { LinphonePrivate::FileContent *fc = static_cast(c); @@ -139,38 +153,58 @@ void linphone_content_set_name(LinphoneContent *content, const char *name) { LinphonePrivate::FileTransferContent *ftc = static_cast(c); ftc->setFileName(L_C_TO_STRING(name)); } + content->name = ms_strdup(name); } bool_t linphone_content_is_multipart(const LinphoneContent *content) { - return sal_body_handler_is_multipart(content->body_handler); + SalBodyHandler *body_handler = sal_body_handler_from_content(content); + bool_t multipart = sal_body_handler_is_multipart(body_handler); + sal_body_handler_unref(body_handler); + return multipart; } LinphoneContent * linphone_content_get_part(const LinphoneContent *content, int idx) { SalBodyHandler *part_body_handler; - if (!linphone_content_is_multipart(content)) return NULL; - part_body_handler = sal_body_handler_get_part(content->body_handler, idx); + SalBodyHandler *body_handler = sal_body_handler_from_content(content); + if (!sal_body_handler_is_multipart(body_handler)) { + sal_body_handler_unref(body_handler); + return NULL; + } + part_body_handler = sal_body_handler_get_part(body_handler, idx); + sal_body_handler_unref(body_handler); return linphone_content_from_sal_body_handler(part_body_handler); } LinphoneContent * linphone_content_find_part_by_header(const LinphoneContent *content, const char *header_name, const char *header_value) { SalBodyHandler *part_body_handler; - if (!linphone_content_is_multipart(content)) return NULL; - part_body_handler = sal_body_handler_find_part_by_header(content->body_handler, header_name, header_value); + SalBodyHandler *body_handler = sal_body_handler_from_content(content); + if (!sal_body_handler_is_multipart(body_handler)) { + sal_body_handler_unref(body_handler); + return NULL; + } + part_body_handler = sal_body_handler_find_part_by_header(body_handler, header_name, header_value); + sal_body_handler_unref(body_handler); return linphone_content_from_sal_body_handler(part_body_handler); } const char * linphone_content_get_custom_header(const LinphoneContent *content, const char *header_name) { - return sal_body_handler_get_header(content->body_handler, header_name); + SalBodyHandler *body_handler = sal_body_handler_from_content(content); + const char *header = sal_body_handler_get_header(body_handler, header_name); + sal_body_handler_unref(body_handler); + return header; } const char *linphone_content_get_key(const LinphoneContent *content) { + if (content->key) ms_free(content->key); + const LinphonePrivate::Content *c = L_GET_CPP_PTR_FROM_C_OBJECT(content); if (c->isFileTransfer()) { const LinphonePrivate::FileTransferContent *ftc = static_cast(c); - return ftc->getFileKeyAsString(); + content->key = ms_strdup(ftc->getFileKeyAsString()); } - return NULL; + + return content->key; } size_t linphone_content_get_key_size(const LinphoneContent *content) { @@ -194,24 +228,17 @@ void linphone_content_set_key(LinphoneContent *content, const char *key, const s // Private functions. // ============================================================================= -static void linphone_content_set_sal_body_handler(LinphoneContent *content, SalBodyHandler *body_handler) { - if (content->body_handler != NULL) { - sal_body_handler_unref(content->body_handler); - content->body_handler = NULL; - } - content->body_handler = sal_body_handler_ref(body_handler); -} - static LinphoneContent * linphone_content_new_with_body_handler(SalBodyHandler *body_handler) { LinphoneContent *content = L_INIT(Content); content->cryptoContext = NULL; - if (body_handler == NULL) { - linphone_content_set_sal_body_handler(content, sal_body_handler_new()); - } else { - linphone_content_set_sal_body_handler(content, body_handler); - } LinphonePrivate::Content *c = new LinphonePrivate::Content(); L_SET_CPP_PTR_FROM_C_OBJECT(content, c); + if (body_handler != NULL) { + linphone_content_set_type(content, sal_body_handler_get_type(body_handler)); + linphone_content_set_subtype(content, sal_body_handler_get_subtype(body_handler)); + linphone_content_set_string_buffer(content, (char *)sal_body_handler_get_data(body_handler)); + linphone_content_set_encoding(content, sal_body_handler_get_encoding(body_handler)); + } return content; } @@ -220,7 +247,6 @@ LinphoneContent * linphone_content_new(void) { } LinphoneContent * linphone_content_copy(const LinphoneContent *ref) { - //TODO return (LinphoneContent *)belle_sip_object_ref(belle_sip_object_clone(BELLE_SIP_OBJECT(ref))); } @@ -242,5 +268,11 @@ LinphoneContent * linphone_content_from_sal_body_handler(SalBodyHandler *body_ha SalBodyHandler * sal_body_handler_from_content(const LinphoneContent *content) { if (content == NULL) return NULL; - return content->body_handler; + SalBodyHandler *body_handler = sal_body_handler_new(); + sal_body_handler_set_type(body_handler, belle_sip_strdup(linphone_content_get_type(content))); + sal_body_handler_set_subtype(body_handler, belle_sip_strdup(linphone_content_get_subtype(content))); + sal_body_handler_set_size(body_handler, linphone_content_get_size(content)); + sal_body_handler_set_data(body_handler, belle_sip_strdup(linphone_content_get_string_buffer(content))); + sal_body_handler_set_encoding(body_handler, belle_sip_strdup(linphone_content_get_encoding(content))); + return body_handler; } From 7e92d238a17d9718644ba0803887724737e6777f Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Fri, 9 Feb 2018 14:33:39 +0100 Subject: [PATCH 11/67] Fixed for c-content.cpp --- src/c-wrapper/api/c-content.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/c-wrapper/api/c-content.cpp b/src/c-wrapper/api/c-content.cpp index 99318aa23..2cf40c119 100644 --- a/src/c-wrapper/api/c-content.cpp +++ b/src/c-wrapper/api/c-content.cpp @@ -90,7 +90,7 @@ void linphone_content_set_subtype(LinphoneContent *content, const char *subtype) } uint8_t * linphone_content_get_buffer(const LinphoneContent *content) { - return (uint8_t *)L_STRING_TO_C(L_GET_CPP_PTR_FROM_C_OBJECT(content)->getBodyAsString()); + return (uint8_t *)L_GET_CPP_PTR_FROM_C_OBJECT(content)->getBody().data(); } void linphone_content_set_buffer(LinphoneContent *content, const uint8_t *buffer, size_t size) { @@ -99,12 +99,12 @@ void linphone_content_set_buffer(LinphoneContent *content, const uint8_t *buffer const char * linphone_content_get_string_buffer(const LinphoneContent *content) { if (content->body) ms_free(content->body); - content->body = ms_strdup(L_STRING_TO_C(L_GET_CPP_PTR_FROM_C_OBJECT(content)->getBodyAsString())); + content->body = ms_strdup(L_GET_CPP_PTR_FROM_C_OBJECT(content)->getBodyAsUtf8String().c_str()); return content->body; } void linphone_content_set_string_buffer(LinphoneContent *content, const char *buffer) { - L_GET_CPP_PTR_FROM_C_OBJECT(content)->setBody(L_C_TO_STRING(buffer)); + L_GET_CPP_PTR_FROM_C_OBJECT(content)->setBodyFromUtf8(L_C_TO_STRING(buffer)); } size_t linphone_content_get_size(const LinphoneContent *content) { @@ -269,10 +269,10 @@ LinphoneContent * linphone_content_from_sal_body_handler(SalBodyHandler *body_ha SalBodyHandler * sal_body_handler_from_content(const LinphoneContent *content) { if (content == NULL) return NULL; SalBodyHandler *body_handler = sal_body_handler_new(); - sal_body_handler_set_type(body_handler, belle_sip_strdup(linphone_content_get_type(content))); - sal_body_handler_set_subtype(body_handler, belle_sip_strdup(linphone_content_get_subtype(content))); + sal_body_handler_set_type(body_handler, linphone_content_get_type(content)); + sal_body_handler_set_subtype(body_handler, linphone_content_get_subtype(content)); sal_body_handler_set_size(body_handler, linphone_content_get_size(content)); sal_body_handler_set_data(body_handler, belle_sip_strdup(linphone_content_get_string_buffer(content))); - sal_body_handler_set_encoding(body_handler, belle_sip_strdup(linphone_content_get_encoding(content))); + if (content->encoding) sal_body_handler_set_encoding(body_handler, linphone_content_get_encoding(content)); return body_handler; } From ee87c0dcc1d3b02dc1ded5ef646967c75b9743fd Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Fri, 9 Feb 2018 16:22:41 +0100 Subject: [PATCH 12/67] Yet another c-content fix --- src/c-wrapper/api/c-content.cpp | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/c-wrapper/api/c-content.cpp b/src/c-wrapper/api/c-content.cpp index 2cf40c119..b38f55c12 100644 --- a/src/c-wrapper/api/c-content.cpp +++ b/src/c-wrapper/api/c-content.cpp @@ -172,8 +172,9 @@ LinphoneContent * linphone_content_get_part(const LinphoneContent *content, int return NULL; } part_body_handler = sal_body_handler_get_part(body_handler, idx); + LinphoneContent *result = linphone_content_from_sal_body_handler(part_body_handler); sal_body_handler_unref(body_handler); - return linphone_content_from_sal_body_handler(part_body_handler); + return result; } LinphoneContent * linphone_content_find_part_by_header(const LinphoneContent *content, const char *header_name, const char *header_value) { @@ -184,8 +185,9 @@ LinphoneContent * linphone_content_find_part_by_header(const LinphoneContent *co return NULL; } part_body_handler = sal_body_handler_find_part_by_header(body_handler, header_name, header_value); + LinphoneContent *result = linphone_content_from_sal_body_handler(part_body_handler); sal_body_handler_unref(body_handler); - return linphone_content_from_sal_body_handler(part_body_handler); + return result; } const char * linphone_content_get_custom_header(const LinphoneContent *content, const char *header_name) { @@ -236,8 +238,18 @@ static LinphoneContent * linphone_content_new_with_body_handler(SalBodyHandler * if (body_handler != NULL) { linphone_content_set_type(content, sal_body_handler_get_type(body_handler)); linphone_content_set_subtype(content, sal_body_handler_get_subtype(body_handler)); - linphone_content_set_string_buffer(content, (char *)sal_body_handler_get_data(body_handler)); - linphone_content_set_encoding(content, sal_body_handler_get_encoding(body_handler)); + if (!sal_body_handler_is_multipart(body_handler)) { + linphone_content_set_string_buffer(content, (char *)sal_body_handler_get_data(body_handler)); + } else { + string body; + belle_sip_multipart_body_handler_t *mpbh = BELLE_SIP_MULTIPART_BODY_HANDLER(body_handler); + for (const belle_sip_list_t *parts = belle_sip_multipart_body_handler_get_parts(mpbh); parts; parts = parts->next) { + belle_sip_body_handler_t *part = BELLE_SIP_BODY_HANDLER(parts->data); + body += (const char *)belle_sip_memory_body_handler_get_buffer(BELLE_SIP_MEMORY_BODY_HANDLER(part)); + } + linphone_content_set_string_buffer(content, body.c_str()); + } + if (sal_body_handler_get_encoding(body_handler)) linphone_content_set_encoding(content, sal_body_handler_get_encoding(body_handler)); } return content; } From 9a45223db4493b62b2cf5657b01b344caf9e6e35 Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Fri, 9 Feb 2018 17:12:28 +0100 Subject: [PATCH 13/67] Use ContentManager in c-content --- src/c-wrapper/api/c-content.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/c-wrapper/api/c-content.cpp b/src/c-wrapper/api/c-content.cpp index b38f55c12..5006d23d9 100644 --- a/src/c-wrapper/api/c-content.cpp +++ b/src/c-wrapper/api/c-content.cpp @@ -24,6 +24,7 @@ #include "content/content.h" #include "content/content-type.h" +#include "content/content-manager.h" #include "content/file-content.h" #include "content/file-transfer-content.h" @@ -158,10 +159,7 @@ void linphone_content_set_name(LinphoneContent *content, const char *name) { } bool_t linphone_content_is_multipart(const LinphoneContent *content) { - SalBodyHandler *body_handler = sal_body_handler_from_content(content); - bool_t multipart = sal_body_handler_is_multipart(body_handler); - sal_body_handler_unref(body_handler); - return multipart; + return L_GET_CPP_PTR_FROM_C_OBJECT(content)->getContentType() == LinphonePrivate::ContentType::Multipart; } LinphoneContent * linphone_content_get_part(const LinphoneContent *content, int idx) { @@ -241,13 +239,15 @@ static LinphoneContent * linphone_content_new_with_body_handler(SalBodyHandler * if (!sal_body_handler_is_multipart(body_handler)) { linphone_content_set_string_buffer(content, (char *)sal_body_handler_get_data(body_handler)); } else { - string body; belle_sip_multipart_body_handler_t *mpbh = BELLE_SIP_MULTIPART_BODY_HANDLER(body_handler); + list contents; for (const belle_sip_list_t *parts = belle_sip_multipart_body_handler_get_parts(mpbh); parts; parts = parts->next) { belle_sip_body_handler_t *part = BELLE_SIP_BODY_HANDLER(parts->data); - body += (const char *)belle_sip_memory_body_handler_get_buffer(BELLE_SIP_MEMORY_BODY_HANDLER(part)); + LinphoneContent *part_content = linphone_content_new_with_body_handler((SalBodyHandler *)part); + contents.push_back(*L_GET_CPP_PTR_FROM_C_OBJECT(part_content)); } - linphone_content_set_string_buffer(content, body.c_str()); + LinphonePrivate::Content multipartContent = LinphonePrivate::ContentManager::contentListToMultipart(contents); + linphone_content_set_string_buffer(content, multipartContent.getBodyAsUtf8String().c_str()); } if (sal_body_handler_get_encoding(body_handler)) linphone_content_set_encoding(content, sal_body_handler_get_encoding(body_handler)); } From 7a5a78c9b89123c20cefc982a2da0871a33d7d69 Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Mon, 12 Feb 2018 10:18:45 +0100 Subject: [PATCH 14/67] Fixes for multipart content --- src/c-wrapper/api/c-content.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/c-wrapper/api/c-content.cpp b/src/c-wrapper/api/c-content.cpp index 5006d23d9..8e135ecfa 100644 --- a/src/c-wrapper/api/c-content.cpp +++ b/src/c-wrapper/api/c-content.cpp @@ -280,11 +280,20 @@ LinphoneContent * linphone_content_from_sal_body_handler(SalBodyHandler *body_ha SalBodyHandler * sal_body_handler_from_content(const LinphoneContent *content) { if (content == NULL) return NULL; - SalBodyHandler *body_handler = sal_body_handler_new(); + SalBodyHandler *body_handler; + if (L_GET_CPP_PTR_FROM_C_OBJECT(content)->getContentType() == LinphonePrivate::ContentType::Multipart) { + size_t size = linphone_content_get_size(content); + char *buffer = ms_strdup(L_GET_CPP_PTR_FROM_C_OBJECT(content)->getBodyAsUtf8String().c_str()); + const char *boundary = L_STRING_TO_C(L_GET_CPP_PTR_FROM_C_OBJECT(content)->getContentType().getParameter()); + belle_sip_multipart_body_handler_t *bh = belle_sip_multipart_body_handler_new_from_buffer(buffer, size, boundary); + body_handler = (SalBodyHandler *)BELLE_SIP_BODY_HANDLER(bh); + } else { + body_handler = sal_body_handler_new(); + sal_body_handler_set_data(body_handler, belle_sip_strdup(linphone_content_get_string_buffer(content))); + } sal_body_handler_set_type(body_handler, linphone_content_get_type(content)); sal_body_handler_set_subtype(body_handler, linphone_content_get_subtype(content)); sal_body_handler_set_size(body_handler, linphone_content_get_size(content)); - sal_body_handler_set_data(body_handler, belle_sip_strdup(linphone_content_get_string_buffer(content))); if (content->encoding) sal_body_handler_set_encoding(body_handler, linphone_content_get_encoding(content)); return body_handler; } From f58dff4a2fefac0847b613891a32210d4c9d9ca5 Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Mon, 12 Feb 2018 11:14:41 +0100 Subject: [PATCH 15/67] Fixed linphone_content_get_buffer --- src/c-wrapper/api/c-content.cpp | 2 +- tester/eventapi_tester.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/c-wrapper/api/c-content.cpp b/src/c-wrapper/api/c-content.cpp index 8e135ecfa..211985bbb 100644 --- a/src/c-wrapper/api/c-content.cpp +++ b/src/c-wrapper/api/c-content.cpp @@ -91,7 +91,7 @@ void linphone_content_set_subtype(LinphoneContent *content, const char *subtype) } uint8_t * linphone_content_get_buffer(const LinphoneContent *content) { - return (uint8_t *)L_GET_CPP_PTR_FROM_C_OBJECT(content)->getBody().data(); + return (uint8_t *)linphone_content_get_string_buffer(content); } void linphone_content_set_buffer(LinphoneContent *content, const uint8_t *buffer, size_t size) { diff --git a/tester/eventapi_tester.c b/tester/eventapi_tester.c index 2119f3500..66ae0f165 100644 --- a/tester/eventapi_tester.c +++ b/tester/eventapi_tester.c @@ -41,7 +41,7 @@ void linphone_notify_received(LinphoneCore *lc, LinphoneEvent *lev, const char * if (!BC_ASSERT_PTR_NOT_NULL(content)) return; if (!linphone_content_is_multipart(content) && (!ua || !strstr(ua, "flexisip"))) { /*disable check for full presence server support*/ /*hack to disable content checking for list notify */ - BC_ASSERT_STRING_EQUAL(notify_content,(const char*)linphone_content_get_buffer(content)); + BC_ASSERT_STRING_EQUAL((const char*)linphone_content_get_buffer(content),notify_content); } mgr=get_manager(lc); mgr->stat.number_of_NotifyReceived++; From de6283928d2acea29f5922b9e87c5c6f1d51d815 Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Mon, 19 Mar 2018 17:26:35 +0100 Subject: [PATCH 16/67] Fixed issue with merge --- src/chat/modifier/file-transfer-chat-message-modifier.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/chat/modifier/file-transfer-chat-message-modifier.cpp b/src/chat/modifier/file-transfer-chat-message-modifier.cpp index fcdf15842..14733e4c8 100644 --- a/src/chat/modifier/file-transfer-chat-message-modifier.cpp +++ b/src/chat/modifier/file-transfer-chat-message-modifier.cpp @@ -298,7 +298,6 @@ void FileTransferChatMessageModifier::processResponseFromPostFile (const belle_h if (body && strlen(body) > 0) { FileTransferContent *fileTransferContent = new FileTransferContent(); fileTransferContent->setContentType(ContentType::FileTransfer); - message->addContent(fileTransferContent); LinphoneImEncryptionEngine *imee = linphone_core_get_im_encryption_engine(message->getCore()->getCCore()); bool_t is_file_encryption_enabled = FALSE; From b248771be135e8cb97431192ae205d2f168517c5 Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Mon, 19 Mar 2018 17:34:14 +0100 Subject: [PATCH 17/67] Removed content.c as it is not compiled anymore --- coreapi/content.c | 243 ---------------------------------------------- 1 file changed, 243 deletions(-) delete mode 100644 coreapi/content.c diff --git a/coreapi/content.c b/coreapi/content.c deleted file mode 100644 index 8d20964bd..000000000 --- a/coreapi/content.c +++ /dev/null @@ -1,243 +0,0 @@ -/* -linphone -Copyright (C) 2010-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 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, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "linphone/core.h" - -#include "c-wrapper/c-wrapper.h" - -// TODO: From coreapi. Remove me later. -#include "private.h" - -static void linphone_content_set_sal_body_handler(LinphoneContent *content, SalBodyHandler *body_handler) { - if (content->body_handler != NULL) { - sal_body_handler_unref(content->body_handler); - content->body_handler = NULL; - } - content->body_handler = sal_body_handler_ref(body_handler); -} - -static LinphoneContent * linphone_content_new_with_body_handler(SalBodyHandler *body_handler) { - LinphoneContent *content = belle_sip_object_new(LinphoneContent); - belle_sip_object_ref(content); - content->owned_fields = TRUE; - content->cryptoContext = NULL; /* this field is managed externally by encryption/decryption functions so be careful to initialise it to NULL */ - if (body_handler == NULL) { - linphone_content_set_sal_body_handler(content, sal_body_handler_new()); - } else { - linphone_content_set_sal_body_handler(content, body_handler); - } - return content; -} - -static void linphone_content_destroy(LinphoneContent *content) { - if (content->owned_fields == TRUE) { - if (content->body_handler) sal_body_handler_unref(content->body_handler); - if (content->name) belle_sip_free(content->name); - if (content->key) belle_sip_free(content->key); - /* note : crypto context is allocated/destroyed by the encryption function */ - } -} - -static void linphone_content_clone(LinphoneContent *obj, const LinphoneContent *ref) { - obj->owned_fields = TRUE; - linphone_content_set_sal_body_handler(obj, sal_body_handler_new()); - if ((linphone_content_get_type(ref) != NULL) || (linphone_content_get_subtype(ref) != NULL)) { - linphone_content_set_type(obj, linphone_content_get_type(ref)); - linphone_content_set_subtype(obj, linphone_content_get_subtype(ref)); - } - if (linphone_content_get_encoding(ref) != NULL) { - linphone_content_set_encoding(obj, linphone_content_get_encoding(ref)); - } - linphone_content_set_name(obj, linphone_content_get_name(ref)); - linphone_content_set_key(obj, linphone_content_get_key(ref), linphone_content_get_key_size(ref)); - if (linphone_content_get_buffer(ref) != NULL) { - linphone_content_set_buffer(obj, linphone_content_get_buffer(ref), linphone_content_get_size(ref)); - } else { - linphone_content_set_size(obj, linphone_content_get_size(ref)); - } -} - - -BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(LinphoneContent); - -BELLE_SIP_INSTANCIATE_VPTR(LinphoneContent, belle_sip_object_t, - (belle_sip_object_destroy_t)linphone_content_destroy, - (belle_sip_object_clone_t)linphone_content_clone, - NULL, // marshal - TRUE -); - - -LinphoneContent * linphone_core_create_content(LinphoneCore *lc) { - return linphone_content_new(); -} - -LinphoneContent * linphone_content_ref(LinphoneContent *content) { - belle_sip_object_ref(content); - return content; -} - -void linphone_content_unref(LinphoneContent *content) { - belle_sip_object_unref(content); -} - -void *linphone_content_get_user_data(const LinphoneContent *content) { - return content->user_data; -} - -void linphone_content_set_user_data(LinphoneContent *content, void *ud) { - content->user_data = ud; -} - -const char * linphone_content_get_type(const LinphoneContent *content) { - return sal_body_handler_get_type(content->body_handler); -} - -void linphone_content_set_type(LinphoneContent *content, const char *type) { - sal_body_handler_set_type(content->body_handler, type); -} - -const char * linphone_content_get_subtype(const LinphoneContent *content) { - return sal_body_handler_get_subtype(content->body_handler); -} - -void linphone_content_set_subtype(LinphoneContent *content, const char *subtype) { - sal_body_handler_set_subtype(content->body_handler, subtype); -} - -uint8_t * linphone_content_get_buffer(const LinphoneContent *content) { - return (uint8_t *)sal_body_handler_get_data(content->body_handler); -} - -void linphone_content_set_buffer(LinphoneContent *content, const uint8_t *buffer, size_t size) { - void *data; - sal_body_handler_set_size(content->body_handler, size); - data = belle_sip_malloc(size + 1); - memcpy(data, buffer, size); - ((char *)data)[size] = '\0'; - sal_body_handler_set_data(content->body_handler, data); -} - -const char * linphone_content_get_string_buffer(const LinphoneContent *content) { - return (const char *)linphone_content_get_buffer(content); -} - -void linphone_content_set_string_buffer(LinphoneContent *content, const char *buffer) { - sal_body_handler_set_size(content->body_handler, strlen(buffer)); - sal_body_handler_set_data(content->body_handler, belle_sip_strdup(buffer)); -} - -size_t linphone_content_get_size(const LinphoneContent *content) { - return sal_body_handler_get_size(content->body_handler); -} - -void linphone_content_set_size(LinphoneContent *content, size_t size) { - sal_body_handler_set_size(content->body_handler, size); -} - -const char * linphone_content_get_encoding(const LinphoneContent *content) { - return sal_body_handler_get_encoding(content->body_handler); -} - -void linphone_content_set_encoding(LinphoneContent *content, const char *encoding) { - sal_body_handler_set_encoding(content->body_handler, encoding); -} - -const char * linphone_content_get_name(const LinphoneContent *content) { - return content->name; -} - -void linphone_content_set_name(LinphoneContent *content, const char *name) { - if (content->name != NULL) { - belle_sip_free(content->name); - content->name = NULL; - } - if (name != NULL) { - content->name = belle_sip_strdup(name); - } -} - -size_t linphone_content_get_key_size(const LinphoneContent *content) { - return content->keyLength; -} - -const char * linphone_content_get_key(const LinphoneContent *content) { - return content->key; -} - -void linphone_content_set_key(LinphoneContent *content, const char *key, const size_t keyLength) { - if (content->key != NULL) { - belle_sip_free(content->key); - content->key = NULL; - } - if (key != NULL) { - content->key = reinterpret_cast(belle_sip_malloc(keyLength + 1)); - memcpy(content->key, key, keyLength); - content->key[keyLength] = '\0'; - content->keyLength = keyLength; - } -} - -/* crypto context is managed(allocated/freed) by the encryption function, so provide the address of field in the private structure */ -void ** linphone_content_get_cryptoContext_address(LinphoneContent *content) { - return &(content->cryptoContext); -} - -bool_t linphone_content_is_multipart(const LinphoneContent *content) { - return sal_body_handler_is_multipart(content->body_handler); -} - -LinphoneContent * linphone_content_get_part(const LinphoneContent *content, int idx) { - SalBodyHandler *part_body_handler; - if (!linphone_content_is_multipart(content)) return NULL; - part_body_handler = sal_body_handler_get_part(content->body_handler, idx); - return linphone_content_from_sal_body_handler(part_body_handler); -} - -LinphoneContent * linphone_content_find_part_by_header(const LinphoneContent *content, const char *header_name, const char *header_value) { - SalBodyHandler *part_body_handler; - if (!linphone_content_is_multipart(content)) return NULL; - part_body_handler = sal_body_handler_find_part_by_header(content->body_handler, header_name, header_value); - return linphone_content_from_sal_body_handler(part_body_handler); -} - -const char * linphone_content_get_custom_header(const LinphoneContent *content, const char *header_name) { - return sal_body_handler_get_header(content->body_handler, header_name); -} - - -LinphoneContent * linphone_content_new(void) { - return linphone_content_new_with_body_handler(NULL); -} - -LinphoneContent * linphone_content_copy(const LinphoneContent *ref) { - return (LinphoneContent *)belle_sip_object_ref(belle_sip_object_clone(BELLE_SIP_OBJECT(ref))); -} - -LinphoneContent * linphone_content_from_sal_body_handler(SalBodyHandler *body_handler) { - if (body_handler) { - return linphone_content_new_with_body_handler(body_handler); - } - return NULL; -} - -SalBodyHandler * sal_body_handler_from_content(const LinphoneContent *content) { - if (content == NULL) return NULL; - return content->body_handler; -} From 472f010e81dc09a1f3a29ff3656e9348ce114ec9 Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Tue, 20 Mar 2018 11:44:53 +0100 Subject: [PATCH 18/67] Fixed leak of LinphoneContent --- src/c-wrapper/api/c-chat-message.cpp | 2 +- src/chat/modifier/file-transfer-chat-message-modifier.cpp | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/c-wrapper/api/c-chat-message.cpp b/src/c-wrapper/api/c-chat-message.cpp index c9ee6184b..b191027ed 100644 --- a/src/c-wrapper/api/c-chat-message.cpp +++ b/src/c-wrapper/api/c-chat-message.cpp @@ -291,7 +291,7 @@ int linphone_chat_message_set_text(LinphoneChatMessage *msg, const char* text) { LinphoneContent *linphone_chat_message_get_file_transfer_information(LinphoneChatMessage *msg) { const LinphonePrivate::Content *content = L_GET_PRIVATE_FROM_C_OBJECT(msg)->getFileTransferInformation(); - if (content) return linphone_content_ref(L_GET_C_BACK_PTR(content)); + if (content) return L_GET_C_BACK_PTR(content); return NULL; } diff --git a/src/chat/modifier/file-transfer-chat-message-modifier.cpp b/src/chat/modifier/file-transfer-chat-message-modifier.cpp index 14733e4c8..6bebbfa0b 100644 --- a/src/chat/modifier/file-transfer-chat-message-modifier.cpp +++ b/src/chat/modifier/file-transfer-chat-message-modifier.cpp @@ -723,6 +723,7 @@ void FileTransferChatMessageModifier::onRecvBody (belle_sip_user_body_handler_t // Legacy: call back given by application level linphone_core_notify_file_transfer_recv(message->getCore()->getCCore(), msg, content, (const char *)buffer, size); } + linphone_content_unref(content); } } else { lWarning() << "File transfer decrypt failed with code " << (int)retval; From 61b45fd7a413eedd1d5000e0a05149e7878f1b71 Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Tue, 20 Mar 2018 14:20:11 +0100 Subject: [PATCH 19/67] Fixed issue with server presence & content headers --- src/c-wrapper/api/c-content.cpp | 22 ++++++++++++++++++++-- src/content/content-manager.cpp | 18 ++++++++++-------- src/content/content-type.cpp | 3 +++ src/content/content-type.h | 2 ++ 4 files changed, 35 insertions(+), 10 deletions(-) diff --git a/src/c-wrapper/api/c-content.cpp b/src/c-wrapper/api/c-content.cpp index 211985bbb..30021cbb7 100644 --- a/src/c-wrapper/api/c-content.cpp +++ b/src/c-wrapper/api/c-content.cpp @@ -159,7 +159,7 @@ void linphone_content_set_name(LinphoneContent *content, const char *name) { } bool_t linphone_content_is_multipart(const LinphoneContent *content) { - return L_GET_CPP_PTR_FROM_C_OBJECT(content)->getContentType() == LinphonePrivate::ContentType::Multipart; + return L_GET_CPP_PTR_FROM_C_OBJECT(content)->getContentType().isMultipart(); } LinphoneContent * linphone_content_get_part(const LinphoneContent *content, int idx) { @@ -244,6 +244,13 @@ static LinphoneContent * linphone_content_new_with_body_handler(SalBodyHandler * for (const belle_sip_list_t *parts = belle_sip_multipart_body_handler_get_parts(mpbh); parts; parts = parts->next) { belle_sip_body_handler_t *part = BELLE_SIP_BODY_HANDLER(parts->data); LinphoneContent *part_content = linphone_content_new_with_body_handler((SalBodyHandler *)part); + + const belle_sip_list_t *headers = belle_sip_body_handler_get_headers(part); + for (; headers != NULL; headers = headers->next) { + belle_sip_header_t *header = BELLE_SIP_HEADER(headers->data); + L_GET_CPP_PTR_FROM_C_OBJECT(part_content)->addHeader(belle_sip_header_get_name(header), belle_sip_header_get_unparsed_value(header)); + } + contents.push_back(*L_GET_CPP_PTR_FROM_C_OBJECT(part_content)); } LinphonePrivate::Content multipartContent = LinphonePrivate::ContentManager::contentListToMultipart(contents); @@ -281,7 +288,7 @@ LinphoneContent * linphone_content_from_sal_body_handler(SalBodyHandler *body_ha SalBodyHandler * sal_body_handler_from_content(const LinphoneContent *content) { if (content == NULL) return NULL; SalBodyHandler *body_handler; - if (L_GET_CPP_PTR_FROM_C_OBJECT(content)->getContentType() == LinphonePrivate::ContentType::Multipart) { + if (L_GET_CPP_PTR_FROM_C_OBJECT(content)->getContentType().isMultipart()) { size_t size = linphone_content_get_size(content); char *buffer = ms_strdup(L_GET_CPP_PTR_FROM_C_OBJECT(content)->getBodyAsUtf8String().c_str()); const char *boundary = L_STRING_TO_C(L_GET_CPP_PTR_FROM_C_OBJECT(content)->getContentType().getParameter()); @@ -291,6 +298,17 @@ SalBodyHandler * sal_body_handler_from_content(const LinphoneContent *content) { body_handler = sal_body_handler_new(); sal_body_handler_set_data(body_handler, belle_sip_strdup(linphone_content_get_string_buffer(content))); } + + for (const auto &header : L_GET_CPP_PTR_FROM_C_OBJECT(content)->getHeaders()) { + belle_sip_header_t *additionalHeader = BELLE_SIP_HEADER( + belle_sip_header_create( + header.first.c_str(), + header.second.c_str() + ) + ); + belle_sip_body_handler_add_header(BELLE_SIP_BODY_HANDLER(body_handler), additionalHeader); + } + sal_body_handler_set_type(body_handler, linphone_content_get_type(content)); sal_body_handler_set_subtype(body_handler, linphone_content_get_subtype(content)); sal_body_handler_set_size(body_handler, linphone_content_get_size(content)); diff --git a/src/content/content-manager.cpp b/src/content/content-manager.cpp index 94ee69ce9..d4c286c79 100644 --- a/src/content/content-manager.cpp +++ b/src/content/content-manager.cpp @@ -45,23 +45,25 @@ list ContentManager::multipartToContentList (const Content &content) { list contents; for (const belle_sip_list_t *parts = belle_sip_multipart_body_handler_get_parts(mpbh); parts; parts = parts->next) { belle_sip_body_handler_t *part = BELLE_SIP_BODY_HANDLER(parts->data); - belle_sip_header_content_type_t *partContentType = nullptr; + Content content; + for (const belle_sip_list_t *it = belle_sip_body_handler_get_headers(part); it; it = it->next) { belle_sip_header_t *header = BELLE_SIP_HEADER(it->data); if (strcasecmp("Content-Type", belle_sip_header_get_name(header)) == 0) { - partContentType = BELLE_SIP_HEADER_CONTENT_TYPE(header); - break; + belle_sip_header_content_type_t * partContentType = BELLE_SIP_HEADER_CONTENT_TYPE(header); + content.setContentType(ContentType( + belle_sip_header_content_type_get_type(partContentType), + belle_sip_header_content_type_get_subtype(partContentType) + )); + } else { + content.addHeader(belle_sip_header_get_name(header), belle_sip_header_get_unparsed_value(header)); } } - Content content; content.setBody(static_cast( belle_sip_memory_body_handler_get_buffer(BELLE_SIP_MEMORY_BODY_HANDLER(part)) )); - content.setContentType(ContentType( - belle_sip_header_content_type_get_type(partContentType), - belle_sip_header_content_type_get_subtype(partContentType) - )); + contents.push_back(move(content)); } diff --git a/src/content/content-type.cpp b/src/content/content-type.cpp index 78c356af6..e457ff828 100644 --- a/src/content/content-type.cpp +++ b/src/content/content-type.cpp @@ -172,6 +172,9 @@ string ContentType::asString () const { return ""; } +bool ContentType::isMultipart() const { + return getType() == "multipart"; +} bool ContentType::isFile () const { // TODO Remove when not needed anymore in step 2.1 of maindb diff --git a/src/content/content-type.h b/src/content/content-type.h index b13063115..bdf51c75d 100644 --- a/src/content/content-type.h +++ b/src/content/content-type.h @@ -60,6 +60,8 @@ public: std::string asString () const; + bool isMultipart() const; + static bool isFile (const ContentType &contentType); static const ContentType ConferenceInfo; From fd6b049203f3502ac1ad1086580517468e7898c8 Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Tue, 20 Mar 2018 14:46:45 +0100 Subject: [PATCH 20/67] Fixed LinphoneContent leak --- src/c-wrapper/api/c-content.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/c-wrapper/api/c-content.cpp b/src/c-wrapper/api/c-content.cpp index 30021cbb7..d487e8847 100644 --- a/src/c-wrapper/api/c-content.cpp +++ b/src/c-wrapper/api/c-content.cpp @@ -252,6 +252,7 @@ static LinphoneContent * linphone_content_new_with_body_handler(SalBodyHandler * } contents.push_back(*L_GET_CPP_PTR_FROM_C_OBJECT(part_content)); + linphone_content_unref(part_content); } LinphonePrivate::Content multipartContent = LinphonePrivate::ContentManager::contentListToMultipart(contents); linphone_content_set_string_buffer(content, multipartContent.getBodyAsUtf8String().c_str()); From cf2b6ca2bf87a2333c02d093362981fb25dfbd57 Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Wed, 21 Mar 2018 10:51:19 +0100 Subject: [PATCH 21/67] Fixed content type parameters between SalBodyHandler and Content --- coreapi/bellesip_sal/sal_impl.c | 20 ++++++++++++++++++++ src/c-wrapper/api/c-content.cpp | 24 ++++++++++++++++++------ src/c-wrapper/internal/c-sal.h | 2 ++ 3 files changed, 40 insertions(+), 6 deletions(-) diff --git a/coreapi/bellesip_sal/sal_impl.c b/coreapi/bellesip_sal/sal_impl.c index ad11525fb..71578364b 100644 --- a/coreapi/bellesip_sal/sal_impl.c +++ b/coreapi/bellesip_sal/sal_impl.c @@ -348,6 +348,26 @@ void sal_body_handler_set_subtype(SalBodyHandler *body_handler, const char *subt belle_sip_header_content_type_set_subtype(content_type, subtype); } +char * sal_body_handler_get_content_type_parameters(const SalBodyHandler *body_handler) { + belle_sip_header_content_type_t *content_type = BELLE_SIP_HEADER_CONTENT_TYPE(sal_body_handler_find_header(body_handler, "Content-Type")); + if (content_type != NULL) { + char buff[2048]; + size_t buff_size = sizeof(buff); + size_t offset = 0; + belle_sip_parameters_marshal(BELLE_SIP_PARAMETERS(content_type), buff, buff_size, &offset); + buff[offset]='\0'; + return strdup(buff); + } + return NULL; +} + +void sal_body_handler_set_content_type_parameters(SalBodyHandler *body_handler, const char *params) { + belle_sip_header_content_type_t *content_type = BELLE_SIP_HEADER_CONTENT_TYPE(sal_body_handler_find_header(body_handler, "Content-Type")); + if (content_type != NULL) { + belle_sip_parameters_set(BELLE_SIP_PARAMETERS(content_type), params); + } +} + const char * sal_body_handler_get_encoding(const SalBodyHandler *body_handler) { belle_sip_header_t *content_encoding = sal_body_handler_find_header(body_handler, "Content-Encoding"); if (content_encoding != NULL) { diff --git a/src/c-wrapper/api/c-content.cpp b/src/c-wrapper/api/c-content.cpp index d487e8847..572444ddf 100644 --- a/src/c-wrapper/api/c-content.cpp +++ b/src/c-wrapper/api/c-content.cpp @@ -233,9 +233,14 @@ static LinphoneContent * linphone_content_new_with_body_handler(SalBodyHandler * content->cryptoContext = NULL; LinphonePrivate::Content *c = new LinphonePrivate::Content(); L_SET_CPP_PTR_FROM_C_OBJECT(content, c); + if (body_handler != NULL) { - linphone_content_set_type(content, sal_body_handler_get_type(body_handler)); - linphone_content_set_subtype(content, sal_body_handler_get_subtype(body_handler)); + LinphonePrivate::ContentType ct = c->getContentType(); + ct.setType(sal_body_handler_get_type(body_handler)); + ct.setSubType(sal_body_handler_get_subtype(body_handler)); + ct.setParameter(sal_body_handler_get_content_type_parameters(body_handler)); + c->setContentType(ct); + if (!sal_body_handler_is_multipart(body_handler)) { linphone_content_set_string_buffer(content, (char *)sal_body_handler_get_data(body_handler)); } else { @@ -257,8 +262,10 @@ static LinphoneContent * linphone_content_new_with_body_handler(SalBodyHandler * LinphonePrivate::Content multipartContent = LinphonePrivate::ContentManager::contentListToMultipart(contents); linphone_content_set_string_buffer(content, multipartContent.getBodyAsUtf8String().c_str()); } + if (sal_body_handler_get_encoding(body_handler)) linphone_content_set_encoding(content, sal_body_handler_get_encoding(body_handler)); } + return content; } @@ -288,11 +295,14 @@ LinphoneContent * linphone_content_from_sal_body_handler(SalBodyHandler *body_ha SalBodyHandler * sal_body_handler_from_content(const LinphoneContent *content) { if (content == NULL) return NULL; + SalBodyHandler *body_handler; - if (L_GET_CPP_PTR_FROM_C_OBJECT(content)->getContentType().isMultipart()) { + LinphonePrivate::ContentType contentType = L_GET_CPP_PTR_FROM_C_OBJECT(content)->getContentType(); + + if (contentType.isMultipart()) { size_t size = linphone_content_get_size(content); char *buffer = ms_strdup(L_GET_CPP_PTR_FROM_C_OBJECT(content)->getBodyAsUtf8String().c_str()); - const char *boundary = L_STRING_TO_C(L_GET_CPP_PTR_FROM_C_OBJECT(content)->getContentType().getParameter()); + const char *boundary = L_STRING_TO_C(contentType.getParameter()); belle_sip_multipart_body_handler_t *bh = belle_sip_multipart_body_handler_new_from_buffer(buffer, size, boundary); body_handler = (SalBodyHandler *)BELLE_SIP_BODY_HANDLER(bh); } else { @@ -310,9 +320,11 @@ SalBodyHandler * sal_body_handler_from_content(const LinphoneContent *content) { belle_sip_body_handler_add_header(BELLE_SIP_BODY_HANDLER(body_handler), additionalHeader); } - sal_body_handler_set_type(body_handler, linphone_content_get_type(content)); - sal_body_handler_set_subtype(body_handler, linphone_content_get_subtype(content)); + sal_body_handler_set_type(body_handler, contentType.getType().c_str()); + sal_body_handler_set_subtype(body_handler, contentType.getSubType().c_str()); sal_body_handler_set_size(body_handler, linphone_content_get_size(content)); + sal_body_handler_set_content_type_parameters(body_handler, contentType.getParameter().c_str()); if (content->encoding) sal_body_handler_set_encoding(body_handler, linphone_content_get_encoding(content)); + return body_handler; } diff --git a/src/c-wrapper/internal/c-sal.h b/src/c-wrapper/internal/c-sal.h index 4aeca0042..3f53db90c 100644 --- a/src/c-wrapper/internal/c-sal.h +++ b/src/c-wrapper/internal/c-sal.h @@ -636,6 +636,8 @@ const char * sal_body_handler_get_type(const SalBodyHandler *body_handler); void sal_body_handler_set_type(SalBodyHandler *body_handler, const char *type); const char * sal_body_handler_get_subtype(const SalBodyHandler *body_handler); void sal_body_handler_set_subtype(SalBodyHandler *body_handler, const char *subtype); +char * sal_body_handler_get_content_type_parameters(const SalBodyHandler *body_handler); +void sal_body_handler_set_content_type_parameters(SalBodyHandler *body_handler, const char *params); const char * sal_body_handler_get_encoding(const SalBodyHandler *body_handler); void sal_body_handler_set_encoding(SalBodyHandler *body_handler, const char *encoding); void * sal_body_handler_get_data(const SalBodyHandler *body_handler); From 8a30c727dbe925e4783dddc078a1598773321871 Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Wed, 21 Mar 2018 13:20:49 +0100 Subject: [PATCH 22/67] Improved parameter use in ContentType --- coreapi/bellesip_sal/sal_impl.c | 21 ++-- include/linphone/api/c-content.h | 8 ++ src/CMakeLists.txt | 2 + src/c-wrapper/api/c-content.cpp | 27 +++-- src/c-wrapper/internal/c-sal.h | 5 +- src/chat/chat-message/chat-message.cpp | 5 +- .../multipart-chat-message-modifier.cpp | 5 +- src/content/content-manager.cpp | 2 +- src/content/content-type.cpp | 91 ++++++++++++--- src/content/content-type.h | 16 ++- src/content/header-param.cpp | 105 ++++++++++++++++++ src/content/header-param.h | 61 ++++++++++ 12 files changed, 307 insertions(+), 41 deletions(-) create mode 100644 src/content/header-param.cpp create mode 100644 src/content/header-param.h diff --git a/coreapi/bellesip_sal/sal_impl.c b/coreapi/bellesip_sal/sal_impl.c index 71578364b..99c859f52 100644 --- a/coreapi/bellesip_sal/sal_impl.c +++ b/coreapi/bellesip_sal/sal_impl.c @@ -348,23 +348,26 @@ void sal_body_handler_set_subtype(SalBodyHandler *body_handler, const char *subt belle_sip_header_content_type_set_subtype(content_type, subtype); } -char * sal_body_handler_get_content_type_parameters(const SalBodyHandler *body_handler) { +const belle_sip_list_t * sal_body_handler_get_content_type_parameters_names(const SalBodyHandler *body_handler) { belle_sip_header_content_type_t *content_type = BELLE_SIP_HEADER_CONTENT_TYPE(sal_body_handler_find_header(body_handler, "Content-Type")); if (content_type != NULL) { - char buff[2048]; - size_t buff_size = sizeof(buff); - size_t offset = 0; - belle_sip_parameters_marshal(BELLE_SIP_PARAMETERS(content_type), buff, buff_size, &offset); - buff[offset]='\0'; - return strdup(buff); + return belle_sip_parameters_get_parameter_names(BELLE_SIP_PARAMETERS(content_type)); } return NULL; } -void sal_body_handler_set_content_type_parameters(SalBodyHandler *body_handler, const char *params) { +const char * sal_body_handler_get_content_type_parameter(const SalBodyHandler *body_handler, const char *name) { belle_sip_header_content_type_t *content_type = BELLE_SIP_HEADER_CONTENT_TYPE(sal_body_handler_find_header(body_handler, "Content-Type")); if (content_type != NULL) { - belle_sip_parameters_set(BELLE_SIP_PARAMETERS(content_type), params); + return belle_sip_parameters_get_parameter(BELLE_SIP_PARAMETERS(content_type), name); + } + return NULL; +} + +void sal_body_handler_set_content_type_parameter(SalBodyHandler *body_handler, const char *paramName, const char *paramValue) { + belle_sip_header_content_type_t *content_type = BELLE_SIP_HEADER_CONTENT_TYPE(sal_body_handler_find_header(body_handler, "Content-Type")); + if (content_type != NULL) { + belle_sip_parameters_set_parameter(BELLE_SIP_PARAMETERS(content_type), paramName, paramValue); } } diff --git a/include/linphone/api/c-content.h b/include/linphone/api/c-content.h index fa030a309..5cdd27663 100644 --- a/include/linphone/api/c-content.h +++ b/include/linphone/api/c-content.h @@ -88,6 +88,14 @@ LINPHONE_PUBLIC const char * linphone_content_get_subtype(const LinphoneContent */ LINPHONE_PUBLIC void linphone_content_set_subtype(LinphoneContent *content, const char *subtype); +/** + * Adds a parameter to the ContentType header. + * @param[in] content LinphoneContent object. + * @param[in] name the name of the parameter to add. + * @param[in] value the value of the parameter to add. + */ +LINPHONE_PUBLIC void linphone_content_add_content_type_parameter(LinphoneContent *content, const char *name, const char *value); + /** * Get the content data buffer, usually a string. * @param[in] content LinphoneContent object. diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 11377efe9..66d42b91e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -99,6 +99,7 @@ set(LINPHONE_CXX_OBJECTS_PRIVATE_HEADER_FILES content/content.h content/file-content.h content/file-transfer-content.h + content/header-param.h core/core-accessor.h core/core-listener.h core/core-p.h @@ -223,6 +224,7 @@ set(LINPHONE_CXX_OBJECTS_SOURCE_FILES content/content.cpp content/file-content.cpp content/file-transfer-content.cpp + content/header-param.cpp core/core-accessor.cpp core/core-call.cpp core/core-chat-room.cpp diff --git a/src/c-wrapper/api/c-content.cpp b/src/c-wrapper/api/c-content.cpp index 572444ddf..5e6c2e94a 100644 --- a/src/c-wrapper/api/c-content.cpp +++ b/src/c-wrapper/api/c-content.cpp @@ -24,6 +24,7 @@ #include "content/content.h" #include "content/content-type.h" +#include "content/header-param.h" #include "content/content-manager.h" #include "content/file-content.h" #include "content/file-transfer-content.h" @@ -90,6 +91,12 @@ void linphone_content_set_subtype(LinphoneContent *content, const char *subtype) L_GET_CPP_PTR_FROM_C_OBJECT(content)->setContentType(ct); } +void linphone_content_add_content_type_parameter(LinphoneContent *content, const char *name, const char *value) { + LinphonePrivate::ContentType ct = L_GET_CPP_PTR_FROM_C_OBJECT(content)->getContentType(); + ct.addParameter(L_C_TO_STRING(name), L_C_TO_STRING(value)); + L_GET_CPP_PTR_FROM_C_OBJECT(content)->setContentType(ct); +} + uint8_t * linphone_content_get_buffer(const LinphoneContent *content) { return (uint8_t *)linphone_content_get_string_buffer(content); } @@ -235,13 +242,15 @@ static LinphoneContent * linphone_content_new_with_body_handler(SalBodyHandler * L_SET_CPP_PTR_FROM_C_OBJECT(content, c); if (body_handler != NULL) { - LinphonePrivate::ContentType ct = c->getContentType(); - ct.setType(sal_body_handler_get_type(body_handler)); - ct.setSubType(sal_body_handler_get_subtype(body_handler)); - ct.setParameter(sal_body_handler_get_content_type_parameters(body_handler)); - c->setContentType(ct); + linphone_content_set_type(content, sal_body_handler_get_type(body_handler)); + linphone_content_set_subtype(content, sal_body_handler_get_subtype(body_handler)); + for (const belle_sip_list_t *params = sal_body_handler_get_content_type_parameters_names(body_handler); params; params = params->next) { + const char *paramName = (const char *)(params->data); + const char *paramValue = sal_body_handler_get_content_type_parameter(body_handler, paramName); + linphone_content_add_content_type_parameter(content, paramName, paramValue); + } - if (!sal_body_handler_is_multipart(body_handler)) { + if (!linphone_content_is_multipart(content)) { linphone_content_set_string_buffer(content, (char *)sal_body_handler_get_data(body_handler)); } else { belle_sip_multipart_body_handler_t *mpbh = BELLE_SIP_MULTIPART_BODY_HANDLER(body_handler); @@ -302,7 +311,7 @@ SalBodyHandler * sal_body_handler_from_content(const LinphoneContent *content) { if (contentType.isMultipart()) { size_t size = linphone_content_get_size(content); char *buffer = ms_strdup(L_GET_CPP_PTR_FROM_C_OBJECT(content)->getBodyAsUtf8String().c_str()); - const char *boundary = L_STRING_TO_C(contentType.getParameter()); + const char *boundary = L_STRING_TO_C(contentType.getParameter("boundary").getValue()); belle_sip_multipart_body_handler_t *bh = belle_sip_multipart_body_handler_new_from_buffer(buffer, size, boundary); body_handler = (SalBodyHandler *)BELLE_SIP_BODY_HANDLER(bh); } else { @@ -323,7 +332,9 @@ SalBodyHandler * sal_body_handler_from_content(const LinphoneContent *content) { sal_body_handler_set_type(body_handler, contentType.getType().c_str()); sal_body_handler_set_subtype(body_handler, contentType.getSubType().c_str()); sal_body_handler_set_size(body_handler, linphone_content_get_size(content)); - sal_body_handler_set_content_type_parameters(body_handler, contentType.getParameter().c_str()); + for (const auto ¶m : contentType.getParameters()) { + sal_body_handler_set_content_type_parameter(body_handler, param.getName().c_str(), param.getValue().c_str()); + } if (content->encoding) sal_body_handler_set_encoding(body_handler, linphone_content_get_encoding(content)); return body_handler; diff --git a/src/c-wrapper/internal/c-sal.h b/src/c-wrapper/internal/c-sal.h index 3f53db90c..dd2e53f8f 100644 --- a/src/c-wrapper/internal/c-sal.h +++ b/src/c-wrapper/internal/c-sal.h @@ -636,8 +636,9 @@ const char * sal_body_handler_get_type(const SalBodyHandler *body_handler); void sal_body_handler_set_type(SalBodyHandler *body_handler, const char *type); const char * sal_body_handler_get_subtype(const SalBodyHandler *body_handler); void sal_body_handler_set_subtype(SalBodyHandler *body_handler, const char *subtype); -char * sal_body_handler_get_content_type_parameters(const SalBodyHandler *body_handler); -void sal_body_handler_set_content_type_parameters(SalBodyHandler *body_handler, const char *params); +const belle_sip_list_t * sal_body_handler_get_content_type_parameters_names(const SalBodyHandler *body_handler); +const char * sal_body_handler_get_content_type_parameter(const SalBodyHandler *body_handler, const char *name); +void sal_body_handler_set_content_type_parameter(SalBodyHandler *body_handler, const char *paramName, const char *paramValue); const char * sal_body_handler_get_encoding(const SalBodyHandler *body_handler); void sal_body_handler_set_encoding(SalBodyHandler *body_handler, const char *encoding); void * sal_body_handler_get_data(const SalBodyHandler *body_handler); diff --git a/src/chat/chat-message/chat-message.cpp b/src/chat/chat-message/chat-message.cpp index ca15d8c6a..ff2a595e7 100644 --- a/src/chat/chat-message/chat-message.cpp +++ b/src/chat/chat-message/chat-message.cpp @@ -36,6 +36,7 @@ #include "chat/modifier/file-transfer-chat-message-modifier.h" #include "chat/modifier/multipart-chat-message-modifier.h" #include "content/file-content.h" +#include "content/header-param.h" #include "content/content.h" #include "core/core.h" #include "core/core-p.h" @@ -450,7 +451,7 @@ static void forceUtf8Content (Content &content) { if (contentType != ContentType::PlainText) return; - string charset = contentType.getParameter(); + string charset = contentType.getParameter("charset").getValue(); if (charset.empty()) return; @@ -469,7 +470,7 @@ static void forceUtf8Content (Content &content) { if (!utf8Body.empty()) { // TODO: use move operator if possible in the future! content.setBodyFromUtf8(utf8Body); - contentType.setParameter(string(contentType.getParameter()).replace(begin, end - begin, "UTF-8")); + contentType.addParameter("charset", "UTF-8"); content.setContentType(contentType); } } diff --git a/src/chat/modifier/multipart-chat-message-modifier.cpp b/src/chat/modifier/multipart-chat-message-modifier.cpp index 5d0a34446..8e110119e 100644 --- a/src/chat/modifier/multipart-chat-message-modifier.cpp +++ b/src/chat/modifier/multipart-chat-message-modifier.cpp @@ -24,6 +24,7 @@ #include "chat/chat-message/chat-message.h" #include "chat/chat-room/chat-room.h" #include "content/content-type.h" +#include "content/header-param.h" #include "content/file-transfer-content.h" #include "logger/logger.h" #include "core/core.h" @@ -60,7 +61,7 @@ ChatMessageModifier::Result MultipartChatMessageModifier::encode ( Content newContent; ContentType newContentType(ContentType::Multipart); - newContentType.setParameter("boundary=" + boundary); + newContentType.addParameter("boundary", boundary); newContent.setContentType(newContentType); newContent.setBody(multipartMessage.str()); message->setInternalContent(newContent); @@ -70,7 +71,7 @@ ChatMessageModifier::Result MultipartChatMessageModifier::encode ( ChatMessageModifier::Result MultipartChatMessageModifier::decode (const shared_ptr &message, int &errorCode) { if (message->getInternalContent().getContentType().getType() == "multipart") { - string boundary = message->getInternalContent().getContentType().getParameter(); + string boundary = message->getInternalContent().getContentType().getParameter("boundary").getValue(); if (boundary.empty()) { lError() << "Boundary parameter of content-type not found: " << message->getInternalContent().getContentType().asString(); return ChatMessageModifier::Result::Error; diff --git a/src/content/content-manager.cpp b/src/content/content-manager.cpp index d4c286c79..8e3908310 100644 --- a/src/content/content-manager.cpp +++ b/src/content/content-manager.cpp @@ -112,7 +112,7 @@ Content ContentManager::contentListToMultipart (const list &contents) { belle_sip_object_unref(mpbh); ContentType contentType = ContentType::Multipart; - contentType.setParameter("boundary=" + string(MultipartBoundary)); + contentType.addParameter("boundary", string(MultipartBoundary)); content.setContentType(contentType); return content; diff --git a/src/content/content-type.cpp b/src/content/content-type.cpp index e457ff828..72fe78fd2 100644 --- a/src/content/content-type.cpp +++ b/src/content/content-type.cpp @@ -18,8 +18,10 @@ */ #include "linphone/utils/utils.h" +#include "linphone/utils/algorithm.h" #include "content-type.h" +#include "header-param.h" #include "object/clonable-object-p.h" // ============================================================================= @@ -34,7 +36,7 @@ class ContentTypePrivate : public ClonableObjectPrivate { public: string type; string subType; - string parameter; + std::list parameters; }; // ----------------------------------------------------------------------------- @@ -68,8 +70,15 @@ ContentType::ContentType (const string &contentType) : ClonableObject(*new Conte d->type.clear(); } - if (posParam != string::npos) - setParameter(Utils::trim(contentType.substr(posParam + 1))); + if (posParam != string::npos) { + string params = contentType.substr(posParam, end); + string token; + while ((pos = params.find(";")) != std::string::npos) { + token = params.substr(0, pos); + addParameter(HeaderParam(token)); + params.erase(0, pos + 1); + } + } } ContentType::ContentType (const string &type, const string &subType) : ClonableObject(*new ContentTypePrivate) { @@ -82,22 +91,34 @@ ContentType::ContentType (const string &type, const string &subType) : ClonableO ContentType::ContentType ( const string &type, const string &subType, - const string ¶meter + const HeaderParam ¶meter ) : ClonableObject(*new ContentTypePrivate) { L_D(); if (setType(type) && !setSubType(subType)) d->type.clear(); - setParameter(parameter); + addParameter(parameter); } -ContentType::ContentType (const ContentType &other) : ContentType(other.getType(), other.getSubType(), other.getParameter()) {} +ContentType::ContentType ( + const string &type, + const string &subType, + const std::list ¶meters +) : ClonableObject(*new ContentTypePrivate) { + L_D(); + + if (setType(type) && !setSubType(subType)) + d->type.clear(); + addParameters(parameters); +} + +ContentType::ContentType (const ContentType &other) : ContentType(other.getType(), other.getSubType(), other.getParameters()) {} ContentType &ContentType::operator= (const ContentType &other) { if (this != &other) { setType(other.getType()); setSubType(other.getSubType()); - setParameter(other.getParameter()); + addParameters(other.getParameters()); } return *this; @@ -106,7 +127,7 @@ ContentType &ContentType::operator= (const ContentType &other) { bool ContentType::operator== (const ContentType &other) const { return getType() == other.getType() && getSubType() == other.getSubType() && - getParameter() == other.getParameter(); + getParameters() == other.getParameters(); } bool ContentType::operator!= (const ContentType &other) const { @@ -141,14 +162,54 @@ bool ContentType::setSubType (const string &subType) { return false; } -const string &ContentType::getParameter () const { +const std::list &ContentType::getParameters () const { L_D(); - return d->parameter; + + return d->parameters; } -void ContentType::setParameter (const string ¶meter) { +void ContentType::addParameter (const std::string ¶mName, const std::string ¶mValue) { + addParameter(HeaderParam(paramName, paramValue)); +} + +void ContentType::addParameter (const HeaderParam ¶m) { L_D(); - d->parameter = parameter; + removeParameter(param); + d->parameters.push_back(param); +} + +void ContentType::addParameters(const std::list ¶ms) { + for (auto it = std::begin(params); it!=std::end(params); ++it) { + HeaderParam param = *it; + addParameter(param.getName(), param.getValue()); + } +} + +void ContentType::removeParameter (const std::string ¶mName) { + L_D(); + auto it = findParameter(paramName); + if (it != d->parameters.cend()) + d->parameters.remove(*it); +} + +void ContentType::removeParameter (const HeaderParam ¶m) { + removeParameter(param.getName()); +} + +std::list::const_iterator ContentType::findParameter (const std::string ¶mName) const { + L_D(); + return findIf(d->parameters, [¶mName](const HeaderParam ¶m) { + return param.getName() == paramName; + }); +} + +const HeaderParam &ContentType::getParameter (const std::string ¶mName) const { + L_D(); + std::list::const_iterator it = findParameter(paramName); + if (it != d->parameters.cend()) { + return *it; + } + return Utils::getEmptyConstRefObject(); } bool ContentType::isEmpty () const { @@ -165,8 +226,10 @@ string ContentType::asString () const { L_D(); if (isValid()) { string asString = d->type + "/" + d->subType; - if (!d->parameter.empty()) - asString += "; " + d->parameter; + for (auto it = std::begin(getParameters()); it!=std::end(getParameters()); ++it) { + HeaderParam param = *it; + asString += param.asString(); + } return asString; } return ""; diff --git a/src/content/content-type.h b/src/content/content-type.h index bdf51c75d..3b155e4cd 100644 --- a/src/content/content-type.h +++ b/src/content/content-type.h @@ -20,6 +20,8 @@ #ifndef _L_CONTENT_TYPE_H_ #define _L_CONTENT_TYPE_H_ +#include + #include "object/clonable-object.h" // ============================================================================= @@ -27,12 +29,14 @@ LINPHONE_BEGIN_NAMESPACE class ContentTypePrivate; +class HeaderParam; class LINPHONE_PUBLIC ContentType : public ClonableObject { public: explicit ContentType (const std::string &contentType = ""); ContentType (const std::string &type, const std::string &subType); - ContentType (const std::string &type, const std::string &subType, const std::string ¶meter); + ContentType (const std::string &type, const std::string &subType, const HeaderParam ¶meter); + ContentType (const std::string &type, const std::string &subType, const std::list ¶meters); ContentType (const ContentType &other); ContentType &operator= (const ContentType &other); @@ -55,8 +59,14 @@ public: const std::string &getSubType () const; bool setSubType (const std::string &subType); - const std::string &getParameter () const; - void setParameter (const std::string ¶meter); + const std::list &getParameters () const; + void addParameter (const std::string ¶mName, const std::string ¶mValue); + void addParameter (const HeaderParam ¶m); + void addParameters(const std::list ¶ms); + void removeParameter (const std::string ¶mName); + void removeParameter (const HeaderParam ¶m); + std::list::const_iterator findParameter (const std::string ¶mName) const; + const HeaderParam &getParameter (const std::string ¶mName) const; std::string asString () const; diff --git a/src/content/header-param.cpp b/src/content/header-param.cpp new file mode 100644 index 000000000..31c89caa5 --- /dev/null +++ b/src/content/header-param.cpp @@ -0,0 +1,105 @@ +/* + * header-param.cpp + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "linphone/utils/utils.h" + +#include "header-param.h" +#include "object/clonable-object-p.h" + +// ============================================================================= + +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +// ----------------------------------------------------------------------------- + +class HeaderParamPrivate : public ClonableObjectPrivate { +public: + string name; + string value; +}; + +// ----------------------------------------------------------------------------- + +HeaderParam::HeaderParam (const string ¶m) : ClonableObject(*new HeaderParamPrivate) { + size_t pos = param.find("="); + size_t end = param.length(); + + if (pos == string::npos) + return; + + setName(param.substr(0, pos)); + setValue(param.substr(pos + 1, end)); +} + +HeaderParam::HeaderParam (const string &name, const string &value) : ClonableObject(*new HeaderParamPrivate) { + setName(name); + setValue(value); +} + +HeaderParam::HeaderParam (const HeaderParam &other) : HeaderParam(other.getName(), other.getValue()) {} + +HeaderParam &HeaderParam::operator= (const HeaderParam &other) { + if (this != &other) { + setName(other.getName()); + setValue(other.getValue()); + } + + return *this; +} + +bool HeaderParam::operator== (const HeaderParam &other) const { + return getName() == other.getName() && + getValue() == other.getValue(); +} + +bool HeaderParam::operator!= (const HeaderParam &other) const { + return !(*this == other); +} + +const string &HeaderParam::getName () const { + L_D(); + return d->name; +} + +bool HeaderParam::setName (const string &name) { + L_D(); + d->name = name; + return true; +} + +const string &HeaderParam::getValue () const { + L_D(); + return d->value; +} + +bool HeaderParam::setValue (const string &value) { + L_D(); + d->value = value; + return true; +} + +string HeaderParam::asString () const { + L_D(); + string asString = ";" + d->name + "=" + d->value; + return asString; +} + +LINPHONE_END_NAMESPACE diff --git a/src/content/header-param.h b/src/content/header-param.h new file mode 100644 index 000000000..a9471b486 --- /dev/null +++ b/src/content/header-param.h @@ -0,0 +1,61 @@ +/* + * header-param.h + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_HEADER_PARAM_H_ +#define _L_HEADER_PARAM_H_ + +#include "object/clonable-object.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class HeaderParamPrivate; + +class LINPHONE_PUBLIC HeaderParam : public ClonableObject { +public: + explicit HeaderParam (const std::string &header = ""); + HeaderParam (const std::string &name, const std::string &value); + HeaderParam (const HeaderParam &other); + + HeaderParam &operator= (const HeaderParam &other); + + bool operator== (const HeaderParam &other) const; + bool operator!= (const HeaderParam &other) const; + + // Delete these operators to prevent putting complicated content-type strings + // in the code. Instead define static const HeaderParam objects below. + bool operator== (const std::string &other) const = delete; + bool operator!= (const std::string &other) const = delete; + + const std::string &getName () const; + bool setName (const std::string &name); + + const std::string &getValue () const; + bool setValue (const std::string &value); + + std::string asString () const; + +private: + L_DECLARE_PRIVATE(HeaderParam); +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_HEADER_PARAM_H_ From b19c228fe4e11692a644dfe7132a5b5a7a078273 Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Wed, 21 Mar 2018 14:29:27 +0100 Subject: [PATCH 23/67] Fixed leak --- src/c-wrapper/api/c-content.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/c-wrapper/api/c-content.cpp b/src/c-wrapper/api/c-content.cpp index 5e6c2e94a..393059486 100644 --- a/src/c-wrapper/api/c-content.cpp +++ b/src/c-wrapper/api/c-content.cpp @@ -283,7 +283,7 @@ LinphoneContent * linphone_content_new(void) { } LinphoneContent * linphone_content_copy(const LinphoneContent *ref) { - return (LinphoneContent *)belle_sip_object_ref(belle_sip_object_clone(BELLE_SIP_OBJECT(ref))); + return (LinphoneContent *)(belle_sip_object_clone(BELLE_SIP_OBJECT(ref))); } LinphoneContent * linphone_core_create_content(LinphoneCore *lc) { From c93eee237bf84bd9ffba3b7c1ad637b522a06e40 Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Wed, 21 Mar 2018 15:13:10 +0100 Subject: [PATCH 24/67] Fixed parsing of content type parameters from ContentType(string) constructor --- .../modifier/multipart-chat-message-modifier.cpp | 9 ++------- src/content/content-type.cpp | 13 +++++++++---- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/chat/modifier/multipart-chat-message-modifier.cpp b/src/chat/modifier/multipart-chat-message-modifier.cpp index 8e110119e..1365d03f8 100644 --- a/src/chat/modifier/multipart-chat-message-modifier.cpp +++ b/src/chat/modifier/multipart-chat-message-modifier.cpp @@ -77,18 +77,13 @@ ChatMessageModifier::Result MultipartChatMessageModifier::decode (const shared_p return ChatMessageModifier::Result::Error; } - size_t pos = boundary.find("="); - if (pos == string::npos) { - lError() << "Parameter seems invalid: " << boundary; - return ChatMessageModifier::Result::Error; - } - boundary = "--" + boundary.substr(pos + 1); + boundary = "--" + boundary; lInfo() << "Multipart boundary is " << boundary; const vector body = message->getInternalContent().getBody(); string contentsString(body.begin(), body.end()); - pos = contentsString.find(boundary); + size_t pos = contentsString.find(boundary); if (pos == string::npos) { lError() << "Boundary not found in body !"; return ChatMessageModifier::Result::Error; diff --git a/src/content/content-type.cpp b/src/content/content-type.cpp index 72fe78fd2..6036f3d46 100644 --- a/src/content/content-type.cpp +++ b/src/content/content-type.cpp @@ -71,13 +71,18 @@ ContentType::ContentType (const string &contentType) : ClonableObject(*new Conte } if (posParam != string::npos) { - string params = contentType.substr(posParam, end); + string params = contentType.substr(posParam + 1); string token; - while ((pos = params.find(";")) != std::string::npos) { - token = params.substr(0, pos); + do { + posParam = params.find(";"); + if (posParam != string::npos) { + token = params; + } else { + token = params.substr(0, posParam); + } addParameter(HeaderParam(token)); params.erase(0, pos + 1); - } + } while (posParam != std::string::npos); } } From 57b07c4545c994b1bcac56384fc3387357c3933a Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Wed, 21 Mar 2018 15:35:32 +0100 Subject: [PATCH 25/67] Fixed header param parsing & dump if header as no value --- src/content/header-param.cpp | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/content/header-param.cpp b/src/content/header-param.cpp index 31c89caa5..cbc07d8a7 100644 --- a/src/content/header-param.cpp +++ b/src/content/header-param.cpp @@ -42,11 +42,12 @@ HeaderParam::HeaderParam (const string ¶m) : ClonableObject(*new HeaderParam size_t pos = param.find("="); size_t end = param.length(); - if (pos == string::npos) - return; - - setName(param.substr(0, pos)); - setValue(param.substr(pos + 1, end)); + if (pos == string::npos) { + setName(param); + } else { + setName(param.substr(0, pos)); + setValue(param.substr(pos + 1, end)); + } } HeaderParam::HeaderParam (const string &name, const string &value) : ClonableObject(*new HeaderParamPrivate) { @@ -98,7 +99,9 @@ bool HeaderParam::setValue (const string &value) { string HeaderParam::asString () const { L_D(); - string asString = ";" + d->name + "=" + d->value; + string asString = ";" + d->name; + if (!d->value.empty()) + asString += "=" + d->value; return asString; } From 5fd6a68b94d7111c15bdfd3a8583bc111aaf335e Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Wed, 21 Mar 2018 16:09:36 +0100 Subject: [PATCH 26/67] Fixed another issue with ContentType & HeaderParam constructors doing parsing --- src/content/content-type.cpp | 2 +- src/content/header-param.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/content/content-type.cpp b/src/content/content-type.cpp index 6036f3d46..4af2f2195 100644 --- a/src/content/content-type.cpp +++ b/src/content/content-type.cpp @@ -75,7 +75,7 @@ ContentType::ContentType (const string &contentType) : ClonableObject(*new Conte string token; do { posParam = params.find(";"); - if (posParam != string::npos) { + if (posParam == string::npos) { token = params; } else { token = params.substr(0, posParam); diff --git a/src/content/header-param.cpp b/src/content/header-param.cpp index cbc07d8a7..9605a2f84 100644 --- a/src/content/header-param.cpp +++ b/src/content/header-param.cpp @@ -46,7 +46,7 @@ HeaderParam::HeaderParam (const string ¶m) : ClonableObject(*new HeaderParam setName(param); } else { setName(param.substr(0, pos)); - setValue(param.substr(pos + 1, end)); + setValue(param.substr(pos + 1, end - (pos + 1))); } } From ba1d6bc8b0cb966b6dfd8b97548899e04d44c4dc Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Wed, 21 Mar 2018 17:01:00 +0100 Subject: [PATCH 27/67] Remove a lot of useless code --- src/c-wrapper/api/c-content.cpp | 19 +++---------------- 1 file changed, 3 insertions(+), 16 deletions(-) diff --git a/src/c-wrapper/api/c-content.cpp b/src/c-wrapper/api/c-content.cpp index 393059486..6d6bdde34 100644 --- a/src/c-wrapper/api/c-content.cpp +++ b/src/c-wrapper/api/c-content.cpp @@ -254,22 +254,9 @@ static LinphoneContent * linphone_content_new_with_body_handler(SalBodyHandler * linphone_content_set_string_buffer(content, (char *)sal_body_handler_get_data(body_handler)); } else { belle_sip_multipart_body_handler_t *mpbh = BELLE_SIP_MULTIPART_BODY_HANDLER(body_handler); - list contents; - for (const belle_sip_list_t *parts = belle_sip_multipart_body_handler_get_parts(mpbh); parts; parts = parts->next) { - belle_sip_body_handler_t *part = BELLE_SIP_BODY_HANDLER(parts->data); - LinphoneContent *part_content = linphone_content_new_with_body_handler((SalBodyHandler *)part); - - const belle_sip_list_t *headers = belle_sip_body_handler_get_headers(part); - for (; headers != NULL; headers = headers->next) { - belle_sip_header_t *header = BELLE_SIP_HEADER(headers->data); - L_GET_CPP_PTR_FROM_C_OBJECT(part_content)->addHeader(belle_sip_header_get_name(header), belle_sip_header_get_unparsed_value(header)); - } - - contents.push_back(*L_GET_CPP_PTR_FROM_C_OBJECT(part_content)); - linphone_content_unref(part_content); - } - LinphonePrivate::Content multipartContent = LinphonePrivate::ContentManager::contentListToMultipart(contents); - linphone_content_set_string_buffer(content, multipartContent.getBodyAsUtf8String().c_str()); + char *body = belle_sip_object_to_string(mpbh); + linphone_content_set_string_buffer(content, body); + belle_sip_free(body); } if (sal_body_handler_get_encoding(body_handler)) linphone_content_set_encoding(content, sal_body_handler_get_encoding(body_handler)); From 0dfd57b50588953214899404c42724a254406b91 Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Fri, 23 Mar 2018 10:37:31 +0100 Subject: [PATCH 28/67] Clean code related to multiparts' Contents --- coreapi/bellesip_sal/sal_impl.c | 5 + src/c-wrapper/internal/c-sal.h | 1 + .../multipart-chat-message-modifier.cpp | 95 ++++--------------- .../local-conference-event-handler.cpp | 4 +- src/content/content-manager.cpp | 95 ++++++------------- src/content/content-manager.h | 2 +- tester/content-manager-tester.cpp | 14 +-- 7 files changed, 65 insertions(+), 151 deletions(-) diff --git a/coreapi/bellesip_sal/sal_impl.c b/coreapi/bellesip_sal/sal_impl.c index 99c859f52..771155918 100644 --- a/coreapi/bellesip_sal/sal_impl.c +++ b/coreapi/bellesip_sal/sal_impl.c @@ -419,6 +419,11 @@ SalBodyHandler * sal_body_handler_get_part(const SalBodyHandler *body_handler, i return (SalBodyHandler *)belle_sip_list_nth_data(l, idx); } +const belle_sip_list_t * sal_body_handler_get_parts(const SalBodyHandler *body_handler) { + if (!sal_body_handler_is_multipart(body_handler)) return NULL; + return belle_sip_multipart_body_handler_get_parts(BELLE_SIP_MULTIPART_BODY_HANDLER(body_handler)); +} + SalBodyHandler * sal_body_handler_find_part_by_header(const SalBodyHandler *body_handler, const char *header_name, const char *header_value) { const belle_sip_list_t *l = belle_sip_multipart_body_handler_get_parts(BELLE_SIP_MULTIPART_BODY_HANDLER(body_handler)); for (; l != NULL; l = l->next) { diff --git a/src/c-wrapper/internal/c-sal.h b/src/c-wrapper/internal/c-sal.h index dd2e53f8f..ebf373229 100644 --- a/src/c-wrapper/internal/c-sal.h +++ b/src/c-wrapper/internal/c-sal.h @@ -647,6 +647,7 @@ size_t sal_body_handler_get_size(const SalBodyHandler *body_handler); void sal_body_handler_set_size(SalBodyHandler *body_handler, size_t size); bool_t sal_body_handler_is_multipart(const SalBodyHandler *body_handler); SalBodyHandler * sal_body_handler_get_part(const SalBodyHandler *body_handler, int idx); +const belle_sip_list_t * sal_body_handler_get_parts(const SalBodyHandler *body_handler); SalBodyHandler * sal_body_handler_find_part_by_header(const SalBodyHandler *body_handler, const char *header_name, const char *header_value); const char * sal_body_handler_get_header(const SalBodyHandler *body_handler, const char *header_name); diff --git a/src/chat/modifier/multipart-chat-message-modifier.cpp b/src/chat/modifier/multipart-chat-message-modifier.cpp index 1365d03f8..13041bdb4 100644 --- a/src/chat/modifier/multipart-chat-message-modifier.cpp +++ b/src/chat/modifier/multipart-chat-message-modifier.cpp @@ -20,14 +20,10 @@ // TODO: Remove me later. #include "private.h" -#include "address/address.h" #include "chat/chat-message/chat-message.h" -#include "chat/chat-room/chat-room.h" #include "content/content-type.h" -#include "content/header-param.h" +#include "content/content-manager.h" #include "content/file-transfer-content.h" -#include "logger/logger.h" -#include "core/core.h" #include "multipart-chat-message-modifier.h" @@ -44,85 +40,30 @@ ChatMessageModifier::Result MultipartChatMessageModifier::encode ( if (message->getContents().size() <= 1) return ChatMessageModifier::Result::Skipped; - LinphoneCore *lc = message->getChatRoom()->getCore()->getCCore(); - char tmp[64]; - lc->sal->create_uuid(tmp, sizeof(tmp)); - string boundary = tmp; - stringstream multipartMessage; - - multipartMessage << "--" << boundary; - for (Content *content : message->getContents()) { - multipartMessage << "\r\n"; - multipartMessage << "Content-Type: " << content->getContentType().asString() << "\r\n\r\n"; - multipartMessage << content->getBodyAsString() << "\r\n\r\n"; - multipartMessage << "--" << boundary; - } - multipartMessage << "--"; - - Content newContent; - ContentType newContentType(ContentType::Multipart); - newContentType.addParameter("boundary", boundary); - newContent.setContentType(newContentType); - newContent.setBody(multipartMessage.str()); - message->setInternalContent(newContent); + Content content = ContentManager::contentListToMultipart(message->getContents()); + message->setInternalContent(content); return ChatMessageModifier::Result::Done; } ChatMessageModifier::Result MultipartChatMessageModifier::decode (const shared_ptr &message, int &errorCode) { - if (message->getInternalContent().getContentType().getType() == "multipart") { - string boundary = message->getInternalContent().getContentType().getParameter("boundary").getValue(); - if (boundary.empty()) { - lError() << "Boundary parameter of content-type not found: " << message->getInternalContent().getContentType().asString(); - return ChatMessageModifier::Result::Error; - } - - boundary = "--" + boundary; - lInfo() << "Multipart boundary is " << boundary; - - const vector body = message->getInternalContent().getBody(); - string contentsString(body.begin(), body.end()); - - size_t pos = contentsString.find(boundary); - if (pos == string::npos) { - lError() << "Boundary not found in body !"; - return ChatMessageModifier::Result::Error; - } - - size_t start = pos + boundary.length() + 2; // 2 is the size of \r\n - size_t end; - do { - end = contentsString.find(boundary, start); - if (end != string::npos) { - string contentString = contentsString.substr(start, end - start); - - size_t contentTypePos = contentString.find(": ") + 2; // 2 is the size of : - size_t endOfLinePos = contentString.find("\r\n"); - if (contentTypePos >= endOfLinePos) { - lError() << "Content should start by a 'Content-Type: ' line !"; - continue; + if (message->getInternalContent().getContentType().isMultipart()) { + for (Content &c : ContentManager::multipartToContentList(message->getInternalContent())) { + Content *content; + if (c.getContentType() == ContentType::FileTransfer) { + content = new FileTransferContent(); + content->setContentType(c.getContentType()); + content->setContentDisposition(c.getContentDisposition()); + content->setContentEncoding(c.getContentEncoding()); + for (const pair &pair : c.getHeaders()) { + content->addHeader(pair.first, pair.second); } - string contentTypeString = contentString.substr(contentTypePos, endOfLinePos - contentTypePos); - ContentType contentType(contentTypeString); - - endOfLinePos += 4; // 4 is two time the size of \r\n - string contentBody = contentString.substr(endOfLinePos, contentString.length() - (endOfLinePos + 4)); // 4 is two time the size of \r\n - - Content *content; - if (contentType == ContentType::FileTransfer) { - content = new FileTransferContent(); - } else { - content = new Content(); - } - content->setContentType(contentType); - content->setBody(contentBody); - message->addContent(content); - - lInfo() << "Parsed and added content with type " << contentType.asString(); + content->setBodyFromUtf8(c.getBodyAsUtf8String()); + } else { + content = new Content(c); } - start = end + boundary.length() + 2; // 2 is the size of \r\n - } while (end != string::npos); - + message->addContent(content); + } return ChatMessageModifier::Result::Done; } return ChatMessageModifier::Result::Skipped; diff --git a/src/conference/handlers/local-conference-event-handler.cpp b/src/conference/handlers/local-conference-event-handler.cpp index b2e4895f2..8f56e74e5 100644 --- a/src/conference/handlers/local-conference-event-handler.cpp +++ b/src/conference/handlers/local-conference-event-handler.cpp @@ -107,7 +107,7 @@ string LocalConferenceEventHandlerPrivate::createNotifyMultipart (int notifyId) static_cast(notifyId) ); - list contents; + list contents; for (const auto &eventLog : events) { Content content; content.setContentType(ContentType("application","conference-info")); @@ -181,7 +181,7 @@ string LocalConferenceEventHandlerPrivate::createNotifyMultipart (int notifyId) continue; } content.setBody(body); - contents.push_back(content); + contents.push_back(&content); } if (contents.empty()) diff --git a/src/content/content-manager.cpp b/src/content/content-manager.cpp index 8e3908310..cbecfaa83 100644 --- a/src/content/content-manager.cpp +++ b/src/content/content-manager.cpp @@ -19,6 +19,10 @@ #include +#include "c-wrapper/c-wrapper.h" + +#include "linphone/api/c-content.h" + #include "content-manager.h" #include "content-type.h" #include "content/content.h" @@ -36,86 +40,47 @@ namespace { // ----------------------------------------------------------------------------- list ContentManager::multipartToContentList (const Content &content) { - const string body = content.getBodyAsString(); - belle_sip_multipart_body_handler_t *mpbh = belle_sip_multipart_body_handler_new_from_buffer( - body.c_str(), body.length(), MultipartBoundary - ); - belle_sip_object_ref(mpbh); + LinphoneContent *cContent = L_GET_C_BACK_PTR(&content); + SalBodyHandler *sbh = sal_body_handler_ref(sal_body_handler_from_content(cContent)); list contents; - for (const belle_sip_list_t *parts = belle_sip_multipart_body_handler_get_parts(mpbh); parts; parts = parts->next) { - belle_sip_body_handler_t *part = BELLE_SIP_BODY_HANDLER(parts->data); - Content content; - - for (const belle_sip_list_t *it = belle_sip_body_handler_get_headers(part); it; it = it->next) { - belle_sip_header_t *header = BELLE_SIP_HEADER(it->data); - if (strcasecmp("Content-Type", belle_sip_header_get_name(header)) == 0) { - belle_sip_header_content_type_t * partContentType = BELLE_SIP_HEADER_CONTENT_TYPE(header); - content.setContentType(ContentType( - belle_sip_header_content_type_get_type(partContentType), - belle_sip_header_content_type_get_subtype(partContentType) - )); - } else { - content.addHeader(belle_sip_header_get_name(header), belle_sip_header_get_unparsed_value(header)); - } - } - - content.setBody(static_cast( - belle_sip_memory_body_handler_get_buffer(BELLE_SIP_MEMORY_BODY_HANDLER(part)) - )); - - contents.push_back(move(content)); + for (const belle_sip_list_t *parts = sal_body_handler_get_parts(sbh); parts; parts = parts->next) { + SalBodyHandler *part = (SalBodyHandler *)parts->data; + LinphoneContent *cContent = linphone_content_from_sal_body_handler(part); + Content *cppContent = L_GET_CPP_PTR_FROM_C_OBJECT(cContent); + contents.push_back(*cppContent); + linphone_content_unref(cContent); } - belle_sip_object_unref(mpbh); + sal_body_handler_unref(sbh); + linphone_content_unref(cContent); return contents; } -Content ContentManager::contentListToMultipart (const list &contents) { +Content ContentManager::contentListToMultipart (const list &contents) { belle_sip_multipart_body_handler_t *mpbh = belle_sip_multipart_body_handler_new( nullptr, nullptr, nullptr, MultipartBoundary ); - belle_sip_object_ref(mpbh); + mpbh = (belle_sip_multipart_body_handler_t *)belle_sip_object_ref(mpbh); - for (const auto &content : contents) { - const ContentType &contentType = content.getContentType(); - belle_sip_header_t *cContentType = BELLE_SIP_HEADER( - belle_sip_header_content_type_create( - contentType.getType().c_str(), - string(contentType.getSubType() + "; charset=\"UTF-8\"").c_str() - ) - ); - - const string body = content.getBodyAsString(); - belle_sip_memory_body_handler_t *mbh = belle_sip_memory_body_handler_new_copy_from_buffer( - body.c_str(), body.length(), nullptr, nullptr - ); - belle_sip_body_handler_add_header(BELLE_SIP_BODY_HANDLER(mbh), cContentType); - - for (const auto &header : content.getHeaders()) { - belle_sip_header_t *additionalHeader = BELLE_SIP_HEADER( - belle_sip_header_create( - header.first.c_str(), - header.second.c_str() - ) - ); - belle_sip_body_handler_add_header(BELLE_SIP_BODY_HANDLER(mbh), additionalHeader); - } - - belle_sip_multipart_body_handler_add_part(mpbh, BELLE_SIP_BODY_HANDLER(mbh)); + for (Content *content : contents) { + LinphoneContent *cContent = L_GET_C_BACK_PTR(content); + SalBodyHandler *sbh = sal_body_handler_from_content(cContent); + belle_sip_multipart_body_handler_add_part(mpbh, BELLE_SIP_BODY_HANDLER(sbh)); + linphone_content_unref(cContent); } - char *desc = belle_sip_object_to_string(mpbh); - Content content; - content.setBody(desc); - belle_sip_free(desc); + SalBodyHandler *sbh = (SalBodyHandler *)mpbh; + sal_body_handler_set_type(sbh, ContentType::Multipart.getType().c_str()); + sal_body_handler_set_subtype(sbh, ContentType::Multipart.getSubType().c_str()); + sal_body_handler_set_content_type_parameter(sbh, "boundary", MultipartBoundary); + LinphoneContent *cContent = linphone_content_from_sal_body_handler(sbh); + Content *content = L_GET_CPP_PTR_FROM_C_OBJECT(cContent); + Content returnContent = *content; + linphone_content_unref(cContent); belle_sip_object_unref(mpbh); - ContentType contentType = ContentType::Multipart; - contentType.addParameter("boundary", string(MultipartBoundary)); - content.setContentType(contentType); - - return content; + return returnContent; } LINPHONE_END_NAMESPACE diff --git a/src/content/content-manager.h b/src/content/content-manager.h index 8251d3c3b..4d19076f0 100644 --- a/src/content/content-manager.h +++ b/src/content/content-manager.h @@ -32,7 +32,7 @@ class Content; namespace ContentManager { std::list multipartToContentList (const Content &content); - Content contentListToMultipart (const std::list &contents); + Content contentListToMultipart (const std::list &contents); } LINPHONE_END_NAMESPACE diff --git a/tester/content-manager-tester.cpp b/tester/content-manager-tester.cpp index e21cc6399..8c688889b 100644 --- a/tester/content-manager-tester.cpp +++ b/tester/content-manager-tester.cpp @@ -234,26 +234,28 @@ void multipart_to_list () { generatedStr4.erase(std::remove(generatedStr4.begin(), generatedStr4.end(), '\r'), generatedStr4.end()); generatedStr4.erase(std::remove(generatedStr4.begin(), generatedStr4.end(), '\n'), generatedStr4.end()); ms_message("\n\n----- Generated part 4 -----"); - ms_message("%s", generatedStr3.c_str()); + ms_message("%s", generatedStr4.c_str()); ms_message("\n\n----- Original part 4 -----"); ms_message("%s", originalStr4.c_str()); BC_ASSERT_TRUE(originalStr4 == generatedStr4); } void list_to_multipart () { + ContentType contentType = ContentType("application", "rlmi+xml"); + contentType.addParameter("charset", "\"UTF-8\""); Content content1; content1.setBody(part1); - content1.setContentType(ContentType("application", "rlmi+xml")); + content1.setContentType(contentType); Content content2; content2.setBody(part2); - content2.setContentType(ContentType("application", "pidf+xml")); + content2.setContentType(contentType); Content content3; content3.setBody(part3); - content3.setContentType(ContentType("application", "pidf+xml")); + content3.setContentType(contentType); Content content4; content4.setBody(part4); - content4.setContentType(ContentType("application", "pidf+xml")); - list contents = {content1, content2, content3, content4}; + content4.setContentType(contentType); + list contents = {&content1, &content2, &content3, &content4}; Content multipartContent = ContentManager::contentListToMultipart(contents); string originalStr(multipart); From acf44578adcbb7dd91fd1db634598c7065e62649 Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Fri, 23 Mar 2018 14:19:42 +0100 Subject: [PATCH 29/67] Fixed Content Manager tester --- tester/content-manager-tester.cpp | 80 +++++++++++++++++++++++++++++-- 1 file changed, 77 insertions(+), 3 deletions(-) diff --git a/tester/content-manager-tester.cpp b/tester/content-manager-tester.cpp index 8c688889b..de371dfb4 100644 --- a/tester/content-manager-tester.cpp +++ b/tester/content-manager-tester.cpp @@ -27,7 +27,7 @@ using namespace LinphonePrivate; using namespace std; -static const char* multipart = \ +static const char* source_multipart = \ "-----------------------------14737809831466499882746641449\r\n" \ "Content-Type: application/rlmi+xml;charset=\"UTF-8\"\r\n\r\n" \ "" \ @@ -95,6 +95,78 @@ static const char* multipart = \ "" \ "-----------------------------14737809831466499882746641449--\r\n"; +static const char* generated_multipart = \ +"-----------------------------14737809831466499882746641449\r\n" \ +"Content-Type: application/rlmi+xml;charset=\"UTF-8\"\r\n\r\n" \ +"Content-Length:582" \ +"" \ +"" \ +" " \ +" " \ +" " \ +" " \ +" " \ +" " \ +" " \ +" " \ +" " \ +"" \ +"-----------------------------14737809831466499882746641449\r\n" \ +"Content-Type: application/pidf+xml;charset=\"UTF-8\"\r\n\r\n" \ +"Content-Length:561" \ +"" \ +"" \ +" " \ +" " \ +" open" \ +" " \ +" sip:+YYYYYYYYYY@sip.linphone.org;user=phone" \ +" 2017-10-25T13:18:26" \ +" " \ +" " \ +" " \ +" " \ +" " \ +" " \ +"" \ +"-----------------------------14737809831466499882746641449\r\n" \ +"Content-Type: application/pidf+xml;charset=\"UTF-8\"\r\n\r\n" \ +"Content-Length:561" \ +"" \ +"" \ +" " \ +" " \ +" open" \ +" " \ +" sip:+XXXXXXXXXX@sip.linphone.org;user=phone" \ +" 2017-10-25T13:18:26" \ +" " \ +" " \ +" " \ +" " \ +" " \ +" " \ +"" \ +"-----------------------------14737809831466499882746641449\r\n" \ +"Content-Type: application/pidf+xml;charset=\"UTF-8\"\r\n\r\n" \ +"Content-Length:546" \ +"" \ +"" \ +" " \ +" " \ +" open" \ +" " \ +" sip:someone@sip.linphone.org" \ +" 2017-10-25T13:18:26" \ +" " \ +" " \ +" " \ +" " \ +" " \ +" " \ +"" \ +"-----------------------------14737809831466499882746641449--\r\n"; + static const char* part1 = \ "" \ "" \ @@ -162,7 +234,7 @@ static const char* part4 = \ void multipart_to_list () { Content multipartContent; - multipartContent.setBody(multipart); + multipartContent.setBody(source_multipart); multipartContent.setContentType(ContentType("multipart", "related")); list contents = ContentManager::multipartToContentList(multipartContent); @@ -246,6 +318,8 @@ void list_to_multipart () { Content content1; content1.setBody(part1); content1.setContentType(contentType); + contentType = ContentType("application", "pidf+xml"); + contentType.addParameter("charset", "\"UTF-8\""); Content content2; content2.setBody(part2); content2.setContentType(contentType); @@ -258,7 +332,7 @@ void list_to_multipart () { list contents = {&content1, &content2, &content3, &content4}; Content multipartContent = ContentManager::contentListToMultipart(contents); - string originalStr(multipart); + string originalStr(generated_multipart); originalStr.erase(std::remove(originalStr.begin(), originalStr.end(), ' '), originalStr.end()); originalStr.erase(std::remove(originalStr.begin(), originalStr.end(), '\t'), originalStr.end()); originalStr.erase(std::remove(originalStr.begin(), originalStr.end(), '\r'), originalStr.end()); From 49b93c6f9a70fc52ce0bba389e63ff74dcd46cd6 Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Fri, 23 Mar 2018 15:20:48 +0100 Subject: [PATCH 30/67] Created Header class as parent of ContentType --- src/CMakeLists.txt | 7 +- src/c-wrapper/api/c-content.cpp | 2 +- src/chat/chat-message/chat-message.cpp | 2 +- src/content/content-type.cpp | 66 ++--------------- src/content/content-type.h | 14 +--- src/content/header/header-p.h | 41 +++++++++++ src/content/{ => header}/header-param.cpp | 0 src/content/{ => header}/header-param.h | 0 src/content/header/header.cpp | 88 +++++++++++++++++++++++ src/content/header/header.h | 54 ++++++++++++++ 10 files changed, 199 insertions(+), 75 deletions(-) create mode 100644 src/content/header/header-p.h rename src/content/{ => header}/header-param.cpp (100%) rename src/content/{ => header}/header-param.h (100%) create mode 100644 src/content/header/header.cpp create mode 100644 src/content/header/header.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 66d42b91e..b7c47abf8 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -99,7 +99,9 @@ set(LINPHONE_CXX_OBJECTS_PRIVATE_HEADER_FILES content/content.h content/file-content.h content/file-transfer-content.h - content/header-param.h + content/header/header.h + content/header/header-p.h + content/header/header-param.h core/core-accessor.h core/core-listener.h core/core-p.h @@ -224,7 +226,8 @@ set(LINPHONE_CXX_OBJECTS_SOURCE_FILES content/content.cpp content/file-content.cpp content/file-transfer-content.cpp - content/header-param.cpp + content/header/header.cpp + content/header/header-param.cpp core/core-accessor.cpp core/core-call.cpp core/core-chat-room.cpp diff --git a/src/c-wrapper/api/c-content.cpp b/src/c-wrapper/api/c-content.cpp index 6d6bdde34..2b68cbbde 100644 --- a/src/c-wrapper/api/c-content.cpp +++ b/src/c-wrapper/api/c-content.cpp @@ -24,7 +24,7 @@ #include "content/content.h" #include "content/content-type.h" -#include "content/header-param.h" +#include "content/header/header-param.h" #include "content/content-manager.h" #include "content/file-content.h" #include "content/file-transfer-content.h" diff --git a/src/chat/chat-message/chat-message.cpp b/src/chat/chat-message/chat-message.cpp index ff2a595e7..407a9e734 100644 --- a/src/chat/chat-message/chat-message.cpp +++ b/src/chat/chat-message/chat-message.cpp @@ -36,7 +36,7 @@ #include "chat/modifier/file-transfer-chat-message-modifier.h" #include "chat/modifier/multipart-chat-message-modifier.h" #include "content/file-content.h" -#include "content/header-param.h" +#include "content/header/header-param.h" #include "content/content.h" #include "core/core.h" #include "core/core-p.h" diff --git a/src/content/content-type.cpp b/src/content/content-type.cpp index 4af2f2195..be3b7da00 100644 --- a/src/content/content-type.cpp +++ b/src/content/content-type.cpp @@ -18,11 +18,10 @@ */ #include "linphone/utils/utils.h" -#include "linphone/utils/algorithm.h" #include "content-type.h" -#include "header-param.h" -#include "object/clonable-object-p.h" +#include "header/header-p.h" +#include "header/header-param.h" // ============================================================================= @@ -32,11 +31,10 @@ LINPHONE_BEGIN_NAMESPACE // ----------------------------------------------------------------------------- -class ContentTypePrivate : public ClonableObjectPrivate { +class ContentTypePrivate : public HeaderPrivate { public: string type; string subType; - std::list parameters; }; // ----------------------------------------------------------------------------- @@ -54,7 +52,7 @@ const ContentType ContentType::Sdp("application/sdp"); // ----------------------------------------------------------------------------- -ContentType::ContentType (const string &contentType) : ClonableObject(*new ContentTypePrivate) { +ContentType::ContentType (const string &contentType) : Header(*new ContentTypePrivate) { L_D(); size_t pos = contentType.find('/'); @@ -86,7 +84,7 @@ ContentType::ContentType (const string &contentType) : ClonableObject(*new Conte } } -ContentType::ContentType (const string &type, const string &subType) : ClonableObject(*new ContentTypePrivate) { +ContentType::ContentType (const string &type, const string &subType) : Header(*new ContentTypePrivate) { L_D(); if (setType(type) && !setSubType(subType)) @@ -97,7 +95,7 @@ ContentType::ContentType ( const string &type, const string &subType, const HeaderParam ¶meter -) : ClonableObject(*new ContentTypePrivate) { +) : Header(*new ContentTypePrivate) { L_D(); if (setType(type) && !setSubType(subType)) @@ -109,7 +107,7 @@ ContentType::ContentType ( const string &type, const string &subType, const std::list ¶meters -) : ClonableObject(*new ContentTypePrivate) { +) : Header(*new ContentTypePrivate) { L_D(); if (setType(type) && !setSubType(subType)) @@ -167,56 +165,6 @@ bool ContentType::setSubType (const string &subType) { return false; } -const std::list &ContentType::getParameters () const { - L_D(); - - return d->parameters; -} - -void ContentType::addParameter (const std::string ¶mName, const std::string ¶mValue) { - addParameter(HeaderParam(paramName, paramValue)); -} - -void ContentType::addParameter (const HeaderParam ¶m) { - L_D(); - removeParameter(param); - d->parameters.push_back(param); -} - -void ContentType::addParameters(const std::list ¶ms) { - for (auto it = std::begin(params); it!=std::end(params); ++it) { - HeaderParam param = *it; - addParameter(param.getName(), param.getValue()); - } -} - -void ContentType::removeParameter (const std::string ¶mName) { - L_D(); - auto it = findParameter(paramName); - if (it != d->parameters.cend()) - d->parameters.remove(*it); -} - -void ContentType::removeParameter (const HeaderParam ¶m) { - removeParameter(param.getName()); -} - -std::list::const_iterator ContentType::findParameter (const std::string ¶mName) const { - L_D(); - return findIf(d->parameters, [¶mName](const HeaderParam ¶m) { - return param.getName() == paramName; - }); -} - -const HeaderParam &ContentType::getParameter (const std::string ¶mName) const { - L_D(); - std::list::const_iterator it = findParameter(paramName); - if (it != d->parameters.cend()) { - return *it; - } - return Utils::getEmptyConstRefObject(); -} - bool ContentType::isEmpty () const { L_D(); return d->type.empty() && d->subType.empty(); diff --git a/src/content/content-type.h b/src/content/content-type.h index 3b155e4cd..2ed267065 100644 --- a/src/content/content-type.h +++ b/src/content/content-type.h @@ -20,9 +20,8 @@ #ifndef _L_CONTENT_TYPE_H_ #define _L_CONTENT_TYPE_H_ -#include - #include "object/clonable-object.h" +#include "header/header.h" // ============================================================================= @@ -31,7 +30,7 @@ LINPHONE_BEGIN_NAMESPACE class ContentTypePrivate; class HeaderParam; -class LINPHONE_PUBLIC ContentType : public ClonableObject { +class LINPHONE_PUBLIC ContentType : public Header { public: explicit ContentType (const std::string &contentType = ""); ContentType (const std::string &type, const std::string &subType); @@ -59,15 +58,6 @@ public: const std::string &getSubType () const; bool setSubType (const std::string &subType); - const std::list &getParameters () const; - void addParameter (const std::string ¶mName, const std::string ¶mValue); - void addParameter (const HeaderParam ¶m); - void addParameters(const std::list ¶ms); - void removeParameter (const std::string ¶mName); - void removeParameter (const HeaderParam ¶m); - std::list::const_iterator findParameter (const std::string ¶mName) const; - const HeaderParam &getParameter (const std::string ¶mName) const; - std::string asString () const; bool isMultipart() const; diff --git a/src/content/header/header-p.h b/src/content/header/header-p.h new file mode 100644 index 000000000..3af1e3688 --- /dev/null +++ b/src/content/header/header-p.h @@ -0,0 +1,41 @@ +/* + * header-p.h + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_HEADER_P_H_ +#define _L_HEADER_P_H_ + +#include + +#include "object/clonable-object-p.h" + +#include "header.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class HeaderPrivate : public ClonableObjectPrivate { +private: + std::list parameters; + L_DECLARE_PUBLIC(Header); +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_HEADER_P_H_ \ No newline at end of file diff --git a/src/content/header-param.cpp b/src/content/header/header-param.cpp similarity index 100% rename from src/content/header-param.cpp rename to src/content/header/header-param.cpp diff --git a/src/content/header-param.h b/src/content/header/header-param.h similarity index 100% rename from src/content/header-param.h rename to src/content/header/header-param.h diff --git a/src/content/header/header.cpp b/src/content/header/header.cpp new file mode 100644 index 000000000..a621a2e8b --- /dev/null +++ b/src/content/header/header.cpp @@ -0,0 +1,88 @@ +/* + * header.cpp + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "linphone/utils/utils.h" +#include "linphone/utils/algorithm.h" + +#include "header-p.h" +#include "header-param.h" + +// ============================================================================= + +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +// ----------------------------------------------------------------------------- + +Header::Header(HeaderPrivate &p) : ClonableObject(p) { + +} + +const std::list &Header::getParameters () const { + L_D(); + + return d->parameters; +} + +void Header::addParameter (const std::string ¶mName, const std::string ¶mValue) { + addParameter(HeaderParam(paramName, paramValue)); +} + +void Header::addParameter (const HeaderParam ¶m) { + L_D(); + removeParameter(param); + d->parameters.push_back(param); +} + +void Header::addParameters(const std::list ¶ms) { + for (auto it = std::begin(params); it!=std::end(params); ++it) { + HeaderParam param = *it; + addParameter(param.getName(), param.getValue()); + } +} + +void Header::removeParameter (const std::string ¶mName) { + L_D(); + auto it = findParameter(paramName); + if (it != d->parameters.cend()) + d->parameters.remove(*it); +} + +void Header::removeParameter (const HeaderParam ¶m) { + removeParameter(param.getName()); +} + +std::list::const_iterator Header::findParameter (const std::string ¶mName) const { + L_D(); + return findIf(d->parameters, [¶mName](const HeaderParam ¶m) { + return param.getName() == paramName; + }); +} + +const HeaderParam &Header::getParameter (const std::string ¶mName) const { + L_D(); + std::list::const_iterator it = findParameter(paramName); + if (it != d->parameters.cend()) { + return *it; + } + return Utils::getEmptyConstRefObject(); +} + +LINPHONE_END_NAMESPACE \ No newline at end of file diff --git a/src/content/header/header.h b/src/content/header/header.h new file mode 100644 index 000000000..9fb3dab47 --- /dev/null +++ b/src/content/header/header.h @@ -0,0 +1,54 @@ +/* + * header.h + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_HEADER_H_ +#define _L_HEADER_H_ + +#include + +#include "object/clonable-object.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class HeaderPrivate; +class HeaderParam; + +class LINPHONE_PUBLIC Header : public ClonableObject { +public: + const std::list &getParameters () const; + void addParameter (const std::string ¶mName, const std::string ¶mValue); + void addParameter (const HeaderParam ¶m); + void addParameters(const std::list ¶ms); + void removeParameter (const std::string ¶mName); + void removeParameter (const HeaderParam ¶m); + std::list::const_iterator findParameter (const std::string ¶mName) const; + const HeaderParam &getParameter (const std::string ¶mName) const; + +protected: + explicit Header (HeaderPrivate &p); + +private: + L_DECLARE_PRIVATE(Header); +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_HEADER_H_ From c0a7c027a6c54fd79b73ae0fda288f643fc38aef Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Fri, 23 Mar 2018 17:56:09 +0100 Subject: [PATCH 31/67] Improved multipart tester --- tester/multipart-tester.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/tester/multipart-tester.cpp b/tester/multipart-tester.cpp index b16e306bd..d3b9f21b5 100644 --- a/tester/multipart-tester.cpp +++ b/tester/multipart-tester.cpp @@ -58,7 +58,7 @@ static void chat_message_multipart_modifier_base(bool first_file_transfer, bool } else { Content *content = new Content(); content->setContentType(ContentType::PlainText); - content->setBody("Hello Part 1"); + content->setBody("Hello part 1"); marieMessage->addContent(content); } @@ -73,7 +73,7 @@ static void chat_message_multipart_modifier_base(bool first_file_transfer, bool } else { Content *content = new Content(); content->setContentType(ContentType::PlainText); - content->setBody("Hello Part 2"); + content->setBody("Hello part 2"); marieMessage->addContent(content); } @@ -83,6 +83,9 @@ static void chat_message_multipart_modifier_base(bool first_file_transfer, bool BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneMessageReceived,1)); BC_ASSERT_PTR_NOT_NULL(pauline->stat.last_received_chat_message); BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_content_type(pauline->stat.last_received_chat_message), "multipart/mixed"); + if (!first_file_transfer) { + BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_text(pauline->stat.last_received_chat_message), "Hello part 1"); + } linphone_core_manager_destroy(marie); linphone_core_manager_destroy(pauline); From 8f2be0252a03c9fc8361d3221e94f6c5325163dd Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Mon, 26 Mar 2018 10:57:08 +0200 Subject: [PATCH 32/67] Fixed 2 issues related to content type parameters : one in = operator, one in the Sal --- src/content/content-type.cpp | 1 + src/content/header/header.cpp | 5 +++++ src/content/header/header.h | 1 + src/sal/op.cpp | 8 +++++++- tester/multipart-tester.cpp | 16 +++++++++++++--- 5 files changed, 27 insertions(+), 4 deletions(-) diff --git a/src/content/content-type.cpp b/src/content/content-type.cpp index be3b7da00..e34241a40 100644 --- a/src/content/content-type.cpp +++ b/src/content/content-type.cpp @@ -121,6 +121,7 @@ ContentType &ContentType::operator= (const ContentType &other) { if (this != &other) { setType(other.getType()); setSubType(other.getSubType()); + cleanParameters(); addParameters(other.getParameters()); } diff --git a/src/content/header/header.cpp b/src/content/header/header.cpp index a621a2e8b..0c8017e60 100644 --- a/src/content/header/header.cpp +++ b/src/content/header/header.cpp @@ -35,6 +35,11 @@ Header::Header(HeaderPrivate &p) : ClonableObject(p) { } +void Header::cleanParameters() { + L_D(); + d->parameters.clear(); +} + const std::list &Header::getParameters () const { L_D(); diff --git a/src/content/header/header.h b/src/content/header/header.h index 9fb3dab47..822839516 100644 --- a/src/content/header/header.h +++ b/src/content/header/header.h @@ -33,6 +33,7 @@ class HeaderParam; class LINPHONE_PUBLIC Header : public ClonableObject { public: + void cleanParameters(); const std::list &getParameters () const; void addParameter (const std::string ¶mName, const std::string ¶mValue); void addParameter (const HeaderParam ¶m); diff --git a/src/sal/op.cpp b/src/sal/op.cpp index e5e211f3b..497a7a99b 100644 --- a/src/sal/op.cpp +++ b/src/sal/op.cpp @@ -1029,12 +1029,18 @@ void SalOp::process_incoming_message(const belle_sip_request_event_t *event) { /* if we just deciphered a message, use the deciphered part(which can be a rcs xml body pointing to the file to retreive from server)*/ salmsg.text=(!external_body)?belle_sip_message_get_body(BELLE_SIP_MESSAGE(req)):NULL; salmsg.url=NULL; - salmsg.content_type = ms_strdup_printf("%s/%s", belle_sip_header_content_type_get_type(content_type), belle_sip_header_content_type_get_subtype(content_type)); + + char buffer[1024]; + size_t offset = 0; + belle_sip_parameters_marshal(BELLE_SIP_PARAMETERS(content_type), buffer, 1024, &offset); + buffer[offset] = '\0'; + salmsg.content_type = ms_strdup_printf("%s/%s%s", belle_sip_header_content_type_get_type(content_type), belle_sip_header_content_type_get_subtype(content_type), buffer); if (external_body && belle_sip_parameters_get_parameter(BELLE_SIP_PARAMETERS(content_type),"URL")) { size_t url_length=strlen(belle_sip_parameters_get_parameter(BELLE_SIP_PARAMETERS(content_type),"URL")); salmsg.url = ms_strdup(belle_sip_parameters_get_parameter(BELLE_SIP_PARAMETERS(content_type),"URL")+1); /* skip first "*/ ((char*)salmsg.url)[url_length-2]='\0'; /*remove trailing "*/ } + salmsg.message_id=message_id; salmsg.time=date ? belle_sip_header_date_get_time(date) : time(NULL); this->root->callbacks.message_received(this,&salmsg); diff --git a/tester/multipart-tester.cpp b/tester/multipart-tester.cpp index d3b9f21b5..c94dc9a2e 100644 --- a/tester/multipart-tester.cpp +++ b/tester/multipart-tester.cpp @@ -82,9 +82,19 @@ static void chat_message_multipart_modifier_base(bool first_file_transfer, bool BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneMessageReceived,1)); BC_ASSERT_PTR_NOT_NULL(pauline->stat.last_received_chat_message); - BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_content_type(pauline->stat.last_received_chat_message), "multipart/mixed"); - if (!first_file_transfer) { - BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_text(pauline->stat.last_received_chat_message), "Hello part 1"); + + if (first_file_transfer || second_file_transfer) { + LinphoneContent *content = linphone_chat_message_get_file_transfer_information(pauline->stat.last_received_chat_message); + BC_ASSERT_PTR_NOT_NULL(content); + linphone_content_unref(content); + } + if (!first_file_transfer || !second_file_transfer) { + const char *content = linphone_chat_message_get_text_content(pauline->stat.last_received_chat_message); + BC_ASSERT_PTR_NOT_NULL(content); + if (!first_file_transfer) + BC_ASSERT_STRING_EQUAL(content, "Hello part 1"); + else if (!second_file_transfer) + BC_ASSERT_STRING_EQUAL(content, "Hello part 2"); } linphone_core_manager_destroy(marie); From 3a6fe5193901e0abe538fb4a49beff17bb2a0b33 Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Mon, 26 Mar 2018 15:58:51 +0200 Subject: [PATCH 33/67] Fixed content type parsing + added test --- src/content/content-type.cpp | 2 +- tester/content-manager-tester.cpp | 11 ++++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/content/content-type.cpp b/src/content/content-type.cpp index e34241a40..f8e5be8ca 100644 --- a/src/content/content-type.cpp +++ b/src/content/content-type.cpp @@ -79,7 +79,7 @@ ContentType::ContentType (const string &contentType) : Header(*new ContentTypePr token = params.substr(0, posParam); } addParameter(HeaderParam(token)); - params.erase(0, pos + 1); + params.erase(0, posParam + 1); } while (posParam != std::string::npos); } } diff --git a/tester/content-manager-tester.cpp b/tester/content-manager-tester.cpp index de371dfb4..9509b5442 100644 --- a/tester/content-manager-tester.cpp +++ b/tester/content-manager-tester.cpp @@ -352,9 +352,18 @@ void list_to_multipart () { BC_ASSERT_TRUE(originalStr == generatedStr); } +static void content_type_parsing(void) { + const string type = "message/external-body;access-type=URL;URL=\"https://www.linphone.org/img/linphone-open-source-voip-projectX2.png\""; + ContentType contentType = ContentType(type); + BC_ASSERT_STRING_EQUAL("message", contentType.getType().c_str()); + BC_ASSERT_STRING_EQUAL("external-body", contentType.getSubType().c_str()); + BC_ASSERT_TRUE(type == contentType.asString()); +} + test_t content_manager_tests[] = { TEST_NO_TAG("Multipart to list", multipart_to_list), - TEST_NO_TAG("List to multipart", list_to_multipart) + TEST_NO_TAG("List to multipart", list_to_multipart), + TEST_NO_TAG("Content type parsing", content_type_parsing) }; test_suite_t content_manager_test_suite = { From 75b80bbe98c1f18801738bd756715bbac084bf23 Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Mon, 26 Mar 2018 16:05:09 +0200 Subject: [PATCH 34/67] Do not compare parameters when comparing ContentType --- src/content/content-type.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/content/content-type.cpp b/src/content/content-type.cpp index f8e5be8ca..4f357f3ee 100644 --- a/src/content/content-type.cpp +++ b/src/content/content-type.cpp @@ -130,8 +130,7 @@ ContentType &ContentType::operator= (const ContentType &other) { bool ContentType::operator== (const ContentType &other) const { return getType() == other.getType() && - getSubType() == other.getSubType() && - getParameters() == other.getParameters(); + getSubType() == other.getSubType(); } bool ContentType::operator!= (const ContentType &other) const { From 22218cb188c0dd6a9801ae0e11e31f07412a9924 Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Mon, 26 Mar 2018 16:07:26 +0200 Subject: [PATCH 35/67] Improved log + fixed external body url format --- coreapi/friendlist.c | 2 +- src/chat/chat-message/chat-message.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/coreapi/friendlist.c b/coreapi/friendlist.c index 249bae980..6f196721e 100644 --- a/coreapi/friendlist.c +++ b/coreapi/friendlist.c @@ -962,7 +962,7 @@ void linphone_friend_list_notify_presence_received(LinphoneFriendList *list, Lin const char *subtype = linphone_content_get_subtype(body); if ((strcmp(type, "multipart") != 0) || (strcmp(subtype, "related") != 0)) { - ms_warning("multipart presence notified but it is not 'multipart/related'"); + ms_warning("multipart presence notified but it is not 'multipart/related', instead is '%s/%s'", type, subtype); return; } diff --git a/src/chat/chat-message/chat-message.cpp b/src/chat/chat-message/chat-message.cpp index 407a9e734..26232bbeb 100644 --- a/src/chat/chat-message/chat-message.cpp +++ b/src/chat/chat-message/chat-message.cpp @@ -741,7 +741,7 @@ void ChatMessagePrivate::send () { auto msgOp = dynamic_cast(op); if (!externalBodyUrl.empty()) { - char *content_type = ms_strdup_printf("message/external-body; access-type=URL; URL=\"%s\"", externalBodyUrl.c_str()); + char *content_type = ms_strdup_printf("message/external-body;access-type=URL;URL=\"%s\"", externalBodyUrl.c_str()); msgOp->send_message(content_type, NULL); ms_free(content_type); } else if (internalContent.getContentType().isValid()) { From 7e5ee05263388560205d0a0d88a0f737a2e03099 Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Mon, 26 Mar 2018 17:19:04 +0200 Subject: [PATCH 36/67] Improved b64 tests --- tester/message_tester.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tester/message_tester.c b/tester/message_tester.c index 396f4b9c4..8922adf20 100644 --- a/tester/message_tester.c +++ b/tester/message_tester.c @@ -2294,15 +2294,19 @@ void text_message_with_custom_content_type_and_lime(void) { static int im_encryption_engine_process_incoming_message_cb(LinphoneImEncryptionEngine *engine, LinphoneChatRoom *room, LinphoneChatMessage *msg) { + ms_debug("IM encryption process incoming message with content type %s", linphone_chat_message_get_content_type(msg)); if (linphone_chat_message_get_content_type(msg)) { if (strcmp(linphone_chat_message_get_content_type(msg), "cipher/b64") == 0) { size_t b64Size = 0; unsigned char *output; - bctbx_base64_decode(NULL, &b64Size, (unsigned char *)linphone_chat_message_get_text(msg), strlen(linphone_chat_message_get_text(msg))); + const char *data = linphone_chat_message_get_text(msg); + ms_debug("IM encryption process incoming message crypted message is %s", data); + bctbx_base64_decode(NULL, &b64Size, (unsigned char *)data, strlen(data)); output = (unsigned char *)ms_malloc(b64Size+1), - bctbx_base64_decode(output, &b64Size, (unsigned char *)linphone_chat_message_get_text(msg), strlen(linphone_chat_message_get_text(msg))); + bctbx_base64_decode(output, &b64Size, (unsigned char *)data, strlen(data)); output[b64Size] = '\0'; linphone_chat_message_set_text(msg, (char *)output); + ms_debug("IM encryption process incoming message decrypted message is %s", output); ms_free(output); linphone_chat_message_set_content_type(msg, "text/plain"); return 0; From 2081f71c78aeef2a3b6605b79669b06c5e8c6a7e Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Tue, 27 Mar 2018 10:10:22 +0200 Subject: [PATCH 37/67] Added more tests for ContentType parsing --- tester/content-manager-tester.cpp | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/tester/content-manager-tester.cpp b/tester/content-manager-tester.cpp index 9509b5442..296231086 100644 --- a/tester/content-manager-tester.cpp +++ b/tester/content-manager-tester.cpp @@ -21,6 +21,7 @@ #include "content/content-manager.h" #include "content/content-type.h" #include "content/content.h" +#include "content/header/header-param.h" #include "liblinphone_tester.h" #include "tester_utils.h" @@ -353,10 +354,31 @@ void list_to_multipart () { } static void content_type_parsing(void) { - const string type = "message/external-body;access-type=URL;URL=\"https://www.linphone.org/img/linphone-open-source-voip-projectX2.png\""; + string type = "message/external-body;access-type=URL;URL=\"https://www.linphone.org/img/linphone-open-source-voip-projectX2.png\""; ContentType contentType = ContentType(type); BC_ASSERT_STRING_EQUAL("message", contentType.getType().c_str()); BC_ASSERT_STRING_EQUAL("external-body", contentType.getSubType().c_str()); + BC_ASSERT_STRING_EQUAL("URL", contentType.getParameter("access-type").getValue().c_str()); + BC_ASSERT_STRING_EQUAL("\"https://www.linphone.org/img/linphone-open-source-voip-projectX2.png\"", contentType.getParameter("URL").getValue().c_str()); + BC_ASSERT_STRING_EQUAL("", contentType.getParameter("boundary").getValue().c_str()); + BC_ASSERT_EQUAL(2, contentType.getParameters().size(), int, "%d"); + BC_ASSERT_TRUE(type == contentType.asString()); + + type = "multipart/mixed;boundary=-----------------------------14737809831466499882746641450"; + contentType = ContentType(type); + BC_ASSERT_STRING_EQUAL("multipart", contentType.getType().c_str()); + BC_ASSERT_STRING_EQUAL("mixed", contentType.getSubType().c_str()); + BC_ASSERT_STRING_EQUAL("-----------------------------14737809831466499882746641450", contentType.getParameter("boundary").getValue().c_str()); + BC_ASSERT_STRING_EQUAL("", contentType.getParameter("access-type").getValue().c_str()); + BC_ASSERT_EQUAL(1, contentType.getParameters().size(), int, "%d"); + BC_ASSERT_TRUE(type == contentType.asString()); + + type = "plain/text"; + contentType = ContentType(type); + BC_ASSERT_STRING_EQUAL("plain", contentType.getType().c_str()); + BC_ASSERT_STRING_EQUAL("text", contentType.getSubType().c_str()); + BC_ASSERT_STRING_EQUAL("", contentType.getParameter("boundary").getValue().c_str()); + BC_ASSERT_EQUAL(0, contentType.getParameters().size(), int, "%d"); BC_ASSERT_TRUE(type == contentType.asString()); } From 813ab614ebdcdadf79af64a9dbde9c12cc3644da Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Tue, 27 Mar 2018 11:48:40 +0200 Subject: [PATCH 38/67] Use Header class instead of pair in Content + improved tester --- coreapi/bellesip_sal/sal_impl.c | 4 ++ src/c-wrapper/api/c-content.cpp | 15 +++-- src/c-wrapper/internal/c-sal.h | 1 + .../multipart-chat-message-modifier.cpp | 5 +- src/content/content-manager.cpp | 8 +-- src/content/content-p.h | 4 +- src/content/content-type.cpp | 3 +- src/content/content.cpp | 18 ++++-- src/content/content.h | 6 +- src/content/header/header-p.h | 2 + src/content/header/header.cpp | 62 ++++++++++++++++++- src/content/header/header.h | 19 +++++- tester/content-manager-tester.cpp | 26 +++++--- 13 files changed, 140 insertions(+), 33 deletions(-) diff --git a/coreapi/bellesip_sal/sal_impl.c b/coreapi/bellesip_sal/sal_impl.c index 771155918..bdf3683dd 100644 --- a/coreapi/bellesip_sal/sal_impl.c +++ b/coreapi/bellesip_sal/sal_impl.c @@ -446,3 +446,7 @@ const char * sal_body_handler_get_header(const SalBodyHandler *body_handler, con } return NULL; } + +const belle_sip_list_t* sal_body_handler_get_headers(const SalBodyHandler *body_handler) { + return belle_sip_body_handler_get_headers(BELLE_SIP_BODY_HANDLER(body_handler)); +} diff --git a/src/c-wrapper/api/c-content.cpp b/src/c-wrapper/api/c-content.cpp index 2b68cbbde..580c78ca3 100644 --- a/src/c-wrapper/api/c-content.cpp +++ b/src/c-wrapper/api/c-content.cpp @@ -25,6 +25,7 @@ #include "content/content.h" #include "content/content-type.h" #include "content/header/header-param.h" +#include "content/header/header.h" #include "content/content-manager.h" #include "content/file-content.h" #include "content/file-transfer-content.h" @@ -259,6 +260,13 @@ static LinphoneContent * linphone_content_new_with_body_handler(SalBodyHandler * belle_sip_free(body); } + belle_sip_list_t *headers = (belle_sip_list_t *)sal_body_handler_get_headers(body_handler); + while (headers) { + belle_sip_header_t *cHeader = BELLE_SIP_HEADER(headers->data); + LinphonePrivate::Header header = LinphonePrivate::Header(belle_sip_header_get_name(cHeader), belle_sip_header_get_unparsed_value(cHeader)); + L_GET_CPP_PTR_FROM_C_OBJECT(content)->addHeader(header); + headers = headers->next; + } if (sal_body_handler_get_encoding(body_handler)) linphone_content_set_encoding(content, sal_body_handler_get_encoding(body_handler)); } @@ -307,12 +315,7 @@ SalBodyHandler * sal_body_handler_from_content(const LinphoneContent *content) { } for (const auto &header : L_GET_CPP_PTR_FROM_C_OBJECT(content)->getHeaders()) { - belle_sip_header_t *additionalHeader = BELLE_SIP_HEADER( - belle_sip_header_create( - header.first.c_str(), - header.second.c_str() - ) - ); + belle_sip_header_t *additionalHeader = belle_sip_header_parse(header.asString().c_str()); belle_sip_body_handler_add_header(BELLE_SIP_BODY_HANDLER(body_handler), additionalHeader); } diff --git a/src/c-wrapper/internal/c-sal.h b/src/c-wrapper/internal/c-sal.h index ebf373229..f34c4ee5f 100644 --- a/src/c-wrapper/internal/c-sal.h +++ b/src/c-wrapper/internal/c-sal.h @@ -650,6 +650,7 @@ SalBodyHandler * sal_body_handler_get_part(const SalBodyHandler *body_handler, i const belle_sip_list_t * sal_body_handler_get_parts(const SalBodyHandler *body_handler); SalBodyHandler * sal_body_handler_find_part_by_header(const SalBodyHandler *body_handler, const char *header_name, const char *header_value); const char * sal_body_handler_get_header(const SalBodyHandler *body_handler, const char *header_name); +const belle_sip_list_t* sal_body_handler_get_headers(const SalBodyHandler *body_handler); /*this function parses a document with key=value pairs separated by new lines, and extracts the value for a given key*/ int sal_lines_get_value(const char *data, const char *key, char *value, size_t value_size); diff --git a/src/chat/modifier/multipart-chat-message-modifier.cpp b/src/chat/modifier/multipart-chat-message-modifier.cpp index 13041bdb4..8ed8312d9 100644 --- a/src/chat/modifier/multipart-chat-message-modifier.cpp +++ b/src/chat/modifier/multipart-chat-message-modifier.cpp @@ -22,6 +22,7 @@ #include "chat/chat-message/chat-message.h" #include "content/content-type.h" +#include "content/header/header.h" #include "content/content-manager.h" #include "content/file-transfer-content.h" @@ -55,8 +56,8 @@ ChatMessageModifier::Result MultipartChatMessageModifier::decode (const shared_p content->setContentType(c.getContentType()); content->setContentDisposition(c.getContentDisposition()); content->setContentEncoding(c.getContentEncoding()); - for (const pair &pair : c.getHeaders()) { - content->addHeader(pair.first, pair.second); + for (const Header &header : c.getHeaders()) { + content->addHeader(header); } content->setBodyFromUtf8(c.getBodyAsUtf8String()); } else { diff --git a/src/content/content-manager.cpp b/src/content/content-manager.cpp index cbecfaa83..ff341bcf2 100644 --- a/src/content/content-manager.cpp +++ b/src/content/content-manager.cpp @@ -29,14 +29,14 @@ // ============================================================================= -using namespace std; - -LINPHONE_BEGIN_NAMESPACE - namespace { constexpr const char MultipartBoundary[] = "---------------------------14737809831466499882746641449"; } +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + // ----------------------------------------------------------------------------- list ContentManager::multipartToContentList (const Content &content) { diff --git a/src/content/content-p.h b/src/content/content-p.h index 167712313..9dc4e1d31 100644 --- a/src/content/content-p.h +++ b/src/content/content-p.h @@ -29,13 +29,15 @@ LINPHONE_BEGIN_NAMESPACE +class Header; + class ContentPrivate : public ClonableObjectPrivate { private: std::vector body; ContentType contentType; ContentDisposition contentDisposition; std::string contentEncoding; - std::list> headers; + std::list
headers; L_DECLARE_PUBLIC(Content); }; diff --git a/src/content/content-type.cpp b/src/content/content-type.cpp index 4f357f3ee..35391783b 100644 --- a/src/content/content-type.cpp +++ b/src/content/content-type.cpp @@ -179,8 +179,7 @@ string ContentType::asString () const { L_D(); if (isValid()) { string asString = d->type + "/" + d->subType; - for (auto it = std::begin(getParameters()); it!=std::end(getParameters()); ++it) { - HeaderParam param = *it; + for (const auto ¶m : getParameters()) { asString += param.asString(); } return asString; diff --git a/src/content/content.cpp b/src/content/content.cpp index f27e731d6..91761e268 100644 --- a/src/content/content.cpp +++ b/src/content/content.cpp @@ -25,6 +25,7 @@ #include "content-p.h" #include "content-type.h" +#include "header/header.h" // ============================================================================= @@ -197,10 +198,17 @@ bool Content::isFileTransfer () const { void Content::addHeader (const string &headerName, const string &headerValue) { L_D(); removeHeader(headerName); - d->headers.push_back(make_pair(headerName, headerValue)); + Header header = Header(headerName, headerValue); + d->headers.push_back(header); } -const list> &Content::getHeaders () const { +void Content::addHeader (const Header &header) { + L_D(); + removeHeader(header.getName()); + d->headers.push_back(header); +} + +const list
&Content::getHeaders () const { L_D(); return d->headers; } @@ -212,10 +220,10 @@ void Content::removeHeader (const string &headerName) { d->headers.remove(*it); } -list>::const_iterator Content::findHeader (const string &headerName) const { +list
::const_iterator Content::findHeader (const string &headerName) const { L_D(); - return findIf(d->headers, [&headerName](const pair &pair) { - return pair.first == headerName; + return findIf(d->headers, [&headerName](const Header &header) { + return header.getName() == headerName; }); } diff --git a/src/content/content.h b/src/content/content.h index 94d832643..50066133f 100644 --- a/src/content/content.h +++ b/src/content/content.h @@ -35,6 +35,7 @@ LINPHONE_BEGIN_NAMESPACE class ContentDisposition; class ContentType; class ContentPrivate; +class Header; class LINPHONE_PUBLIC Content : public ClonableObject, public AppDataContainer { public: @@ -76,10 +77,11 @@ public: virtual bool isFile () const; virtual bool isFileTransfer () const; - const std::list> &getHeaders () const; + const std::list
&getHeaders () const; void addHeader (const std::string &headerName, const std::string &headerValue); + void addHeader (const Header &header); void removeHeader (const std::string &headerName); - std::list>::const_iterator findHeader (const std::string &headerName) const; + std::list
::const_iterator findHeader (const std::string &headerName) const; protected: explicit Content (ContentPrivate &p); diff --git a/src/content/header/header-p.h b/src/content/header/header-p.h index 3af1e3688..fd4663efe 100644 --- a/src/content/header/header-p.h +++ b/src/content/header/header-p.h @@ -32,6 +32,8 @@ LINPHONE_BEGIN_NAMESPACE class HeaderPrivate : public ClonableObjectPrivate { private: + std::string name; + std::string value; std::list parameters; L_DECLARE_PUBLIC(Header); }; diff --git a/src/content/header/header.cpp b/src/content/header/header.cpp index 0c8017e60..561b7ce05 100644 --- a/src/content/header/header.cpp +++ b/src/content/header/header.cpp @@ -35,14 +35,64 @@ Header::Header(HeaderPrivate &p) : ClonableObject(p) { } -void Header::cleanParameters() { +Header::Header (const string &name, const string &value) : ClonableObject(*new HeaderPrivate) { + setName(name); + setValue(value); +} + +Header::Header (const string &name, const string &value, const list ¶ms) : Header(name, value) { + addParameters(params); +} + +Header::Header (const Header &other) : Header(other.getName(), other.getValue(), other.getParameters()) {} + +Header &Header::operator= (const Header &other) { + if (this != &other) { + setName(other.getName()); + setValue(other.getValue()); + cleanParameters(); + addParameters(other.getParameters()); + } + + return *this; +} + +bool Header::operator== (const Header &other) const { + return getName() == other.getName() && + getValue() == other.getValue(); +} + +bool Header::operator!= (const Header &other) const { + return !(*this == other); +} + +void Header::setName (const string &name) { + L_D(); + d->name = name; +} + +string Header::getName () const { + L_D(); + return d->name; +} + +void Header::setValue (const string &value) { + L_D(); + d->value = value; +} + +string Header::getValue () const { + L_D(); + return d->value; +} + +void Header::cleanParameters () { L_D(); d->parameters.clear(); } const std::list &Header::getParameters () const { L_D(); - return d->parameters; } @@ -90,4 +140,12 @@ const HeaderParam &Header::getParameter (const std::string ¶mName) const { return Utils::getEmptyConstRefObject(); } +string Header::asString () const { + string asString = getName() + ":" + getValue(); + for (const auto ¶m : getParameters()) { + asString += param.asString(); + } + return asString; +} + LINPHONE_END_NAMESPACE \ No newline at end of file diff --git a/src/content/header/header.h b/src/content/header/header.h index 822839516..a0b8083fe 100644 --- a/src/content/header/header.h +++ b/src/content/header/header.h @@ -33,7 +33,22 @@ class HeaderParam; class LINPHONE_PUBLIC Header : public ClonableObject { public: - void cleanParameters(); + Header (const std::string &name, const std::string &value); + Header (const std::string &name, const std::string &value, const std::list ¶ms); + Header (const Header &other); + + Header &operator= (const Header &other); + + bool operator== (const Header &other) const; + bool operator!= (const Header &other) const; + + void setName (const std::string &name); + std::string getName () const; + + void setValue (const std::string &value); + std::string getValue () const; + + void cleanParameters (); const std::list &getParameters () const; void addParameter (const std::string ¶mName, const std::string ¶mValue); void addParameter (const HeaderParam ¶m); @@ -43,6 +58,8 @@ public: std::list::const_iterator findParameter (const std::string ¶mName) const; const HeaderParam &getParameter (const std::string ¶mName) const; + std::string asString () const; + protected: explicit Header (HeaderPrivate &p); diff --git a/tester/content-manager-tester.cpp b/tester/content-manager-tester.cpp index 296231086..24c4817d5 100644 --- a/tester/content-manager-tester.cpp +++ b/tester/content-manager-tester.cpp @@ -61,6 +61,7 @@ static const char* source_multipart = \ " " \ "" \ "-----------------------------14737809831466499882746641449\r\n" \ +"Content-Encoding: b64\r\n" \ "Content-Type: application/pidf+xml;charset=\"UTF-8\"\r\n\r\n" \ "" \ "" \ @@ -78,6 +79,7 @@ static const char* source_multipart = \ " " \ "" \ "-----------------------------14737809831466499882746641449\r\n" \ +"Content-Id: toto;param1=value1;param2;param3=value3\r\n" \ "Content-Type: application/pidf+xml;charset=\"UTF-8\"\r\n\r\n" \ "" \ "" \ @@ -98,8 +100,8 @@ static const char* source_multipart = \ static const char* generated_multipart = \ "-----------------------------14737809831466499882746641449\r\n" \ -"Content-Type: application/rlmi+xml;charset=\"UTF-8\"\r\n\r\n" \ -"Content-Length:582" \ +"Content-Type: application/rlmi+xml;charset=\"UTF-8\"\r\n" \ +"Content-Length:582\r\n\r\n" \ "" \ "" \ " " \ @@ -113,8 +115,8 @@ static const char* generated_multipart = \ " " \ "" \ "-----------------------------14737809831466499882746641449\r\n" \ -"Content-Type: application/pidf+xml;charset=\"UTF-8\"\r\n\r\n" \ -"Content-Length:561" \ +"Content-Type: application/pidf+xml;charset=\"UTF-8\"\r\n" \ +"Content-Length:561\r\n\r\n" \ "" \ "" \ " " \ @@ -131,8 +133,9 @@ static const char* generated_multipart = \ " " \ "" \ "-----------------------------14737809831466499882746641449\r\n" \ -"Content-Type: application/pidf+xml;charset=\"UTF-8\"\r\n\r\n" \ -"Content-Length:561" \ +"Content-Encoding:b64\r\n" \ +"Content-Type: application/pidf+xml;charset=\"UTF-8\"\r\n" \ +"Content-Length:561\r\n\r\n" \ "" \ "" \ " " \ @@ -149,8 +152,9 @@ static const char* generated_multipart = \ " " \ "" \ "-----------------------------14737809831466499882746641449\r\n" \ -"Content-Type: application/pidf+xml;charset=\"UTF-8\"\r\n\r\n" \ -"Content-Length:546" \ +"Content-Id:toto;param1=value1;param2;param3=value3\r\n" \ +"Content-Type: application/pidf+xml;charset=\"UTF-8\"\r\n" \ +"Content-Length:546\r\n\r\n" \ "" \ "" \ " " \ @@ -326,8 +330,14 @@ void list_to_multipart () { content2.setContentType(contentType); Content content3; content3.setBody(part3); + content3.addHeader("Content-Encoding", "b64"); content3.setContentType(contentType); Content content4; + Header header = Header("Content-Id", "toto"); + header.addParameter("param1", "value1"); + header.addParameter("param2", ""); + header.addParameter("param3", "value3"); + content4.addHeader(header); content4.setBody(part4); content4.setContentType(contentType); list contents = {&content1, &content2, &content3, &content4}; From 646cff8460b50d146b0f407841e9f4f233c4d98e Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Tue, 27 Mar 2018 12:16:42 +0200 Subject: [PATCH 39/67] Improved presence tester, now more reliable --- tester/presence_server_tester.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/tester/presence_server_tester.c b/tester/presence_server_tester.c index 62bb8a364..4aa3b4ee8 100644 --- a/tester/presence_server_tester.c +++ b/tester/presence_server_tester.c @@ -430,8 +430,10 @@ static void test_presence_list_base(bool_t enable_compression) { lcs = bctbx_list_append(lcs, pauline->lc); wait_for_list(lcs, &laure->stat.number_of_NotifyPresenceReceived, 2, 4000); - BC_ASSERT_EQUAL(laure->stat.number_of_NotifyPresenceReceived, 2, int, "%d"); - BC_ASSERT_EQUAL(linphone_friend_list_get_expected_notification_version(linphone_core_get_default_friend_list(laure->lc)), 1, int, "%d"); + BC_ASSERT_GREATER(laure->stat.number_of_NotifyPresenceReceived, 2, int, "%d"); + BC_ASSERT_LOWER(laure->stat.number_of_NotifyPresenceReceived, 3, int, "%d"); + BC_ASSERT_GREATER(linphone_friend_list_get_expected_notification_version(linphone_core_get_default_friend_list(laure->lc)), 1, int, "%d"); + BC_ASSERT_LOWER(linphone_friend_list_get_expected_notification_version(linphone_core_get_default_friend_list(laure->lc)), 2, int, "%d"); lf = linphone_friend_list_find_friend_by_address(linphone_core_get_default_friend_list(laure->lc), get_identity_address(marie)); if (!BC_ASSERT_PTR_NOT_NULL(lf)) goto end; BC_ASSERT_EQUAL(linphone_friend_get_status(lf), LinphoneStatusBusy, int, "%d"); @@ -485,7 +487,8 @@ static void test_presence_list_base(bool_t enable_compression) { /* The number of PresenceReceived events can be 3 or 4 here. TODO: ideally it should always be 3. */ BC_ASSERT_GREATER(laure->stat.number_of_NotifyPresenceReceived, 3, int, "%d"); BC_ASSERT_LOWER(laure->stat.number_of_NotifyPresenceReceived, 4, int, "%d"); - BC_ASSERT_EQUAL(linphone_friend_list_get_expected_notification_version(linphone_core_get_default_friend_list(laure->lc)), 2, int, "%d"); + BC_ASSERT_GREATER(linphone_friend_list_get_expected_notification_version(linphone_core_get_default_friend_list(laure->lc)), 2, int, "%d"); + BC_ASSERT_LOWER(linphone_friend_list_get_expected_notification_version(linphone_core_get_default_friend_list(laure->lc)), 3, int, "%d"); lf = linphone_friend_list_find_friend_by_address(linphone_core_get_default_friend_list(laure->lc), get_identity_address(marie)); BC_ASSERT_EQUAL(linphone_friend_get_status(lf), LinphoneStatusOnThePhone, int, "%d"); From 7009b68b9a149fe5484ddc36992dbedc9be8ad62 Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Tue, 27 Mar 2018 12:45:47 +0200 Subject: [PATCH 40/67] Added << operator for ContentType and Header --- src/content/content-type.cpp | 13 +++++++++++++ src/content/content-type.h | 1 + src/content/header/header.cpp | 5 +++++ src/content/header/header.h | 1 + tester/content-manager-tester.cpp | 4 ++++ 5 files changed, 24 insertions(+) diff --git a/src/content/content-type.cpp b/src/content/content-type.cpp index 35391783b..e5d58c7a7 100644 --- a/src/content/content-type.cpp +++ b/src/content/content-type.cpp @@ -55,6 +55,7 @@ const ContentType ContentType::Sdp("application/sdp"); ContentType::ContentType (const string &contentType) : Header(*new ContentTypePrivate) { L_D(); + setName("Content-Type"); size_t pos = contentType.find('/'); size_t posParam = contentType.find(";"); size_t end = contentType.length(); @@ -82,11 +83,13 @@ ContentType::ContentType (const string &contentType) : Header(*new ContentTypePr params.erase(0, posParam + 1); } while (posParam != std::string::npos); } + setValue(d->type + "/" + d->subType); } ContentType::ContentType (const string &type, const string &subType) : Header(*new ContentTypePrivate) { L_D(); + setName("Content-Type"); if (setType(type) && !setSubType(subType)) d->type.clear(); } @@ -98,6 +101,7 @@ ContentType::ContentType ( ) : Header(*new ContentTypePrivate) { L_D(); + setName("Content-Type"); if (setType(type) && !setSubType(subType)) d->type.clear(); addParameter(parameter); @@ -110,6 +114,7 @@ ContentType::ContentType ( ) : Header(*new ContentTypePrivate) { L_D(); + setName("Content-Type"); if (setType(type) && !setSubType(subType)) d->type.clear(); addParameters(parameters); @@ -119,6 +124,7 @@ ContentType::ContentType (const ContentType &other) : ContentType(other.getType( ContentType &ContentType::operator= (const ContentType &other) { if (this != &other) { + setName("Content-Type"); setType(other.getType()); setSubType(other.getSubType()); cleanParameters(); @@ -146,6 +152,7 @@ bool ContentType::setType (const string &type) { L_D(); if (type.find('/') == string::npos) { d->type = Utils::stringToLower(type); + setValue(d->type + "/" + d->subType); return true; } return false; @@ -160,6 +167,7 @@ bool ContentType::setSubType (const string &subType) { L_D(); if (subType.find('/') == string::npos) { d->subType = Utils::stringToLower(subType); + setValue(d->type + "/" + d->subType); return true; } return false; @@ -187,6 +195,11 @@ string ContentType::asString () const { return ""; } +ostream &operator<<(ostream& stream, const ContentType& contentType) { + stream << contentType.asString(); + return stream; +} + bool ContentType::isMultipart() const { return getType() == "multipart"; } diff --git a/src/content/content-type.h b/src/content/content-type.h index 2ed267065..10f895e4d 100644 --- a/src/content/content-type.h +++ b/src/content/content-type.h @@ -59,6 +59,7 @@ public: bool setSubType (const std::string &subType); std::string asString () const; + friend std::ostream &operator<<(std::ostream&, const ContentType&); bool isMultipart() const; diff --git a/src/content/header/header.cpp b/src/content/header/header.cpp index 561b7ce05..14ce99f85 100644 --- a/src/content/header/header.cpp +++ b/src/content/header/header.cpp @@ -148,4 +148,9 @@ string Header::asString () const { return asString; } +ostream &operator<<(ostream& stream, const Header& header) { + stream << header.asString(); + return stream; +} + LINPHONE_END_NAMESPACE \ No newline at end of file diff --git a/src/content/header/header.h b/src/content/header/header.h index a0b8083fe..5d111900d 100644 --- a/src/content/header/header.h +++ b/src/content/header/header.h @@ -59,6 +59,7 @@ public: const HeaderParam &getParameter (const std::string ¶mName) const; std::string asString () const; + friend std::ostream &operator<<(std::ostream&, const Header&); protected: explicit Header (HeaderPrivate &p); diff --git a/tester/content-manager-tester.cpp b/tester/content-manager-tester.cpp index 24c4817d5..52d461ef9 100644 --- a/tester/content-manager-tester.cpp +++ b/tester/content-manager-tester.cpp @@ -24,6 +24,7 @@ #include "content/header/header-param.h" #include "liblinphone_tester.h" #include "tester_utils.h" +#include "logger/logger.h" using namespace LinphonePrivate; using namespace std; @@ -372,6 +373,7 @@ static void content_type_parsing(void) { BC_ASSERT_STRING_EQUAL("\"https://www.linphone.org/img/linphone-open-source-voip-projectX2.png\"", contentType.getParameter("URL").getValue().c_str()); BC_ASSERT_STRING_EQUAL("", contentType.getParameter("boundary").getValue().c_str()); BC_ASSERT_EQUAL(2, contentType.getParameters().size(), int, "%d"); + lInfo() << "Content-Type is " << contentType; BC_ASSERT_TRUE(type == contentType.asString()); type = "multipart/mixed;boundary=-----------------------------14737809831466499882746641450"; @@ -381,6 +383,7 @@ static void content_type_parsing(void) { BC_ASSERT_STRING_EQUAL("-----------------------------14737809831466499882746641450", contentType.getParameter("boundary").getValue().c_str()); BC_ASSERT_STRING_EQUAL("", contentType.getParameter("access-type").getValue().c_str()); BC_ASSERT_EQUAL(1, contentType.getParameters().size(), int, "%d"); + lInfo() << "Content-Type is " << contentType; BC_ASSERT_TRUE(type == contentType.asString()); type = "plain/text"; @@ -389,6 +392,7 @@ static void content_type_parsing(void) { BC_ASSERT_STRING_EQUAL("text", contentType.getSubType().c_str()); BC_ASSERT_STRING_EQUAL("", contentType.getParameter("boundary").getValue().c_str()); BC_ASSERT_EQUAL(0, contentType.getParameters().size(), int, "%d"); + lInfo() << "Content-Type is " << contentType; BC_ASSERT_TRUE(type == contentType.asString()); } From af2a607014a341da246174f5c914a697880e8d47 Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Tue, 27 Mar 2018 14:39:32 +0200 Subject: [PATCH 41/67] Improved ContentType's asString() method --- src/chat/chat-message/chat-message.cpp | 2 +- .../modifier/cpim-chat-message-modifier.cpp | 2 +- src/content/content-type.cpp | 22 ------------------- src/content/content-type.h | 3 --- src/content/header/header.cpp | 12 +++++++--- 5 files changed, 11 insertions(+), 30 deletions(-) diff --git a/src/chat/chat-message/chat-message.cpp b/src/chat/chat-message/chat-message.cpp index 26232bbeb..ddfd018a6 100644 --- a/src/chat/chat-message/chat-message.cpp +++ b/src/chat/chat-message/chat-message.cpp @@ -582,7 +582,7 @@ LinphoneReason ChatMessagePrivate::receive () { foundSupportContentType = true; break; } else - lError() << "Unsupported content-type: " << c->getContentType().asString(); + lError() << "Unsupported content-type: " << c->getContentType(); } if (!foundSupportContentType) { diff --git a/src/chat/modifier/cpim-chat-message-modifier.cpp b/src/chat/modifier/cpim-chat-message-modifier.cpp index 8958c0f82..03c35fed0 100644 --- a/src/chat/modifier/cpim-chat-message-modifier.cpp +++ b/src/chat/modifier/cpim-chat-message-modifier.cpp @@ -98,7 +98,7 @@ ChatMessageModifier::Result CpimChatMessageModifier::decode (const shared_ptrgetContents().front(); if (content->getContentType() != ContentType::Cpim) { - lError() << "[CPIM] Message is not CPIM but " << content->getContentType().asString(); + lError() << "[CPIM] Message is not CPIM but " << content->getContentType(); return ChatMessageModifier::Result::Skipped; } diff --git a/src/content/content-type.cpp b/src/content/content-type.cpp index e5d58c7a7..3d6b4689f 100644 --- a/src/content/content-type.cpp +++ b/src/content/content-type.cpp @@ -55,7 +55,6 @@ const ContentType ContentType::Sdp("application/sdp"); ContentType::ContentType (const string &contentType) : Header(*new ContentTypePrivate) { L_D(); - setName("Content-Type"); size_t pos = contentType.find('/'); size_t posParam = contentType.find(";"); size_t end = contentType.length(); @@ -89,7 +88,6 @@ ContentType::ContentType (const string &contentType) : Header(*new ContentTypePr ContentType::ContentType (const string &type, const string &subType) : Header(*new ContentTypePrivate) { L_D(); - setName("Content-Type"); if (setType(type) && !setSubType(subType)) d->type.clear(); } @@ -101,7 +99,6 @@ ContentType::ContentType ( ) : Header(*new ContentTypePrivate) { L_D(); - setName("Content-Type"); if (setType(type) && !setSubType(subType)) d->type.clear(); addParameter(parameter); @@ -114,7 +111,6 @@ ContentType::ContentType ( ) : Header(*new ContentTypePrivate) { L_D(); - setName("Content-Type"); if (setType(type) && !setSubType(subType)) d->type.clear(); addParameters(parameters); @@ -124,7 +120,6 @@ ContentType::ContentType (const ContentType &other) : ContentType(other.getType( ContentType &ContentType::operator= (const ContentType &other) { if (this != &other) { - setName("Content-Type"); setType(other.getType()); setSubType(other.getSubType()); cleanParameters(); @@ -183,23 +178,6 @@ bool ContentType::isValid () const { return !d->type.empty() && !d->subType.empty(); } -string ContentType::asString () const { - L_D(); - if (isValid()) { - string asString = d->type + "/" + d->subType; - for (const auto ¶m : getParameters()) { - asString += param.asString(); - } - return asString; - } - return ""; -} - -ostream &operator<<(ostream& stream, const ContentType& contentType) { - stream << contentType.asString(); - return stream; -} - bool ContentType::isMultipart() const { return getType() == "multipart"; } diff --git a/src/content/content-type.h b/src/content/content-type.h index 10f895e4d..c9aa7af77 100644 --- a/src/content/content-type.h +++ b/src/content/content-type.h @@ -58,9 +58,6 @@ public: const std::string &getSubType () const; bool setSubType (const std::string &subType); - std::string asString () const; - friend std::ostream &operator<<(std::ostream&, const ContentType&); - bool isMultipart() const; static bool isFile (const ContentType &contentType); diff --git a/src/content/header/header.cpp b/src/content/header/header.cpp index 14ce99f85..92920e024 100644 --- a/src/content/header/header.cpp +++ b/src/content/header/header.cpp @@ -17,6 +17,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +#include + #include "linphone/utils/utils.h" #include "linphone/utils/algorithm.h" @@ -141,11 +143,15 @@ const HeaderParam &Header::getParameter (const std::string ¶mName) const { } string Header::asString () const { - string asString = getName() + ":" + getValue(); + stringstream asString; + if (!getName().empty()) { + asString << getName() << ":"; + } + asString << getValue(); for (const auto ¶m : getParameters()) { - asString += param.asString(); + asString << param.asString(); } - return asString; + return asString.str(); } ostream &operator<<(ostream& stream, const Header& header) { From ee88045383626abd452ba66dec64b3d6bd3e447e Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Tue, 27 Mar 2018 16:10:17 +0200 Subject: [PATCH 42/67] Renamed content_manager_tester + improved header parsing + new tests --- src/content/content-type.cpp | 1 - src/content/content.cpp | 9 ++++ src/content/content.h | 1 + src/content/header/header.cpp | 41 ++++++++++++++----- src/content/header/header.h | 1 + tester/CMakeLists.txt | 2 +- ...manager-tester.cpp => contents-tester.cpp} | 33 ++++++++++++--- tester/liblinphone_tester.h | 2 +- tester/tester.c | 2 +- 9 files changed, 73 insertions(+), 19 deletions(-) rename tester/{content-manager-tester.cpp => contents-tester.cpp} (92%) diff --git a/src/content/content-type.cpp b/src/content/content-type.cpp index 3d6b4689f..7aee05247 100644 --- a/src/content/content-type.cpp +++ b/src/content/content-type.cpp @@ -82,7 +82,6 @@ ContentType::ContentType (const string &contentType) : Header(*new ContentTypePr params.erase(0, posParam + 1); } while (posParam != std::string::npos); } - setValue(d->type + "/" + d->subType); } ContentType::ContentType (const string &type, const string &subType) : Header(*new ContentTypePrivate) { diff --git a/src/content/content.cpp b/src/content/content.cpp index 91761e268..ad74de27f 100644 --- a/src/content/content.cpp +++ b/src/content/content.cpp @@ -213,6 +213,15 @@ const list
&Content::getHeaders () const { return d->headers; } +const Header &Content::getHeader (const string &headerName) const { + L_D(); + list
::const_iterator it = findHeader(headerName); + if (it != d->headers.cend()) { + return *it; + } + return Utils::getEmptyConstRefObject
(); +} + void Content::removeHeader (const string &headerName) { L_D(); auto it = findHeader(headerName); diff --git a/src/content/content.h b/src/content/content.h index 50066133f..3c29d3a1a 100644 --- a/src/content/content.h +++ b/src/content/content.h @@ -78,6 +78,7 @@ public: virtual bool isFileTransfer () const; const std::list
&getHeaders () const; + const Header &getHeader (const std::string &headerName) const; void addHeader (const std::string &headerName, const std::string &headerValue); void addHeader (const Header &header); void removeHeader (const std::string &headerName); diff --git a/src/content/header/header.cpp b/src/content/header/header.cpp index 92920e024..5924cdf5b 100644 --- a/src/content/header/header.cpp +++ b/src/content/header/header.cpp @@ -33,13 +33,34 @@ LINPHONE_BEGIN_NAMESPACE // ----------------------------------------------------------------------------- -Header::Header(HeaderPrivate &p) : ClonableObject(p) { +Header::Header(HeaderPrivate &p) : ClonableObject(p) {} -} +Header::Header() : ClonableObject(*new HeaderPrivate) {} Header::Header (const string &name, const string &value) : ClonableObject(*new HeaderPrivate) { setName(name); - setValue(value); + + size_t posParam = value.find(";"); + if (posParam == string::npos) { + setValue(value); + return; + } + + string parsedValue = value.substr(0, posParam); + string params = value.substr(posParam + 1); + string token; + do { + posParam = params.find(";"); + if (posParam == string::npos) { + token = params; + } else { + token = params.substr(0, posParam); + } + addParameter(HeaderParam(token)); + params.erase(0, posParam + 1); + } while (posParam != std::string::npos); + + setValue(parsedValue); } Header::Header (const string &name, const string &value, const list ¶ms) : Header(name, value) { @@ -93,12 +114,12 @@ void Header::cleanParameters () { d->parameters.clear(); } -const std::list &Header::getParameters () const { +const list &Header::getParameters () const { L_D(); return d->parameters; } -void Header::addParameter (const std::string ¶mName, const std::string ¶mValue) { +void Header::addParameter (const string ¶mName, const string ¶mValue) { addParameter(HeaderParam(paramName, paramValue)); } @@ -108,14 +129,14 @@ void Header::addParameter (const HeaderParam ¶m) { d->parameters.push_back(param); } -void Header::addParameters(const std::list ¶ms) { +void Header::addParameters(const list ¶ms) { for (auto it = std::begin(params); it!=std::end(params); ++it) { HeaderParam param = *it; addParameter(param.getName(), param.getValue()); } } -void Header::removeParameter (const std::string ¶mName) { +void Header::removeParameter (const string ¶mName) { L_D(); auto it = findParameter(paramName); if (it != d->parameters.cend()) @@ -126,16 +147,16 @@ void Header::removeParameter (const HeaderParam ¶m) { removeParameter(param.getName()); } -std::list::const_iterator Header::findParameter (const std::string ¶mName) const { +list::const_iterator Header::findParameter (const string ¶mName) const { L_D(); return findIf(d->parameters, [¶mName](const HeaderParam ¶m) { return param.getName() == paramName; }); } -const HeaderParam &Header::getParameter (const std::string ¶mName) const { +const HeaderParam &Header::getParameter (const string ¶mName) const { L_D(); - std::list::const_iterator it = findParameter(paramName); + list::const_iterator it = findParameter(paramName); if (it != d->parameters.cend()) { return *it; } diff --git a/src/content/header/header.h b/src/content/header/header.h index 5d111900d..583572523 100644 --- a/src/content/header/header.h +++ b/src/content/header/header.h @@ -33,6 +33,7 @@ class HeaderParam; class LINPHONE_PUBLIC Header : public ClonableObject { public: + Header (); Header (const std::string &name, const std::string &value); Header (const std::string &name, const std::string &value, const std::list ¶ms); Header (const Header &other); diff --git a/tester/CMakeLists.txt b/tester/CMakeLists.txt index b14e28572..e07217934 100644 --- a/tester/CMakeLists.txt +++ b/tester/CMakeLists.txt @@ -199,7 +199,7 @@ set(SOURCE_FILES_C set(SOURCE_FILES_CXX clonable-object-tester.cpp conference-event-tester.cpp - content-manager-tester.cpp + contents-tester.cpp cpim-tester.cpp main-db-tester.cpp multipart-tester.cpp diff --git a/tester/content-manager-tester.cpp b/tester/contents-tester.cpp similarity index 92% rename from tester/content-manager-tester.cpp rename to tester/contents-tester.cpp index 52d461ef9..99ecee08d 100644 --- a/tester/content-manager-tester.cpp +++ b/tester/contents-tester.cpp @@ -298,6 +298,7 @@ void multipart_to_list () { ms_message("\n\n----- Original part 3 -----"); ms_message("%s", originalStr3.c_str()); BC_ASSERT_TRUE(originalStr3 == generatedStr3); + BC_ASSERT_TRUE(content3.getHeader("Content-Encoding").getValue() == "b64"); Content content4 = contents.front(); contents.pop_front(); @@ -316,6 +317,10 @@ void multipart_to_list () { ms_message("\n\n----- Original part 4 -----"); ms_message("%s", originalStr4.c_str()); BC_ASSERT_TRUE(originalStr4 == generatedStr4); + BC_ASSERT_TRUE(content4.getHeader("Content-Id").getValue() == "toto"); + BC_ASSERT_TRUE(content4.getHeader("Content-Id").getParameter("param1").getValue() == "value1"); + BC_ASSERT_TRUE(content4.getHeader("Content-Id").getParameter("param2").getValue().empty()); + BC_ASSERT_TRUE(content4.getHeader("Content-Id").getParameter("param3").getValue() == "value3"); } void list_to_multipart () { @@ -396,17 +401,35 @@ static void content_type_parsing(void) { BC_ASSERT_TRUE(type == contentType.asString()); } -test_t content_manager_tests[] = { +static void content_header_parsing(void) { + string value = "toto;param1=value1;param2;param3=value3"; + Header header = Header("Content-Id", value); + BC_ASSERT_TRUE(header.getValue() == "toto"); + BC_ASSERT_TRUE(header.getParameter("param1").getValue() == "value1"); + BC_ASSERT_TRUE(header.getParameter("param2").getValue().empty()); + BC_ASSERT_TRUE(header.getParameter("param3").getValue() == "value3"); + BC_ASSERT_EQUAL(3, header.getParameters().size(), int, "%d"); + BC_ASSERT_STRING_EQUAL("", header.getParameter("encoding").getValue().c_str()); + + value = "b64"; + header = Header("Content-Encoding", value); + BC_ASSERT_TRUE(header.getValue() == value); + BC_ASSERT_EQUAL(0, header.getParameters().size(), int, "%d"); + BC_ASSERT_STRING_EQUAL("", header.getParameter("access-type").getValue().c_str()); +} + +test_t contents_tests[] = { TEST_NO_TAG("Multipart to list", multipart_to_list), TEST_NO_TAG("List to multipart", list_to_multipart), - TEST_NO_TAG("Content type parsing", content_type_parsing) + TEST_NO_TAG("Content type parsing", content_type_parsing), + TEST_NO_TAG("Content header parsing", content_header_parsing) }; -test_suite_t content_manager_test_suite = { - "Content manager", +test_suite_t contents_test_suite = { + "Contents", nullptr, nullptr, liblinphone_tester_before_each, liblinphone_tester_after_each, - sizeof(content_manager_tests) / sizeof(content_manager_tests[0]), content_manager_tests + sizeof(contents_tests) / sizeof(contents_tests[0]), contents_tests }; diff --git a/tester/liblinphone_tester.h b/tester/liblinphone_tester.h index 9824c2084..c96be9ed4 100644 --- a/tester/liblinphone_tester.h +++ b/tester/liblinphone_tester.h @@ -45,7 +45,7 @@ extern test_suite_t call_video_test_suite; extern test_suite_t clonable_object_test_suite; extern test_suite_t conference_event_test_suite; extern test_suite_t conference_test_suite; -extern test_suite_t content_manager_test_suite; +extern test_suite_t contents_test_suite; extern test_suite_t cpim_test_suite; extern test_suite_t dtmf_test_suite; extern test_suite_t event_test_suite; diff --git a/tester/tester.c b/tester/tester.c index c47cff87f..95e3a9fe5 100644 --- a/tester/tester.c +++ b/tester/tester.c @@ -604,7 +604,7 @@ void liblinphone_tester_add_suites() { bc_tester_add_suite(&stun_test_suite); bc_tester_add_suite(&event_test_suite); bc_tester_add_suite(&conference_event_test_suite); - bc_tester_add_suite(&content_manager_test_suite); + bc_tester_add_suite(&contents_test_suite); bc_tester_add_suite(&flexisip_test_suite); bc_tester_add_suite(&remote_provisioning_test_suite); bc_tester_add_suite(&quality_reporting_test_suite); From 0d604bd547e4335da52b1bc8f4f8de662dc77f1d Mon Sep 17 00:00:00 2001 From: Jehan Monnier Date: Wed, 28 Mar 2018 13:03:54 +0200 Subject: [PATCH 43/67] add performance test for resource list subscription --- tester/flexisip/userdb.conf | 2019 ++++++++++++++++++++++++++++++- tester/presence_server_tester.c | 25 +- 2 files changed, 2035 insertions(+), 9 deletions(-) diff --git a/tester/flexisip/userdb.conf b/tester/flexisip/userdb.conf index 5e861921d..b5d995365 100644 --- a/tester/flexisip/userdb.conf +++ b/tester/flexisip/userdb.conf @@ -1,9 +1,2012 @@ version:1 -liblinphone_tester@sip.example.org clrtxt:secret ; -liblinphone_tester@auth.example.org clrtxt:secret ; -liblinphone_tester@auth1.example.org clrtxt:secret ; -tester@sip.example.org clrtxt:secret ; -pauline@sip.example.org clrtxt:secret ; -marie@sip.example.org cltxt:secret ; -laure@sip.example.org clrtxt:secret ; -bellesip@sip.example.org clrtxt:secret ; +liblinphone_tester@sip.example.org md5:19ffdcec6adc70629617046a60e529fc ; liblinphone_tester +33123456789 +liblinphone_tester@auth.example.org md5:db9ddf59cb75ae15f51745192d23ddae ; +liblinphone_tester@auth1.example.org md5:fe32fa7157d629145f1282a73a36a961 ; +tester@sip.example.org md5:61d963d04c360eceb424043e0d53676b ; +pauline@sip.example.org md5:46b03c8f72e61f4340a6d3d06a726d2e ; +marie@sip.example.org md5:c4ce0fe4c1c82e4b700726e085aee9b3 ; +laure@sip.example.org md5:63d09951793c1361768531f9a9011331 ; +bellesip@sip.example.org md5:2fc013743b860819a784b0e6c4bee11a ; +liblinphone_sha_tester@sip.example.org clrtxt:secret ; +test%20username@sip.example.org clrtxt:secret ; + +sip:user_1@sip.example.org clrtxt:secret ; +sip:user_2@sip.example.org clrtxt:secret ; +sip:user_3@sip.example.org clrtxt:secret ; +sip:user_4@sip.example.org clrtxt:secret ; +sip:user_5@sip.example.org clrtxt:secret ; +sip:user_6@sip.example.org clrtxt:secret ; +sip:user_7@sip.example.org clrtxt:secret ; +sip:user_8@sip.example.org clrtxt:secret ; +sip:user_9@sip.example.org clrtxt:secret ; +sip:user_10@sip.example.org clrtxt:secret ; +sip:user_11@sip.example.org clrtxt:secret ; +sip:user_12@sip.example.org clrtxt:secret ; +sip:user_13@sip.example.org clrtxt:secret ; +sip:user_14@sip.example.org clrtxt:secret ; +sip:user_15@sip.example.org clrtxt:secret ; +sip:user_16@sip.example.org clrtxt:secret ; +sip:user_17@sip.example.org clrtxt:secret ; +sip:user_18@sip.example.org clrtxt:secret ; +sip:user_19@sip.example.org clrtxt:secret ; +sip:user_20@sip.example.org clrtxt:secret ; +sip:user_21@sip.example.org clrtxt:secret ; +sip:user_22@sip.example.org clrtxt:secret ; +sip:user_23@sip.example.org clrtxt:secret ; +sip:user_24@sip.example.org clrtxt:secret ; +sip:user_25@sip.example.org clrtxt:secret ; +sip:user_26@sip.example.org clrtxt:secret ; +sip:user_27@sip.example.org clrtxt:secret ; +sip:user_28@sip.example.org clrtxt:secret ; +sip:user_29@sip.example.org clrtxt:secret ; +sip:user_30@sip.example.org clrtxt:secret ; +sip:user_31@sip.example.org clrtxt:secret ; +sip:user_32@sip.example.org clrtxt:secret ; +sip:user_33@sip.example.org clrtxt:secret ; +sip:user_34@sip.example.org clrtxt:secret ; +sip:user_35@sip.example.org clrtxt:secret ; +sip:user_36@sip.example.org clrtxt:secret ; +sip:user_37@sip.example.org clrtxt:secret ; +sip:user_38@sip.example.org clrtxt:secret ; +sip:user_39@sip.example.org clrtxt:secret ; +sip:user_40@sip.example.org clrtxt:secret ; +sip:user_41@sip.example.org clrtxt:secret ; +sip:user_42@sip.example.org clrtxt:secret ; +sip:user_43@sip.example.org clrtxt:secret ; +sip:user_44@sip.example.org clrtxt:secret ; +sip:user_45@sip.example.org clrtxt:secret ; +sip:user_46@sip.example.org clrtxt:secret ; +sip:user_47@sip.example.org clrtxt:secret ; +sip:user_48@sip.example.org clrtxt:secret ; +sip:user_49@sip.example.org clrtxt:secret ; +sip:user_50@sip.example.org clrtxt:secret ; +sip:user_51@sip.example.org clrtxt:secret ; +sip:user_52@sip.example.org clrtxt:secret ; +sip:user_53@sip.example.org clrtxt:secret ; +sip:user_54@sip.example.org clrtxt:secret ; +sip:user_55@sip.example.org clrtxt:secret ; +sip:user_56@sip.example.org clrtxt:secret ; +sip:user_57@sip.example.org clrtxt:secret ; +sip:user_58@sip.example.org clrtxt:secret ; +sip:user_59@sip.example.org clrtxt:secret ; +sip:user_60@sip.example.org clrtxt:secret ; +sip:user_61@sip.example.org clrtxt:secret ; +sip:user_62@sip.example.org clrtxt:secret ; +sip:user_63@sip.example.org clrtxt:secret ; +sip:user_64@sip.example.org clrtxt:secret ; +sip:user_65@sip.example.org clrtxt:secret ; +sip:user_66@sip.example.org clrtxt:secret ; +sip:user_67@sip.example.org clrtxt:secret ; +sip:user_68@sip.example.org clrtxt:secret ; +sip:user_69@sip.example.org clrtxt:secret ; +sip:user_70@sip.example.org clrtxt:secret ; +sip:user_71@sip.example.org clrtxt:secret ; +sip:user_72@sip.example.org clrtxt:secret ; +sip:user_73@sip.example.org clrtxt:secret ; +sip:user_74@sip.example.org clrtxt:secret ; +sip:user_75@sip.example.org clrtxt:secret ; +sip:user_76@sip.example.org clrtxt:secret ; +sip:user_77@sip.example.org clrtxt:secret ; +sip:user_78@sip.example.org clrtxt:secret ; +sip:user_79@sip.example.org clrtxt:secret ; +sip:user_80@sip.example.org clrtxt:secret ; +sip:user_81@sip.example.org clrtxt:secret ; +sip:user_82@sip.example.org clrtxt:secret ; +sip:user_83@sip.example.org clrtxt:secret ; +sip:user_84@sip.example.org clrtxt:secret ; +sip:user_85@sip.example.org clrtxt:secret ; +sip:user_86@sip.example.org clrtxt:secret ; +sip:user_87@sip.example.org clrtxt:secret ; +sip:user_88@sip.example.org clrtxt:secret ; +sip:user_89@sip.example.org clrtxt:secret ; +sip:user_90@sip.example.org clrtxt:secret ; +sip:user_91@sip.example.org clrtxt:secret ; +sip:user_92@sip.example.org clrtxt:secret ; +sip:user_93@sip.example.org clrtxt:secret ; +sip:user_94@sip.example.org clrtxt:secret ; +sip:user_95@sip.example.org clrtxt:secret ; +sip:user_96@sip.example.org clrtxt:secret ; +sip:user_97@sip.example.org clrtxt:secret ; +sip:user_98@sip.example.org clrtxt:secret ; +sip:user_99@sip.example.org clrtxt:secret ; +sip:user_100@sip.example.org clrtxt:secret ; +sip:user_101@sip.example.org clrtxt:secret ; +sip:user_102@sip.example.org clrtxt:secret ; +sip:user_103@sip.example.org clrtxt:secret ; +sip:user_104@sip.example.org clrtxt:secret ; +sip:user_105@sip.example.org clrtxt:secret ; +sip:user_106@sip.example.org clrtxt:secret ; +sip:user_107@sip.example.org clrtxt:secret ; +sip:user_108@sip.example.org clrtxt:secret ; +sip:user_109@sip.example.org clrtxt:secret ; +sip:user_110@sip.example.org clrtxt:secret ; +sip:user_111@sip.example.org clrtxt:secret ; +sip:user_112@sip.example.org clrtxt:secret ; +sip:user_113@sip.example.org clrtxt:secret ; +sip:user_114@sip.example.org clrtxt:secret ; +sip:user_115@sip.example.org clrtxt:secret ; +sip:user_116@sip.example.org clrtxt:secret ; +sip:user_117@sip.example.org clrtxt:secret ; +sip:user_118@sip.example.org clrtxt:secret ; +sip:user_119@sip.example.org clrtxt:secret ; +sip:user_120@sip.example.org clrtxt:secret ; +sip:user_121@sip.example.org clrtxt:secret ; +sip:user_122@sip.example.org clrtxt:secret ; +sip:user_123@sip.example.org clrtxt:secret ; +sip:user_124@sip.example.org clrtxt:secret ; +sip:user_125@sip.example.org clrtxt:secret ; +sip:user_126@sip.example.org clrtxt:secret ; +sip:user_127@sip.example.org clrtxt:secret ; +sip:user_128@sip.example.org clrtxt:secret ; +sip:user_129@sip.example.org clrtxt:secret ; +sip:user_130@sip.example.org clrtxt:secret ; +sip:user_131@sip.example.org clrtxt:secret ; +sip:user_132@sip.example.org clrtxt:secret ; +sip:user_133@sip.example.org clrtxt:secret ; +sip:user_134@sip.example.org clrtxt:secret ; +sip:user_135@sip.example.org clrtxt:secret ; +sip:user_136@sip.example.org clrtxt:secret ; +sip:user_137@sip.example.org clrtxt:secret ; +sip:user_138@sip.example.org clrtxt:secret ; +sip:user_139@sip.example.org clrtxt:secret ; +sip:user_140@sip.example.org clrtxt:secret ; +sip:user_141@sip.example.org clrtxt:secret ; +sip:user_142@sip.example.org clrtxt:secret ; +sip:user_143@sip.example.org clrtxt:secret ; +sip:user_144@sip.example.org clrtxt:secret ; +sip:user_145@sip.example.org clrtxt:secret ; +sip:user_146@sip.example.org clrtxt:secret ; +sip:user_147@sip.example.org clrtxt:secret ; +sip:user_148@sip.example.org clrtxt:secret ; +sip:user_149@sip.example.org clrtxt:secret ; +sip:user_150@sip.example.org clrtxt:secret ; +sip:user_151@sip.example.org clrtxt:secret ; +sip:user_152@sip.example.org clrtxt:secret ; +sip:user_153@sip.example.org clrtxt:secret ; +sip:user_154@sip.example.org clrtxt:secret ; +sip:user_155@sip.example.org clrtxt:secret ; +sip:user_156@sip.example.org clrtxt:secret ; +sip:user_157@sip.example.org clrtxt:secret ; +sip:user_158@sip.example.org clrtxt:secret ; +sip:user_159@sip.example.org clrtxt:secret ; +sip:user_160@sip.example.org clrtxt:secret ; +sip:user_161@sip.example.org clrtxt:secret ; +sip:user_162@sip.example.org clrtxt:secret ; +sip:user_163@sip.example.org clrtxt:secret ; +sip:user_164@sip.example.org clrtxt:secret ; +sip:user_165@sip.example.org clrtxt:secret ; +sip:user_166@sip.example.org clrtxt:secret ; +sip:user_167@sip.example.org clrtxt:secret ; +sip:user_168@sip.example.org clrtxt:secret ; +sip:user_169@sip.example.org clrtxt:secret ; +sip:user_170@sip.example.org clrtxt:secret ; +sip:user_171@sip.example.org clrtxt:secret ; +sip:user_172@sip.example.org clrtxt:secret ; +sip:user_173@sip.example.org clrtxt:secret ; +sip:user_174@sip.example.org clrtxt:secret ; +sip:user_175@sip.example.org clrtxt:secret ; +sip:user_176@sip.example.org clrtxt:secret ; +sip:user_177@sip.example.org clrtxt:secret ; +sip:user_178@sip.example.org clrtxt:secret ; +sip:user_179@sip.example.org clrtxt:secret ; +sip:user_180@sip.example.org clrtxt:secret ; +sip:user_181@sip.example.org clrtxt:secret ; +sip:user_182@sip.example.org clrtxt:secret ; +sip:user_183@sip.example.org clrtxt:secret ; +sip:user_184@sip.example.org clrtxt:secret ; +sip:user_185@sip.example.org clrtxt:secret ; +sip:user_186@sip.example.org clrtxt:secret ; +sip:user_187@sip.example.org clrtxt:secret ; +sip:user_188@sip.example.org clrtxt:secret ; +sip:user_189@sip.example.org clrtxt:secret ; +sip:user_190@sip.example.org clrtxt:secret ; +sip:user_191@sip.example.org clrtxt:secret ; +sip:user_192@sip.example.org clrtxt:secret ; +sip:user_193@sip.example.org clrtxt:secret ; +sip:user_194@sip.example.org clrtxt:secret ; +sip:user_195@sip.example.org clrtxt:secret ; +sip:user_196@sip.example.org clrtxt:secret ; +sip:user_197@sip.example.org clrtxt:secret ; +sip:user_198@sip.example.org clrtxt:secret ; +sip:user_199@sip.example.org clrtxt:secret ; +sip:user_200@sip.example.org clrtxt:secret ; +sip:user_201@sip.example.org clrtxt:secret ; +sip:user_202@sip.example.org clrtxt:secret ; +sip:user_203@sip.example.org clrtxt:secret ; +sip:user_204@sip.example.org clrtxt:secret ; +sip:user_205@sip.example.org clrtxt:secret ; +sip:user_206@sip.example.org clrtxt:secret ; +sip:user_207@sip.example.org clrtxt:secret ; +sip:user_208@sip.example.org clrtxt:secret ; +sip:user_209@sip.example.org clrtxt:secret ; +sip:user_210@sip.example.org clrtxt:secret ; +sip:user_211@sip.example.org clrtxt:secret ; +sip:user_212@sip.example.org clrtxt:secret ; +sip:user_213@sip.example.org clrtxt:secret ; +sip:user_214@sip.example.org clrtxt:secret ; +sip:user_215@sip.example.org clrtxt:secret ; +sip:user_216@sip.example.org clrtxt:secret ; +sip:user_217@sip.example.org clrtxt:secret ; +sip:user_218@sip.example.org clrtxt:secret ; +sip:user_219@sip.example.org clrtxt:secret ; +sip:user_220@sip.example.org clrtxt:secret ; +sip:user_221@sip.example.org clrtxt:secret ; +sip:user_222@sip.example.org clrtxt:secret ; +sip:user_223@sip.example.org clrtxt:secret ; +sip:user_224@sip.example.org clrtxt:secret ; +sip:user_225@sip.example.org clrtxt:secret ; +sip:user_226@sip.example.org clrtxt:secret ; +sip:user_227@sip.example.org clrtxt:secret ; +sip:user_228@sip.example.org clrtxt:secret ; +sip:user_229@sip.example.org clrtxt:secret ; +sip:user_230@sip.example.org clrtxt:secret ; +sip:user_231@sip.example.org clrtxt:secret ; +sip:user_232@sip.example.org clrtxt:secret ; +sip:user_233@sip.example.org clrtxt:secret ; +sip:user_234@sip.example.org clrtxt:secret ; +sip:user_235@sip.example.org clrtxt:secret ; +sip:user_236@sip.example.org clrtxt:secret ; +sip:user_237@sip.example.org clrtxt:secret ; +sip:user_238@sip.example.org clrtxt:secret ; +sip:user_239@sip.example.org clrtxt:secret ; +sip:user_240@sip.example.org clrtxt:secret ; +sip:user_241@sip.example.org clrtxt:secret ; +sip:user_242@sip.example.org clrtxt:secret ; +sip:user_243@sip.example.org clrtxt:secret ; +sip:user_244@sip.example.org clrtxt:secret ; +sip:user_245@sip.example.org clrtxt:secret ; +sip:user_246@sip.example.org clrtxt:secret ; +sip:user_247@sip.example.org clrtxt:secret ; +sip:user_248@sip.example.org clrtxt:secret ; +sip:user_249@sip.example.org clrtxt:secret ; +sip:user_250@sip.example.org clrtxt:secret ; +sip:user_251@sip.example.org clrtxt:secret ; +sip:user_252@sip.example.org clrtxt:secret ; +sip:user_253@sip.example.org clrtxt:secret ; +sip:user_254@sip.example.org clrtxt:secret ; +sip:user_255@sip.example.org clrtxt:secret ; +sip:user_256@sip.example.org clrtxt:secret ; +sip:user_257@sip.example.org clrtxt:secret ; +sip:user_258@sip.example.org clrtxt:secret ; +sip:user_259@sip.example.org clrtxt:secret ; +sip:user_260@sip.example.org clrtxt:secret ; +sip:user_261@sip.example.org clrtxt:secret ; +sip:user_262@sip.example.org clrtxt:secret ; +sip:user_263@sip.example.org clrtxt:secret ; +sip:user_264@sip.example.org clrtxt:secret ; +sip:user_265@sip.example.org clrtxt:secret ; +sip:user_266@sip.example.org clrtxt:secret ; +sip:user_267@sip.example.org clrtxt:secret ; +sip:user_268@sip.example.org clrtxt:secret ; +sip:user_269@sip.example.org clrtxt:secret ; +sip:user_270@sip.example.org clrtxt:secret ; +sip:user_271@sip.example.org clrtxt:secret ; +sip:user_272@sip.example.org clrtxt:secret ; +sip:user_273@sip.example.org clrtxt:secret ; +sip:user_274@sip.example.org clrtxt:secret ; +sip:user_275@sip.example.org clrtxt:secret ; +sip:user_276@sip.example.org clrtxt:secret ; +sip:user_277@sip.example.org clrtxt:secret ; +sip:user_278@sip.example.org clrtxt:secret ; +sip:user_279@sip.example.org clrtxt:secret ; +sip:user_280@sip.example.org clrtxt:secret ; +sip:user_281@sip.example.org clrtxt:secret ; +sip:user_282@sip.example.org clrtxt:secret ; +sip:user_283@sip.example.org clrtxt:secret ; +sip:user_284@sip.example.org clrtxt:secret ; +sip:user_285@sip.example.org clrtxt:secret ; +sip:user_286@sip.example.org clrtxt:secret ; +sip:user_287@sip.example.org clrtxt:secret ; +sip:user_288@sip.example.org clrtxt:secret ; +sip:user_289@sip.example.org clrtxt:secret ; +sip:user_290@sip.example.org clrtxt:secret ; +sip:user_291@sip.example.org clrtxt:secret ; +sip:user_292@sip.example.org clrtxt:secret ; +sip:user_293@sip.example.org clrtxt:secret ; +sip:user_294@sip.example.org clrtxt:secret ; +sip:user_295@sip.example.org clrtxt:secret ; +sip:user_296@sip.example.org clrtxt:secret ; +sip:user_297@sip.example.org clrtxt:secret ; +sip:user_298@sip.example.org clrtxt:secret ; +sip:user_299@sip.example.org clrtxt:secret ; +sip:user_300@sip.example.org clrtxt:secret ; +sip:user_301@sip.example.org clrtxt:secret ; +sip:user_302@sip.example.org clrtxt:secret ; +sip:user_303@sip.example.org clrtxt:secret ; +sip:user_304@sip.example.org clrtxt:secret ; +sip:user_305@sip.example.org clrtxt:secret ; +sip:user_306@sip.example.org clrtxt:secret ; +sip:user_307@sip.example.org clrtxt:secret ; +sip:user_308@sip.example.org clrtxt:secret ; +sip:user_309@sip.example.org clrtxt:secret ; +sip:user_310@sip.example.org clrtxt:secret ; +sip:user_311@sip.example.org clrtxt:secret ; +sip:user_312@sip.example.org clrtxt:secret ; +sip:user_313@sip.example.org clrtxt:secret ; +sip:user_314@sip.example.org clrtxt:secret ; +sip:user_315@sip.example.org clrtxt:secret ; +sip:user_316@sip.example.org clrtxt:secret ; +sip:user_317@sip.example.org clrtxt:secret ; +sip:user_318@sip.example.org clrtxt:secret ; +sip:user_319@sip.example.org clrtxt:secret ; +sip:user_320@sip.example.org clrtxt:secret ; +sip:user_321@sip.example.org clrtxt:secret ; +sip:user_322@sip.example.org clrtxt:secret ; +sip:user_323@sip.example.org clrtxt:secret ; +sip:user_324@sip.example.org clrtxt:secret ; +sip:user_325@sip.example.org clrtxt:secret ; +sip:user_326@sip.example.org clrtxt:secret ; +sip:user_327@sip.example.org clrtxt:secret ; +sip:user_328@sip.example.org clrtxt:secret ; +sip:user_329@sip.example.org clrtxt:secret ; +sip:user_330@sip.example.org clrtxt:secret ; +sip:user_331@sip.example.org clrtxt:secret ; +sip:user_332@sip.example.org clrtxt:secret ; +sip:user_333@sip.example.org clrtxt:secret ; +sip:user_334@sip.example.org clrtxt:secret ; +sip:user_335@sip.example.org clrtxt:secret ; +sip:user_336@sip.example.org clrtxt:secret ; +sip:user_337@sip.example.org clrtxt:secret ; +sip:user_338@sip.example.org clrtxt:secret ; +sip:user_339@sip.example.org clrtxt:secret ; +sip:user_340@sip.example.org clrtxt:secret ; +sip:user_341@sip.example.org clrtxt:secret ; +sip:user_342@sip.example.org clrtxt:secret ; +sip:user_343@sip.example.org clrtxt:secret ; +sip:user_344@sip.example.org clrtxt:secret ; +sip:user_345@sip.example.org clrtxt:secret ; +sip:user_346@sip.example.org clrtxt:secret ; +sip:user_347@sip.example.org clrtxt:secret ; +sip:user_348@sip.example.org clrtxt:secret ; +sip:user_349@sip.example.org clrtxt:secret ; +sip:user_350@sip.example.org clrtxt:secret ; +sip:user_351@sip.example.org clrtxt:secret ; +sip:user_352@sip.example.org clrtxt:secret ; +sip:user_353@sip.example.org clrtxt:secret ; +sip:user_354@sip.example.org clrtxt:secret ; +sip:user_355@sip.example.org clrtxt:secret ; +sip:user_356@sip.example.org clrtxt:secret ; +sip:user_357@sip.example.org clrtxt:secret ; +sip:user_358@sip.example.org clrtxt:secret ; +sip:user_359@sip.example.org clrtxt:secret ; +sip:user_360@sip.example.org clrtxt:secret ; +sip:user_361@sip.example.org clrtxt:secret ; +sip:user_362@sip.example.org clrtxt:secret ; +sip:user_363@sip.example.org clrtxt:secret ; +sip:user_364@sip.example.org clrtxt:secret ; +sip:user_365@sip.example.org clrtxt:secret ; +sip:user_366@sip.example.org clrtxt:secret ; +sip:user_367@sip.example.org clrtxt:secret ; +sip:user_368@sip.example.org clrtxt:secret ; +sip:user_369@sip.example.org clrtxt:secret ; +sip:user_370@sip.example.org clrtxt:secret ; +sip:user_371@sip.example.org clrtxt:secret ; +sip:user_372@sip.example.org clrtxt:secret ; +sip:user_373@sip.example.org clrtxt:secret ; +sip:user_374@sip.example.org clrtxt:secret ; +sip:user_375@sip.example.org clrtxt:secret ; +sip:user_376@sip.example.org clrtxt:secret ; +sip:user_377@sip.example.org clrtxt:secret ; +sip:user_378@sip.example.org clrtxt:secret ; +sip:user_379@sip.example.org clrtxt:secret ; +sip:user_380@sip.example.org clrtxt:secret ; +sip:user_381@sip.example.org clrtxt:secret ; +sip:user_382@sip.example.org clrtxt:secret ; +sip:user_383@sip.example.org clrtxt:secret ; +sip:user_384@sip.example.org clrtxt:secret ; +sip:user_385@sip.example.org clrtxt:secret ; +sip:user_386@sip.example.org clrtxt:secret ; +sip:user_387@sip.example.org clrtxt:secret ; +sip:user_388@sip.example.org clrtxt:secret ; +sip:user_389@sip.example.org clrtxt:secret ; +sip:user_390@sip.example.org clrtxt:secret ; +sip:user_391@sip.example.org clrtxt:secret ; +sip:user_392@sip.example.org clrtxt:secret ; +sip:user_393@sip.example.org clrtxt:secret ; +sip:user_394@sip.example.org clrtxt:secret ; +sip:user_395@sip.example.org clrtxt:secret ; +sip:user_396@sip.example.org clrtxt:secret ; +sip:user_397@sip.example.org clrtxt:secret ; +sip:user_398@sip.example.org clrtxt:secret ; +sip:user_399@sip.example.org clrtxt:secret ; +sip:user_400@sip.example.org clrtxt:secret ; +sip:user_401@sip.example.org clrtxt:secret ; +sip:user_402@sip.example.org clrtxt:secret ; +sip:user_403@sip.example.org clrtxt:secret ; +sip:user_404@sip.example.org clrtxt:secret ; +sip:user_405@sip.example.org clrtxt:secret ; +sip:user_406@sip.example.org clrtxt:secret ; +sip:user_407@sip.example.org clrtxt:secret ; +sip:user_408@sip.example.org clrtxt:secret ; +sip:user_409@sip.example.org clrtxt:secret ; +sip:user_410@sip.example.org clrtxt:secret ; +sip:user_411@sip.example.org clrtxt:secret ; +sip:user_412@sip.example.org clrtxt:secret ; +sip:user_413@sip.example.org clrtxt:secret ; +sip:user_414@sip.example.org clrtxt:secret ; +sip:user_415@sip.example.org clrtxt:secret ; +sip:user_416@sip.example.org clrtxt:secret ; +sip:user_417@sip.example.org clrtxt:secret ; +sip:user_418@sip.example.org clrtxt:secret ; +sip:user_419@sip.example.org clrtxt:secret ; +sip:user_420@sip.example.org clrtxt:secret ; +sip:user_421@sip.example.org clrtxt:secret ; +sip:user_422@sip.example.org clrtxt:secret ; +sip:user_423@sip.example.org clrtxt:secret ; +sip:user_424@sip.example.org clrtxt:secret ; +sip:user_425@sip.example.org clrtxt:secret ; +sip:user_426@sip.example.org clrtxt:secret ; +sip:user_427@sip.example.org clrtxt:secret ; +sip:user_428@sip.example.org clrtxt:secret ; +sip:user_429@sip.example.org clrtxt:secret ; +sip:user_430@sip.example.org clrtxt:secret ; +sip:user_431@sip.example.org clrtxt:secret ; +sip:user_432@sip.example.org clrtxt:secret ; +sip:user_433@sip.example.org clrtxt:secret ; +sip:user_434@sip.example.org clrtxt:secret ; +sip:user_435@sip.example.org clrtxt:secret ; +sip:user_436@sip.example.org clrtxt:secret ; +sip:user_437@sip.example.org clrtxt:secret ; +sip:user_438@sip.example.org clrtxt:secret ; +sip:user_439@sip.example.org clrtxt:secret ; +sip:user_440@sip.example.org clrtxt:secret ; +sip:user_441@sip.example.org clrtxt:secret ; +sip:user_442@sip.example.org clrtxt:secret ; +sip:user_443@sip.example.org clrtxt:secret ; +sip:user_444@sip.example.org clrtxt:secret ; +sip:user_445@sip.example.org clrtxt:secret ; +sip:user_446@sip.example.org clrtxt:secret ; +sip:user_447@sip.example.org clrtxt:secret ; +sip:user_448@sip.example.org clrtxt:secret ; +sip:user_449@sip.example.org clrtxt:secret ; +sip:user_450@sip.example.org clrtxt:secret ; +sip:user_451@sip.example.org clrtxt:secret ; +sip:user_452@sip.example.org clrtxt:secret ; +sip:user_453@sip.example.org clrtxt:secret ; +sip:user_454@sip.example.org clrtxt:secret ; +sip:user_455@sip.example.org clrtxt:secret ; +sip:user_456@sip.example.org clrtxt:secret ; +sip:user_457@sip.example.org clrtxt:secret ; +sip:user_458@sip.example.org clrtxt:secret ; +sip:user_459@sip.example.org clrtxt:secret ; +sip:user_460@sip.example.org clrtxt:secret ; +sip:user_461@sip.example.org clrtxt:secret ; +sip:user_462@sip.example.org clrtxt:secret ; +sip:user_463@sip.example.org clrtxt:secret ; +sip:user_464@sip.example.org clrtxt:secret ; +sip:user_465@sip.example.org clrtxt:secret ; +sip:user_466@sip.example.org clrtxt:secret ; +sip:user_467@sip.example.org clrtxt:secret ; +sip:user_468@sip.example.org clrtxt:secret ; +sip:user_469@sip.example.org clrtxt:secret ; +sip:user_470@sip.example.org clrtxt:secret ; +sip:user_471@sip.example.org clrtxt:secret ; +sip:user_472@sip.example.org clrtxt:secret ; +sip:user_473@sip.example.org clrtxt:secret ; +sip:user_474@sip.example.org clrtxt:secret ; +sip:user_475@sip.example.org clrtxt:secret ; +sip:user_476@sip.example.org clrtxt:secret ; +sip:user_477@sip.example.org clrtxt:secret ; +sip:user_478@sip.example.org clrtxt:secret ; +sip:user_479@sip.example.org clrtxt:secret ; +sip:user_480@sip.example.org clrtxt:secret ; +sip:user_481@sip.example.org clrtxt:secret ; +sip:user_482@sip.example.org clrtxt:secret ; +sip:user_483@sip.example.org clrtxt:secret ; +sip:user_484@sip.example.org clrtxt:secret ; +sip:user_485@sip.example.org clrtxt:secret ; +sip:user_486@sip.example.org clrtxt:secret ; +sip:user_487@sip.example.org clrtxt:secret ; +sip:user_488@sip.example.org clrtxt:secret ; +sip:user_489@sip.example.org clrtxt:secret ; +sip:user_490@sip.example.org clrtxt:secret ; +sip:user_491@sip.example.org clrtxt:secret ; +sip:user_492@sip.example.org clrtxt:secret ; +sip:user_493@sip.example.org clrtxt:secret ; +sip:user_494@sip.example.org clrtxt:secret ; +sip:user_495@sip.example.org clrtxt:secret ; +sip:user_496@sip.example.org clrtxt:secret ; +sip:user_497@sip.example.org clrtxt:secret ; +sip:user_498@sip.example.org clrtxt:secret ; +sip:user_499@sip.example.org clrtxt:secret ; +sip:user_500@sip.example.org clrtxt:secret ; +sip:user_501@sip.example.org clrtxt:secret ; +sip:user_502@sip.example.org clrtxt:secret ; +sip:user_503@sip.example.org clrtxt:secret ; +sip:user_504@sip.example.org clrtxt:secret ; +sip:user_505@sip.example.org clrtxt:secret ; +sip:user_506@sip.example.org clrtxt:secret ; +sip:user_507@sip.example.org clrtxt:secret ; +sip:user_508@sip.example.org clrtxt:secret ; +sip:user_509@sip.example.org clrtxt:secret ; +sip:user_510@sip.example.org clrtxt:secret ; +sip:user_511@sip.example.org clrtxt:secret ; +sip:user_512@sip.example.org clrtxt:secret ; +sip:user_513@sip.example.org clrtxt:secret ; +sip:user_514@sip.example.org clrtxt:secret ; +sip:user_515@sip.example.org clrtxt:secret ; +sip:user_516@sip.example.org clrtxt:secret ; +sip:user_517@sip.example.org clrtxt:secret ; +sip:user_518@sip.example.org clrtxt:secret ; +sip:user_519@sip.example.org clrtxt:secret ; +sip:user_520@sip.example.org clrtxt:secret ; +sip:user_521@sip.example.org clrtxt:secret ; +sip:user_522@sip.example.org clrtxt:secret ; +sip:user_523@sip.example.org clrtxt:secret ; +sip:user_524@sip.example.org clrtxt:secret ; +sip:user_525@sip.example.org clrtxt:secret ; +sip:user_526@sip.example.org clrtxt:secret ; +sip:user_527@sip.example.org clrtxt:secret ; +sip:user_528@sip.example.org clrtxt:secret ; +sip:user_529@sip.example.org clrtxt:secret ; +sip:user_530@sip.example.org clrtxt:secret ; +sip:user_531@sip.example.org clrtxt:secret ; +sip:user_532@sip.example.org clrtxt:secret ; +sip:user_533@sip.example.org clrtxt:secret ; +sip:user_534@sip.example.org clrtxt:secret ; +sip:user_535@sip.example.org clrtxt:secret ; +sip:user_536@sip.example.org clrtxt:secret ; +sip:user_537@sip.example.org clrtxt:secret ; +sip:user_538@sip.example.org clrtxt:secret ; +sip:user_539@sip.example.org clrtxt:secret ; +sip:user_540@sip.example.org clrtxt:secret ; +sip:user_541@sip.example.org clrtxt:secret ; +sip:user_542@sip.example.org clrtxt:secret ; +sip:user_543@sip.example.org clrtxt:secret ; +sip:user_544@sip.example.org clrtxt:secret ; +sip:user_545@sip.example.org clrtxt:secret ; +sip:user_546@sip.example.org clrtxt:secret ; +sip:user_547@sip.example.org clrtxt:secret ; +sip:user_548@sip.example.org clrtxt:secret ; +sip:user_549@sip.example.org clrtxt:secret ; +sip:user_550@sip.example.org clrtxt:secret ; +sip:user_551@sip.example.org clrtxt:secret ; +sip:user_552@sip.example.org clrtxt:secret ; +sip:user_553@sip.example.org clrtxt:secret ; +sip:user_554@sip.example.org clrtxt:secret ; +sip:user_555@sip.example.org clrtxt:secret ; +sip:user_556@sip.example.org clrtxt:secret ; +sip:user_557@sip.example.org clrtxt:secret ; +sip:user_558@sip.example.org clrtxt:secret ; +sip:user_559@sip.example.org clrtxt:secret ; +sip:user_560@sip.example.org clrtxt:secret ; +sip:user_561@sip.example.org clrtxt:secret ; +sip:user_562@sip.example.org clrtxt:secret ; +sip:user_563@sip.example.org clrtxt:secret ; +sip:user_564@sip.example.org clrtxt:secret ; +sip:user_565@sip.example.org clrtxt:secret ; +sip:user_566@sip.example.org clrtxt:secret ; +sip:user_567@sip.example.org clrtxt:secret ; +sip:user_568@sip.example.org clrtxt:secret ; +sip:user_569@sip.example.org clrtxt:secret ; +sip:user_570@sip.example.org clrtxt:secret ; +sip:user_571@sip.example.org clrtxt:secret ; +sip:user_572@sip.example.org clrtxt:secret ; +sip:user_573@sip.example.org clrtxt:secret ; +sip:user_574@sip.example.org clrtxt:secret ; +sip:user_575@sip.example.org clrtxt:secret ; +sip:user_576@sip.example.org clrtxt:secret ; +sip:user_577@sip.example.org clrtxt:secret ; +sip:user_578@sip.example.org clrtxt:secret ; +sip:user_579@sip.example.org clrtxt:secret ; +sip:user_580@sip.example.org clrtxt:secret ; +sip:user_581@sip.example.org clrtxt:secret ; +sip:user_582@sip.example.org clrtxt:secret ; +sip:user_583@sip.example.org clrtxt:secret ; +sip:user_584@sip.example.org clrtxt:secret ; +sip:user_585@sip.example.org clrtxt:secret ; +sip:user_586@sip.example.org clrtxt:secret ; +sip:user_587@sip.example.org clrtxt:secret ; +sip:user_588@sip.example.org clrtxt:secret ; +sip:user_589@sip.example.org clrtxt:secret ; +sip:user_590@sip.example.org clrtxt:secret ; +sip:user_591@sip.example.org clrtxt:secret ; +sip:user_592@sip.example.org clrtxt:secret ; +sip:user_593@sip.example.org clrtxt:secret ; +sip:user_594@sip.example.org clrtxt:secret ; +sip:user_595@sip.example.org clrtxt:secret ; +sip:user_596@sip.example.org clrtxt:secret ; +sip:user_597@sip.example.org clrtxt:secret ; +sip:user_598@sip.example.org clrtxt:secret ; +sip:user_599@sip.example.org clrtxt:secret ; +sip:user_600@sip.example.org clrtxt:secret ; +sip:user_601@sip.example.org clrtxt:secret ; +sip:user_602@sip.example.org clrtxt:secret ; +sip:user_603@sip.example.org clrtxt:secret ; +sip:user_604@sip.example.org clrtxt:secret ; +sip:user_605@sip.example.org clrtxt:secret ; +sip:user_606@sip.example.org clrtxt:secret ; +sip:user_607@sip.example.org clrtxt:secret ; +sip:user_608@sip.example.org clrtxt:secret ; +sip:user_609@sip.example.org clrtxt:secret ; +sip:user_610@sip.example.org clrtxt:secret ; +sip:user_611@sip.example.org clrtxt:secret ; +sip:user_612@sip.example.org clrtxt:secret ; +sip:user_613@sip.example.org clrtxt:secret ; +sip:user_614@sip.example.org clrtxt:secret ; +sip:user_615@sip.example.org clrtxt:secret ; +sip:user_616@sip.example.org clrtxt:secret ; +sip:user_617@sip.example.org clrtxt:secret ; +sip:user_618@sip.example.org clrtxt:secret ; +sip:user_619@sip.example.org clrtxt:secret ; +sip:user_620@sip.example.org clrtxt:secret ; +sip:user_621@sip.example.org clrtxt:secret ; +sip:user_622@sip.example.org clrtxt:secret ; +sip:user_623@sip.example.org clrtxt:secret ; +sip:user_624@sip.example.org clrtxt:secret ; +sip:user_625@sip.example.org clrtxt:secret ; +sip:user_626@sip.example.org clrtxt:secret ; +sip:user_627@sip.example.org clrtxt:secret ; +sip:user_628@sip.example.org clrtxt:secret ; +sip:user_629@sip.example.org clrtxt:secret ; +sip:user_630@sip.example.org clrtxt:secret ; +sip:user_631@sip.example.org clrtxt:secret ; +sip:user_632@sip.example.org clrtxt:secret ; +sip:user_633@sip.example.org clrtxt:secret ; +sip:user_634@sip.example.org clrtxt:secret ; +sip:user_635@sip.example.org clrtxt:secret ; +sip:user_636@sip.example.org clrtxt:secret ; +sip:user_637@sip.example.org clrtxt:secret ; +sip:user_638@sip.example.org clrtxt:secret ; +sip:user_639@sip.example.org clrtxt:secret ; +sip:user_640@sip.example.org clrtxt:secret ; +sip:user_641@sip.example.org clrtxt:secret ; +sip:user_642@sip.example.org clrtxt:secret ; +sip:user_643@sip.example.org clrtxt:secret ; +sip:user_644@sip.example.org clrtxt:secret ; +sip:user_645@sip.example.org clrtxt:secret ; +sip:user_646@sip.example.org clrtxt:secret ; +sip:user_647@sip.example.org clrtxt:secret ; +sip:user_648@sip.example.org clrtxt:secret ; +sip:user_649@sip.example.org clrtxt:secret ; +sip:user_650@sip.example.org clrtxt:secret ; +sip:user_651@sip.example.org clrtxt:secret ; +sip:user_652@sip.example.org clrtxt:secret ; +sip:user_653@sip.example.org clrtxt:secret ; +sip:user_654@sip.example.org clrtxt:secret ; +sip:user_655@sip.example.org clrtxt:secret ; +sip:user_656@sip.example.org clrtxt:secret ; +sip:user_657@sip.example.org clrtxt:secret ; +sip:user_658@sip.example.org clrtxt:secret ; +sip:user_659@sip.example.org clrtxt:secret ; +sip:user_660@sip.example.org clrtxt:secret ; +sip:user_661@sip.example.org clrtxt:secret ; +sip:user_662@sip.example.org clrtxt:secret ; +sip:user_663@sip.example.org clrtxt:secret ; +sip:user_664@sip.example.org clrtxt:secret ; +sip:user_665@sip.example.org clrtxt:secret ; +sip:user_666@sip.example.org clrtxt:secret ; +sip:user_667@sip.example.org clrtxt:secret ; +sip:user_668@sip.example.org clrtxt:secret ; +sip:user_669@sip.example.org clrtxt:secret ; +sip:user_670@sip.example.org clrtxt:secret ; +sip:user_671@sip.example.org clrtxt:secret ; +sip:user_672@sip.example.org clrtxt:secret ; +sip:user_673@sip.example.org clrtxt:secret ; +sip:user_674@sip.example.org clrtxt:secret ; +sip:user_675@sip.example.org clrtxt:secret ; +sip:user_676@sip.example.org clrtxt:secret ; +sip:user_677@sip.example.org clrtxt:secret ; +sip:user_678@sip.example.org clrtxt:secret ; +sip:user_679@sip.example.org clrtxt:secret ; +sip:user_680@sip.example.org clrtxt:secret ; +sip:user_681@sip.example.org clrtxt:secret ; +sip:user_682@sip.example.org clrtxt:secret ; +sip:user_683@sip.example.org clrtxt:secret ; +sip:user_684@sip.example.org clrtxt:secret ; +sip:user_685@sip.example.org clrtxt:secret ; +sip:user_686@sip.example.org clrtxt:secret ; +sip:user_687@sip.example.org clrtxt:secret ; +sip:user_688@sip.example.org clrtxt:secret ; +sip:user_689@sip.example.org clrtxt:secret ; +sip:user_690@sip.example.org clrtxt:secret ; +sip:user_691@sip.example.org clrtxt:secret ; +sip:user_692@sip.example.org clrtxt:secret ; +sip:user_693@sip.example.org clrtxt:secret ; +sip:user_694@sip.example.org clrtxt:secret ; +sip:user_695@sip.example.org clrtxt:secret ; +sip:user_696@sip.example.org clrtxt:secret ; +sip:user_697@sip.example.org clrtxt:secret ; +sip:user_698@sip.example.org clrtxt:secret ; +sip:user_699@sip.example.org clrtxt:secret ; +sip:user_700@sip.example.org clrtxt:secret ; +sip:user_701@sip.example.org clrtxt:secret ; +sip:user_702@sip.example.org clrtxt:secret ; +sip:user_703@sip.example.org clrtxt:secret ; +sip:user_704@sip.example.org clrtxt:secret ; +sip:user_705@sip.example.org clrtxt:secret ; +sip:user_706@sip.example.org clrtxt:secret ; +sip:user_707@sip.example.org clrtxt:secret ; +sip:user_708@sip.example.org clrtxt:secret ; +sip:user_709@sip.example.org clrtxt:secret ; +sip:user_710@sip.example.org clrtxt:secret ; +sip:user_711@sip.example.org clrtxt:secret ; +sip:user_712@sip.example.org clrtxt:secret ; +sip:user_713@sip.example.org clrtxt:secret ; +sip:user_714@sip.example.org clrtxt:secret ; +sip:user_715@sip.example.org clrtxt:secret ; +sip:user_716@sip.example.org clrtxt:secret ; +sip:user_717@sip.example.org clrtxt:secret ; +sip:user_718@sip.example.org clrtxt:secret ; +sip:user_719@sip.example.org clrtxt:secret ; +sip:user_720@sip.example.org clrtxt:secret ; +sip:user_721@sip.example.org clrtxt:secret ; +sip:user_722@sip.example.org clrtxt:secret ; +sip:user_723@sip.example.org clrtxt:secret ; +sip:user_724@sip.example.org clrtxt:secret ; +sip:user_725@sip.example.org clrtxt:secret ; +sip:user_726@sip.example.org clrtxt:secret ; +sip:user_727@sip.example.org clrtxt:secret ; +sip:user_728@sip.example.org clrtxt:secret ; +sip:user_729@sip.example.org clrtxt:secret ; +sip:user_730@sip.example.org clrtxt:secret ; +sip:user_731@sip.example.org clrtxt:secret ; +sip:user_732@sip.example.org clrtxt:secret ; +sip:user_733@sip.example.org clrtxt:secret ; +sip:user_734@sip.example.org clrtxt:secret ; +sip:user_735@sip.example.org clrtxt:secret ; +sip:user_736@sip.example.org clrtxt:secret ; +sip:user_737@sip.example.org clrtxt:secret ; +sip:user_738@sip.example.org clrtxt:secret ; +sip:user_739@sip.example.org clrtxt:secret ; +sip:user_740@sip.example.org clrtxt:secret ; +sip:user_741@sip.example.org clrtxt:secret ; +sip:user_742@sip.example.org clrtxt:secret ; +sip:user_743@sip.example.org clrtxt:secret ; +sip:user_744@sip.example.org clrtxt:secret ; +sip:user_745@sip.example.org clrtxt:secret ; +sip:user_746@sip.example.org clrtxt:secret ; +sip:user_747@sip.example.org clrtxt:secret ; +sip:user_748@sip.example.org clrtxt:secret ; +sip:user_749@sip.example.org clrtxt:secret ; +sip:user_750@sip.example.org clrtxt:secret ; +sip:user_751@sip.example.org clrtxt:secret ; +sip:user_752@sip.example.org clrtxt:secret ; +sip:user_753@sip.example.org clrtxt:secret ; +sip:user_754@sip.example.org clrtxt:secret ; +sip:user_755@sip.example.org clrtxt:secret ; +sip:user_756@sip.example.org clrtxt:secret ; +sip:user_757@sip.example.org clrtxt:secret ; +sip:user_758@sip.example.org clrtxt:secret ; +sip:user_759@sip.example.org clrtxt:secret ; +sip:user_760@sip.example.org clrtxt:secret ; +sip:user_761@sip.example.org clrtxt:secret ; +sip:user_762@sip.example.org clrtxt:secret ; +sip:user_763@sip.example.org clrtxt:secret ; +sip:user_764@sip.example.org clrtxt:secret ; +sip:user_765@sip.example.org clrtxt:secret ; +sip:user_766@sip.example.org clrtxt:secret ; +sip:user_767@sip.example.org clrtxt:secret ; +sip:user_768@sip.example.org clrtxt:secret ; +sip:user_769@sip.example.org clrtxt:secret ; +sip:user_770@sip.example.org clrtxt:secret ; +sip:user_771@sip.example.org clrtxt:secret ; +sip:user_772@sip.example.org clrtxt:secret ; +sip:user_773@sip.example.org clrtxt:secret ; +sip:user_774@sip.example.org clrtxt:secret ; +sip:user_775@sip.example.org clrtxt:secret ; +sip:user_776@sip.example.org clrtxt:secret ; +sip:user_777@sip.example.org clrtxt:secret ; +sip:user_778@sip.example.org clrtxt:secret ; +sip:user_779@sip.example.org clrtxt:secret ; +sip:user_780@sip.example.org clrtxt:secret ; +sip:user_781@sip.example.org clrtxt:secret ; +sip:user_782@sip.example.org clrtxt:secret ; +sip:user_783@sip.example.org clrtxt:secret ; +sip:user_784@sip.example.org clrtxt:secret ; +sip:user_785@sip.example.org clrtxt:secret ; +sip:user_786@sip.example.org clrtxt:secret ; +sip:user_787@sip.example.org clrtxt:secret ; +sip:user_788@sip.example.org clrtxt:secret ; +sip:user_789@sip.example.org clrtxt:secret ; +sip:user_790@sip.example.org clrtxt:secret ; +sip:user_791@sip.example.org clrtxt:secret ; +sip:user_792@sip.example.org clrtxt:secret ; +sip:user_793@sip.example.org clrtxt:secret ; +sip:user_794@sip.example.org clrtxt:secret ; +sip:user_795@sip.example.org clrtxt:secret ; +sip:user_796@sip.example.org clrtxt:secret ; +sip:user_797@sip.example.org clrtxt:secret ; +sip:user_798@sip.example.org clrtxt:secret ; +sip:user_799@sip.example.org clrtxt:secret ; +sip:user_800@sip.example.org clrtxt:secret ; +sip:user_801@sip.example.org clrtxt:secret ; +sip:user_802@sip.example.org clrtxt:secret ; +sip:user_803@sip.example.org clrtxt:secret ; +sip:user_804@sip.example.org clrtxt:secret ; +sip:user_805@sip.example.org clrtxt:secret ; +sip:user_806@sip.example.org clrtxt:secret ; +sip:user_807@sip.example.org clrtxt:secret ; +sip:user_808@sip.example.org clrtxt:secret ; +sip:user_809@sip.example.org clrtxt:secret ; +sip:user_810@sip.example.org clrtxt:secret ; +sip:user_811@sip.example.org clrtxt:secret ; +sip:user_812@sip.example.org clrtxt:secret ; +sip:user_813@sip.example.org clrtxt:secret ; +sip:user_814@sip.example.org clrtxt:secret ; +sip:user_815@sip.example.org clrtxt:secret ; +sip:user_816@sip.example.org clrtxt:secret ; +sip:user_817@sip.example.org clrtxt:secret ; +sip:user_818@sip.example.org clrtxt:secret ; +sip:user_819@sip.example.org clrtxt:secret ; +sip:user_820@sip.example.org clrtxt:secret ; +sip:user_821@sip.example.org clrtxt:secret ; +sip:user_822@sip.example.org clrtxt:secret ; +sip:user_823@sip.example.org clrtxt:secret ; +sip:user_824@sip.example.org clrtxt:secret ; +sip:user_825@sip.example.org clrtxt:secret ; +sip:user_826@sip.example.org clrtxt:secret ; +sip:user_827@sip.example.org clrtxt:secret ; +sip:user_828@sip.example.org clrtxt:secret ; +sip:user_829@sip.example.org clrtxt:secret ; +sip:user_830@sip.example.org clrtxt:secret ; +sip:user_831@sip.example.org clrtxt:secret ; +sip:user_832@sip.example.org clrtxt:secret ; +sip:user_833@sip.example.org clrtxt:secret ; +sip:user_834@sip.example.org clrtxt:secret ; +sip:user_835@sip.example.org clrtxt:secret ; +sip:user_836@sip.example.org clrtxt:secret ; +sip:user_837@sip.example.org clrtxt:secret ; +sip:user_838@sip.example.org clrtxt:secret ; +sip:user_839@sip.example.org clrtxt:secret ; +sip:user_840@sip.example.org clrtxt:secret ; +sip:user_841@sip.example.org clrtxt:secret ; +sip:user_842@sip.example.org clrtxt:secret ; +sip:user_843@sip.example.org clrtxt:secret ; +sip:user_844@sip.example.org clrtxt:secret ; +sip:user_845@sip.example.org clrtxt:secret ; +sip:user_846@sip.example.org clrtxt:secret ; +sip:user_847@sip.example.org clrtxt:secret ; +sip:user_848@sip.example.org clrtxt:secret ; +sip:user_849@sip.example.org clrtxt:secret ; +sip:user_850@sip.example.org clrtxt:secret ; +sip:user_851@sip.example.org clrtxt:secret ; +sip:user_852@sip.example.org clrtxt:secret ; +sip:user_853@sip.example.org clrtxt:secret ; +sip:user_854@sip.example.org clrtxt:secret ; +sip:user_855@sip.example.org clrtxt:secret ; +sip:user_856@sip.example.org clrtxt:secret ; +sip:user_857@sip.example.org clrtxt:secret ; +sip:user_858@sip.example.org clrtxt:secret ; +sip:user_859@sip.example.org clrtxt:secret ; +sip:user_860@sip.example.org clrtxt:secret ; +sip:user_861@sip.example.org clrtxt:secret ; +sip:user_862@sip.example.org clrtxt:secret ; +sip:user_863@sip.example.org clrtxt:secret ; +sip:user_864@sip.example.org clrtxt:secret ; +sip:user_865@sip.example.org clrtxt:secret ; +sip:user_866@sip.example.org clrtxt:secret ; +sip:user_867@sip.example.org clrtxt:secret ; +sip:user_868@sip.example.org clrtxt:secret ; +sip:user_869@sip.example.org clrtxt:secret ; +sip:user_870@sip.example.org clrtxt:secret ; +sip:user_871@sip.example.org clrtxt:secret ; +sip:user_872@sip.example.org clrtxt:secret ; +sip:user_873@sip.example.org clrtxt:secret ; +sip:user_874@sip.example.org clrtxt:secret ; +sip:user_875@sip.example.org clrtxt:secret ; +sip:user_876@sip.example.org clrtxt:secret ; +sip:user_877@sip.example.org clrtxt:secret ; +sip:user_878@sip.example.org clrtxt:secret ; +sip:user_879@sip.example.org clrtxt:secret ; +sip:user_880@sip.example.org clrtxt:secret ; +sip:user_881@sip.example.org clrtxt:secret ; +sip:user_882@sip.example.org clrtxt:secret ; +sip:user_883@sip.example.org clrtxt:secret ; +sip:user_884@sip.example.org clrtxt:secret ; +sip:user_885@sip.example.org clrtxt:secret ; +sip:user_886@sip.example.org clrtxt:secret ; +sip:user_887@sip.example.org clrtxt:secret ; +sip:user_888@sip.example.org clrtxt:secret ; +sip:user_889@sip.example.org clrtxt:secret ; +sip:user_890@sip.example.org clrtxt:secret ; +sip:user_891@sip.example.org clrtxt:secret ; +sip:user_892@sip.example.org clrtxt:secret ; +sip:user_893@sip.example.org clrtxt:secret ; +sip:user_894@sip.example.org clrtxt:secret ; +sip:user_895@sip.example.org clrtxt:secret ; +sip:user_896@sip.example.org clrtxt:secret ; +sip:user_897@sip.example.org clrtxt:secret ; +sip:user_898@sip.example.org clrtxt:secret ; +sip:user_899@sip.example.org clrtxt:secret ; +sip:user_900@sip.example.org clrtxt:secret ; +sip:user_901@sip.example.org clrtxt:secret ; +sip:user_902@sip.example.org clrtxt:secret ; +sip:user_903@sip.example.org clrtxt:secret ; +sip:user_904@sip.example.org clrtxt:secret ; +sip:user_905@sip.example.org clrtxt:secret ; +sip:user_906@sip.example.org clrtxt:secret ; +sip:user_907@sip.example.org clrtxt:secret ; +sip:user_908@sip.example.org clrtxt:secret ; +sip:user_909@sip.example.org clrtxt:secret ; +sip:user_910@sip.example.org clrtxt:secret ; +sip:user_911@sip.example.org clrtxt:secret ; +sip:user_912@sip.example.org clrtxt:secret ; +sip:user_913@sip.example.org clrtxt:secret ; +sip:user_914@sip.example.org clrtxt:secret ; +sip:user_915@sip.example.org clrtxt:secret ; +sip:user_916@sip.example.org clrtxt:secret ; +sip:user_917@sip.example.org clrtxt:secret ; +sip:user_918@sip.example.org clrtxt:secret ; +sip:user_919@sip.example.org clrtxt:secret ; +sip:user_920@sip.example.org clrtxt:secret ; +sip:user_921@sip.example.org clrtxt:secret ; +sip:user_922@sip.example.org clrtxt:secret ; +sip:user_923@sip.example.org clrtxt:secret ; +sip:user_924@sip.example.org clrtxt:secret ; +sip:user_925@sip.example.org clrtxt:secret ; +sip:user_926@sip.example.org clrtxt:secret ; +sip:user_927@sip.example.org clrtxt:secret ; +sip:user_928@sip.example.org clrtxt:secret ; +sip:user_929@sip.example.org clrtxt:secret ; +sip:user_930@sip.example.org clrtxt:secret ; +sip:user_931@sip.example.org clrtxt:secret ; +sip:user_932@sip.example.org clrtxt:secret ; +sip:user_933@sip.example.org clrtxt:secret ; +sip:user_934@sip.example.org clrtxt:secret ; +sip:user_935@sip.example.org clrtxt:secret ; +sip:user_936@sip.example.org clrtxt:secret ; +sip:user_937@sip.example.org clrtxt:secret ; +sip:user_938@sip.example.org clrtxt:secret ; +sip:user_939@sip.example.org clrtxt:secret ; +sip:user_940@sip.example.org clrtxt:secret ; +sip:user_941@sip.example.org clrtxt:secret ; +sip:user_942@sip.example.org clrtxt:secret ; +sip:user_943@sip.example.org clrtxt:secret ; +sip:user_944@sip.example.org clrtxt:secret ; +sip:user_945@sip.example.org clrtxt:secret ; +sip:user_946@sip.example.org clrtxt:secret ; +sip:user_947@sip.example.org clrtxt:secret ; +sip:user_948@sip.example.org clrtxt:secret ; +sip:user_949@sip.example.org clrtxt:secret ; +sip:user_950@sip.example.org clrtxt:secret ; +sip:user_951@sip.example.org clrtxt:secret ; +sip:user_952@sip.example.org clrtxt:secret ; +sip:user_953@sip.example.org clrtxt:secret ; +sip:user_954@sip.example.org clrtxt:secret ; +sip:user_955@sip.example.org clrtxt:secret ; +sip:user_956@sip.example.org clrtxt:secret ; +sip:user_957@sip.example.org clrtxt:secret ; +sip:user_958@sip.example.org clrtxt:secret ; +sip:user_959@sip.example.org clrtxt:secret ; +sip:user_960@sip.example.org clrtxt:secret ; +sip:user_961@sip.example.org clrtxt:secret ; +sip:user_962@sip.example.org clrtxt:secret ; +sip:user_963@sip.example.org clrtxt:secret ; +sip:user_964@sip.example.org clrtxt:secret ; +sip:user_965@sip.example.org clrtxt:secret ; +sip:user_966@sip.example.org clrtxt:secret ; +sip:user_967@sip.example.org clrtxt:secret ; +sip:user_968@sip.example.org clrtxt:secret ; +sip:user_969@sip.example.org clrtxt:secret ; +sip:user_970@sip.example.org clrtxt:secret ; +sip:user_971@sip.example.org clrtxt:secret ; +sip:user_972@sip.example.org clrtxt:secret ; +sip:user_973@sip.example.org clrtxt:secret ; +sip:user_974@sip.example.org clrtxt:secret ; +sip:user_975@sip.example.org clrtxt:secret ; +sip:user_976@sip.example.org clrtxt:secret ; +sip:user_977@sip.example.org clrtxt:secret ; +sip:user_978@sip.example.org clrtxt:secret ; +sip:user_979@sip.example.org clrtxt:secret ; +sip:user_980@sip.example.org clrtxt:secret ; +sip:user_981@sip.example.org clrtxt:secret ; +sip:user_982@sip.example.org clrtxt:secret ; +sip:user_983@sip.example.org clrtxt:secret ; +sip:user_984@sip.example.org clrtxt:secret ; +sip:user_985@sip.example.org clrtxt:secret ; +sip:user_986@sip.example.org clrtxt:secret ; +sip:user_987@sip.example.org clrtxt:secret ; +sip:user_988@sip.example.org clrtxt:secret ; +sip:user_989@sip.example.org clrtxt:secret ; +sip:user_990@sip.example.org clrtxt:secret ; +sip:user_991@sip.example.org clrtxt:secret ; +sip:user_992@sip.example.org clrtxt:secret ; +sip:user_993@sip.example.org clrtxt:secret ; +sip:user_994@sip.example.org clrtxt:secret ; +sip:user_995@sip.example.org clrtxt:secret ; +sip:user_996@sip.example.org clrtxt:secret ; +sip:user_997@sip.example.org clrtxt:secret ; +sip:user_998@sip.example.org clrtxt:secret ; +sip:user_999@sip.example.org clrtxt:secret ; +sip:user_1000@sip.example.org clrtxt:secret ; +sip:user_1001@sip.example.org clrtxt:secret ; +sip:user_1002@sip.example.org clrtxt:secret ; +sip:user_1003@sip.example.org clrtxt:secret ; +sip:user_1004@sip.example.org clrtxt:secret ; +sip:user_1005@sip.example.org clrtxt:secret ; +sip:user_1006@sip.example.org clrtxt:secret ; +sip:user_1007@sip.example.org clrtxt:secret ; +sip:user_1008@sip.example.org clrtxt:secret ; +sip:user_1009@sip.example.org clrtxt:secret ; +sip:user_1010@sip.example.org clrtxt:secret ; +sip:user_1011@sip.example.org clrtxt:secret ; +sip:user_1012@sip.example.org clrtxt:secret ; +sip:user_1013@sip.example.org clrtxt:secret ; +sip:user_1014@sip.example.org clrtxt:secret ; +sip:user_1015@sip.example.org clrtxt:secret ; +sip:user_1016@sip.example.org clrtxt:secret ; +sip:user_1017@sip.example.org clrtxt:secret ; +sip:user_1018@sip.example.org clrtxt:secret ; +sip:user_1019@sip.example.org clrtxt:secret ; +sip:user_1020@sip.example.org clrtxt:secret ; +sip:user_1021@sip.example.org clrtxt:secret ; +sip:user_1022@sip.example.org clrtxt:secret ; +sip:user_1023@sip.example.org clrtxt:secret ; +sip:user_1024@sip.example.org clrtxt:secret ; +sip:user_1025@sip.example.org clrtxt:secret ; +sip:user_1026@sip.example.org clrtxt:secret ; +sip:user_1027@sip.example.org clrtxt:secret ; +sip:user_1028@sip.example.org clrtxt:secret ; +sip:user_1029@sip.example.org clrtxt:secret ; +sip:user_1030@sip.example.org clrtxt:secret ; +sip:user_1031@sip.example.org clrtxt:secret ; +sip:user_1032@sip.example.org clrtxt:secret ; +sip:user_1033@sip.example.org clrtxt:secret ; +sip:user_1034@sip.example.org clrtxt:secret ; +sip:user_1035@sip.example.org clrtxt:secret ; +sip:user_1036@sip.example.org clrtxt:secret ; +sip:user_1037@sip.example.org clrtxt:secret ; +sip:user_1038@sip.example.org clrtxt:secret ; +sip:user_1039@sip.example.org clrtxt:secret ; +sip:user_1040@sip.example.org clrtxt:secret ; +sip:user_1041@sip.example.org clrtxt:secret ; +sip:user_1042@sip.example.org clrtxt:secret ; +sip:user_1043@sip.example.org clrtxt:secret ; +sip:user_1044@sip.example.org clrtxt:secret ; +sip:user_1045@sip.example.org clrtxt:secret ; +sip:user_1046@sip.example.org clrtxt:secret ; +sip:user_1047@sip.example.org clrtxt:secret ; +sip:user_1048@sip.example.org clrtxt:secret ; +sip:user_1049@sip.example.org clrtxt:secret ; +sip:user_1050@sip.example.org clrtxt:secret ; +sip:user_1051@sip.example.org clrtxt:secret ; +sip:user_1052@sip.example.org clrtxt:secret ; +sip:user_1053@sip.example.org clrtxt:secret ; +sip:user_1054@sip.example.org clrtxt:secret ; +sip:user_1055@sip.example.org clrtxt:secret ; +sip:user_1056@sip.example.org clrtxt:secret ; +sip:user_1057@sip.example.org clrtxt:secret ; +sip:user_1058@sip.example.org clrtxt:secret ; +sip:user_1059@sip.example.org clrtxt:secret ; +sip:user_1060@sip.example.org clrtxt:secret ; +sip:user_1061@sip.example.org clrtxt:secret ; +sip:user_1062@sip.example.org clrtxt:secret ; +sip:user_1063@sip.example.org clrtxt:secret ; +sip:user_1064@sip.example.org clrtxt:secret ; +sip:user_1065@sip.example.org clrtxt:secret ; +sip:user_1066@sip.example.org clrtxt:secret ; +sip:user_1067@sip.example.org clrtxt:secret ; +sip:user_1068@sip.example.org clrtxt:secret ; +sip:user_1069@sip.example.org clrtxt:secret ; +sip:user_1070@sip.example.org clrtxt:secret ; +sip:user_1071@sip.example.org clrtxt:secret ; +sip:user_1072@sip.example.org clrtxt:secret ; +sip:user_1073@sip.example.org clrtxt:secret ; +sip:user_1074@sip.example.org clrtxt:secret ; +sip:user_1075@sip.example.org clrtxt:secret ; +sip:user_1076@sip.example.org clrtxt:secret ; +sip:user_1077@sip.example.org clrtxt:secret ; +sip:user_1078@sip.example.org clrtxt:secret ; +sip:user_1079@sip.example.org clrtxt:secret ; +sip:user_1080@sip.example.org clrtxt:secret ; +sip:user_1081@sip.example.org clrtxt:secret ; +sip:user_1082@sip.example.org clrtxt:secret ; +sip:user_1083@sip.example.org clrtxt:secret ; +sip:user_1084@sip.example.org clrtxt:secret ; +sip:user_1085@sip.example.org clrtxt:secret ; +sip:user_1086@sip.example.org clrtxt:secret ; +sip:user_1087@sip.example.org clrtxt:secret ; +sip:user_1088@sip.example.org clrtxt:secret ; +sip:user_1089@sip.example.org clrtxt:secret ; +sip:user_1090@sip.example.org clrtxt:secret ; +sip:user_1091@sip.example.org clrtxt:secret ; +sip:user_1092@sip.example.org clrtxt:secret ; +sip:user_1093@sip.example.org clrtxt:secret ; +sip:user_1094@sip.example.org clrtxt:secret ; +sip:user_1095@sip.example.org clrtxt:secret ; +sip:user_1096@sip.example.org clrtxt:secret ; +sip:user_1097@sip.example.org clrtxt:secret ; +sip:user_1098@sip.example.org clrtxt:secret ; +sip:user_1099@sip.example.org clrtxt:secret ; +sip:user_1100@sip.example.org clrtxt:secret ; +sip:user_1101@sip.example.org clrtxt:secret ; +sip:user_1102@sip.example.org clrtxt:secret ; +sip:user_1103@sip.example.org clrtxt:secret ; +sip:user_1104@sip.example.org clrtxt:secret ; +sip:user_1105@sip.example.org clrtxt:secret ; +sip:user_1106@sip.example.org clrtxt:secret ; +sip:user_1107@sip.example.org clrtxt:secret ; +sip:user_1108@sip.example.org clrtxt:secret ; +sip:user_1109@sip.example.org clrtxt:secret ; +sip:user_1110@sip.example.org clrtxt:secret ; +sip:user_1111@sip.example.org clrtxt:secret ; +sip:user_1112@sip.example.org clrtxt:secret ; +sip:user_1113@sip.example.org clrtxt:secret ; +sip:user_1114@sip.example.org clrtxt:secret ; +sip:user_1115@sip.example.org clrtxt:secret ; +sip:user_1116@sip.example.org clrtxt:secret ; +sip:user_1117@sip.example.org clrtxt:secret ; +sip:user_1118@sip.example.org clrtxt:secret ; +sip:user_1119@sip.example.org clrtxt:secret ; +sip:user_1120@sip.example.org clrtxt:secret ; +sip:user_1121@sip.example.org clrtxt:secret ; +sip:user_1122@sip.example.org clrtxt:secret ; +sip:user_1123@sip.example.org clrtxt:secret ; +sip:user_1124@sip.example.org clrtxt:secret ; +sip:user_1125@sip.example.org clrtxt:secret ; +sip:user_1126@sip.example.org clrtxt:secret ; +sip:user_1127@sip.example.org clrtxt:secret ; +sip:user_1128@sip.example.org clrtxt:secret ; +sip:user_1129@sip.example.org clrtxt:secret ; +sip:user_1130@sip.example.org clrtxt:secret ; +sip:user_1131@sip.example.org clrtxt:secret ; +sip:user_1132@sip.example.org clrtxt:secret ; +sip:user_1133@sip.example.org clrtxt:secret ; +sip:user_1134@sip.example.org clrtxt:secret ; +sip:user_1135@sip.example.org clrtxt:secret ; +sip:user_1136@sip.example.org clrtxt:secret ; +sip:user_1137@sip.example.org clrtxt:secret ; +sip:user_1138@sip.example.org clrtxt:secret ; +sip:user_1139@sip.example.org clrtxt:secret ; +sip:user_1140@sip.example.org clrtxt:secret ; +sip:user_1141@sip.example.org clrtxt:secret ; +sip:user_1142@sip.example.org clrtxt:secret ; +sip:user_1143@sip.example.org clrtxt:secret ; +sip:user_1144@sip.example.org clrtxt:secret ; +sip:user_1145@sip.example.org clrtxt:secret ; +sip:user_1146@sip.example.org clrtxt:secret ; +sip:user_1147@sip.example.org clrtxt:secret ; +sip:user_1148@sip.example.org clrtxt:secret ; +sip:user_1149@sip.example.org clrtxt:secret ; +sip:user_1150@sip.example.org clrtxt:secret ; +sip:user_1151@sip.example.org clrtxt:secret ; +sip:user_1152@sip.example.org clrtxt:secret ; +sip:user_1153@sip.example.org clrtxt:secret ; +sip:user_1154@sip.example.org clrtxt:secret ; +sip:user_1155@sip.example.org clrtxt:secret ; +sip:user_1156@sip.example.org clrtxt:secret ; +sip:user_1157@sip.example.org clrtxt:secret ; +sip:user_1158@sip.example.org clrtxt:secret ; +sip:user_1159@sip.example.org clrtxt:secret ; +sip:user_1160@sip.example.org clrtxt:secret ; +sip:user_1161@sip.example.org clrtxt:secret ; +sip:user_1162@sip.example.org clrtxt:secret ; +sip:user_1163@sip.example.org clrtxt:secret ; +sip:user_1164@sip.example.org clrtxt:secret ; +sip:user_1165@sip.example.org clrtxt:secret ; +sip:user_1166@sip.example.org clrtxt:secret ; +sip:user_1167@sip.example.org clrtxt:secret ; +sip:user_1168@sip.example.org clrtxt:secret ; +sip:user_1169@sip.example.org clrtxt:secret ; +sip:user_1170@sip.example.org clrtxt:secret ; +sip:user_1171@sip.example.org clrtxt:secret ; +sip:user_1172@sip.example.org clrtxt:secret ; +sip:user_1173@sip.example.org clrtxt:secret ; +sip:user_1174@sip.example.org clrtxt:secret ; +sip:user_1175@sip.example.org clrtxt:secret ; +sip:user_1176@sip.example.org clrtxt:secret ; +sip:user_1177@sip.example.org clrtxt:secret ; +sip:user_1178@sip.example.org clrtxt:secret ; +sip:user_1179@sip.example.org clrtxt:secret ; +sip:user_1180@sip.example.org clrtxt:secret ; +sip:user_1181@sip.example.org clrtxt:secret ; +sip:user_1182@sip.example.org clrtxt:secret ; +sip:user_1183@sip.example.org clrtxt:secret ; +sip:user_1184@sip.example.org clrtxt:secret ; +sip:user_1185@sip.example.org clrtxt:secret ; +sip:user_1186@sip.example.org clrtxt:secret ; +sip:user_1187@sip.example.org clrtxt:secret ; +sip:user_1188@sip.example.org clrtxt:secret ; +sip:user_1189@sip.example.org clrtxt:secret ; +sip:user_1190@sip.example.org clrtxt:secret ; +sip:user_1191@sip.example.org clrtxt:secret ; +sip:user_1192@sip.example.org clrtxt:secret ; +sip:user_1193@sip.example.org clrtxt:secret ; +sip:user_1194@sip.example.org clrtxt:secret ; +sip:user_1195@sip.example.org clrtxt:secret ; +sip:user_1196@sip.example.org clrtxt:secret ; +sip:user_1197@sip.example.org clrtxt:secret ; +sip:user_1198@sip.example.org clrtxt:secret ; +sip:user_1199@sip.example.org clrtxt:secret ; +sip:user_1200@sip.example.org clrtxt:secret ; +sip:user_1201@sip.example.org clrtxt:secret ; +sip:user_1202@sip.example.org clrtxt:secret ; +sip:user_1203@sip.example.org clrtxt:secret ; +sip:user_1204@sip.example.org clrtxt:secret ; +sip:user_1205@sip.example.org clrtxt:secret ; +sip:user_1206@sip.example.org clrtxt:secret ; +sip:user_1207@sip.example.org clrtxt:secret ; +sip:user_1208@sip.example.org clrtxt:secret ; +sip:user_1209@sip.example.org clrtxt:secret ; +sip:user_1210@sip.example.org clrtxt:secret ; +sip:user_1211@sip.example.org clrtxt:secret ; +sip:user_1212@sip.example.org clrtxt:secret ; +sip:user_1213@sip.example.org clrtxt:secret ; +sip:user_1214@sip.example.org clrtxt:secret ; +sip:user_1215@sip.example.org clrtxt:secret ; +sip:user_1216@sip.example.org clrtxt:secret ; +sip:user_1217@sip.example.org clrtxt:secret ; +sip:user_1218@sip.example.org clrtxt:secret ; +sip:user_1219@sip.example.org clrtxt:secret ; +sip:user_1220@sip.example.org clrtxt:secret ; +sip:user_1221@sip.example.org clrtxt:secret ; +sip:user_1222@sip.example.org clrtxt:secret ; +sip:user_1223@sip.example.org clrtxt:secret ; +sip:user_1224@sip.example.org clrtxt:secret ; +sip:user_1225@sip.example.org clrtxt:secret ; +sip:user_1226@sip.example.org clrtxt:secret ; +sip:user_1227@sip.example.org clrtxt:secret ; +sip:user_1228@sip.example.org clrtxt:secret ; +sip:user_1229@sip.example.org clrtxt:secret ; +sip:user_1230@sip.example.org clrtxt:secret ; +sip:user_1231@sip.example.org clrtxt:secret ; +sip:user_1232@sip.example.org clrtxt:secret ; +sip:user_1233@sip.example.org clrtxt:secret ; +sip:user_1234@sip.example.org clrtxt:secret ; +sip:user_1235@sip.example.org clrtxt:secret ; +sip:user_1236@sip.example.org clrtxt:secret ; +sip:user_1237@sip.example.org clrtxt:secret ; +sip:user_1238@sip.example.org clrtxt:secret ; +sip:user_1239@sip.example.org clrtxt:secret ; +sip:user_1240@sip.example.org clrtxt:secret ; +sip:user_1241@sip.example.org clrtxt:secret ; +sip:user_1242@sip.example.org clrtxt:secret ; +sip:user_1243@sip.example.org clrtxt:secret ; +sip:user_1244@sip.example.org clrtxt:secret ; +sip:user_1245@sip.example.org clrtxt:secret ; +sip:user_1246@sip.example.org clrtxt:secret ; +sip:user_1247@sip.example.org clrtxt:secret ; +sip:user_1248@sip.example.org clrtxt:secret ; +sip:user_1249@sip.example.org clrtxt:secret ; +sip:user_1250@sip.example.org clrtxt:secret ; +sip:user_1251@sip.example.org clrtxt:secret ; +sip:user_1252@sip.example.org clrtxt:secret ; +sip:user_1253@sip.example.org clrtxt:secret ; +sip:user_1254@sip.example.org clrtxt:secret ; +sip:user_1255@sip.example.org clrtxt:secret ; +sip:user_1256@sip.example.org clrtxt:secret ; +sip:user_1257@sip.example.org clrtxt:secret ; +sip:user_1258@sip.example.org clrtxt:secret ; +sip:user_1259@sip.example.org clrtxt:secret ; +sip:user_1260@sip.example.org clrtxt:secret ; +sip:user_1261@sip.example.org clrtxt:secret ; +sip:user_1262@sip.example.org clrtxt:secret ; +sip:user_1263@sip.example.org clrtxt:secret ; +sip:user_1264@sip.example.org clrtxt:secret ; +sip:user_1265@sip.example.org clrtxt:secret ; +sip:user_1266@sip.example.org clrtxt:secret ; +sip:user_1267@sip.example.org clrtxt:secret ; +sip:user_1268@sip.example.org clrtxt:secret ; +sip:user_1269@sip.example.org clrtxt:secret ; +sip:user_1270@sip.example.org clrtxt:secret ; +sip:user_1271@sip.example.org clrtxt:secret ; +sip:user_1272@sip.example.org clrtxt:secret ; +sip:user_1273@sip.example.org clrtxt:secret ; +sip:user_1274@sip.example.org clrtxt:secret ; +sip:user_1275@sip.example.org clrtxt:secret ; +sip:user_1276@sip.example.org clrtxt:secret ; +sip:user_1277@sip.example.org clrtxt:secret ; +sip:user_1278@sip.example.org clrtxt:secret ; +sip:user_1279@sip.example.org clrtxt:secret ; +sip:user_1280@sip.example.org clrtxt:secret ; +sip:user_1281@sip.example.org clrtxt:secret ; +sip:user_1282@sip.example.org clrtxt:secret ; +sip:user_1283@sip.example.org clrtxt:secret ; +sip:user_1284@sip.example.org clrtxt:secret ; +sip:user_1285@sip.example.org clrtxt:secret ; +sip:user_1286@sip.example.org clrtxt:secret ; +sip:user_1287@sip.example.org clrtxt:secret ; +sip:user_1288@sip.example.org clrtxt:secret ; +sip:user_1289@sip.example.org clrtxt:secret ; +sip:user_1290@sip.example.org clrtxt:secret ; +sip:user_1291@sip.example.org clrtxt:secret ; +sip:user_1292@sip.example.org clrtxt:secret ; +sip:user_1293@sip.example.org clrtxt:secret ; +sip:user_1294@sip.example.org clrtxt:secret ; +sip:user_1295@sip.example.org clrtxt:secret ; +sip:user_1296@sip.example.org clrtxt:secret ; +sip:user_1297@sip.example.org clrtxt:secret ; +sip:user_1298@sip.example.org clrtxt:secret ; +sip:user_1299@sip.example.org clrtxt:secret ; +sip:user_1300@sip.example.org clrtxt:secret ; +sip:user_1301@sip.example.org clrtxt:secret ; +sip:user_1302@sip.example.org clrtxt:secret ; +sip:user_1303@sip.example.org clrtxt:secret ; +sip:user_1304@sip.example.org clrtxt:secret ; +sip:user_1305@sip.example.org clrtxt:secret ; +sip:user_1306@sip.example.org clrtxt:secret ; +sip:user_1307@sip.example.org clrtxt:secret ; +sip:user_1308@sip.example.org clrtxt:secret ; +sip:user_1309@sip.example.org clrtxt:secret ; +sip:user_1310@sip.example.org clrtxt:secret ; +sip:user_1311@sip.example.org clrtxt:secret ; +sip:user_1312@sip.example.org clrtxt:secret ; +sip:user_1313@sip.example.org clrtxt:secret ; +sip:user_1314@sip.example.org clrtxt:secret ; +sip:user_1315@sip.example.org clrtxt:secret ; +sip:user_1316@sip.example.org clrtxt:secret ; +sip:user_1317@sip.example.org clrtxt:secret ; +sip:user_1318@sip.example.org clrtxt:secret ; +sip:user_1319@sip.example.org clrtxt:secret ; +sip:user_1320@sip.example.org clrtxt:secret ; +sip:user_1321@sip.example.org clrtxt:secret ; +sip:user_1322@sip.example.org clrtxt:secret ; +sip:user_1323@sip.example.org clrtxt:secret ; +sip:user_1324@sip.example.org clrtxt:secret ; +sip:user_1325@sip.example.org clrtxt:secret ; +sip:user_1326@sip.example.org clrtxt:secret ; +sip:user_1327@sip.example.org clrtxt:secret ; +sip:user_1328@sip.example.org clrtxt:secret ; +sip:user_1329@sip.example.org clrtxt:secret ; +sip:user_1330@sip.example.org clrtxt:secret ; +sip:user_1331@sip.example.org clrtxt:secret ; +sip:user_1332@sip.example.org clrtxt:secret ; +sip:user_1333@sip.example.org clrtxt:secret ; +sip:user_1334@sip.example.org clrtxt:secret ; +sip:user_1335@sip.example.org clrtxt:secret ; +sip:user_1336@sip.example.org clrtxt:secret ; +sip:user_1337@sip.example.org clrtxt:secret ; +sip:user_1338@sip.example.org clrtxt:secret ; +sip:user_1339@sip.example.org clrtxt:secret ; +sip:user_1340@sip.example.org clrtxt:secret ; +sip:user_1341@sip.example.org clrtxt:secret ; +sip:user_1342@sip.example.org clrtxt:secret ; +sip:user_1343@sip.example.org clrtxt:secret ; +sip:user_1344@sip.example.org clrtxt:secret ; +sip:user_1345@sip.example.org clrtxt:secret ; +sip:user_1346@sip.example.org clrtxt:secret ; +sip:user_1347@sip.example.org clrtxt:secret ; +sip:user_1348@sip.example.org clrtxt:secret ; +sip:user_1349@sip.example.org clrtxt:secret ; +sip:user_1350@sip.example.org clrtxt:secret ; +sip:user_1351@sip.example.org clrtxt:secret ; +sip:user_1352@sip.example.org clrtxt:secret ; +sip:user_1353@sip.example.org clrtxt:secret ; +sip:user_1354@sip.example.org clrtxt:secret ; +sip:user_1355@sip.example.org clrtxt:secret ; +sip:user_1356@sip.example.org clrtxt:secret ; +sip:user_1357@sip.example.org clrtxt:secret ; +sip:user_1358@sip.example.org clrtxt:secret ; +sip:user_1359@sip.example.org clrtxt:secret ; +sip:user_1360@sip.example.org clrtxt:secret ; +sip:user_1361@sip.example.org clrtxt:secret ; +sip:user_1362@sip.example.org clrtxt:secret ; +sip:user_1363@sip.example.org clrtxt:secret ; +sip:user_1364@sip.example.org clrtxt:secret ; +sip:user_1365@sip.example.org clrtxt:secret ; +sip:user_1366@sip.example.org clrtxt:secret ; +sip:user_1367@sip.example.org clrtxt:secret ; +sip:user_1368@sip.example.org clrtxt:secret ; +sip:user_1369@sip.example.org clrtxt:secret ; +sip:user_1370@sip.example.org clrtxt:secret ; +sip:user_1371@sip.example.org clrtxt:secret ; +sip:user_1372@sip.example.org clrtxt:secret ; +sip:user_1373@sip.example.org clrtxt:secret ; +sip:user_1374@sip.example.org clrtxt:secret ; +sip:user_1375@sip.example.org clrtxt:secret ; +sip:user_1376@sip.example.org clrtxt:secret ; +sip:user_1377@sip.example.org clrtxt:secret ; +sip:user_1378@sip.example.org clrtxt:secret ; +sip:user_1379@sip.example.org clrtxt:secret ; +sip:user_1380@sip.example.org clrtxt:secret ; +sip:user_1381@sip.example.org clrtxt:secret ; +sip:user_1382@sip.example.org clrtxt:secret ; +sip:user_1383@sip.example.org clrtxt:secret ; +sip:user_1384@sip.example.org clrtxt:secret ; +sip:user_1385@sip.example.org clrtxt:secret ; +sip:user_1386@sip.example.org clrtxt:secret ; +sip:user_1387@sip.example.org clrtxt:secret ; +sip:user_1388@sip.example.org clrtxt:secret ; +sip:user_1389@sip.example.org clrtxt:secret ; +sip:user_1390@sip.example.org clrtxt:secret ; +sip:user_1391@sip.example.org clrtxt:secret ; +sip:user_1392@sip.example.org clrtxt:secret ; +sip:user_1393@sip.example.org clrtxt:secret ; +sip:user_1394@sip.example.org clrtxt:secret ; +sip:user_1395@sip.example.org clrtxt:secret ; +sip:user_1396@sip.example.org clrtxt:secret ; +sip:user_1397@sip.example.org clrtxt:secret ; +sip:user_1398@sip.example.org clrtxt:secret ; +sip:user_1399@sip.example.org clrtxt:secret ; +sip:user_1400@sip.example.org clrtxt:secret ; +sip:user_1401@sip.example.org clrtxt:secret ; +sip:user_1402@sip.example.org clrtxt:secret ; +sip:user_1403@sip.example.org clrtxt:secret ; +sip:user_1404@sip.example.org clrtxt:secret ; +sip:user_1405@sip.example.org clrtxt:secret ; +sip:user_1406@sip.example.org clrtxt:secret ; +sip:user_1407@sip.example.org clrtxt:secret ; +sip:user_1408@sip.example.org clrtxt:secret ; +sip:user_1409@sip.example.org clrtxt:secret ; +sip:user_1410@sip.example.org clrtxt:secret ; +sip:user_1411@sip.example.org clrtxt:secret ; +sip:user_1412@sip.example.org clrtxt:secret ; +sip:user_1413@sip.example.org clrtxt:secret ; +sip:user_1414@sip.example.org clrtxt:secret ; +sip:user_1415@sip.example.org clrtxt:secret ; +sip:user_1416@sip.example.org clrtxt:secret ; +sip:user_1417@sip.example.org clrtxt:secret ; +sip:user_1418@sip.example.org clrtxt:secret ; +sip:user_1419@sip.example.org clrtxt:secret ; +sip:user_1420@sip.example.org clrtxt:secret ; +sip:user_1421@sip.example.org clrtxt:secret ; +sip:user_1422@sip.example.org clrtxt:secret ; +sip:user_1423@sip.example.org clrtxt:secret ; +sip:user_1424@sip.example.org clrtxt:secret ; +sip:user_1425@sip.example.org clrtxt:secret ; +sip:user_1426@sip.example.org clrtxt:secret ; +sip:user_1427@sip.example.org clrtxt:secret ; +sip:user_1428@sip.example.org clrtxt:secret ; +sip:user_1429@sip.example.org clrtxt:secret ; +sip:user_1430@sip.example.org clrtxt:secret ; +sip:user_1431@sip.example.org clrtxt:secret ; +sip:user_1432@sip.example.org clrtxt:secret ; +sip:user_1433@sip.example.org clrtxt:secret ; +sip:user_1434@sip.example.org clrtxt:secret ; +sip:user_1435@sip.example.org clrtxt:secret ; +sip:user_1436@sip.example.org clrtxt:secret ; +sip:user_1437@sip.example.org clrtxt:secret ; +sip:user_1438@sip.example.org clrtxt:secret ; +sip:user_1439@sip.example.org clrtxt:secret ; +sip:user_1440@sip.example.org clrtxt:secret ; +sip:user_1441@sip.example.org clrtxt:secret ; +sip:user_1442@sip.example.org clrtxt:secret ; +sip:user_1443@sip.example.org clrtxt:secret ; +sip:user_1444@sip.example.org clrtxt:secret ; +sip:user_1445@sip.example.org clrtxt:secret ; +sip:user_1446@sip.example.org clrtxt:secret ; +sip:user_1447@sip.example.org clrtxt:secret ; +sip:user_1448@sip.example.org clrtxt:secret ; +sip:user_1449@sip.example.org clrtxt:secret ; +sip:user_1450@sip.example.org clrtxt:secret ; +sip:user_1451@sip.example.org clrtxt:secret ; +sip:user_1452@sip.example.org clrtxt:secret ; +sip:user_1453@sip.example.org clrtxt:secret ; +sip:user_1454@sip.example.org clrtxt:secret ; +sip:user_1455@sip.example.org clrtxt:secret ; +sip:user_1456@sip.example.org clrtxt:secret ; +sip:user_1457@sip.example.org clrtxt:secret ; +sip:user_1458@sip.example.org clrtxt:secret ; +sip:user_1459@sip.example.org clrtxt:secret ; +sip:user_1460@sip.example.org clrtxt:secret ; +sip:user_1461@sip.example.org clrtxt:secret ; +sip:user_1462@sip.example.org clrtxt:secret ; +sip:user_1463@sip.example.org clrtxt:secret ; +sip:user_1464@sip.example.org clrtxt:secret ; +sip:user_1465@sip.example.org clrtxt:secret ; +sip:user_1466@sip.example.org clrtxt:secret ; +sip:user_1467@sip.example.org clrtxt:secret ; +sip:user_1468@sip.example.org clrtxt:secret ; +sip:user_1469@sip.example.org clrtxt:secret ; +sip:user_1470@sip.example.org clrtxt:secret ; +sip:user_1471@sip.example.org clrtxt:secret ; +sip:user_1472@sip.example.org clrtxt:secret ; +sip:user_1473@sip.example.org clrtxt:secret ; +sip:user_1474@sip.example.org clrtxt:secret ; +sip:user_1475@sip.example.org clrtxt:secret ; +sip:user_1476@sip.example.org clrtxt:secret ; +sip:user_1477@sip.example.org clrtxt:secret ; +sip:user_1478@sip.example.org clrtxt:secret ; +sip:user_1479@sip.example.org clrtxt:secret ; +sip:user_1480@sip.example.org clrtxt:secret ; +sip:user_1481@sip.example.org clrtxt:secret ; +sip:user_1482@sip.example.org clrtxt:secret ; +sip:user_1483@sip.example.org clrtxt:secret ; +sip:user_1484@sip.example.org clrtxt:secret ; +sip:user_1485@sip.example.org clrtxt:secret ; +sip:user_1486@sip.example.org clrtxt:secret ; +sip:user_1487@sip.example.org clrtxt:secret ; +sip:user_1488@sip.example.org clrtxt:secret ; +sip:user_1489@sip.example.org clrtxt:secret ; +sip:user_1490@sip.example.org clrtxt:secret ; +sip:user_1491@sip.example.org clrtxt:secret ; +sip:user_1492@sip.example.org clrtxt:secret ; +sip:user_1493@sip.example.org clrtxt:secret ; +sip:user_1494@sip.example.org clrtxt:secret ; +sip:user_1495@sip.example.org clrtxt:secret ; +sip:user_1496@sip.example.org clrtxt:secret ; +sip:user_1497@sip.example.org clrtxt:secret ; +sip:user_1498@sip.example.org clrtxt:secret ; +sip:user_1499@sip.example.org clrtxt:secret ; +sip:user_1500@sip.example.org clrtxt:secret ; +sip:user_1501@sip.example.org clrtxt:secret ; +sip:user_1502@sip.example.org clrtxt:secret ; +sip:user_1503@sip.example.org clrtxt:secret ; +sip:user_1504@sip.example.org clrtxt:secret ; +sip:user_1505@sip.example.org clrtxt:secret ; +sip:user_1506@sip.example.org clrtxt:secret ; +sip:user_1507@sip.example.org clrtxt:secret ; +sip:user_1508@sip.example.org clrtxt:secret ; +sip:user_1509@sip.example.org clrtxt:secret ; +sip:user_1510@sip.example.org clrtxt:secret ; +sip:user_1511@sip.example.org clrtxt:secret ; +sip:user_1512@sip.example.org clrtxt:secret ; +sip:user_1513@sip.example.org clrtxt:secret ; +sip:user_1514@sip.example.org clrtxt:secret ; +sip:user_1515@sip.example.org clrtxt:secret ; +sip:user_1516@sip.example.org clrtxt:secret ; +sip:user_1517@sip.example.org clrtxt:secret ; +sip:user_1518@sip.example.org clrtxt:secret ; +sip:user_1519@sip.example.org clrtxt:secret ; +sip:user_1520@sip.example.org clrtxt:secret ; +sip:user_1521@sip.example.org clrtxt:secret ; +sip:user_1522@sip.example.org clrtxt:secret ; +sip:user_1523@sip.example.org clrtxt:secret ; +sip:user_1524@sip.example.org clrtxt:secret ; +sip:user_1525@sip.example.org clrtxt:secret ; +sip:user_1526@sip.example.org clrtxt:secret ; +sip:user_1527@sip.example.org clrtxt:secret ; +sip:user_1528@sip.example.org clrtxt:secret ; +sip:user_1529@sip.example.org clrtxt:secret ; +sip:user_1530@sip.example.org clrtxt:secret ; +sip:user_1531@sip.example.org clrtxt:secret ; +sip:user_1532@sip.example.org clrtxt:secret ; +sip:user_1533@sip.example.org clrtxt:secret ; +sip:user_1534@sip.example.org clrtxt:secret ; +sip:user_1535@sip.example.org clrtxt:secret ; +sip:user_1536@sip.example.org clrtxt:secret ; +sip:user_1537@sip.example.org clrtxt:secret ; +sip:user_1538@sip.example.org clrtxt:secret ; +sip:user_1539@sip.example.org clrtxt:secret ; +sip:user_1540@sip.example.org clrtxt:secret ; +sip:user_1541@sip.example.org clrtxt:secret ; +sip:user_1542@sip.example.org clrtxt:secret ; +sip:user_1543@sip.example.org clrtxt:secret ; +sip:user_1544@sip.example.org clrtxt:secret ; +sip:user_1545@sip.example.org clrtxt:secret ; +sip:user_1546@sip.example.org clrtxt:secret ; +sip:user_1547@sip.example.org clrtxt:secret ; +sip:user_1548@sip.example.org clrtxt:secret ; +sip:user_1549@sip.example.org clrtxt:secret ; +sip:user_1550@sip.example.org clrtxt:secret ; +sip:user_1551@sip.example.org clrtxt:secret ; +sip:user_1552@sip.example.org clrtxt:secret ; +sip:user_1553@sip.example.org clrtxt:secret ; +sip:user_1554@sip.example.org clrtxt:secret ; +sip:user_1555@sip.example.org clrtxt:secret ; +sip:user_1556@sip.example.org clrtxt:secret ; +sip:user_1557@sip.example.org clrtxt:secret ; +sip:user_1558@sip.example.org clrtxt:secret ; +sip:user_1559@sip.example.org clrtxt:secret ; +sip:user_1560@sip.example.org clrtxt:secret ; +sip:user_1561@sip.example.org clrtxt:secret ; +sip:user_1562@sip.example.org clrtxt:secret ; +sip:user_1563@sip.example.org clrtxt:secret ; +sip:user_1564@sip.example.org clrtxt:secret ; +sip:user_1565@sip.example.org clrtxt:secret ; +sip:user_1566@sip.example.org clrtxt:secret ; +sip:user_1567@sip.example.org clrtxt:secret ; +sip:user_1568@sip.example.org clrtxt:secret ; +sip:user_1569@sip.example.org clrtxt:secret ; +sip:user_1570@sip.example.org clrtxt:secret ; +sip:user_1571@sip.example.org clrtxt:secret ; +sip:user_1572@sip.example.org clrtxt:secret ; +sip:user_1573@sip.example.org clrtxt:secret ; +sip:user_1574@sip.example.org clrtxt:secret ; +sip:user_1575@sip.example.org clrtxt:secret ; +sip:user_1576@sip.example.org clrtxt:secret ; +sip:user_1577@sip.example.org clrtxt:secret ; +sip:user_1578@sip.example.org clrtxt:secret ; +sip:user_1579@sip.example.org clrtxt:secret ; +sip:user_1580@sip.example.org clrtxt:secret ; +sip:user_1581@sip.example.org clrtxt:secret ; +sip:user_1582@sip.example.org clrtxt:secret ; +sip:user_1583@sip.example.org clrtxt:secret ; +sip:user_1584@sip.example.org clrtxt:secret ; +sip:user_1585@sip.example.org clrtxt:secret ; +sip:user_1586@sip.example.org clrtxt:secret ; +sip:user_1587@sip.example.org clrtxt:secret ; +sip:user_1588@sip.example.org clrtxt:secret ; +sip:user_1589@sip.example.org clrtxt:secret ; +sip:user_1590@sip.example.org clrtxt:secret ; +sip:user_1591@sip.example.org clrtxt:secret ; +sip:user_1592@sip.example.org clrtxt:secret ; +sip:user_1593@sip.example.org clrtxt:secret ; +sip:user_1594@sip.example.org clrtxt:secret ; +sip:user_1595@sip.example.org clrtxt:secret ; +sip:user_1596@sip.example.org clrtxt:secret ; +sip:user_1597@sip.example.org clrtxt:secret ; +sip:user_1598@sip.example.org clrtxt:secret ; +sip:user_1599@sip.example.org clrtxt:secret ; +sip:user_1600@sip.example.org clrtxt:secret ; +sip:user_1601@sip.example.org clrtxt:secret ; +sip:user_1602@sip.example.org clrtxt:secret ; +sip:user_1603@sip.example.org clrtxt:secret ; +sip:user_1604@sip.example.org clrtxt:secret ; +sip:user_1605@sip.example.org clrtxt:secret ; +sip:user_1606@sip.example.org clrtxt:secret ; +sip:user_1607@sip.example.org clrtxt:secret ; +sip:user_1608@sip.example.org clrtxt:secret ; +sip:user_1609@sip.example.org clrtxt:secret ; +sip:user_1610@sip.example.org clrtxt:secret ; +sip:user_1611@sip.example.org clrtxt:secret ; +sip:user_1612@sip.example.org clrtxt:secret ; +sip:user_1613@sip.example.org clrtxt:secret ; +sip:user_1614@sip.example.org clrtxt:secret ; +sip:user_1615@sip.example.org clrtxt:secret ; +sip:user_1616@sip.example.org clrtxt:secret ; +sip:user_1617@sip.example.org clrtxt:secret ; +sip:user_1618@sip.example.org clrtxt:secret ; +sip:user_1619@sip.example.org clrtxt:secret ; +sip:user_1620@sip.example.org clrtxt:secret ; +sip:user_1621@sip.example.org clrtxt:secret ; +sip:user_1622@sip.example.org clrtxt:secret ; +sip:user_1623@sip.example.org clrtxt:secret ; +sip:user_1624@sip.example.org clrtxt:secret ; +sip:user_1625@sip.example.org clrtxt:secret ; +sip:user_1626@sip.example.org clrtxt:secret ; +sip:user_1627@sip.example.org clrtxt:secret ; +sip:user_1628@sip.example.org clrtxt:secret ; +sip:user_1629@sip.example.org clrtxt:secret ; +sip:user_1630@sip.example.org clrtxt:secret ; +sip:user_1631@sip.example.org clrtxt:secret ; +sip:user_1632@sip.example.org clrtxt:secret ; +sip:user_1633@sip.example.org clrtxt:secret ; +sip:user_1634@sip.example.org clrtxt:secret ; +sip:user_1635@sip.example.org clrtxt:secret ; +sip:user_1636@sip.example.org clrtxt:secret ; +sip:user_1637@sip.example.org clrtxt:secret ; +sip:user_1638@sip.example.org clrtxt:secret ; +sip:user_1639@sip.example.org clrtxt:secret ; +sip:user_1640@sip.example.org clrtxt:secret ; +sip:user_1641@sip.example.org clrtxt:secret ; +sip:user_1642@sip.example.org clrtxt:secret ; +sip:user_1643@sip.example.org clrtxt:secret ; +sip:user_1644@sip.example.org clrtxt:secret ; +sip:user_1645@sip.example.org clrtxt:secret ; +sip:user_1646@sip.example.org clrtxt:secret ; +sip:user_1647@sip.example.org clrtxt:secret ; +sip:user_1648@sip.example.org clrtxt:secret ; +sip:user_1649@sip.example.org clrtxt:secret ; +sip:user_1650@sip.example.org clrtxt:secret ; +sip:user_1651@sip.example.org clrtxt:secret ; +sip:user_1652@sip.example.org clrtxt:secret ; +sip:user_1653@sip.example.org clrtxt:secret ; +sip:user_1654@sip.example.org clrtxt:secret ; +sip:user_1655@sip.example.org clrtxt:secret ; +sip:user_1656@sip.example.org clrtxt:secret ; +sip:user_1657@sip.example.org clrtxt:secret ; +sip:user_1658@sip.example.org clrtxt:secret ; +sip:user_1659@sip.example.org clrtxt:secret ; +sip:user_1660@sip.example.org clrtxt:secret ; +sip:user_1661@sip.example.org clrtxt:secret ; +sip:user_1662@sip.example.org clrtxt:secret ; +sip:user_1663@sip.example.org clrtxt:secret ; +sip:user_1664@sip.example.org clrtxt:secret ; +sip:user_1665@sip.example.org clrtxt:secret ; +sip:user_1666@sip.example.org clrtxt:secret ; +sip:user_1667@sip.example.org clrtxt:secret ; +sip:user_1668@sip.example.org clrtxt:secret ; +sip:user_1669@sip.example.org clrtxt:secret ; +sip:user_1670@sip.example.org clrtxt:secret ; +sip:user_1671@sip.example.org clrtxt:secret ; +sip:user_1672@sip.example.org clrtxt:secret ; +sip:user_1673@sip.example.org clrtxt:secret ; +sip:user_1674@sip.example.org clrtxt:secret ; +sip:user_1675@sip.example.org clrtxt:secret ; +sip:user_1676@sip.example.org clrtxt:secret ; +sip:user_1677@sip.example.org clrtxt:secret ; +sip:user_1678@sip.example.org clrtxt:secret ; +sip:user_1679@sip.example.org clrtxt:secret ; +sip:user_1680@sip.example.org clrtxt:secret ; +sip:user_1681@sip.example.org clrtxt:secret ; +sip:user_1682@sip.example.org clrtxt:secret ; +sip:user_1683@sip.example.org clrtxt:secret ; +sip:user_1684@sip.example.org clrtxt:secret ; +sip:user_1685@sip.example.org clrtxt:secret ; +sip:user_1686@sip.example.org clrtxt:secret ; +sip:user_1687@sip.example.org clrtxt:secret ; +sip:user_1688@sip.example.org clrtxt:secret ; +sip:user_1689@sip.example.org clrtxt:secret ; +sip:user_1690@sip.example.org clrtxt:secret ; +sip:user_1691@sip.example.org clrtxt:secret ; +sip:user_1692@sip.example.org clrtxt:secret ; +sip:user_1693@sip.example.org clrtxt:secret ; +sip:user_1694@sip.example.org clrtxt:secret ; +sip:user_1695@sip.example.org clrtxt:secret ; +sip:user_1696@sip.example.org clrtxt:secret ; +sip:user_1697@sip.example.org clrtxt:secret ; +sip:user_1698@sip.example.org clrtxt:secret ; +sip:user_1699@sip.example.org clrtxt:secret ; +sip:user_1700@sip.example.org clrtxt:secret ; +sip:user_1701@sip.example.org clrtxt:secret ; +sip:user_1702@sip.example.org clrtxt:secret ; +sip:user_1703@sip.example.org clrtxt:secret ; +sip:user_1704@sip.example.org clrtxt:secret ; +sip:user_1705@sip.example.org clrtxt:secret ; +sip:user_1706@sip.example.org clrtxt:secret ; +sip:user_1707@sip.example.org clrtxt:secret ; +sip:user_1708@sip.example.org clrtxt:secret ; +sip:user_1709@sip.example.org clrtxt:secret ; +sip:user_1710@sip.example.org clrtxt:secret ; +sip:user_1711@sip.example.org clrtxt:secret ; +sip:user_1712@sip.example.org clrtxt:secret ; +sip:user_1713@sip.example.org clrtxt:secret ; +sip:user_1714@sip.example.org clrtxt:secret ; +sip:user_1715@sip.example.org clrtxt:secret ; +sip:user_1716@sip.example.org clrtxt:secret ; +sip:user_1717@sip.example.org clrtxt:secret ; +sip:user_1718@sip.example.org clrtxt:secret ; +sip:user_1719@sip.example.org clrtxt:secret ; +sip:user_1720@sip.example.org clrtxt:secret ; +sip:user_1721@sip.example.org clrtxt:secret ; +sip:user_1722@sip.example.org clrtxt:secret ; +sip:user_1723@sip.example.org clrtxt:secret ; +sip:user_1724@sip.example.org clrtxt:secret ; +sip:user_1725@sip.example.org clrtxt:secret ; +sip:user_1726@sip.example.org clrtxt:secret ; +sip:user_1727@sip.example.org clrtxt:secret ; +sip:user_1728@sip.example.org clrtxt:secret ; +sip:user_1729@sip.example.org clrtxt:secret ; +sip:user_1730@sip.example.org clrtxt:secret ; +sip:user_1731@sip.example.org clrtxt:secret ; +sip:user_1732@sip.example.org clrtxt:secret ; +sip:user_1733@sip.example.org clrtxt:secret ; +sip:user_1734@sip.example.org clrtxt:secret ; +sip:user_1735@sip.example.org clrtxt:secret ; +sip:user_1736@sip.example.org clrtxt:secret ; +sip:user_1737@sip.example.org clrtxt:secret ; +sip:user_1738@sip.example.org clrtxt:secret ; +sip:user_1739@sip.example.org clrtxt:secret ; +sip:user_1740@sip.example.org clrtxt:secret ; +sip:user_1741@sip.example.org clrtxt:secret ; +sip:user_1742@sip.example.org clrtxt:secret ; +sip:user_1743@sip.example.org clrtxt:secret ; +sip:user_1744@sip.example.org clrtxt:secret ; +sip:user_1745@sip.example.org clrtxt:secret ; +sip:user_1746@sip.example.org clrtxt:secret ; +sip:user_1747@sip.example.org clrtxt:secret ; +sip:user_1748@sip.example.org clrtxt:secret ; +sip:user_1749@sip.example.org clrtxt:secret ; +sip:user_1750@sip.example.org clrtxt:secret ; +sip:user_1751@sip.example.org clrtxt:secret ; +sip:user_1752@sip.example.org clrtxt:secret ; +sip:user_1753@sip.example.org clrtxt:secret ; +sip:user_1754@sip.example.org clrtxt:secret ; +sip:user_1755@sip.example.org clrtxt:secret ; +sip:user_1756@sip.example.org clrtxt:secret ; +sip:user_1757@sip.example.org clrtxt:secret ; +sip:user_1758@sip.example.org clrtxt:secret ; +sip:user_1759@sip.example.org clrtxt:secret ; +sip:user_1760@sip.example.org clrtxt:secret ; +sip:user_1761@sip.example.org clrtxt:secret ; +sip:user_1762@sip.example.org clrtxt:secret ; +sip:user_1763@sip.example.org clrtxt:secret ; +sip:user_1764@sip.example.org clrtxt:secret ; +sip:user_1765@sip.example.org clrtxt:secret ; +sip:user_1766@sip.example.org clrtxt:secret ; +sip:user_1767@sip.example.org clrtxt:secret ; +sip:user_1768@sip.example.org clrtxt:secret ; +sip:user_1769@sip.example.org clrtxt:secret ; +sip:user_1770@sip.example.org clrtxt:secret ; +sip:user_1771@sip.example.org clrtxt:secret ; +sip:user_1772@sip.example.org clrtxt:secret ; +sip:user_1773@sip.example.org clrtxt:secret ; +sip:user_1774@sip.example.org clrtxt:secret ; +sip:user_1775@sip.example.org clrtxt:secret ; +sip:user_1776@sip.example.org clrtxt:secret ; +sip:user_1777@sip.example.org clrtxt:secret ; +sip:user_1778@sip.example.org clrtxt:secret ; +sip:user_1779@sip.example.org clrtxt:secret ; +sip:user_1780@sip.example.org clrtxt:secret ; +sip:user_1781@sip.example.org clrtxt:secret ; +sip:user_1782@sip.example.org clrtxt:secret ; +sip:user_1783@sip.example.org clrtxt:secret ; +sip:user_1784@sip.example.org clrtxt:secret ; +sip:user_1785@sip.example.org clrtxt:secret ; +sip:user_1786@sip.example.org clrtxt:secret ; +sip:user_1787@sip.example.org clrtxt:secret ; +sip:user_1788@sip.example.org clrtxt:secret ; +sip:user_1789@sip.example.org clrtxt:secret ; +sip:user_1790@sip.example.org clrtxt:secret ; +sip:user_1791@sip.example.org clrtxt:secret ; +sip:user_1792@sip.example.org clrtxt:secret ; +sip:user_1793@sip.example.org clrtxt:secret ; +sip:user_1794@sip.example.org clrtxt:secret ; +sip:user_1795@sip.example.org clrtxt:secret ; +sip:user_1796@sip.example.org clrtxt:secret ; +sip:user_1797@sip.example.org clrtxt:secret ; +sip:user_1798@sip.example.org clrtxt:secret ; +sip:user_1799@sip.example.org clrtxt:secret ; +sip:user_1800@sip.example.org clrtxt:secret ; +sip:user_1801@sip.example.org clrtxt:secret ; +sip:user_1802@sip.example.org clrtxt:secret ; +sip:user_1803@sip.example.org clrtxt:secret ; +sip:user_1804@sip.example.org clrtxt:secret ; +sip:user_1805@sip.example.org clrtxt:secret ; +sip:user_1806@sip.example.org clrtxt:secret ; +sip:user_1807@sip.example.org clrtxt:secret ; +sip:user_1808@sip.example.org clrtxt:secret ; +sip:user_1809@sip.example.org clrtxt:secret ; +sip:user_1810@sip.example.org clrtxt:secret ; +sip:user_1811@sip.example.org clrtxt:secret ; +sip:user_1812@sip.example.org clrtxt:secret ; +sip:user_1813@sip.example.org clrtxt:secret ; +sip:user_1814@sip.example.org clrtxt:secret ; +sip:user_1815@sip.example.org clrtxt:secret ; +sip:user_1816@sip.example.org clrtxt:secret ; +sip:user_1817@sip.example.org clrtxt:secret ; +sip:user_1818@sip.example.org clrtxt:secret ; +sip:user_1819@sip.example.org clrtxt:secret ; +sip:user_1820@sip.example.org clrtxt:secret ; +sip:user_1821@sip.example.org clrtxt:secret ; +sip:user_1822@sip.example.org clrtxt:secret ; +sip:user_1823@sip.example.org clrtxt:secret ; +sip:user_1824@sip.example.org clrtxt:secret ; +sip:user_1825@sip.example.org clrtxt:secret ; +sip:user_1826@sip.example.org clrtxt:secret ; +sip:user_1827@sip.example.org clrtxt:secret ; +sip:user_1828@sip.example.org clrtxt:secret ; +sip:user_1829@sip.example.org clrtxt:secret ; +sip:user_1830@sip.example.org clrtxt:secret ; +sip:user_1831@sip.example.org clrtxt:secret ; +sip:user_1832@sip.example.org clrtxt:secret ; +sip:user_1833@sip.example.org clrtxt:secret ; +sip:user_1834@sip.example.org clrtxt:secret ; +sip:user_1835@sip.example.org clrtxt:secret ; +sip:user_1836@sip.example.org clrtxt:secret ; +sip:user_1837@sip.example.org clrtxt:secret ; +sip:user_1838@sip.example.org clrtxt:secret ; +sip:user_1839@sip.example.org clrtxt:secret ; +sip:user_1840@sip.example.org clrtxt:secret ; +sip:user_1841@sip.example.org clrtxt:secret ; +sip:user_1842@sip.example.org clrtxt:secret ; +sip:user_1843@sip.example.org clrtxt:secret ; +sip:user_1844@sip.example.org clrtxt:secret ; +sip:user_1845@sip.example.org clrtxt:secret ; +sip:user_1846@sip.example.org clrtxt:secret ; +sip:user_1847@sip.example.org clrtxt:secret ; +sip:user_1848@sip.example.org clrtxt:secret ; +sip:user_1849@sip.example.org clrtxt:secret ; +sip:user_1850@sip.example.org clrtxt:secret ; +sip:user_1851@sip.example.org clrtxt:secret ; +sip:user_1852@sip.example.org clrtxt:secret ; +sip:user_1853@sip.example.org clrtxt:secret ; +sip:user_1854@sip.example.org clrtxt:secret ; +sip:user_1855@sip.example.org clrtxt:secret ; +sip:user_1856@sip.example.org clrtxt:secret ; +sip:user_1857@sip.example.org clrtxt:secret ; +sip:user_1858@sip.example.org clrtxt:secret ; +sip:user_1859@sip.example.org clrtxt:secret ; +sip:user_1860@sip.example.org clrtxt:secret ; +sip:user_1861@sip.example.org clrtxt:secret ; +sip:user_1862@sip.example.org clrtxt:secret ; +sip:user_1863@sip.example.org clrtxt:secret ; +sip:user_1864@sip.example.org clrtxt:secret ; +sip:user_1865@sip.example.org clrtxt:secret ; +sip:user_1866@sip.example.org clrtxt:secret ; +sip:user_1867@sip.example.org clrtxt:secret ; +sip:user_1868@sip.example.org clrtxt:secret ; +sip:user_1869@sip.example.org clrtxt:secret ; +sip:user_1870@sip.example.org clrtxt:secret ; +sip:user_1871@sip.example.org clrtxt:secret ; +sip:user_1872@sip.example.org clrtxt:secret ; +sip:user_1873@sip.example.org clrtxt:secret ; +sip:user_1874@sip.example.org clrtxt:secret ; +sip:user_1875@sip.example.org clrtxt:secret ; +sip:user_1876@sip.example.org clrtxt:secret ; +sip:user_1877@sip.example.org clrtxt:secret ; +sip:user_1878@sip.example.org clrtxt:secret ; +sip:user_1879@sip.example.org clrtxt:secret ; +sip:user_1880@sip.example.org clrtxt:secret ; +sip:user_1881@sip.example.org clrtxt:secret ; +sip:user_1882@sip.example.org clrtxt:secret ; +sip:user_1883@sip.example.org clrtxt:secret ; +sip:user_1884@sip.example.org clrtxt:secret ; +sip:user_1885@sip.example.org clrtxt:secret ; +sip:user_1886@sip.example.org clrtxt:secret ; +sip:user_1887@sip.example.org clrtxt:secret ; +sip:user_1888@sip.example.org clrtxt:secret ; +sip:user_1889@sip.example.org clrtxt:secret ; +sip:user_1890@sip.example.org clrtxt:secret ; +sip:user_1891@sip.example.org clrtxt:secret ; +sip:user_1892@sip.example.org clrtxt:secret ; +sip:user_1893@sip.example.org clrtxt:secret ; +sip:user_1894@sip.example.org clrtxt:secret ; +sip:user_1895@sip.example.org clrtxt:secret ; +sip:user_1896@sip.example.org clrtxt:secret ; +sip:user_1897@sip.example.org clrtxt:secret ; +sip:user_1898@sip.example.org clrtxt:secret ; +sip:user_1899@sip.example.org clrtxt:secret ; +sip:user_1900@sip.example.org clrtxt:secret ; +sip:user_1901@sip.example.org clrtxt:secret ; +sip:user_1902@sip.example.org clrtxt:secret ; +sip:user_1903@sip.example.org clrtxt:secret ; +sip:user_1904@sip.example.org clrtxt:secret ; +sip:user_1905@sip.example.org clrtxt:secret ; +sip:user_1906@sip.example.org clrtxt:secret ; +sip:user_1907@sip.example.org clrtxt:secret ; +sip:user_1908@sip.example.org clrtxt:secret ; +sip:user_1909@sip.example.org clrtxt:secret ; +sip:user_1910@sip.example.org clrtxt:secret ; +sip:user_1911@sip.example.org clrtxt:secret ; +sip:user_1912@sip.example.org clrtxt:secret ; +sip:user_1913@sip.example.org clrtxt:secret ; +sip:user_1914@sip.example.org clrtxt:secret ; +sip:user_1915@sip.example.org clrtxt:secret ; +sip:user_1916@sip.example.org clrtxt:secret ; +sip:user_1917@sip.example.org clrtxt:secret ; +sip:user_1918@sip.example.org clrtxt:secret ; +sip:user_1919@sip.example.org clrtxt:secret ; +sip:user_1920@sip.example.org clrtxt:secret ; +sip:user_1921@sip.example.org clrtxt:secret ; +sip:user_1922@sip.example.org clrtxt:secret ; +sip:user_1923@sip.example.org clrtxt:secret ; +sip:user_1924@sip.example.org clrtxt:secret ; +sip:user_1925@sip.example.org clrtxt:secret ; +sip:user_1926@sip.example.org clrtxt:secret ; +sip:user_1927@sip.example.org clrtxt:secret ; +sip:user_1928@sip.example.org clrtxt:secret ; +sip:user_1929@sip.example.org clrtxt:secret ; +sip:user_1930@sip.example.org clrtxt:secret ; +sip:user_1931@sip.example.org clrtxt:secret ; +sip:user_1932@sip.example.org clrtxt:secret ; +sip:user_1933@sip.example.org clrtxt:secret ; +sip:user_1934@sip.example.org clrtxt:secret ; +sip:user_1935@sip.example.org clrtxt:secret ; +sip:user_1936@sip.example.org clrtxt:secret ; +sip:user_1937@sip.example.org clrtxt:secret ; +sip:user_1938@sip.example.org clrtxt:secret ; +sip:user_1939@sip.example.org clrtxt:secret ; +sip:user_1940@sip.example.org clrtxt:secret ; +sip:user_1941@sip.example.org clrtxt:secret ; +sip:user_1942@sip.example.org clrtxt:secret ; +sip:user_1943@sip.example.org clrtxt:secret ; +sip:user_1944@sip.example.org clrtxt:secret ; +sip:user_1945@sip.example.org clrtxt:secret ; +sip:user_1946@sip.example.org clrtxt:secret ; +sip:user_1947@sip.example.org clrtxt:secret ; +sip:user_1948@sip.example.org clrtxt:secret ; +sip:user_1949@sip.example.org clrtxt:secret ; +sip:user_1950@sip.example.org clrtxt:secret ; +sip:user_1951@sip.example.org clrtxt:secret ; +sip:user_1952@sip.example.org clrtxt:secret ; +sip:user_1953@sip.example.org clrtxt:secret ; +sip:user_1954@sip.example.org clrtxt:secret ; +sip:user_1955@sip.example.org clrtxt:secret ; +sip:user_1956@sip.example.org clrtxt:secret ; +sip:user_1957@sip.example.org clrtxt:secret ; +sip:user_1958@sip.example.org clrtxt:secret ; +sip:user_1959@sip.example.org clrtxt:secret ; +sip:user_1960@sip.example.org clrtxt:secret ; +sip:user_1961@sip.example.org clrtxt:secret ; +sip:user_1962@sip.example.org clrtxt:secret ; +sip:user_1963@sip.example.org clrtxt:secret ; +sip:user_1964@sip.example.org clrtxt:secret ; +sip:user_1965@sip.example.org clrtxt:secret ; +sip:user_1966@sip.example.org clrtxt:secret ; +sip:user_1967@sip.example.org clrtxt:secret ; +sip:user_1968@sip.example.org clrtxt:secret ; +sip:user_1969@sip.example.org clrtxt:secret ; +sip:user_1970@sip.example.org clrtxt:secret ; +sip:user_1971@sip.example.org clrtxt:secret ; +sip:user_1972@sip.example.org clrtxt:secret ; +sip:user_1973@sip.example.org clrtxt:secret ; +sip:user_1974@sip.example.org clrtxt:secret ; +sip:user_1975@sip.example.org clrtxt:secret ; +sip:user_1976@sip.example.org clrtxt:secret ; +sip:user_1977@sip.example.org clrtxt:secret ; +sip:user_1978@sip.example.org clrtxt:secret ; +sip:user_1979@sip.example.org clrtxt:secret ; +sip:user_1980@sip.example.org clrtxt:secret ; +sip:user_1981@sip.example.org clrtxt:secret ; +sip:user_1982@sip.example.org clrtxt:secret ; +sip:user_1983@sip.example.org clrtxt:secret ; +sip:user_1984@sip.example.org clrtxt:secret ; +sip:user_1985@sip.example.org clrtxt:secret ; +sip:user_1986@sip.example.org clrtxt:secret ; +sip:user_1987@sip.example.org clrtxt:secret ; +sip:user_1988@sip.example.org clrtxt:secret ; +sip:user_1989@sip.example.org clrtxt:secret ; +sip:user_1990@sip.example.org clrtxt:secret ; +sip:user_1991@sip.example.org clrtxt:secret ; +sip:user_1992@sip.example.org clrtxt:secret ; +sip:user_1993@sip.example.org clrtxt:secret ; +sip:user_1994@sip.example.org clrtxt:secret ; +sip:user_1995@sip.example.org clrtxt:secret ; +sip:user_1996@sip.example.org clrtxt:secret ; +sip:user_1997@sip.example.org clrtxt:secret ; +sip:user_1998@sip.example.org clrtxt:secret ; +sip:user_1999@sip.example.org clrtxt:secret ; +sip:user_2000@sip.example.org clrtxt:secret ; diff --git a/tester/presence_server_tester.c b/tester/presence_server_tester.c index 62bb8a364..db3f0ca07 100644 --- a/tester/presence_server_tester.c +++ b/tester/presence_server_tester.c @@ -788,7 +788,7 @@ static void presence_list_subscribe_network_changes(void) { linphone_core_set_presence_model(pauline->lc, presence); linphone_presence_model_unref(presence); - BC_ASSERT_TRUE(wait_for_until(laure->lc, pauline->lc, &laure->stat.number_of_LinphonePresenceActivityAway, 1, 6000)); + BC_ASSERT_TRUE(wait_for_until(laure->lc, pauline->lc, &laure->stat.number_of_LinphonePresenceActivityAway, 2, 6000)); lf = linphone_friend_list_find_friend_by_uri(linphone_core_get_default_friend_list(laure->lc), pauline_identity); BC_ASSERT_EQUAL(linphone_friend_get_status(lf), LinphoneStatusAway, int, "%d"); @@ -829,6 +829,28 @@ static void long_term_presence_base(const char* addr, bool_t exist, const char* linphone_friend_unref(friend2); linphone_core_manager_destroy(pauline); } + +static void long_term_presence_large_number_of_subs(void) { + int i=0; + LinphoneCoreManager* pauline = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc"); + linphone_core_set_user_agent(pauline->lc, "bypass", NULL); + LinphoneFriendList *friends = linphone_core_create_friend_list(pauline->lc); + linphone_friend_list_set_rls_uri(friends, "sip:rls@sip.example.org"); + for (i = 0 ; i <1000; i++ ) { + char user_id[256]; + snprintf(user_id, sizeof(user_id), "sip:user_%i@sip.example.org",i); + LinphoneFriend* friend2 =linphone_core_create_friend_with_address(pauline->lc, user_id); + linphone_friend_list_add_friend(friends,friend2); + linphone_friend_unref(friend2); + } + linphone_core_add_friend_list(pauline->lc, friends); + linphone_friend_list_unref(friends); + + BC_ASSERT_TRUE(wait_for(pauline->lc,NULL,&pauline->stat.number_of_NotifyPresenceReceived,i)); + + linphone_core_manager_destroy(pauline); +} + static void long_term_presence_existing_friend(void) { // this friend is not online, but is known from flexisip to be registered (see flexisip/userdb.conf), // so we expect to get a report that he is currently not online @@ -1739,6 +1761,7 @@ test_t presence_server_tests[] = { TEST_ONE_TAG("Long term presence with +164 phone, without sip",long_term_presence_with_e164_phone_without_sip, "longterm"), TEST_ONE_TAG("Long term presence with phone, without sip",long_term_presence_with_phone_without_sip, "longterm"), TEST_ONE_TAG("Long term presence with cross references", long_term_presence_with_crossed_references,"longtern"), + TEST_ONE_TAG("Long term presence with large number of subs", long_term_presence_large_number_of_subs,"longtern"), TEST_NO_TAG("Subscriber no longer reachable using server",subscriber_no_longer_reachable), TEST_NO_TAG("Subscribe with late publish", subscribe_with_late_publish), TEST_NO_TAG("Multiple publish aggregation", multiple_publish_aggregation), From ba68bf754c82ce3d53be5c91d93adf0e022774ad Mon Sep 17 00:00:00 2001 From: Jehan Monnier Date: Wed, 28 Mar 2018 15:09:20 +0200 Subject: [PATCH 44/67] improve group chat tests reliability --- tester/group_chat_tester.c | 5 +++-- tester/rcfiles/marie_rc | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/tester/group_chat_tester.c b/tester/group_chat_tester.c index bc9bb7159..9ddfc9329 100644 --- a/tester/group_chat_tester.c +++ b/tester/group_chat_tester.c @@ -2430,6 +2430,7 @@ static void group_chat_room_migrate_from_basic_to_client_fail (void) { BC_ASSERT_EQUAL(linphone_chat_room_get_history_size(paulineCr), 4, int, "%d"); // Activate groupchat on Pauline's side and wait for 5 seconds, the migration should now be done on next message sending + lp_config_set_int(linphone_core_get_config(marie->lc),"misc","basic_to_client_group_chat_room_migration_timer",5); linphone_core_set_linphone_specs(pauline->lc, "groupchat"); linphone_core_set_network_reachable(pauline->lc, FALSE); wait_for_list(coresList, &dummy, 1, 1000); @@ -2508,13 +2509,13 @@ static void group_chat_donot_room_migrate_from_basic_chat_room (void) { linphone_chat_message_send(msg); linphone_chat_message_unref(msg); BC_ASSERT_FALSE(wait_for_list(coresList, &marie->stat.number_of_LinphoneChatRoomStateCreationPending, initialMarieStats.number_of_LinphoneChatRoomStateCreationPending + 1, 10000)); - BC_ASSERT_FALSE(wait_for_list(coresList, &marie->stat.number_of_LinphoneChatRoomStateCreated, initialMarieStats.number_of_LinphoneChatRoomStateCreated + 1, 10000)); + BC_ASSERT_FALSE(wait_for_list(coresList, &marie->stat.number_of_LinphoneChatRoomStateCreated, initialMarieStats.number_of_LinphoneChatRoomStateCreated + 1, 3000)); BC_ASSERT_TRUE(linphone_chat_room_get_capabilities(marieCr) & LinphoneChatRoomCapabilitiesBasic); BC_ASSERT_EQUAL(linphone_chat_room_get_nb_participants(marieCr), 1, int, "%d"); BC_ASSERT_EQUAL(linphone_chat_room_get_history_size(marieCr), 2, int, "%d"); BC_ASSERT_FALSE(wait_for_list(coresList, &pauline->stat.number_of_LinphoneChatRoomStateCreationPending, initialPaulineStats.number_of_LinphoneChatRoomStateCreationPending + 1, 10000)); - BC_ASSERT_FALSE(wait_for_list(coresList, &pauline->stat.number_of_LinphoneChatRoomStateCreated, initialPaulineStats.number_of_LinphoneChatRoomStateCreated + 1, 10000)); + BC_ASSERT_FALSE(wait_for_list(coresList, &pauline->stat.number_of_LinphoneChatRoomStateCreated, initialPaulineStats.number_of_LinphoneChatRoomStateCreated + 1, 3000)); BC_ASSERT_TRUE(linphone_chat_room_get_capabilities(paulineCr) & LinphoneChatRoomCapabilitiesBasic); BC_ASSERT_EQUAL(linphone_chat_room_get_nb_participants(paulineCr), 1, int, "%d"); BC_ASSERT_TRUE(wait_for_list(coresList, &pauline->stat.number_of_LinphoneMessageReceived, initialPaulineStats.number_of_LinphoneMessageReceived + 1, 1000)); diff --git a/tester/rcfiles/marie_rc b/tester/rcfiles/marie_rc index ce4c4877f..7c511b311 100644 --- a/tester/rcfiles/marie_rc +++ b/tester/rcfiles/marie_rc @@ -29,7 +29,7 @@ subscribe=0 [misc] enable_basic_to_client_group_chat_room_migration=1 -basic_to_client_group_chat_room_migration_timer=10 +basic_to_client_group_chat_room_migration_timer=180 [rtp] audio_rtp_port=18070-28000 From cd08c6e2fee6c99ead64dde6783337714c5aedc8 Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Wed, 28 Mar 2018 15:28:49 +0200 Subject: [PATCH 45/67] Added missing doc in header --- include/linphone/api/c-chat-room.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/include/linphone/api/c-chat-room.h b/include/linphone/api/c-chat-room.h index 63aa290cb..41f3c669e 100644 --- a/include/linphone/api/c-chat-room.h +++ b/include/linphone/api/c-chat-room.h @@ -227,6 +227,12 @@ LINPHONE_PUBLIC int linphone_chat_room_get_history_events_size(LinphoneChatRoom */ LINPHONE_PUBLIC LinphoneChatMessage *linphone_chat_room_get_last_message_in_history(LinphoneChatRoom *cr); +/** + * Gets the chat message sent or received in this chat room that matches the message_id + * @param[in] cr The #LinphoneChatRoom object corresponding to the conversation for which the message should be retrieved + * @param[in] message_id The id of the message to find + * @return the #LinphoneChatMessage + */ LINPHONE_PUBLIC LinphoneChatMessage * linphone_chat_room_find_message(LinphoneChatRoom *cr, const char *message_id); /** From 8966c2ca77289366aa6bb93ec5199683d057acd8 Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Wed, 28 Mar 2018 18:20:22 +0200 Subject: [PATCH 46/67] Started method to get participants in given state for given chat message --- include/linphone/api/c-chat-message.h | 2 ++ src/c-wrapper/api/c-chat-message.cpp | 5 +++++ src/chat/chat-message/chat-message-p.h | 1 + src/chat/chat-message/chat-message.cpp | 24 ++++++++++++++++++++++++ src/chat/chat-message/chat-message.h | 1 + src/db/main-db.cpp | 24 ++++++++++++++++++++++++ src/db/main-db.h | 1 + 7 files changed, 58 insertions(+) diff --git a/include/linphone/api/c-chat-message.h b/include/linphone/api/c-chat-message.h index f028464a2..1cd3dbd21 100644 --- a/include/linphone/api/c-chat-message.h +++ b/include/linphone/api/c-chat-message.h @@ -369,6 +369,8 @@ LINPHONE_PUBLIC const char* linphone_chat_message_get_text_content(const Linphon */ LINPHONE_PUBLIC bool_t linphone_chat_message_is_file_transfer_in_progress(LinphoneChatMessage *msg); +LINPHONE_PUBLIC bctbx_list_t *linphone_chat_message_get_participants_in_state (const LinphoneChatMessage *msg, const LinphoneChatMessageState state); + /** * @} */ diff --git a/src/c-wrapper/api/c-chat-message.cpp b/src/c-wrapper/api/c-chat-message.cpp index 902055f9a..a616a9659 100644 --- a/src/c-wrapper/api/c-chat-message.cpp +++ b/src/c-wrapper/api/c-chat-message.cpp @@ -31,6 +31,7 @@ #include "chat/notification/imdn.h" #include "content/content-type.h" #include "content/content.h" +#include "conference/participant.h" // ============================================================================= @@ -246,6 +247,10 @@ bool_t linphone_chat_message_is_file_transfer_in_progress(LinphoneChatMessage *m return L_GET_CPP_PTR_FROM_C_OBJECT(msg)->isFileTransferInProgress(); } +bctbx_list_t *linphone_chat_message_get_participants_in_state (const LinphoneChatMessage *msg, const LinphoneChatMessageState state) { + return L_GET_RESOLVED_C_LIST_FROM_CPP_LIST(L_GET_PRIVATE_FROM_C_OBJECT(msg)->getParticipantsInState((LinphonePrivate::ChatMessage::State) state)); +} + // ============================================================================= // Old listener // ============================================================================= diff --git a/src/chat/chat-message/chat-message-p.h b/src/chat/chat-message/chat-message-p.h index b665e0d1f..4c957ed71 100644 --- a/src/chat/chat-message/chat-message-p.h +++ b/src/chat/chat-message/chat-message-p.h @@ -59,6 +59,7 @@ public: void setDirection (ChatMessage::Direction dir); void setParticipantState (const IdentityAddress &participantAddress, ChatMessage::State newState); + std::list> getParticipantsInState (const ChatMessage::State state) const; void setState (ChatMessage::State newState, bool force = false); void setTime (time_t time); diff --git a/src/chat/chat-message/chat-message.cpp b/src/chat/chat-message/chat-message.cpp index eb2d1f029..0fcde7521 100644 --- a/src/chat/chat-message/chat-message.cpp +++ b/src/chat/chat-message/chat-message.cpp @@ -34,6 +34,7 @@ #include "chat/modifier/encryption-chat-message-modifier.h" #include "chat/modifier/file-transfer-chat-message-modifier.h" #include "chat/modifier/multipart-chat-message-modifier.h" +#include "conference/participant.h" #include "content/file-content.h" #include "content/content.h" #include "core/core.h" @@ -122,6 +123,29 @@ void ChatMessagePrivate::setParticipantState (const IdentityAddress &participant setState(ChatMessage::State::DeliveredToUser); } +list> ChatMessagePrivate::getParticipantsInState (const ChatMessage::State state) const { + L_Q(); + + list> participantsInState; + if (!(q->getChatRoom()->getCapabilities() & AbstractChatRoom::Capabilities::Conference) || !dbKey.isValid()) { + return participantsInState; + } + + unique_ptr &mainDb = q->getChatRoom()->getCore()->getPrivate()->mainDb; + shared_ptr eventLog = mainDb->getEventFromKey(dbKey); + list addressesInState = mainDb->getChatMessageParticipantsInState(eventLog, state); + const list> &participants = q->getChatRoom()->getParticipants(); + for (IdentityAddress addr : addressesInState) { + for (const auto &participant : participants) { + if (participant->getAddress() == addr) { + participantsInState.push_back(participant); + } + } + } + + return participantsInState; +} + void ChatMessagePrivate::setState (ChatMessage::State newState, bool force) { L_Q(); diff --git a/src/chat/chat-message/chat-message.h b/src/chat/chat-message/chat-message.h index 961455882..2b53bda7d 100644 --- a/src/chat/chat-message/chat-message.h +++ b/src/chat/chat-message/chat-message.h @@ -39,6 +39,7 @@ class AbstractChatRoom; class Content; class FileTransferContent; class ChatMessagePrivate; +class Participant; class LINPHONE_PUBLIC ChatMessage : public Object, public CoreAccessor { friend class BasicToClientGroupChatRoom; diff --git a/src/db/main-db.cpp b/src/db/main-db.cpp index 983630099..e6cfd375d 100644 --- a/src/db/main-db.cpp +++ b/src/db/main-db.cpp @@ -1970,6 +1970,30 @@ list MainDb::getChatMessageParticipantStates (const shared_p }; } +list MainDb::getChatMessageParticipantsInState (const shared_ptr &eventLog, const ChatMessage::State state) const { + return L_DB_TRANSACTION { + L_D(); + + const EventLogPrivate *dEventLog = eventLog->getPrivate(); + MainDbKeyPrivate *dEventKey = static_cast(dEventLog->dbKey).getPrivate(); + const long long &eventId = dEventKey->storageId; + + int stateInt = static_cast(state); + list participantsAddresses; + + static const string query = "SELECT sip_address.value" + " FROM sip_address, chat_message_participant" + " WHERE event_id = :eventId AND state = :state" + " AND sip_address.id = chat_message_participant.participant_sip_address_id"; + soci::rowset rows = (d->dbSession.getBackendSession()->prepare << query, soci::use(eventId), soci::use(stateInt)); + for (const auto &row : rows) { + participantsAddresses.push_back(IdentityAddress(row.get(0))); + } + + return participantsAddresses; + }; +} + ChatMessage::State MainDb::getChatMessageParticipantState ( const shared_ptr &eventLog, const IdentityAddress &participantAddress diff --git a/src/db/main-db.h b/src/db/main-db.h index f0f4b6f06..ae46a5e3e 100644 --- a/src/db/main-db.h +++ b/src/db/main-db.h @@ -91,6 +91,7 @@ public: std::list> getUnreadChatMessages (const ChatRoomId &chatRoomId) const; std::list getChatMessageParticipantStates (const std::shared_ptr &eventLog) const; + std::list getChatMessageParticipantsInState (const std::shared_ptr &eventLog, const ChatMessage::State state) const; ChatMessage::State getChatMessageParticipantState ( const std::shared_ptr &eventLog, const IdentityAddress &participantAddress From 04fffe5c9053f2b4ec6f2d79b857d6907f4ce864 Mon Sep 17 00:00:00 2001 From: Simon Morlat Date: Tue, 26 Sep 2017 10:22:08 +0200 Subject: [PATCH 47/67] attempt to fix a crash with LinphoneChatMessage (java) pointing to a null LinphoneChatMessage (C) --- coreapi/linphonecore_jni.cc | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/coreapi/linphonecore_jni.cc b/coreapi/linphonecore_jni.cc index 707d229f3..6b33215d2 100644 --- a/coreapi/linphonecore_jni.cc +++ b/coreapi/linphonecore_jni.cc @@ -4742,7 +4742,7 @@ static void message_state_changed(LinphoneChatMessage* msg, LinphoneChatMessageS } jclass clazz = (jclass) env->GetObjectClass(listener); jmethodID method = env->GetMethodID(clazz, "onLinphoneChatMessageStateChanged","(Lorg/linphone/core/LinphoneChatMessage;Lorg/linphone/core/LinphoneChatMessage$State;)V"); - jobject jmessage = getChatMessage(env, msg); + jobject jmessage = (jobject)linphone_chat_message_get_user_data(msg); /*this returns a global ref that was taken in setListener*/ env->DeleteLocalRef(clazz); LinphoneChatRoom *room = linphone_chat_message_get_chat_room(msg); @@ -4756,6 +4756,10 @@ static void message_state_changed(LinphoneChatMessage* msg, LinphoneChatMessageS } if (jmessage) { env->DeleteLocalRef(jmessage); + //We are going to drop our global ref, as the listener is no longer needed. + //Before, replace it by a weak ref, as other messages. + linphone_chat_message_set_user_data(msg, env->NewWeakGlobalRef(jmessage)); + env->DeleteGlobalRef(jmessage); } } @@ -4840,11 +4844,17 @@ static LinphoneBuffer* file_transfer_send(LinphoneChatMessage *msg, const Linph return buffer; } +/* + * When the listener is set, we must take a global reference to the listener and the message, so that + * we are able to notify the state changes of the message, until it reaches its final state + */ extern "C" void Java_org_linphone_core_LinphoneChatMessageImpl_setListener(JNIEnv* env, jobject thiz, jlong ptr, jobject jlistener) { jobject listener = env->NewGlobalRef(jlistener); LinphoneChatMessage *message = (LinphoneChatMessage *)ptr; LinphoneChatMessageCbs *cbs; + jobject jmessage = env->NewGlobalRef(thiz); + linphone_chat_message_set_user_data(message, jmessage); linphone_chat_message_set_message_state_changed_cb_user_data(message, listener); cbs = linphone_chat_message_get_callbacks(message); linphone_chat_message_cbs_set_msg_state_changed(cbs, message_state_changed); @@ -4961,8 +4971,7 @@ extern "C" void Java_org_linphone_core_LinphoneChatRoomImpl_sendChatMessage(JNIE ,jlong chatroom_ptr ,jobject message ,jlong messagePtr) { - message = env->NewGlobalRef(message); - linphone_chat_message_set_user_data((LinphoneChatMessage*)messagePtr, message); + linphone_chat_room_send_chat_message_2((LinphoneChatRoom*)chatroom_ptr, (LinphoneChatMessage*)messagePtr); } From 4dd2b64c0b64371eabe4519565e5e7332ead7760 Mon Sep 17 00:00:00 2001 From: Simon Morlat Date: Fri, 6 Oct 2017 13:39:47 +0200 Subject: [PATCH 48/67] Fix reference model of LinphoneChatMessage and its listener. --- coreapi/linphonecore_jni.cc | 134 +++++------------- .../org/linphone/core/LinphoneChatRoom.java | 5 - .../linphone/core/LinphoneChatRoomImpl.java | 20 +-- 3 files changed, 40 insertions(+), 119 deletions(-) diff --git a/coreapi/linphonecore_jni.cc b/coreapi/linphonecore_jni.cc index 6b33215d2..a6b01bb58 100644 --- a/coreapi/linphonecore_jni.cc +++ b/coreapi/linphonecore_jni.cc @@ -4462,7 +4462,7 @@ extern "C" jlong Java_org_linphone_core_LinphoneChatRoomImpl_getPeerAddress(JNIE ,jlong ptr) { return (jlong) linphone_chat_room_get_peer_address((LinphoneChatRoom*)ptr); } -extern "C" jlong Java_org_linphone_core_LinphoneChatRoomImpl_createLinphoneChatMessage(JNIEnv* env +extern "C" jobject Java_org_linphone_core_LinphoneChatRoomImpl_createLinphoneChatMessage(JNIEnv* env ,jobject thiz ,jlong ptr ,jstring jmessage) { @@ -4470,29 +4470,10 @@ extern "C" jlong Java_org_linphone_core_LinphoneChatRoomImpl_createLinphoneChatM LinphoneChatMessage *chatMessage = linphone_chat_room_create_message((LinphoneChatRoom *)ptr, message); ReleaseStringUTFChars(env, jmessage, message); - return (jlong) chatMessage; + return getChatMessage(env, chatMessage); } -extern "C" jlong Java_org_linphone_core_LinphoneChatRoomImpl_createLinphoneChatMessage2(JNIEnv* env - ,jobject thiz - ,jlong ptr - ,jstring jmessage - ,jstring jurl - ,jint state - ,jlong time - ,jboolean read - ,jboolean incoming) { - const char* message = GetStringUTFChars(env, jmessage); - const char* url = GetStringUTFChars(env, jurl); - LinphoneChatMessage *chatMessage = linphone_chat_room_create_message_2( - (LinphoneChatRoom *)ptr, message, url, (LinphoneChatMessageState)state, - (time_t)time, read, incoming); - ReleaseStringUTFChars(env, jmessage, message); - ReleaseStringUTFChars(env, jurl, url); - - return (jlong) chatMessage; -} extern "C" jint Java_org_linphone_core_LinphoneChatRoomImpl_getHistorySize (JNIEnv* env ,jobject thiz ,jlong ptr) { @@ -4527,7 +4508,7 @@ extern "C" void Java_org_linphone_core_LinphoneChatRoomImpl_markAsRead(JNIEnv* } -extern "C" jlong Java_org_linphone_core_LinphoneChatRoomImpl_createFileTransferMessage(JNIEnv* env, jobject thiz, jlong ptr, jstring jname, jstring jtype, jstring jsubtype, jint data_size) { +extern "C" jobject Java_org_linphone_core_LinphoneChatRoomImpl_createFileTransferMessage(JNIEnv* env, jobject thiz, jlong ptr, jstring jname, jstring jtype, jstring jsubtype, jint data_size) { LinphoneCore *lc = linphone_chat_room_get_core((LinphoneChatRoom*) ptr); LinphoneContent * content = linphone_core_create_content(lc); LinphoneChatMessage *message = NULL; @@ -4548,7 +4529,7 @@ extern "C" jlong Java_org_linphone_core_LinphoneChatRoomImpl_createFileTransferM linphone_content_unref(content); - return (jlong) message; + return getChatMessage(env, message); } extern "C" jboolean Java_org_linphone_core_LinphoneChatRoomImpl_islimeAvailable(JNIEnv *env, jobject thiz, jlong ptr) { @@ -4726,6 +4707,22 @@ extern "C" void Java_org_linphone_core_LinphoneChatMessageImpl_reSend(JNIEnv* e linphone_chat_message_resend_2((LinphoneChatMessage*)ptr); } +static jobject getMessageListener(JNIEnv *env, LinphoneChatMessage *msg){ + jobject listener = (jobject) linphone_chat_message_get_message_state_changed_cb_user_data(msg); + + if (listener == NULL) { + ms_error("message_state_changed() notification without listener"); + return NULL; + } + listener = env->NewLocalRef(listener); //promote the weak ref into a local ref*/ + if (listener == NULL){ + ms_error("message_state_changed() listener is no longer valid"); + linphone_chat_message_set_message_state_changed_cb_user_data(msg, NULL); + return NULL; + } + return listener; +} + static void message_state_changed(LinphoneChatMessage* msg, LinphoneChatMessageState state) { JNIEnv *env = 0; jint result = jvm->AttachCurrentThread(&env,NULL); @@ -4734,33 +4731,19 @@ static void message_state_changed(LinphoneChatMessage* msg, LinphoneChatMessageS return; } - jobject listener = (jobject) linphone_chat_message_get_message_state_changed_cb_user_data(msg); + jobject listener = getMessageListener(env, msg); + if (!listener) return; - if (listener == NULL) { - ms_error("message_state_changed() notification without listener"); - return ; - } jclass clazz = (jclass) env->GetObjectClass(listener); jmethodID method = env->GetMethodID(clazz, "onLinphoneChatMessageStateChanged","(Lorg/linphone/core/LinphoneChatMessage;Lorg/linphone/core/LinphoneChatMessage$State;)V"); - jobject jmessage = (jobject)linphone_chat_message_get_user_data(msg); /*this returns a global ref that was taken in setListener*/ + jobject jmessage = getChatMessage(env, msg); env->DeleteLocalRef(clazz); LinphoneChatRoom *room = linphone_chat_message_get_chat_room(msg); LinphoneCore *lc = linphone_chat_room_get_core(room); LinphoneJavaBindings *ljb = (LinphoneJavaBindings *)linphone_core_get_user_data(lc); env->CallVoidMethod(listener, method, jmessage, env->CallStaticObjectMethod(ljb->chatMessageStateClass, ljb->chatMessageStateFromIntId, (jint)state)); - - if (state == LinphoneChatMessageStateDisplayed) { - env->DeleteGlobalRef(listener); - linphone_chat_message_set_message_state_changed_cb_user_data(msg, NULL); - } - if (jmessage) { - env->DeleteLocalRef(jmessage); - //We are going to drop our global ref, as the listener is no longer needed. - //Before, replace it by a weak ref, as other messages. - linphone_chat_message_set_user_data(msg, env->NewWeakGlobalRef(jmessage)); - env->DeleteGlobalRef(jmessage); - } + env->DeleteLocalRef(listener); } static void file_transfer_progress_indication(LinphoneChatMessage *msg, const LinphoneContent* content, size_t offset, size_t total) { @@ -4771,7 +4754,8 @@ static void file_transfer_progress_indication(LinphoneChatMessage *msg, const Li return; } - jobject listener = (jobject) linphone_chat_message_get_message_state_changed_cb_user_data(msg); + jobject listener = getMessageListener(env, msg); + if (!listener) return; jclass clazz = (jclass) env->GetObjectClass(listener); jmethodID method = env->GetMethodID(clazz, "onLinphoneChatMessageFileTransferProgressChanged", "(Lorg/linphone/core/LinphoneChatMessage;Lorg/linphone/core/LinphoneContent;II)V"); env->DeleteLocalRef(clazz); @@ -4794,7 +4778,8 @@ static void file_transfer_recv(LinphoneChatMessage *msg, const LinphoneContent* return; } - jobject listener = (jobject) linphone_chat_message_get_message_state_changed_cb_user_data(msg); + jobject listener = getMessageListener(env, msg); + if (!listener) return; jclass clazz = (jclass) env->GetObjectClass(listener); jmethodID method = env->GetMethodID(clazz, "onLinphoneChatMessageFileTransferReceived", "(Lorg/linphone/core/LinphoneChatMessage;Lorg/linphone/core/LinphoneContent;Lorg/linphone/core/LinphoneBuffer;)V"); env->DeleteLocalRef(clazz); @@ -4823,7 +4808,8 @@ static LinphoneBuffer* file_transfer_send(LinphoneChatMessage *msg, const Linph return buffer; } - jobject listener = (jobject) linphone_chat_message_get_message_state_changed_cb_user_data(msg); + jobject listener = getMessageListener(env, msg); + if (!listener) return NULL; jclass clazz = (jclass) env->GetObjectClass(listener); jmethodID method = env->GetMethodID(clazz, "onLinphoneChatMessageFileTransferSent","(Lorg/linphone/core/LinphoneChatMessage;Lorg/linphone/core/LinphoneContent;IILorg/linphone/core/LinphoneBuffer;)V"); env->DeleteLocalRef(clazz); @@ -4849,13 +4835,10 @@ static LinphoneBuffer* file_transfer_send(LinphoneChatMessage *msg, const Linph * we are able to notify the state changes of the message, until it reaches its final state */ extern "C" void Java_org_linphone_core_LinphoneChatMessageImpl_setListener(JNIEnv* env, jobject thiz, jlong ptr, jobject jlistener) { - jobject listener = env->NewGlobalRef(jlistener); LinphoneChatMessage *message = (LinphoneChatMessage *)ptr; LinphoneChatMessageCbs *cbs; - jobject jmessage = env->NewGlobalRef(thiz); - linphone_chat_message_set_user_data(message, jmessage); - linphone_chat_message_set_message_state_changed_cb_user_data(message, listener); + linphone_chat_message_set_message_state_changed_cb_user_data(message, env->NewWeakGlobalRef(jlistener)); cbs = linphone_chat_message_get_callbacks(message); linphone_chat_message_cbs_set_msg_state_changed(cbs, message_state_changed); linphone_chat_message_cbs_set_file_transfer_progress_indication(cbs, file_transfer_progress_indication); @@ -4867,10 +4850,15 @@ extern "C" void Java_org_linphone_core_LinphoneChatMessageImpl_unref(JNIEnv* en ,jobject thiz ,jlong ptr) { jobject wref = (jobject)linphone_chat_message_get_user_data((LinphoneChatMessage*)ptr); + jobject listener_wref = (jobject) linphone_chat_message_get_message_state_changed_cb_user_data((LinphoneChatMessage*)ptr); linphone_chat_message_set_user_data((LinphoneChatMessage*)ptr, NULL); if (wref){ env->DeleteWeakGlobalRef(wref); } + if (listener_wref){ + linphone_chat_message_set_message_state_changed_cb_user_data((LinphoneChatMessage*)ptr, NULL); + env->DeleteWeakGlobalRef(listener_wref); + } linphone_chat_message_unref((LinphoneChatMessage*)ptr); } @@ -4905,34 +4893,6 @@ extern "C" void Java_org_linphone_core_LinphoneChatRoomImpl_sendMessage(JNIEnv* ReleaseStringUTFChars(env, jmessage, message); } -static void chat_room_impl_callback(LinphoneChatMessage* msg, LinphoneChatMessageState state, void* ud) { - JNIEnv *env = 0; - jint result = jvm->AttachCurrentThread(&env,NULL); - if (result != 0) { - ms_error("cannot attach VM\n"); - return; - } - - jobject listener = (jobject) ud; - jclass clazz = (jclass) env->GetObjectClass(listener); - jmethodID method = env->GetMethodID(clazz, "onLinphoneChatMessageStateChanged","(Lorg/linphone/core/LinphoneChatMessage;Lorg/linphone/core/LinphoneChatMessage$State;)V"); - jobject jmessage=(jobject)linphone_chat_message_get_user_data(msg); - - LinphoneChatRoom *room = linphone_chat_message_get_chat_room(msg); - LinphoneCore *lc = linphone_chat_room_get_core(room); - LinphoneJavaBindings *ljb = (LinphoneJavaBindings *)linphone_core_get_user_data(lc); - env->CallVoidMethod( - listener, - method, - jmessage, - env->CallStaticObjectMethod(ljb->chatMessageStateClass,ljb->chatMessageStateFromIntId,(jint)state)); - - if (state == LinphoneChatMessageStateDisplayed ) { - env->DeleteGlobalRef(listener); - env->DeleteGlobalRef(jmessage); - linphone_chat_message_set_user_data(msg,NULL); - } -} extern "C" jobject Java_org_linphone_core_LinphoneChatRoomImpl_getCore(JNIEnv* env ,jobject thiz @@ -4943,28 +4903,6 @@ extern "C" jobject Java_org_linphone_core_LinphoneChatRoomImpl_getCore(JNIEnv* return core; } -extern "C" void Java_org_linphone_core_LinphoneChatRoomImpl_sendMessage2(JNIEnv* env - ,jobject thiz - ,jlong chatroom_ptr - ,jobject message - ,jlong messagePtr - ,jobject jlistener) { - jobject listener = env->NewGlobalRef(jlistener); - LinphoneChatMessage *msg = (LinphoneChatMessage *)messagePtr; - message = env->NewGlobalRef(message); - linphone_chat_message_ref(msg); - linphone_chat_message_set_user_data(msg, message); - - LinphoneChatMessageCbs *cbs; - cbs = linphone_chat_message_get_callbacks(msg); - linphone_chat_message_cbs_set_user_data(cbs, (void *)listener); - linphone_chat_message_cbs_set_msg_state_changed(cbs, message_state_changed); - linphone_chat_message_cbs_set_file_transfer_progress_indication(cbs, file_transfer_progress_indication); - linphone_chat_message_cbs_set_file_transfer_recv(cbs, file_transfer_recv); - linphone_chat_message_cbs_set_file_transfer_send(cbs, file_transfer_send); - - linphone_chat_room_send_chat_message_2((LinphoneChatRoom*)chatroom_ptr, msg); -} extern "C" void Java_org_linphone_core_LinphoneChatRoomImpl_sendChatMessage(JNIEnv* env ,jobject thiz diff --git a/java/common/org/linphone/core/LinphoneChatRoom.java b/java/common/org/linphone/core/LinphoneChatRoom.java index e08378b02..65b635e51 100644 --- a/java/common/org/linphone/core/LinphoneChatRoom.java +++ b/java/common/org/linphone/core/LinphoneChatRoom.java @@ -115,11 +115,6 @@ public interface LinphoneChatRoom { */ void deleteMessage(LinphoneChatMessage message); - /** - * Create a LinphoneChatMessage - * @return LinphoneChatMessage object - */ - LinphoneChatMessage createLinphoneChatMessage(String message, String url, State state, long timestamp, boolean isRead, boolean isIncoming); /** * Returns a back pointer to the core managing the chat room. diff --git a/java/impl/org/linphone/core/LinphoneChatRoomImpl.java b/java/impl/org/linphone/core/LinphoneChatRoomImpl.java index f44c6ecf6..97c919716 100644 --- a/java/impl/org/linphone/core/LinphoneChatRoomImpl.java +++ b/java/impl/org/linphone/core/LinphoneChatRoomImpl.java @@ -25,7 +25,7 @@ import org.linphone.core.LinphoneCall; @SuppressWarnings("deprecation") class LinphoneChatRoomImpl implements LinphoneChatRoom { protected final long nativePtr; - private native long createLinphoneChatMessage(long ptr, String message); + private native Object createLinphoneChatMessage(long ptr, String message); private native long getPeerAddress(long ptr); private native void sendMessage(long ptr, String message); private native void sendMessage2(long ptr, Object msg, long messagePtr, StateListener listener); @@ -39,9 +39,6 @@ class LinphoneChatRoomImpl implements LinphoneChatRoom { private native boolean isRemoteComposing(long ptr); private native void markAsRead(long ptr); private native void deleteMessage(long room, long message); - private native long createLinphoneChatMessage2(long ptr, String message, - String url, int state, long timestamp, boolean isRead, - boolean isIncoming); private native void sendChatMessage(long ptr, Object message, long messagePtr); private native void finalize(long nativePtr); private native boolean islimeAvailable(long nativePtr); @@ -77,7 +74,7 @@ class LinphoneChatRoomImpl implements LinphoneChatRoom { @Override public LinphoneChatMessage createLinphoneChatMessage(String message) { synchronized(getCore()){ - return new LinphoneChatMessageImpl(createLinphoneChatMessage(nativePtr, message)); + return (LinphoneChatMessage)createLinphoneChatMessage(nativePtr, message); } } @@ -144,15 +141,6 @@ class LinphoneChatRoomImpl implements LinphoneChatRoom { } } - @Override - public LinphoneChatMessage createLinphoneChatMessage(String message, - String url, State state, long timestamp, boolean isRead, - boolean isIncoming) { - synchronized(getCore()){ - return new LinphoneChatMessageImpl(createLinphoneChatMessage2( - nativePtr, message, url, state.value(), timestamp / 1000, isRead, isIncoming)); - } - } private native Object getCore(long nativePtr); @Override public synchronized LinphoneCore getCore() { @@ -162,11 +150,11 @@ class LinphoneChatRoomImpl implements LinphoneChatRoom { return (LinphoneChatMessage[]) typesPtr; } - private native long createFileTransferMessage(long ptr, String name, String type, String subtype, int size); + private native Object createFileTransferMessage(long ptr, String name, String type, String subtype, int size); @Override public LinphoneChatMessage createFileTransferMessage(LinphoneContent content) { synchronized(getCore()) { - return new LinphoneChatMessageImpl(createFileTransferMessage(nativePtr, content.getName(), content.getType(), content.getSubtype(), content.getRealSize())); + return (LinphoneChatMessage)createFileTransferMessage(nativePtr, content.getName(), content.getType(), content.getSubtype(), content.getRealSize()); } } @Override From 853f44269423bd4a4f65d95b2a5ca2c9ac4d5c02 Mon Sep 17 00:00:00 2001 From: Benjamin Reis Date: Fri, 30 Mar 2018 16:54:23 +0200 Subject: [PATCH 49/67] fix NULL reason header & missed call when timeout --- src/conference/session/call-session.cpp | 5 +++-- src/sal/call-op.cpp | 6 +++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/conference/session/call-session.cpp b/src/conference/session/call-session.cpp index a11a4ed1d..c2244a569 100644 --- a/src/conference/session/call-session.cpp +++ b/src/conference/session/call-session.cpp @@ -92,7 +92,8 @@ void CallSessionPrivate::setState (CallSession::State newState, const string &me case CallSession::State::Error: switch (linphone_error_info_get_reason(q->getErrorInfo())) { case LinphoneReasonDeclined: - log->status = LinphoneCallDeclined; + if(log->status == LinphoneCallSuccess) // Do not re-change the status of a call if it's already set + log->status = LinphoneCallDeclined; break; case LinphoneReasonNotAnswered: if (log->dir == LinphoneCallIncoming) @@ -470,7 +471,7 @@ void CallSessionPrivate::updatedByRemote () { if (deferUpdate || deferUpdateInternal) { if (state == CallSession::State::UpdatedByRemote && !deferUpdateInternal){ lInfo() << "CallSession [" << q << "]: UpdatedByRemoted was signaled but defered. LinphoneCore expects the application to call linphone_call_accept_update() later"; - } + } } else { if (state == CallSession::State::UpdatedByRemote) q->acceptUpdate(nullptr); diff --git a/src/sal/call-op.cpp b/src/sal/call-op.cpp index 238e6d255..ade2d214b 100644 --- a/src/sal/call-op.cpp +++ b/src/sal/call-op.cpp @@ -1037,7 +1037,7 @@ int SalCallOp::decline(SalReason reason, const char *redirection /*optional*/){ } belle_sip_header_reason_t *SalCallOp::make_reason_header( const SalErrorInfo *info){ - if (info != NULL){ + if (info && info->reason != SalReasonNone) { belle_sip_header_reason_t* reason = BELLE_SIP_HEADER_REASON(belle_sip_header_reason_new()); belle_sip_header_reason_set_text(reason, info->status_string); belle_sip_header_reason_set_protocol(reason,info->protocol); @@ -1123,12 +1123,12 @@ int SalCallOp::update(const char *subject, bool_t no_user_consent) { int SalCallOp::cancel_invite_with_info(const SalErrorInfo *info) { belle_sip_request_t* cancel; ms_message("Cancelling INVITE request from [%s] to [%s] ",get_from(), get_to()); - + if (this->pending_client_trans == NULL){ ms_warning("There is no transaction to cancel."); return -1; } - + cancel = belle_sip_client_transaction_create_cancel(this->pending_client_trans); if (cancel){ if (info != NULL){ From 91f5e64e5c3e40de4247930fe84ec8b251635737 Mon Sep 17 00:00:00 2001 From: Benjamin Reis Date: Fri, 30 Mar 2018 16:56:50 +0200 Subject: [PATCH 50/67] do not crash on null reason header --- src/sal/call-op.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/sal/call-op.cpp b/src/sal/call-op.cpp index ade2d214b..a900ab5d8 100644 --- a/src/sal/call-op.cpp +++ b/src/sal/call-op.cpp @@ -1124,24 +1124,24 @@ int SalCallOp::cancel_invite_with_info(const SalErrorInfo *info) { belle_sip_request_t* cancel; ms_message("Cancelling INVITE request from [%s] to [%s] ",get_from(), get_to()); - if (this->pending_client_trans == NULL){ + if (this->pending_client_trans == NULL) { ms_warning("There is no transaction to cancel."); return -1; } cancel = belle_sip_client_transaction_create_cancel(this->pending_client_trans); - if (cancel){ - if (info != NULL){ + if (cancel) { + if (info && info->reason != SalReasonNone) { belle_sip_header_reason_t* reason = make_reason_header(info); belle_sip_message_add_header(BELLE_SIP_MESSAGE(cancel),BELLE_SIP_HEADER(reason)); } send_request(cancel); return 0; - }else if (this->dialog){ + } else if (this->dialog) { belle_sip_dialog_state_t state = belle_sip_dialog_get_state(this->dialog);; /*case where the response received is invalid (could not establish a dialog), but the transaction is not cancellable * because already terminated*/ - switch(state){ + switch(state) { case BELLE_SIP_DIALOG_EARLY: case BELLE_SIP_DIALOG_NULL: /*force kill the dialog*/ @@ -1303,7 +1303,7 @@ int SalCallOp::terminate_with_error(const SalErrorInfo *info) { int ret = 0; memset(&sei, 0, sizeof(sei)); - if (info == NULL && dialog_state != BELLE_SIP_DIALOG_CONFIRMED && this->dir == Dir::Incoming){ + if (info == NULL && dialog_state != BELLE_SIP_DIALOG_CONFIRMED && this->dir == Dir::Incoming) { /*the purpose of this line is to set a default SalErrorInfo for declining an incoming call (not yet established of course) */ sal_error_info_set(&sei,SalReasonDeclined, "SIP", 0, NULL, NULL); p_sei = &sei; @@ -1318,7 +1318,7 @@ int SalCallOp::terminate_with_error(const SalErrorInfo *info) { switch(dialog_state) { case BELLE_SIP_DIALOG_CONFIRMED: { belle_sip_request_t * req = belle_sip_dialog_create_request(this->dialog,"BYE"); - if (info != NULL){ + if (info && info->reason != SalReasonNone) { belle_sip_header_reason_t* reason = make_reason_header(info); belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(reason)); } @@ -1334,7 +1334,7 @@ int SalCallOp::terminate_with_error(const SalErrorInfo *info) { } else if (this->pending_client_trans){ if (belle_sip_transaction_get_state(BELLE_SIP_TRANSACTION(this->pending_client_trans)) == BELLE_SIP_TRANSACTION_PROCEEDING){ cancelling_invite(p_sei); - }else{ + } else { /* Case where the CANCEL cannot be sent because no provisional response was received so far. * The Op must be kept for the time of the transaction in case a response is received later. * The state is passed to Terminating to remember to terminate later. @@ -1351,7 +1351,7 @@ int SalCallOp::terminate_with_error(const SalErrorInfo *info) { if (this->dir == Dir::Incoming) { decline_with_error_info(p_sei,NULL); this->state=State::Terminated; - } else { + } else { cancelling_invite(p_sei); } break; From e63290b4c7acffd7602baaeb2eb9f09c0e3f95d2 Mon Sep 17 00:00:00 2001 From: Benjamin Reis Date: Fri, 30 Mar 2018 17:00:52 +0200 Subject: [PATCH 51/67] better reason management --- src/conference/session/call-session.cpp | 2 +- tester/call_single_tester.c | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/conference/session/call-session.cpp b/src/conference/session/call-session.cpp index c2244a569..668f0df33 100644 --- a/src/conference/session/call-session.cpp +++ b/src/conference/session/call-session.cpp @@ -92,7 +92,7 @@ void CallSessionPrivate::setState (CallSession::State newState, const string &me case CallSession::State::Error: switch (linphone_error_info_get_reason(q->getErrorInfo())) { case LinphoneReasonDeclined: - if(log->status == LinphoneCallSuccess) // Do not re-change the status of a call if it's already set + if (log->status != LinphoneCallMissed) // Do not re-change the status of a call if it's already set log->status = LinphoneCallDeclined; break; case LinphoneReasonNotAnswered: diff --git a/tester/call_single_tester.c b/tester/call_single_tester.c index 88a6de226..c33e95e63 100644 --- a/tester/call_single_tester.c +++ b/tester/call_single_tester.c @@ -821,11 +821,11 @@ static void multiple_answers_call_with_media_relay(void) { linphone_core_remove_supported_tag(pauline->lc,"gruu"); linphone_core_remove_supported_tag(marie1->lc,"gruu"); linphone_core_remove_supported_tag(marie2->lc,"gruu"); - + linphone_core_manager_start(pauline, TRUE); linphone_core_manager_start(marie1, TRUE); linphone_core_manager_start(marie2, TRUE); - + LinphoneCall* call1, *call2; bctbx_list_t* lcs = bctbx_list_append(NULL,pauline->lc); @@ -1038,7 +1038,7 @@ static void terminate_call_with_error(void) { linphone_call_ref(out_call); ei = linphone_error_info_new(); - linphone_error_info_set(ei, NULL, LinphoneReasonNone, 200, "Call refused for security reason", NULL); + linphone_error_info_set(ei, NULL, LinphoneReasonUnknown, 200, "Call refused for security reason", NULL); BC_ASSERT_TRUE(wait_for(caller_mgr->lc, callee_mgr->lc, &caller_mgr->stat.number_of_LinphoneCallOutgoingInit,1)); BC_ASSERT_TRUE(wait_for(caller_mgr->lc, callee_mgr->lc, &callee_mgr->stat.number_of_LinphoneCallIncomingReceived, 1)); @@ -1093,7 +1093,7 @@ static void cancel_call_with_error(void) { linphone_call_ref(out_call); ei = linphone_error_info_new(); - linphone_error_info_set(ei, NULL, LinphoneReasonNone, 600, "Call has been cancelled", NULL); + linphone_error_info_set(ei, NULL, LinphoneReasonUnknown, 600, "Call has been cancelled", NULL); BC_ASSERT_TRUE(wait_for(caller_mgr->lc, callee_mgr->lc, &caller_mgr->stat.number_of_LinphoneCallOutgoingInit,1)); BC_ASSERT_TRUE(wait_for(caller_mgr->lc, callee_mgr->lc, &callee_mgr->stat.number_of_LinphoneCallIncomingReceived, 1)); @@ -1421,8 +1421,8 @@ static void call_declined_with_error(void) { LinphoneErrorInfo *ei = linphone_factory_create_error_info(factory); LinphoneErrorInfo *reason_ei = linphone_factory_create_error_info(factory); - linphone_error_info_set(ei, "SIP", LinphoneReasonUnknown, 603, "Decline", NULL); //ordre des arguments à vérifier - linphone_error_info_set(reason_ei, "hardware", LinphoneReasonUnknown, 66, "J'ai plus de batterie", NULL); + linphone_error_info_set(ei, "SIP", LinphoneReasonDeclined, 603, "Decline", NULL); //ordre des arguments à vérifier + linphone_error_info_set(reason_ei, "hardware", LinphoneReasonDeclined, 66, "J'ai plus de batterie", NULL); linphone_error_info_set_sub_error_info(ei, reason_ei); @@ -5908,7 +5908,7 @@ static void call_with_ice_without_stun2(void){ static void call_with_ice_stun_not_responding(void){ LinphoneCoreManager * marie = linphone_core_manager_new( "marie_rc"); LinphoneCoreManager *pauline = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc"); - + /*set dummy stun servers*/ linphone_core_set_stun_server(marie->lc, "belledonne-communications.com:443"); linphone_core_set_stun_server(pauline->lc, "belledonne-communications.com:443"); From fd91311ace8091f945f0fee59970e66a66d27113 Mon Sep 17 00:00:00 2001 From: Jehan Monnier Date: Wed, 27 Sep 2017 15:04:31 +0200 Subject: [PATCH 52/67] avoid crash in case audio resources (mainly on macosx) take to much time to start --- tester/call_single_tester.c | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/tester/call_single_tester.c b/tester/call_single_tester.c index c33e95e63..08be21bf9 100644 --- a/tester/call_single_tester.c +++ b/tester/call_single_tester.c @@ -3153,22 +3153,25 @@ static void early_media_call_with_ringing_base(bool_t network_change){ _linphone_call_add_local_desc_changed_flag(marie_call, SAL_MEDIA_DESCRIPTION_NETWORK_CHANGED); } - linphone_call_accept(linphone_core_get_current_call(pauline->lc)); - - BC_ASSERT_TRUE(wait_for_list(lcs, &marie->stat.number_of_LinphoneCallConnected, 1,1000)); - connected_time=ms_get_cur_time_ms(); - BC_ASSERT_TRUE(wait_for_list(lcs, &marie->stat.number_of_LinphoneCallStreamsRunning, 1,1000)); - - BC_ASSERT_PTR_EQUAL(marie_call, linphone_core_get_current_call(marie->lc)); - BC_ASSERT_FALSE(linphone_call_get_all_muted(marie_call)); - - liblinphone_tester_check_rtcp(marie, pauline); - /*just to have a call duration !=0*/ - wait_for_list(lcs,&dummy,1,2000); - - end_call(pauline, marie); - ended_time=ms_get_cur_time_ms(); - BC_ASSERT_LOWER( labs((long)((linphone_call_log_get_duration(marie_call_log)*1000) - (int64_t)(ended_time - connected_time))), 1000, long, "%ld"); + if (linphone_core_get_current_call(pauline->lc) + && linphone_call_get_state(linphone_core_get_current_call(pauline->lc)) == LinphoneCallIncomingEarlyMedia) { + linphone_call_accept(linphone_core_get_current_call(pauline->lc)); + + BC_ASSERT_TRUE(wait_for_list(lcs, &marie->stat.number_of_LinphoneCallConnected, 1,1000)); + connected_time=ms_get_cur_time_ms(); + BC_ASSERT_TRUE(wait_for_list(lcs, &marie->stat.number_of_LinphoneCallStreamsRunning, 1,1000)); + + BC_ASSERT_PTR_EQUAL(marie_call, linphone_core_get_current_call(marie->lc)); + BC_ASSERT_FALSE(linphone_call_get_all_muted(marie_call)); + + liblinphone_tester_check_rtcp(marie, pauline); + /*just to have a call duration !=0*/ + wait_for_list(lcs,&dummy,1,2000); + + end_call(pauline, marie); + ended_time=ms_get_cur_time_ms(); + BC_ASSERT_LOWER( labs((long)((linphone_call_log_get_duration(marie_call_log)*1000) - (int64_t)(ended_time - connected_time))), 1000, long, "%ld"); + } bctbx_list_free(lcs); } From 220ccbac9a16ed4ac2ac6012e05595b53292ea4e Mon Sep 17 00:00:00 2001 From: Jehan Monnier Date: Wed, 27 Sep 2017 17:05:59 +0200 Subject: [PATCH 53/67] make sure local sip ports used by testers are always random --- tester/rcfiles/laure_call_logs_rc | 6 +++--- tester/rcfiles/laure_rc_udp | 6 +++--- tester/rcfiles/laure_tcp_rc | 6 +++--- tester/rcfiles/multi_account_rc | 6 +++--- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/tester/rcfiles/laure_call_logs_rc b/tester/rcfiles/laure_call_logs_rc index bbeafabeb..e5a964f72 100644 --- a/tester/rcfiles/laure_call_logs_rc +++ b/tester/rcfiles/laure_call_logs_rc @@ -1,7 +1,7 @@ [sip] -sip_port=5092 -sip_tcp_port=5092 -sip_tls_port=5093 +sip_port=-1 +sip_tcp_port=-1 +sip_tls_port=-1 default_proxy=0 ping_with_options=0 diff --git a/tester/rcfiles/laure_rc_udp b/tester/rcfiles/laure_rc_udp index c4016c4fa..e221c248a 100644 --- a/tester/rcfiles/laure_rc_udp +++ b/tester/rcfiles/laure_rc_udp @@ -1,7 +1,7 @@ [sip] -sip_port=5092 -sip_tcp_port=5092 -sip_tls_port=5093 +sip_port=-1 +sip_tcp_port=-1 +sip_tls_port=-1 default_proxy=0 ping_with_options=0 diff --git a/tester/rcfiles/laure_tcp_rc b/tester/rcfiles/laure_tcp_rc index 8ed5de984..912db8271 100644 --- a/tester/rcfiles/laure_tcp_rc +++ b/tester/rcfiles/laure_tcp_rc @@ -1,7 +1,7 @@ [sip] -sip_port=5092 -sip_tcp_port=5092 -sip_tls_port=5093 +sip_port=-1 +sip_tcp_port=-1 +sip_tls_port=-1 default_proxy=0 ping_with_options=0 diff --git a/tester/rcfiles/multi_account_rc b/tester/rcfiles/multi_account_rc index 8aefbfcaf..3c1e52020 100644 --- a/tester/rcfiles/multi_account_rc +++ b/tester/rcfiles/multi_account_rc @@ -1,7 +1,7 @@ [sip] -sip_port=5072 -sip_tcp_port=5072 -sip_tls_port=5073 +sip_port=-1 +sip_tcp_port=-1 +sip_tls_port=-1 default_proxy=0 [auth_info_0] From 4b2c1ef133df64cee9b90978b51859b14d81e43b Mon Sep 17 00:00:00 2001 From: Erwan Croze Date: Wed, 27 Sep 2017 17:18:59 +0200 Subject: [PATCH 54/67] Init bctbx logger before create the core in factory --- coreapi/factory.c | 1 + 1 file changed, 1 insertion(+) diff --git a/coreapi/factory.c b/coreapi/factory.c index e316a93ba..5138534a4 100644 --- a/coreapi/factory.c +++ b/coreapi/factory.c @@ -167,6 +167,7 @@ static LinphoneCore *_linphone_factory_create_core ( LpConfig *config = lp_config_new_with_factory(config_path, factory_config_path); LinphoneCore *lc = _linphone_core_new_with_config(cbs, config, user_data, system_context, automatically_start); lp_config_unref(config); + bctbx_uninit_logger(); return lc; } From 3976181afaa8996154ce5438607618025bd86ed1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micka=C3=ABl=20Turnel?= Date: Tue, 3 Apr 2018 14:47:46 +0200 Subject: [PATCH 55/67] Removed default bitrate limitation. (retrofit of commit 0d38a7) --- src/conference/session/media-session.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/conference/session/media-session.cpp b/src/conference/session/media-session.cpp index a124200cf..853d6ffc4 100644 --- a/src/conference/session/media-session.cpp +++ b/src/conference/session/media-session.cpp @@ -1920,8 +1920,7 @@ int MediaSessionPrivate::getVideoBandwidth (const SalMediaDescription *md, const else if (md->bandwidth > 0) { /* Case where b=AS is given globally, not per stream */ remoteBandwidth = PayloadTypeHandler::getRemainingBandwidthForVideo(md->bandwidth, audioBandwidth); - } else - remoteBandwidth = lp_config_get_int(linphone_core_get_config(q->getCore()->getCCore()), "net", "default_max_bandwidth", 1500); + } return PayloadTypeHandler::getMinBandwidth(PayloadTypeHandler::getRemainingBandwidthForVideo(linphone_core_get_upload_bandwidth(q->getCore()->getCCore()), audioBandwidth), remoteBandwidth); } From b2f43b06de2521c1cfd3d95a25d4800546a0571a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micka=C3=ABl=20Turnel?= Date: Tue, 3 Apr 2018 14:53:51 +0200 Subject: [PATCH 56/67] Add unit tests for fps in video calls. (retrofit of commit cc6b6b) --- tester/call_video_tester.c | 96 +++++++++++++++++++++++++++++++++++++- 1 file changed, 95 insertions(+), 1 deletion(-) diff --git a/tester/call_video_tester.c b/tester/call_video_tester.c index d74fbd2f8..fe85820a3 100644 --- a/tester/call_video_tester.c +++ b/tester/call_video_tester.c @@ -2072,6 +2072,97 @@ static void video_call_with_high_bandwidth_available(void) { linphone_core_manager_destroy(pauline); } +static void video_call_expected_fps_for_specified_bandwidth(int bandwidth, int fps, const char *resolution) { + LinphoneCoreManager *marie = linphone_core_manager_new("marie_rc"); + LinphoneCoreManager *pauline = linphone_core_manager_new("pauline_rc"); + LinphoneVideoPolicy pol = {0}; + OrtpNetworkSimulatorParams simparams = { 0 }; + + if (ms_factory_get_cpu_count(linphone_core_get_ms_factory(marie->lc)) >= 2) { + linphone_core_set_video_device(marie->lc, "Mire: Mire (synthetic moving picture)"); + linphone_core_enable_video_capture(marie->lc, TRUE); + linphone_core_enable_video_display(marie->lc, TRUE); + linphone_core_enable_video_capture(pauline->lc, TRUE); + linphone_core_enable_video_display(pauline->lc, TRUE); + + pol.automatically_accept = TRUE; + pol.automatically_initiate = TRUE; + linphone_core_set_video_policy(marie->lc, &pol); + linphone_core_set_video_policy(pauline->lc, &pol); + + linphone_core_set_preferred_video_size_by_name(marie->lc, resolution); + simparams.mode = OrtpNetworkSimulatorOutbound; + simparams.enabled = TRUE; + simparams.max_bandwidth = bandwidth; + simparams.max_buffer_size = (int)simparams.max_bandwidth; + simparams.latency = 60; + + linphone_core_set_network_simulator_params(marie->lc, &simparams); + + if (BC_ASSERT_TRUE(call(marie, pauline))){ + LinphoneCall *call = linphone_core_get_current_call(marie->lc); + + /*wait for the first TMMBR*/ + BC_ASSERT_TRUE(wait_for_until(marie->lc, pauline->lc, &marie->stat.last_tmmbr_value_received, 1, 10000)); + + VideoStream *vstream = (VideoStream *)linphone_call_get_stream(call, LinphoneStreamTypeVideo); + BC_ASSERT_EQUAL((int)vstream->configured_fps, fps, int, "%d"); + + end_call(marie, pauline); + } + } else { + BC_PASS("Test requires at least a dual core"); + } + + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline); +} + +/* + * This test simulates a video call with a lower bandwidth than the required_bitrate of the lowest given configuration. + * The stream from pauline to marie is not under test. + * It checks that after a few seconds marie, after receiving a TMMBR, has her fps set to the lowest given configuration. + * This test requires at least a computer with 2 CPUs. + * +**/ +static void video_call_expected_fps_for_low_bandwidth(void) { +#if defined(__ANDROID__) || (TARGET_OS_IPHONE == 1) || defined(__arm__) || defined(_M_ARM) + video_call_expected_fps_for_specified_bandwidth(80000, 10, "qvga"); +#else + video_call_expected_fps_for_specified_bandwidth(250000, 15, "vga"); +#endif +} + +/* + * This test simulates a video call with a regular bandwidth that is between a given configuration. + * The stream from pauline to marie is not under test. + * It checks that after a few seconds marie, after receiving a TMMBR, has her fps set to the expected given configuration. + * This test requires at least a computer with 2 CPUs. + * +**/ +static void video_call_expected_fps_for_regular_bandwidth(void) { +#if defined(__ANDROID__) || (TARGET_OS_IPHONE == 1) || defined(__arm__) || defined(_M_ARM) + video_call_expected_fps_for_specified_bandwidth(400000, 12, "vga"); +#else + video_call_expected_fps_for_specified_bandwidth(450000, 25, "vga"); +#endif +} + +/* + * This test simulates a video call with a higher bandwidth than the bitrate_limit of the highest given configuration. + * The stream from pauline to marie is not under test. + * It checks that after a few seconds marie, after receiving a TMMBR, has her fps set to the highest given configuration. + * This test requires at least a computer with 2 CPUs. + * +**/ +static void video_call_expected_fps_for_high_bandwidth(void) { +#if defined(__ANDROID__) || (TARGET_OS_IPHONE == 1) || defined(__arm__) || defined(_M_ARM) + video_call_expected_fps_for_specified_bandwidth(400000, 12, "qcif"); +#else + video_call_expected_fps_for_specified_bandwidth(5000000, 30, "vga"); +#endif +} + test_t call_video_tests[] = { #ifdef VIDEO_ENABLED TEST_NO_TAG("Call paused resumed with video", call_paused_resumed_with_video), @@ -2140,7 +2231,10 @@ test_t call_video_tests[] = { TEST_NO_TAG("Video call with no audio and no video codec", video_call_with_no_audio_and_no_video_codec), TEST_NO_TAG("Call with early media and no SDP in 200 Ok with video", call_with_early_media_and_no_sdp_in_200_with_video), TEST_NO_TAG("Video call with thin congestion", video_call_with_thin_congestion), - TEST_NO_TAG("Video call with high bandwidth available", video_call_with_high_bandwidth_available) + TEST_NO_TAG("Video call with high bandwidth available", video_call_with_high_bandwidth_available), + TEST_NO_TAG("Video call expected FPS for low bandwidth", video_call_expected_fps_for_low_bandwidth), + TEST_NO_TAG("Video call expected FPS for regular bandwidth", video_call_expected_fps_for_regular_bandwidth), + TEST_NO_TAG("Video call expected FPS for high bandwidth", video_call_expected_fps_for_high_bandwidth) #endif }; From 47415adf2aa216a45ae6163271af64f333688273 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Grisez?= Date: Tue, 3 Apr 2018 15:36:11 +0200 Subject: [PATCH 57/67] Removes duplicate CMake command --- coreapi/help/doc/doxygen/CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/coreapi/help/doc/doxygen/CMakeLists.txt b/coreapi/help/doc/doxygen/CMakeLists.txt index ef96a784f..91c62458d 100644 --- a/coreapi/help/doc/doxygen/CMakeLists.txt +++ b/coreapi/help/doc/doxygen/CMakeLists.txt @@ -39,7 +39,6 @@ if (ENABLE_DOC OR ENABLE_CXX_WRAPPER OR ENABLE_CSHARP_WRAPPER OR ENABLE_JAVA_WRA set(XML_DIR "${CMAKE_CURRENT_BINARY_DIR}/xml") set(LINPHONE_DOXYGEN_XML_DIR ${XML_DIR} PARENT_SCOPE) add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/html/index.html" "${XML_DIR}/index.xml" - COMMAND ${CMAKE_COMMAND} -E remove -f html/* xml/* COMMAND ${CMAKE_COMMAND} -E remove -f html/* xml/* COMMAND ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile DEPENDS ${DOC_INPUT_FILES} From 4f805973aef4d50dfab099e264b1e7b40cd9a020 Mon Sep 17 00:00:00 2001 From: Erwan Croze Date: Tue, 3 Apr 2018 16:17:10 +0200 Subject: [PATCH 58/67] Blacklist linphone_call_set_audio_route --- include/linphone/api/c-call.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/linphone/api/c-call.h b/include/linphone/api/c-call.h index 272e67b1d..464436945 100644 --- a/include/linphone/api/c-call.h +++ b/include/linphone/api/c-call.h @@ -338,6 +338,7 @@ LINPHONE_PUBLIC LinphoneConference *linphone_call_get_conference (const Linphone * Change the playback output device (currently only used for blackberry) * @param call * @param route the wanted audio route (earpiece, speaker, ...) + * @donotwrap **/ LINPHONE_PUBLIC void linphone_call_set_audio_route (LinphoneCall *call, LinphoneAudioRoute route); From 490c4bf913e741e9e0799fa4b9cdc6d26104adf9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micka=C3=ABl=20Turnel?= Date: Tue, 3 Apr 2018 16:58:13 +0200 Subject: [PATCH 59/67] Update fps tests according to VP8 conf table changes. (retrofit of commit fb465e) --- tester/call_video_tester.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tester/call_video_tester.c b/tester/call_video_tester.c index fe85820a3..3189fe3c2 100644 --- a/tester/call_video_tester.c +++ b/tester/call_video_tester.c @@ -2142,7 +2142,7 @@ static void video_call_expected_fps_for_low_bandwidth(void) { **/ static void video_call_expected_fps_for_regular_bandwidth(void) { #if defined(__ANDROID__) || (TARGET_OS_IPHONE == 1) || defined(__arm__) || defined(_M_ARM) - video_call_expected_fps_for_specified_bandwidth(400000, 12, "vga"); + video_call_expected_fps_for_specified_bandwidth(500000, 12, "vga"); #else video_call_expected_fps_for_specified_bandwidth(450000, 25, "vga"); #endif From 13a398462c1befcecd83d135922f1189577747ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micka=C3=ABl=20Turnel?= Date: Tue, 3 Apr 2018 16:58:56 +0200 Subject: [PATCH 60/67] Fix implicit cast for windows. (retrofit of commit 1dfa27) --- tester/call_video_tester.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tester/call_video_tester.c b/tester/call_video_tester.c index 3189fe3c2..4b4efb5ad 100644 --- a/tester/call_video_tester.c +++ b/tester/call_video_tester.c @@ -2093,8 +2093,8 @@ static void video_call_expected_fps_for_specified_bandwidth(int bandwidth, int f linphone_core_set_preferred_video_size_by_name(marie->lc, resolution); simparams.mode = OrtpNetworkSimulatorOutbound; simparams.enabled = TRUE; - simparams.max_bandwidth = bandwidth; - simparams.max_buffer_size = (int)simparams.max_bandwidth; + simparams.max_bandwidth = (float)bandwidth; + simparams.max_buffer_size = bandwidth; simparams.latency = 60; linphone_core_set_network_simulator_params(marie->lc, &simparams); From 5e98347b313a5703a88d2c1fb12537565d426c1a Mon Sep 17 00:00:00 2001 From: Ghislain MARY Date: Tue, 3 Apr 2018 17:05:02 +0200 Subject: [PATCH 61/67] Add log when we cannot find the selected valid ICE pair in the case where it should be there (retrofit of commit 452234d4). --- src/nat/ice-agent.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/nat/ice-agent.cpp b/src/nat/ice-agent.cpp index 726312f9f..cbc74cd4a 100644 --- a/src/nat/ice-agent.cpp +++ b/src/nat/ice-agent.cpp @@ -317,10 +317,12 @@ void IceAgent::updateLocalMediaDescriptionFromIce (SalMediaDescription *desc) { } if (firstCl) result = !!ice_check_list_selected_valid_local_candidate(firstCl, &rtpCandidate, nullptr); - if (result) + if (result) { strncpy(desc->addr, rtpCandidate->taddr.ip, sizeof(desc->addr)); - else + } else { lWarning() << "If ICE has completed successfully, rtp_candidate should be set!"; + ice_dump_valid_list(firstCl); + } } strncpy(desc->ice_pwd, ice_session_local_pwd(iceSession), sizeof(desc->ice_pwd)); From facab07c405225cbb99f8c8a4b94ec7a43f48367 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Grisez?= Date: Tue, 10 Oct 2017 14:31:58 +0200 Subject: [PATCH 62/67] Creates a new singleton object for logging features in the API of Liblinphone (cherry picked from commit d61a62de91483a5ba6029153c224adec9ef68622) --- coreapi/CMakeLists.txt | 1 + coreapi/linphonecore.c | 39 ++--- coreapi/logging-private.h | 61 ++++++++ coreapi/logging.c | 256 +++++++++++++++++++++++++++++++ include/CMakeLists.txt | 1 + include/linphone/core.h | 23 ++- include/linphone/logging.h | 178 +++++++++++++++++++++ src/c-wrapper/c-wrapper.h | 2 + tester/tester.c | 4 +- wrappers/cpp/class_impl.mustache | 1 + 10 files changed, 527 insertions(+), 39 deletions(-) create mode 100644 coreapi/logging-private.h create mode 100644 coreapi/logging.c create mode 100644 include/linphone/logging.h diff --git a/coreapi/CMakeLists.txt b/coreapi/CMakeLists.txt index 03600de80..85e13205c 100644 --- a/coreapi/CMakeLists.txt +++ b/coreapi/CMakeLists.txt @@ -84,6 +84,7 @@ set(LINPHONE_SOURCE_FILES_C linphonecore.c linphone_tunnel_config.c localplayer.c + logging.c lpc2xml.c lpconfig.c lsd.c diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index c6af072cf..b0a4347fe 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -21,7 +21,9 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "linphone/core.h" #include "linphone/sipsetup.h" #include "linphone/lpconfig.h" +#include "linphone/logging.h" #include "private.h" +#include "logging-private.h" #include "quality_reporting.h" #include "lime.h" #include "conference_private.h" @@ -500,40 +502,17 @@ void linphone_core_set_log_file(FILE *file) { } void linphone_core_set_log_level(OrtpLogLevel loglevel) { - unsigned int mask = loglevel; - switch (loglevel) { - case ORTP_TRACE: - case ORTP_DEBUG: - mask |= ORTP_DEBUG; - BCTBX_NO_BREAK; - case ORTP_MESSAGE: - mask |= ORTP_MESSAGE; - BCTBX_NO_BREAK; - case ORTP_WARNING: - mask |= ORTP_WARNING; - BCTBX_NO_BREAK; - case ORTP_ERROR: - mask |= ORTP_ERROR; - BCTBX_NO_BREAK; - case ORTP_FATAL: - mask |= ORTP_FATAL; - break; - case ORTP_LOGLEV_END: - break; - } - linphone_core_set_log_level_mask(mask); + LinphoneLoggingService *log_service = linphone_logging_service_get(); + linphone_logging_service_set_log_level(log_service, _bctbx_log_level_to_linphone_log_level(loglevel)); } -void linphone_core_set_log_level_mask(unsigned int loglevel) { - bctbx_set_log_level_mask("bctbx", (int)loglevel); - bctbx_set_log_level_mask("ortp", (int)loglevel); - bctbx_set_log_level_mask("mediastreamer", (int)loglevel); - bctbx_set_log_level_mask("bzrtp", (int)loglevel); /*need something to set log level for all domains*/ - bctbx_set_log_level_mask("linphone", (int)loglevel); - sal_set_log_level((OrtpLogLevel)loglevel); +void linphone_core_set_log_level_mask(unsigned int mask) { + LinphoneLoggingService *log_service = linphone_logging_service_get(); + linphone_logging_service_set_log_level_mask(log_service, _bctbx_log_mask_to_linphone_log_mask(mask)); } unsigned int linphone_core_get_log_level_mask(void) { - return bctbx_get_log_level_mask(ORTP_LOG_DOMAIN); + LinphoneLoggingService *log_service = linphone_logging_service_get(); + return linphone_logging_service_get_log_level_mask(log_service); } static int _open_log_collection_file_with_idx(int idx) { struct stat statbuf; diff --git a/coreapi/logging-private.h b/coreapi/logging-private.h new file mode 100644 index 000000000..e9b54b990 --- /dev/null +++ b/coreapi/logging-private.h @@ -0,0 +1,61 @@ +/* +logging-private.h +Copyright (C) 2017 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, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef _LOGGING_PRIVATE_H_ +#define _LOGGING_PRIVATE_H_ + +#include +#include "linphone/logging.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Converts a #BctbxLogLevel into #LinphoneLogLevel. + */ +LinphoneLogLevel _bctbx_log_level_to_linphone_log_level(BctbxLogLevel level); + +/** + * @brief Converts a mask of #BctbxLogLevel into a mask of #LinphoneLogLevel. + */ +unsigned int _bctbx_log_mask_to_linphone_log_mask(unsigned int mask); + +/** + * @brief Converts a #LinphoneLogLevel into #BctbxLogLevel. + */ +BctbxLogLevel _linphone_log_level_to_bctbx_log_level(LinphoneLogLevel level); + +/** + * @brief Converts a mask of #LinphoneLogLevel into a mask of #BctbxLogLevel. + */ +unsigned int _linphone_log_mask_to_bctbx_log_mask(unsigned int mask); + +/** + * @brief Releases the instance pointer of the singleton. + * @note You should not need to call this function since it is automatically done + * at process ending. + */ +void _linphone_logging_service_clean(void); + +#ifdef __cplusplus +} +#endif + +#endif // _LOGGING_PRIVATE_H_ diff --git a/coreapi/logging.c b/coreapi/logging.c new file mode 100644 index 000000000..e39ae0012 --- /dev/null +++ b/coreapi/logging.c @@ -0,0 +1,256 @@ +/* +log.c +Copyright (C) 2017 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, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include +#include + +#include +#include +#include + +#include "linphone/logging.h" + +#include "c-wrapper/c-wrapper.h" +#include "logging-private.h" + + +struct _LinphoneLoggingService { + belle_sip_object_t base; + LinphoneLoggingServiceCbs *cbs; + bctbx_log_handler_t *log_handler; +}; + +BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(LinphoneLoggingService); +BELLE_SIP_DECLARE_VPTR_NO_EXPORT(LinphoneLoggingService); + +struct _LinphoneLoggingServiceCbs { + belle_sip_object_t base; + void *user_data; + LinphoneLoggingServiceCbsLogMessageWrittenCb message_event_cb; +}; + +BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(LinphoneLoggingServiceCbs); +BELLE_SIP_DECLARE_VPTR_NO_EXPORT(LinphoneLoggingServiceCbs); + +static LinphoneLoggingServiceCbs *_linphone_logging_service_cbs_new(void); + + + + + +static LinphoneLoggingService *_linphone_logging_service_instance = NULL; + +static std::map _linphone_log_level_to_bctbx_log_level_map = { + { LinphoneLogLevelDebug , BCTBX_LOG_DEBUG }, + { LinphoneLogLevelTrace , BCTBX_LOG_TRACE }, + { LinphoneLogLevelMessage , BCTBX_LOG_MESSAGE }, + { LinphoneLogLevelWarning , BCTBX_LOG_WARNING }, + { LinphoneLogLevelError , BCTBX_LOG_ERROR }, + { LinphoneLogLevelFatal , BCTBX_LOG_FATAL } +}; + +LinphoneLogLevel _bctbx_log_level_to_linphone_log_level(BctbxLogLevel level) { + auto &tmap = _linphone_log_level_to_bctbx_log_level_map; + auto predicate = [level](const std::pair &tuple)->bool{return tuple.second==level;}; + auto response = std::find_if(tmap.cbegin(), tmap.cend(), predicate); + if (response != tmap.cend()) { + return response->first; + } else { + ms_fatal("%s(): invalid argurement [%d]", __FUNCTION__, level); + return LinphoneLogLevelDebug; + } +} + +unsigned int _bctbx_log_mask_to_linphone_log_mask(unsigned int mask) { + unsigned int res = 0; + auto &tmap = _linphone_log_level_to_bctbx_log_level_map; + for (auto it=tmap.cbegin(); it!=tmap.cend(); it++) { + if (mask & it->second) { + mask&=~it->second; + res|=it->first; + } + } + if (mask != 0) { + ms_fatal("%s(): invalid flag set in mask [%x]", __FUNCTION__, mask); + } + return res; +} + +BctbxLogLevel _linphone_log_level_to_bctbx_log_level(LinphoneLogLevel level) { + try { + return _linphone_log_level_to_bctbx_log_level_map.at(level); + } catch (const std::out_of_range &e) { + ms_fatal("%s(): invalid argument [%d]", __FUNCTION__, level); + return BCTBX_LOG_LOGLEV_END; + } +} + +unsigned int _linphone_log_mask_to_bctbx_log_mask(unsigned int mask) { + unsigned int res = 0; + auto &tmap = _linphone_log_level_to_bctbx_log_level_map; + for (auto it=tmap.cbegin(); it!=tmap.cend(); it++) { + if (mask & it->first) { + mask&=~it->first; + res|=it->second; + } + } + if (mask != 0) { + ms_fatal("%s(): invalid flag set in mask [%x]", __FUNCTION__, mask); + } + return res; +} + +static void _log_handler_on_message_written_cb(void *info,const char *domain, BctbxLogLevel lev, const char *fmt, va_list args) { + LinphoneLoggingService *service = (LinphoneLoggingService *)info; + if (service->cbs->message_event_cb) { + char *message = bctbx_strdup_vprintf(fmt, args); + service->cbs->message_event_cb(service, domain, _bctbx_log_level_to_linphone_log_level(lev), message); + bctbx_free(message); + } +} + +static void _log_handler_destroy_cb(bctbx_log_handler_t *handler) { + LinphoneLoggingService *service = (LinphoneLoggingService *)bctbx_log_handler_get_user_data(handler); + service->log_handler = NULL; +} + +static LinphoneLoggingService *_linphone_logging_service_new(void) { + LinphoneLoggingService *service = belle_sip_object_new(LinphoneLoggingService); + service->log_handler = bctbx_create_log_handler(_log_handler_on_message_written_cb, _log_handler_destroy_cb, service); + service->cbs = _linphone_logging_service_cbs_new(); + bctbx_add_log_handler(service->log_handler); + return service; +} + +LinphoneLoggingService *linphone_logging_service_get(void) { + if (_linphone_logging_service_instance == NULL) { + _linphone_logging_service_instance = _linphone_logging_service_new(); + atexit(_linphone_logging_service_clean); + } + return _linphone_logging_service_instance; +} + +void _linphone_logging_service_clean(void) { + if (_linphone_logging_service_instance) { + linphone_logging_service_unref(_linphone_logging_service_instance); + _linphone_logging_service_instance = NULL; + } +} + +LinphoneLoggingService *linphone_logging_service_ref(LinphoneLoggingService *service) { + return (LinphoneLoggingService *)belle_sip_object_ref(service); +} + +void linphone_logging_service_unref(LinphoneLoggingService *service) { + belle_sip_object_ref(service); +} + +static void _linphone_logging_service_uninit(LinphoneLoggingService *log_service) { + if (log_service->log_handler) bctbx_remove_log_handler(log_service->log_handler); + linphone_logging_service_cbs_unref(log_service->cbs); +} + +void linphone_logging_service_release_instance(void) { + if (_linphone_logging_service_instance) { + belle_sip_object_unref(BELLE_SIP_OBJECT(_linphone_logging_service_instance)); + } + _linphone_logging_service_instance = NULL; +} + +LinphoneLoggingServiceCbs *linphone_logging_service_get_callbacks(const LinphoneLoggingService *log_service) { + return log_service->cbs; +} + +static const char *_linphone_logging_service_log_domains[] = { + "bctbx", + "ortp", + "mediastreamer", + "bzrtp", + "linphone", + NULL +}; + +void linphone_logging_service_set_log_level(LinphoneLoggingService *log_service, LinphoneLogLevel loglevel) { + const char **domain; + for (domain=_linphone_logging_service_log_domains; *domain; domain++) { + bctbx_set_log_level(*domain, _linphone_log_level_to_bctbx_log_level(loglevel)); + } +} + +void linphone_logging_service_set_log_level_mask(LinphoneLoggingService *log_service, unsigned int mask) { + const char **domain; + for (domain=_linphone_logging_service_log_domains; *domain; domain++) { + bctbx_set_log_level_mask(*domain, _linphone_log_mask_to_bctbx_log_mask(mask)); + } +} + +unsigned int linphone_logging_service_get_log_level_mask(const LinphoneLoggingService *log_service) { + return _bctbx_log_mask_to_linphone_log_mask(bctbx_get_log_level_mask(ORTP_LOG_DOMAIN)); +} + +void linphone_logging_service_set_log_file(const LinphoneLoggingService *service, const char *dir, const char *filename, size_t max_size) { + bctbx_log_handler_t *log_handler = bctbx_create_file_log_handler((uint64_t)max_size, dir, filename, NULL); + bctbx_add_log_handler(log_handler); +} + +BELLE_SIP_INSTANCIATE_VPTR(LinphoneLoggingService, belle_sip_object_t, + _linphone_logging_service_uninit, // uninit + NULL, // clone + NULL, // marshal + FALSE // unown +); + + + + + + + + + +static LinphoneLoggingServiceCbs *_linphone_logging_service_cbs_new(void) { + return belle_sip_object_new(LinphoneLoggingServiceCbs); +} + +LinphoneLoggingServiceCbs *linphone_logging_service_cbs_ref(LinphoneLoggingServiceCbs *cbs) { + return (LinphoneLoggingServiceCbs *)belle_sip_object_ref(cbs); +} + +void linphone_logging_service_cbs_unref(LinphoneLoggingServiceCbs *cbs) { + belle_sip_object_unref(cbs); +} + +void linphone_logging_service_cbs_set_log_message_written(LinphoneLoggingServiceCbs *cbs, LinphoneLoggingServiceCbsLogMessageWrittenCb cb) { + cbs->message_event_cb = cb; +} + +LinphoneLoggingServiceCbsLogMessageWrittenCb linphone_logging_service_cbs_get_log_message_written(const LinphoneLoggingServiceCbs *cbs) { + return cbs->message_event_cb; +} + +void linphone_logging_service_cbs_set_user_data(LinphoneLoggingServiceCbs *cbs, void *user_data) { + cbs->user_data = user_data; +} + +BELLE_SIP_INSTANCIATE_VPTR(LinphoneLoggingServiceCbs, belle_sip_object_t, + NULL, // uninit + NULL, // clone + NULL, // marshal + FALSE // unown +); diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt index 92593391a..2e09af5eb 100644 --- a/include/CMakeLists.txt +++ b/include/CMakeLists.txt @@ -48,6 +48,7 @@ set(ROOT_HEADER_FILES im_notif_policy.h info_message.h ldapprovider.h + logging.h lpconfig.h misc.h nat_policy.h diff --git a/include/linphone/core.h b/include/linphone/core.h index 7ee26c5d0..ce0e774e0 100644 --- a/include/linphone/core.h +++ b/include/linphone/core.h @@ -800,25 +800,28 @@ LINPHONE_PUBLIC void linphone_core_reset_log_collection(void); /** * @bref Define a log handler. * @param logfunc The function pointer of the log handler. + * @deprecated Use #linphone_log_service_set_log_handler() instead. Deprecated since 2017-10-10. * @donotwrap */ -LINPHONE_PUBLIC void linphone_core_set_log_handler(OrtpLogFunc logfunc); +LINPHONE_PUBLIC LINPHONE_DEPRECATED void linphone_core_set_log_handler(OrtpLogFunc logfunc); /** * @brief Define a log file. * * If the file pointer passed as an argument is NULL, stdout is used instead. * @param file A pointer to the FILE structure of the file to write to. + * @deprecated Use #linphone_log_service_set_file() instead. Deprecated since 2017-10-10. * @donotwrap */ -LINPHONE_PUBLIC void linphone_core_set_log_file(FILE *file); +LINPHONE_PUBLIC LINPHONE_DEPRECATED void linphone_core_set_log_file(FILE *file); /** * @brief Define the minimum level for logging. * @param loglevel Minimum level for logging messages. + * @deprecated Use #linphone_logging_service_set_log_level() instead. Deprecated since 2017-10-10. * @donotwrap **/ -LINPHONE_PUBLIC void linphone_core_set_log_level(OrtpLogLevel loglevel); +LINPHONE_PUBLIC LINPHONE_DEPRECATED void linphone_core_set_log_level(OrtpLogLevel loglevel); /** * Define the log level using mask. @@ -826,22 +829,25 @@ LINPHONE_PUBLIC void linphone_core_set_log_level(OrtpLogLevel loglevel); * The loglevel parameter is a bitmask parameter. Therefore to enable only warning and error * messages, use ORTP_WARNING | ORTP_ERROR. To disable logs, simply set loglevel to 0. * - * @param loglevel A bitmask of the log levels to set. + * @param mask A bitmask of the log levels to set. + * @deprecated Use #linphone_logging_service_set_log_level() instead. Deprecated since 2017-10-10. */ -LINPHONE_PUBLIC void linphone_core_set_log_level_mask(unsigned int loglevel); +LINPHONE_PUBLIC LINPHONE_DEPRECATED void linphone_core_set_log_level_mask(unsigned int mask); /** * Get defined log level mask. * * @return The loglevel parameter is a bitmask parameter. Therefore to enable only warning and error * messages, use ORTP_WARNING | ORTP_ERROR. To disable logs, simply set loglevel to 0. + * @deprecated Use #linphone_logging_service_get_log_level_mask() instead. Deprecated since 2017-10-10. */ -LINPHONE_PUBLIC unsigned int linphone_core_get_log_level_mask(void); +LINPHONE_PUBLIC LINPHONE_DEPRECATED unsigned int linphone_core_get_log_level_mask(void); /** * Enable logs in supplied FILE*. * @param file a C FILE* where to fprintf logs. If null stdout is used. - * @deprecated Use #linphone_core_set_log_file and #linphone_core_set_log_level instead. + * @deprecated Use #linphone_core_set_log_file and #linphone_core_set_log_level() instead. + * Deprecated since 2017-01-12. * @donotwrap **/ LINPHONE_DEPRECATED LINPHONE_PUBLIC void linphone_core_enable_logs(FILE *file); @@ -851,13 +857,14 @@ LINPHONE_DEPRECATED LINPHONE_PUBLIC void linphone_core_enable_logs(FILE *file); * @param logfunc The address of a OrtpLogFunc callback whose protoype is * typedef void (*OrtpLogFunc)(OrtpLogLevel lev, const char *fmt, va_list args); * @deprecated Use #linphone_core_set_log_handler and #linphone_core_set_log_level instead. + * Deprecated since 2017-01-12. * @donotwrap **/ LINPHONE_DEPRECATED LINPHONE_PUBLIC void linphone_core_enable_logs_with_cb(OrtpLogFunc logfunc); /** * Entirely disable logging. - * @deprecated Use #linphone_core_set_log_level instead. + * @deprecated Use #linphone_core_set_log_level() instead. Deprecated since 2017-01-12. * @donotwrap **/ LINPHONE_DEPRECATED LINPHONE_PUBLIC void linphone_core_disable_logs(void); diff --git a/include/linphone/logging.h b/include/linphone/logging.h new file mode 100644 index 000000000..e54d0702f --- /dev/null +++ b/include/linphone/logging.h @@ -0,0 +1,178 @@ +/* +logging.h +Copyright (C) 2017 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, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef _LINPHONE_LOG_H_ +#define _LINPHONE_LOG_H_ + +#include "types.h" +#include "defs.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @addtogroup logging + * @{ + */ + +/** + * @brief Singleton class giving access to logging features. + */ +typedef struct _LinphoneLoggingService LinphoneLoggingService; + +/** + * @brief Listener for #LinphoneLoggingService. + */ +typedef struct _LinphoneLoggingServiceCbs LinphoneLoggingServiceCbs; + +/** + * @brief Verbosity levels of log messages. + */ +typedef enum _LinphoneLogLevel { + LinphoneLogLevelDebug = 1, /**< @brief Level for debug messages. */ + LinphoneLogLevelTrace = 1<<1, /**< @brief Level for traces. */ + LinphoneLogLevelMessage = 1<<2, /**< @brief Level for information messages. */ + LinphoneLogLevelWarning = 1<<3, /**< @brief Level for warning messages. */ + LinphoneLogLevelError = 1<<4, /**< @brief Level for error messages. */ + LinphoneLogLevelFatal = 1<<5 /**< @brief Level for fatal error messages. */ +} LinphoneLogLevel; + +/** + * @brief Type of callbacks called each time liblinphone write a log message. + * + * @param log_service A pointer on the logging service singleton. + * @param domain A string describing which sub-library of liblinphone the message is coming from. + * @param lev Verbosity level of the message. + * @param message Content of the message. + */ +typedef void (*LinphoneLoggingServiceCbsLogMessageWrittenCb)(LinphoneLoggingService *log_service, const char *domain, LinphoneLogLevel lev, const char *message); + + + + + +/** + * @brief Gets the singleton logging service object. + * + * The singleton is automatically instantiated if it hasn't + * been done yet. + * + * @return A pointer on the singleton. + */ +LINPHONE_PUBLIC LinphoneLoggingService *linphone_logging_service_get(void); + +/** + * @brief Increases the reference counter. + */ +LINPHONE_PUBLIC LinphoneLoggingService *linphone_logging_service_ref(LinphoneLoggingService *service); + +/** + * @brief Decreases the reference counter and destroy the object + * if the counter reaches 0. + */ +LINPHONE_PUBLIC void linphone_logging_service_unref(LinphoneLoggingService *service); + +/** + * @brief Gets the logging service listener. + */ +LINPHONE_PUBLIC LinphoneLoggingServiceCbs *linphone_logging_service_get_callbacks(const LinphoneLoggingService *log_service); + +/** + * @brief Set the verbosity of the log. + * + * For instance, a level of #LinphoneLogLevelMessage will let pass fatal, error, warning and message-typed messages + * whereas trace and debug messages will be dumped out. + */ +LINPHONE_PUBLIC void linphone_logging_service_set_log_level(LinphoneLoggingService *log_service, LinphoneLogLevel level); + +/** + * @brief Sets the types of messages that will be authorized to be written in the log. + * @param log_service The logging service singleton. + * @param mask Example: #LinphoneLogLevelMessage|#LinphoneLogLevelError will ONLY let pass message-typed and error messages. + * @note Calling that function reset the log level that has been specified by #linphone_logging_service_set_log_level(). + */ +LINPHONE_PUBLIC void linphone_logging_service_set_log_level_mask(LinphoneLoggingService *log_service, unsigned int mask); + +/** + * @brief Gets the log level mask. + */ +LINPHONE_PUBLIC unsigned int linphone_logging_service_get_log_level_mask(const LinphoneLoggingService *log_service); + +/** + * @brief Enables logging in a file. + * + * That function enables an internal log handler that writes log messages in + * log-rotated files. + * + * @param dir Directory where to create the distinct parts of the log. + * @param filename Name of the log file. + * @param max_size The maximal size of each part of the log. The log rotating is triggered + * each time the currently opened log part reach that limit. + */ +LINPHONE_PUBLIC void linphone_logging_service_set_log_file(const LinphoneLoggingService *service, const char *dir, const char *filename, size_t max_size); + + + + + +/** + * @brief Increases the reference counter. + */ +LINPHONE_PUBLIC LinphoneLoggingServiceCbs *linphone_logging_service_cbs_ref(LinphoneLoggingServiceCbs *cbs); + +/** + * @brief Decreases the reference counter. + * + * The object is automatically destroyed once the counter reach 0. + */ +LINPHONE_PUBLIC void linphone_logging_service_cbs_unref(LinphoneLoggingServiceCbs *cbs); + +/** + * @brief Sets the callback to call each time liblinphone writes a log message. + */ +LINPHONE_PUBLIC void linphone_logging_service_cbs_set_log_message_written(LinphoneLoggingServiceCbs *cbs, LinphoneLoggingServiceCbsLogMessageWrittenCb cb); + +/** + * @brief Gets the value of the message event callback. + */ +LINPHONE_PUBLIC LinphoneLoggingServiceCbsLogMessageWrittenCb linphone_logging_service_cbs_get_log_message_written(const LinphoneLoggingServiceCbs *cbs); + +/** + * @brief Pass a pointer on a custom object. + * + * That pointer can be get back by callbacks by using #linphone_logging_service_get_cbs() and #linphone_logging_service_cbs_get_user_data(). + */ +LINPHONE_PUBLIC void linphone_logging_service_cbs_set_user_data(LinphoneLoggingServiceCbs *cbs, void *user_data); + +/** + * @brief Gets the user_data pointer back. + */ +LINPHONE_PUBLIC void *linphone_logging_service_cbs_get_user_data(const LinphoneLoggingServiceCbs *cbs); + + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif // _LINPHONE_LOG_H_ diff --git a/src/c-wrapper/c-wrapper.h b/src/c-wrapper/c-wrapper.h index 9ebb30f72..e0109ce7c 100644 --- a/src/c-wrapper/c-wrapper.h +++ b/src/c-wrapper/c-wrapper.h @@ -100,6 +100,8 @@ BELLE_SIP_TYPE_ID(LinphoneImNotifPolicy), BELLE_SIP_TYPE_ID(LinphoneInfoMessage), BELLE_SIP_TYPE_ID(LinphoneLDAPContactProvider), BELLE_SIP_TYPE_ID(LinphoneLDAPContactSearch), +BELLE_SIP_TYPE_ID(LinphoneLoggingService), +BELLE_SIP_TYPE_ID(LinphoneLoggingServiceCbs), BELLE_SIP_TYPE_ID(LinphoneNatPolicy), BELLE_SIP_TYPE_ID(LinphonePayloadType), BELLE_SIP_TYPE_ID(LinphonePlayer), diff --git a/tester/tester.c b/tester/tester.c index c47cff87f..6eaafeab9 100644 --- a/tester/tester.c +++ b/tester/tester.c @@ -19,6 +19,8 @@ #include #include #include "linphone/core.h" +#include "linphone/logging.h" +#include "logging-private.h" #include "liblinphone_tester.h" #include #include "tester_utils.h" @@ -503,7 +505,7 @@ void linphone_core_manager_uninit(LinphoneCoreManager *mgr) { linphone_core_cbs_unref(mgr->cbs); manager_count--; - linphone_core_set_log_level(old_log_level); + linphone_core_set_log_level_mask(old_log_level); } void linphone_core_manager_wait_for_stun_resolution(LinphoneCoreManager *mgr) { diff --git a/wrappers/cpp/class_impl.mustache b/wrappers/cpp/class_impl.mustache index 3002c3c9c..f780ed6e5 100644 --- a/wrappers/cpp/class_impl.mustache +++ b/wrappers/cpp/class_impl.mustache @@ -21,6 +21,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include #include #include +#include #include "linphone++/linphone.hh" #include "tools.hh" From e6158d8da50eefcbe0625fc32651962871f75313 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Grisez?= Date: Tue, 10 Oct 2017 17:55:16 +0200 Subject: [PATCH 63/67] Add the deprecation date on some deprecated functions (cherry picked from commit f56f27fb2c6f25356ac22db059ed653ad1ad57ab) --- include/linphone/core.h | 112 +++++++++++++++++++++++----------------- 1 file changed, 65 insertions(+), 47 deletions(-) diff --git a/include/linphone/core.h b/include/linphone/core.h index ce0e774e0..ded8e3949 100644 --- a/include/linphone/core.h +++ b/include/linphone/core.h @@ -165,7 +165,8 @@ typedef struct _LinphoneCoreVTable{ LinphoneCoreNotifyPresenceReceivedCb notify_presence_received; /**< Notify received presence events*/ LinphoneCoreNotifyPresenceReceivedForUriOrTelCb notify_presence_received_for_uri_or_tel; /**< Notify received presence events*/ LinphoneCoreNewSubscriptionRequestedCb new_subscription_requested; /**< Notify about pending presence subscription request */ - LINPHONE_DEPRECATED LinphoneCoreAuthInfoRequestedCb auth_info_requested; /**< @deprecated Use authentication_requested instead. Ask the application some authentication information */ + LINPHONE_DEPRECATED LinphoneCoreAuthInfoRequestedCb auth_info_requested; /** @brief Ask the application some authentication information. + @deprecated Use authentication_requested instead. Deprecated since 2016-09-21 */ LinphoneCoreAuthenticationRequestedCb authentication_requested; /**< Ask the application some authentication information */ LinphoneCoreCallLogUpdatedCb call_log_updated; /**< Notifies that call log list has been updated */ LinphoneCoreMessageReceivedCb message_received; /**< a message is received, can be text or external body*/ @@ -181,11 +182,16 @@ typedef struct _LinphoneCoreVTable{ LinphoneCoreSubscriptionStateChangedCb subscription_state_changed; /** A text message has been received */ - LINPHONE_DEPRECATED LinphoneCoreFileTransferRecvCb file_transfer_recv; /**< @deprecated Callback to store file received attached to a #LinphoneChatMessage */ - LINPHONE_DEPRECATED LinphoneCoreFileTransferSendCb file_transfer_send; /**< @deprecated Callback to collect file chunk to be sent for a #LinphoneChatMessage */ - LINPHONE_DEPRECATED LinphoneCoreFileTransferProgressIndicationCb file_transfer_progress_indication; /**< @deprecated Callback to indicate file transfer progress */ + LinphoneCoreConfiguringStatusCb configuring_status; /**< Notifies configuring status changes + @deprecated Deprecated since 2015-11-19. */ + LINPHONE_DEPRECATED LinphoneCoreTextMessageReceivedCb text_received; /**< @brief A text message has been received. + @deprecated Use #message_received instead. Deprecated since 2015-11-19. */ + LINPHONE_DEPRECATED LinphoneCoreFileTransferRecvCb file_transfer_recv; /**< @brief Callback to store file received attached to a #LinphoneChatMessage. + @deprecated Deprecated since 2015-11-19. */ + LINPHONE_DEPRECATED LinphoneCoreFileTransferSendCb file_transfer_send; /**< @brief Callback to collect file chunk to be sent for a #LinphoneChatMessage. + @deprecated Deprecated since 2015-11-19. */ + LINPHONE_DEPRECATED LinphoneCoreFileTransferProgressIndicationCb file_transfer_progress_indication; /**< @brief Callback to indicate file transfer progress. + @deprecated Deprecated since 2015-11-19. */ LinphoneCoreNetworkReachableCb network_reachable; /**< Callback to report IP network status (I.E up/down )*/ LinphoneCoreLogCollectionUploadStateChangedCb log_collection_upload_state_changed; /**< Callback to upload collected logs */ LinphoneCoreLogCollectionUploadProgressIndicationCb log_collection_upload_progress_indication; /**< Callback to indicate log collection upload progress */ @@ -886,13 +892,15 @@ LINPHONE_PUBLIC const char *linphone_core_get_version(void); LINPHONE_PUBLIC const char *linphone_core_get_user_agent(LinphoneCore *lc); /** - * @deprecated 2016-12-20: Use #linphone_core_get_user_agent instead. + * @deprecated Use #linphone_core_get_user_agent() instead. + * Deprecated since 2015-11-19. * @donotwrap **/ LINPHONE_PUBLIC LINPHONE_DEPRECATED const char *linphone_core_get_user_agent_name(void); /** - * @deprecated 2016-12-20: Use #linphone_core_get_user_agent instead. + * @deprecated Use #linphone_core_get_user_agent instead. + * Deprecated since 2015-11-19. * @donotwrap **/ LINPHONE_PUBLIC LINPHONE_DEPRECATED const char *linphone_core_get_user_agent_version(void); @@ -910,8 +918,8 @@ LINPHONE_PUBLIC LINPHONE_DEPRECATED const char *linphone_core_get_user_agent_ver * @param vtable a LinphoneCoreVTable structure holding your application callbacks * @param config_path a path to a config file. If it does not exists it will be created. * The config file is used to store all settings, call logs, friends, proxies... so that all these settings - * become persistent over the life of the LinphoneCore object. - * It is allowed to set a NULL config file. In that case LinphoneCore will not store any settings. + * become persistent over the life of the LinphoneCore object. + * It is allowed to set a NULL config file. In that case LinphoneCore will not store any settings. * @param factory_config_path a path to a read-only config file that can be used to * to store hard-coded preference such as proxy settings or internal preferences. * The settings in this factory file always override the one in the normal config file. @@ -919,7 +927,7 @@ LINPHONE_PUBLIC LINPHONE_DEPRECATED const char *linphone_core_get_user_agent_ver * @param userdata an opaque user pointer that can be retrieved at any time (for example in * callbacks) using linphone_core_get_user_data(). * @see linphone_core_new_with_config - * @deprecated 2017-01-12: Use linphone_factory_create_core() instead. + * @deprecated Use #linphone_factory_create_core() instead. Deprecated since 2017-01-12. * @donotwrap **/ LINPHONE_DEPRECATED LINPHONE_PUBLIC LinphoneCore *linphone_core_new(const LinphoneCoreVTable *vtable, @@ -936,7 +944,7 @@ LINPHONE_DEPRECATED LINPHONE_PUBLIC LinphoneCore *linphone_core_new(const Linpho * @param userdata an opaque user pointer that can be retrieved at any time (for example in * callbacks) using linphone_core_get_user_data(). * @see linphone_core_new - * @deprecated 2017-01-12: Use linphone_factory_create_core_with_config() instead. + * @deprecated Use #linphone_factory_create_core_with_config() instead. Deprecated since 2017-01-12. * @donotwrap **/ LINPHONE_DEPRECATED LINPHONE_PUBLIC LinphoneCore *linphone_core_new_with_config(const LinphoneCoreVTable *vtable, LpConfig *config, void *userdata); @@ -987,7 +995,7 @@ LINPHONE_PUBLIC void linphone_core_iterate(LinphoneCore *lc); * add a listener to be notified of linphone core events. Once events are received, registered vtable are invoked in order. * @param vtable a LinphoneCoreVTable structure holding your application callbacks. Object is owned by linphone core until linphone_core_remove_listener. * @param lc object - * @deprecated Use linphone_core_add_callbacks() instead. + * @deprecated Use linphone_core_add_callbacks() instead. Deprecated since 2017-01-12. * @donotwrap */ LINPHONE_DEPRECATED LINPHONE_PUBLIC void linphone_core_add_listener(LinphoneCore *lc, LinphoneCoreVTable *vtable); @@ -1006,7 +1014,7 @@ LINPHONE_PUBLIC void linphone_core_add_callbacks(LinphoneCore *lc, LinphoneCoreC * remove a listener registred by linphone_core_add_listener. * @param lc object * @param vtable a LinphoneCoreVTable structure holding your application callbacks. - * @deprecated Use linphone_core_remove_callbacks() instead. + * @deprecated Use linphone_core_remove_callbacks() instead. Deprecated since 2017-01-12. * @donotwrap */ LINPHONE_DEPRECATED LINPHONE_PUBLIC void linphone_core_remove_listener(LinphoneCore *lc, const LinphoneCoreVTable *vtable); @@ -1086,7 +1094,8 @@ LINPHONE_PUBLIC LinphoneCall * linphone_core_invite_with_params(LinphoneCore *lc LINPHONE_PUBLIC LinphoneCall * linphone_core_invite_address_with_params(LinphoneCore *lc, const LinphoneAddress *addr, const LinphoneCallParams *params); /** - * Performs a simple call transfer to the specified destination. + * @brief Performs a simple call transfer to the specified destination. + * * The remote endpoint is expected to issue a new call to the specified destination. * The current call remains active and thus can be later paused or terminated. * It is possible to follow the progress of the transfer provided that transferee sends notification about it. @@ -1097,12 +1106,13 @@ LINPHONE_PUBLIC LinphoneCall * linphone_core_invite_address_with_params(Linphone * @param[in] refer_to The destination the call is to be refered to * @return 0 on success, -1 on failure * @ingroup call_control - * @deprecated Use linphone_call_transfer() instead + * @deprecated Use #linphone_call_transfer() instead. Deprecated since 2017-02-13. **/ LINPHONE_PUBLIC LINPHONE_DEPRECATED LinphoneStatus linphone_core_transfer_call(LinphoneCore *lc, LinphoneCall *call, const char *refer_to); /** - * Transfers a call to destination of another running call. This is used for "attended transfer" scenarios. + * @brief Transfers a call to destination of another running call. This is used for "attended transfer" scenarios. + * * The transfered call is supposed to be in paused state, so that it is able to accept the transfer immediately. * The destination call is a call previously established to introduce the transfered person. * This method will send a transfer request to the transfered person. The phone of the transfered is then @@ -1116,12 +1126,13 @@ LINPHONE_PUBLIC LINPHONE_DEPRECATED LinphoneStatus linphone_core_transfer_call(L * @param[in] dest A running call whose remote person will receive the transfer * @return 0 on success, -1 on failure * @ingroup call_control - * @deprecated Use linphone_call_transfer_to_another() instead + * @deprecated Use #linphone_call_transfer_to_another() instead. Deprecated since 2017-02-13. **/ LINPHONE_PUBLIC LINPHONE_DEPRECATED LinphoneStatus linphone_core_transfer_call_to_another(LinphoneCore *lc, LinphoneCall *call, LinphoneCall *dest); /** - * Start a new call as a consequence of a transfer request received from a call. + * @brief Start a new call as a consequence of a transfer request received from a call. + * * This function is for advanced usage: the execution of transfers is automatically managed by the LinphoneCore. However if an application * wants to have control over the call parameters for the new call, it should call this function immediately during the LinphoneCallRefered notification. * @see LinphoneCoreVTable::call_state_changed @@ -1136,7 +1147,8 @@ LINPHONE_PUBLIC LinphoneCall * linphone_core_start_refered_call(LinphoneCore *lc #define linphone_core_inc_invite_pending(lc) linphone_core_is_incoming_invite_pending(lc) /** - * Tells whether there is an incoming invite pending. + * @brief Tells whether there is an incoming invite pending. + * * @ingroup call_control * @param[in] lc LinphoneCore object * @return A boolean telling whether an incoming invite is pending or not. @@ -1160,7 +1172,7 @@ LINPHONE_PUBLIC bool_t linphone_core_in_call(const LinphoneCore *lc); LINPHONE_PUBLIC LinphoneCall *linphone_core_get_current_call(const LinphoneCore *lc); /** - * Accept an incoming call. + * @brief Accept an incoming call. * * Basically the application is notified of incoming calls within the * call_state_changed callback of the #LinphoneCoreVTable structure, where it will receive @@ -1170,12 +1182,12 @@ LINPHONE_PUBLIC LinphoneCall *linphone_core_get_current_call(const LinphoneCore * @param[in] call The LinphoneCall object representing the call to be answered * @return 0 on success, -1 on failure * @ingroup call_control - * @deprecated Use linphone_call_accept() instead + * @deprecated Use #linphone_call_accept() instead. Deprecated since 2017-02-13. **/ LINPHONE_PUBLIC LINPHONE_DEPRECATED LinphoneStatus linphone_core_accept_call(LinphoneCore *lc, LinphoneCall *call); /** - * Accept an incoming call, with parameters. + * @brief Accept an incoming call, with parameters. * * Basically the application is notified of incoming calls within the * call_state_changed callback of the #LinphoneCoreVTable structure, where it will receive @@ -1187,12 +1199,13 @@ LINPHONE_PUBLIC LINPHONE_DEPRECATED LinphoneStatus linphone_core_accept_call(Lin * @param[in] params The specific parameters for this call, for example whether video is accepted or not. Use NULL to use default parameters * @return 0 on success, -1 on failure * @ingroup call_control - * @deprecated Use linphone_call_accept_with_params() instead + * @deprecated Use #linphone_call_accept_with_params() instead. Deprecated since 2017-02-13. **/ LINPHONE_PUBLIC LINPHONE_DEPRECATED LinphoneStatus linphone_core_accept_call_with_params(LinphoneCore *lc, LinphoneCall *call, const LinphoneCallParams *params); /** - * When receiving an incoming, accept to start a media session as early-media. + * @brief When receiving an incoming, accept to start a media session as early-media. + * * This means the call is not accepted but audio & video streams can be established if the remote party supports early media. * However, unlike after call acceptance, mic and camera input are not sent during early-media, though received audio & video are played normally. * The call can then later be fully accepted using linphone_core_accept_call() or linphone_core_accept_call_with_params(). @@ -1201,29 +1214,31 @@ LINPHONE_PUBLIC LINPHONE_DEPRECATED LinphoneStatus linphone_core_accept_call_wit * @param[in] params The call parameters to use (can be NULL) * @return 0 if successful, -1 otherwise * @ingroup call_control - * @deprecated Use linphone_call_accept_early_media_with_params() instead + * @deprecated Use linphone_call_accept_early_media_with_params() instead. **/ LINPHONE_PUBLIC LINPHONE_DEPRECATED LinphoneStatus linphone_core_accept_early_media_with_params(LinphoneCore* lc, LinphoneCall* call, const LinphoneCallParams* params); /** - * Accept an early media session for an incoming call. + * @brief Accept an early media session for an incoming call. + * * This is identical as calling linphone_core_accept_early_media_with_params() with NULL call parameters. * @param[in] lc LinphoneCore object * @param[in] call The incoming call to accept * @return 0 if successful, -1 otherwise * @ingroup call_control * @see linphone_core_accept_early_media_with_params() - * @deprecated Use linphone_call_accept_early_media() instead + * @deprecated Use #linphone_call_accept_early_media() instead. Deprecated since 2017-02-13. **/ LINPHONE_PUBLIC LINPHONE_DEPRECATED LinphoneStatus linphone_core_accept_early_media(LinphoneCore* lc, LinphoneCall* call); /** - * Terminates a call. + * @brief Terminates a call. + * * @param[in] lc LinphoneCore object * @param[in] call The LinphoneCall object representing the call to be terminated * @return 0 on success, -1 on failure * @ingroup call_control - * @deprecated Use linphone_call_terminate() instead + * @deprecated Use #linphone_call_terminate() instead. Deprecated since 2017-02-13. **/ LINPHONE_PUBLIC LINPHONE_DEPRECATED LinphoneStatus linphone_core_terminate_call(LinphoneCore *lc, LinphoneCall *call); @@ -1234,18 +1249,18 @@ LINPHONE_PUBLIC LINPHONE_DEPRECATED LinphoneStatus linphone_core_terminate_call( * @param[in] redirect_uri The URI to redirect the call to * @return 0 if successful, -1 on error. * @ingroup call_control - * @deprecated Use linphone_call_redirect() instead + * @deprecated Use #linphone_call_redirect() instead. Deprecated since 2017-02-13. */ LINPHONE_PUBLIC LINPHONE_DEPRECATED LinphoneStatus linphone_core_redirect_call(LinphoneCore *lc, LinphoneCall *call, const char *redirect_uri); /** - * Decline a pending incoming call, with a reason. - * @param[in] lc LinphoneCore object - * @param[in] call The LinphoneCall to decline, must be in the IncomingReceived state - * @param[in] reason The reason for rejecting the call: LinphoneReasonDeclined or LinphoneReasonBusy + * @brief Decline a pending incoming call, with a reason. + * @param[in] lc #LinphoneCore object + * @param[in] call The #LinphoneCall to decline, must be in the IncomingReceived state + * @param[in] reason The reason for rejecting the call: #LinphoneReasonDeclined or #LinphoneReasonBusy * @return 0 on success, -1 on failure * @ingroup call_control - * @deprecated Use linphone_call_decline() instead + * @deprecated Use #linphone_call_decline() instead. Deprecated since 2017-02-13. **/ LINPHONE_PUBLIC LINPHONE_DEPRECATED LinphoneStatus linphone_core_decline_call(LinphoneCore *lc, LinphoneCall * call, LinphoneReason reason); @@ -1258,15 +1273,16 @@ LINPHONE_PUBLIC LINPHONE_DEPRECATED LinphoneStatus linphone_core_decline_call(Li LINPHONE_PUBLIC LinphoneStatus linphone_core_terminate_all_calls(LinphoneCore *lc); /** - * Pauses the call. If a music file has been setup using linphone_core_set_play_file(), + * @biref Pauses the call. If a music file has been setup using linphone_core_set_play_file(), * this file will be played to the remote user. + * * The only way to resume a paused call is to call linphone_core_resume_call(). * @param[in] lc LinphoneCore object * @param[in] call The call to pause * @return 0 on success, -1 on failure * @ingroup call_control * @see linphone_core_resume_call() - * @deprecated Use linphone_call_pause() instead + * @deprecated Use #linphone_call_pause() instead. Deprecated since 2017-02-13. **/ LINPHONE_PUBLIC LINPHONE_DEPRECATED LinphoneStatus linphone_core_pause_call(LinphoneCore *lc, LinphoneCall *call); @@ -1279,19 +1295,21 @@ LINPHONE_PUBLIC LINPHONE_DEPRECATED LinphoneStatus linphone_core_pause_call(Linp LINPHONE_PUBLIC LinphoneStatus linphone_core_pause_all_calls(LinphoneCore *lc); /** - * Resumes a call. + * @brief Resumes a call. + * * The call needs to have been paused previously with linphone_core_pause_call(). * @param[in] lc LinphoneCore object * @param[in] call The call to resume * @return 0 on success, -1 on failure * @ingroup call_control * @see linphone_core_pause_call() - * @deprecated Use linphone_call_resume() instead + * @deprecated Use #linphone_call_resume() instead. Deprecated since 2017-02-13. **/ LINPHONE_PUBLIC LINPHONE_DEPRECATED LinphoneStatus linphone_core_resume_call(LinphoneCore *lc, LinphoneCall *call); /** - * Updates a running call according to supplied call parameters or parameters changed in the LinphoneCore. + * @brief Updates a running call according to supplied call parameters or parameters changed in the LinphoneCore. + * * In this version this is limited to the following use cases: * - setting up/down the video stream according to the video parameter of the LinphoneCallParams (see linphone_call_params_enable_video() ). * - changing the size of the transmitted video after calling linphone_core_set_preferred_video_size() @@ -1304,7 +1322,7 @@ LINPHONE_PUBLIC LINPHONE_DEPRECATED LinphoneStatus linphone_core_resume_call(Lin * @param[in] params The new call parameters to use (may be NULL) * @return 0 if successful, -1 otherwise. * @ingroup call_control - * @deprecated Use linphone_call_update() instead + * @deprecated Use #linphone_call_update() instead. Deprecated since 2017-02-13. **/ LINPHONE_PUBLIC LINPHONE_DEPRECATED LinphoneStatus linphone_core_update_call(LinphoneCore *lc, LinphoneCall *call, const LinphoneCallParams *params); @@ -1333,7 +1351,7 @@ LINPHONE_PUBLIC LINPHONE_DEPRECATED LinphoneStatus linphone_core_update_call(Lin LINPHONE_PUBLIC LINPHONE_DEPRECATED LinphoneStatus linphone_core_defer_call_update(LinphoneCore *lc, LinphoneCall *call); /** - * Accept call modifications initiated by other end. + * @brief Accept call modifications initiated by other end. * * This call may be performed in response to a #LinphoneCallUpdatedByRemote state notification. * When such notification arrives, the application can decide to call linphone_core_defer_update_call() so that it can @@ -1350,7 +1368,7 @@ LINPHONE_PUBLIC LINPHONE_DEPRECATED LinphoneStatus linphone_core_defer_call_upda * @param[in] params A LinphoneCallParams object describing the call parameters to accept * @return 0 if successful, -1 otherwise (actually when this function call is performed outside ot #LinphoneCallUpdatedByRemote state) * @ingroup call_control - * @deprecated Use linphone_call_accept_update() instead + * @deprecated Use #linphone_call_accept_update() instead. Deprecated since 2017-02-13. **/ LINPHONE_PUBLIC LINPHONE_DEPRECATED LinphoneStatus linphone_core_accept_call_update(LinphoneCore *lc, LinphoneCall *call, const LinphoneCallParams *params); @@ -1386,13 +1404,13 @@ LINPHONE_PUBLIC LinphoneCall *linphone_core_get_call_by_remote_address2(const Li /** - * Send the specified dtmf. + * @brief Send the specified dtmf. * - * @ingroup media_parameters - * @deprecated Use #linphone_call_send_dtmf instead. * This function only works during calls. The dtmf is automatically played to the user. * @param lc The LinphoneCore object * @param dtmf The dtmf name specified as a char, such as '0', '#' etc... + * @deprecated Use #linphone_call_send_dtmf instead. Deprecated since 2015-11-23. + * @ingroup media_parameters * @donotwrap **/ LINPHONE_PUBLIC LINPHONE_DEPRECATED void linphone_core_send_dtmf(LinphoneCore *lc, char dtmf); From f6f3557d88aafa74190d2a3c2b5d0a225c2440fe Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Wed, 4 Apr 2018 15:42:31 +0200 Subject: [PATCH 64/67] Fixed an issue in CPIM tester --- tester/cpim-tester.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tester/cpim-tester.cpp b/tester/cpim-tester.cpp index 74eb70524..66cc661d8 100644 --- a/tester/cpim-tester.cpp +++ b/tester/cpim-tester.cpp @@ -428,7 +428,7 @@ static void cpim_chat_message_modifier_base(bool_t use_multipart) { marieMessage->send(); BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneMessageReceived,1)); - BC_ASSERT_STRING_EQUAL(marieMessage->getInternalContent().getContentType().asString().c_str(), ""); // Internal content is cleaned after message is sent or received + BC_ASSERT_TRUE(marieMessage->getInternalContent().getContentType().isEmpty()); // Internal content is cleaned after message is sent or received BC_ASSERT_PTR_NOT_NULL(pauline->stat.last_received_chat_message); if (pauline->stat.last_received_chat_message != NULL) { From 797d7e3f64e88c2562c2134dde0df85aa5339ae8 Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Wed, 4 Apr 2018 15:51:47 +0200 Subject: [PATCH 65/67] Fixed another CPIM issue --- src/chat/cpim/message/cpim-message.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/chat/cpim/message/cpim-message.cpp b/src/chat/cpim/message/cpim-message.cpp index 84753f4ef..123ef6c66 100644 --- a/src/chat/cpim/message/cpim-message.cpp +++ b/src/chat/cpim/message/cpim-message.cpp @@ -149,9 +149,11 @@ string Cpim::Message::asString () const { string output; // TODO: Remove cpimHeaders - for (const auto &cpimHeader : *d->cpimHeaders) - output += cpimHeader->asString(); - output += "\r\n"; + if (d->cpimHeaders->size() > 0) { + for (const auto &cpimHeader : *d->cpimHeaders) + output += cpimHeader->asString(); + output += "\r\n"; + } // TODO Remove cpimHeaders if (d->messageHeaders->size() > 0) { From 3761d1a5d90bdaa2e0bd5bca3e763badedfa9c99 Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Wed, 4 Apr 2018 16:52:51 +0200 Subject: [PATCH 66/67] Fixed compil --- coreapi/logging.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/coreapi/logging.c b/coreapi/logging.c index e39ae0012..8a87b8264 100644 --- a/coreapi/logging.c +++ b/coreapi/logging.c @@ -196,7 +196,7 @@ void linphone_logging_service_set_log_level(LinphoneLoggingService *log_service, void linphone_logging_service_set_log_level_mask(LinphoneLoggingService *log_service, unsigned int mask) { const char **domain; for (domain=_linphone_logging_service_log_domains; *domain; domain++) { - bctbx_set_log_level_mask(*domain, _linphone_log_mask_to_bctbx_log_mask(mask)); + bctbx_set_log_level_mask(*domain, (int)_linphone_log_mask_to_bctbx_log_mask(mask)); } } From 2686dca63a47a21ee075d23b5b2179ee6fc2e92f Mon Sep 17 00:00:00 2001 From: Jehan Monnier Date: Thu, 5 Apr 2018 12:08:44 +0200 Subject: [PATCH 67/67] Revert "Merge branch 'dev_content_cpp' into dev_refactor_cpp" This reverts commit d7890dbe7407993e665c3b5868fbb960c758b139, reversing changes made to e6158d8da50eefcbe0625fc32651962871f75313. --- coreapi/CMakeLists.txt | 1 + coreapi/Makefile.am | 1 + coreapi/bellesip_sal/sal_impl.c | 32 -- coreapi/callbacks.c | 3 +- coreapi/content.c | 243 +++++++++++++ coreapi/friendlist.c | 3 +- coreapi/info.c | 1 - coreapi/lime.c | 9 +- coreapi/linphonecore.c | 4 +- coreapi/private_structs.h | 11 + coreapi/proxy.c | 1 - coreapi/quality_reporting.c | 2 - include/CMakeLists.txt | 2 +- include/linphone/Makefile.am | 1 + include/linphone/api/c-api.h | 7 +- include/linphone/api/c-chat-room.h | 2 +- include/linphone/api/c-types.h | 6 - .../linphone/{api/c-content.h => content.h} | 64 ++-- include/linphone/core.h | 1 + include/linphone/types.h | 6 + src/CMakeLists.txt | 6 - src/c-wrapper/api/c-chat-message.cpp | 7 +- src/c-wrapper/api/c-chat-room.cpp | 4 +- src/c-wrapper/api/c-content.cpp | 331 ------------------ src/c-wrapper/c-wrapper.h | 2 +- src/c-wrapper/internal/c-sal.h | 5 - src/chat/chat-message/chat-message-p.h | 8 +- src/chat/chat-message/chat-message.cpp | 77 ++-- src/chat/chat-message/chat-message.h | 6 +- src/chat/chat-room/abstract-chat-room.h | 3 +- src/chat/chat-room/chat-room.cpp | 6 +- src/chat/chat-room/chat-room.h | 3 +- src/chat/chat-room/proxy-chat-room.cpp | 2 +- src/chat/chat-room/proxy-chat-room.h | 3 +- src/chat/cpim/message/cpim-message.cpp | 8 +- .../modifier/cpim-chat-message-modifier.cpp | 2 +- .../file-transfer-chat-message-modifier.cpp | 77 ++-- .../multipart-chat-message-modifier.cpp | 102 ++++-- .../local-conference-event-handler.cpp | 5 +- src/conference/session/call-session.cpp | 7 +- src/content/content-manager.cpp | 101 ++++-- src/content/content-manager.h | 2 +- src/content/content-p.h | 4 +- src/content/content-type.cpp | 76 ++-- src/content/content-type.h | 12 +- src/content/content.cpp | 38 +- src/content/content.h | 11 +- src/content/file-content.cpp | 30 +- src/content/file-content.h | 7 +- src/content/file-transfer-content.cpp | 35 +- src/content/file-transfer-content.h | 11 +- src/content/header/header-p.h | 43 --- src/content/header/header-param.cpp | 108 ------ src/content/header/header-param.h | 61 ---- src/content/header/header.cpp | 183 ---------- src/content/header/header.h | 74 ---- src/db/main-db.cpp | 2 +- src/sal/op.cpp | 8 +- tester/CMakeLists.txt | 2 +- ...-tester.cpp => content-manager-tester.cpp} | 172 +-------- tester/cpim-tester.cpp | 4 +- tester/eventapi_tester.c | 2 +- tester/liblinphone_tester.h | 2 +- tester/message_tester.c | 8 +- tester/multipart-tester.cpp | 27 +- tester/presence_server_tester.c | 9 +- tester/tester.c | 2 +- 67 files changed, 687 insertions(+), 1411 deletions(-) create mode 100644 coreapi/content.c rename include/linphone/{api/c-content.h => content.h} (83%) delete mode 100644 src/c-wrapper/api/c-content.cpp delete mode 100644 src/content/header/header-p.h delete mode 100644 src/content/header/header-param.cpp delete mode 100644 src/content/header/header-param.h delete mode 100644 src/content/header/header.cpp delete mode 100644 src/content/header/header.h rename tester/{contents-tester.cpp => content-manager-tester.cpp} (62%) diff --git a/coreapi/CMakeLists.txt b/coreapi/CMakeLists.txt index 2effcf5ec..85e13205c 100644 --- a/coreapi/CMakeLists.txt +++ b/coreapi/CMakeLists.txt @@ -64,6 +64,7 @@ set(LINPHONE_SOURCE_FILES_C carddav.c chat.c contactprovider.c + content.c dial_plan.c dict.c ec-calibrator.c diff --git a/coreapi/Makefile.am b/coreapi/Makefile.am index c2b2ee53b..4e63d8879 100644 --- a/coreapi/Makefile.am +++ b/coreapi/Makefile.am @@ -39,6 +39,7 @@ liblinphone_la_SOURCES=\ chat_file_transfer.c \ conference.cc conference_private.h \ contactprovider.c contact_providers_priv.h \ + content.c \ dial_plan.c \ dict.c \ ec-calibrator.c \ diff --git a/coreapi/bellesip_sal/sal_impl.c b/coreapi/bellesip_sal/sal_impl.c index bdf3683dd..ad11525fb 100644 --- a/coreapi/bellesip_sal/sal_impl.c +++ b/coreapi/bellesip_sal/sal_impl.c @@ -348,29 +348,6 @@ void sal_body_handler_set_subtype(SalBodyHandler *body_handler, const char *subt belle_sip_header_content_type_set_subtype(content_type, subtype); } -const belle_sip_list_t * sal_body_handler_get_content_type_parameters_names(const SalBodyHandler *body_handler) { - belle_sip_header_content_type_t *content_type = BELLE_SIP_HEADER_CONTENT_TYPE(sal_body_handler_find_header(body_handler, "Content-Type")); - if (content_type != NULL) { - return belle_sip_parameters_get_parameter_names(BELLE_SIP_PARAMETERS(content_type)); - } - return NULL; -} - -const char * sal_body_handler_get_content_type_parameter(const SalBodyHandler *body_handler, const char *name) { - belle_sip_header_content_type_t *content_type = BELLE_SIP_HEADER_CONTENT_TYPE(sal_body_handler_find_header(body_handler, "Content-Type")); - if (content_type != NULL) { - return belle_sip_parameters_get_parameter(BELLE_SIP_PARAMETERS(content_type), name); - } - return NULL; -} - -void sal_body_handler_set_content_type_parameter(SalBodyHandler *body_handler, const char *paramName, const char *paramValue) { - belle_sip_header_content_type_t *content_type = BELLE_SIP_HEADER_CONTENT_TYPE(sal_body_handler_find_header(body_handler, "Content-Type")); - if (content_type != NULL) { - belle_sip_parameters_set_parameter(BELLE_SIP_PARAMETERS(content_type), paramName, paramValue); - } -} - const char * sal_body_handler_get_encoding(const SalBodyHandler *body_handler) { belle_sip_header_t *content_encoding = sal_body_handler_find_header(body_handler, "Content-Encoding"); if (content_encoding != NULL) { @@ -419,11 +396,6 @@ SalBodyHandler * sal_body_handler_get_part(const SalBodyHandler *body_handler, i return (SalBodyHandler *)belle_sip_list_nth_data(l, idx); } -const belle_sip_list_t * sal_body_handler_get_parts(const SalBodyHandler *body_handler) { - if (!sal_body_handler_is_multipart(body_handler)) return NULL; - return belle_sip_multipart_body_handler_get_parts(BELLE_SIP_MULTIPART_BODY_HANDLER(body_handler)); -} - SalBodyHandler * sal_body_handler_find_part_by_header(const SalBodyHandler *body_handler, const char *header_name, const char *header_value) { const belle_sip_list_t *l = belle_sip_multipart_body_handler_get_parts(BELLE_SIP_MULTIPART_BODY_HANDLER(body_handler)); for (; l != NULL; l = l->next) { @@ -446,7 +418,3 @@ const char * sal_body_handler_get_header(const SalBodyHandler *body_handler, con } return NULL; } - -const belle_sip_list_t* sal_body_handler_get_headers(const SalBodyHandler *body_handler) { - return belle_sip_body_handler_get_headers(BELLE_SIP_BODY_HANDLER(body_handler)); -} diff --git a/coreapi/callbacks.c b/coreapi/callbacks.c index 126cb41d2..da809bc05 100644 --- a/coreapi/callbacks.c +++ b/coreapi/callbacks.c @@ -17,15 +17,14 @@ along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + #include "c-wrapper/internal/c-sal.h" #include "sal/call-op.h" #include "sal/message-op.h" #include "sal/refer-op.h" -#include "linphone/api/c-content.h" #include "linphone/core.h" #include "linphone/utils/utils.h" - #include "private.h" #include "mediastreamer2/mediastream.h" #include "linphone/lpconfig.h" diff --git a/coreapi/content.c b/coreapi/content.c new file mode 100644 index 000000000..8d20964bd --- /dev/null +++ b/coreapi/content.c @@ -0,0 +1,243 @@ +/* +linphone +Copyright (C) 2010-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 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, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "linphone/core.h" + +#include "c-wrapper/c-wrapper.h" + +// TODO: From coreapi. Remove me later. +#include "private.h" + +static void linphone_content_set_sal_body_handler(LinphoneContent *content, SalBodyHandler *body_handler) { + if (content->body_handler != NULL) { + sal_body_handler_unref(content->body_handler); + content->body_handler = NULL; + } + content->body_handler = sal_body_handler_ref(body_handler); +} + +static LinphoneContent * linphone_content_new_with_body_handler(SalBodyHandler *body_handler) { + LinphoneContent *content = belle_sip_object_new(LinphoneContent); + belle_sip_object_ref(content); + content->owned_fields = TRUE; + content->cryptoContext = NULL; /* this field is managed externally by encryption/decryption functions so be careful to initialise it to NULL */ + if (body_handler == NULL) { + linphone_content_set_sal_body_handler(content, sal_body_handler_new()); + } else { + linphone_content_set_sal_body_handler(content, body_handler); + } + return content; +} + +static void linphone_content_destroy(LinphoneContent *content) { + if (content->owned_fields == TRUE) { + if (content->body_handler) sal_body_handler_unref(content->body_handler); + if (content->name) belle_sip_free(content->name); + if (content->key) belle_sip_free(content->key); + /* note : crypto context is allocated/destroyed by the encryption function */ + } +} + +static void linphone_content_clone(LinphoneContent *obj, const LinphoneContent *ref) { + obj->owned_fields = TRUE; + linphone_content_set_sal_body_handler(obj, sal_body_handler_new()); + if ((linphone_content_get_type(ref) != NULL) || (linphone_content_get_subtype(ref) != NULL)) { + linphone_content_set_type(obj, linphone_content_get_type(ref)); + linphone_content_set_subtype(obj, linphone_content_get_subtype(ref)); + } + if (linphone_content_get_encoding(ref) != NULL) { + linphone_content_set_encoding(obj, linphone_content_get_encoding(ref)); + } + linphone_content_set_name(obj, linphone_content_get_name(ref)); + linphone_content_set_key(obj, linphone_content_get_key(ref), linphone_content_get_key_size(ref)); + if (linphone_content_get_buffer(ref) != NULL) { + linphone_content_set_buffer(obj, linphone_content_get_buffer(ref), linphone_content_get_size(ref)); + } else { + linphone_content_set_size(obj, linphone_content_get_size(ref)); + } +} + + +BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(LinphoneContent); + +BELLE_SIP_INSTANCIATE_VPTR(LinphoneContent, belle_sip_object_t, + (belle_sip_object_destroy_t)linphone_content_destroy, + (belle_sip_object_clone_t)linphone_content_clone, + NULL, // marshal + TRUE +); + + +LinphoneContent * linphone_core_create_content(LinphoneCore *lc) { + return linphone_content_new(); +} + +LinphoneContent * linphone_content_ref(LinphoneContent *content) { + belle_sip_object_ref(content); + return content; +} + +void linphone_content_unref(LinphoneContent *content) { + belle_sip_object_unref(content); +} + +void *linphone_content_get_user_data(const LinphoneContent *content) { + return content->user_data; +} + +void linphone_content_set_user_data(LinphoneContent *content, void *ud) { + content->user_data = ud; +} + +const char * linphone_content_get_type(const LinphoneContent *content) { + return sal_body_handler_get_type(content->body_handler); +} + +void linphone_content_set_type(LinphoneContent *content, const char *type) { + sal_body_handler_set_type(content->body_handler, type); +} + +const char * linphone_content_get_subtype(const LinphoneContent *content) { + return sal_body_handler_get_subtype(content->body_handler); +} + +void linphone_content_set_subtype(LinphoneContent *content, const char *subtype) { + sal_body_handler_set_subtype(content->body_handler, subtype); +} + +uint8_t * linphone_content_get_buffer(const LinphoneContent *content) { + return (uint8_t *)sal_body_handler_get_data(content->body_handler); +} + +void linphone_content_set_buffer(LinphoneContent *content, const uint8_t *buffer, size_t size) { + void *data; + sal_body_handler_set_size(content->body_handler, size); + data = belle_sip_malloc(size + 1); + memcpy(data, buffer, size); + ((char *)data)[size] = '\0'; + sal_body_handler_set_data(content->body_handler, data); +} + +const char * linphone_content_get_string_buffer(const LinphoneContent *content) { + return (const char *)linphone_content_get_buffer(content); +} + +void linphone_content_set_string_buffer(LinphoneContent *content, const char *buffer) { + sal_body_handler_set_size(content->body_handler, strlen(buffer)); + sal_body_handler_set_data(content->body_handler, belle_sip_strdup(buffer)); +} + +size_t linphone_content_get_size(const LinphoneContent *content) { + return sal_body_handler_get_size(content->body_handler); +} + +void linphone_content_set_size(LinphoneContent *content, size_t size) { + sal_body_handler_set_size(content->body_handler, size); +} + +const char * linphone_content_get_encoding(const LinphoneContent *content) { + return sal_body_handler_get_encoding(content->body_handler); +} + +void linphone_content_set_encoding(LinphoneContent *content, const char *encoding) { + sal_body_handler_set_encoding(content->body_handler, encoding); +} + +const char * linphone_content_get_name(const LinphoneContent *content) { + return content->name; +} + +void linphone_content_set_name(LinphoneContent *content, const char *name) { + if (content->name != NULL) { + belle_sip_free(content->name); + content->name = NULL; + } + if (name != NULL) { + content->name = belle_sip_strdup(name); + } +} + +size_t linphone_content_get_key_size(const LinphoneContent *content) { + return content->keyLength; +} + +const char * linphone_content_get_key(const LinphoneContent *content) { + return content->key; +} + +void linphone_content_set_key(LinphoneContent *content, const char *key, const size_t keyLength) { + if (content->key != NULL) { + belle_sip_free(content->key); + content->key = NULL; + } + if (key != NULL) { + content->key = reinterpret_cast(belle_sip_malloc(keyLength + 1)); + memcpy(content->key, key, keyLength); + content->key[keyLength] = '\0'; + content->keyLength = keyLength; + } +} + +/* crypto context is managed(allocated/freed) by the encryption function, so provide the address of field in the private structure */ +void ** linphone_content_get_cryptoContext_address(LinphoneContent *content) { + return &(content->cryptoContext); +} + +bool_t linphone_content_is_multipart(const LinphoneContent *content) { + return sal_body_handler_is_multipart(content->body_handler); +} + +LinphoneContent * linphone_content_get_part(const LinphoneContent *content, int idx) { + SalBodyHandler *part_body_handler; + if (!linphone_content_is_multipart(content)) return NULL; + part_body_handler = sal_body_handler_get_part(content->body_handler, idx); + return linphone_content_from_sal_body_handler(part_body_handler); +} + +LinphoneContent * linphone_content_find_part_by_header(const LinphoneContent *content, const char *header_name, const char *header_value) { + SalBodyHandler *part_body_handler; + if (!linphone_content_is_multipart(content)) return NULL; + part_body_handler = sal_body_handler_find_part_by_header(content->body_handler, header_name, header_value); + return linphone_content_from_sal_body_handler(part_body_handler); +} + +const char * linphone_content_get_custom_header(const LinphoneContent *content, const char *header_name) { + return sal_body_handler_get_header(content->body_handler, header_name); +} + + +LinphoneContent * linphone_content_new(void) { + return linphone_content_new_with_body_handler(NULL); +} + +LinphoneContent * linphone_content_copy(const LinphoneContent *ref) { + return (LinphoneContent *)belle_sip_object_ref(belle_sip_object_clone(BELLE_SIP_OBJECT(ref))); +} + +LinphoneContent * linphone_content_from_sal_body_handler(SalBodyHandler *body_handler) { + if (body_handler) { + return linphone_content_new_with_body_handler(body_handler); + } + return NULL; +} + +SalBodyHandler * sal_body_handler_from_content(const LinphoneContent *content) { + if (content == NULL) return NULL; + return content->body_handler; +} diff --git a/coreapi/friendlist.c b/coreapi/friendlist.c index 6f196721e..5e9ca2abf 100644 --- a/coreapi/friendlist.c +++ b/coreapi/friendlist.c @@ -19,7 +19,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include -#include "linphone/api/c-content.h" #include "linphone/core.h" #include "c-wrapper/c-wrapper.h" @@ -962,7 +961,7 @@ void linphone_friend_list_notify_presence_received(LinphoneFriendList *list, Lin const char *subtype = linphone_content_get_subtype(body); if ((strcmp(type, "multipart") != 0) || (strcmp(subtype, "related") != 0)) { - ms_warning("multipart presence notified but it is not 'multipart/related', instead is '%s/%s'", type, subtype); + ms_warning("multipart presence notified but it is not 'multipart/related'"); return; } diff --git a/coreapi/info.c b/coreapi/info.c index f68bb4522..5b12089bb 100644 --- a/coreapi/info.c +++ b/coreapi/info.c @@ -23,7 +23,6 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include "linphone/api/c-content.h" #include "linphone/core.h" #include "linphone/lpconfig.h" diff --git a/coreapi/lime.c b/coreapi/lime.c index cdf697b95..4270f9d2a 100644 --- a/coreapi/lime.c +++ b/coreapi/lime.c @@ -17,8 +17,6 @@ along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#include "linphone/api/c-content.h" - #include "lime.h" #ifdef HAVE_CONFIG_H #include "config.h" @@ -421,8 +419,6 @@ int lime_encryptFile(void **cryptoContext, unsigned char *key, size_t length, ch int lime_decryptFile(void **cryptoContext, unsigned char *key, size_t length, char *plain, char *cipher) { bctbx_aes_gcm_context_t *gcmContext; - if (key == NULL) return -1; - if (*cryptoContext == NULL) { /* first call to the function, allocate a crypto context and initialise it */ /* key contains 192bits of key || 64 bits of Initialisation Vector, no additional data */ gcmContext = bctbx_aes_gcm_context_new(key, 24, NULL, 0, key+24, 8, BCTBX_GCM_DECRYPT); @@ -791,8 +787,8 @@ int lime_im_encryption_engine_process_incoming_message_cb(LinphoneImEncryptionEn LinphoneCore *lc = linphone_im_encryption_engine_get_core(engine); int errcode = -1; /* check if we have a xml/cipher message to be decrypted */ - if (linphone_chat_message_get_content_type(msg) && - (strcmp("xml/cipher", linphone_chat_message_get_content_type(msg)) == 0 || + if (linphone_chat_message_get_content_type(msg) && + (strcmp("xml/cipher", linphone_chat_message_get_content_type(msg)) == 0 || strcmp("application/cipher.vnd.gsma.rcs-ft-http+xml", linphone_chat_message_get_content_type(msg)) == 0)) { errcode = 0; int retval; @@ -897,7 +893,6 @@ int lime_im_encryption_engine_process_downloading_file_cb(LinphoneImEncryptionEn LinphoneContent *content = linphone_chat_message_get_file_transfer_information(msg); if (!content) return -1; - if (!linphone_content_get_key(content)) { linphone_content_unref(content); return -1; diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index 4a052feca..b0a4347fe 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -18,12 +18,10 @@ along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#include "linphone/api/c-content.h" #include "linphone/core.h" +#include "linphone/sipsetup.h" #include "linphone/lpconfig.h" #include "linphone/logging.h" -#include "linphone/sipsetup.h" - #include "private.h" #include "logging-private.h" #include "quality_reporting.h" diff --git a/coreapi/private_structs.h b/coreapi/private_structs.h index 6b6486ab8..3bcfc4d78 100644 --- a/coreapi/private_structs.h +++ b/coreapi/private_structs.h @@ -449,6 +449,17 @@ struct _EchoTester { unsigned int rate; }; +struct _LinphoneContent { + belle_sip_object_t base; + void *user_data; + SalBodyHandler *body_handler; + char *name; /**< used by RCS File transfer messages to store the original filename of the file to be downloaded from server */ + char *key; /**< used by RCS File transfer messages to store the key to encrypt file if needed */ + size_t keyLength; /**< Length of key in bytes */ + void *cryptoContext; /**< crypto context used to encrypt file for RCS file transfer */ + bool_t owned_fields; +}; + BELLE_SIP_DECLARE_VPTR_NO_EXPORT(LinphoneContent); struct _LinphoneBuffer { diff --git a/coreapi/proxy.c b/coreapi/proxy.c index b797e1d0b..03213da1e 100644 --- a/coreapi/proxy.c +++ b/coreapi/proxy.c @@ -25,7 +25,6 @@ Copyright (C) 2000 Simon MORLAT (simon.morlat@linphone.org) #include "linphone/core.h" #include "linphone/lpconfig.h" #include "linphone/sipsetup.h" - #include "mediastreamer2/mediastream.h" #include "enum.h" diff --git a/coreapi/quality_reporting.c b/coreapi/quality_reporting.c index a20b03b8e..571a8faa0 100644 --- a/coreapi/quality_reporting.c +++ b/coreapi/quality_reporting.c @@ -21,9 +21,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "config.h" #endif -#include "linphone/api/c-content.h" #include "linphone/core.h" - #include "private.h" #include "c-wrapper/internal/c-sal.h" #include "sal/sal.h" diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt index 04aee8ddd..2e09af5eb 100644 --- a/include/CMakeLists.txt +++ b/include/CMakeLists.txt @@ -33,6 +33,7 @@ set(ROOT_HEADER_FILES chat.h conference.h contactprovider.h + content.h core_utils.h core.h defs.h @@ -84,7 +85,6 @@ set(C_API_HEADER_FILES c-chat-message.h c-chat-room-cbs.h c-chat-room.h - c-content.h c-dial-plan.h c-event-log.h c-magic-search.h diff --git a/include/linphone/Makefile.am b/include/linphone/Makefile.am index 56c2c3dda..dc9488e0b 100644 --- a/include/linphone/Makefile.am +++ b/include/linphone/Makefile.am @@ -14,6 +14,7 @@ linphone_include_HEADERS=\ chat.h \ conference.h \ contactprovider.h \ + content.h \ core.h \ core_utils.h \ defs.h \ diff --git a/include/linphone/api/c-api.h b/include/linphone/api/c-api.h index 7044bed6a..039b55246 100644 --- a/include/linphone/api/c-api.h +++ b/include/linphone/api/c-api.h @@ -23,15 +23,14 @@ #include "linphone/utils/general.h" #include "linphone/api/c-address.h" +#include "linphone/api/c-call.h" #include "linphone/api/c-call-cbs.h" #include "linphone/api/c-call-stats.h" -#include "linphone/api/c-call.h" #include "linphone/api/c-callbacks.h" -#include "linphone/api/c-chat-message-cbs.h" #include "linphone/api/c-chat-message.h" -#include "linphone/api/c-chat-room-cbs.h" +#include "linphone/api/c-chat-message-cbs.h" #include "linphone/api/c-chat-room.h" -#include "linphone/api/c-content.h" +#include "linphone/api/c-chat-room-cbs.h" #include "linphone/api/c-dial-plan.h" #include "linphone/api/c-event-log.h" #include "linphone/api/c-participant.h" diff --git a/include/linphone/api/c-chat-room.h b/include/linphone/api/c-chat-room.h index 312a6fc6f..41f3c669e 100644 --- a/include/linphone/api/c-chat-room.h +++ b/include/linphone/api/c-chat-room.h @@ -90,7 +90,7 @@ LINPHONE_PUBLIC LinphoneChatMessage* linphone_chat_room_create_message_2(Linphon * @param initial_content #LinphoneContent initial content. #LinphoneCoreVTable.file_transfer_send is invoked later to notify file transfer progress and collect next chunk of the message if LinphoneContent.data is NULL. * @return a new #LinphoneChatMessage */ -LINPHONE_PUBLIC LinphoneChatMessage* linphone_chat_room_create_file_transfer_message(LinphoneChatRoom *cr, LinphoneContent* initial_content); +LINPHONE_PUBLIC LinphoneChatMessage* linphone_chat_room_create_file_transfer_message(LinphoneChatRoom *cr, const LinphoneContent* initial_content); /** * get peer address \link linphone_core_get_chat_room() associated to \endlink this #LinphoneChatRoom diff --git a/include/linphone/api/c-types.h b/include/linphone/api/c-types.h index b4f629101..f587b77f8 100644 --- a/include/linphone/api/c-types.h +++ b/include/linphone/api/c-types.h @@ -162,12 +162,6 @@ typedef struct _LinphoneMagicSearch LinphoneMagicSearch; **/ typedef struct _LinphoneParticipant LinphoneParticipant; -/** - * The LinphoneContent object holds data that can be embedded in a signaling message. - * @ingroup misc -**/ -typedef struct _LinphoneContent LinphoneContent; - /** * The LinphoneSearchResult object represents a result of a search * @ingroup misc diff --git a/include/linphone/api/c-content.h b/include/linphone/content.h similarity index 83% rename from include/linphone/api/c-content.h rename to include/linphone/content.h index 5cdd27663..78ebc3114 100644 --- a/include/linphone/api/c-content.h +++ b/include/linphone/content.h @@ -1,32 +1,33 @@ /* - * c-content.h - * 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, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ +content.h +Copyright (C) 2010-2014 Belledonne Communications SARL -#ifndef _L_C_CONTENT_H_ -#define _L_C_CONTENT_H_ +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. -#include "linphone/api/c-types.h" +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, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef LINPHONE_CONTENT_H_ +#define LINPHONE_CONTENT_H_ + + +#include "linphone/types.h" -// ============================================================================= #ifdef __cplusplus - extern "C" { -#endif // ifdef __cplusplus +extern "C" { +#endif + /** * @addtogroup misc @@ -88,14 +89,6 @@ LINPHONE_PUBLIC const char * linphone_content_get_subtype(const LinphoneContent */ LINPHONE_PUBLIC void linphone_content_set_subtype(LinphoneContent *content, const char *subtype); -/** - * Adds a parameter to the ContentType header. - * @param[in] content LinphoneContent object. - * @param[in] name the name of the parameter to add. - * @param[in] value the value of the parameter to add. - */ -LINPHONE_PUBLIC void linphone_content_add_content_type_parameter(LinphoneContent *content, const char *name, const char *value); - /** * Get the content data buffer, usually a string. * @param[in] content LinphoneContent object. @@ -225,8 +218,9 @@ LINPHONE_PUBLIC void linphone_content_set_key(LinphoneContent *content, const ch * @} */ -#ifdef __cplusplus - } -#endif // ifdef __cplusplus -#endif // ifndef _L_C_CONTENT_H_ \ No newline at end of file +#ifdef __cplusplus +} +#endif + +#endif /* LINPHONE_CONTENT_H_ */ diff --git a/include/linphone/core.h b/include/linphone/core.h index ff15192e9..ded8e3949 100644 --- a/include/linphone/core.h +++ b/include/linphone/core.h @@ -42,6 +42,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "linphone/call_stats.h" #include "linphone/chat.h" #include "linphone/conference.h" +#include "linphone/content.h" #include "linphone/dictionary.h" #include "linphone/error_info.h" #include "linphone/event.h" diff --git a/include/linphone/types.h b/include/linphone/types.h index 32384b498..9a8ba46c9 100644 --- a/include/linphone/types.h +++ b/include/linphone/types.h @@ -367,6 +367,12 @@ typedef unsigned int LinphoneContactSearchID; */ LINPHONE_DEPRECATED typedef LinphoneContactSearchID ContactSearchID; +/** + * The LinphoneContent object holds data that can be embedded in a signaling message. + * @ingroup misc +**/ +typedef struct _LinphoneContent LinphoneContent; + /** * Linphone core main object created by function linphone_core_new() . * @ingroup initializing diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index b7c47abf8..ca182139f 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -99,9 +99,6 @@ set(LINPHONE_CXX_OBJECTS_PRIVATE_HEADER_FILES content/content.h content/file-content.h content/file-transfer-content.h - content/header/header.h - content/header/header-p.h - content/header/header-param.h core/core-accessor.h core/core-listener.h core/core-p.h @@ -176,7 +173,6 @@ set(LINPHONE_CXX_OBJECTS_SOURCE_FILES c-wrapper/api/c-chat-room-cbs.cpp c-wrapper/api/c-chat-room.cpp c-wrapper/api/c-core.cpp - c-wrapper/api/c-content.cpp c-wrapper/api/c-dial-plan.cpp c-wrapper/api/c-event-log.cpp c-wrapper/api/c-magic-search.cpp @@ -226,8 +222,6 @@ set(LINPHONE_CXX_OBJECTS_SOURCE_FILES content/content.cpp content/file-content.cpp content/file-transfer-content.cpp - content/header/header.cpp - content/header/header-param.cpp core/core-accessor.cpp core/core-call.cpp core/core-chat-room.cpp diff --git a/src/c-wrapper/api/c-chat-message.cpp b/src/c-wrapper/api/c-chat-message.cpp index 76916ca2b..a616a9659 100644 --- a/src/c-wrapper/api/c-chat-message.cpp +++ b/src/c-wrapper/api/c-chat-message.cpp @@ -18,7 +18,6 @@ */ #include "linphone/api/c-chat-message.h" -#include "linphone/api/c-content.h" #include "linphone/utils/utils.h" #include "linphone/wrapper_utils.h" @@ -229,7 +228,7 @@ void linphone_chat_message_add_text_content(LinphoneChatMessage *msg, const char LinphonePrivate::ContentType contentType = LinphonePrivate::ContentType::PlainText; content->setContentType(contentType); content->setBody(L_C_TO_STRING(c_content)); - L_GET_CPP_PTR_FROM_C_OBJECT(msg)->addContent(content); + L_GET_CPP_PTR_FROM_C_OBJECT(msg)->addContent(*content); } bool_t linphone_chat_message_has_text_content(const LinphoneChatMessage *msg) { @@ -295,9 +294,7 @@ int linphone_chat_message_set_text(LinphoneChatMessage *msg, const char* text) { } LinphoneContent *linphone_chat_message_get_file_transfer_information(LinphoneChatMessage *msg) { - const LinphonePrivate::Content *content = L_GET_PRIVATE_FROM_C_OBJECT(msg)->getFileTransferInformation(); - if (content) return L_GET_C_BACK_PTR(content); - return NULL; + return L_GET_PRIVATE_FROM_C_OBJECT(msg)->getFileTransferInformation(); } // ============================================================================= diff --git a/src/c-wrapper/api/c-chat-room.cpp b/src/c-wrapper/api/c-chat-room.cpp index b8fa75567..e549964e0 100644 --- a/src/c-wrapper/api/c-chat-room.cpp +++ b/src/c-wrapper/api/c-chat-room.cpp @@ -355,8 +355,8 @@ const bctbx_list_t *linphone_chat_room_get_composing_addresses (LinphoneChatRoom return cr->composingAddresses; } -LinphoneChatMessage *linphone_chat_room_create_file_transfer_message(LinphoneChatRoom *cr, LinphoneContent *initial_content) { - shared_ptr cppPtr = L_GET_CPP_PTR_FROM_C_OBJECT(cr)->createFileTransferMessage(L_GET_CPP_PTR_FROM_C_OBJECT(initial_content)); +LinphoneChatMessage *linphone_chat_room_create_file_transfer_message(LinphoneChatRoom *cr, const LinphoneContent *initial_content) { + shared_ptr cppPtr = L_GET_CPP_PTR_FROM_C_OBJECT(cr)->createFileTransferMessage(initial_content); LinphoneChatMessage *object = L_INIT(ChatMessage); L_SET_CPP_PTR_FROM_C_OBJECT(object, cppPtr); return object; diff --git a/src/c-wrapper/api/c-content.cpp b/src/c-wrapper/api/c-content.cpp deleted file mode 100644 index 580c78ca3..000000000 --- a/src/c-wrapper/api/c-content.cpp +++ /dev/null @@ -1,331 +0,0 @@ -/* - * c-content.cpp - * 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, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include "linphone/api/c-content.h" -#include "linphone/wrapper_utils.h" - -#include "c-wrapper/c-wrapper.h" - -#include "content/content.h" -#include "content/content-type.h" -#include "content/header/header-param.h" -#include "content/header/header.h" -#include "content/content-manager.h" -#include "content/file-content.h" -#include "content/file-transfer-content.h" - -// ============================================================================= - -using namespace std; - -L_DECLARE_C_CLONABLE_OBJECT_IMPL(Content, - void *cryptoContext; /**< crypto context used to encrypt file for RCS file transfer */ - mutable char *name; - mutable char *type; - mutable char *subtype; - mutable char *body; - mutable size_t size; - mutable char *encoding; - mutable char *key; -) - -// ============================================================================= -// Reference and user data handling functions. -// ============================================================================= - -LinphoneContent * linphone_content_ref(LinphoneContent *content) { - belle_sip_object_ref(content); - return content; -} - -void linphone_content_unref(LinphoneContent *content) { - belle_sip_object_unref(content); -} - -void *linphone_content_get_user_data(const LinphoneContent *content) { - return L_GET_USER_DATA_FROM_C_OBJECT(content); -} - -void linphone_content_set_user_data(LinphoneContent *content, void *ud) { - return L_SET_USER_DATA_FROM_C_OBJECT(content, ud); -} - -// ============================================================================= - -const char * linphone_content_get_type(const LinphoneContent *content) { - if (content->type) ms_free(content->type); - content->type = ms_strdup(L_STRING_TO_C(L_GET_CPP_PTR_FROM_C_OBJECT(content)->getContentType().getType())); - return content->type; -} - -void linphone_content_set_type(LinphoneContent *content, const char *type) { - LinphonePrivate::ContentType ct = L_GET_CPP_PTR_FROM_C_OBJECT(content)->getContentType(); - ct.setType(L_C_TO_STRING(type)); - L_GET_CPP_PTR_FROM_C_OBJECT(content)->setContentType(ct); -} - -const char * linphone_content_get_subtype(const LinphoneContent *content) { - if (content->subtype) ms_free(content->subtype); - content->subtype = ms_strdup(L_STRING_TO_C(L_GET_CPP_PTR_FROM_C_OBJECT(content)->getContentType().getSubType())); - return content->subtype; -} - -void linphone_content_set_subtype(LinphoneContent *content, const char *subtype) { - LinphonePrivate::ContentType ct = L_GET_CPP_PTR_FROM_C_OBJECT(content)->getContentType(); - ct.setSubType(L_C_TO_STRING(subtype)); - L_GET_CPP_PTR_FROM_C_OBJECT(content)->setContentType(ct); -} - -void linphone_content_add_content_type_parameter(LinphoneContent *content, const char *name, const char *value) { - LinphonePrivate::ContentType ct = L_GET_CPP_PTR_FROM_C_OBJECT(content)->getContentType(); - ct.addParameter(L_C_TO_STRING(name), L_C_TO_STRING(value)); - L_GET_CPP_PTR_FROM_C_OBJECT(content)->setContentType(ct); -} - -uint8_t * linphone_content_get_buffer(const LinphoneContent *content) { - return (uint8_t *)linphone_content_get_string_buffer(content); -} - -void linphone_content_set_buffer(LinphoneContent *content, const uint8_t *buffer, size_t size) { - L_GET_CPP_PTR_FROM_C_OBJECT(content)->setBody(buffer, size); -} - -const char * linphone_content_get_string_buffer(const LinphoneContent *content) { - if (content->body) ms_free(content->body); - content->body = ms_strdup(L_GET_CPP_PTR_FROM_C_OBJECT(content)->getBodyAsUtf8String().c_str()); - return content->body; -} - -void linphone_content_set_string_buffer(LinphoneContent *content, const char *buffer) { - L_GET_CPP_PTR_FROM_C_OBJECT(content)->setBodyFromUtf8(L_C_TO_STRING(buffer)); -} - -size_t linphone_content_get_size(const LinphoneContent *content) { - size_t size = L_GET_CPP_PTR_FROM_C_OBJECT(content)->getSize(); - if (size == 0) { - size = content->size; - } - return size; -} - -void linphone_content_set_size(LinphoneContent *content, size_t size) { - content->size = size; -} - -const char * linphone_content_get_encoding(const LinphoneContent *content) { - return content->encoding; -} - -void linphone_content_set_encoding(LinphoneContent *content, const char *encoding) { - if (content->encoding) ms_free(content->encoding); - content->encoding = ms_strdup(encoding); -} - -const char * linphone_content_get_name(const LinphoneContent *content) { - const LinphonePrivate::Content *c = L_GET_CPP_PTR_FROM_C_OBJECT(content); - if (c->isFile()) { - const LinphonePrivate::FileContent *fc = static_cast(c); - if (content->name) ms_free(content->name); - content->name = ms_strdup(L_STRING_TO_C(fc->getFileName())); - } else if (c->isFileTransfer()) { - const LinphonePrivate::FileTransferContent *ftc = static_cast(c); - if (content->name) ms_free(content->name); - content->name = ms_strdup(L_STRING_TO_C(ftc->getFileName())); - } - return content->name; -} - -void linphone_content_set_name(LinphoneContent *content, const char *name) { - if (content->name) ms_free(content->name); - - LinphonePrivate::Content *c = L_GET_CPP_PTR_FROM_C_OBJECT(content); - if (c->isFile()) { - LinphonePrivate::FileContent *fc = static_cast(c); - fc->setFileName(L_C_TO_STRING(name)); - } else if (c->isFileTransfer()) { - LinphonePrivate::FileTransferContent *ftc = static_cast(c); - ftc->setFileName(L_C_TO_STRING(name)); - } - - content->name = ms_strdup(name); -} - -bool_t linphone_content_is_multipart(const LinphoneContent *content) { - return L_GET_CPP_PTR_FROM_C_OBJECT(content)->getContentType().isMultipart(); -} - -LinphoneContent * linphone_content_get_part(const LinphoneContent *content, int idx) { - SalBodyHandler *part_body_handler; - SalBodyHandler *body_handler = sal_body_handler_from_content(content); - if (!sal_body_handler_is_multipart(body_handler)) { - sal_body_handler_unref(body_handler); - return NULL; - } - part_body_handler = sal_body_handler_get_part(body_handler, idx); - LinphoneContent *result = linphone_content_from_sal_body_handler(part_body_handler); - sal_body_handler_unref(body_handler); - return result; -} - -LinphoneContent * linphone_content_find_part_by_header(const LinphoneContent *content, const char *header_name, const char *header_value) { - SalBodyHandler *part_body_handler; - SalBodyHandler *body_handler = sal_body_handler_from_content(content); - if (!sal_body_handler_is_multipart(body_handler)) { - sal_body_handler_unref(body_handler); - return NULL; - } - part_body_handler = sal_body_handler_find_part_by_header(body_handler, header_name, header_value); - LinphoneContent *result = linphone_content_from_sal_body_handler(part_body_handler); - sal_body_handler_unref(body_handler); - return result; -} - -const char * linphone_content_get_custom_header(const LinphoneContent *content, const char *header_name) { - SalBodyHandler *body_handler = sal_body_handler_from_content(content); - const char *header = sal_body_handler_get_header(body_handler, header_name); - sal_body_handler_unref(body_handler); - return header; -} - -const char *linphone_content_get_key(const LinphoneContent *content) { - if (content->key) ms_free(content->key); - - const LinphonePrivate::Content *c = L_GET_CPP_PTR_FROM_C_OBJECT(content); - if (c->isFileTransfer()) { - const LinphonePrivate::FileTransferContent *ftc = static_cast(c); - content->key = ms_strdup(ftc->getFileKeyAsString()); - } - - return content->key; -} - -size_t linphone_content_get_key_size(const LinphoneContent *content) { - const LinphonePrivate::Content *c = L_GET_CPP_PTR_FROM_C_OBJECT(content); - if (c->isFileTransfer()) { - const LinphonePrivate::FileTransferContent *ftc = static_cast(c); - return ftc->getFileKeySize(); - } - return 0; -} - -void linphone_content_set_key(LinphoneContent *content, const char *key, const size_t keyLength) { - LinphonePrivate::Content *c = L_GET_CPP_PTR_FROM_C_OBJECT(content); - if (c->isFileTransfer()) { - LinphonePrivate::FileTransferContent *ftc = static_cast(c); - ftc->setFileKey(key, keyLength); - } -} - -// ============================================================================= -// Private functions. -// ============================================================================= - -static LinphoneContent * linphone_content_new_with_body_handler(SalBodyHandler *body_handler) { - LinphoneContent *content = L_INIT(Content); - content->cryptoContext = NULL; - LinphonePrivate::Content *c = new LinphonePrivate::Content(); - L_SET_CPP_PTR_FROM_C_OBJECT(content, c); - - if (body_handler != NULL) { - linphone_content_set_type(content, sal_body_handler_get_type(body_handler)); - linphone_content_set_subtype(content, sal_body_handler_get_subtype(body_handler)); - for (const belle_sip_list_t *params = sal_body_handler_get_content_type_parameters_names(body_handler); params; params = params->next) { - const char *paramName = (const char *)(params->data); - const char *paramValue = sal_body_handler_get_content_type_parameter(body_handler, paramName); - linphone_content_add_content_type_parameter(content, paramName, paramValue); - } - - if (!linphone_content_is_multipart(content)) { - linphone_content_set_string_buffer(content, (char *)sal_body_handler_get_data(body_handler)); - } else { - belle_sip_multipart_body_handler_t *mpbh = BELLE_SIP_MULTIPART_BODY_HANDLER(body_handler); - char *body = belle_sip_object_to_string(mpbh); - linphone_content_set_string_buffer(content, body); - belle_sip_free(body); - } - - belle_sip_list_t *headers = (belle_sip_list_t *)sal_body_handler_get_headers(body_handler); - while (headers) { - belle_sip_header_t *cHeader = BELLE_SIP_HEADER(headers->data); - LinphonePrivate::Header header = LinphonePrivate::Header(belle_sip_header_get_name(cHeader), belle_sip_header_get_unparsed_value(cHeader)); - L_GET_CPP_PTR_FROM_C_OBJECT(content)->addHeader(header); - headers = headers->next; - } - if (sal_body_handler_get_encoding(body_handler)) linphone_content_set_encoding(content, sal_body_handler_get_encoding(body_handler)); - } - - return content; -} - -LinphoneContent * linphone_content_new(void) { - return linphone_content_new_with_body_handler(NULL); -} - -LinphoneContent * linphone_content_copy(const LinphoneContent *ref) { - return (LinphoneContent *)(belle_sip_object_clone(BELLE_SIP_OBJECT(ref))); -} - -LinphoneContent * linphone_core_create_content(LinphoneCore *lc) { - return linphone_content_new(); -} - -/* crypto context is managed(allocated/freed) by the encryption function, so provide the address of field in the private structure */ -void ** linphone_content_get_cryptoContext_address(LinphoneContent *content) { - return &(content->cryptoContext); -} - -LinphoneContent * linphone_content_from_sal_body_handler(SalBodyHandler *body_handler) { - if (body_handler) { - return linphone_content_new_with_body_handler(body_handler); - } - return NULL; -} - -SalBodyHandler * sal_body_handler_from_content(const LinphoneContent *content) { - if (content == NULL) return NULL; - - SalBodyHandler *body_handler; - LinphonePrivate::ContentType contentType = L_GET_CPP_PTR_FROM_C_OBJECT(content)->getContentType(); - - if (contentType.isMultipart()) { - size_t size = linphone_content_get_size(content); - char *buffer = ms_strdup(L_GET_CPP_PTR_FROM_C_OBJECT(content)->getBodyAsUtf8String().c_str()); - const char *boundary = L_STRING_TO_C(contentType.getParameter("boundary").getValue()); - belle_sip_multipart_body_handler_t *bh = belle_sip_multipart_body_handler_new_from_buffer(buffer, size, boundary); - body_handler = (SalBodyHandler *)BELLE_SIP_BODY_HANDLER(bh); - } else { - body_handler = sal_body_handler_new(); - sal_body_handler_set_data(body_handler, belle_sip_strdup(linphone_content_get_string_buffer(content))); - } - - for (const auto &header : L_GET_CPP_PTR_FROM_C_OBJECT(content)->getHeaders()) { - belle_sip_header_t *additionalHeader = belle_sip_header_parse(header.asString().c_str()); - belle_sip_body_handler_add_header(BELLE_SIP_BODY_HANDLER(body_handler), additionalHeader); - } - - sal_body_handler_set_type(body_handler, contentType.getType().c_str()); - sal_body_handler_set_subtype(body_handler, contentType.getSubType().c_str()); - sal_body_handler_set_size(body_handler, linphone_content_get_size(content)); - for (const auto ¶m : contentType.getParameters()) { - sal_body_handler_set_content_type_parameter(body_handler, param.getName().c_str(), param.getValue().c_str()); - } - if (content->encoding) sal_body_handler_set_encoding(body_handler, linphone_content_get_encoding(content)); - - return body_handler; -} diff --git a/src/c-wrapper/c-wrapper.h b/src/c-wrapper/c-wrapper.h index c6382b809..e0109ce7c 100644 --- a/src/c-wrapper/c-wrapper.h +++ b/src/c-wrapper/c-wrapper.h @@ -37,7 +37,6 @@ F(ChatMessage, ChatMessage) \ F(AbstractChatRoom, ChatRoom) \ F(Core, Core) \ - F(Content, Content) \ F(DialPlan, DialPlan) \ F(EventLog, EventLog) \ F(MagicSearch, MagicSearch) \ @@ -86,6 +85,7 @@ BELLE_SIP_TYPE_ID(LinphoneConferenceParams), BELLE_SIP_TYPE_ID(LinphoneConfig), BELLE_SIP_TYPE_ID(LinphoneContactProvider), BELLE_SIP_TYPE_ID(LinphoneContactSearch), +BELLE_SIP_TYPE_ID(LinphoneContent), BELLE_SIP_TYPE_ID(LinphoneCoreCbs), BELLE_SIP_TYPE_ID(LinphoneErrorInfo), BELLE_SIP_TYPE_ID(LinphoneEvent), diff --git a/src/c-wrapper/internal/c-sal.h b/src/c-wrapper/internal/c-sal.h index f34c4ee5f..4aeca0042 100644 --- a/src/c-wrapper/internal/c-sal.h +++ b/src/c-wrapper/internal/c-sal.h @@ -636,9 +636,6 @@ const char * sal_body_handler_get_type(const SalBodyHandler *body_handler); void sal_body_handler_set_type(SalBodyHandler *body_handler, const char *type); const char * sal_body_handler_get_subtype(const SalBodyHandler *body_handler); void sal_body_handler_set_subtype(SalBodyHandler *body_handler, const char *subtype); -const belle_sip_list_t * sal_body_handler_get_content_type_parameters_names(const SalBodyHandler *body_handler); -const char * sal_body_handler_get_content_type_parameter(const SalBodyHandler *body_handler, const char *name); -void sal_body_handler_set_content_type_parameter(SalBodyHandler *body_handler, const char *paramName, const char *paramValue); const char * sal_body_handler_get_encoding(const SalBodyHandler *body_handler); void sal_body_handler_set_encoding(SalBodyHandler *body_handler, const char *encoding); void * sal_body_handler_get_data(const SalBodyHandler *body_handler); @@ -647,10 +644,8 @@ size_t sal_body_handler_get_size(const SalBodyHandler *body_handler); void sal_body_handler_set_size(SalBodyHandler *body_handler, size_t size); bool_t sal_body_handler_is_multipart(const SalBodyHandler *body_handler); SalBodyHandler * sal_body_handler_get_part(const SalBodyHandler *body_handler, int idx); -const belle_sip_list_t * sal_body_handler_get_parts(const SalBodyHandler *body_handler); SalBodyHandler * sal_body_handler_find_part_by_header(const SalBodyHandler *body_handler, const char *header_name, const char *header_value); const char * sal_body_handler_get_header(const SalBodyHandler *body_handler, const char *header_name); -const belle_sip_list_t* sal_body_handler_get_headers(const SalBodyHandler *body_handler); /*this function parses a document with key=value pairs separated by new lines, and extracts the value for a given key*/ int sal_lines_get_value(const char *data, const char *key, char *value, size_t value_size); diff --git a/src/chat/chat-message/chat-message-p.h b/src/chat/chat-message/chat-message-p.h index 0e17afc88..4c957ed71 100644 --- a/src/chat/chat-message/chat-message-p.h +++ b/src/chat/chat-message/chat-message-p.h @@ -137,11 +137,11 @@ public: bool hasFileTransferContent () const; const Content* getFileTransferContent () const; - const Content* getFileTransferInformation () const; - void setFileTransferInformation (Content *content); + LinphoneContent *getFileTransferInformation () const; + void setFileTransferInformation (const LinphoneContent *content); - void addContent (Content *content); - void removeContent (Content *content); + void addContent (Content &content); + void removeContent (const Content &content); bool downloadFile (); diff --git a/src/chat/chat-message/chat-message.cpp b/src/chat/chat-message/chat-message.cpp index 81efcd2ec..0fcde7521 100644 --- a/src/chat/chat-message/chat-message.cpp +++ b/src/chat/chat-message/chat-message.cpp @@ -19,7 +19,6 @@ #include "object/object-p.h" -#include "linphone/api/c-content.h" #include "linphone/core.h" #include "linphone/lpconfig.h" #include "linphone/utils/utils.h" @@ -37,7 +36,6 @@ #include "chat/modifier/multipart-chat-message-modifier.h" #include "conference/participant.h" #include "content/file-content.h" -#include "content/header/header-param.h" #include "content/content.h" #include "core/core.h" #include "core/core-p.h" @@ -241,8 +239,8 @@ const Content* ChatMessagePrivate::getTextContent() const { } bool ChatMessagePrivate::hasFileTransferContent() const { - for (const Content *c : contents) { - if (c->isFileTransfer()) { + for (const Content *c : getContents()) { + if (c->getContentType() == ContentType::FileTransfer) { return true; } } @@ -250,8 +248,8 @@ bool ChatMessagePrivate::hasFileTransferContent() const { } const Content* ChatMessagePrivate::getFileTransferContent() const { - for (const Content *c : contents) { - if (c->isFileTransfer()) { + for (const Content *c : getContents()) { + if (c->getContentType() == ContentType::FileTransfer) { return c; } } @@ -376,54 +374,51 @@ void ChatMessagePrivate::setText (const string &text) { } } -const Content *ChatMessagePrivate::getFileTransferInformation () const { +LinphoneContent *ChatMessagePrivate::getFileTransferInformation () const { if (hasFileTransferContent()) { - return getFileTransferContent(); + return getFileTransferContent()->toLinphoneContent(); } for (const Content *c : getContents()) { if (c->isFile()) { FileContent *fileContent = (FileContent *)c; - return fileContent; + return fileContent->toLinphoneContent(); } } return nullptr; } -void ChatMessagePrivate::setFileTransferInformation (Content *content) { +void ChatMessagePrivate::setFileTransferInformation (const LinphoneContent *c_content) { L_Q(); - if (content->isFile()) { - q->addContent(content); - } else { - // This scenario is more likely to happen because the caller is using the C API - LinphoneContent *c_content = L_GET_C_BACK_PTR(content); - FileContent *fileContent = new FileContent(); - fileContent->setContentType(content->getContentType()); - fileContent->setFileSize(linphone_content_get_size(c_content)); // This information is only available from C Content if it was created from C API - fileContent->setFileName(linphone_content_get_name(c_content)); // This information is only available from C Content if it was created from C API - if (!content->isEmpty()) { - fileContent->setBody(content->getBody()); - } - q->addContent(fileContent); + // Create a FileContent, it will create the FileTransferContent at upload time + FileContent *fileContent = new FileContent(); + ContentType contentType(linphone_content_get_type(c_content), linphone_content_get_subtype(c_content)); + fileContent->setContentType(contentType); + fileContent->setFileSize(linphone_content_get_size(c_content)); + fileContent->setFileName(linphone_content_get_name(c_content)); + if (linphone_content_get_string_buffer(c_content)) { + fileContent->setBody(linphone_content_get_string_buffer(c_content)); } + + q->addContent(*fileContent); } bool ChatMessagePrivate::downloadFile () { L_Q(); for (auto &content : getContents()) - if (content->isFileTransfer()) - return q->downloadFile(static_cast(content)); + if (content->getContentType() == ContentType::FileTransfer) + return q->downloadFile(*static_cast(content)); return false; } -void ChatMessagePrivate::addContent (Content *content) { - getContents().push_back(content); +void ChatMessagePrivate::addContent (Content &content) { + getContents().push_back(&content); } -void ChatMessagePrivate::removeContent (Content *content) { - getContents().remove(content); +void ChatMessagePrivate::removeContent (const Content &content) { + getContents().remove(&const_cast(content)); } void ChatMessagePrivate::loadFileTransferUrlFromBodyToContent() { @@ -458,7 +453,7 @@ void ChatMessagePrivate::sendImdn (Imdn::Type imdnType, LinphoneReason reason) { Content *content = new Content(); content->setContentType(ContentType::Imdn); content->setBody(Imdn::createXml(imdnId, time, imdnType, reason)); - msg->addContent(content); + msg->addContent(*content); if (reason != LinphoneReasonNone) msg->getPrivate()->setEncryptionPrevented(true); @@ -475,7 +470,7 @@ static void forceUtf8Content (Content &content) { if (contentType != ContentType::PlainText) return; - string charset = contentType.getParameter("charset").getValue(); + string charset = contentType.getParameter(); if (charset.empty()) return; @@ -494,7 +489,7 @@ static void forceUtf8Content (Content &content) { if (!utf8Body.empty()) { // TODO: use move operator if possible in the future! content.setBodyFromUtf8(utf8Body); - contentType.addParameter("charset", "UTF-8"); + contentType.setParameter(string(contentType.getParameter()).replace(begin, end - begin, "UTF-8")); content.setContentType(contentType); } } @@ -606,7 +601,7 @@ LinphoneReason ChatMessagePrivate::receive () { foundSupportContentType = true; break; } else - lError() << "Unsupported content-type: " << c->getContentType(); + lError() << "Unsupported content-type: " << c->getContentType().asString(); } if (!foundSupportContentType) { @@ -765,7 +760,7 @@ void ChatMessagePrivate::send () { auto msgOp = dynamic_cast(op); if (!externalBodyUrl.empty()) { - char *content_type = ms_strdup_printf("message/external-body;access-type=URL;URL=\"%s\"", externalBodyUrl.c_str()); + char *content_type = ms_strdup_printf("message/external-body; access-type=URL; URL=\"%s\"", externalBodyUrl.c_str()); msgOp->send_message(content_type, NULL); ms_free(content_type); } else if (internalContent.getContentType().isValid()) { @@ -778,10 +773,10 @@ void ChatMessagePrivate::send () { list::iterator it = contents.begin(); while (it != contents.end()) { Content *content = *it; - if (content->isFileTransfer()) { - FileTransferContent *fileTransferContent = static_cast(content); + if (content->getContentType() == ContentType::FileTransfer) { + FileTransferContent *fileTransferContent = (FileTransferContent *)content; it = contents.erase(it); - addContent(fileTransferContent->getFileContent()); + addContent(*fileTransferContent->getFileContent()); delete fileTransferContent; } else { it++; @@ -1019,13 +1014,13 @@ const list &ChatMessage::getContents () const { return d->getContents(); } -void ChatMessage::addContent (Content *content) { +void ChatMessage::addContent (Content &content) { L_D(); if (!d->isReadOnly) d->addContent(content); } -void ChatMessage::removeContent (Content *content) { +void ChatMessage::removeContent (const Content &content) { L_D(); if (!d->isReadOnly) d->removeContent(content); @@ -1095,9 +1090,9 @@ void ChatMessage::sendDisplayNotification () { d->sendImdn(Imdn::Type::Display, LinphoneReasonNone); } -bool ChatMessage::downloadFile(FileTransferContent *fileTransferContent) { +bool ChatMessage::downloadFile(FileTransferContent &fileTransferContent) { L_D(); - return d->fileTransferChatMessageModifier.downloadFile(getSharedFromThis(), fileTransferContent); + return d->fileTransferChatMessageModifier.downloadFile(getSharedFromThis(), &fileTransferContent); } bool ChatMessage::isFileTransferInProgress() { diff --git a/src/chat/chat-message/chat-message.h b/src/chat/chat-message/chat-message.h index ea1cffedd..2b53bda7d 100644 --- a/src/chat/chat-message/chat-message.h +++ b/src/chat/chat-message/chat-message.h @@ -95,8 +95,8 @@ public: void setToBeStored (bool value); const std::list &getContents () const; - void addContent (Content *content); - void removeContent (Content *content); + void addContent (Content &content); + void removeContent (const Content &content); const Content &getInternalContent () const; void setInternalContent (const Content &content); @@ -106,7 +106,7 @@ public: void addCustomHeader (const std::string &headerName, const std::string &headerValue); void removeCustomHeader (const std::string &headerName); - bool downloadFile (FileTransferContent *content); + bool downloadFile (FileTransferContent &content); bool isFileTransferInProgress(); private: diff --git a/src/chat/chat-room/abstract-chat-room.h b/src/chat/chat-room/abstract-chat-room.h index 8a259466f..9662f89b9 100644 --- a/src/chat/chat-room/abstract-chat-room.h +++ b/src/chat/chat-room/abstract-chat-room.h @@ -89,7 +89,8 @@ public: virtual std::shared_ptr createChatMessage () = 0; virtual std::shared_ptr createChatMessage (const std::string &text) = 0; - virtual std::shared_ptr createFileTransferMessage (Content *initialContent) = 0; + // TODO: Remove LinphoneContent by LinphonePrivate::Content. + virtual std::shared_ptr createFileTransferMessage (const LinphoneContent *initialContent) = 0; virtual std::shared_ptr findChatMessage (const std::string &messageId) const = 0; virtual std::shared_ptr findChatMessage ( diff --git a/src/chat/chat-room/chat-room.cpp b/src/chat/chat-room/chat-room.cpp index b0b86553f..28106b50d 100644 --- a/src/chat/chat-room/chat-room.cpp +++ b/src/chat/chat-room/chat-room.cpp @@ -86,7 +86,7 @@ void ChatRoomPrivate::sendIsComposingNotification () { shared_ptr chatMessage = createChatMessage(ChatMessage::Direction::Outgoing); chatMessage->setToBeStored(false); - chatMessage->addContent(content); + chatMessage->addContent(*content); chatMessage->getPrivate()->addSalCustomHeader(PriorityHeader::HeaderName, PriorityHeader::NonUrgent); chatMessage->getPrivate()->addSalCustomHeader("Expires", "0"); @@ -414,11 +414,11 @@ shared_ptr ChatRoom::createChatMessage (const string &text) { Content *content = new Content(); content->setContentType(ContentType::PlainText); content->setBody(text); - chatMessage->addContent(content); + chatMessage->addContent(*content); return chatMessage; } -shared_ptr ChatRoom::createFileTransferMessage (Content *initialContent) { +shared_ptr ChatRoom::createFileTransferMessage (const LinphoneContent *initialContent) { shared_ptr chatMessage = createChatMessage(); chatMessage->getPrivate()->setFileTransferInformation(initialContent); return chatMessage; diff --git a/src/chat/chat-room/chat-room.h b/src/chat/chat-room/chat-room.h index c63e70c7d..40cad5ae3 100644 --- a/src/chat/chat-room/chat-room.h +++ b/src/chat/chat-room/chat-room.h @@ -65,7 +65,8 @@ public: std::shared_ptr createChatMessage () override; std::shared_ptr createChatMessage (const std::string &text) override; - std::shared_ptr createFileTransferMessage (Content *initialContent) override; + // TODO: Remove LinphoneContent by LinphonePrivate::Content. + std::shared_ptr createFileTransferMessage (const LinphoneContent *initialContent) override; std::shared_ptr findChatMessage (const std::string &messageId) const override; std::shared_ptr findChatMessage ( diff --git a/src/chat/chat-room/proxy-chat-room.cpp b/src/chat/chat-room/proxy-chat-room.cpp index 2e64bae01..6ddcb4f74 100644 --- a/src/chat/chat-room/proxy-chat-room.cpp +++ b/src/chat/chat-room/proxy-chat-room.cpp @@ -173,7 +173,7 @@ shared_ptr ProxyChatRoom::createChatMessage (const string &text) { return d->chatRoom->createChatMessage(text); } -shared_ptr ProxyChatRoom::createFileTransferMessage (Content *initialContent) { +shared_ptr ProxyChatRoom::createFileTransferMessage (const LinphoneContent *initialContent) { L_D(); return d->chatRoom->createFileTransferMessage(initialContent); } diff --git a/src/chat/chat-room/proxy-chat-room.h b/src/chat/chat-room/proxy-chat-room.h index 68ff37e5c..5e4c68d11 100644 --- a/src/chat/chat-room/proxy-chat-room.h +++ b/src/chat/chat-room/proxy-chat-room.h @@ -66,7 +66,8 @@ public: std::shared_ptr createChatMessage () override; std::shared_ptr createChatMessage (const std::string &text) override; - std::shared_ptr createFileTransferMessage (Content *initialContent) override; + // TODO: Remove LinphoneContent by LinphonePrivate::Content. + std::shared_ptr createFileTransferMessage (const LinphoneContent *initialContent) override; std::shared_ptr findChatMessage (const std::string &messageId) const override; std::shared_ptr findChatMessage ( diff --git a/src/chat/cpim/message/cpim-message.cpp b/src/chat/cpim/message/cpim-message.cpp index 123ef6c66..84753f4ef 100644 --- a/src/chat/cpim/message/cpim-message.cpp +++ b/src/chat/cpim/message/cpim-message.cpp @@ -149,11 +149,9 @@ string Cpim::Message::asString () const { string output; // TODO: Remove cpimHeaders - if (d->cpimHeaders->size() > 0) { - for (const auto &cpimHeader : *d->cpimHeaders) - output += cpimHeader->asString(); - output += "\r\n"; - } + for (const auto &cpimHeader : *d->cpimHeaders) + output += cpimHeader->asString(); + output += "\r\n"; // TODO Remove cpimHeaders if (d->messageHeaders->size() > 0) { diff --git a/src/chat/modifier/cpim-chat-message-modifier.cpp b/src/chat/modifier/cpim-chat-message-modifier.cpp index 03c35fed0..8958c0f82 100644 --- a/src/chat/modifier/cpim-chat-message-modifier.cpp +++ b/src/chat/modifier/cpim-chat-message-modifier.cpp @@ -98,7 +98,7 @@ ChatMessageModifier::Result CpimChatMessageModifier::decode (const shared_ptrgetContents().front(); if (content->getContentType() != ContentType::Cpim) { - lError() << "[CPIM] Message is not CPIM but " << content->getContentType(); + lError() << "[CPIM] Message is not CPIM but " << content->getContentType().asString(); return ChatMessageModifier::Result::Skipped; } diff --git a/src/chat/modifier/file-transfer-chat-message-modifier.cpp b/src/chat/modifier/file-transfer-chat-message-modifier.cpp index 6bebbfa0b..d9d0767b2 100644 --- a/src/chat/modifier/file-transfer-chat-message-modifier.cpp +++ b/src/chat/modifier/file-transfer-chat-message-modifier.cpp @@ -17,17 +17,15 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#include "linphone/api/c-content.h" - -#include "address/address.h" -#include "bctoolbox/crypto.h" #include "c-wrapper/c-wrapper.h" +#include "address/address.h" #include "chat/chat-message/chat-message-p.h" -#include "chat/chat-room/chat-room-p.h" #include "content/content-type.h" #include "content/content.h" +#include "chat/chat-room/chat-room-p.h" #include "core/core.h" #include "logger/logger.h" +#include "bctoolbox/crypto.h" #include "file-transfer-chat-message-modifier.h" @@ -109,7 +107,7 @@ void FileTransferChatMessageModifier::fileTransferOnProgress ( LinphoneChatMessage *msg = L_GET_C_BACK_PTR(message); LinphoneChatMessageCbs *cbs = linphone_chat_message_get_callbacks(msg); - LinphoneContent *content = L_GET_C_BACK_PTR((Content *)currentFileContentToTransfer); + LinphoneContent *content = currentFileContentToTransfer->toLinphoneContent(); if (linphone_chat_message_cbs_get_file_transfer_progress_indication(cbs)) { linphone_chat_message_cbs_get_file_transfer_progress_indication(cbs)(msg, content, offset, total); } else { @@ -159,7 +157,7 @@ int FileTransferChatMessageModifier::onSendBody ( LinphoneChatMessageCbs *cbs = linphone_chat_message_get_callbacks(msg); LinphoneChatMessageCbsFileTransferSendCb file_transfer_send_cb = linphone_chat_message_cbs_get_file_transfer_send(cbs); - LinphoneContent *content = L_GET_C_BACK_PTR((Content *)currentFileContentToTransfer); + LinphoneContent *content = currentFileContentToTransfer->toLinphoneContent(); if (file_transfer_send_cb) { LinphoneBuffer *lb = file_transfer_send_cb(msg, content, offset, *size); if (lb) { @@ -255,6 +253,12 @@ void FileTransferChatMessageModifier::processResponseFromPostFile (const belle_h } // shall we encrypt the file if (is_file_encryption_enabled && message->getChatRoom()) { + LinphoneImEncryptionEngineCbs *imee_cbs = linphone_im_encryption_engine_get_callbacks(imee); + LinphoneImEncryptionEngineCbsGenerateFileTransferKeyCb generate_file_transfer_key_cb = + linphone_im_encryption_engine_cbs_get_generate_file_transfer_key(imee_cbs); + if (generate_file_transfer_key_cb) { + generate_file_transfer_key_cb(imee, L_GET_C_BACK_PTR(message->getChatRoom()), L_GET_C_BACK_PTR(message)); + } // temporary storage for the Content-disposition header value : use a generic filename to not leak it // Actual filename stored in msg->file_transfer_information->name will be set in encrypted msg // sended to the @@ -297,31 +301,9 @@ void FileTransferChatMessageModifier::processResponseFromPostFile (const belle_h const char *body = belle_sip_message_get_body((belle_sip_message_t *)event->response); if (body && strlen(body) > 0) { FileTransferContent *fileTransferContent = new FileTransferContent(); - fileTransferContent->setContentType(ContentType::FileTransfer); - - LinphoneImEncryptionEngine *imee = linphone_core_get_im_encryption_engine(message->getCore()->getCCore()); - bool_t is_file_encryption_enabled = FALSE; - if (imee && message->getChatRoom()) { - LinphoneImEncryptionEngineCbs *imee_cbs = linphone_im_encryption_engine_get_callbacks(imee); - LinphoneImEncryptionEngineCbsIsEncryptionEnabledForFileTransferCb is_encryption_enabled_for_file_transfer_cb = - linphone_im_encryption_engine_cbs_get_is_encryption_enabled_for_file_transfer(imee_cbs); - if (is_encryption_enabled_for_file_transfer_cb) { - is_file_encryption_enabled = is_encryption_enabled_for_file_transfer_cb(imee, L_GET_C_BACK_PTR(message->getChatRoom())); - } - } - if (is_file_encryption_enabled && message->getChatRoom()) { - LinphoneImEncryptionEngineCbs *imee_cbs = linphone_im_encryption_engine_get_callbacks(imee); - LinphoneImEncryptionEngineCbsGenerateFileTransferKeyCb generate_file_transfer_key_cb = - linphone_im_encryption_engine_cbs_get_generate_file_transfer_key(imee_cbs); - if (generate_file_transfer_key_cb) { - generate_file_transfer_key_cb(imee, L_GET_C_BACK_PTR(message->getChatRoom()), L_GET_C_BACK_PTR(message)); - } - } - // if we have an encryption key for the file, we must insert it into the msg and restore the correct filename - const char *content_key = fileTransferContent->getFileKeyAsString(); - size_t content_key_size = fileTransferContent->getFileKey().size(); - if (content_key_size > 0) { + string content_key = currentFileContentToTransfer->getFileKey(); + if (!content_key.empty()) { // parse the msg body xmlDocPtr xmlMessageBody = xmlParseDoc((const xmlChar *)body); @@ -334,15 +316,16 @@ void FileTransferChatMessageModifier::processResponseFromPostFile (const belle_h xmlChar *typeAttribute = xmlGetProp(cur, (const xmlChar *)"type"); // this is the node we are looking for : add a file-key children node if (!xmlStrcmp(typeAttribute, (const xmlChar *)"file")) { + size_t content_key_size = content_key.length(); // need to parse the children node to update the file-name one xmlNodePtr fileInfoNodeChildren = cur->xmlChildrenNode; // convert key to base64 size_t b64Size; - bctbx_base64_encode(nullptr, &b64Size, (unsigned char *)content_key, content_key_size); + bctbx_base64_encode(nullptr, &b64Size, (unsigned char *)content_key.c_str(), content_key_size); unsigned char *keyb64 = (unsigned char *)ms_malloc0(b64Size + 1); int xmlStringLength; - bctbx_base64_encode(keyb64, &b64Size, (unsigned char *)content_key, content_key_size); + bctbx_base64_encode(keyb64, &b64Size, (unsigned char *)content_key.c_str(), content_key_size); keyb64[b64Size] = '\0'; // libxml need a null terminated string // add the node containing the key to the file-info node @@ -378,10 +361,11 @@ void FileTransferChatMessageModifier::processResponseFromPostFile (const belle_h } FileContent *fileContent = currentFileContentToTransfer; + fileTransferContent->setContentType(ContentType::FileTransfer); fileTransferContent->setFileContent(fileContent); - message->getPrivate()->removeContent(fileContent); - message->getPrivate()->addContent(fileTransferContent); + message->getPrivate()->removeContent(*fileContent); + message->getPrivate()->addContent(*fileTransferContent); message->getPrivate()->setState(ChatMessage::State::FileTransferDone); releaseHttpRequest(); @@ -575,13 +559,13 @@ ChatMessageModifier::Result FileTransferChatMessageModifier::decode (const share fileTransferContent->setContentType(internalContent.getContentType()); fileTransferContent->setBody(internalContent.getBody()); fillFileTransferContentInformationsFromVndGsmaRcsFtHttpXml(fileTransferContent); - message->addContent(fileTransferContent); + message->addContent(*fileTransferContent); return ChatMessageModifier::Result::Done; } for (Content *content : message->getContents()) { - if (content->isFileTransfer()) { - FileTransferContent *fileTransferContent = static_cast(content); + if (content->getContentType() == ContentType::FileTransfer) { + FileTransferContent *fileTransferContent = (FileTransferContent *)content; fillFileTransferContentInformationsFromVndGsmaRcsFtHttpXml(fileTransferContent); } } @@ -650,7 +634,8 @@ static void createFileTransferInformationsFromVndGsmaRcsFtHttpXml (FileTransferC uint8_t *keyBuffer = (uint8_t *)malloc(keyLength); // decode the key into local key buffer bctbx_base64_decode(keyBuffer, &keyLength, (unsigned char *)keyb64, strlen((const char *)keyb64)); - fileTransferContent->setFileKey((const char *)keyBuffer, keyLength); + string key = string((const char *)keyBuffer); + fileContent->setFileKey(key); // duplicate key value into the linphone content private structure xmlFree(keyb64); free(keyBuffer); @@ -714,7 +699,7 @@ void FileTransferChatMessageModifier::onRecvBody (belle_sip_user_body_handler_t if (currentFileContentToTransfer->getFilePath().empty()) { LinphoneChatMessage *msg = L_GET_C_BACK_PTR(message); LinphoneChatMessageCbs *cbs = linphone_chat_message_get_callbacks(msg); - LinphoneContent *content = L_GET_C_BACK_PTR((Content *)currentFileContentToTransfer); + LinphoneContent *content = currentFileContentToTransfer->toLinphoneContent(); if (linphone_chat_message_cbs_get_file_transfer_recv(cbs)) { LinphoneBuffer *lb = linphone_buffer_new_from_data(buffer, size); linphone_chat_message_cbs_get_file_transfer_recv(cbs)(msg, content, lb); @@ -755,7 +740,7 @@ void FileTransferChatMessageModifier::onRecvEnd (belle_sip_user_body_handler_t * if (currentFileContentToTransfer->getFilePath().empty()) { LinphoneChatMessage *msg = L_GET_C_BACK_PTR(message); LinphoneChatMessageCbs *cbs = linphone_chat_message_get_callbacks(msg); - LinphoneContent *content = L_GET_C_BACK_PTR((Content *)currentFileContentToTransfer); + LinphoneContent *content = currentFileContentToTransfer->toLinphoneContent(); if (linphone_chat_message_cbs_get_file_transfer_recv(cbs)) { LinphoneBuffer *lb = linphone_buffer_new(); linphone_chat_message_cbs_get_file_transfer_recv(cbs)(msg, content, lb); @@ -771,12 +756,12 @@ void FileTransferChatMessageModifier::onRecvEnd (belle_sip_user_body_handler_t * if (retval <= 0 && message->getState() != ChatMessage::State::FileTransferError) { // Remove the FileTransferContent from the message and store the FileContent FileContent *fileContent = currentFileContentToTransfer; - message->getPrivate()->addContent(fileContent); + message->getPrivate()->addContent(*fileContent); for (Content *content : message->getContents()) { - if (content->isFileTransfer()) { - FileTransferContent *fileTransferContent = static_cast(content); + if (content->getContentType() == ContentType::FileTransfer) { + FileTransferContent *fileTransferContent = (FileTransferContent*)content; if (fileTransferContent->getFileContent() == fileContent) { - message->getPrivate()->removeContent(content); + message->getPrivate()->removeContent(*content); delete fileTransferContent; break; } @@ -829,7 +814,7 @@ void FileTransferChatMessageModifier::processResponseHeadersFromGetFile (const b } else { lWarning() << "No file transfer information for msg [" << this << "]: creating..."; FileContent *content = createFileTransferInformationFromHeaders(response); - message->addContent(content); + message->addContent(*content); } size_t body_size = 0; diff --git a/src/chat/modifier/multipart-chat-message-modifier.cpp b/src/chat/modifier/multipart-chat-message-modifier.cpp index 8ed8312d9..243cb32e1 100644 --- a/src/chat/modifier/multipart-chat-message-modifier.cpp +++ b/src/chat/modifier/multipart-chat-message-modifier.cpp @@ -20,11 +20,13 @@ // TODO: Remove me later. #include "private.h" +#include "address/address.h" #include "chat/chat-message/chat-message.h" +#include "chat/chat-room/chat-room.h" #include "content/content-type.h" -#include "content/header/header.h" -#include "content/content-manager.h" #include "content/file-transfer-content.h" +#include "logger/logger.h" +#include "core/core.h" #include "multipart-chat-message-modifier.h" @@ -41,30 +43,90 @@ ChatMessageModifier::Result MultipartChatMessageModifier::encode ( if (message->getContents().size() <= 1) return ChatMessageModifier::Result::Skipped; - Content content = ContentManager::contentListToMultipart(message->getContents()); - message->setInternalContent(content); + LinphoneCore *lc = message->getChatRoom()->getCore()->getCCore(); + char tmp[64]; + lc->sal->create_uuid(tmp, sizeof(tmp)); + string boundary = tmp; + stringstream multipartMessage; + + multipartMessage << "--" << boundary; + for (Content *content : message->getContents()) { + multipartMessage << "\r\n"; + multipartMessage << "Content-Type: " << content->getContentType().asString() << "\r\n\r\n"; + multipartMessage << content->getBodyAsString() << "\r\n\r\n"; + multipartMessage << "--" << boundary; + } + multipartMessage << "--"; + + Content newContent; + ContentType newContentType(ContentType::Multipart); + newContentType.setParameter("boundary=" + boundary); + newContent.setContentType(newContentType); + newContent.setBody(multipartMessage.str()); + message->setInternalContent(newContent); return ChatMessageModifier::Result::Done; } ChatMessageModifier::Result MultipartChatMessageModifier::decode (const shared_ptr &message, int &errorCode) { - if (message->getInternalContent().getContentType().isMultipart()) { - for (Content &c : ContentManager::multipartToContentList(message->getInternalContent())) { - Content *content; - if (c.getContentType() == ContentType::FileTransfer) { - content = new FileTransferContent(); - content->setContentType(c.getContentType()); - content->setContentDisposition(c.getContentDisposition()); - content->setContentEncoding(c.getContentEncoding()); - for (const Header &header : c.getHeaders()) { - content->addHeader(header); - } - content->setBodyFromUtf8(c.getBodyAsUtf8String()); - } else { - content = new Content(c); - } - message->addContent(content); + if (message->getInternalContent().getContentType().getType() == "multipart") { + string boundary = message->getInternalContent().getContentType().getParameter(); + if (boundary.empty()) { + lError() << "Boundary parameter of content-type not found: " << message->getInternalContent().getContentType().asString(); + return ChatMessageModifier::Result::Error; } + + size_t pos = boundary.find("="); + if (pos == string::npos) { + lError() << "Parameter seems invalid: " << boundary; + return ChatMessageModifier::Result::Error; + } + boundary = "--" + boundary.substr(pos + 1); + lInfo() << "Multipart boundary is " << boundary; + + const vector body = message->getInternalContent().getBody(); + string contentsString(body.begin(), body.end()); + + pos = contentsString.find(boundary); + if (pos == string::npos) { + lError() << "Boundary not found in body !"; + return ChatMessageModifier::Result::Error; + } + + size_t start = pos + boundary.length() + 2; // 2 is the size of \r\n + size_t end; + do { + end = contentsString.find(boundary, start); + if (end != string::npos) { + string contentString = contentsString.substr(start, end - start); + + size_t contentTypePos = contentString.find(": ") + 2; // 2 is the size of : + size_t endOfLinePos = contentString.find("\r\n"); + if (contentTypePos >= endOfLinePos) { + lError() << "Content should start by a 'Content-Type: ' line !"; + continue; + } + string contentTypeString = contentString.substr(contentTypePos, endOfLinePos - contentTypePos); + ContentType contentType(contentTypeString); + + endOfLinePos += 4; // 4 is two time the size of \r\n + string contentBody = contentString.substr(endOfLinePos, contentString.length() - (endOfLinePos + 4)); // 4 is two time the size of \r\n + + Content *content; + if (contentType == ContentType::FileTransfer) { + content = new FileTransferContent(); + } else { + content = new Content(); + } + content->setContentType(contentType); + content->setBody(contentBody); + message->addContent(*content); + + lInfo() << "Parsed and added content with type " << contentType.asString(); + } + start = end + boundary.length() + 2; // 2 is the size of \r\n + } while (end != string::npos); + return ChatMessageModifier::Result::Done; } return ChatMessageModifier::Result::Skipped; diff --git a/src/conference/handlers/local-conference-event-handler.cpp b/src/conference/handlers/local-conference-event-handler.cpp index 8f56e74e5..9847a93e9 100644 --- a/src/conference/handlers/local-conference-event-handler.cpp +++ b/src/conference/handlers/local-conference-event-handler.cpp @@ -19,7 +19,6 @@ #include -#include "linphone/api/c-content.h" #include "linphone/utils/utils.h" #include "conference/local-conference.h" @@ -107,7 +106,7 @@ string LocalConferenceEventHandlerPrivate::createNotifyMultipart (int notifyId) static_cast(notifyId) ); - list contents; + list contents; for (const auto &eventLog : events) { Content content; content.setContentType(ContentType("application","conference-info")); @@ -181,7 +180,7 @@ string LocalConferenceEventHandlerPrivate::createNotifyMultipart (int notifyId) continue; } content.setBody(body); - contents.push_back(&content); + contents.push_back(content); } if (contents.empty()) diff --git a/src/conference/session/call-session.cpp b/src/conference/session/call-session.cpp index ea125826e..668f0df33 100644 --- a/src/conference/session/call-session.cpp +++ b/src/conference/session/call-session.cpp @@ -19,18 +19,19 @@ #include -#include "linphone/api/c-content.h" -#include "linphone/core.h" +#include "c-wrapper/c-wrapper.h" #include "address/address-p.h" -#include "c-wrapper/c-wrapper.h" #include "call/call-p.h" #include "conference/params/call-session-params-p.h" #include "conference/session/call-session-p.h" #include "conference/session/call-session.h" #include "core/core-p.h" + #include "logger/logger.h" +#include "linphone/core.h" + #include "private.h" using namespace std; diff --git a/src/content/content-manager.cpp b/src/content/content-manager.cpp index ff341bcf2..94ee69ce9 100644 --- a/src/content/content-manager.cpp +++ b/src/content/content-manager.cpp @@ -19,68 +19,101 @@ #include -#include "c-wrapper/c-wrapper.h" - -#include "linphone/api/c-content.h" - #include "content-manager.h" #include "content-type.h" #include "content/content.h" // ============================================================================= -namespace { - constexpr const char MultipartBoundary[] = "---------------------------14737809831466499882746641449"; -} - using namespace std; LINPHONE_BEGIN_NAMESPACE +namespace { + constexpr const char MultipartBoundary[] = "---------------------------14737809831466499882746641449"; +} + // ----------------------------------------------------------------------------- list ContentManager::multipartToContentList (const Content &content) { - LinphoneContent *cContent = L_GET_C_BACK_PTR(&content); - SalBodyHandler *sbh = sal_body_handler_ref(sal_body_handler_from_content(cContent)); + const string body = content.getBodyAsString(); + belle_sip_multipart_body_handler_t *mpbh = belle_sip_multipart_body_handler_new_from_buffer( + body.c_str(), body.length(), MultipartBoundary + ); + belle_sip_object_ref(mpbh); list contents; - for (const belle_sip_list_t *parts = sal_body_handler_get_parts(sbh); parts; parts = parts->next) { - SalBodyHandler *part = (SalBodyHandler *)parts->data; - LinphoneContent *cContent = linphone_content_from_sal_body_handler(part); - Content *cppContent = L_GET_CPP_PTR_FROM_C_OBJECT(cContent); - contents.push_back(*cppContent); - linphone_content_unref(cContent); + for (const belle_sip_list_t *parts = belle_sip_multipart_body_handler_get_parts(mpbh); parts; parts = parts->next) { + belle_sip_body_handler_t *part = BELLE_SIP_BODY_HANDLER(parts->data); + belle_sip_header_content_type_t *partContentType = nullptr; + for (const belle_sip_list_t *it = belle_sip_body_handler_get_headers(part); it; it = it->next) { + belle_sip_header_t *header = BELLE_SIP_HEADER(it->data); + if (strcasecmp("Content-Type", belle_sip_header_get_name(header)) == 0) { + partContentType = BELLE_SIP_HEADER_CONTENT_TYPE(header); + break; + } + } + + Content content; + content.setBody(static_cast( + belle_sip_memory_body_handler_get_buffer(BELLE_SIP_MEMORY_BODY_HANDLER(part)) + )); + content.setContentType(ContentType( + belle_sip_header_content_type_get_type(partContentType), + belle_sip_header_content_type_get_subtype(partContentType) + )); + contents.push_back(move(content)); } - sal_body_handler_unref(sbh); - linphone_content_unref(cContent); + belle_sip_object_unref(mpbh); return contents; } -Content ContentManager::contentListToMultipart (const list &contents) { +Content ContentManager::contentListToMultipart (const list &contents) { belle_sip_multipart_body_handler_t *mpbh = belle_sip_multipart_body_handler_new( nullptr, nullptr, nullptr, MultipartBoundary ); - mpbh = (belle_sip_multipart_body_handler_t *)belle_sip_object_ref(mpbh); + belle_sip_object_ref(mpbh); - for (Content *content : contents) { - LinphoneContent *cContent = L_GET_C_BACK_PTR(content); - SalBodyHandler *sbh = sal_body_handler_from_content(cContent); - belle_sip_multipart_body_handler_add_part(mpbh, BELLE_SIP_BODY_HANDLER(sbh)); - linphone_content_unref(cContent); + for (const auto &content : contents) { + const ContentType &contentType = content.getContentType(); + belle_sip_header_t *cContentType = BELLE_SIP_HEADER( + belle_sip_header_content_type_create( + contentType.getType().c_str(), + string(contentType.getSubType() + "; charset=\"UTF-8\"").c_str() + ) + ); + + const string body = content.getBodyAsString(); + belle_sip_memory_body_handler_t *mbh = belle_sip_memory_body_handler_new_copy_from_buffer( + body.c_str(), body.length(), nullptr, nullptr + ); + belle_sip_body_handler_add_header(BELLE_SIP_BODY_HANDLER(mbh), cContentType); + + for (const auto &header : content.getHeaders()) { + belle_sip_header_t *additionalHeader = BELLE_SIP_HEADER( + belle_sip_header_create( + header.first.c_str(), + header.second.c_str() + ) + ); + belle_sip_body_handler_add_header(BELLE_SIP_BODY_HANDLER(mbh), additionalHeader); + } + + belle_sip_multipart_body_handler_add_part(mpbh, BELLE_SIP_BODY_HANDLER(mbh)); } - SalBodyHandler *sbh = (SalBodyHandler *)mpbh; - sal_body_handler_set_type(sbh, ContentType::Multipart.getType().c_str()); - sal_body_handler_set_subtype(sbh, ContentType::Multipart.getSubType().c_str()); - sal_body_handler_set_content_type_parameter(sbh, "boundary", MultipartBoundary); - LinphoneContent *cContent = linphone_content_from_sal_body_handler(sbh); - Content *content = L_GET_CPP_PTR_FROM_C_OBJECT(cContent); - Content returnContent = *content; - linphone_content_unref(cContent); + char *desc = belle_sip_object_to_string(mpbh); + Content content; + content.setBody(desc); + belle_sip_free(desc); belle_sip_object_unref(mpbh); - return returnContent; + ContentType contentType = ContentType::Multipart; + contentType.setParameter("boundary=" + string(MultipartBoundary)); + content.setContentType(contentType); + + return content; } LINPHONE_END_NAMESPACE diff --git a/src/content/content-manager.h b/src/content/content-manager.h index 4d19076f0..8251d3c3b 100644 --- a/src/content/content-manager.h +++ b/src/content/content-manager.h @@ -32,7 +32,7 @@ class Content; namespace ContentManager { std::list multipartToContentList (const Content &content); - Content contentListToMultipart (const std::list &contents); + Content contentListToMultipart (const std::list &contents); } LINPHONE_END_NAMESPACE diff --git a/src/content/content-p.h b/src/content/content-p.h index 9dc4e1d31..167712313 100644 --- a/src/content/content-p.h +++ b/src/content/content-p.h @@ -29,15 +29,13 @@ LINPHONE_BEGIN_NAMESPACE -class Header; - class ContentPrivate : public ClonableObjectPrivate { private: std::vector body; ContentType contentType; ContentDisposition contentDisposition; std::string contentEncoding; - std::list
headers; + std::list> headers; L_DECLARE_PUBLIC(Content); }; diff --git a/src/content/content-type.cpp b/src/content/content-type.cpp index 7aee05247..78c356af6 100644 --- a/src/content/content-type.cpp +++ b/src/content/content-type.cpp @@ -20,8 +20,7 @@ #include "linphone/utils/utils.h" #include "content-type.h" -#include "header/header-p.h" -#include "header/header-param.h" +#include "object/clonable-object-p.h" // ============================================================================= @@ -31,10 +30,11 @@ LINPHONE_BEGIN_NAMESPACE // ----------------------------------------------------------------------------- -class ContentTypePrivate : public HeaderPrivate { +class ContentTypePrivate : public ClonableObjectPrivate { public: string type; string subType; + string parameter; }; // ----------------------------------------------------------------------------- @@ -52,7 +52,7 @@ const ContentType ContentType::Sdp("application/sdp"); // ----------------------------------------------------------------------------- -ContentType::ContentType (const string &contentType) : Header(*new ContentTypePrivate) { +ContentType::ContentType (const string &contentType) : ClonableObject(*new ContentTypePrivate) { L_D(); size_t pos = contentType.find('/'); @@ -68,23 +68,11 @@ ContentType::ContentType (const string &contentType) : Header(*new ContentTypePr d->type.clear(); } - if (posParam != string::npos) { - string params = contentType.substr(posParam + 1); - string token; - do { - posParam = params.find(";"); - if (posParam == string::npos) { - token = params; - } else { - token = params.substr(0, posParam); - } - addParameter(HeaderParam(token)); - params.erase(0, posParam + 1); - } while (posParam != std::string::npos); - } + if (posParam != string::npos) + setParameter(Utils::trim(contentType.substr(posParam + 1))); } -ContentType::ContentType (const string &type, const string &subType) : Header(*new ContentTypePrivate) { +ContentType::ContentType (const string &type, const string &subType) : ClonableObject(*new ContentTypePrivate) { L_D(); if (setType(type) && !setSubType(subType)) @@ -94,35 +82,22 @@ ContentType::ContentType (const string &type, const string &subType) : Header(*n ContentType::ContentType ( const string &type, const string &subType, - const HeaderParam ¶meter -) : Header(*new ContentTypePrivate) { + const string ¶meter +) : ClonableObject(*new ContentTypePrivate) { L_D(); if (setType(type) && !setSubType(subType)) d->type.clear(); - addParameter(parameter); + setParameter(parameter); } -ContentType::ContentType ( - const string &type, - const string &subType, - const std::list ¶meters -) : Header(*new ContentTypePrivate) { - L_D(); - - if (setType(type) && !setSubType(subType)) - d->type.clear(); - addParameters(parameters); -} - -ContentType::ContentType (const ContentType &other) : ContentType(other.getType(), other.getSubType(), other.getParameters()) {} +ContentType::ContentType (const ContentType &other) : ContentType(other.getType(), other.getSubType(), other.getParameter()) {} ContentType &ContentType::operator= (const ContentType &other) { if (this != &other) { setType(other.getType()); setSubType(other.getSubType()); - cleanParameters(); - addParameters(other.getParameters()); + setParameter(other.getParameter()); } return *this; @@ -130,7 +105,8 @@ ContentType &ContentType::operator= (const ContentType &other) { bool ContentType::operator== (const ContentType &other) const { return getType() == other.getType() && - getSubType() == other.getSubType(); + getSubType() == other.getSubType() && + getParameter() == other.getParameter(); } bool ContentType::operator!= (const ContentType &other) const { @@ -146,7 +122,6 @@ bool ContentType::setType (const string &type) { L_D(); if (type.find('/') == string::npos) { d->type = Utils::stringToLower(type); - setValue(d->type + "/" + d->subType); return true; } return false; @@ -161,12 +136,21 @@ bool ContentType::setSubType (const string &subType) { L_D(); if (subType.find('/') == string::npos) { d->subType = Utils::stringToLower(subType); - setValue(d->type + "/" + d->subType); return true; } return false; } +const string &ContentType::getParameter () const { + L_D(); + return d->parameter; +} + +void ContentType::setParameter (const string ¶meter) { + L_D(); + d->parameter = parameter; +} + bool ContentType::isEmpty () const { L_D(); return d->type.empty() && d->subType.empty(); @@ -177,10 +161,18 @@ bool ContentType::isValid () const { return !d->type.empty() && !d->subType.empty(); } -bool ContentType::isMultipart() const { - return getType() == "multipart"; +string ContentType::asString () const { + L_D(); + if (isValid()) { + string asString = d->type + "/" + d->subType; + if (!d->parameter.empty()) + asString += "; " + d->parameter; + return asString; + } + return ""; } + bool ContentType::isFile () const { // TODO Remove when not needed anymore in step 2.1 of maindb return isFile(*this); diff --git a/src/content/content-type.h b/src/content/content-type.h index c9aa7af77..b13063115 100644 --- a/src/content/content-type.h +++ b/src/content/content-type.h @@ -21,21 +21,18 @@ #define _L_CONTENT_TYPE_H_ #include "object/clonable-object.h" -#include "header/header.h" // ============================================================================= LINPHONE_BEGIN_NAMESPACE class ContentTypePrivate; -class HeaderParam; -class LINPHONE_PUBLIC ContentType : public Header { +class LINPHONE_PUBLIC ContentType : public ClonableObject { public: explicit ContentType (const std::string &contentType = ""); ContentType (const std::string &type, const std::string &subType); - ContentType (const std::string &type, const std::string &subType, const HeaderParam ¶meter); - ContentType (const std::string &type, const std::string &subType, const std::list ¶meters); + ContentType (const std::string &type, const std::string &subType, const std::string ¶meter); ContentType (const ContentType &other); ContentType &operator= (const ContentType &other); @@ -58,7 +55,10 @@ public: const std::string &getSubType () const; bool setSubType (const std::string &subType); - bool isMultipart() const; + const std::string &getParameter () const; + void setParameter (const std::string ¶meter); + + std::string asString () const; static bool isFile (const ContentType &contentType); diff --git a/src/content/content.cpp b/src/content/content.cpp index ad74de27f..aa30503d4 100644 --- a/src/content/content.cpp +++ b/src/content/content.cpp @@ -25,7 +25,6 @@ #include "content-p.h" #include "content-type.h" -#include "header/header.h" // ============================================================================= @@ -191,37 +190,17 @@ bool Content::isFile () const { return false; } -bool Content::isFileTransfer () const { - return false; -} - void Content::addHeader (const string &headerName, const string &headerValue) { L_D(); removeHeader(headerName); - Header header = Header(headerName, headerValue); - d->headers.push_back(header); + d->headers.push_back(make_pair(headerName, headerValue)); } -void Content::addHeader (const Header &header) { - L_D(); - removeHeader(header.getName()); - d->headers.push_back(header); -} - -const list
&Content::getHeaders () const { +const list> &Content::getHeaders () const { L_D(); return d->headers; } -const Header &Content::getHeader (const string &headerName) const { - L_D(); - list
::const_iterator it = findHeader(headerName); - if (it != d->headers.cend()) { - return *it; - } - return Utils::getEmptyConstRefObject
(); -} - void Content::removeHeader (const string &headerName) { L_D(); auto it = findHeader(headerName); @@ -229,11 +208,18 @@ void Content::removeHeader (const string &headerName) { d->headers.remove(*it); } -list
::const_iterator Content::findHeader (const string &headerName) const { +list>::const_iterator Content::findHeader (const string &headerName) const { L_D(); - return findIf(d->headers, [&headerName](const Header &header) { - return header.getName() == headerName; + return findIf(d->headers, [&headerName](const pair &pair) { + return pair.first == headerName; }); } +LinphoneContent *Content::toLinphoneContent () const { + LinphoneContent *content = linphone_core_create_content(nullptr); + linphone_content_set_type(content, getContentType().getType().c_str()); + linphone_content_set_subtype(content, getContentType().getSubType().c_str()); + return content; +} + LINPHONE_END_NAMESPACE diff --git a/src/content/content.h b/src/content/content.h index 3c29d3a1a..c570670c5 100644 --- a/src/content/content.h +++ b/src/content/content.h @@ -35,7 +35,6 @@ LINPHONE_BEGIN_NAMESPACE class ContentDisposition; class ContentType; class ContentPrivate; -class Header; class LINPHONE_PUBLIC Content : public ClonableObject, public AppDataContainer { public: @@ -75,14 +74,14 @@ public: bool isEmpty () const; virtual bool isFile () const; - virtual bool isFileTransfer () const; - const std::list
&getHeaders () const; - const Header &getHeader (const std::string &headerName) const; + const std::list> &getHeaders () const; void addHeader (const std::string &headerName, const std::string &headerValue); - void addHeader (const Header &header); void removeHeader (const std::string &headerName); - std::list
::const_iterator findHeader (const std::string &headerName) const; + std::list>::const_iterator findHeader (const std::string &headerName) const; + + // TODO: Remove me later. + virtual LinphoneContent *toLinphoneContent () const; protected: explicit Content (ContentPrivate &p); diff --git a/src/content/file-content.cpp b/src/content/file-content.cpp index b4a0ef0fb..851d935d3 100644 --- a/src/content/file-content.cpp +++ b/src/content/file-content.cpp @@ -36,6 +36,7 @@ public: string fileName; string filePath; size_t fileSize = 0; + string fileKey; }; // ----------------------------------------------------------------------------- @@ -47,6 +48,7 @@ FileContent::FileContent (const FileContent &other) : Content(*new FileContentPr d->fileName = other.getFileName(); d->filePath = other.getFilePath(); d->fileSize = other.getFileSize(); + d->fileKey = other.getFileKey(); } FileContent::FileContent (FileContent &&other) : Content(*new FileContentPrivate) { @@ -54,14 +56,18 @@ FileContent::FileContent (FileContent &&other) : Content(*new FileContentPrivate d->fileName = move(other.getPrivate()->fileName); d->filePath = move(other.getPrivate()->filePath); d->fileSize = move(other.getPrivate()->fileSize); + d->fileKey = move(other.getPrivate()->fileKey); } FileContent &FileContent::operator= (const FileContent &other) { L_D(); + if (this != &other) { Content::operator=(other); d->fileName = other.getFileName(); d->filePath = other.getFilePath(); d->fileSize = other.getFileSize(); + d->fileKey = other.getFileKey(); + } return *this; } @@ -72,6 +78,7 @@ FileContent &FileContent::operator= (FileContent &&other) { d->fileName = move(other.getPrivate()->fileName); d->filePath = move(other.getPrivate()->filePath); d->fileSize = move(other.getPrivate()->fileSize); + d->fileKey = move(other.getPrivate()->fileKey); return *this; } @@ -80,7 +87,8 @@ bool FileContent::operator== (const FileContent &other) const { return Content::operator==(other) && d->fileName == other.getFileName() && d->filePath == other.getFilePath() && - d->fileSize == other.getFileSize(); + d->fileSize == other.getFileSize() && + d->fileKey == other.getFileKey(); } void FileContent::setFileSize (size_t size) { @@ -113,12 +121,28 @@ const string &FileContent::getFilePath () const { return d->filePath; } +void FileContent::setFileKey (const string &key) { + L_D(); + d->fileKey = key; +} + +const string &FileContent::getFileKey () const { + L_D(); + return d->fileKey; +} + bool FileContent::isFile () const { return true; } -bool FileContent::isFileTransfer () const { - return false; +LinphoneContent *FileContent::toLinphoneContent () const { + LinphoneContent *content = linphone_core_create_content(nullptr); + linphone_content_set_type(content, getContentType().getType().c_str()); + linphone_content_set_subtype(content, getContentType().getSubType().c_str()); + linphone_content_set_name(content, getFileName().c_str()); + linphone_content_set_size(content, getFileSize()); + linphone_content_set_key(content, getFileKey().c_str(), getFileKey().size()); + return content; } LINPHONE_END_NAMESPACE diff --git a/src/content/file-content.h b/src/content/file-content.h index 081a5898a..645fc6312 100644 --- a/src/content/file-content.h +++ b/src/content/file-content.h @@ -48,8 +48,13 @@ public: void setFilePath (const std::string &path); const std::string &getFilePath () const; + void setFileKey (const std::string &key); + const std::string &getFileKey () const; + bool isFile () const override; - bool isFileTransfer () const override; + + // TODO: Remove me later. + LinphoneContent *toLinphoneContent () const override; private: L_DECLARE_PRIVATE(FileContent); diff --git a/src/content/file-transfer-content.cpp b/src/content/file-transfer-content.cpp index e2fe5ab4f..4bc5ed691 100644 --- a/src/content/file-transfer-content.cpp +++ b/src/content/file-transfer-content.cpp @@ -38,7 +38,6 @@ public: string filePath; FileContent *fileContent = nullptr; size_t fileSize = 0; - std::vector fileKey; }; // ----------------------------------------------------------------------------- @@ -52,7 +51,6 @@ FileTransferContent::FileTransferContent (const FileTransferContent &other) : Co d->filePath = other.getFilePath(); d->fileContent = other.getFileContent(); d->fileSize = other.getFileSize(); - d->fileKey = other.getFileKey(); } FileTransferContent::FileTransferContent (FileTransferContent &&other) : Content(*new FileTransferContentPrivate) { @@ -62,7 +60,6 @@ FileTransferContent::FileTransferContent (FileTransferContent &&other) : Content d->filePath = move(other.getPrivate()->filePath); d->fileContent = move(other.getPrivate()->fileContent); d->fileSize = move(other.getPrivate()->fileSize); - d->fileKey = move(other.getPrivate()->fileKey); } FileTransferContent &FileTransferContent::operator= (const FileTransferContent &other) { @@ -74,7 +71,6 @@ FileTransferContent &FileTransferContent::operator= (const FileTransferContent & d->filePath = other.getFilePath(); d->fileContent = other.getFileContent(); d->fileSize = other.getFileSize(); - d->fileKey = other.getFileKey(); } return *this; @@ -88,8 +84,6 @@ FileTransferContent &FileTransferContent::operator= (FileTransferContent &&other d->filePath = move(other.getPrivate()->filePath); d->fileContent = move(other.getPrivate()->fileContent); d->fileSize = move(other.getPrivate()->fileSize); - d->fileKey = move(other.getPrivate()->fileKey); - return *this; } @@ -152,32 +146,17 @@ size_t FileTransferContent::getFileSize () const { return d->fileSize; } -void FileTransferContent::setFileKey (const char *key, size_t size) { - L_D(); - d->fileKey = vector(key, key + size); -} - -const vector &FileTransferContent::getFileKey () const { - L_D(); - return d->fileKey; -} - -const char *FileTransferContent::getFileKeyAsString() const { - L_D(); - return d->fileKey.data(); -} - -size_t FileTransferContent::getFileKeySize() const { - L_D(); - return d->fileKey.size(); +LinphoneContent *FileTransferContent::toLinphoneContent () const { + LinphoneContent *content = linphone_core_create_content(nullptr); + linphone_content_set_type(content, getContentType().getType().c_str()); + linphone_content_set_subtype(content, getContentType().getSubType().c_str()); + linphone_content_set_name(content, getFileName().c_str()); + linphone_content_set_size(content, getFileSize()); + return content; } bool FileTransferContent::isFile () const { return false; } -bool FileTransferContent::isFileTransfer () const { - return true; -} - LINPHONE_END_NAMESPACE diff --git a/src/content/file-transfer-content.h b/src/content/file-transfer-content.h index 1904e11c5..59b4cc125 100644 --- a/src/content/file-transfer-content.h +++ b/src/content/file-transfer-content.h @@ -20,8 +20,6 @@ #ifndef _L_FILE_TRANSFER_CONTENT_H_ #define _L_FILE_TRANSFER_CONTENT_H_ -#include - #include "content.h" // ============================================================================= @@ -57,13 +55,10 @@ public: void setFileSize (size_t size); size_t getFileSize () const; - void setFileKey (const char *key, size_t size); - const std::vector &getFileKey () const; - const char *getFileKeyAsString () const; - size_t getFileKeySize() const; - bool isFile () const override; - bool isFileTransfer () const override; + + // TODO: Remove me later. + LinphoneContent *toLinphoneContent () const override; private: L_DECLARE_PRIVATE(FileTransferContent); diff --git a/src/content/header/header-p.h b/src/content/header/header-p.h deleted file mode 100644 index fd4663efe..000000000 --- a/src/content/header/header-p.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * header-p.h - * 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, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef _L_HEADER_P_H_ -#define _L_HEADER_P_H_ - -#include - -#include "object/clonable-object-p.h" - -#include "header.h" - -// ============================================================================= - -LINPHONE_BEGIN_NAMESPACE - -class HeaderPrivate : public ClonableObjectPrivate { -private: - std::string name; - std::string value; - std::list parameters; - L_DECLARE_PUBLIC(Header); -}; - -LINPHONE_END_NAMESPACE - -#endif // ifndef _L_HEADER_P_H_ \ No newline at end of file diff --git a/src/content/header/header-param.cpp b/src/content/header/header-param.cpp deleted file mode 100644 index 9605a2f84..000000000 --- a/src/content/header/header-param.cpp +++ /dev/null @@ -1,108 +0,0 @@ -/* - * header-param.cpp - * 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, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include "linphone/utils/utils.h" - -#include "header-param.h" -#include "object/clonable-object-p.h" - -// ============================================================================= - -using namespace std; - -LINPHONE_BEGIN_NAMESPACE - -// ----------------------------------------------------------------------------- - -class HeaderParamPrivate : public ClonableObjectPrivate { -public: - string name; - string value; -}; - -// ----------------------------------------------------------------------------- - -HeaderParam::HeaderParam (const string ¶m) : ClonableObject(*new HeaderParamPrivate) { - size_t pos = param.find("="); - size_t end = param.length(); - - if (pos == string::npos) { - setName(param); - } else { - setName(param.substr(0, pos)); - setValue(param.substr(pos + 1, end - (pos + 1))); - } -} - -HeaderParam::HeaderParam (const string &name, const string &value) : ClonableObject(*new HeaderParamPrivate) { - setName(name); - setValue(value); -} - -HeaderParam::HeaderParam (const HeaderParam &other) : HeaderParam(other.getName(), other.getValue()) {} - -HeaderParam &HeaderParam::operator= (const HeaderParam &other) { - if (this != &other) { - setName(other.getName()); - setValue(other.getValue()); - } - - return *this; -} - -bool HeaderParam::operator== (const HeaderParam &other) const { - return getName() == other.getName() && - getValue() == other.getValue(); -} - -bool HeaderParam::operator!= (const HeaderParam &other) const { - return !(*this == other); -} - -const string &HeaderParam::getName () const { - L_D(); - return d->name; -} - -bool HeaderParam::setName (const string &name) { - L_D(); - d->name = name; - return true; -} - -const string &HeaderParam::getValue () const { - L_D(); - return d->value; -} - -bool HeaderParam::setValue (const string &value) { - L_D(); - d->value = value; - return true; -} - -string HeaderParam::asString () const { - L_D(); - string asString = ";" + d->name; - if (!d->value.empty()) - asString += "=" + d->value; - return asString; -} - -LINPHONE_END_NAMESPACE diff --git a/src/content/header/header-param.h b/src/content/header/header-param.h deleted file mode 100644 index a9471b486..000000000 --- a/src/content/header/header-param.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * header-param.h - * 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, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef _L_HEADER_PARAM_H_ -#define _L_HEADER_PARAM_H_ - -#include "object/clonable-object.h" - -// ============================================================================= - -LINPHONE_BEGIN_NAMESPACE - -class HeaderParamPrivate; - -class LINPHONE_PUBLIC HeaderParam : public ClonableObject { -public: - explicit HeaderParam (const std::string &header = ""); - HeaderParam (const std::string &name, const std::string &value); - HeaderParam (const HeaderParam &other); - - HeaderParam &operator= (const HeaderParam &other); - - bool operator== (const HeaderParam &other) const; - bool operator!= (const HeaderParam &other) const; - - // Delete these operators to prevent putting complicated content-type strings - // in the code. Instead define static const HeaderParam objects below. - bool operator== (const std::string &other) const = delete; - bool operator!= (const std::string &other) const = delete; - - const std::string &getName () const; - bool setName (const std::string &name); - - const std::string &getValue () const; - bool setValue (const std::string &value); - - std::string asString () const; - -private: - L_DECLARE_PRIVATE(HeaderParam); -}; - -LINPHONE_END_NAMESPACE - -#endif // ifndef _L_HEADER_PARAM_H_ diff --git a/src/content/header/header.cpp b/src/content/header/header.cpp deleted file mode 100644 index 5924cdf5b..000000000 --- a/src/content/header/header.cpp +++ /dev/null @@ -1,183 +0,0 @@ -/* - * header.cpp - * 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, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include - -#include "linphone/utils/utils.h" -#include "linphone/utils/algorithm.h" - -#include "header-p.h" -#include "header-param.h" - -// ============================================================================= - -using namespace std; - -LINPHONE_BEGIN_NAMESPACE - -// ----------------------------------------------------------------------------- - -Header::Header(HeaderPrivate &p) : ClonableObject(p) {} - -Header::Header() : ClonableObject(*new HeaderPrivate) {} - -Header::Header (const string &name, const string &value) : ClonableObject(*new HeaderPrivate) { - setName(name); - - size_t posParam = value.find(";"); - if (posParam == string::npos) { - setValue(value); - return; - } - - string parsedValue = value.substr(0, posParam); - string params = value.substr(posParam + 1); - string token; - do { - posParam = params.find(";"); - if (posParam == string::npos) { - token = params; - } else { - token = params.substr(0, posParam); - } - addParameter(HeaderParam(token)); - params.erase(0, posParam + 1); - } while (posParam != std::string::npos); - - setValue(parsedValue); -} - -Header::Header (const string &name, const string &value, const list ¶ms) : Header(name, value) { - addParameters(params); -} - -Header::Header (const Header &other) : Header(other.getName(), other.getValue(), other.getParameters()) {} - -Header &Header::operator= (const Header &other) { - if (this != &other) { - setName(other.getName()); - setValue(other.getValue()); - cleanParameters(); - addParameters(other.getParameters()); - } - - return *this; -} - -bool Header::operator== (const Header &other) const { - return getName() == other.getName() && - getValue() == other.getValue(); -} - -bool Header::operator!= (const Header &other) const { - return !(*this == other); -} - -void Header::setName (const string &name) { - L_D(); - d->name = name; -} - -string Header::getName () const { - L_D(); - return d->name; -} - -void Header::setValue (const string &value) { - L_D(); - d->value = value; -} - -string Header::getValue () const { - L_D(); - return d->value; -} - -void Header::cleanParameters () { - L_D(); - d->parameters.clear(); -} - -const list &Header::getParameters () const { - L_D(); - return d->parameters; -} - -void Header::addParameter (const string ¶mName, const string ¶mValue) { - addParameter(HeaderParam(paramName, paramValue)); -} - -void Header::addParameter (const HeaderParam ¶m) { - L_D(); - removeParameter(param); - d->parameters.push_back(param); -} - -void Header::addParameters(const list ¶ms) { - for (auto it = std::begin(params); it!=std::end(params); ++it) { - HeaderParam param = *it; - addParameter(param.getName(), param.getValue()); - } -} - -void Header::removeParameter (const string ¶mName) { - L_D(); - auto it = findParameter(paramName); - if (it != d->parameters.cend()) - d->parameters.remove(*it); -} - -void Header::removeParameter (const HeaderParam ¶m) { - removeParameter(param.getName()); -} - -list::const_iterator Header::findParameter (const string ¶mName) const { - L_D(); - return findIf(d->parameters, [¶mName](const HeaderParam ¶m) { - return param.getName() == paramName; - }); -} - -const HeaderParam &Header::getParameter (const string ¶mName) const { - L_D(); - list::const_iterator it = findParameter(paramName); - if (it != d->parameters.cend()) { - return *it; - } - return Utils::getEmptyConstRefObject(); -} - -string Header::asString () const { - stringstream asString; - if (!getName().empty()) { - asString << getName() << ":"; - } - asString << getValue(); - for (const auto ¶m : getParameters()) { - asString << param.asString(); - } - return asString.str(); -} - -ostream &operator<<(ostream& stream, const Header& header) { - stream << header.asString(); - return stream; -} - -LINPHONE_END_NAMESPACE \ No newline at end of file diff --git a/src/content/header/header.h b/src/content/header/header.h deleted file mode 100644 index 583572523..000000000 --- a/src/content/header/header.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * header.h - * 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, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef _L_HEADER_H_ -#define _L_HEADER_H_ - -#include - -#include "object/clonable-object.h" - -// ============================================================================= - -LINPHONE_BEGIN_NAMESPACE - -class HeaderPrivate; -class HeaderParam; - -class LINPHONE_PUBLIC Header : public ClonableObject { -public: - Header (); - Header (const std::string &name, const std::string &value); - Header (const std::string &name, const std::string &value, const std::list ¶ms); - Header (const Header &other); - - Header &operator= (const Header &other); - - bool operator== (const Header &other) const; - bool operator!= (const Header &other) const; - - void setName (const std::string &name); - std::string getName () const; - - void setValue (const std::string &value); - std::string getValue () const; - - void cleanParameters (); - const std::list &getParameters () const; - void addParameter (const std::string ¶mName, const std::string ¶mValue); - void addParameter (const HeaderParam ¶m); - void addParameters(const std::list ¶ms); - void removeParameter (const std::string ¶mName); - void removeParameter (const HeaderParam ¶m); - std::list::const_iterator findParameter (const std::string ¶mName) const; - const HeaderParam &getParameter (const std::string ¶mName) const; - - std::string asString () const; - friend std::ostream &operator<<(std::ostream&, const Header&); - -protected: - explicit Header (HeaderPrivate &p); - -private: - L_DECLARE_PRIVATE(Header); -}; - -LINPHONE_END_NAMESPACE - -#endif // ifndef _L_HEADER_H_ diff --git a/src/db/main-db.cpp b/src/db/main-db.cpp index ac26bff98..e6cfd375d 100644 --- a/src/db/main-db.cpp +++ b/src/db/main-db.cpp @@ -2226,7 +2226,7 @@ void MainDb::loadChatMessageContents (const shared_ptr &chatMessage string data; fetchContentAppData(session, *content, contentId, data); } - chatMessage->addContent(content); + chatMessage->addContent(*content); } // 2 - Load external body url from body into FileTransferContent if needed. diff --git a/src/sal/op.cpp b/src/sal/op.cpp index 497a7a99b..e5e211f3b 100644 --- a/src/sal/op.cpp +++ b/src/sal/op.cpp @@ -1029,18 +1029,12 @@ void SalOp::process_incoming_message(const belle_sip_request_event_t *event) { /* if we just deciphered a message, use the deciphered part(which can be a rcs xml body pointing to the file to retreive from server)*/ salmsg.text=(!external_body)?belle_sip_message_get_body(BELLE_SIP_MESSAGE(req)):NULL; salmsg.url=NULL; - - char buffer[1024]; - size_t offset = 0; - belle_sip_parameters_marshal(BELLE_SIP_PARAMETERS(content_type), buffer, 1024, &offset); - buffer[offset] = '\0'; - salmsg.content_type = ms_strdup_printf("%s/%s%s", belle_sip_header_content_type_get_type(content_type), belle_sip_header_content_type_get_subtype(content_type), buffer); + salmsg.content_type = ms_strdup_printf("%s/%s", belle_sip_header_content_type_get_type(content_type), belle_sip_header_content_type_get_subtype(content_type)); if (external_body && belle_sip_parameters_get_parameter(BELLE_SIP_PARAMETERS(content_type),"URL")) { size_t url_length=strlen(belle_sip_parameters_get_parameter(BELLE_SIP_PARAMETERS(content_type),"URL")); salmsg.url = ms_strdup(belle_sip_parameters_get_parameter(BELLE_SIP_PARAMETERS(content_type),"URL")+1); /* skip first "*/ ((char*)salmsg.url)[url_length-2]='\0'; /*remove trailing "*/ } - salmsg.message_id=message_id; salmsg.time=date ? belle_sip_header_date_get_time(date) : time(NULL); this->root->callbacks.message_received(this,&salmsg); diff --git a/tester/CMakeLists.txt b/tester/CMakeLists.txt index e07217934..b14e28572 100644 --- a/tester/CMakeLists.txt +++ b/tester/CMakeLists.txt @@ -199,7 +199,7 @@ set(SOURCE_FILES_C set(SOURCE_FILES_CXX clonable-object-tester.cpp conference-event-tester.cpp - contents-tester.cpp + content-manager-tester.cpp cpim-tester.cpp main-db-tester.cpp multipart-tester.cpp diff --git a/tester/contents-tester.cpp b/tester/content-manager-tester.cpp similarity index 62% rename from tester/contents-tester.cpp rename to tester/content-manager-tester.cpp index 99ecee08d..e21cc6399 100644 --- a/tester/contents-tester.cpp +++ b/tester/content-manager-tester.cpp @@ -21,15 +21,13 @@ #include "content/content-manager.h" #include "content/content-type.h" #include "content/content.h" -#include "content/header/header-param.h" #include "liblinphone_tester.h" #include "tester_utils.h" -#include "logger/logger.h" using namespace LinphonePrivate; using namespace std; -static const char* source_multipart = \ +static const char* multipart = \ "-----------------------------14737809831466499882746641449\r\n" \ "Content-Type: application/rlmi+xml;charset=\"UTF-8\"\r\n\r\n" \ "" \ @@ -62,7 +60,6 @@ static const char* source_multipart = \ " " \ "" \ "-----------------------------14737809831466499882746641449\r\n" \ -"Content-Encoding: b64\r\n" \ "Content-Type: application/pidf+xml;charset=\"UTF-8\"\r\n\r\n" \ "" \ "" \ @@ -80,7 +77,6 @@ static const char* source_multipart = \ " " \ "" \ "-----------------------------14737809831466499882746641449\r\n" \ -"Content-Id: toto;param1=value1;param2;param3=value3\r\n" \ "Content-Type: application/pidf+xml;charset=\"UTF-8\"\r\n\r\n" \ "" \ "" \ @@ -99,80 +95,6 @@ static const char* source_multipart = \ "" \ "-----------------------------14737809831466499882746641449--\r\n"; -static const char* generated_multipart = \ -"-----------------------------14737809831466499882746641449\r\n" \ -"Content-Type: application/rlmi+xml;charset=\"UTF-8\"\r\n" \ -"Content-Length:582\r\n\r\n" \ -"" \ -"" \ -" " \ -" " \ -" " \ -" " \ -" " \ -" " \ -" " \ -" " \ -" " \ -"" \ -"-----------------------------14737809831466499882746641449\r\n" \ -"Content-Type: application/pidf+xml;charset=\"UTF-8\"\r\n" \ -"Content-Length:561\r\n\r\n" \ -"" \ -"" \ -" " \ -" " \ -" open" \ -" " \ -" sip:+YYYYYYYYYY@sip.linphone.org;user=phone" \ -" 2017-10-25T13:18:26" \ -" " \ -" " \ -" " \ -" " \ -" " \ -" " \ -"" \ -"-----------------------------14737809831466499882746641449\r\n" \ -"Content-Encoding:b64\r\n" \ -"Content-Type: application/pidf+xml;charset=\"UTF-8\"\r\n" \ -"Content-Length:561\r\n\r\n" \ -"" \ -"" \ -" " \ -" " \ -" open" \ -" " \ -" sip:+XXXXXXXXXX@sip.linphone.org;user=phone" \ -" 2017-10-25T13:18:26" \ -" " \ -" " \ -" " \ -" " \ -" " \ -" " \ -"" \ -"-----------------------------14737809831466499882746641449\r\n" \ -"Content-Id:toto;param1=value1;param2;param3=value3\r\n" \ -"Content-Type: application/pidf+xml;charset=\"UTF-8\"\r\n" \ -"Content-Length:546\r\n\r\n" \ -"" \ -"" \ -" " \ -" " \ -" open" \ -" " \ -" sip:someone@sip.linphone.org" \ -" 2017-10-25T13:18:26" \ -" " \ -" " \ -" " \ -" " \ -" " \ -" " \ -"" \ -"-----------------------------14737809831466499882746641449--\r\n"; - static const char* part1 = \ "" \ "" \ @@ -240,7 +162,7 @@ static const char* part4 = \ void multipart_to_list () { Content multipartContent; - multipartContent.setBody(source_multipart); + multipartContent.setBody(multipart); multipartContent.setContentType(ContentType("multipart", "related")); list contents = ContentManager::multipartToContentList(multipartContent); @@ -298,7 +220,6 @@ void multipart_to_list () { ms_message("\n\n----- Original part 3 -----"); ms_message("%s", originalStr3.c_str()); BC_ASSERT_TRUE(originalStr3 == generatedStr3); - BC_ASSERT_TRUE(content3.getHeader("Content-Encoding").getValue() == "b64"); Content content4 = contents.front(); contents.pop_front(); @@ -313,43 +234,29 @@ void multipart_to_list () { generatedStr4.erase(std::remove(generatedStr4.begin(), generatedStr4.end(), '\r'), generatedStr4.end()); generatedStr4.erase(std::remove(generatedStr4.begin(), generatedStr4.end(), '\n'), generatedStr4.end()); ms_message("\n\n----- Generated part 4 -----"); - ms_message("%s", generatedStr4.c_str()); + ms_message("%s", generatedStr3.c_str()); ms_message("\n\n----- Original part 4 -----"); ms_message("%s", originalStr4.c_str()); BC_ASSERT_TRUE(originalStr4 == generatedStr4); - BC_ASSERT_TRUE(content4.getHeader("Content-Id").getValue() == "toto"); - BC_ASSERT_TRUE(content4.getHeader("Content-Id").getParameter("param1").getValue() == "value1"); - BC_ASSERT_TRUE(content4.getHeader("Content-Id").getParameter("param2").getValue().empty()); - BC_ASSERT_TRUE(content4.getHeader("Content-Id").getParameter("param3").getValue() == "value3"); } void list_to_multipart () { - ContentType contentType = ContentType("application", "rlmi+xml"); - contentType.addParameter("charset", "\"UTF-8\""); Content content1; content1.setBody(part1); - content1.setContentType(contentType); - contentType = ContentType("application", "pidf+xml"); - contentType.addParameter("charset", "\"UTF-8\""); + content1.setContentType(ContentType("application", "rlmi+xml")); Content content2; content2.setBody(part2); - content2.setContentType(contentType); + content2.setContentType(ContentType("application", "pidf+xml")); Content content3; content3.setBody(part3); - content3.addHeader("Content-Encoding", "b64"); - content3.setContentType(contentType); + content3.setContentType(ContentType("application", "pidf+xml")); Content content4; - Header header = Header("Content-Id", "toto"); - header.addParameter("param1", "value1"); - header.addParameter("param2", ""); - header.addParameter("param3", "value3"); - content4.addHeader(header); content4.setBody(part4); - content4.setContentType(contentType); - list contents = {&content1, &content2, &content3, &content4}; + content4.setContentType(ContentType("application", "pidf+xml")); + list contents = {content1, content2, content3, content4}; Content multipartContent = ContentManager::contentListToMultipart(contents); - string originalStr(generated_multipart); + string originalStr(multipart); originalStr.erase(std::remove(originalStr.begin(), originalStr.end(), ' '), originalStr.end()); originalStr.erase(std::remove(originalStr.begin(), originalStr.end(), '\t'), originalStr.end()); originalStr.erase(std::remove(originalStr.begin(), originalStr.end(), '\r'), originalStr.end()); @@ -369,67 +276,16 @@ void list_to_multipart () { BC_ASSERT_TRUE(originalStr == generatedStr); } -static void content_type_parsing(void) { - string type = "message/external-body;access-type=URL;URL=\"https://www.linphone.org/img/linphone-open-source-voip-projectX2.png\""; - ContentType contentType = ContentType(type); - BC_ASSERT_STRING_EQUAL("message", contentType.getType().c_str()); - BC_ASSERT_STRING_EQUAL("external-body", contentType.getSubType().c_str()); - BC_ASSERT_STRING_EQUAL("URL", contentType.getParameter("access-type").getValue().c_str()); - BC_ASSERT_STRING_EQUAL("\"https://www.linphone.org/img/linphone-open-source-voip-projectX2.png\"", contentType.getParameter("URL").getValue().c_str()); - BC_ASSERT_STRING_EQUAL("", contentType.getParameter("boundary").getValue().c_str()); - BC_ASSERT_EQUAL(2, contentType.getParameters().size(), int, "%d"); - lInfo() << "Content-Type is " << contentType; - BC_ASSERT_TRUE(type == contentType.asString()); - - type = "multipart/mixed;boundary=-----------------------------14737809831466499882746641450"; - contentType = ContentType(type); - BC_ASSERT_STRING_EQUAL("multipart", contentType.getType().c_str()); - BC_ASSERT_STRING_EQUAL("mixed", contentType.getSubType().c_str()); - BC_ASSERT_STRING_EQUAL("-----------------------------14737809831466499882746641450", contentType.getParameter("boundary").getValue().c_str()); - BC_ASSERT_STRING_EQUAL("", contentType.getParameter("access-type").getValue().c_str()); - BC_ASSERT_EQUAL(1, contentType.getParameters().size(), int, "%d"); - lInfo() << "Content-Type is " << contentType; - BC_ASSERT_TRUE(type == contentType.asString()); - - type = "plain/text"; - contentType = ContentType(type); - BC_ASSERT_STRING_EQUAL("plain", contentType.getType().c_str()); - BC_ASSERT_STRING_EQUAL("text", contentType.getSubType().c_str()); - BC_ASSERT_STRING_EQUAL("", contentType.getParameter("boundary").getValue().c_str()); - BC_ASSERT_EQUAL(0, contentType.getParameters().size(), int, "%d"); - lInfo() << "Content-Type is " << contentType; - BC_ASSERT_TRUE(type == contentType.asString()); -} - -static void content_header_parsing(void) { - string value = "toto;param1=value1;param2;param3=value3"; - Header header = Header("Content-Id", value); - BC_ASSERT_TRUE(header.getValue() == "toto"); - BC_ASSERT_TRUE(header.getParameter("param1").getValue() == "value1"); - BC_ASSERT_TRUE(header.getParameter("param2").getValue().empty()); - BC_ASSERT_TRUE(header.getParameter("param3").getValue() == "value3"); - BC_ASSERT_EQUAL(3, header.getParameters().size(), int, "%d"); - BC_ASSERT_STRING_EQUAL("", header.getParameter("encoding").getValue().c_str()); - - value = "b64"; - header = Header("Content-Encoding", value); - BC_ASSERT_TRUE(header.getValue() == value); - BC_ASSERT_EQUAL(0, header.getParameters().size(), int, "%d"); - BC_ASSERT_STRING_EQUAL("", header.getParameter("access-type").getValue().c_str()); -} - -test_t contents_tests[] = { +test_t content_manager_tests[] = { TEST_NO_TAG("Multipart to list", multipart_to_list), - TEST_NO_TAG("List to multipart", list_to_multipart), - TEST_NO_TAG("Content type parsing", content_type_parsing), - TEST_NO_TAG("Content header parsing", content_header_parsing) + TEST_NO_TAG("List to multipart", list_to_multipart) }; -test_suite_t contents_test_suite = { - "Contents", +test_suite_t content_manager_test_suite = { + "Content manager", nullptr, nullptr, liblinphone_tester_before_each, liblinphone_tester_after_each, - sizeof(contents_tests) / sizeof(contents_tests[0]), contents_tests + sizeof(content_manager_tests) / sizeof(content_manager_tests[0]), content_manager_tests }; diff --git a/tester/cpim-tester.cpp b/tester/cpim-tester.cpp index 66cc661d8..e803ae33a 100644 --- a/tester/cpim-tester.cpp +++ b/tester/cpim-tester.cpp @@ -423,12 +423,12 @@ static void cpim_chat_message_modifier_base(bool_t use_multipart) { Content *content = new Content(); content->setContentType(ContentType::PlainText); content->setBody("Hello Part 2"); - marieMessage->addContent(content); + marieMessage->addContent(*content); } marieMessage->send(); BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneMessageReceived,1)); - BC_ASSERT_TRUE(marieMessage->getInternalContent().getContentType().isEmpty()); // Internal content is cleaned after message is sent or received + BC_ASSERT_STRING_EQUAL(marieMessage->getInternalContent().getContentType().asString().c_str(), ""); // Internal content is cleaned after message is sent or received BC_ASSERT_PTR_NOT_NULL(pauline->stat.last_received_chat_message); if (pauline->stat.last_received_chat_message != NULL) { diff --git a/tester/eventapi_tester.c b/tester/eventapi_tester.c index 66ae0f165..2119f3500 100644 --- a/tester/eventapi_tester.c +++ b/tester/eventapi_tester.c @@ -41,7 +41,7 @@ void linphone_notify_received(LinphoneCore *lc, LinphoneEvent *lev, const char * if (!BC_ASSERT_PTR_NOT_NULL(content)) return; if (!linphone_content_is_multipart(content) && (!ua || !strstr(ua, "flexisip"))) { /*disable check for full presence server support*/ /*hack to disable content checking for list notify */ - BC_ASSERT_STRING_EQUAL((const char*)linphone_content_get_buffer(content),notify_content); + BC_ASSERT_STRING_EQUAL(notify_content,(const char*)linphone_content_get_buffer(content)); } mgr=get_manager(lc); mgr->stat.number_of_NotifyReceived++; diff --git a/tester/liblinphone_tester.h b/tester/liblinphone_tester.h index c96be9ed4..9824c2084 100644 --- a/tester/liblinphone_tester.h +++ b/tester/liblinphone_tester.h @@ -45,7 +45,7 @@ extern test_suite_t call_video_test_suite; extern test_suite_t clonable_object_test_suite; extern test_suite_t conference_event_test_suite; extern test_suite_t conference_test_suite; -extern test_suite_t contents_test_suite; +extern test_suite_t content_manager_test_suite; extern test_suite_t cpim_test_suite; extern test_suite_t dtmf_test_suite; extern test_suite_t event_test_suite; diff --git a/tester/message_tester.c b/tester/message_tester.c index 8922adf20..396f4b9c4 100644 --- a/tester/message_tester.c +++ b/tester/message_tester.c @@ -2294,19 +2294,15 @@ void text_message_with_custom_content_type_and_lime(void) { static int im_encryption_engine_process_incoming_message_cb(LinphoneImEncryptionEngine *engine, LinphoneChatRoom *room, LinphoneChatMessage *msg) { - ms_debug("IM encryption process incoming message with content type %s", linphone_chat_message_get_content_type(msg)); if (linphone_chat_message_get_content_type(msg)) { if (strcmp(linphone_chat_message_get_content_type(msg), "cipher/b64") == 0) { size_t b64Size = 0; unsigned char *output; - const char *data = linphone_chat_message_get_text(msg); - ms_debug("IM encryption process incoming message crypted message is %s", data); - bctbx_base64_decode(NULL, &b64Size, (unsigned char *)data, strlen(data)); + bctbx_base64_decode(NULL, &b64Size, (unsigned char *)linphone_chat_message_get_text(msg), strlen(linphone_chat_message_get_text(msg))); output = (unsigned char *)ms_malloc(b64Size+1), - bctbx_base64_decode(output, &b64Size, (unsigned char *)data, strlen(data)); + bctbx_base64_decode(output, &b64Size, (unsigned char *)linphone_chat_message_get_text(msg), strlen(linphone_chat_message_get_text(msg))); output[b64Size] = '\0'; linphone_chat_message_set_text(msg, (char *)output); - ms_debug("IM encryption process incoming message decrypted message is %s", output); ms_free(output); linphone_chat_message_set_content_type(msg, "text/plain"); return 0; diff --git a/tester/multipart-tester.cpp b/tester/multipart-tester.cpp index c94dc9a2e..3fdd9073a 100644 --- a/tester/multipart-tester.cpp +++ b/tester/multipart-tester.cpp @@ -53,13 +53,13 @@ static void chat_message_multipart_modifier_base(bool first_file_transfer, bool content->setContentType(ContentType("video/mkv")); content->setFilePath(send_filepath); content->setFileName("sintel_trailer_opus_h264.mkv"); - marieMessage->addContent(content); + marieMessage->addContent(*content); bc_free(send_filepath); } else { Content *content = new Content(); content->setContentType(ContentType::PlainText); - content->setBody("Hello part 1"); - marieMessage->addContent(content); + content->setBody("Hello Part 1"); + marieMessage->addContent(*content); } if (second_file_transfer) { @@ -68,13 +68,13 @@ static void chat_message_multipart_modifier_base(bool first_file_transfer, bool content->setContentType(ContentType("file/vcf")); content->setFilePath(send_filepath); content->setFileName("vcards.vcf"); - marieMessage->addContent(content); + marieMessage->addContent(*content); bc_free(send_filepath); } else { Content *content = new Content(); content->setContentType(ContentType::PlainText); - content->setBody("Hello part 2"); - marieMessage->addContent(content); + content->setBody("Hello Part 2"); + marieMessage->addContent(*content); } linphone_core_set_file_transfer_server(marie->lc,"https://www.linphone.org:444/lft.php"); @@ -82,20 +82,7 @@ static void chat_message_multipart_modifier_base(bool first_file_transfer, bool BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneMessageReceived,1)); BC_ASSERT_PTR_NOT_NULL(pauline->stat.last_received_chat_message); - - if (first_file_transfer || second_file_transfer) { - LinphoneContent *content = linphone_chat_message_get_file_transfer_information(pauline->stat.last_received_chat_message); - BC_ASSERT_PTR_NOT_NULL(content); - linphone_content_unref(content); - } - if (!first_file_transfer || !second_file_transfer) { - const char *content = linphone_chat_message_get_text_content(pauline->stat.last_received_chat_message); - BC_ASSERT_PTR_NOT_NULL(content); - if (!first_file_transfer) - BC_ASSERT_STRING_EQUAL(content, "Hello part 1"); - else if (!second_file_transfer) - BC_ASSERT_STRING_EQUAL(content, "Hello part 2"); - } + BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_content_type(pauline->stat.last_received_chat_message), "multipart/mixed"); linphone_core_manager_destroy(marie); linphone_core_manager_destroy(pauline); diff --git a/tester/presence_server_tester.c b/tester/presence_server_tester.c index c0587fe7d..db3f0ca07 100644 --- a/tester/presence_server_tester.c +++ b/tester/presence_server_tester.c @@ -430,10 +430,8 @@ static void test_presence_list_base(bool_t enable_compression) { lcs = bctbx_list_append(lcs, pauline->lc); wait_for_list(lcs, &laure->stat.number_of_NotifyPresenceReceived, 2, 4000); - BC_ASSERT_GREATER(laure->stat.number_of_NotifyPresenceReceived, 2, int, "%d"); - BC_ASSERT_LOWER(laure->stat.number_of_NotifyPresenceReceived, 3, int, "%d"); - BC_ASSERT_GREATER(linphone_friend_list_get_expected_notification_version(linphone_core_get_default_friend_list(laure->lc)), 1, int, "%d"); - BC_ASSERT_LOWER(linphone_friend_list_get_expected_notification_version(linphone_core_get_default_friend_list(laure->lc)), 2, int, "%d"); + BC_ASSERT_EQUAL(laure->stat.number_of_NotifyPresenceReceived, 2, int, "%d"); + BC_ASSERT_EQUAL(linphone_friend_list_get_expected_notification_version(linphone_core_get_default_friend_list(laure->lc)), 1, int, "%d"); lf = linphone_friend_list_find_friend_by_address(linphone_core_get_default_friend_list(laure->lc), get_identity_address(marie)); if (!BC_ASSERT_PTR_NOT_NULL(lf)) goto end; BC_ASSERT_EQUAL(linphone_friend_get_status(lf), LinphoneStatusBusy, int, "%d"); @@ -487,8 +485,7 @@ static void test_presence_list_base(bool_t enable_compression) { /* The number of PresenceReceived events can be 3 or 4 here. TODO: ideally it should always be 3. */ BC_ASSERT_GREATER(laure->stat.number_of_NotifyPresenceReceived, 3, int, "%d"); BC_ASSERT_LOWER(laure->stat.number_of_NotifyPresenceReceived, 4, int, "%d"); - BC_ASSERT_GREATER(linphone_friend_list_get_expected_notification_version(linphone_core_get_default_friend_list(laure->lc)), 2, int, "%d"); - BC_ASSERT_LOWER(linphone_friend_list_get_expected_notification_version(linphone_core_get_default_friend_list(laure->lc)), 3, int, "%d"); + BC_ASSERT_EQUAL(linphone_friend_list_get_expected_notification_version(linphone_core_get_default_friend_list(laure->lc)), 2, int, "%d"); lf = linphone_friend_list_find_friend_by_address(linphone_core_get_default_friend_list(laure->lc), get_identity_address(marie)); BC_ASSERT_EQUAL(linphone_friend_get_status(lf), LinphoneStatusOnThePhone, int, "%d"); diff --git a/tester/tester.c b/tester/tester.c index cd8481381..6eaafeab9 100644 --- a/tester/tester.c +++ b/tester/tester.c @@ -606,7 +606,7 @@ void liblinphone_tester_add_suites() { bc_tester_add_suite(&stun_test_suite); bc_tester_add_suite(&event_test_suite); bc_tester_add_suite(&conference_event_test_suite); - bc_tester_add_suite(&contents_test_suite); + bc_tester_add_suite(&content_manager_test_suite); bc_tester_add_suite(&flexisip_test_suite); bc_tester_add_suite(&remote_provisioning_test_suite); bc_tester_add_suite(&quality_reporting_test_suite);