From 1948fbcb074e042a7bf3b25381eaff73e2280c37 Mon Sep 17 00:00:00 2001 From: Jehan Monnier Date: Fri, 8 Sep 2017 15:10:39 +0200 Subject: [PATCH] Revert most of Ronan refactoring to avoid to much instability on master. --- coreapi/CMakeLists.txt | 4 +- coreapi/address.c | 221 ++++ coreapi/bellesip_sal/sal_address_impl.c | 3 +- coreapi/bellesip_sal/sal_op_call.c | 3 - coreapi/bellesip_sal/sal_op_registration.c | 4 +- coreapi/call_log.c | 6 - coreapi/callbacks.c | 23 +- coreapi/chat.c | 986 +++++++++++++++-- coreapi/chat_file_transfer.c | 51 +- coreapi/event.c | 57 +- coreapi/factory.c | 28 +- coreapi/help/doc/doxygen/CMakeLists.txt | 62 +- coreapi/help/doc/doxygen/Doxyfile.in | 4 +- coreapi/lime.c | 8 +- coreapi/linphonecall.c | 67 +- coreapi/linphonecore.c | 18 +- coreapi/message_storage.c | 378 ++++++- coreapi/presence.c | 7 +- coreapi/private.h | 55 +- coreapi/proxy.c | 106 +- coreapi/quality_reporting.c | 10 +- coreapi/sal/sal.c | 942 ----------------- coreapi/video_definition.c | 18 +- gtk/calllogs.c | 6 - include/CMakeLists.txt | 92 +- include/linphone/address.h | 241 +++++ include/linphone/api/c-address.h | 242 ----- include/linphone/api/c-api.h | 25 - include/linphone/core.h | 3 +- include/linphone/types.h | 22 +- {coreapi => include}/sal/sal.h | 2 +- .../org/linphone/core/LinphoneCallLog.java | 10 - src/CMakeLists.txt | 25 +- src/address/address-p.h | 59 -- src/address/address.cpp | 354 ------- src/address/address.h | 100 -- src/c-wrapper/api/c-address.cpp | 192 ---- src/c-wrapper/api/c-event-log.cpp | 6 +- .../c-wrapper}/api/c-event-log.h | 4 +- src/c-wrapper/c-tools.h | 77 +- .../linphone/api => src/c-wrapper}/c-types.h | 56 +- src/chat/chat-room-p.h | 113 -- src/chat/chat-room.cpp | 993 ------------------ src/chat/chat-room.h | 70 -- src/chat/imdn.cpp | 104 -- src/chat/imdn.h | 47 - src/chat/is-composing-listener.h | 37 - src/chat/is-composing.cpp | 267 ----- src/chat/is-composing.h | 78 -- src/cpim/header/cpim-generic-header.cpp | 3 +- src/cpim/message/cpim-message.cpp | 3 +- src/cpim/parser/cpim-grammar.h | 2 +- src/cpim/parser/cpim-parser.cpp | 3 +- src/db/abstract/abstract-db.cpp | 15 +- src/db/events-db.cpp | 117 +-- src/enums.h | 37 - src/event-log/conference-event.cpp | 14 +- .../conference-participant-event.cpp | 11 +- .../enums => src/event-log}/event-log-enums.h | 2 +- src/event-log/event-log.h | 3 +- src/logger/logger.h | 10 +- .../chat-message.cpp => message/message.cpp} | 98 +- .../chat-message.h => message/message.h} | 19 +- src/object/clonable-object-p.h | 7 +- src/object/clonable-object.cpp | 2 +- src/object/clonable-object.h | 2 +- src/object/object-p.h | 2 +- src/object/object.h | 2 +- src/utils/content-type.cpp | 43 - src/utils/content-type.h | 39 - .../linphone => src}/utils/enum-generator.h | 2 +- src/utils/general.cpp | 4 +- {include/linphone => src}/utils/general.h | 13 +- .../linphone => src}/utils/magic-macros.h | 2 +- src/utils/utils.cpp | 55 +- {include/linphone => src}/utils/utils.h | 21 +- tester/CMakeLists.txt | 24 +- tester/call_single_tester.c | 30 +- tester/clonable-object-tester.cpp | 66 -- tester/{cpim-tester.cpp => cpim_tester.cpp} | 26 +- tester/db/linphone.db | Bin 18432 -> 0 bytes tester/events-db-tester.cpp | 50 - tester/flexisip_tester.c | 2 +- tester/liblinphone_tester.c | 1 - tester/liblinphone_tester.h | 2 - tester/message_tester.c | 18 +- tester/{db => }/messages.db | Bin tester/presence_tester.c | 37 +- tester/register_tester.c | 13 +- tester/setup_tester.c | 14 +- tester/tester.c | 3 - wrappers/csharp/genwrapper.py | 25 +- 92 files changed, 2180 insertions(+), 4948 deletions(-) create mode 100644 coreapi/address.c delete mode 100644 coreapi/sal/sal.c create mode 100644 include/linphone/address.h delete mode 100644 include/linphone/api/c-address.h delete mode 100644 include/linphone/api/c-api.h rename {coreapi => include}/sal/sal.h (99%) delete mode 100644 src/address/address-p.h delete mode 100644 src/address/address.cpp delete mode 100644 src/address/address.h delete mode 100644 src/c-wrapper/api/c-address.cpp rename {include/linphone => src/c-wrapper}/api/c-event-log.h (97%) rename {include/linphone/api => src/c-wrapper}/c-types.h (51%) delete mode 100644 src/chat/chat-room-p.h delete mode 100644 src/chat/chat-room.cpp delete mode 100644 src/chat/chat-room.h delete mode 100644 src/chat/imdn.cpp delete mode 100644 src/chat/imdn.h delete mode 100644 src/chat/is-composing-listener.h delete mode 100644 src/chat/is-composing.cpp delete mode 100644 src/chat/is-composing.h delete mode 100644 src/enums.h rename {include/linphone/enums => src/event-log}/event-log-enums.h (96%) rename src/{chat/chat-message.cpp => message/message.cpp} (53%) rename src/{chat/chat-message.h => message/message.h} (89%) delete mode 100644 src/utils/content-type.cpp delete mode 100644 src/utils/content-type.h rename {include/linphone => src}/utils/enum-generator.h (96%) rename {include/linphone => src}/utils/general.h (92%) rename {include/linphone => src}/utils/magic-macros.h (99%) rename {include/linphone => src}/utils/utils.h (65%) delete mode 100644 tester/clonable-object-tester.cpp rename tester/{cpim-tester.cpp => cpim_tester.cpp} (96%) delete mode 100644 tester/db/linphone.db delete mode 100644 tester/events-db-tester.cpp rename tester/{db => }/messages.db (100%) diff --git a/coreapi/CMakeLists.txt b/coreapi/CMakeLists.txt index a22bfc5ed..3eddeb895 100644 --- a/coreapi/CMakeLists.txt +++ b/coreapi/CMakeLists.txt @@ -45,7 +45,6 @@ list(APPEND LINPHONE_PRIVATE_HEADER_FILES offeranswer.h private.h quality_reporting.h - sal/sal.h sqlite3_bctbx_vfs.h vcard_private.h xml2lpc.h @@ -54,6 +53,7 @@ list(APPEND LINPHONE_PRIVATE_HEADER_FILES set(LINPHONE_SOURCE_FILES_C account_creator.c account_creator_service.c + address.c authentication.c bellesip_sal/sal_address_impl.c bellesip_sal/sal_impl.c @@ -109,7 +109,7 @@ set(LINPHONE_SOURCE_FILES_C quality_reporting.c remote_provisioning.c ringtoneplayer.c - sal/sal.c + sal.c siplogin.c sipsetup.c sqlite3_bctbx_vfs.c diff --git a/coreapi/address.c b/coreapi/address.c new file mode 100644 index 000000000..696ff0ba8 --- /dev/null +++ b/coreapi/address.c @@ -0,0 +1,221 @@ +/* +linphone +Copyright (C) 2009 Simon MORLAT (simon.morlat@linphone.org) + +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 "linphone/lpconfig.h" +#include "private.h" + +LinphoneAddress * _linphone_address_new(const char *addr){ + SalAddress *saddr=sal_address_new(addr); + if (saddr==NULL) + ms_error("Cannot create LinphoneAddress, bad uri [%s]",addr); + return saddr; +} + +LinphoneAddress * linphone_address_new(const char *addr) { + return _linphone_address_new(addr); +} + +LinphoneAddress * linphone_address_clone(const LinphoneAddress *addr){ + return sal_address_clone(addr); +} + +LinphoneAddress * linphone_address_ref(LinphoneAddress *addr){ + return sal_address_ref(addr); +} + +void linphone_address_unref(LinphoneAddress *addr){ + sal_address_unref(addr); +} + +const char *linphone_address_get_scheme(const LinphoneAddress *u){ + return sal_address_get_scheme(u); +} + +const char *linphone_address_get_display_name(const LinphoneAddress* u){ + return sal_address_get_display_name(u); +} + +const char *linphone_address_get_username(const LinphoneAddress *u){ + return sal_address_get_username(u); +} + +const char *linphone_address_get_domain(const LinphoneAddress *u){ + return sal_address_get_domain(u); +} + +int linphone_address_get_port(const LinphoneAddress *u) { + return sal_address_get_port(u); +} + +LinphoneStatus linphone_address_set_display_name(LinphoneAddress *u, const char *display_name){ + sal_address_set_display_name(u,display_name); + return 0; +} + +LinphoneStatus linphone_address_set_username(LinphoneAddress *uri, const char *username) { + sal_address_set_username(uri,username); + return 0; +} + +LinphoneStatus linphone_address_set_domain(LinphoneAddress *uri, const char *host){ + sal_address_set_domain(uri,host); + return 0; +} + +LinphoneStatus linphone_address_set_port(LinphoneAddress *uri, int port){ + sal_address_set_port(uri,port); + return 0; +} + +LinphoneStatus linphone_address_set_transport(LinphoneAddress *uri, LinphoneTransportType tp){ + sal_address_set_transport(uri,(SalTransport)tp); + return 0; +} + +LinphoneTransportType linphone_address_get_transport(const LinphoneAddress *uri){ + return (LinphoneTransportType)sal_address_get_transport(uri); +} + +void linphone_address_set_method_param(LinphoneAddress *addr, const char *method) { + sal_address_set_method_param(addr, method); +} + +const char *linphone_address_get_method_param(const LinphoneAddress *addr) { + return sal_address_get_method_param(addr); +} + +void linphone_address_clean(LinphoneAddress *uri){ + sal_address_clean(uri); +} + +char *linphone_address_as_string(const LinphoneAddress *u){ + return sal_address_as_string(u); +} + +char *linphone_address_as_string_uri_only(const LinphoneAddress *u){ + return sal_address_as_string_uri_only(u); +} + +bool_t linphone_address_is_secure(const LinphoneAddress *uri){ + return sal_address_is_secure(uri); +} + +bool_t linphone_address_get_secure(const LinphoneAddress *uri){ + return sal_address_is_secure(uri); +} + +void linphone_address_set_secure(LinphoneAddress *addr, bool_t enabled){ + sal_address_set_secure(addr, enabled); +} + +bool_t linphone_address_is_sip(const LinphoneAddress *uri){ + return sal_address_is_sip(uri); +} + +static bool_t strings_equals(const char *s1, const char *s2){ + if (s1==NULL && s2==NULL) return TRUE; + if (s1!=NULL && s2!=NULL && strcmp(s1,s2)==0) return TRUE; + return FALSE; +} + +bool_t linphone_address_weak_equal(const LinphoneAddress *a1, const LinphoneAddress *a2){ + const char *u1,*u2; + const char *h1,*h2; + int p1,p2; + u1=linphone_address_get_username(a1); + u2=linphone_address_get_username(a2); + p1=linphone_address_get_port(a1); + p2=linphone_address_get_port(a2); + h1=linphone_address_get_domain(a1); + h2=linphone_address_get_domain(a2); + return strings_equals(u1,u2) && strings_equals(h1,h2) && p1==p2; +} + +bool_t linphone_address_equal(const LinphoneAddress *a1, const LinphoneAddress *a2) { + char *s1; + char *s2; + bool_t res; + if ((a1 == NULL) && (a2 == NULL)) return TRUE; + if ((a1 == NULL) || (a2 == NULL)) return FALSE; + s1 = linphone_address_as_string(a1); + s2 = linphone_address_as_string(a2); + res = (strcmp(s1, s2) == 0) ? TRUE : FALSE; + ms_free(s1); + ms_free(s2); + return res; +} + +void linphone_address_destroy(LinphoneAddress *u){ + linphone_address_unref(u); +} + +void linphone_address_set_password(LinphoneAddress *addr, const char *passwd){ + sal_address_set_password(addr,passwd); +} + +const char *linphone_address_get_password(const LinphoneAddress *addr){ + return sal_address_get_password(addr); +} + +void linphone_address_set_header(LinphoneAddress *addr, const char *header_name, const char *header_value){ + sal_address_set_header(addr,header_name,header_value); +} + +const char *linphone_address_get_header(const LinphoneAddress *addr, const char *name){ + return sal_address_get_header(addr,name); +} + +bool_t linphone_address_has_param(const LinphoneAddress *addr, const char *name) { + return sal_address_has_param(addr, name); +} + +const char * linphone_address_get_param(const LinphoneAddress *addr, const char *name) { + return sal_address_get_param(addr, name); +} + +void linphone_address_set_param(LinphoneAddress *addr, const char *name, const char *value) { + sal_address_set_param(addr, name, value); +} + +void linphone_address_set_params(LinphoneAddress *addr, const char *params) { + sal_address_set_params(addr, params); +} + +void linphone_address_set_uri_param(LinphoneAddress *addr, const char *name, const char *value) { + sal_address_set_uri_param(addr, name, value); +} + +void linphone_address_set_uri_params(LinphoneAddress *addr, const char *params) { + sal_address_set_uri_params(addr, params); +} + +bool_t linphone_address_has_uri_param(const LinphoneAddress *addr, const char *name) { + return sal_address_has_uri_param(addr, name); +} + +const char * linphone_address_get_uri_param(const LinphoneAddress *addr, const char *name) { + return sal_address_get_uri_param(addr, name); +} + +LinphoneAddress * linphone_core_create_address(LinphoneCore *lc, const char *address) { + return linphone_address_new(address); +} + +/** @} */ diff --git a/coreapi/bellesip_sal/sal_address_impl.c b/coreapi/bellesip_sal/sal_address_impl.c index 6d89ef8aa..dbeb9b8e0 100644 --- a/coreapi/bellesip_sal/sal_address_impl.c +++ b/coreapi/bellesip_sal/sal_address_impl.c @@ -33,7 +33,7 @@ SalAddress * sal_address_new(const char *uri){ } SalAddress * sal_address_clone(const SalAddress *addr){ - return (SalAddress *) belle_sip_object_ref(belle_sip_header_address_clone(BELLE_SIP_HEADER_ADDRESS(addr))); + return (SalAddress *) belle_sip_object_ref(belle_sip_object_clone(BELLE_SIP_OBJECT(addr))); } const char *sal_address_get_scheme(const SalAddress *addr){ @@ -277,3 +277,4 @@ bool_t sal_address_is_ipv6(const SalAddress *addr){ void sal_address_destroy(SalAddress *addr){ sal_address_unref(addr); } + diff --git a/coreapi/bellesip_sal/sal_op_call.c b/coreapi/bellesip_sal/sal_op_call.c index c6e35e1db..c8a06a95b 100644 --- a/coreapi/bellesip_sal/sal_op_call.c +++ b/coreapi/bellesip_sal/sal_op_call.c @@ -1141,9 +1141,6 @@ int sal_call_terminate_with_error(SalOp *op, const SalErrorInfo *info){ * The state is passed to Terminating to remember to terminate later. */ op->state=SalOpStateTerminating; - /* However, even if the transaction is kept alive, we can stop sending retransmissions to avoid flowing the network with no longer - * necessary messages and avoid confusion in logs.*/ - belle_sip_client_transaction_stop_retransmissions(op->pending_client_trans); } } break; diff --git a/coreapi/bellesip_sal/sal_op_registration.c b/coreapi/bellesip_sal/sal_op_registration.c index 0bff2470d..3526152e0 100644 --- a/coreapi/bellesip_sal/sal_op_registration.c +++ b/coreapi/bellesip_sal/sal_op_registration.c @@ -84,7 +84,7 @@ static void register_refresher_listener (belle_sip_refresher_t* refresher } } -int sal_register(SalOp *op, const char *proxy, const char *from, int expires, const SalAddress* old_contact){ +int sal_register(SalOp *op, const char *proxy, const char *from, int expires,SalAddress* old_contact){ belle_sip_request_t *req; belle_sip_uri_t* req_uri; belle_sip_header_t* accept_header; @@ -135,3 +135,5 @@ int sal_register_refresh(SalOp *op, int expires){ int sal_unregister(SalOp *op){ return sal_register_refresh(op,0); } + + diff --git a/coreapi/call_log.c b/coreapi/call_log.c index 47e689b1a..d0f67d781 100644 --- a/coreapi/call_log.c +++ b/coreapi/call_log.c @@ -238,12 +238,6 @@ char * linphone_call_log_to_str(LinphoneCallLog *cl){ case LinphoneCallMissed: status=_("missed"); break; - case LinphoneCallAcceptedElsewhere: - status=_("answered elsewhere"); - break; - case LinphoneCallDeclinedElsewhere: - status=_("declined elsewhere"); - break; default: status=_("unknown"); } diff --git a/coreapi/callbacks.c b/coreapi/callbacks.c index 155d87db4..83aad97d3 100644 --- a/coreapi/callbacks.c +++ b/coreapi/callbacks.c @@ -950,20 +950,19 @@ static void call_failure(SalOp *op){ case SalReasonRedirect: { linphone_call_stop_media_streams(call); - if ( - call->state == LinphoneCallOutgoingInit || - call->state == LinphoneCallOutgoingProgress || - call->state == LinphoneCallOutgoingRinging || - call->state == LinphoneCallOutgoingEarlyMedia - ) { - const SalAddress* redirection_to = sal_op_get_remote_contact_address(call->op); - if (redirection_to) { - char *url = sal_address_as_string(redirection_to); + if ( call->state==LinphoneCallOutgoingInit + || call->state==LinphoneCallOutgoingProgress + || call->state==LinphoneCallOutgoingRinging /*push case*/ + || call->state==LinphoneCallOutgoingEarlyMedia){ + LinphoneAddress* redirection_to = (LinphoneAddress*)sal_op_get_remote_contact_address(call->op); + if( redirection_to ){ + char* url = linphone_address_as_string(redirection_to); ms_warning("Redirecting call [%p] to %s",call, url); - if (call->log->to) - linphone_address_unref(call->log->to); - call->log->to = linphone_address_new(url); ms_free(url); + if( call->log->to != NULL ) { + linphone_address_unref(call->log->to); + } + call->log->to = linphone_address_ref(redirection_to); linphone_call_restart_invite(call); return; } diff --git a/coreapi/chat.c b/coreapi/chat.c index 3710ad7f6..2d0a9dc18 100644 --- a/coreapi/chat.c +++ b/coreapi/chat.c @@ -22,12 +22,6 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include -#include -#include - -#include - #include "linphone/core.h" #include "private.h" #include "linphone/lpconfig.h" @@ -35,20 +29,22 @@ #include "ortp/b64.h" #include "linphone/wrapper_utils.h" -#include "c-wrapper/c-tools.h" -#include "chat/chat-room-p.h" -#include "chat/chat-room.h" -#include "utils/content-type.h" +#include +#include +#include -struct _LinphoneChatRoom{ - belle_sip_object_t base; - void *user_data; - LinphonePrivate::ChatRoom *cr; -}; - -BELLE_SIP_DECLARE_VPTR_NO_EXPORT(LinphoneChatRoom); +#define COMPOSING_DEFAULT_IDLE_TIMEOUT 15 +#define COMPOSING_DEFAULT_REFRESH_TIMEOUT 60 +#define COMPOSING_DEFAULT_REMOTE_REFRESH_TIMEOUT 120 +static void linphone_chat_message_release(LinphoneChatMessage *msg); +static void linphone_chat_room_delete_composing_idle_timer(LinphoneChatRoom *cr); +static void linphone_chat_room_delete_composing_refresh_timer(LinphoneChatRoom *cr); +static void linphone_chat_room_delete_remote_composing_refresh_timer(LinphoneChatRoom *cr); static void _linphone_chat_message_destroy(LinphoneChatMessage *msg); +static void linphone_chat_room_notify_is_composing(LinphoneChatRoom *cr, const char *text); +static void linphone_chat_room_notify_imdn(LinphoneChatRoom *cr, const char *text); +static void linphone_chat_message_deactivate(LinphoneChatMessage *msg); BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(LinphoneChatMessageCbs); @@ -120,6 +116,31 @@ void linphone_chat_message_cbs_set_file_transfer_progress_indication( BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(LinphoneChatMessage); +static void _linphone_chat_room_destroy(LinphoneChatRoom *cr) { + linphone_chat_room_delete_composing_idle_timer(cr); + linphone_chat_room_delete_composing_refresh_timer(cr); + linphone_chat_room_delete_remote_composing_refresh_timer(cr); + bctbx_list_free_with_data(cr->transient_messages, (bctbx_list_free_func)linphone_chat_message_release); + if (cr->weak_messages != NULL) bctbx_list_free(cr->weak_messages); + if (cr->received_rtt_characters) { + cr->received_rtt_characters = bctbx_list_free_with_data(cr->received_rtt_characters, (bctbx_list_free_func)ms_free); + } + if (cr->lc != NULL) { + if (bctbx_list_find(cr->lc->chatrooms, cr)) { + ms_error("LinphoneChatRoom[%p] is destroyed while still being used by the LinphoneCore. This is abnormal." + " linphone_core_get_chat_room() doesn't give a reference, there is no need to call " + "linphone_chat_room_unref(). " + "In order to remove a chat room from the core, use linphone_core_delete_chat_room().", + cr); + cr->lc->chatrooms = bctbx_list_remove(cr->lc->chatrooms, cr); + } + } + linphone_address_unref(cr->peer_url); + if (cr->pending_message) + linphone_chat_message_destroy(cr->pending_message); + ms_free(cr->peer); +} + void linphone_chat_message_set_state(LinphoneChatMessage *msg, LinphoneChatMessageState state) { /* do not invoke callbacks on orphan messages */ if (state != msg->state && msg->chat_room != NULL) { @@ -163,25 +184,24 @@ const bctbx_list_t *linphone_core_get_chat_rooms(LinphoneCore *lc) { } static bool_t linphone_chat_room_matches(LinphoneChatRoom *cr, const LinphoneAddress *from) { - return linphone_address_weak_equal(cr->cr->getPeerAddress(), from); + return linphone_address_weak_equal(cr->peer_url, from); } BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(LinphoneChatRoom); -static void _linphone_chat_room_destroy(LinphoneChatRoom *cr) { - delete cr->cr; -} - BELLE_SIP_INSTANCIATE_VPTR(LinphoneChatRoom, belle_sip_object_t, (belle_sip_object_destroy_t)_linphone_chat_room_destroy, NULL, // clone NULL, // marshal FALSE); -LinphoneChatRoom *_linphone_core_create_chat_room_base(LinphoneCore *lc, LinphoneAddress *addr){ +static LinphoneChatRoom *_linphone_core_create_chat_room_base(LinphoneCore *lc, LinphoneAddress *addr){ LinphoneChatRoom *cr = belle_sip_object_new(LinphoneChatRoom); - cr->cr = new LinphonePrivate::ChatRoom(lc, addr); - L_GET_PRIVATE(cr->cr)->setCBackPointer(cr); + cr->lc = lc; + cr->peer = linphone_address_as_string(addr); + cr->peer_url = addr; + cr->unread_count = -1; + cr->received_rtt_characters = NULL; return cr; } @@ -194,7 +214,7 @@ static LinphoneChatRoom *_linphone_core_create_chat_room(LinphoneCore *lc, Linph LinphoneChatRoom *_linphone_core_create_chat_room_from_call(LinphoneCall *call){ LinphoneChatRoom *cr = _linphone_core_create_chat_room_base(call->core, linphone_address_clone(linphone_call_get_remote_address(call))); - linphone_chat_room_set_call(cr, call); + cr->call = call; return cr; } @@ -245,7 +265,7 @@ LinphoneChatRoom *linphone_core_get_chat_room(LinphoneCore *lc, const LinphoneAd void linphone_core_delete_chat_room(LinphoneCore *lc, LinphoneChatRoom *cr) { if (bctbx_list_find(lc->chatrooms, cr)) { - lc->chatrooms = bctbx_list_remove(lc->chatrooms, cr); + lc->chatrooms = bctbx_list_remove(cr->lc->chatrooms, cr); linphone_chat_room_delete_history(cr); linphone_chat_room_unref(cr); } else { @@ -257,12 +277,57 @@ LinphoneChatRoom *linphone_core_get_chat_room_from_uri(LinphoneCore *lc, const c return _linphone_core_get_or_create_chat_room(lc, to); } +static void linphone_chat_room_delete_composing_idle_timer(LinphoneChatRoom *cr) { + if (cr->composing_idle_timer) { + if (cr->lc && cr->lc->sal) + sal_cancel_timer(cr->lc->sal, cr->composing_idle_timer); + belle_sip_object_unref(cr->composing_idle_timer); + cr->composing_idle_timer = NULL; + } +} + +static void linphone_chat_room_delete_composing_refresh_timer(LinphoneChatRoom *cr) { + if (cr->composing_refresh_timer) { + if (cr->lc && cr->lc->sal) + sal_cancel_timer(cr->lc->sal, cr->composing_refresh_timer); + belle_sip_object_unref(cr->composing_refresh_timer); + cr->composing_refresh_timer = NULL; + } +} + +static void linphone_chat_room_delete_remote_composing_refresh_timer(LinphoneChatRoom *cr) { + if (cr->remote_composing_refresh_timer) { + if (cr->lc && cr->lc->sal) + sal_cancel_timer(cr->lc->sal, cr->remote_composing_refresh_timer); + belle_sip_object_unref(cr->remote_composing_refresh_timer); + cr->remote_composing_refresh_timer = NULL; + } +} + void linphone_chat_room_destroy(LinphoneChatRoom *cr) { linphone_chat_room_unref(cr); } void linphone_chat_room_release(LinphoneChatRoom *cr) { - L_GET_PRIVATE(cr->cr)->release(); + linphone_chat_room_delete_composing_idle_timer(cr); + linphone_chat_room_delete_composing_refresh_timer(cr); + linphone_chat_room_delete_remote_composing_refresh_timer(cr); + bctbx_list_for_each(cr->weak_messages, (bctbx_list_iterate_func)linphone_chat_message_deactivate); + bctbx_list_for_each(cr->transient_messages, (bctbx_list_iterate_func)linphone_chat_message_deactivate); + cr->lc = NULL; + linphone_chat_room_unref(cr); +} + +static void on_weak_message_destroy(void *obj, belle_sip_object_t *message_being_destroyed) { + LinphoneChatRoom *cr = (LinphoneChatRoom *)obj; + cr->weak_messages = bctbx_list_remove(cr->weak_messages, message_being_destroyed); +} + +void linphone_chat_room_add_weak_message(LinphoneChatRoom *cr, LinphoneChatMessage *cm) { + bctbx_list_t *item = bctbx_list_find(cr->weak_messages, cm); + if (item == NULL) { + cr->weak_messages = bctbx_list_append(cr->weak_messages, belle_sip_object_weak_ref(cm, on_weak_message_destroy, cr)); + } } LinphoneChatRoom *linphone_chat_room_ref(LinphoneChatRoom *cr) { @@ -282,8 +347,183 @@ void linphone_chat_room_set_user_data(LinphoneChatRoom *cr, void *ud) { cr->user_data = ud; } +void linphone_chat_room_add_transient_message(LinphoneChatRoom *cr, LinphoneChatMessage *msg) { + if (bctbx_list_find(msg->chat_room->transient_messages, msg) == NULL) { + cr->transient_messages = bctbx_list_append(cr->transient_messages, linphone_chat_message_ref(msg)); + } +} + void linphone_chat_room_remove_transient_message(LinphoneChatRoom *cr, LinphoneChatMessage *msg) { - L_GET_PRIVATE(cr->cr)->removeTransientMessage(msg); + if (bctbx_list_find(msg->chat_room->transient_messages, msg) != NULL) { + cr->transient_messages = bctbx_list_remove(cr->transient_messages, msg); + linphone_chat_message_unref(msg); + } +} + +static void store_or_update_chat_message(LinphoneChatMessage *msg) { + if (msg->storage_id != 0) { + /* The message has already been stored (probably because of file transfer), update it */ + linphone_chat_message_store_update(msg); + } else { + /* Store the new message */ + msg->storage_id = linphone_chat_message_store(msg); + } +} + +void _linphone_chat_room_send_message(LinphoneChatRoom *cr, LinphoneChatMessage *msg) { + int retval = -1; + LinphoneCore *lc = cr->lc; + LinphoneImEncryptionEngine *imee = lc->im_encryption_engine; + + /*stubed rtt text*/ + if (cr->call && linphone_call_params_realtime_text_enabled(linphone_call_get_current_params(cr->call))) { + uint32_t new_line = 0x2028; + linphone_chat_message_put_char(msg, new_line); // New Line + linphone_chat_message_unref(msg); + return; + } + + msg->dir = LinphoneChatMessageOutgoing; + + /* Check if we shall upload a file to a server */ + if (msg->file_transfer_information != NULL && msg->content_type == NULL) { + /* open a transaction with the server and send an empty request(RCS5.1 section 3.5.4.8.3.1) */ + if (linphone_chat_room_upload_file(msg) == 0) { + /* Add to transient list only if message is going out */ + linphone_chat_room_add_transient_message(cr, msg); + /* Store the message so that even if the upload is stopped, it can be done again */ + msg->storage_id = linphone_chat_message_store(msg); + } else { + linphone_chat_message_unref(msg); + return; + } + } else { + SalOp *op = msg->op; + LinphoneCall *call=NULL; + char *content_type; + const char *identity = NULL; + char *clear_text_message = NULL; + char *clear_text_content_type = NULL; + + if (msg->message) { + clear_text_message = ms_strdup(msg->message); + } + if (msg->content_type) { + clear_text_content_type = ms_strdup(msg->content_type); + } + + /* Add to transient list */ + linphone_chat_room_add_transient_message(cr, msg); + msg->time = ms_time(0); + if (lp_config_get_int(cr->lc->config, "sip", "chat_use_call_dialogs", 0) != 0) { + if ((call = linphone_core_get_call_by_remote_address(cr->lc, cr->peer)) != NULL) { + if (call->state == LinphoneCallConnected || call->state == LinphoneCallStreamsRunning || + call->state == LinphoneCallPaused || call->state == LinphoneCallPausing || + call->state == LinphoneCallPausedByRemote) { + ms_message("send SIP msg through the existing call."); + op = call->op; + identity = linphone_core_find_best_identity(cr->lc, linphone_call_get_remote_address(call)); + } + } + } + + if (!identity) { + LinphoneProxyConfig *proxy = linphone_core_lookup_known_proxy(cr->lc, cr->peer_url); + if (proxy) { + identity = linphone_proxy_config_get_identity(proxy); + } else { + identity = linphone_core_get_primary_contact(cr->lc); + } + } + if (msg->from){ + /* + * BUG + * the file transfer message constructor sets the from, but doesn't do it as well as here. + */ + linphone_address_unref(msg->from); + } + msg->from = linphone_address_new(identity); + + if (imee) { + LinphoneImEncryptionEngineCbs *imee_cbs = linphone_im_encryption_engine_get_callbacks(imee); + LinphoneImEncryptionEngineCbsOutgoingMessageCb cb_process_outgoing_message = linphone_im_encryption_engine_cbs_get_process_outgoing_message(imee_cbs); + if (cb_process_outgoing_message) { + retval = cb_process_outgoing_message(imee, cr, msg); + if(retval == 0) { + msg->is_secured = TRUE; + } + } + } + + if (op == NULL) { + /*sending out of calls*/ + msg->op = op = sal_op_new(cr->lc->sal); + linphone_configure_op(cr->lc, op, cr->peer_url, msg->custom_headers, + lp_config_get_int(cr->lc->config, "sip", "chat_msg_with_contact", 0)); + sal_op_set_user_pointer(op, msg); /*if out of call, directly store msg*/ + } + + if (retval > 0) { + sal_error_info_set((SalErrorInfo *)sal_op_get_error_info(op), SalReasonNotAcceptable, "SIP", retval, "Unable to encrypt IM", NULL); + store_or_update_chat_message(msg); + linphone_chat_message_update_state(msg, LinphoneChatMessageStateNotDelivered); + linphone_chat_message_unref(msg); + return; + } + + if (msg->external_body_url) { + content_type = ms_strdup_printf("message/external-body; access-type=URL; URL=\"%s\"", msg->external_body_url); + sal_message_send(op, identity, cr->peer, content_type, NULL, NULL); + ms_free(content_type); + } else { + char *peer_uri = linphone_address_as_string_uri_only(linphone_chat_room_get_peer_address(cr)); + const char *content_type = msg->content_type; + if (content_type == NULL) { + sal_text_send(op, identity, cr->peer, msg->message); + } else { + sal_message_send(op, identity, cr->peer, content_type, msg->message, peer_uri); + } + ms_free(peer_uri); + } + + if (msg->message && clear_text_message && strcmp(msg->message, clear_text_message) != 0) { + // We replace the encrypted message by the original one so it can be correctly stored and displayed by the application + ms_free(msg->message); + msg->message = ms_strdup(clear_text_message); + } + if (msg->content_type && clear_text_content_type && (strcmp(msg->content_type, clear_text_content_type) != 0)) { + /* We replace the encrypted content type by the original one */ + ms_free(msg->content_type); + msg->content_type = ms_strdup(clear_text_content_type); + } + msg->message_id = ms_strdup(sal_op_get_call_id(op)); /* must be known at that time */ + store_or_update_chat_message(msg); + + if (cr->is_composing == LinphoneIsComposingActive) { + cr->is_composing = LinphoneIsComposingIdle; + } + linphone_chat_room_delete_composing_idle_timer(cr); + linphone_chat_room_delete_composing_refresh_timer(cr); + + if (clear_text_message) { + ms_free(clear_text_message); + } + if (clear_text_content_type) { + ms_free(clear_text_content_type); + } + + if (call && call->op == op) { + /*In this case, chat delivery status is not notified, so unrefing chat message right now*/ + /*Might be better fixed by delivering status, but too costly for now*/ + linphone_chat_room_remove_transient_message(msg->chat_room, msg); + linphone_chat_message_unref(msg); + return; + } + } + // if operation failed, we should not change message state + if (msg->dir == LinphoneChatMessageOutgoing) { + linphone_chat_message_set_state(msg, LinphoneChatMessageStateInProgress); + } } void linphone_chat_message_update_state(LinphoneChatMessage *msg, LinphoneChatMessageState new_state) { @@ -291,15 +531,50 @@ void linphone_chat_message_update_state(LinphoneChatMessage *msg, LinphoneChatMe linphone_chat_message_store_state(msg); if (msg->state == LinphoneChatMessageStateDelivered || msg->state == LinphoneChatMessageStateNotDelivered) { - L_GET_PRIVATE(msg->chat_room->cr)->moveTransientMessageToWeakMessages(msg); + if (bctbx_list_find(msg->chat_room->transient_messages, msg) != NULL) { + // msg is not transient anymore, we can remove it from our transient list and unref it + linphone_chat_room_add_weak_message(msg->chat_room, msg); + linphone_chat_room_remove_transient_message(msg->chat_room, msg); + } else { + // msg has already been removed from the transient messages, do nothing. */ + } } } void linphone_chat_room_send_message(LinphoneChatRoom *cr, const char *msg) { - cr->cr->sendMessage(cr->cr->createMessage(msg)); + _linphone_chat_room_send_message(cr, linphone_chat_room_create_message(cr, msg)); } -void create_file_transfer_information_from_vnd_gsma_rcs_ft_http_xml(LinphoneChatMessage *msg) { +static bool_t is_file_transfer(const char *content_type) { + return (strcmp("application/vnd.gsma.rcs-ft-http+xml", content_type) == 0); +} + +static bool_t is_im_iscomposing(const char* content_type) { + return (strcmp("application/im-iscomposing+xml", content_type) == 0); +} + +static bool_t is_imdn(const char *content_type) { + return (strcmp("message/imdn+xml", content_type) == 0); +} + +static bool_t is_text(const char *content_type) { + return (strcmp("text/plain", content_type) == 0); +} + +void linphone_chat_room_message_received(LinphoneChatRoom *cr, LinphoneCore *lc, LinphoneChatMessage *msg) { + if (msg->message) { + /*legacy API*/ + linphone_core_notify_text_message_received(lc, cr, msg->from, msg->message); + } + linphone_core_notify_message_received(lc, cr, msg); + if(!is_imdn(msg->content_type) && !is_im_iscomposing(msg->content_type)) { + cr->remote_is_composing = LinphoneIsComposingIdle; + linphone_core_notify_is_composing_received(cr->lc, cr); + linphone_chat_message_send_delivery_notification(msg, LinphoneReasonNone); + } +} + +static void create_file_transfer_information_from_vnd_gsma_rcs_ft_http_xml(LinphoneChatMessage *msg) { xmlChar *file_url = NULL; xmlDocPtr xmlMessageBody; xmlNodePtr cur; @@ -348,7 +623,7 @@ void create_file_transfer_information_from_vnd_gsma_rcs_ft_http_xml(LinphoneChat file_url = xmlGetProp(cur, (const xmlChar *)"url"); } - if (!xmlStrcmp(cur->name, (const xmlChar *)"file-key")) { + if (!xmlStrcmp(cur->name, (const xmlChar *)"file-key")) { /* there is a key in the msg: file has been encrypted */ /* convert the key from base 64 */ xmlChar *keyb64 = xmlNodeListGetString(xmlMessageBody, cur->xmlChildrenNode, 1); @@ -356,7 +631,7 @@ void create_file_transfer_information_from_vnd_gsma_rcs_ft_http_xml(LinphoneChat uint8_t *keyBuffer = (uint8_t *)malloc(keyLength); /* decode the key into local key buffer */ b64::b64_decode((char *)keyb64, strlen((char *)keyb64), keyBuffer, keyLength); - linphone_content_set_key(msg->file_transfer_information, (char *)keyBuffer, keyLength); + linphone_content_set_key(msg->file_transfer_information, (char *)keyBuffer, keyLength); /* duplicate key value into the linphone content private structure */ xmlFree(keyb64); free(keyBuffer); @@ -378,17 +653,285 @@ void create_file_transfer_information_from_vnd_gsma_rcs_ft_http_xml(LinphoneChat xmlFree(file_url); } -int linphone_core_message_received(LinphoneCore *lc, SalOp *op, const SalMessage *sal_msg) { - LinphoneAddress *addr = linphone_address_new(sal_msg->from); +LinphoneReason linphone_core_message_received(LinphoneCore *lc, SalOp *op, const SalMessage *sal_msg) { + LinphoneChatRoom *cr = NULL; + LinphoneAddress *addr; + LinphoneAddress *to; + LinphoneChatMessage *msg = NULL; + LinphoneImEncryptionEngine *imee = lc->im_encryption_engine; + const SalCustomHeader *ch; + LinphoneReason reason = LinphoneReasonNone; + int retval = -1; + bool_t increase_msg_count = TRUE; + + addr = linphone_address_new(sal_msg->from); linphone_address_clean(addr); - LinphoneChatRoom *cr = linphone_core_get_chat_room(lc, addr); - LinphoneReason reason = L_GET_PRIVATE(cr->cr)->messageReceived(op, sal_msg); + cr = linphone_core_get_chat_room(lc, addr); + + /* Check if this is a duplicate message */ + if ((msg = linphone_chat_room_find_message_with_dir(cr, sal_op_get_call_id(op), LinphoneChatMessageIncoming))) { + reason = lc->chat_deny_code; + goto end; + } + + msg = linphone_chat_room_create_message(cr, sal_msg->text); + linphone_chat_message_set_content_type(msg, sal_msg->content_type); + linphone_chat_message_set_from(msg, cr->peer_url); + + to = sal_op_get_to(op) ? linphone_address_new(sal_op_get_to(op)) : linphone_address_new(linphone_core_get_identity(lc)); + msg->to = to; + + msg->time = sal_msg->time; + msg->state = LinphoneChatMessageStateDelivered; + msg->dir = LinphoneChatMessageIncoming; + msg->message_id = ms_strdup(sal_op_get_call_id(op)); + + ch = sal_op_get_recv_custom_header(op); + if (ch) { + msg->custom_headers = sal_custom_header_clone(ch); + } + + if (sal_msg->url) { + linphone_chat_message_set_external_body_url(msg, sal_msg->url); + } + + if (imee) { + LinphoneImEncryptionEngineCbs *imee_cbs = linphone_im_encryption_engine_get_callbacks(imee); + LinphoneImEncryptionEngineCbsIncomingMessageCb cb_process_incoming_message = linphone_im_encryption_engine_cbs_get_process_incoming_message(imee_cbs); + if (cb_process_incoming_message) { + retval = cb_process_incoming_message(imee, cr, msg); + if(retval == 0) { + msg->is_secured = TRUE; + } else if(retval > 0) { + // Unable to decrypt message + linphone_core_notify_message_received_unable_decrypt(cr->lc, cr, msg); + reason = linphone_error_code_to_reason(retval); + linphone_chat_message_send_delivery_notification(msg, reason); + // return LinphoneReasonNone to avoid flexisip resending us a message we can't decrypt + reason = LinphoneReasonNone; + goto end; + } + } + } + + if ((retval <= 0) && (linphone_core_is_content_type_supported(lc, msg->content_type) == FALSE)) { + retval = 415; + ms_error("Unsupported MESSAGE (content-type %s not recognized)", msg->content_type); + } + + if (retval > 0) { + reason = linphone_error_code_to_reason(retval); + linphone_chat_message_send_delivery_notification(msg, reason); + goto end; + } + + if (is_file_transfer(msg->content_type)) { + create_file_transfer_information_from_vnd_gsma_rcs_ft_http_xml(msg); + linphone_chat_message_set_to_be_stored(msg, TRUE); + } else if (is_im_iscomposing(msg->content_type)) { + linphone_chat_room_notify_is_composing(cr, msg->message); + linphone_chat_message_set_to_be_stored(msg, FALSE); + increase_msg_count = FALSE; + if(lp_config_get_int(cr->lc->config, "sip", "deliver_imdn", 0) != 1) { + goto end; + } + } else if (is_imdn(msg->content_type)) { + linphone_chat_room_notify_imdn(cr, msg->message); + linphone_chat_message_set_to_be_stored(msg, FALSE); + increase_msg_count = FALSE; + if(lp_config_get_int(cr->lc->config, "sip", "deliver_imdn", 0) != 1) { + goto end; + } + } else if (is_text(msg->content_type)) { + linphone_chat_message_set_to_be_stored(msg, TRUE); + } + + if (increase_msg_count == TRUE) { + if (cr->unread_count < 0) + cr->unread_count = 1; + else + cr->unread_count++; + /* Mark the message as pending so that if linphone_core_chat_room_mark_as_read() is called + in the linphone_chat_room_message_received() callback, it will effectively be marked as + being read before being stored. */ + cr->pending_message = msg; + } + + linphone_chat_room_message_received(cr, lc, msg); + + if(linphone_chat_message_get_to_be_stored(msg)) { + msg->storage_id = linphone_chat_message_store(msg); + } + + cr->pending_message = NULL; + +end: linphone_address_unref(addr); + if (msg != NULL) linphone_chat_message_unref(msg); return reason; } +static int linphone_chat_room_remote_refresh_composing_expired(void *data, unsigned int revents) { + LinphoneChatRoom *cr = (LinphoneChatRoom *)data; + belle_sip_object_unref(cr->remote_composing_refresh_timer); + cr->remote_composing_refresh_timer = NULL; + cr->remote_is_composing = LinphoneIsComposingIdle; + linphone_core_notify_is_composing_received(cr->lc, cr); + return BELLE_SIP_STOP; +} + +static const char *iscomposing_prefix = "/xsi:isComposing"; + +static void process_im_is_composing_notification(LinphoneChatRoom *cr, xmlparsing_context_t *xml_ctx) { + char xpath_str[MAX_XPATH_LENGTH]; + xmlXPathObjectPtr iscomposing_object; + char *state_str = NULL; + char *refresh_str = NULL; + int refresh_duration = lp_config_get_int(cr->lc->config, "sip", "composing_remote_refresh_timeout", + COMPOSING_DEFAULT_REMOTE_REFRESH_TIMEOUT); + int i; + LinphoneIsComposingState state = LinphoneIsComposingIdle; + + if (linphone_create_xml_xpath_context(xml_ctx) < 0) + return; + + xmlXPathRegisterNs(xml_ctx->xpath_ctx, (const xmlChar *)"xsi", + (const xmlChar *)"urn:ietf:params:xml:ns:im-iscomposing"); + iscomposing_object = linphone_get_xml_xpath_object_for_node_list(xml_ctx, iscomposing_prefix); + if (iscomposing_object != NULL) { + if (iscomposing_object->nodesetval != NULL) { + for (i = 1; i <= iscomposing_object->nodesetval->nodeNr; i++) { + snprintf(xpath_str, sizeof(xpath_str), "%s[%i]/xsi:state", iscomposing_prefix, i); + state_str = linphone_get_xml_text_content(xml_ctx, xpath_str); + if (state_str == NULL) + continue; + snprintf(xpath_str, sizeof(xpath_str), "%s[%i]/xsi:refresh", iscomposing_prefix, i); + refresh_str = linphone_get_xml_text_content(xml_ctx, xpath_str); + } + } + xmlXPathFreeObject(iscomposing_object); + } + + if (state_str != NULL) { + if (strcmp(state_str, "active") == 0) { + state = LinphoneIsComposingActive; + if (refresh_str != NULL) { + refresh_duration = atoi(refresh_str); + } + if (!cr->remote_composing_refresh_timer) { + cr->remote_composing_refresh_timer = + sal_create_timer(cr->lc->sal, linphone_chat_room_remote_refresh_composing_expired, cr, + refresh_duration * 1000, "composing remote refresh timeout"); + } else { + belle_sip_source_set_timeout(cr->remote_composing_refresh_timer, refresh_duration * 1000); + } + } else { + linphone_chat_room_delete_remote_composing_refresh_timer(cr); + } + + cr->remote_is_composing = state; + linphone_core_notify_is_composing_received(cr->lc, cr); + linphone_free_xml_text_content(state_str); + } + if (refresh_str != NULL) { + linphone_free_xml_text_content(refresh_str); + } +} + +static void linphone_chat_room_notify_is_composing(LinphoneChatRoom *cr, const char *text) { + xmlparsing_context_t *xml_ctx = linphone_xmlparsing_context_new(); + xmlSetGenericErrorFunc(xml_ctx, linphone_xmlparsing_genericxml_error); + xml_ctx->doc = xmlReadDoc((const unsigned char *)text, 0, NULL, 0); + if (xml_ctx->doc != NULL) { + process_im_is_composing_notification(cr, xml_ctx); + } else { + ms_warning("Wrongly formatted presence XML: %s", xml_ctx->errorBuffer); + } + linphone_xmlparsing_context_destroy(xml_ctx); +} + bool_t linphone_chat_room_is_remote_composing(const LinphoneChatRoom *cr) { - return cr->cr->isRemoteComposing(); + return (cr->remote_is_composing == LinphoneIsComposingActive) ? TRUE : FALSE; +} + +static const char *imdn_prefix = "/imdn:imdn"; + +static void process_imdn(LinphoneChatRoom *cr, xmlparsing_context_t *xml_ctx) { + char xpath_str[MAX_XPATH_LENGTH]; + xmlXPathObjectPtr imdn_object; + xmlXPathObjectPtr delivery_status_object; + xmlXPathObjectPtr display_status_object; + char *message_id_str = NULL; + char *datetime_str = NULL; + LinphoneCore *lc = linphone_chat_room_get_core(cr); + LinphoneImNotifPolicy *policy = linphone_core_get_im_notif_policy(lc); + + if (linphone_create_xml_xpath_context(xml_ctx) < 0) + return; + + xmlXPathRegisterNs(xml_ctx->xpath_ctx, (const xmlChar *)"imdn", + (const xmlChar *)"urn:ietf:params:xml:ns:imdn"); + imdn_object = linphone_get_xml_xpath_object_for_node_list(xml_ctx, imdn_prefix); + if (imdn_object != NULL) { + if ((imdn_object->nodesetval != NULL) && (imdn_object->nodesetval->nodeNr >= 1)) { + snprintf(xpath_str, sizeof(xpath_str), "%s[1]/imdn:message-id", imdn_prefix); + message_id_str = linphone_get_xml_text_content(xml_ctx, xpath_str); + snprintf(xpath_str, sizeof(xpath_str), "%s[1]/imdn:datetime", imdn_prefix); + datetime_str = linphone_get_xml_text_content(xml_ctx, xpath_str); + } + xmlXPathFreeObject(imdn_object); + } + + if ((message_id_str != NULL) && (datetime_str != NULL)) { + LinphoneChatMessage *cm = linphone_chat_room_find_message_with_dir(cr, message_id_str, LinphoneChatMessageOutgoing); + if (cm == NULL) { + ms_warning("Received IMDN for unknown message %s", message_id_str); + } else { + snprintf(xpath_str, sizeof(xpath_str), "%s[1]/imdn:delivery-notification/imdn:status", imdn_prefix); + delivery_status_object = linphone_get_xml_xpath_object_for_node_list(xml_ctx, xpath_str); + snprintf(xpath_str, sizeof(xpath_str), "%s[1]/imdn:display-notification/imdn:status", imdn_prefix); + display_status_object = linphone_get_xml_xpath_object_for_node_list(xml_ctx, xpath_str); + if ((delivery_status_object != NULL) && (linphone_im_notif_policy_get_recv_imdn_delivered(policy) == TRUE)) { + if ((delivery_status_object->nodesetval != NULL) && (delivery_status_object->nodesetval->nodeNr >= 1)) { + xmlNodePtr node = delivery_status_object->nodesetval->nodeTab[0]; + if ((node->children != NULL) && (node->children->name != NULL)) { + if (strcmp((const char *)node->children->name, "delivered") == 0) { + linphone_chat_message_update_state(cm, LinphoneChatMessageStateDeliveredToUser); + } else if (strcmp((const char *)node->children->name, "error") == 0) { + linphone_chat_message_update_state(cm, LinphoneChatMessageStateNotDelivered); + } + } + } + xmlXPathFreeObject(delivery_status_object); + } + if ((display_status_object != NULL) && (linphone_im_notif_policy_get_recv_imdn_displayed(policy) == TRUE)) { + if ((display_status_object->nodesetval != NULL) && (display_status_object->nodesetval->nodeNr >= 1)) { + xmlNodePtr node = display_status_object->nodesetval->nodeTab[0]; + if ((node->children != NULL) && (node->children->name != NULL)) { + if (strcmp((const char *)node->children->name, "displayed") == 0) { + linphone_chat_message_update_state(cm, LinphoneChatMessageStateDisplayed); + } + } + } + xmlXPathFreeObject(display_status_object); + } + linphone_chat_message_unref(cm); + } + } + if (message_id_str != NULL) linphone_free_xml_text_content(message_id_str); + if (datetime_str != NULL) linphone_free_xml_text_content(datetime_str); +} + +static void linphone_chat_room_notify_imdn(LinphoneChatRoom *cr, const char *text) { + xmlparsing_context_t *xml_ctx = linphone_xmlparsing_context_new(); + xmlSetGenericErrorFunc(xml_ctx, linphone_xmlparsing_genericxml_error); + xml_ctx->doc = xmlReadDoc((const unsigned char *)text, 0, NULL, 0); + if (xml_ctx->doc != NULL) { + process_imdn(cr, xml_ctx); + } else { + ms_warning("Wrongly formatted IMDN XML: %s", xml_ctx->errorBuffer); + } + linphone_xmlparsing_context_destroy(xml_ctx); } LinphoneCore *linphone_chat_room_get_lc(LinphoneChatRoom *cr) { @@ -396,15 +939,25 @@ LinphoneCore *linphone_chat_room_get_lc(LinphoneChatRoom *cr) { } LinphoneCore *linphone_chat_room_get_core(LinphoneChatRoom *cr) { - return cr->cr->getCore(); + return cr->lc; } const LinphoneAddress *linphone_chat_room_get_peer_address(LinphoneChatRoom *cr) { - return cr->cr->getPeerAddress(); + return cr->peer_url; } LinphoneChatMessage *linphone_chat_room_create_message(LinphoneChatRoom *cr, const char *message) { - return cr->cr->createMessage(message ? message : ""); + LinphoneChatMessage *msg = belle_sip_object_new(LinphoneChatMessage); + msg->state = LinphoneChatMessageStateIdle; + msg->callbacks = linphone_chat_message_cbs_new(); + msg->chat_room = (LinphoneChatRoom *)cr; + msg->message = message ? ms_strdup(message) : NULL; + msg->content_type = ms_strdup("text/plain"); + msg->file_transfer_information = NULL; /* this property is used only when transfering file */ + msg->http_request = NULL; + msg->time = ms_time(0); + msg->is_secured = FALSE; + return msg; } LinphoneChatMessage *linphone_chat_room_create_message_2(LinphoneChatRoom *cr, const char *message, @@ -432,20 +985,16 @@ void linphone_chat_room_send_message2(LinphoneChatRoom *cr, LinphoneChatMessage LinphoneChatMessageStateChangedCb status_cb, void *ud) { msg->message_state_changed_cb = status_cb; msg->message_state_changed_user_data = ud; - cr->cr->sendMessage(msg); + _linphone_chat_room_send_message(cr, msg); } void linphone_chat_room_send_chat_message_2(LinphoneChatRoom *cr, LinphoneChatMessage *msg) { linphone_chat_message_ref(msg); - cr->cr->sendMessage(msg); + _linphone_chat_room_send_message(cr, msg); } void linphone_chat_room_send_chat_message(LinphoneChatRoom *cr, LinphoneChatMessage *msg) { - cr->cr->sendMessage(msg); -} - -LinphonePrivate::ChatRoom& linphone_chat_room_get_cpp_obj(LinphoneChatRoom *cr) { - return *cr->cr; + _linphone_chat_room_send_message(cr, msg); } void _linphone_chat_message_resend(LinphoneChatMessage *msg, bool_t ref_msg) { @@ -459,7 +1008,7 @@ void _linphone_chat_message_resend(LinphoneChatMessage *msg, bool_t ref_msg) { cr = linphone_chat_message_get_chat_room(msg); if (ref_msg) linphone_chat_message_ref(msg); - cr->cr->sendMessage(msg); + _linphone_chat_room_send_message(cr, msg); } void linphone_chat_message_resend(LinphoneChatMessage *msg) { @@ -470,7 +1019,121 @@ void linphone_chat_message_resend_2(LinphoneChatMessage *msg) { _linphone_chat_message_resend(msg, TRUE); } -static char *linphone_chat_message_create_imdn_xml(LinphoneChatMessage *cm, ImdnType imdn_type, LinphoneReason reason) { +static char *linphone_chat_room_create_is_composing_xml(LinphoneChatRoom *cr) { + xmlBufferPtr buf; + xmlTextWriterPtr writer; + int err; + char *content = NULL; + + buf = xmlBufferCreate(); + if (buf == NULL) { + ms_error("Error creating the XML buffer"); + return content; + } + writer = xmlNewTextWriterMemory(buf, 0); + if (writer == NULL) { + ms_error("Error creating the XML writer"); + return content; + } + + err = xmlTextWriterStartDocument(writer, "1.0", "UTF-8", NULL); + if (err >= 0) { + err = xmlTextWriterStartElementNS(writer, NULL, (const xmlChar *)"isComposing", + (const xmlChar *)"urn:ietf:params:xml:ns:im-iscomposing"); + } + if (err >= 0) { + err = xmlTextWriterWriteAttributeNS(writer, (const xmlChar *)"xmlns", (const xmlChar *)"xsi", NULL, + (const xmlChar *)"http://www.w3.org/2001/XMLSchema-instance"); + } + if (err >= 0) { + err = xmlTextWriterWriteAttributeNS(writer, (const xmlChar *)"xsi", (const xmlChar *)"schemaLocation", NULL, + (const xmlChar *)"urn:ietf:params:xml:ns:im-composing iscomposing.xsd"); + } + if (err >= 0) { + err = xmlTextWriterWriteElement(writer, (const xmlChar *)"state", + (cr->is_composing == LinphoneIsComposingActive) ? (const xmlChar *)"active" + : (const xmlChar *)"idle"); + } + if ((err >= 0) && (cr->is_composing == LinphoneIsComposingActive)) { + char refresh_str[4] = {0}; + int refresh_timeout = + lp_config_get_int(cr->lc->config, "sip", "composing_refresh_timeout", COMPOSING_DEFAULT_REFRESH_TIMEOUT); + snprintf(refresh_str, sizeof(refresh_str), "%u", refresh_timeout); + err = xmlTextWriterWriteElement(writer, (const xmlChar *)"refresh", (const xmlChar *)refresh_str); + } + if (err >= 0) { + /* Close the "isComposing" element. */ + err = xmlTextWriterEndElement(writer); + } + if (err >= 0) { + err = xmlTextWriterEndDocument(writer); + } + if (err > 0) { + /* xmlTextWriterEndDocument returns the size of the content. */ + content = ms_strdup((char *)buf->content); + } + xmlFreeTextWriter(writer); + xmlBufferFree(buf); + return content; +} + +static void linphone_chat_room_send_is_composing_notification(LinphoneChatRoom *cr) { + SalOp *op = NULL; + const char *identity = NULL; + char *content = NULL; + LinphoneCore *lc = linphone_chat_room_get_core(cr); + LinphoneImNotifPolicy *policy = linphone_core_get_im_notif_policy(lc); + if (linphone_im_notif_policy_get_send_is_composing(policy) == TRUE) { + LinphoneProxyConfig *proxy = linphone_core_lookup_known_proxy(lc, cr->peer_url); + LinphoneImEncryptionEngine *imee = linphone_core_get_im_encryption_engine(lc); + LinphoneChatMessage *msg = NULL; + + if (proxy) + identity = linphone_proxy_config_get_identity(proxy); + else + identity = linphone_core_get_primary_contact(lc); + /*sending out of calls*/ + op = sal_op_new(lc->sal); + linphone_configure_op(lc, op, cr->peer_url, NULL, + lp_config_get_int(lc->config, "sip", "chat_msg_with_contact", 0)); + + content = linphone_chat_room_create_is_composing_xml(cr); + if (content != NULL) { + int retval = -1; + LinphoneAddress *from_addr = linphone_address_new(identity); + LinphoneAddress *to_addr = linphone_address_new(cr->peer); + msg = linphone_chat_room_create_message(cr, content); + linphone_chat_message_set_from_address(msg, from_addr); + linphone_chat_message_set_to_address(msg, to_addr); + linphone_chat_message_set_content_type(msg, "application/im-iscomposing+xml"); + + if (imee) { + LinphoneImEncryptionEngineCbs *imee_cbs = linphone_im_encryption_engine_get_callbacks(imee); + LinphoneImEncryptionEngineCbsOutgoingMessageCb cb_process_outgoing_message = linphone_im_encryption_engine_cbs_get_process_outgoing_message(imee_cbs); + if (cb_process_outgoing_message) { + retval = cb_process_outgoing_message(imee, cr, msg); + } + } + + if (retval <= 0) { + sal_message_send(op, identity, cr->peer, msg->content_type, msg->message, NULL); + } + + linphone_chat_message_unref(msg); + linphone_address_unref(from_addr); + linphone_address_unref(to_addr); + ms_free(content); + sal_op_unref(op); + } + } +} + +enum ImdnType { + ImdnTypeDelivery, + ImdnTypeDisplay +}; + +static char *linphone_chat_message_create_imdn_xml(LinphoneChatMessage *cm, enum ImdnType imdn_type, LinphoneReason reason) { xmlBufferPtr buf; xmlTextWriterPtr writer; int err; @@ -572,12 +1235,53 @@ static char *linphone_chat_message_create_imdn_xml(LinphoneChatMessage *cm, Imdn return content; } -void linphone_chat_message_send_imdn(LinphoneChatMessage *cm, ImdnType imdn_type, LinphoneReason reason) { - char *content = linphone_chat_message_create_imdn_xml(cm, imdn_type, reason); - if (content) { - L_GET_PRIVATE(linphone_chat_message_get_chat_room(cm)->cr)->sendImdn(content, reason); +static void linphone_chat_message_send_imdn(LinphoneChatMessage *cm, enum ImdnType imdn_type, LinphoneReason reason) { + SalOp *op = NULL; + const char *identity = NULL; + char *content = NULL; + LinphoneChatRoom *cr = linphone_chat_message_get_chat_room(cm); + LinphoneProxyConfig *proxy = linphone_core_lookup_known_proxy(cr->lc, cr->peer_url); + LinphoneImEncryptionEngine *imee = linphone_core_get_im_encryption_engine(cr->lc); + LinphoneChatMessage *msg; + + if (proxy) + identity = linphone_proxy_config_get_identity(proxy); + else + identity = linphone_core_get_primary_contact(cr->lc); + /* Sending out of calls */ + op = sal_op_new(cr->lc->sal); + linphone_configure_op(cr->lc, op, cr->peer_url, NULL, + lp_config_get_int(cr->lc->config, "sip", "chat_msg_with_contact", 0)); + + content = linphone_chat_message_create_imdn_xml(cm, imdn_type, reason); + if (content != NULL) { + int retval = -1; + LinphoneAddress *from_addr = linphone_address_new(identity); + LinphoneAddress *to_addr = linphone_address_new(cr->peer); + msg = linphone_chat_room_create_message(cr, content); + linphone_chat_message_set_from_address(msg, from_addr); + linphone_chat_message_set_to_address(msg, to_addr); + linphone_chat_message_set_content_type(msg, "message/imdn+xml"); + + /* Do not try to encrypt the notification when it is reporting an error (maybe it should be bypassed only for some reasons). */ + if (imee && (reason == LinphoneReasonNone)) { + LinphoneImEncryptionEngineCbs *imee_cbs = linphone_im_encryption_engine_get_callbacks(imee); + LinphoneImEncryptionEngineCbsOutgoingMessageCb cb_process_outgoing_message = linphone_im_encryption_engine_cbs_get_process_outgoing_message(imee_cbs); + if (cb_process_outgoing_message) { + retval = cb_process_outgoing_message(imee, cr, msg); + } + } + + if (retval <= 0) { + sal_message_send(op, identity, cr->peer, msg->content_type, msg->message, NULL); + } + + linphone_chat_message_unref(msg); + linphone_address_unref(from_addr); + linphone_address_unref(to_addr); ms_free(content); } + sal_op_unref(op); } void linphone_chat_message_send_delivery_notification(LinphoneChatMessage *cm, LinphoneReason reason) { @@ -598,21 +1302,107 @@ void linphone_chat_message_send_display_notification(LinphoneChatMessage *cm) { } } +static char* utf8_to_char(uint32_t ic) { + char *result = reinterpret_cast(ms_malloc(sizeof(char) * 5)); + int size = 0; + if (ic < 0x80) { + result[0] = ic; + size = 1; + } else if (ic < 0x800) { + result[1] = 0x80 + ((ic & 0x3F)); + result[0] = 0xC0 + ((ic >> 6) & 0x1F); + size = 2; + } else if (ic < 0x100000) { + result[2] = 0x80 + (ic & 0x3F); + result[1] = 0x80 + ((ic >> 6) & 0x3F); + result[0] = 0xE0 + ((ic >> 12) & 0xF); + size = 3; + } else if (ic < 0x110000) { + result[3] = 0x80 + (ic & 0x3F); + result[2] = 0x80 + ((ic >> 6) & 0x3F); + result[1] = 0x80 + ((ic >> 12) & 0x3F); + result[0] = 0xF0 + ((ic >> 18) & 0x7); + size = 4; + } + result[size] = '\0'; + return result; +} + void linphone_core_real_time_text_received(LinphoneCore *lc, LinphoneChatRoom *cr, uint32_t character, LinphoneCall *call) { - L_GET_PRIVATE(cr->cr)->realtimeTextReceived(character, call); + uint32_t new_line = 0x2028; + uint32_t crlf = 0x0D0A; + uint32_t lf = 0x0A; + + if (call && linphone_call_params_realtime_text_enabled(linphone_call_get_current_params(call))) { + LinphoneChatMessageCharacter *cmc = ms_new0(LinphoneChatMessageCharacter, 1); + + if (cr->pending_message == NULL) { + cr->pending_message = linphone_chat_room_create_message(cr, ""); + } + + cmc->value = character; + cmc->has_been_read = FALSE; + cr->received_rtt_characters = bctbx_list_append(cr->received_rtt_characters, (void *)cmc); + + cr->remote_is_composing = LinphoneIsComposingActive; + linphone_core_notify_is_composing_received(cr->lc, cr); + + if (character == new_line || character == crlf || character == lf) { + // End of message + LinphoneChatMessage *msg = cr->pending_message; + ms_debug("New line received, forge a message with content %s", cr->pending_message->message); + + linphone_chat_message_set_from(msg, cr->peer_url); + if (msg->to) + linphone_address_unref(msg->to); + msg->to = call->dest_proxy ? linphone_address_clone(call->dest_proxy->identity_address) : + linphone_address_new(linphone_core_get_identity(lc)); + msg->time = ms_time(0); + msg->state = LinphoneChatMessageStateDelivered; + msg->dir = LinphoneChatMessageIncoming; + + if (lp_config_get_int(lc->config, "misc", "store_rtt_messages", 1) == 1) { + msg->storage_id = linphone_chat_message_store(msg); + } + + if (cr->unread_count < 0) cr->unread_count = 1; + else cr->unread_count++; + + linphone_chat_room_message_received(cr, lc, msg); + linphone_chat_message_unref(msg); + cr->pending_message = NULL; + cr->received_rtt_characters = bctbx_list_free_with_data(cr->received_rtt_characters, (void (*)(void *))ms_free); + } else { + char *value = utf8_to_char(character); + cr->pending_message->message = ms_strcat_printf(cr->pending_message->message, value); + ms_debug("Received RTT character: %s (%lu), pending text is %s", value, (unsigned long)character, cr->pending_message->message); + ms_free(value); + } + } } uint32_t linphone_chat_room_get_char(const LinphoneChatRoom *cr) { - return cr->cr->getChar(); + if (cr && cr->received_rtt_characters) { + bctbx_list_t *characters = cr->received_rtt_characters; + while (characters != NULL) { + LinphoneChatMessageCharacter *cmc = (LinphoneChatMessageCharacter *)characters->data; + if (!cmc->has_been_read) { + cmc->has_been_read = TRUE; + return cmc->value; + } + characters = bctbx_list_next(characters); + } + } + return 0; } LinphoneStatus linphone_chat_message_put_char(LinphoneChatMessage *msg, uint32_t character) { LinphoneChatRoom *cr = linphone_chat_message_get_chat_room(msg); - LinphoneCall *call = cr->cr->getCall(); - LinphoneCore *lc = cr->cr->getCore(); - const uint32_t new_line = 0x2028; - const uint32_t crlf = 0x0D0A; - const uint32_t lf = 0x0A; + LinphoneCall *call = cr->call; + LinphoneCore *lc = cr->lc; + uint32_t new_line = 0x2028; + uint32_t crlf = 0x0D0A; + uint32_t lf = 0x0A; if (!call || !call->textstream) { return -1; @@ -631,10 +1421,10 @@ LinphoneStatus linphone_chat_message_put_char(LinphoneChatMessage *msg, uint32_t msg->message = NULL; } } else { - char *value = LinphonePrivate::Utils::utf8ToChar(character); + char *value = utf8_to_char(character); msg->message = ms_strcat_printf(msg->message, value); ms_debug("Sent RTT character: %s (%lu), pending text is %s", value, (unsigned long)character, msg->message); - delete value; + ms_free(value); } text_stream_putchar32(call->textstream, character); @@ -645,24 +1435,42 @@ const char* linphone_chat_message_get_message_id(const LinphoneChatMessage *cm) return cm->message_id; } +static int linphone_chat_room_stop_composing(void *data, unsigned int revents) { + LinphoneChatRoom *cr = (LinphoneChatRoom *)data; + cr->is_composing = LinphoneIsComposingIdle; + linphone_chat_room_send_is_composing_notification(cr); + linphone_chat_room_delete_composing_refresh_timer(cr); + belle_sip_object_unref(cr->composing_idle_timer); + cr->composing_idle_timer = NULL; + return BELLE_SIP_STOP; +} + +static int linphone_chat_room_refresh_composing(void *data, unsigned int revents) { + LinphoneChatRoom *cr = (LinphoneChatRoom *)data; + linphone_chat_room_send_is_composing_notification(cr); + return BELLE_SIP_CONTINUE; +} + void linphone_chat_room_compose(LinphoneChatRoom *cr) { - cr->cr->compose(); -} - -LinphoneCall *linphone_chat_room_get_call(const LinphoneChatRoom *room) { - return room->cr->getCall(); -} - -void linphone_chat_room_set_call(LinphoneChatRoom *cr, LinphoneCall *call) { - L_GET_PRIVATE(cr->cr)->setCall(call); -} - -bctbx_list_t * linphone_chat_room_get_transient_messages(const LinphoneChatRoom *cr) { - std::list l = L_GET_PRIVATE(cr->cr)->getTransientMessages(); - bctbx_list_t *result = nullptr; - for (auto it = l.begin(); it != l.end(); it++) - result = bctbx_list_append(result, *it); - return result; + int idle_timeout = + lp_config_get_int(cr->lc->config, "sip", "composing_idle_timeout", COMPOSING_DEFAULT_IDLE_TIMEOUT); + int refresh_timeout = + lp_config_get_int(cr->lc->config, "sip", "composing_refresh_timeout", COMPOSING_DEFAULT_REFRESH_TIMEOUT); + if (cr->is_composing == LinphoneIsComposingIdle) { + cr->is_composing = LinphoneIsComposingActive; + linphone_chat_room_send_is_composing_notification(cr); + if (!cr->composing_refresh_timer) { + cr->composing_refresh_timer = sal_create_timer(cr->lc->sal, linphone_chat_room_refresh_composing, cr, + refresh_timeout * 1000, "composing refresh timeout"); + } else { + belle_sip_source_set_timeout(cr->composing_refresh_timer, refresh_timeout * 1000); + } + if (!cr->composing_idle_timer) { + cr->composing_idle_timer = sal_create_timer(cr->lc->sal, linphone_chat_room_stop_composing, cr, + idle_timeout * 1000, "composing idle timeout"); + } + } + belle_sip_source_set_timeout(cr->composing_idle_timer, idle_timeout * 1000); } const char *linphone_chat_message_state_to_string(const LinphoneChatMessageState state) { @@ -726,11 +1534,11 @@ void linphone_chat_message_set_content_type(LinphoneChatMessage *msg, const char } bool_t linphone_chat_message_is_file_transfer(const LinphoneChatMessage *msg) { - return LinphonePrivate::ContentType::isFileTransfer(msg->content_type); + return is_file_transfer(msg->content_type); } bool_t linphone_chat_message_is_text(const LinphoneChatMessage *msg) { - return LinphonePrivate::ContentType::isText(msg->content_type); + return is_text(msg->content_type); } bool_t linphone_chat_message_get_to_be_stored(const LinphoneChatMessage *msg) { @@ -773,7 +1581,7 @@ const LinphoneAddress *linphone_chat_message_get_to_address(const LinphoneChatMe if (msg->to) return msg->to; if (msg->dir == LinphoneChatMessageOutgoing) { - return msg->chat_room->cr->getPeerAddress(); + return msg->chat_room->peer_url; } return NULL; } @@ -809,7 +1617,7 @@ int linphone_chat_message_set_text(LinphoneChatMessage *msg, const char* text) { msg->message = ms_strdup(text); else msg->message = NULL; - + return 0; } @@ -909,7 +1717,7 @@ void linphone_chat_message_unref(LinphoneChatMessage *msg) { belle_sip_object_unref(msg); } -void linphone_chat_message_deactivate(LinphoneChatMessage *msg){ +static void linphone_chat_message_deactivate(LinphoneChatMessage *msg){ if (msg->file_transfer_information != NULL) { _linphone_chat_message_cancel_file_transfer(msg, FALSE); } @@ -917,7 +1725,7 @@ void linphone_chat_message_deactivate(LinphoneChatMessage *msg){ msg->chat_room = NULL; } -void linphone_chat_message_release(LinphoneChatMessage *msg) { +static void linphone_chat_message_release(LinphoneChatMessage *msg) { linphone_chat_message_deactivate(msg); linphone_chat_message_unref(msg); } @@ -935,3 +1743,7 @@ LinphoneReason linphone_chat_message_get_reason(LinphoneChatMessage *msg) { LinphoneChatMessageCbs *linphone_chat_message_get_callbacks(const LinphoneChatMessage *msg) { return msg->callbacks; } + +LinphoneCall *linphone_chat_room_get_call(const LinphoneChatRoom *room) { + return room->call; +} diff --git a/coreapi/chat_file_transfer.c b/coreapi/chat_file_transfer.c index 02fb3daa3..c1fd37984 100644 --- a/coreapi/chat_file_transfer.c +++ b/coreapi/chat_file_transfer.c @@ -26,12 +26,8 @@ #include "private.h" #include "ortp/b64.h" -#include "chat/chat-room.h" - -extern LinphonePrivate::ChatRoom& linphone_chat_room_get_cpp_obj(LinphoneChatRoom *cr); - static bool_t file_transfer_in_progress_and_valid(LinphoneChatMessage* msg) { - return (msg->chat_room && linphone_chat_room_get_core(msg->chat_room) && msg->http_request && !belle_http_request_is_cancelled(msg->http_request)); + return (msg->chat_room && msg->chat_room->lc && msg->http_request && !belle_http_request_is_cancelled(msg->http_request)); } static void _release_http_request(LinphoneChatMessage* msg) { @@ -92,7 +88,7 @@ static void linphone_chat_message_file_transfer_on_progress(belle_sip_body_handl msg, msg->file_transfer_information, offset, total); } else { /* Legacy: call back given by application level */ - linphone_core_notify_file_transfer_progress_indication(linphone_chat_room_get_core(msg->chat_room), msg, msg->file_transfer_information, + linphone_core_notify_file_transfer_progress_indication(msg->chat_room->lc, msg, msg->file_transfer_information, offset, total); } } @@ -112,7 +108,7 @@ static int on_send_body(belle_sip_user_body_handler_t *bh, belle_sip_message_t * return BELLE_SIP_STOP; } - lc = linphone_chat_room_get_core(msg->chat_room); + lc = msg->chat_room->lc; /* if we've not reach the end of file yet, ask for more data */ /* in case of file body handler, won't be called */ if (msg->file_transfer_filepath == NULL && offset < linphone_content_get_size(msg->file_transfer_information)) { @@ -157,7 +153,7 @@ static int on_send_body(belle_sip_user_body_handler_t *bh, belle_sip_message_t * static void on_send_end(belle_sip_user_body_handler_t *bh, void *data) { LinphoneChatMessage *msg = (LinphoneChatMessage *)data; - LinphoneCore *lc = linphone_chat_room_get_core(msg->chat_room); + LinphoneCore *lc = msg->chat_room->lc; LinphoneImEncryptionEngine *imee = linphone_core_get_im_encryption_engine(lc); if (imee) { @@ -189,7 +185,8 @@ static void file_upload_begin_background_task(LinphoneChatMessage *obj){ } } -static void linphone_chat_message_process_response_from_post_file(void *data, const belle_http_response_event_t *event) { +static void linphone_chat_message_process_response_from_post_file(void *data, + const belle_http_response_event_t *event) { LinphoneChatMessage *msg = (LinphoneChatMessage *)data; if (msg->http_request && !file_transfer_in_progress_and_valid(msg)) { @@ -208,7 +205,7 @@ static void linphone_chat_message_process_response_from_post_file(void *data, co belle_sip_body_handler_t *first_part_bh; bool_t is_file_encryption_enabled = FALSE; - LinphoneImEncryptionEngine *imee = linphone_core_get_im_encryption_engine(linphone_chat_room_get_core(msg->chat_room)); + LinphoneImEncryptionEngine *imee = linphone_core_get_im_encryption_engine(msg->chat_room->lc); if (imee) { LinphoneImEncryptionEngineCbs *imee_cbs = linphone_im_encryption_engine_get_callbacks(imee); LinphoneImEncryptionEngineCbsIsEncryptionEnabledForFileTransferCb is_encryption_enabled_for_file_transfer_cb = @@ -342,7 +339,7 @@ static void linphone_chat_message_process_response_from_post_file(void *data, co linphone_chat_message_ref(msg); linphone_chat_message_set_state(msg, LinphoneChatMessageStateFileTransferDone); _release_http_request(msg); - linphone_chat_room_get_cpp_obj(msg->chat_room).sendMessage(msg); + _linphone_chat_room_send_message(msg->chat_room, msg); file_upload_end_background_task(msg); linphone_chat_message_unref(msg); } else { @@ -377,7 +374,7 @@ static void on_recv_body(belle_sip_user_body_handler_t *bh, belle_sip_message_t linphone_chat_message_cancel_file_transfer(msg); return; } - lc = linphone_chat_room_get_core(msg->chat_room); + lc = msg->chat_room->lc; if (lc == NULL){ return; /*might happen during linphone_core_destroy()*/ @@ -428,7 +425,7 @@ static void on_recv_body(belle_sip_user_body_handler_t *bh, belle_sip_message_t static void on_recv_end(belle_sip_user_body_handler_t *bh, void *data) { LinphoneChatMessage *msg = (LinphoneChatMessage *)data; - LinphoneCore *lc = linphone_chat_room_get_core(msg->chat_room); + LinphoneCore *lc = msg->chat_room->lc; LinphoneImEncryptionEngine *imee = linphone_core_get_im_encryption_engine(lc); int retval = -1; @@ -539,7 +536,7 @@ static void linphone_chat_process_response_from_get_file(void *data, const belle int _linphone_chat_room_start_http_transfer(LinphoneChatMessage *msg, const char* url, const char* action, const belle_http_request_listener_callbacks_t *cbs) { belle_generic_uri_t *uri = NULL; - const char* ua = linphone_core_get_user_agent(linphone_chat_room_get_core(msg->chat_room)); + const char* ua = linphone_core_get_user_agent(msg->chat_room->lc); if (url == NULL) { ms_warning("Cannot process file transfer msg: no file remote URI configured."); @@ -562,7 +559,7 @@ int _linphone_chat_room_start_http_transfer(LinphoneChatMessage *msg, const char /* give msg to listener to be able to start the actual file upload when server answer a 204 No content */ msg->http_listener = belle_http_request_listener_create_from_callbacks(cbs, linphone_chat_message_ref(msg)); - belle_http_provider_send_request(linphone_chat_room_get_core(msg->chat_room)->http_provider, msg->http_request, msg->http_listener); + belle_http_provider_send_request(msg->chat_room->lc->http_provider, msg->http_request, msg->http_listener); return 0; error: if (uri) { @@ -583,7 +580,7 @@ int linphone_chat_room_upload_file(LinphoneChatMessage *msg) { cbs.process_response = linphone_chat_message_process_response_from_post_file; cbs.process_io_error = linphone_chat_message_process_io_error_upload; cbs.process_auth_requested = linphone_chat_message_process_auth_requested_upload; - err = _linphone_chat_room_start_http_transfer(msg, linphone_core_get_file_transfer_server(linphone_chat_room_get_core(msg->chat_room)), "POST", &cbs); + err = _linphone_chat_room_start_http_transfer(msg, linphone_core_get_file_transfer_server(msg->chat_room->lc), "POST", &cbs); if (err == -1){ linphone_chat_message_set_state(msg, LinphoneChatMessageStateNotDelivered); } @@ -624,10 +621,10 @@ void _linphone_chat_message_cancel_file_transfer(LinphoneChatMessage *msg, bool_ if (!belle_http_request_is_cancelled(msg->http_request)) { if (msg->chat_room) { ms_message("Canceling file transfer %s - msg [%p] chat room[%p]" - , (msg->external_body_url == NULL) ? linphone_core_get_file_transfer_server(linphone_chat_room_get_core(msg->chat_room)) : msg->external_body_url + , (msg->external_body_url == NULL) ? linphone_core_get_file_transfer_server(msg->chat_room->lc) : msg->external_body_url , msg , msg->chat_room); - belle_http_provider_cancel_request(linphone_chat_room_get_core(msg->chat_room)->http_provider, msg->http_request); + belle_http_provider_cancel_request(msg->chat_room->lc->http_provider, msg->http_request); if ((msg->dir == LinphoneChatMessageOutgoing) && unref) { // must release it linphone_chat_message_unref(msg); @@ -657,6 +654,20 @@ const char *linphone_chat_message_get_file_transfer_filepath(LinphoneChatMessage return msg->file_transfer_filepath; } -LinphoneChatMessage *linphone_chat_room_create_file_transfer_message(LinphoneChatRoom *cr, const LinphoneContent *initial_content) { - return linphone_chat_room_get_cpp_obj(cr).createFileTransferMessage(initial_content); +LinphoneChatMessage *linphone_chat_room_create_file_transfer_message(LinphoneChatRoom *cr, + const LinphoneContent *initial_content) { + LinphoneChatMessage *msg = belle_sip_object_new(LinphoneChatMessage); + msg->callbacks = linphone_chat_message_cbs_new(); + msg->chat_room = (LinphoneChatRoom *)cr; + msg->message = NULL; + msg->file_transfer_information = linphone_content_copy(initial_content); + msg->dir = LinphoneChatMessageOutgoing; + linphone_chat_message_set_to(msg, linphone_chat_room_get_peer_address(cr)); + msg->from = linphone_address_new(linphone_core_get_identity(cr->lc)); /*direct assignment*/ + /* this will be set to application/vnd.gsma.rcs-ft-http+xml when we will transfer the xml reply from server to the peers */ + msg->content_type = NULL; + /* this will store the http request during file upload to the server */ + msg->http_request = NULL; + msg->time = ms_time(0); + return msg; } diff --git a/coreapi/event.c b/coreapi/event.c index cb7a7f898..d5926dd96 100644 --- a/coreapi/event.c +++ b/coreapi/event.c @@ -128,14 +128,10 @@ void linphone_event_set_state(LinphoneEvent *lev, LinphoneSubscriptionState stat void linphone_event_set_publish_state(LinphoneEvent *lev, LinphonePublishState state){ if (lev->publish_state!=state){ - ms_message("LinphoneEvent [%p] moving from [%s] to publish state %s" - , lev - , linphone_publish_state_to_string(lev->publish_state) - , linphone_publish_state_to_string(state)); + ms_message("LinphoneEvent [%p] moving to publish state %s",lev,linphone_publish_state_to_string(state)); lev->publish_state=state; linphone_core_notify_publish_state_changed(lev->lc,lev,state); switch(state){ - case LinphonePublishNone: /*this state is probably trigered by a network state change to DOWN, we should release the op*/ case LinphonePublishCleared: linphone_event_release(lev); break; @@ -145,6 +141,7 @@ void linphone_event_set_publish_state(LinphoneEvent *lev, LinphonePublishState s case LinphonePublishError: linphone_event_release(lev); break; + case LinphonePublishNone: case LinphonePublishProgress: case LinphonePublishExpiring: /*nothing special to do*/ @@ -278,7 +275,7 @@ LinphoneStatus linphone_event_notify(LinphoneEvent *lev, const LinphoneContent * static LinphoneEvent *_linphone_core_create_publish(LinphoneCore *core, LinphoneProxyConfig *cfg, const LinphoneAddress *resource, const char *event, int expires){ LinphoneCore *lc = core; LinphoneEvent *lev; - + if (!lc && cfg) { if (cfg->lc) lc = cfg->lc; @@ -289,7 +286,7 @@ static LinphoneEvent *_linphone_core_create_publish(LinphoneCore *core, Linphone } if (!resource && cfg) resource = linphone_proxy_config_get_identity_address(cfg); - + lev = linphone_event_new(lc,LinphoneSubscriptionInvalidDir, event,expires); linphone_configure_op_with_proxy(lc,lev->op,resource,NULL,lp_config_get_int(lc->config,"sip","publish_msg_with_contact",0),cfg); sal_op_set_manual_refresher_mode(lev->op,!lp_config_get_int(lc->config,"sip","refresh_generic_publish",1)); @@ -299,10 +296,10 @@ LinphoneEvent *linphone_core_create_publish(LinphoneCore *lc, const LinphoneAddr return _linphone_core_create_publish(lc, NULL, resource, event, expires); } LinphoneEvent *linphone_proxy_config_create_publish(LinphoneProxyConfig *cfg, const char *event, int expires) { - + return _linphone_core_create_publish(NULL, cfg,NULL, event, expires); - - + + } LinphoneEvent *linphone_core_create_one_shot_publish(LinphoneCore *lc, const LinphoneAddress *resource, const char *event){ LinphoneEvent *lev = linphone_core_create_publish(lc, resource, event, -1); @@ -423,9 +420,6 @@ static void linphone_event_destroy(LinphoneEvent *lev){ if (lev->ei) linphone_error_info_unref(lev->ei); if (lev->op) sal_op_release(lev->op); if (lev->send_custom_headers) sal_custom_header_free(lev->send_custom_headers); - if (lev->to_address) linphone_address_unref(lev->to_address); - if (lev->from_address) linphone_address_unref(lev->from_address); - ms_free(lev->name); } @@ -445,34 +439,20 @@ const char *linphone_event_get_name(const LinphoneEvent *lev){ return lev->name; } -static const LinphoneAddress *_linphone_event_cache_to (const LinphoneEvent *lev) { - if (lev->to_address) - linphone_address_unref(lev->to_address); - char *buf = sal_address_as_string(sal_op_get_to_address(lev->op)); - ((LinphoneEvent *)lev)->to_address = linphone_address_new(buf); - ms_free(buf); - return lev->to_address; -} - -static const LinphoneAddress *_linphone_event_cache_from (const LinphoneEvent *lev) { - if (lev->from_address) - linphone_address_unref(lev->from_address); - char *buf = sal_address_as_string(sal_op_get_from_address(lev->op)); - ((LinphoneEvent *)lev)->from_address = linphone_address_new(buf); - ms_free(buf); - return lev->from_address; -} - -const LinphoneAddress *linphone_event_get_from (const LinphoneEvent *lev) { - if (lev->is_out_of_dialog_op && lev->dir == LinphoneSubscriptionOutgoing) - return _linphone_event_cache_to(lev); - return _linphone_event_cache_from(lev); +const LinphoneAddress *linphone_event_get_from(const LinphoneEvent *lev){ + if (lev->is_out_of_dialog_op && lev->dir == LinphoneSubscriptionOutgoing){ + return (LinphoneAddress*)sal_op_get_to_address(lev->op); + }else{ + return (LinphoneAddress*)sal_op_get_from_address(lev->op); + } } const LinphoneAddress *linphone_event_get_resource(const LinphoneEvent *lev){ - if (lev->is_out_of_dialog_op && lev->dir == LinphoneSubscriptionOutgoing) - return _linphone_event_cache_from(lev); - return _linphone_event_cache_to(lev); + if (lev->is_out_of_dialog_op && lev->dir == LinphoneSubscriptionOutgoing){ + return (LinphoneAddress*)sal_op_get_from_address(lev->op); + }else{ + return (LinphoneAddress*)sal_op_get_to_address(lev->op); + } } LinphoneCore *linphone_event_get_core(const LinphoneEvent *lev){ @@ -497,3 +477,4 @@ BELLE_SIP_INSTANCIATE_VPTR(LinphoneEvent, belle_sip_object_t, _linphone_event_marshall, FALSE ); + diff --git a/coreapi/factory.c b/coreapi/factory.c index 65bc944e2..27e30e984 100644 --- a/coreapi/factory.c +++ b/coreapi/factory.c @@ -48,7 +48,7 @@ struct _LinphoneFactory { char *ring_resources_dir; char *image_resources_dir; char *msplugins_dir; - + /*these are the cached result computed from directories set by the application*/ char *cached_data_resources_dir; char *cached_sound_resources_dir; @@ -67,7 +67,7 @@ static void linphone_factory_uninit(LinphoneFactory *obj){ STRING_RESET(obj->ring_resources_dir); STRING_RESET(obj->image_resources_dir); STRING_RESET(obj->msplugins_dir); - + STRING_RESET(obj->cached_data_resources_dir); STRING_RESET(obj->cached_sound_resources_dir); STRING_RESET(obj->cached_ring_resources_dir); @@ -94,7 +94,7 @@ static void _linphone_factory_destroying_cb(void) { #define ADD_SUPPORTED_VIDEO_DEFINITION(factory, width, height, name) \ (factory)->supported_video_definitions = bctbx_list_append((factory)->supported_video_definitions, \ - linphone_video_definition_new(width, height, name)) + linphone_video_definition_ref(linphone_video_definition_new(width, height, name))) static void initialize_supported_video_definitions(LinphoneFactory *factory) { #if !defined(__ANDROID__) && !TARGET_OS_IPHONE @@ -163,7 +163,7 @@ LinphoneCoreCbs *linphone_factory_create_core_cbs(const LinphoneFactory *factory } LinphoneAddress *linphone_factory_create_address(const LinphoneFactory *factory, const char *addr) { - return linphone_address_new(addr); + return _linphone_address_new(addr); } LinphoneAuthInfo *linphone_factory_create_auth_info(const LinphoneFactory *factory, const char *username, const char *userid, const char *passwd, const char *ha1, const char *realm, const char *domain) { @@ -179,8 +179,7 @@ LinphoneVcard *linphone_factory_create_vcard(LinphoneFactory *factory) { } LinphoneVideoDefinition * linphone_factory_create_video_definition(const LinphoneFactory *factory, unsigned int width, unsigned int height) { - LinphoneVideoDefinition *supported = linphone_factory_find_supported_video_definition(factory, width, height); - return supported ? linphone_video_definition_clone(supported) : linphone_video_definition_new(width, height, NULL); + return linphone_video_definition_ref(linphone_video_definition_new(width, height, NULL)); } LinphoneVideoDefinition * linphone_factory_create_video_definition_from_name(const LinphoneFactory *factory, const char *name) { @@ -202,17 +201,16 @@ LinphoneVideoDefinition * linphone_factory_find_supported_video_definition(const const bctbx_list_t *item; const bctbx_list_t *supported = linphone_factory_get_supported_video_definitions(factory); LinphoneVideoDefinition *searched_vdef = linphone_video_definition_new(width, height, NULL); - LinphoneVideoDefinition *found = NULL; for (item = supported; item != NULL; item = bctbx_list_next(item)) { LinphoneVideoDefinition *svdef = (LinphoneVideoDefinition *)bctbx_list_get_data(item); if (linphone_video_definition_equals(svdef, searched_vdef)) { - found = svdef; - break; + linphone_video_definition_unref(searched_vdef); + return linphone_video_definition_clone(svdef); } } - linphone_video_definition_unref(searched_vdef); - return found; + + return searched_vdef; } LinphoneVideoDefinition * linphone_factory_find_supported_video_definition_by_name(const LinphoneFactory *factory, const char *name) { @@ -222,7 +220,7 @@ LinphoneVideoDefinition * linphone_factory_find_supported_video_definition_by_na for (item = supported; item != NULL; item = bctbx_list_next(item)) { LinphoneVideoDefinition *svdef = (LinphoneVideoDefinition *)bctbx_list_get_data(item); if (strcmp(linphone_video_definition_get_name(svdef), name) == 0) { - return svdef; + return linphone_video_definition_clone(svdef); } } return NULL; @@ -303,9 +301,9 @@ void linphone_factory_set_msplugins_dir(LinphoneFactory *factory, const char *pa } LinphoneErrorInfo *linphone_factory_create_error_info(LinphoneFactory *factory){ - + return linphone_error_info_new(); - + } LinphoneRange *linphone_factory_create_range(LinphoneFactory *factory) { @@ -318,4 +316,4 @@ LinphoneTransports *linphone_factory_create_transports(LinphoneFactory *factory) LinphoneVideoActivationPolicy *linphone_factory_create_video_activation_policy(LinphoneFactory *factory) { return linphone_video_activation_policy_new(); -} +} \ No newline at end of file diff --git a/coreapi/help/doc/doxygen/CMakeLists.txt b/coreapi/help/doc/doxygen/CMakeLists.txt index 2574eb772..181dba7dc 100644 --- a/coreapi/help/doc/doxygen/CMakeLists.txt +++ b/coreapi/help/doc/doxygen/CMakeLists.txt @@ -1,8 +1,8 @@ -################################################################################ +############################################################################ # CMakeLists.txt # Copyright (C) 2017 Belledonne Communications, Grenoble France # -################################################################################ +############################################################################ # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License @@ -18,36 +18,32 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # -################################################################################ +############################################################################ if (ENABLE_DOC OR ENABLE_CXX_WRAPPER OR ENABLE_CSHARP_WRAPPER) - find_package(Doxygen) - if (DOXYGEN_FOUND) - if (DOXYGEN_DOT_FOUND) - set(DOC_INPUT_FILES ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile - ${CMAKE_CURRENT_SOURCE_DIR}/doxygen.dox - ${LINPHONE_HEADER_FILES} - ) - set(DOXYGEN_INPUT "") - foreach (HEADER_FILE ${LINPHONE_HEADER_FILES}) - string(CONCAT DOXYGEN_INPUT ${DOXYGEN_INPUT} " \"${HEADER_FILE}\"") - endforeach () - string(CONCAT DOXYGEN_INPUT ${DOXYGEN_INPUT} " \"${CMAKE_CURRENT_SOURCE_DIR}\"") - string(CONCAT DOXYGEN_INPUT ${DOXYGEN_INPUT} " \"${PROJECT_SOURCE_DIR}/coreapi/help/examples/C\"") - configure_file(${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile) - add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/html/index.html" "${CMAKE_CURRENT_BINARY_DIR}/xml/index.xml" - COMMAND ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile - DEPENDS ${DOC_INPUT_FILES} - ) - add_custom_target(linphone-doc ALL DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/html/index.html" "${CMAKE_CURRENT_BINARY_DIR}/xml/index.xml") - install(DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/html" "${CMAKE_CURRENT_BINARY_DIR}/xml" - DESTINATION "${CMAKE_INSTALL_DATADIR}/doc/linphone-${LINPHONE_VERSION}") - else () - if (ENABLE_CXX_WRAPPER) - message(FATAL_ERROR "The dot program is needed to generate the linphone documentation. You can get it from http://www.graphviz.org/.") - else () - message(WARNING "The dot program is needed to generate the linphone documentation. You can get it from http://www.graphviz.org/.") - endif () - endif () - endif () -endif () + find_package(Doxygen) + if(DOXYGEN_FOUND) + if(DOXYGEN_DOT_FOUND) + set(top_srcdir "${PROJECT_SOURCE_DIR}") + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile) + set(DOC_INPUT_FILES ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile + ${CMAKE_CURRENT_SOURCE_DIR}/doxygen.dox + ${LINPHONE_HEADER_FILES} + ) + add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/html/index.html" "${CMAKE_CURRENT_BINARY_DIR}/xml/index.xml" + COMMAND ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile + DEPENDS ${DOC_INPUT_FILES} + ) + add_custom_target(linphone-doc ALL DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/html/index.html" "${CMAKE_CURRENT_BINARY_DIR}/xml/index.xml") + install(DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/html" "${CMAKE_CURRENT_BINARY_DIR}/xml" + DESTINATION "${CMAKE_INSTALL_DATADIR}/doc/linphone-${LINPHONE_VERSION}") + else() + if (ENABLE_CXX_WRAPPER) + message(FATAL_ERROR "The dot program is needed to generate the linphone documentation. You can get it from http://www.graphviz.org/.") + else() + message(WARNING "The dot program is needed to generate the linphone documentation. You can get it from http://www.graphviz.org/.") + endif() + endif() + endif() +endif() + diff --git a/coreapi/help/doc/doxygen/Doxyfile.in b/coreapi/help/doc/doxygen/Doxyfile.in index 1e0ea6679..9aeb18d6f 100644 --- a/coreapi/help/doc/doxygen/Doxyfile.in +++ b/coreapi/help/doc/doxygen/Doxyfile.in @@ -772,7 +772,9 @@ WARN_LOGFILE = # spaces. See also FILE_PATTERNS and EXTENSION_MAPPING # Note: If this tag is empty the current directory is searched. -INPUT = @DOXYGEN_INPUT@ +INPUT = @top_srcdir@/include/linphone \ + @top_srcdir@/coreapi/help/doc/doxygen \ + @top_srcdir@/coreapi/help/examples/C # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses diff --git a/coreapi/lime.c b/coreapi/lime.c index 80ebfefc1..ba4e00027 100644 --- a/coreapi/lime.c +++ b/coreapi/lime.c @@ -749,11 +749,11 @@ error: bool_t linphone_chat_room_lime_available(LinphoneChatRoom *cr) { if (cr) { - switch (linphone_core_lime_enabled(linphone_chat_room_get_core(cr))) { + switch (linphone_core_lime_enabled(cr->lc)) { case LinphoneLimeDisabled: return FALSE; case LinphoneLimeMandatory: case LinphoneLimePreferred: { - void *zrtp_cache_db = linphone_core_get_zrtp_cache_db(linphone_chat_room_get_core(cr)); + void *zrtp_cache_db = linphone_core_get_zrtp_cache_db(cr->lc); if (zrtp_cache_db != NULL) { bool_t res; limeURIKeys_t associatedKeys; @@ -832,7 +832,7 @@ int lime_im_encryption_engine_process_outgoing_message_cb(LinphoneImEncryptionEn LinphoneCore *lc = linphone_im_encryption_engine_get_core(engine); int errcode = -1; const char *new_content_type = "xml/cipher"; - if(linphone_core_lime_enabled(linphone_chat_room_get_core(room))) { + if(linphone_core_lime_enabled(room->lc)) { if (linphone_chat_room_lime_available(room)) { void *zrtp_cache_db = NULL; /* use a void * instead of sqlite3 * to avoid problems and ifdef when SQLITE is not available(the get function shall return NULL in that case) */ if (msg->content_type) { @@ -862,7 +862,7 @@ int lime_im_encryption_engine_process_outgoing_message_cb(LinphoneImEncryptionEn retval = lime_createMultipartMessage(zrtp_cache_db, msg->content_type, (uint8_t *)msg->message, selfUri, peerUri, &crypted_body); if (retval != 0) { /* fail to encrypt */ - ms_warning("Unable to encrypt message for %s : %s", peerUri, lime_error_code_to_string(retval)); + ms_warning("Unable to encrypt message for %s : %s", room->peer, lime_error_code_to_string(retval)); if (crypted_body) ms_free(crypted_body); errcode = 488; } else { /* encryption ok, swap plain text message body by encrypted one */ diff --git a/coreapi/linphonecall.c b/coreapi/linphonecall.c index 9a67095d5..c455c68e2 100644 --- a/coreapi/linphonecall.c +++ b/coreapi/linphonecall.c @@ -43,9 +43,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include -// For migration purpose. -#include "address/address-p.h" -#include "c-wrapper/c-tools.h" inline OrtpRtcpXrStatSummaryFlag operator|(OrtpRtcpXrStatSummaryFlag a, OrtpRtcpXrStatSummaryFlag b) { return static_cast(static_cast(a) | static_cast(b)); @@ -1202,7 +1199,7 @@ void linphone_call_create_op(LinphoneCall *call){ **/ static void linphone_call_outgoing_select_ip_version(LinphoneCall *call, LinphoneAddress *to, LinphoneProxyConfig *cfg){ if (linphone_core_ipv6_enabled(call->core)){ - if (sal_address_is_ipv6(L_GET_PRIVATE_FROM_C_STRUCT(to, Address)->getInternalAddress())) { + if (sal_address_is_ipv6((SalAddress*)to)){ call->af=AF_INET6; }else if (cfg && cfg->op){ call->af=sal_op_get_address_family(cfg->op); @@ -1365,8 +1362,7 @@ LinphoneCall * linphone_call_new_outgoing(struct _LinphoneCore *lc, LinphoneAddr linphone_call_check_ice_session(call, IR_Controlling, FALSE); - if (linphone_nat_policy_stun_enabled(call->nat_policy) && !(linphone_nat_policy_ice_enabled(call->nat_policy) - || linphone_nat_policy_turn_enabled(call->nat_policy))) { + if (linphone_nat_policy_ice_enabled(call->nat_policy)) { call->ping_time=linphone_core_run_stun_tests(call->core,call); } #ifdef BUILD_UPNP @@ -1723,7 +1719,7 @@ static void linphone_call_set_terminated(LinphoneCall *call){ call->ringing_beep=FALSE; } if (call->chat_room){ - linphone_chat_room_set_call(call->chat_room, NULL); + call->chat_room->call = NULL; } if (lc->calls == NULL){ ms_bandwidth_controller_reset_state(lc->bw_controller); @@ -1868,32 +1864,6 @@ void linphone_call_set_state(LinphoneCall *call, LinphoneCallState cstate, const call->log->status=LinphoneCallMissed; } break; - case LinphoneReasonNone: - if (call->log->dir == LinphoneCallIncoming){ - const LinphoneErrorInfo *ei = linphone_call_get_error_info(call); - if (ei) { - int code = linphone_error_info_get_protocol_code(ei); - if((code >= 200 && code < 300)) { - // error between 200-299 means accepted elsewhere - call->log->status=LinphoneCallAcceptedElsewhere; - break; - } - } - } - break; - case LinphoneReasonDoNotDisturb: - if (call->log->dir == LinphoneCallIncoming){ - const LinphoneErrorInfo *ei = linphone_call_get_error_info(call); - if (ei) { - int code = linphone_error_info_get_protocol_code(ei); - if(code >= 600 && code < 700) { - // error between 600-699 means declined elsewhere - call->log->status=LinphoneCallDeclinedElsewhere; - break; - } - } - } - break; default: break; } @@ -2070,10 +2040,10 @@ const LinphoneCallParams * linphone_call_get_current_params(LinphoneCall *call){ if (vstream != NULL) { call->current_params->sent_vsize = video_stream_get_sent_video_size(vstream); call->current_params->recv_vsize = video_stream_get_received_video_size(vstream); - call->current_params->sent_vdef = linphone_factory_create_video_definition( - linphone_factory_get(), call->current_params->sent_vsize.width, call->current_params->sent_vsize.height); - call->current_params->recv_vdef = linphone_factory_create_video_definition( - linphone_factory_get(), call->current_params->recv_vsize.width, call->current_params->recv_vsize.height); + call->current_params->sent_vdef = linphone_video_definition_ref(linphone_factory_find_supported_video_definition( + linphone_factory_get(), call->current_params->sent_vsize.width, call->current_params->sent_vsize.height)); + call->current_params->recv_vdef = linphone_video_definition_ref(linphone_factory_find_supported_video_definition( + linphone_factory_get(), call->current_params->recv_vsize.width, call->current_params->recv_vsize.height)); call->current_params->sent_fps = video_stream_get_sent_framerate(vstream); call->current_params->received_fps = video_stream_get_received_framerate(vstream); } @@ -4989,19 +4959,14 @@ static LinphoneAddress *get_fixed_contact(LinphoneCore *lc, LinphoneCall *call , /* if already choosed, don't change it */ return NULL; } else if (call->ping_op && sal_op_get_contact_address(call->ping_op)) { - char *addr = sal_address_as_string(sal_op_get_contact_address(call->ping_op)); /* if the ping OPTIONS request succeeded use the contact guessed from the received, rport*/ ms_message("Contact has been fixed using OPTIONS"/* to %s",guessed*/); - ret=linphone_address_new(addr); - ms_free(addr); + ret=linphone_address_clone(sal_op_get_contact_address(call->ping_op));; } else if (dest_proxy && dest_proxy->op && sal_op_get_contact_address(dest_proxy->op)){ - char *addr = sal_address_as_string(sal_op_get_contact_address(dest_proxy->op)); - /*if using a proxy, use the contact address as guessed with the REGISTERs*/ ms_message("Contact has been fixed using proxy" /*to %s",fixed_contact*/); - ret=linphone_address_new(addr); - ms_free(addr); + ret=linphone_address_clone(sal_op_get_contact_address(dest_proxy->op)); } else { ctt=linphone_core_get_primary_contact_parsed(lc); if (ctt!=NULL){ @@ -5016,17 +4981,9 @@ static LinphoneAddress *get_fixed_contact(LinphoneCore *lc, LinphoneCall *call , } void linphone_call_set_contact_op(LinphoneCall* call) { - SalAddress *sal_address = nullptr; - { - LinphoneAddress *contact = get_fixed_contact(call->core,call,call->dest_proxy); - if (contact) { - sal_address = const_cast(L_GET_PRIVATE_FROM_C_STRUCT(contact, Address)->getInternalAddress()); - sal_address_ref(sal_address); - linphone_address_unref(contact); - } - } - - sal_op_set_and_clean_contact_address(call->op, sal_address); + LinphoneAddress *contact; + contact=get_fixed_contact(call->core,call,call->dest_proxy); + sal_op_set_and_clean_contact_address(call->op, (SalAddress *)contact); } LinphonePlayer *linphone_call_get_player(LinphoneCall *call){ diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index d629a5d93..a0c4c78ad 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -46,10 +46,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "mediastreamer2/msogl.h" #include "mediastreamer2/msvolume.h" -// For migration purpose. -#include "address/address-p.h" -#include "c-wrapper/c-tools.h" - #ifdef INET6 #ifndef _WIN32 #include @@ -3384,7 +3380,7 @@ static bctbx_list_t *make_routes_for_proxy(LinphoneProxyConfig *proxy, const Lin ret=bctbx_list_append(ret,sal_address_new(local_route)); } if (srv_route){ - ret=bctbx_list_append(ret,sal_address_clone(L_GET_PRIVATE_FROM_C_STRUCT(srv_route, Address)->getInternalAddress())); + ret=bctbx_list_append(ret,sal_address_clone((SalAddress*)srv_route)); } if (ret==NULL){ /*if the proxy address matches the domain part of the destination, then use the same transport @@ -3411,7 +3407,7 @@ LinphoneProxyConfig * linphone_core_lookup_known_proxy(LinphoneCore *lc, const L /*return default proxy if it is matching the destination uri*/ if (default_cfg){ const char *domain=linphone_proxy_config_get_domain(default_cfg); - if (domain && !strcmp(domain,linphone_address_get_domain(uri))){ + if (strcmp(domain,linphone_address_get_domain(uri))==0){ found_cfg=default_cfg; goto end; } @@ -3503,9 +3499,7 @@ void linphone_configure_op_with_proxy(LinphoneCore *lc, SalOp *op, const Linphon routes=make_routes_for_proxy(proxy,dest); linphone_transfer_routes_to_op(routes,op); } - char *addr = linphone_address_as_string(dest); - sal_op_set_to(op,addr); - ms_free(addr); + sal_op_set_to_address(op,dest); sal_op_set_from(op,identity); sal_op_set_sent_custom_header(op,headers); sal_op_set_realm(op,linphone_proxy_config_get_realm(proxy)); @@ -6040,10 +6034,6 @@ LinphoneConfig * linphone_core_create_config(LinphoneCore *lc, const char *filen return lp_config_new(filename); } -LinphoneAddress * linphone_core_create_address(LinphoneCore *lc, const char *address) { - return linphone_address_new(address); -} - static void linphone_core_uninit(LinphoneCore *lc) { bctbx_list_t *elem = NULL; @@ -6163,8 +6153,6 @@ static void stop_refreshing_proxy_config(bool_t is_sip_reachable, LinphoneProxyC linphone_proxy_config_set_state(cfg, LinphoneRegistrationNone,"Registration impossible (network down)"); }else{ cfg->commit=TRUE; - if (linphone_proxy_config_publish_enabled(cfg)) - cfg->send_publish=TRUE; /*not sure if really the best place*/ } } } diff --git a/coreapi/message_storage.c b/coreapi/message_storage.c index 0b9b39bd0..9067afdd7 100644 --- a/coreapi/message_storage.c +++ b/coreapi/message_storage.c @@ -23,7 +23,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #ifdef SQLITE_STORAGE_ENABLED -#include "chat/chat-room.h" #ifndef _WIN32 #if !defined(__QNXNTO__) && !defined(__ANDROID__) @@ -43,9 +42,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include -extern LinphonePrivate::ChatRoom& linphone_chat_room_get_cpp_obj(LinphoneChatRoom *cr); - - static char *utf8_convert(const char *filename){ char db_file_utf8[MAX_PATH_SIZE] = ""; #if defined(_WIN32) @@ -121,6 +117,31 @@ int _linphone_sqlite3_open(const char *db_file, sqlite3 **db) { #ifdef SQLITE_STORAGE_ENABLED + +static LinphoneChatMessage * get_weak_message(LinphoneChatRoom *cr, unsigned int storage_id) { + LinphoneChatMessage *cm; + bctbx_list_t *item; + for (item = cr->weak_messages; item != NULL; item = bctbx_list_next(item)) { + cm = (LinphoneChatMessage *)bctbx_list_get_data(item); + if (linphone_chat_message_get_storage_id(cm) == storage_id) + return linphone_chat_message_ref(cm); + } + return NULL; +} + +static ORTP_INLINE LinphoneChatMessage* get_transient_message(LinphoneChatRoom* cr, unsigned int storage_id){ + bctbx_list_t* transients = cr->transient_messages; + LinphoneChatMessage* chat; + while( transients ){ + chat = (LinphoneChatMessage*)transients->data; + if(chat->storage_id == storage_id){ + return linphone_chat_message_ref(chat); + } + transients = transients->next; + } + return NULL; +} + /* DB layout: * | 0 | storage_id * | 1 | type @@ -151,7 +172,7 @@ static int callback_content(void *data, int argc, char **argv, char **colName) { return 0; } -void linphone_chat_message_fetch_content_from_database(sqlite3 *db, LinphoneChatMessage *message, int content_id) { +static void fetch_content_from_database(sqlite3 *db, LinphoneChatMessage *message, int content_id) { char* errmsg = NULL; int ret; char * buf; @@ -165,6 +186,8 @@ void linphone_chat_message_fetch_content_from_database(sqlite3 *db, LinphoneChat sqlite3_free(buf); } + + // Called when fetching all conversations from database static int callback_all(void *data, int argc, char **argv, char **colName){ LinphoneCore* lc = (LinphoneCore*) data; @@ -177,6 +200,93 @@ static int callback_all(void *data, int argc, char **argv, char **colName){ return 0; } +/* DB layout: + * | 0 | storage_id + * | 1 | localContact + * | 2 | remoteContact + * | 3 | direction flag (LinphoneChatMessageDir) + * | 4 | message (text content of the message) + * | 5 | time (unused now, used to be string-based timestamp, replaced by the utc timestamp) + * | 6 | read flag (no longer used, replaced by the LinphoneChatMessageStateDisplayed state) + * | 7 | status (LinphoneChatMessageState) + * | 8 | external body url (deprecated file transfer system) + * | 9 | utc timestamp + * | 10 | app data text + * | 11 | linphone content id (LinphoneContent describing a file transfer) + * | 12 | message id (used for IMDN) + * | 13 | content type (of the message field [must be text representable]) + * | 14 | secured flag + */ +static int create_chat_message(void *data, int argc, char **argv, char **colName){ + LinphoneChatRoom *cr = (LinphoneChatRoom *)data; + unsigned int storage_id = (unsigned int)atoi(argv[0]); + LinphoneChatMessage* new_message; + + /* Check if the message exists in the weak messages list, in which case we should return that one. */ + new_message = get_weak_message(cr, storage_id); + if (new_message == NULL) { + /* Check if the message exists in the transient list, in which case we should return that one. */ + new_message = get_transient_message(cr, storage_id); + } + if (new_message == NULL) { + new_message = linphone_chat_room_create_message(cr, argv[4]); + + if(atoi(argv[3])==LinphoneChatMessageIncoming){ + new_message->dir=LinphoneChatMessageIncoming; + linphone_chat_message_set_from(new_message,linphone_chat_room_get_peer_address(cr)); + new_message->to = NULL; /*will be filled at the end */ + } else { + new_message->dir=LinphoneChatMessageOutgoing; + new_message->from = NULL; /*will be filled at the end */ + linphone_chat_message_set_to(new_message,linphone_chat_room_get_peer_address(cr)); + } + + new_message->time = (time_t)atol(argv[9]); + new_message->is_read=atoi(argv[6]); + new_message->state=static_cast(atoi(argv[7])); + new_message->storage_id=storage_id; + new_message->external_body_url= ms_strdup(argv[8]); + new_message->appdata = ms_strdup(argv[10]); + new_message->message_id = ms_strdup(argv[12]); + linphone_chat_message_set_content_type(new_message, argv[13]); + new_message->is_secured = (bool_t)atoi(argv[14]); + + if (argv[11] != NULL) { + int id = atoi(argv[11]); + if (id >= 0) { + fetch_content_from_database(cr->lc->db, new_message, id); + } + } + + /* Fix content type for old messages that were stored without it */ + if (new_message->content_type == NULL) { + if (new_message->file_transfer_information != NULL) { + new_message->content_type = ms_strdup("application/vnd.gsma.rcs-ft-http+xml"); + } else if (new_message->external_body_url != NULL) { + new_message->content_type = ms_strdup("message/external-body"); + } else { + new_message->content_type = ms_strdup("text/plain"); + } + } + + /* Add the new message to the weak messages list. */ + linphone_chat_room_add_weak_message(cr, new_message); + } + cr->messages_hist=bctbx_list_prepend(cr->messages_hist,new_message); + + return 0; +} + +void linphone_sql_request_message(sqlite3 *db,const char *stmt,LinphoneChatRoom *cr){ + char* errmsg=NULL; + int ret; + ret=sqlite3_exec(db,stmt,create_chat_message,cr,&errmsg); + if(ret != SQLITE_OK) { + ms_error("Error in creation: %s.", errmsg); + sqlite3_free(errmsg); + } +} + int linphone_sql_request(sqlite3* db,const char *stmt){ char* errmsg=NULL; int ret; @@ -297,7 +407,7 @@ void linphone_chat_message_store_update(LinphoneChatMessage *msg) { } void linphone_chat_message_store_state(LinphoneChatMessage *msg){ - LinphoneCore *lc=linphone_chat_room_get_core(msg->chat_room); + LinphoneCore *lc=msg->chat_room->lc; if (lc->db){ char *buf=sqlite3_mprintf("UPDATE history SET status=%i WHERE (id = %u);", msg->state,msg->storage_id); @@ -307,7 +417,7 @@ void linphone_chat_message_store_state(LinphoneChatMessage *msg){ } void linphone_chat_message_store_appdata(LinphoneChatMessage* msg){ - LinphoneCore *lc=linphone_chat_room_get_core(msg->chat_room); + LinphoneCore *lc=msg->chat_room->lc; if (lc->db){ char *buf=sqlite3_mprintf("UPDATE history SET appdata=%Q WHERE id=%u;", msg->appdata,msg->storage_id); @@ -316,44 +426,251 @@ void linphone_chat_message_store_appdata(LinphoneChatMessage* msg){ } } -void linphone_chat_room_mark_as_read(LinphoneChatRoom *cr) { - linphone_chat_room_get_cpp_obj(cr).markAsRead(); +void linphone_chat_room_mark_as_read(LinphoneChatRoom *cr){ + LinphoneCore *lc=linphone_chat_room_get_core(cr); + bctbx_list_t *item; + char *peer; + char *buf; + + if (lc->db==NULL) return ; + + // optimization: do not modify the database if no message is marked as unread + if(linphone_chat_room_get_unread_messages_count(cr) == 0) return; + + peer=linphone_address_as_string_uri_only(linphone_chat_room_get_peer_address(cr)); + buf = sqlite3_mprintf("SELECT * FROM history WHERE remoteContact = %Q AND direction = %i AND status != %i", peer, LinphoneChatMessageIncoming, LinphoneChatMessageStateDisplayed); + linphone_sql_request_message(lc->db, buf, cr); + sqlite3_free(buf); + for (item = cr->messages_hist; item != NULL; item = bctbx_list_next(item)) { + LinphoneChatMessage *cm = (LinphoneChatMessage *)bctbx_list_get_data(item); + linphone_chat_message_send_display_notification(cm); + } + bctbx_list_free_with_data(cr->messages_hist, (bctbx_list_free_func)linphone_chat_message_unref); + cr->messages_hist = NULL; + buf=sqlite3_mprintf("UPDATE history SET status=%i WHERE remoteContact=%Q AND direction=%i;", + LinphoneChatMessageStateDisplayed, peer, LinphoneChatMessageIncoming); + linphone_sql_request(lc->db,buf); + sqlite3_free(buf); + ms_free(peer); + + if (cr->pending_message) { + linphone_chat_message_set_state(cr->pending_message, LinphoneChatMessageStateDisplayed); + linphone_chat_message_send_display_notification(cr->pending_message); + } + + cr->unread_count = 0; } -int linphone_chat_room_get_unread_messages_count(LinphoneChatRoom *cr) { - return linphone_chat_room_get_cpp_obj(cr).getUnreadMessagesCount(); +void linphone_chat_room_update_url(LinphoneChatRoom *cr, LinphoneChatMessage *msg) { + LinphoneCore *lc=linphone_chat_room_get_core(cr); + char *buf; + + if (lc->db==NULL) return ; + + buf=sqlite3_mprintf("UPDATE history SET url=%Q WHERE id=%u;",msg->external_body_url,msg->storage_id); + linphone_sql_request(lc->db,buf); + sqlite3_free(buf); } -int linphone_chat_room_get_history_size(LinphoneChatRoom *cr) { - return linphone_chat_room_get_cpp_obj(cr).getHistorySize(); +static int linphone_chat_room_get_messages_count(LinphoneChatRoom *cr, bool_t unread_only){ + LinphoneCore *lc=linphone_chat_room_get_core(cr); + int numrows=0; + char *peer; + char *buf; + char *option = NULL; + sqlite3_stmt *selectStatement; + int returnValue; + + if (lc->db==NULL) return 0; + + // optimization: do not read database if the count is already available in memory + if(unread_only && cr->unread_count >= 0) return cr->unread_count; + + peer=linphone_address_as_string_uri_only(linphone_chat_room_get_peer_address(cr)); + if (unread_only) { + option = bctbx_strdup_printf("AND status!=%i AND direction=%i", LinphoneChatMessageStateDisplayed, LinphoneChatMessageIncoming); + } + buf=sqlite3_mprintf("SELECT count(*) FROM history WHERE remoteContact = %Q %s;",peer,unread_only?option:""); + returnValue = sqlite3_prepare_v2(lc->db,buf,-1,&selectStatement,NULL); + if (returnValue == SQLITE_OK){ + if(sqlite3_step(selectStatement) == SQLITE_ROW){ + numrows= sqlite3_column_int(selectStatement, 0); + } + } + sqlite3_finalize(selectStatement); + sqlite3_free(buf); + ms_free(peer); + + /* no need to test the sign of cr->unread_count here + * because it has been tested above */ + if(unread_only) { + cr->unread_count = numrows; + if (option) bctbx_free(option); + } + + return numrows; +} + +int linphone_chat_room_get_unread_messages_count(LinphoneChatRoom *cr){ + return linphone_chat_room_get_messages_count(cr, TRUE); +} + +int linphone_chat_room_get_history_size(LinphoneChatRoom *cr){ + return linphone_chat_room_get_messages_count(cr, FALSE); } void linphone_chat_room_delete_message(LinphoneChatRoom *cr, LinphoneChatMessage *msg) { - linphone_chat_room_get_cpp_obj(cr).deleteMessage(msg); + LinphoneCore *lc=cr->lc; + char *buf; + + if (lc->db==NULL) return ; + + buf=sqlite3_mprintf("DELETE FROM history WHERE id = %u;", msg->storage_id); + linphone_sql_request(lc->db,buf); + sqlite3_free(buf); + + /* Invalidate unread_count when we modify the database, so that next + time we need it it will be recomputed from latest database state */ + cr->unread_count = -1; } -void linphone_chat_room_delete_history(LinphoneChatRoom *cr) { - linphone_chat_room_get_cpp_obj(cr).deleteHistory(); +void linphone_chat_room_delete_history(LinphoneChatRoom *cr){ + LinphoneCore *lc=cr->lc; + char *peer; + char *buf; + + if (lc->db==NULL) return ; + + peer=linphone_address_as_string_uri_only(linphone_chat_room_get_peer_address(cr)); + buf=sqlite3_mprintf("DELETE FROM history WHERE remoteContact = %Q;",peer); + linphone_sql_request(lc->db,buf); + sqlite3_free(buf); + ms_free(peer); + + if(cr->unread_count > 0) cr->unread_count = 0; } -bctbx_list_t *linphone_chat_room_get_history_range(LinphoneChatRoom *cr, int startm, int endm) { - std::list l = linphone_chat_room_get_cpp_obj(cr).getHistoryRange(startm, endm); - bctbx_list_t *result = nullptr; - for (auto it = l.begin(); it != l.end(); it++) - result = bctbx_list_append(result, *it); - return result; +bctbx_list_t *linphone_chat_room_get_history_range(LinphoneChatRoom *cr, int startm, int endm){ + LinphoneCore *lc=linphone_chat_room_get_core(cr); + bctbx_list_t *ret; + char *buf,*buf2; + char *peer; + uint64_t begin,end; + int buf_max_size = 512; + + if (lc->db==NULL) return NULL; + peer = linphone_address_as_string_uri_only(linphone_chat_room_get_peer_address(cr)); + + cr->messages_hist = NULL; + + /*since we want to append query parameters depending on arguments given, we use malloc instead of sqlite3_mprintf*/ + buf=reinterpret_cast(ms_malloc(buf_max_size)); + buf=sqlite3_snprintf(buf_max_size-1,buf,"SELECT * FROM history WHERE remoteContact = %Q ORDER BY id DESC",peer); + + + if (startm<0) startm=0; + + if ((endm>0&&endm>=startm) || (startm == 0 && endm == 0) ){ + buf2=ms_strdup_printf("%s LIMIT %i ",buf,endm+1-startm); + ms_free(buf); + buf = buf2; + }else if(startm>0){ + ms_message("%s(): end is lower than start (%d < %d). Assuming no end limit.",__FUNCTION__,endm,startm); + buf2=ms_strdup_printf("%s LIMIT -1",buf); + ms_free(buf); + buf = buf2; + } + + if (startm>0){ + buf2=ms_strdup_printf("%s OFFSET %i ",buf,startm); + ms_free(buf); + buf = buf2; + } + + begin=ortp_get_cur_time_ms(); + linphone_sql_request_message(lc->db,buf,cr); + end=ortp_get_cur_time_ms(); + + if (endm+1-startm > 1) { + //display message only if at least 2 messages are loaded + ms_message("%s(): completed in %i ms",__FUNCTION__, (int)(end-begin)); + } + ms_free(buf); + + if (cr->messages_hist) { + //fill local addr with core identity instead of per message + LinphoneAddress* local_addr = linphone_address_new(linphone_core_get_identity(cr->lc)); + bctbx_list_t* it = cr->messages_hist; + while (it) { + LinphoneChatMessage* msg = reinterpret_cast(it->data); + if (msg->dir == LinphoneChatMessageOutgoing) { + if (msg->from != NULL) linphone_address_unref(msg->from); + msg->from = linphone_address_ref(local_addr); + } else { + msg->to = linphone_address_ref(local_addr); + } + it = it->next; + } + linphone_address_unref(local_addr); + } + + ret=cr->messages_hist; + cr->messages_hist=NULL; + ms_free(peer); + return ret; } -bctbx_list_t *linphone_chat_room_get_history(LinphoneChatRoom *cr, int nb_message) { - std::list l = linphone_chat_room_get_cpp_obj(cr).getHistory(nb_message); - bctbx_list_t *result = nullptr; - for (auto it = l.begin(); it != l.end(); it++) - result = bctbx_list_append(result, *it); - return result; +bctbx_list_t *linphone_chat_room_get_history(LinphoneChatRoom *cr,int nb_message){ + return linphone_chat_room_get_history_range(cr, 0, nb_message-1); +} + + +bctbx_list_t* linphone_chat_room_find_messages(LinphoneChatRoom *cr, const char *message_id) { + LinphoneCore *lc = linphone_chat_room_get_core(cr); + char *buf; + char *peer; + bctbx_list_t* messages; + + if (lc->db == NULL) return NULL; + peer = linphone_address_as_string_uri_only(linphone_chat_room_get_peer_address(cr)); + cr->messages_hist = NULL; + buf = sqlite3_mprintf("SELECT * FROM history WHERE remoteContact = %Q AND messageId = %Q", peer, message_id); + linphone_sql_request_message(lc->db, buf, cr); + sqlite3_free(buf); + ms_free(peer); + messages = cr->messages_hist; + cr->messages_hist = NULL; + return messages; +} + +LinphoneChatMessage * linphone_chat_room_find_message_with_dir(LinphoneChatRoom *cr, const char *message_id, LinphoneChatMessageDir dir) { + bctbx_list_t* messages = linphone_chat_room_find_messages(cr, message_id); + bctbx_list_t* it; + LinphoneChatMessage *ret = NULL; + for (it = messages; it != NULL; it = it->next) { + LinphoneChatMessage * cm = (LinphoneChatMessage*)it->data; + if (cm->dir == dir) { + linphone_chat_message_ref(cm); + ret = cm; + break; + } + } + if (messages) + bctbx_list_free_with_data(messages, (bctbx_list_free_func)linphone_chat_message_unref); + + return ret; + } LinphoneChatMessage * linphone_chat_room_find_message(LinphoneChatRoom *cr, const char *message_id) { - return linphone_chat_room_get_cpp_obj(cr).findMessage(message_id); + bctbx_list_t* messages = linphone_chat_room_find_messages(cr, message_id); + LinphoneChatMessage *cm = NULL; + if (messages) { + cm = (LinphoneChatMessage *)bctbx_list_nth_data(messages, 0); + linphone_chat_message_ref(cm); + bctbx_list_free_with_data(messages, (bctbx_list_free_func)linphone_chat_message_unref); + } + return cm; } static void linphone_create_history_table(sqlite3* db){ @@ -658,6 +975,9 @@ void linphone_core_message_storage_init(LinphoneCore *lc){ void linphone_core_message_storage_close(LinphoneCore *lc){ } +void linphone_chat_room_update_url(LinphoneChatRoom *cr, LinphoneChatMessage *msg) { +} + int linphone_chat_room_get_unread_messages_count(LinphoneChatRoom *cr){ return 0; } diff --git a/coreapi/presence.c b/coreapi/presence.c index 43c7a8ffd..a49550991 100644 --- a/coreapi/presence.c +++ b/coreapi/presence.c @@ -1933,11 +1933,8 @@ void linphone_notify_recv(LinphoneCore *lc, SalOp *op, SalSubscribeStatus ss, Sa if (linphone_core_get_default_friend_list(lc) != NULL) lf=linphone_core_find_friend_by_out_subscribe(lc, op); if (lf==NULL && lp_config_get_int(lc->config,"sip","allow_out_of_subscribe_presence",0)){ - char *buf = sal_address_as_string_uri_only(sal_op_get_from_address(op)); - LinphoneAddress *addr = linphone_address_new(buf); - lf = linphone_core_find_friend(lc, addr); - ms_free(buf); - linphone_address_unref(addr); + const SalAddress *addr=sal_op_get_from_address(op); + lf = linphone_core_find_friend(lc, (LinphoneAddress *)addr); } if (lf!=NULL){ LinphonePresenceActivity *activity = NULL; diff --git a/coreapi/private.h b/coreapi/private.h index 24f2b2649..8d4c02c1a 100644 --- a/coreapi/private.h +++ b/coreapi/private.h @@ -180,12 +180,6 @@ struct _LinphoneCallParams{ BELLE_SIP_DECLARE_VPTR_NO_EXPORT(LinphoneCallParams); -typedef enum _ImdnType { - ImdnTypeDelivery, - ImdnTypeDisplay -} ImdnType; - - struct _LinphoneQualityReporting{ reporting_session_report_t * reports[3]; /**Store information on audio and video media streams (RFC 6035) */ bool_t was_video_running; /*Keep video state since last check in order to detect its (de)activation*/ @@ -285,6 +279,11 @@ struct _LinphoneChatMessage { #endif }; +/* + *Gets a Message with a given message id and direction. + */ +LINPHONE_PUBLIC LinphoneChatMessage * linphone_chat_room_find_message_with_dir(LinphoneChatRoom *cr, const char *message_id,LinphoneChatMessageDir dir); + BELLE_SIP_DECLARE_VPTR_NO_EXPORT(LinphoneChatMessage); typedef struct StunCandidate{ @@ -595,7 +594,7 @@ LINPHONE_PUBLIC void linphone_core_get_local_ip(LinphoneCore *lc, int af, const LinphoneProxyConfig *linphone_proxy_config_new_from_config_file(LinphoneCore *lc, int index); void linphone_proxy_config_write_to_config_file(LinphoneConfig* config,LinphoneProxyConfig *obj, int index); -int linphone_core_message_received(LinphoneCore *lc, SalOp *op, const SalMessage *msg); +LinphoneReason linphone_core_message_received(LinphoneCore *lc, SalOp *op, const SalMessage *msg); void linphone_core_real_time_text_received(LinphoneCore *lc, LinphoneChatRoom *cr, uint32_t character, LinphoneCall *call); void linphone_call_init_stats(LinphoneCallStats *stats, LinphoneStreamType type); @@ -651,8 +650,7 @@ void _linphone_proxy_config_release_ops(LinphoneProxyConfig *obj); /*chat*/ void linphone_chat_room_release(LinphoneChatRoom *cr); -void linphone_chat_room_set_call(LinphoneChatRoom *cr, LinphoneCall *call); -bctbx_list_t * linphone_chat_room_get_transient_messages(const LinphoneChatRoom *cr); +void linphone_chat_room_add_weak_message(LinphoneChatRoom *cr, LinphoneChatMessage *cm); void linphone_chat_message_destroy(LinphoneChatMessage* msg); void linphone_chat_message_update_state(LinphoneChatMessage *msg, LinphoneChatMessageState new_state); void linphone_chat_message_set_state(LinphoneChatMessage *msg, LinphoneChatMessageState state); @@ -661,14 +659,11 @@ void linphone_chat_message_send_delivery_notification(LinphoneChatMessage *cm, L void linphone_chat_message_send_display_notification(LinphoneChatMessage *cm); void _linphone_chat_message_cancel_file_transfer(LinphoneChatMessage *msg, bool_t unref); int linphone_chat_room_upload_file(LinphoneChatMessage *msg); +void _linphone_chat_room_send_message(LinphoneChatRoom *cr, LinphoneChatMessage *msg); LinphoneChatMessageCbs *linphone_chat_message_cbs_new(void); LinphoneChatRoom *_linphone_core_create_chat_room_from_call(LinphoneCall *call); +void linphone_chat_room_add_transient_message(LinphoneChatRoom *cr, LinphoneChatMessage *msg); void linphone_chat_room_remove_transient_message(LinphoneChatRoom *cr, LinphoneChatMessage *msg); -void linphone_chat_message_deactivate(LinphoneChatMessage *msg); -void linphone_chat_message_release(LinphoneChatMessage *msg); -void create_file_transfer_information_from_vnd_gsma_rcs_ft_http_xml(LinphoneChatMessage *msg); -void linphone_chat_message_fetch_content_from_database(sqlite3 *db, LinphoneChatMessage *message, int content_id); -void linphone_chat_message_send_imdn(LinphoneChatMessage *cm, ImdnType imdn_type, LinphoneReason reason); /**/ struct _LinphoneProxyConfig @@ -721,10 +716,6 @@ struct _LinphoneProxyConfig char *refkey; char *sip_etag; /*publish context*/ - - // For migration purpose. (Do not use directly!) - // Cache. - LinphoneAddress *contact_address; }; BELLE_SIP_DECLARE_VPTR_NO_EXPORT(LinphoneProxyConfig); @@ -749,11 +740,33 @@ typedef enum _LinphoneIsComposingState { LinphoneIsComposingActive } LinphoneIsComposingState; +struct _LinphoneChatRoom{ + belle_sip_object_t base; + void *user_data; + struct _LinphoneCore *lc; + char *peer; + LinphoneAddress *peer_url; + MSList *messages_hist; + MSList *transient_messages; + bctbx_list_t *weak_messages; + int unread_count; + LinphoneIsComposingState remote_is_composing; + LinphoneIsComposingState is_composing; + belle_sip_source_t *remote_composing_refresh_timer; + belle_sip_source_t *composing_idle_timer; + belle_sip_source_t *composing_refresh_timer; + LinphoneCall *call; + LinphoneChatMessage *pending_message; + MSList *received_rtt_characters; +}; + typedef struct _LinphoneChatMessageCharacter { uint32_t value; bool_t has_been_read; } LinphoneChatMessageCharacter; +BELLE_SIP_DECLARE_VPTR_NO_EXPORT(LinphoneChatRoom); + typedef struct _LinphoneFriendPresence { char *uri_or_tel; @@ -1159,11 +1172,6 @@ struct _LinphoneEvent{ bool_t is_out_of_dialog_op; /*used for out of dialog notify*/ bool_t internal; bool_t oneshot; - - // For migration purpose. (Do not use directly!) - // Cache. - LinphoneAddress *to_address; - LinphoneAddress *from_address; }; BELLE_SIP_DECLARE_VPTR_NO_EXPORT(LinphoneEvent); @@ -1833,7 +1841,6 @@ BELLE_SIP_DECLARE_TYPES_BEGIN(linphone,10000) BELLE_SIP_TYPE_ID(LinphoneAccountCreator), BELLE_SIP_TYPE_ID(LinphoneAccountCreatorCbs), BELLE_SIP_TYPE_ID(LinphoneAccountCreatorService), -BELLE_SIP_TYPE_ID(LinphoneAddress), BELLE_SIP_TYPE_ID(LinphoneBuffer), BELLE_SIP_TYPE_ID(LinphoneContactProvider), BELLE_SIP_TYPE_ID(LinphoneContactSearch), diff --git a/coreapi/proxy.c b/coreapi/proxy.c index 43ddd184a..756ad7d76 100644 --- a/coreapi/proxy.c +++ b/coreapi/proxy.c @@ -18,20 +18,14 @@ Copyright (C) 2000 Simon MORLAT (simon.morlat@linphone.org) * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include - -#include "linphone/core_utils.h" #include "linphone/core.h" -#include "linphone/lpconfig.h" +#include "linphone/core_utils.h" #include "linphone/sipsetup.h" -#include "mediastreamer2/mediastream.h" - -#include "enum.h" +#include "linphone/lpconfig.h" #include "private.h" - -// For migration purpose. -#include "address/address-p.h" -#include "c-wrapper/c-tools.h" +#include "mediastreamer2/mediastream.h" +#include "enum.h" +#include /*store current config related to server location*/ static void linphone_proxy_config_store_server_config(LinphoneProxyConfig* cfg) { @@ -246,9 +240,6 @@ void _linphone_proxy_config_destroy(LinphoneProxyConfig *cfg){ if (cfg->ei){ linphone_error_info_unref(cfg->ei); } - - if (cfg->contact_address) linphone_address_unref(cfg->contact_address); - _linphone_proxy_config_release_ops(cfg); } @@ -413,33 +404,26 @@ void linphone_proxy_config_apply(LinphoneProxyConfig *cfg,LinphoneCore *lc){ } void linphone_proxy_config_stop_refreshing(LinphoneProxyConfig * cfg){ - LinphoneAddress *contact_addr = NULL; - { - const SalAddress *sal_addr = cfg->op && cfg->state == LinphoneRegistrationOk - ? sal_op_get_contact_address(cfg->op) - : NULL; - if (sal_addr) { - char *buf = sal_address_as_string(sal_addr); - contact_addr = buf ? linphone_address_new(buf) : NULL; - ms_free(buf); - } - } + LinphoneAddress *contact_addr=NULL; + if ( cfg->op + && cfg->state == LinphoneRegistrationOk + && (contact_addr = (LinphoneAddress*)sal_op_get_contact_address(cfg->op)) + && linphone_address_get_transport(contact_addr) != LinphoneTransportUdp /*with udp, there is a risk of port reuse, so I prefer to not do anything for now*/) { + /*need to save current contact in order to reset is later*/ + linphone_address_ref(contact_addr); + if (cfg->pending_contact) + linphone_address_unref(cfg->pending_contact); + cfg->pending_contact=contact_addr; - /*with udp, there is a risk of port reuse, so I prefer to not do anything for now*/ - if (contact_addr) { - if (linphone_address_get_transport(contact_addr) != LinphoneTransportUdp) { - if (cfg->pending_contact) - linphone_address_unref(cfg->pending_contact); - cfg->pending_contact=contact_addr; - } else - linphone_address_unref(contact_addr); } if (cfg->presence_publish_event){ /*might probably do better*/ - linphone_event_set_publish_state(cfg->presence_publish_event,LinphonePublishNone); - linphone_event_unref(cfg->presence_publish_event); /*probably useless as cfg->long_term_event is already unref in linphone_proxy_config_notify_publish_state_changed. To be check with Ghislain*/ - cfg->presence_publish_event=NULL; + linphone_event_terminate(cfg->presence_publish_event); + if (cfg->presence_publish_event) { + linphone_event_unref(cfg->presence_publish_event); /*probably useless as cfg->long_term_event is already unref in linphone_proxy_config_notify_publish_state_changed. To be check with Ghislain*/ + cfg->presence_publish_event=NULL; + } + } - if (cfg->op){ sal_op_release(cfg->op); cfg->op=NULL; @@ -462,10 +446,10 @@ LinphoneAddress *guess_contact_for_register(LinphoneProxyConfig *cfg){ if (cfg->contact_params) { // We want to add a list of contacts params to the linphone address - linphone_address_set_params(contact,cfg->contact_params); + sal_address_set_params(contact,cfg->contact_params); } if (cfg->contact_uri_params){ - linphone_address_set_uri_params(contact,cfg->contact_uri_params); + sal_address_set_uri_params(contact,cfg->contact_uri_params); } #ifdef BUILD_UPNP if (cfg->lc->upnp != NULL && linphone_core_get_firewall_policy(cfg->lc)==LinphonePolicyUseUpnp && @@ -507,19 +491,14 @@ static void linphone_proxy_config_register(LinphoneProxyConfig *cfg){ linphone_configure_op(cfg->lc, cfg->op, cfg->identity_address, cfg->sent_headers, FALSE); if ((contact=guess_contact_for_register(cfg))) { - sal_op_set_contact_address(cfg->op, L_GET_PRIVATE_FROM_C_STRUCT(contact, Address)->getInternalAddress()); + sal_op_set_contact_address(cfg->op,contact); linphone_address_unref(contact); } sal_op_set_user_pointer(cfg->op,cfg); - if (sal_register( - cfg->op, - proxy_string, - cfg->reg_identity, - cfg->expires, - cfg->pending_contact ? L_GET_PRIVATE_FROM_C_STRUCT(cfg->pending_contact, Address)->getInternalAddress() : NULL - )==0) { + + if (sal_register(cfg->op,proxy_string, cfg->reg_identity, cfg->expires, cfg->pending_contact)==0) { if (cfg->pending_contact) { linphone_address_unref(cfg->pending_contact); cfg->pending_contact=NULL; @@ -900,7 +879,7 @@ int linphone_proxy_config_send_publish(LinphoneProxyConfig *proxy, LinphonePrese } linphone_presence_model_set_presentity(presence,linphone_proxy_config_get_identity_address(proxy)); linphone_presence_model_set_contact(presence,NULL); /*it will be automatically computed*/ - + } if (!(presence_body = linphone_presence_model_to_xml(presence))) { ms_error("Cannot publish presence model [%p] for proxy config [%p] because of xml serialization error",presence,proxy); @@ -927,7 +906,7 @@ int linphone_proxy_config_send_publish(LinphoneProxyConfig *proxy, LinphonePrese linphone_presence_model_set_contact(presence,contact); bctbx_free(contact); } - + }else proxy->send_publish=TRUE; /*otherwise do not send publish if registration is in progress, this will be done later*/ return err; } @@ -1404,11 +1383,9 @@ const LinphoneAddress* linphone_proxy_config_get_service_route(const LinphonePro const char* linphone_proxy_config_get_transport(const LinphoneProxyConfig *cfg) { const char* addr=NULL; const char* ret="udp"; /*default value*/ - const SalAddress* route_addr=NULL; - bool_t destroy_route_addr = FALSE; - + SalAddress* route_addr=NULL; if (linphone_proxy_config_get_service_route(cfg)) { - route_addr = L_GET_PRIVATE_FROM_C_STRUCT(linphone_proxy_config_get_service_route(cfg), Address)->getInternalAddress(); + route_addr=(SalAddress*)linphone_proxy_config_get_service_route(cfg); } else if (linphone_proxy_config_get_route(cfg)) { addr=linphone_proxy_config_get_route(cfg); } else if(linphone_proxy_config_get_addr(cfg)) { @@ -1418,16 +1395,13 @@ const char* linphone_proxy_config_get_transport(const LinphoneProxyConfig *cfg) return NULL; } - if (!route_addr) { - if (!((*(SalAddress **)&route_addr) = sal_address_new(addr))) - return NULL; - destroy_route_addr = TRUE; + if (route_addr || (route_addr=sal_address_new(addr))) { + ret=sal_transport_to_string(sal_address_get_transport(route_addr)); + if (!linphone_proxy_config_get_service_route(cfg)) { + sal_address_destroy(route_addr); + } } - ret=sal_transport_to_string(sal_address_get_transport(route_addr)); - if (destroy_route_addr) - sal_address_destroy((SalAddress *)route_addr); - return ret; } void linphone_proxy_config_set_privacy(LinphoneProxyConfig *params, LinphonePrivacyMask privacy) { @@ -1476,15 +1450,7 @@ uint8_t linphone_proxy_config_get_avpf_rr_interval(const LinphoneProxyConfig *cf } const LinphoneAddress* linphone_proxy_config_get_contact(const LinphoneProxyConfig *cfg) { - // Workaround for wrapping. - if (cfg->contact_address) - linphone_address_unref(cfg->contact_address); - - char *buf = sal_address_as_string(sal_op_get_contact_address(cfg->op)); - const_cast(cfg)->contact_address = linphone_address_new(buf); - ms_free(buf); - - return cfg->contact_address; + return sal_op_get_contact_address(cfg->op); } const struct _LinphoneAuthInfo* linphone_proxy_config_find_auth_info(const LinphoneProxyConfig *cfg) { diff --git a/coreapi/quality_reporting.c b/coreapi/quality_reporting.c index bee5dc6dc..9e8302dda 100644 --- a/coreapi/quality_reporting.c +++ b/coreapi/quality_reporting.c @@ -32,10 +32,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include #endif -// For migration purpose. -#include "address/address-p.h" -#include "c-wrapper/c-tools.h" - #define STR_REASSIGN(dest, src) {\ if (dest != NULL) \ ms_free(dest); \ @@ -276,7 +272,6 @@ static int send_report(LinphoneCall* call, reporting_session_report_t * report, LinphoneAddress *request_uri; const char* collector_uri; char *collector_uri_allocated = NULL; - const SalAddress *salAddress; /*if we are on a low bandwidth network, do not send reports to not overload it*/ if (linphone_call_params_low_bandwidth_enabled(linphone_call_get_current_params(call))){ @@ -367,9 +362,8 @@ static int send_report(LinphoneCall* call, reporting_session_report_t * report, * (port, transport, maddr), then it is sent directly. * Otherwise it is routed as any LinphoneEvent publish, following proxy config policy. **/ - salAddress = L_GET_PRIVATE_FROM_C_STRUCT(request_uri, Address)->getInternalAddress(); - if (sal_address_has_uri_param(salAddress, "transport") || - sal_address_has_uri_param(salAddress, "maddr") || + if (sal_address_has_uri_param((SalAddress*)request_uri, "transport") || + sal_address_has_uri_param((SalAddress*)request_uri, "maddr") || linphone_address_get_port(request_uri) != 0) { ms_message("Publishing report with custom route %s", collector_uri); sal_op_set_route(lev->op, collector_uri); diff --git a/coreapi/sal/sal.c b/coreapi/sal/sal.c deleted file mode 100644 index 3870e59e3..000000000 --- a/coreapi/sal/sal.c +++ /dev/null @@ -1,942 +0,0 @@ -/* -linphone -Copyright (C) 2010 Simon MORLAT (simon.morlat@free.fr) - -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 file contains SAL API functions that do not depend on the underlying implementation (like belle-sip). -**/ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif -#include "sal/sal.h" - - -#include - - -const char *sal_multicast_role_to_string(SalMulticastRole role){ - switch(role){ - case SalMulticastInactive: - return "inactive"; - case SalMulticastReceiver: - return "receiver"; - case SalMulticastSender: - return "sender"; - case SalMulticastSenderReceiver: - return "sender-receiver"; - } - return "INVALID"; -} - -const char* sal_transport_to_string(SalTransport transport) { - switch (transport) { - case SalTransportUDP:return "udp"; - case SalTransportTCP: return "tcp"; - case SalTransportTLS:return "tls"; - case SalTransportDTLS:return "dtls"; - default: { - ms_fatal("Unexpected transport [%i]",transport); - return NULL; - } - } -} - -SalTransport sal_transport_parse(const char* param) { - if (!param) return SalTransportUDP; - if (strcasecmp("udp",param)==0) return SalTransportUDP; - if (strcasecmp("tcp",param)==0) return SalTransportTCP; - if (strcasecmp("tls",param)==0) return SalTransportTLS; - if (strcasecmp("dtls",param)==0) return SalTransportDTLS; - ms_error("Unknown transport type[%s], returning UDP", param); - return SalTransportUDP; -} - -SalMediaDescription *sal_media_description_new(){ - SalMediaDescription *md=ms_new0(SalMediaDescription,1); - int i; - md->refcount=1; - for(i = 0; i < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; i++) { - md->streams[i].dir=SalStreamInactive; - md->streams[i].rtp_port = 0; - md->streams[i].rtcp_port = 0; - md->streams[i].haveZrtpHash = 0; - } - return md; -} - -static void sal_media_description_destroy(SalMediaDescription *md){ - int i; - for(i=0;istreams[i].payloads,(void (*)(void *))payload_type_destroy); - bctbx_list_free_with_data(md->streams[i].already_assigned_payloads,(void (*)(void *))payload_type_destroy); - md->streams[i].payloads=NULL; - md->streams[i].already_assigned_payloads=NULL; - sal_custom_sdp_attribute_free(md->streams[i].custom_sdp_attributes); - } - sal_custom_sdp_attribute_free(md->custom_sdp_attributes); - ms_free(md); -} - -SalMediaDescription * sal_media_description_ref(SalMediaDescription *md){ - md->refcount++; - return md; -} - -void sal_media_description_unref(SalMediaDescription *md){ - md->refcount--; - if (md->refcount==0){ - sal_media_description_destroy (md); - } -} - -SalStreamDescription *sal_media_description_find_stream(SalMediaDescription *md, SalMediaProto proto, SalStreamType type){ - int i; - for(i=0;istreams[i]; - if (!sal_stream_description_active(ss)) continue; - if (ss->proto==proto && ss->type==type) return ss; - } - return NULL; -} - -unsigned int sal_media_description_nb_active_streams_of_type(SalMediaDescription *md, SalStreamType type) { - unsigned int i; - unsigned int nb = 0; - for (i = 0; i < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; ++i) { - if (!sal_stream_description_active(&md->streams[i])) continue; - if (md->streams[i].type == type) nb++; - } - return nb; -} - -SalStreamDescription * sal_media_description_get_active_stream_of_type(SalMediaDescription *md, SalStreamType type, unsigned int idx) { - unsigned int i; - for (i = 0; i < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; ++i) { - if (!sal_stream_description_active(&md->streams[i])) continue; - if (md->streams[i].type == type) { - if (idx-- == 0) return &md->streams[i]; - } - } - return NULL; -} - -SalStreamDescription * sal_media_description_find_secure_stream_of_type(SalMediaDescription *md, SalStreamType type) { - SalStreamDescription *desc = sal_media_description_find_stream(md, SalProtoRtpSavpf, type); - if (desc == NULL) desc = sal_media_description_find_stream(md, SalProtoRtpSavp, type); - return desc; -} - -SalStreamDescription * sal_media_description_find_best_stream(SalMediaDescription *md, SalStreamType type) { - SalStreamDescription *desc = sal_media_description_find_stream(md, SalProtoUdpTlsRtpSavpf, type); - if (desc == NULL) desc = sal_media_description_find_stream(md, SalProtoUdpTlsRtpSavp, type); - if (desc == NULL) desc = sal_media_description_find_stream(md, SalProtoRtpSavpf, type); - if (desc == NULL) desc = sal_media_description_find_stream(md, SalProtoRtpSavp, type); - if (desc == NULL) desc = sal_media_description_find_stream(md, SalProtoRtpAvpf, type); - if (desc == NULL) desc = sal_media_description_find_stream(md, SalProtoRtpAvp, type); - return desc; -} - -bool_t sal_media_description_empty(const SalMediaDescription *md){ - if (sal_media_description_get_nb_active_streams(md) > 0) return FALSE; - return TRUE; -} - -void sal_media_description_set_dir(SalMediaDescription *md, SalStreamDir stream_dir){ - int i; - for(i=0;istreams[i]; - if (!sal_stream_description_active(ss)) continue; - ss->dir=stream_dir; - } -} - -int sal_media_description_get_nb_active_streams(const SalMediaDescription *md) { - int i; - int nb = 0; - for (i = 0; i < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; i++) { - if (sal_stream_description_active(&md->streams[i])) nb++; - } - return nb; -} - -static bool_t is_null_address(const char *addr){ - return strcmp(addr,"0.0.0.0")==0 || strcmp(addr,"::0")==0; -} - -/*check for the presence of at least one stream with requested direction */ -static bool_t has_dir(const SalMediaDescription *md, SalStreamDir stream_dir){ - int i; - - /* we are looking for at least one stream with requested direction, inactive streams are ignored*/ - for(i=0;istreams[i]; - if (!sal_stream_description_active(ss)) continue; - if (ss->dir==stream_dir) { - return TRUE; - } - /*compatibility check for phones that only used the null address and no attributes */ - if (ss->dir==SalStreamSendRecv && stream_dir==SalStreamSendOnly && (is_null_address(md->addr) || is_null_address(ss->rtp_addr))){ - return TRUE; - } - } - return FALSE; -} - -bool_t sal_media_description_has_dir(const SalMediaDescription *md, SalStreamDir stream_dir){ - if (stream_dir==SalStreamRecvOnly){ - return has_dir(md, SalStreamRecvOnly) && !(has_dir(md,SalStreamSendOnly) || has_dir(md,SalStreamSendRecv)); - }else if (stream_dir==SalStreamSendOnly){ - return has_dir(md, SalStreamSendOnly) && !(has_dir(md,SalStreamRecvOnly) || has_dir(md,SalStreamSendRecv)); - }else if (stream_dir==SalStreamSendRecv){ - return has_dir(md,SalStreamSendRecv); - }else{ - /*SalStreamInactive*/ - if (has_dir(md,SalStreamSendOnly) || has_dir(md,SalStreamSendRecv) || has_dir(md,SalStreamRecvOnly)) - return FALSE; - else return TRUE; - } - return FALSE; -} - -bool_t sal_stream_description_active(const SalStreamDescription *sd) { - return (sd->rtp_port > 0); -} - -/*these are switch case, so that when a new proto is added we can't forget to modify this function*/ -bool_t sal_stream_description_has_avpf(const SalStreamDescription *sd) { - switch (sd->proto){ - case SalProtoRtpAvpf: - case SalProtoRtpSavpf: - case SalProtoUdpTlsRtpSavpf: - return TRUE; - case SalProtoRtpAvp: - case SalProtoRtpSavp: - case SalProtoUdpTlsRtpSavp: - case SalProtoOther: - return FALSE; - } - return FALSE; -} - -bool_t sal_stream_description_has_ipv6(const SalStreamDescription *sd){ - return strchr(sd->rtp_addr,':') != NULL; -} - -bool_t sal_stream_description_has_implicit_avpf(const SalStreamDescription *sd){ - return sd->implicit_rtcp_fb; -} -/*these are switch case, so that when a new proto is added we can't forget to modify this function*/ -bool_t sal_stream_description_has_srtp(const SalStreamDescription *sd) { - switch (sd->proto){ - case SalProtoRtpSavp: - case SalProtoRtpSavpf: - return TRUE; - case SalProtoRtpAvp: - case SalProtoRtpAvpf: - case SalProtoUdpTlsRtpSavpf: - case SalProtoUdpTlsRtpSavp: - case SalProtoOther: - return FALSE; - } - return FALSE; -} - -bool_t sal_stream_description_has_dtls(const SalStreamDescription *sd) { - switch (sd->proto){ - case SalProtoUdpTlsRtpSavpf: - case SalProtoUdpTlsRtpSavp: - return TRUE; - case SalProtoRtpSavp: - case SalProtoRtpSavpf: - case SalProtoRtpAvp: - case SalProtoRtpAvpf: - case SalProtoOther: - return FALSE; - } - return FALSE; -} - -bool_t sal_stream_description_has_zrtp(const SalStreamDescription *sd) { - if (sd->haveZrtpHash==1) return TRUE; - return FALSE; -} - -bool_t sal_media_description_has_avpf(const SalMediaDescription *md) { - int i; - if (md->nb_streams == 0) return FALSE; - for (i = 0; i < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; i++) { - if (!sal_stream_description_active(&md->streams[i])) continue; - if (sal_stream_description_has_avpf(&md->streams[i]) != TRUE) return FALSE; - } - return TRUE; -} - -bool_t sal_media_description_has_implicit_avpf(const SalMediaDescription *md) { - int i; - if (md->nb_streams == 0) return FALSE; - for (i = 0; i < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; i++) { - if (!sal_stream_description_active(&md->streams[i])) continue; - if (sal_stream_description_has_implicit_avpf(&md->streams[i]) != TRUE) return FALSE; - } - return TRUE; -} - -bool_t sal_media_description_has_srtp(const SalMediaDescription *md) { - int i; - if (md->nb_streams == 0) return FALSE; - for (i = 0; i < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; i++) { - if (!sal_stream_description_active(&md->streams[i])) continue; - if (sal_stream_description_has_srtp(&md->streams[i]) != TRUE) return FALSE; - } - return TRUE; -} - -bool_t sal_media_description_has_dtls(const SalMediaDescription *md) { - int i; - if (md->nb_streams == 0) return FALSE; - for (i = 0; i < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; i++) { - if (!sal_stream_description_active(&md->streams[i])) continue; - if (sal_stream_description_has_dtls(&md->streams[i]) != TRUE) return FALSE; - } - return TRUE; -} - -bool_t sal_media_description_has_zrtp(const SalMediaDescription *md) { - int i; - if (md->nb_streams == 0) return FALSE; - for (i = 0; i < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; i++) { - if (!sal_stream_description_active(&md->streams[i])) continue; - if (sal_stream_description_has_zrtp(&md->streams[i]) != TRUE) return FALSE; - } - return TRUE; -} - -bool_t sal_media_description_has_ipv6(const SalMediaDescription *md){ - int i; - if (md->nb_streams == 0) return FALSE; - for (i = 0; i < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; i++) { - if (!sal_stream_description_active(&md->streams[i])) continue; - if (md->streams[i].rtp_addr[0] != '\0'){ - if (!sal_stream_description_has_ipv6(&md->streams[i])) return FALSE; - }else{ - if (strchr(md->addr,':') == NULL) return FALSE; - } - } - return TRUE; -} - -/* -static bool_t fmtp_equals(const char *p1, const char *p2){ - if (p1 && p2 && strcmp(p1,p2)==0) return TRUE; - if (p1==NULL && p2==NULL) return TRUE; - return FALSE; -} -*/ - -static bool_t payload_type_equals(const PayloadType *p1, const PayloadType *p2){ - if (p1->type!=p2->type) return FALSE; - if (strcmp(p1->mime_type,p2->mime_type)!=0) return FALSE; - if (p1->clock_rate!=p2->clock_rate) return FALSE; - if (p1->channels!=p2->channels) return FALSE; - if (payload_type_get_number(p1) != payload_type_get_number(p2)) return FALSE; - /* - Do not compare fmtp right now: they are modified internally when the call is started - */ - /* - if (!fmtp_equals(p1->recv_fmtp,p2->recv_fmtp) || - !fmtp_equals(p1->send_fmtp,p2->send_fmtp)) - return FALSE; - */ - return TRUE; -} - -static bool_t is_recv_only(PayloadType *p){ - return (p->flags & PAYLOAD_TYPE_FLAG_CAN_RECV) && ! (p->flags & PAYLOAD_TYPE_FLAG_CAN_SEND); -} - -static bool_t payload_list_equals(const bctbx_list_t *l1, const bctbx_list_t *l2){ - const bctbx_list_t *e1,*e2; - for(e1=l1,e2=l2;e1!=NULL && e2!=NULL; e1=e1->next,e2=e2->next){ - PayloadType *p1=(PayloadType*)e1->data; - PayloadType *p2=(PayloadType*)e2->data; - if (!payload_type_equals(p1,p2)) - return FALSE; - } - if (e1!=NULL){ - /*skip possible recv-only payloads*/ - for(;e1!=NULL && is_recv_only((PayloadType*)e1->data);e1=e1->next){ - ms_message("Skipping recv-only payload type..."); - } - } - if (e1!=NULL || e2!=NULL){ - /*means one list is longer than the other*/ - return FALSE; - } - return TRUE; -} - -int sal_stream_description_equals(const SalStreamDescription *sd1, const SalStreamDescription *sd2) { - int result = SAL_MEDIA_DESCRIPTION_UNCHANGED; - int i; - - /* A different proto should result in SAL_MEDIA_DESCRIPTION_NETWORK_CHANGED but the encryption change - needs a stream restart for now, so use SAL_MEDIA_DESCRIPTION_CODEC_CHANGED */ - if (sd1->proto != sd2->proto) result |= SAL_MEDIA_DESCRIPTION_CODEC_CHANGED; - for (i = 0; i < SAL_CRYPTO_ALGO_MAX; i++) { - if ((sd1->crypto[i].tag != sd2->crypto[i].tag) - || (sd1->crypto[i].algo != sd2->crypto[i].algo)){ - result|=SAL_MEDIA_DESCRIPTION_CRYPTO_POLICY_CHANGED; - } - if ((strncmp(sd1->crypto[i].master_key, sd2->crypto[i].master_key, sizeof(sd1->crypto[i].master_key) - 1))) { - result |= SAL_MEDIA_DESCRIPTION_CRYPTO_KEYS_CHANGED; - } - } - - if (sd1->type != sd2->type) result |= SAL_MEDIA_DESCRIPTION_CODEC_CHANGED; - if (strcmp(sd1->rtp_addr, sd2->rtp_addr) != 0) result |= SAL_MEDIA_DESCRIPTION_NETWORK_CHANGED; - if (sd1->rtp_addr[0]!='\0' && sd2->rtp_addr[0]!='\0' && ms_is_multicast(sd1->rtp_addr) != ms_is_multicast(sd2->rtp_addr)) - result |= SAL_MEDIA_DESCRIPTION_NETWORK_XXXCAST_CHANGED; - if (sd1->rtp_port != sd2->rtp_port) { - if ((sd1->rtp_port == 0) || (sd2->rtp_port == 0)) result |= SAL_MEDIA_DESCRIPTION_CODEC_CHANGED; - else result |= SAL_MEDIA_DESCRIPTION_NETWORK_CHANGED; - } - if (strcmp(sd1->rtcp_addr, sd2->rtcp_addr) != 0) result |= SAL_MEDIA_DESCRIPTION_NETWORK_CHANGED; - if (sd1->rtcp_port != sd2->rtcp_port) result |= SAL_MEDIA_DESCRIPTION_NETWORK_CHANGED; - if (!payload_list_equals(sd1->payloads, sd2->payloads)) result |= SAL_MEDIA_DESCRIPTION_CODEC_CHANGED; - if (sd1->bandwidth != sd2->bandwidth) result |= SAL_MEDIA_DESCRIPTION_CODEC_CHANGED; - if (sd1->ptime != sd2->ptime) result |= SAL_MEDIA_DESCRIPTION_CODEC_CHANGED; - if (sd1->dir != sd2->dir) result |= SAL_MEDIA_DESCRIPTION_CODEC_CHANGED; - - /* ICE */ - if (strcmp(sd1->ice_ufrag, sd2->ice_ufrag) != 0) result |= SAL_MEDIA_DESCRIPTION_ICE_RESTART_DETECTED; - if (strcmp(sd1->ice_pwd, sd2->ice_pwd) != 0) result |= SAL_MEDIA_DESCRIPTION_ICE_RESTART_DETECTED; - - /*DTLS*/ - if (sd1->dtls_role != sd2->dtls_role) result |= SAL_MEDIA_DESCRIPTION_CRYPTO_KEYS_CHANGED; - if (strcmp(sd1->dtls_fingerprint, sd2->dtls_fingerprint) != 0) result |= SAL_MEDIA_DESCRIPTION_CRYPTO_KEYS_CHANGED; - - return result; -} - -char * sal_media_description_print_differences(int result){ - char *out = NULL; - if (result & SAL_MEDIA_DESCRIPTION_CODEC_CHANGED){ - out = ms_strcat_printf(out, "%s ", "CODEC_CHANGED"); - result &= ~SAL_MEDIA_DESCRIPTION_CODEC_CHANGED; - } - if (result & SAL_MEDIA_DESCRIPTION_NETWORK_CHANGED){ - out = ms_strcat_printf(out, "%s ", "NETWORK_CHANGED"); - result &= ~SAL_MEDIA_DESCRIPTION_NETWORK_CHANGED; - } - if (result & SAL_MEDIA_DESCRIPTION_ICE_RESTART_DETECTED){ - out = ms_strcat_printf(out, "%s ", "ICE_RESTART_DETECTED"); - result &= ~SAL_MEDIA_DESCRIPTION_ICE_RESTART_DETECTED; - } - if (result & SAL_MEDIA_DESCRIPTION_CRYPTO_KEYS_CHANGED){ - out = ms_strcat_printf(out, "%s ", "CRYPTO_KEYS_CHANGED"); - result &= ~SAL_MEDIA_DESCRIPTION_CRYPTO_KEYS_CHANGED; - } - if (result & SAL_MEDIA_DESCRIPTION_NETWORK_XXXCAST_CHANGED){ - out = ms_strcat_printf(out, "%s ", "NETWORK_XXXCAST_CHANGED"); - result &= ~SAL_MEDIA_DESCRIPTION_NETWORK_XXXCAST_CHANGED; - } - if (result & SAL_MEDIA_DESCRIPTION_STREAMS_CHANGED){ - out = ms_strcat_printf(out, "%s ", "STREAMS_CHANGED"); - result &= ~SAL_MEDIA_DESCRIPTION_STREAMS_CHANGED; - } - if (result & SAL_MEDIA_DESCRIPTION_CRYPTO_POLICY_CHANGED){ - out = ms_strcat_printf(out, "%s ", "CRYPTO_POLICY_CHANGED"); - result &= ~SAL_MEDIA_DESCRIPTION_CRYPTO_POLICY_CHANGED; - } - if (result & SAL_MEDIA_DESCRIPTION_FORCE_STREAM_RECONSTRUCTION){ - out = ms_strcat_printf(out, "%s ", "FORCE_STREAM_RECONSTRUCTION"); - result &= ~SAL_MEDIA_DESCRIPTION_FORCE_STREAM_RECONSTRUCTION; - } - if (result){ - ms_fatal("There are unhandled result bitmasks in sal_media_description_print_differences(), fix it"); - } - if (!out) out = ms_strdup("NONE"); - return out; -} - -int sal_media_description_equals(const SalMediaDescription *md1, const SalMediaDescription *md2) { - int result = SAL_MEDIA_DESCRIPTION_UNCHANGED; - int i; - - if (strcmp(md1->addr, md2->addr) != 0) result |= SAL_MEDIA_DESCRIPTION_NETWORK_CHANGED; - if (md1->addr[0]!='\0' && md2->addr[0]!='\0' && ms_is_multicast(md1->addr) != ms_is_multicast(md2->addr)) - result |= SAL_MEDIA_DESCRIPTION_NETWORK_XXXCAST_CHANGED; - if (md1->nb_streams != md2->nb_streams) result |= SAL_MEDIA_DESCRIPTION_STREAMS_CHANGED; - if (md1->bandwidth != md2->bandwidth) result |= SAL_MEDIA_DESCRIPTION_CODEC_CHANGED; - - /* ICE */ - if (strcmp(md1->ice_ufrag, md2->ice_ufrag) != 0) result |= SAL_MEDIA_DESCRIPTION_ICE_RESTART_DETECTED; - if (strcmp(md1->ice_pwd, md2->ice_pwd) != 0) result |= SAL_MEDIA_DESCRIPTION_ICE_RESTART_DETECTED; - - for(i = 0; i < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; ++i){ - if (!sal_stream_description_active(&md1->streams[i]) && !sal_stream_description_active(&md2->streams[i])) continue; - result |= sal_stream_description_equals(&md1->streams[i], &md2->streams[i]); - } - return result; -} - -static void assign_address(SalAddress** address, const char *value){ - if (*address){ - sal_address_destroy(*address); - *address=NULL; - } - if (value) - *address=sal_address_new(value); -} - -static void assign_string(char **str, const char *arg){ - if (*str){ - ms_free(*str); - *str=NULL; - } - if (arg) - *str=ms_strdup(arg); -} - -void sal_op_set_contact_address(SalOp *op, const SalAddress *address){ - if (((SalOpBase*)op)->contact_address) sal_address_destroy(((SalOpBase*)op)->contact_address); - ((SalOpBase*)op)->contact_address=address?sal_address_clone(address):NULL; -} - -void sal_op_set_and_clean_contact_address(SalOp *op, SalAddress *contact) { - if (contact){ - SalTransport tport = sal_address_get_transport((SalAddress*)contact); - const char* gruu = bctbx_strdup(sal_address_get_uri_param(contact, "gr")); - sal_address_clean((SalAddress*)contact); /* clean out contact_params that come from proxy config*/ - sal_address_set_transport((SalAddress*)contact,tport); - if(gruu) - sal_address_set_uri_param(contact, "gr", gruu); - sal_op_set_contact_address(op, contact); - sal_address_unref(contact); - } -} - -const SalAddress* sal_op_get_contact_address(const SalOp *op) { - return ((SalOpBase*)op)->contact_address; -} - -const SalAddress*sal_op_get_remote_contact_address(const SalOp* op) -{ - return ((SalOpBase*)op)->remote_contact_address; -} - -#define SET_PARAM(op,name) \ - char* name##_string=NULL; \ - assign_address(&((SalOpBase*)op)->name##_address,name); \ - if (((SalOpBase*)op)->name##_address) { \ - name##_string=sal_address_as_string(((SalOpBase*)op)->name##_address); \ - }\ - assign_string(&((SalOpBase*)op)->name,name##_string); \ - if(name##_string) ms_free(name##_string); - - -void sal_op_set_route(SalOp *op, const char *route){ - char* route_string=NULL; - SalOpBase* op_base = (SalOpBase*)op; - if (op_base->route_addresses) { - bctbx_list_for_each(op_base->route_addresses,(void (*)(void *))sal_address_destroy); - op_base->route_addresses=bctbx_list_free(op_base->route_addresses); - } - if (route) { - op_base->route_addresses=bctbx_list_append(NULL,NULL); - assign_address((SalAddress**)&(op_base->route_addresses->data),route); - route_string=sal_address_as_string((SalAddress*)op_base->route_addresses->data); \ - } - assign_string(&op_base->route,route_string); \ - if(route_string) ms_free(route_string); -} -const bctbx_list_t* sal_op_get_route_addresses(const SalOp *op) { - return ((SalOpBase*)op)->route_addresses; -} -void sal_op_set_route_address(SalOp *op, const SalAddress *address){ - char* address_string=sal_address_as_string(address); /*can probably be optimized*/ - sal_op_set_route(op,address_string); - ms_free(address_string); -} -void sal_op_add_route_address(SalOp *op, const SalAddress *address){ - SalOpBase* op_base = (SalOpBase*)op; - if (op_base->route_addresses) { - op_base->route_addresses=bctbx_list_append(op_base->route_addresses,(void*)sal_address_clone(address)); - } else { - sal_op_set_route_address(op,address); - } -} -void sal_op_set_realm(SalOp *op, const char *realm){ - SalOpBase* op_base = (SalOpBase*)op; - if (op_base->realm != NULL){ - ms_free(op_base->realm); - } - op_base->realm = ms_strdup(realm); -} -void sal_op_set_from(SalOp *op, const char *from){ - SET_PARAM(op,from); -} -void sal_op_set_from_address(SalOp *op, const SalAddress *from){ - char* address_string=sal_address_as_string(from); /*can probably be optimized*/ - sal_op_set_from(op,address_string); - ms_free(address_string); -} -void sal_op_set_to(SalOp *op, const char *to){ - SET_PARAM(op,to); -} -void sal_op_set_to_address(SalOp *op, const SalAddress *to){ - char* address_string=sal_address_as_string(to); /*can probably be optimized*/ - sal_op_set_to(op,address_string); - ms_free(address_string); -} -void sal_op_set_diversion_address(SalOp *op, const SalAddress *diversion){ - if (((SalOpBase*)op)->diversion_address) sal_address_destroy(((SalOpBase*)op)->diversion_address); - ((SalOpBase*)op)->diversion_address=diversion?sal_address_clone(diversion):NULL; -} -void sal_op_set_user_pointer(SalOp *op, void *up){ - ((SalOpBase*)op)->user_pointer=up; -} - -Sal *sal_op_get_sal(const SalOp *op){ - return ((SalOpBase*)op)->root; -} - -const char *sal_op_get_from(const SalOp *op){ - return ((SalOpBase*)op)->from; -} -const SalAddress *sal_op_get_from_address(const SalOp *op){ - return ((SalOpBase*)op)->from_address; -} - -const char *sal_op_get_to(const SalOp *op){ - return ((SalOpBase*)op)->to; -} - -const SalAddress *sal_op_get_to_address(const SalOp *op){ - return ((SalOpBase*)op)->to_address; -} - -const SalAddress *sal_op_get_diversion_address(const SalOp *op){ - return ((SalOpBase*)op)->diversion_address; -} - -const char *sal_op_get_remote_ua(const SalOp *op){ - return ((SalOpBase*)op)->remote_ua; -} - -void *sal_op_get_user_pointer(const SalOp *op){ - return ((SalOpBase*)op)->user_pointer; -} - -const char *sal_op_get_proxy(const SalOp *op){ - return ((SalOpBase*)op)->route; -} - -const char *sal_op_get_network_origin(const SalOp *op){ - return ((SalOpBase*)op)->origin; -} -const char* sal_op_get_call_id(const SalOp *op) { - return ((SalOpBase*)op)->call_id; -} - -void __sal_op_init(SalOp *b, Sal *sal){ - memset(b,0,sizeof(SalOpBase)); - ((SalOpBase*)b)->root=sal; -} - -void __sal_op_set_network_origin(SalOp *op, const char *origin){ - SET_PARAM(op,origin); -} - -void __sal_op_set_remote_contact(SalOp *op, const char* remote_contact){ - assign_address(&((SalOpBase*)op)->remote_contact_address,remote_contact);\ - /*to preserve header params*/ - assign_string(&((SalOpBase*)op)->remote_contact,remote_contact); \ -} - -void __sal_op_set_network_origin_address(SalOp *op, SalAddress *origin){ - char* address_string=sal_address_as_string(origin); /*can probably be optimized*/ - __sal_op_set_network_origin(op,address_string); - ms_free(address_string); -} - -void __sal_op_free(SalOp *op){ - SalOpBase *b=(SalOpBase *)op; - if (b->from_address){ - sal_address_destroy(b->from_address); - b->from_address=NULL; - } - if (b->to_address){ - sal_address_destroy(b->to_address); - b->to_address=NULL; - } - - if (b->service_route){ - sal_address_destroy(b->service_route); - b->service_route=NULL; - } - - if (b->origin_address){ - sal_address_destroy(b->origin_address); - b->origin_address=NULL; - } - - if (b->from) { - ms_free(b->from); - b->from=NULL; - } - if (b->to) { - ms_free(b->to); - b->to=NULL; - } - if (b->route) { - ms_free(b->route); - b->route=NULL; - } - if (b->realm) { - ms_free(b->realm); - b->realm=NULL; - } - if (b->contact_address) { - sal_address_destroy(b->contact_address); - } - if (b->origin){ - ms_free(b->origin); - b->origin=NULL; - } - if (b->remote_ua){ - ms_free(b->remote_ua); - b->remote_ua=NULL; - } - if (b->remote_contact){ - ms_free(b->remote_contact); - b->remote_contact=NULL; - } - if (b->remote_contact_address){ - sal_address_destroy(b->remote_contact_address); - } - if (b->local_media) - sal_media_description_unref(b->local_media); - if (b->remote_media) - sal_media_description_unref(b->remote_media); - if (b->call_id) - ms_free((void*)b->call_id); - if (b->service_route) { - sal_address_destroy(b->service_route); - } - if (b->route_addresses){ - bctbx_list_for_each(b->route_addresses,(void (*)(void*)) sal_address_destroy); - b->route_addresses=bctbx_list_free(b->route_addresses); - } - if (b->recv_custom_headers) - sal_custom_header_free(b->recv_custom_headers); - if (b->sent_custom_headers) - sal_custom_header_free(b->sent_custom_headers); - - if (b->entity_tag != NULL){ - ms_free(b->entity_tag); - b->entity_tag = NULL; - } - ms_free(op); -} - -SalAuthInfo* sal_auth_info_new() { - return ms_new0(SalAuthInfo,1); -} - -SalAuthInfo* sal_auth_info_clone(const SalAuthInfo* auth_info) { - SalAuthInfo* new_auth_info=sal_auth_info_new(); - new_auth_info->username=auth_info->username?ms_strdup(auth_info->username):NULL; - new_auth_info->userid=auth_info->userid?ms_strdup(auth_info->userid):NULL; - new_auth_info->realm=auth_info->realm?ms_strdup(auth_info->realm):NULL; - new_auth_info->domain=auth_info->realm?ms_strdup(auth_info->domain):NULL; - new_auth_info->password=auth_info->password?ms_strdup(auth_info->password):NULL; - return new_auth_info; -} - -void sal_auth_info_delete(SalAuthInfo* auth_info) { - if (auth_info->username) ms_free(auth_info->username); - if (auth_info->userid) ms_free(auth_info->userid); - if (auth_info->realm) ms_free(auth_info->realm); - if (auth_info->domain) ms_free(auth_info->domain); - if (auth_info->password) ms_free(auth_info->password); - if (auth_info->ha1) ms_free(auth_info->ha1); - if (auth_info->certificates) sal_certificates_chain_delete(auth_info->certificates); - if (auth_info->key) sal_signing_key_delete(auth_info->key); - ms_free(auth_info); -} - - - -const char* sal_stream_type_to_string(SalStreamType type) { - switch (type) { - case SalAudio: return "audio"; - case SalVideo: return "video"; - case SalText: return "text"; - default: return "other"; - } -} - -const char *sal_stream_description_get_type_as_string(const SalStreamDescription *desc){ - if (desc->type==SalOther) return desc->typeother; - else return sal_stream_type_to_string(desc->type); -} - -const char* sal_media_proto_to_string(SalMediaProto type) { - switch (type) { - case SalProtoRtpAvp:return "RTP/AVP"; - case SalProtoRtpSavp:return "RTP/SAVP"; - case SalProtoUdpTlsRtpSavp:return "UDP/TLS/RTP/SAVP"; - case SalProtoRtpAvpf:return "RTP/AVPF"; - case SalProtoRtpSavpf:return "RTP/SAVPF"; - case SalProtoUdpTlsRtpSavpf:return "UDP/TLS/RTP/SAVPF"; - default: return "unknown"; - } -} - -const char *sal_stream_description_get_proto_as_string(const SalStreamDescription *desc){ - if (desc->proto==SalProtoOther) return desc->proto_other; - else return sal_media_proto_to_string(desc->proto); -} - - -const char* sal_stream_dir_to_string(SalStreamDir type) { - switch (type) { - case SalStreamSendRecv:return "sendrecv"; - case SalStreamSendOnly:return "sendonly"; - case SalStreamRecvOnly:return "recvonly"; - case SalStreamInactive:return "inative"; - default: return "unknown"; - } - -} - -const char* sal_reason_to_string(const SalReason reason) { - switch (reason) { - case SalReasonDeclined : return "SalReasonDeclined"; - case SalReasonBusy: return "SalReasonBusy"; - case SalReasonRedirect: return "SalReasonRedirect"; - case SalReasonTemporarilyUnavailable: return "SalReasonTemporarilyUnavailable"; - case SalReasonNotFound: return "SalReasonNotFound"; - case SalReasonDoNotDisturb: return "SalReasonDoNotDisturb"; - case SalReasonUnsupportedContent: return "SalReasonUnsupportedContent"; - case SalReasonForbidden: return "SalReasonForbidden"; - case SalReasonUnknown: return "SalReasonUnknown"; - case SalReasonServiceUnavailable: return "SalReasonServiceUnavailable"; - case SalReasonNotAcceptable: return "SalReasonNotAcceptable"; - default: return "Unkown reason"; - } -} -const SalAddress* sal_op_get_service_route(const SalOp *op) { - return ((SalOpBase*)op)->service_route; -} -void sal_op_set_service_route(SalOp *op,const SalAddress* service_route) { - if (((SalOpBase*)op)->service_route) - sal_address_destroy(((SalOpBase*)op)->service_route); - - ((SalOpBase*)op)->service_route=service_route?sal_address_clone(service_route):NULL; -} - -const char* sal_presence_status_to_string(const SalPresenceStatus status) { - switch (status) { - case SalPresenceOffline: return "SalPresenceOffline"; - case SalPresenceOnline: return "SalPresenceOnline"; - case SalPresenceBusy: return "SalPresenceBusy"; - case SalPresenceBerightback: return "SalPresenceBerightback"; - case SalPresenceAway: return "SalPresenceAway"; - case SalPresenceOnthephone: return "SalPresenceOnthephone"; - case SalPresenceOuttolunch: return "SalPresenceOuttolunch"; - case SalPresenceDonotdisturb: return "SalPresenceDonotdisturb"; - case SalPresenceMoved: return "SalPresenceMoved"; - case SalPresenceAltService: return "SalPresenceAltService"; - default : return "unknown"; - } - -} -const char* sal_privacy_to_string(SalPrivacy privacy) { - switch(privacy) { - case SalPrivacyUser: return "user"; - case SalPrivacyHeader: return "header"; - case SalPrivacySession: return "session"; - case SalPrivacyId: return "id"; - case SalPrivacyNone: return "none"; - case SalPrivacyCritical: return "critical"; - default: return NULL; - } -} - -static void remove_trailing_spaces(char *line) { - size_t size = strlen(line); - char *end = line + size - 1; - while (end >= line && isspace(*end)) { - end--; - } - *(end + 1) = '\0'; -} - -static int line_get_value(const char *input, const char *key, char *value, size_t value_size, size_t *read){ - const char *end=strchr(input,'\n'); - char line[256]={0}; - char key_candidate[256]; - char *equal; - size_t len; - if (!end) len=strlen(input); - else len=end +1 -input; - *read=len; - strncpy(line,input,MIN(len,sizeof(line))); - equal=strchr(line,'='); - if (!equal) return FALSE; - *equal='\0'; - if (sscanf(line,"%s",key_candidate)!=1) return FALSE; - if (strcasecmp(key,key_candidate)==0){ - equal++; - remove_trailing_spaces(equal); - strncpy(value,equal,value_size-1); - value[value_size-1]='\0'; - return TRUE; - } - return FALSE; -} - -int sal_lines_get_value(const char *data, const char *key, char *value, size_t value_size){ - size_t read=0; - - do{ - if (line_get_value(data,key,value,value_size,&read)) - return TRUE; - data+=read; - }while(read!=0); - return FALSE; -} - -const char *sal_op_get_entity_tag(const SalOp* op) { - SalOpBase* op_base = (SalOpBase*)op; - return op_base->entity_tag; -} - - -void sal_op_set_entity_tag(SalOp *op, const char* entity_tag) { - SalOpBase* op_base = (SalOpBase*)op; - if (op_base->entity_tag != NULL){ - ms_free(op_base->entity_tag); - } - if (entity_tag) - op_base->entity_tag = ms_strdup(entity_tag); - else - op_base->entity_tag = NULL; -} diff --git a/coreapi/video_definition.c b/coreapi/video_definition.c index 717fdfd73..d193d0363 100644 --- a/coreapi/video_definition.c +++ b/coreapi/video_definition.c @@ -27,23 +27,13 @@ static void linphone_video_definition_destroy(LinphoneVideoDefinition *vdef) { if (vdef->name) bctbx_free(vdef->name); } -static void _linphone_video_definition_clone(LinphoneVideoDefinition *obj, const LinphoneVideoDefinition *orig){ - obj->name = bctbx_strdup(orig->name); - obj->width = orig->width; - obj->height = orig->height; -} - -belle_sip_error_code _linphone_video_definition_marshal(const LinphoneVideoDefinition* obj, char* buff, size_t buff_size, size_t *offset){ - return belle_sip_snprintf(buff,buff_size,offset,"%s",obj->name); -} - BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(LinphoneVideoDefinition); BELLE_SIP_INSTANCIATE_VPTR(LinphoneVideoDefinition, belle_sip_object_t, (belle_sip_object_destroy_t)linphone_video_definition_destroy, - (belle_sip_object_clone_t)_linphone_video_definition_clone, // clone - (belle_sip_object_marshal_t)_linphone_video_definition_marshal, // marshal - FALSE + NULL, // clone + NULL, // marshal + TRUE ); @@ -77,7 +67,7 @@ void linphone_video_definition_set_user_data(LinphoneVideoDefinition *vdef, void } LinphoneVideoDefinition * linphone_video_definition_clone(const LinphoneVideoDefinition *vdef) { - return (LinphoneVideoDefinition*)belle_sip_object_clone((belle_sip_object_t*)vdef); + return linphone_video_definition_new(linphone_video_definition_get_width(vdef), linphone_video_definition_get_height(vdef), linphone_video_definition_get_name(vdef)); } unsigned int linphone_video_definition_get_width(const LinphoneVideoDefinition *vdef) { diff --git a/gtk/calllogs.c b/gtk/calllogs.c index 9ee24eba8..5f5384d45 100644 --- a/gtk/calllogs.c +++ b/gtk/calllogs.c @@ -342,12 +342,6 @@ void linphone_gtk_call_log_update(GtkWidget *w){ case LinphoneCallDeclined: status=_("Declined"); break; - case LinphoneCallAnsweredElsewhere: - status=_("Answered elsewhere"); - break; - case LinphoneCallDeclinedElsewhere: - status=_("Declined elsewhere"); - break; default: break; } diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt index d54cb0ddf..fac14e8d6 100644 --- a/include/CMakeLists.txt +++ b/include/CMakeLists.txt @@ -1,8 +1,8 @@ -################################################################################ +############################################################################ # CMakeLists.txt -# Copyright (C) 2017 Belledonne Communications, Grenoble France +# Copyright (C) 2010-2016 Belledonne Communications, Grenoble France # -################################################################################ +############################################################################ # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License @@ -18,24 +18,25 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # -################################################################################ +############################################################################ -set(ROOT_HEADER_FILES - account_creator_service.h +set(HEADER_FILES account_creator.h + account_creator_service.h + address.h auth_info.h buffer.h + call.h + callbacks.h call_log.h call_params.h call_stats.h - call.h - callbacks.h chat.h conference.h contactprovider.h content.h - core_utils.h core.h + core_utils.h defs.h dictionary.h error_info.h @@ -43,7 +44,6 @@ set(ROOT_HEADER_FILES factory.h friend.h friendlist.h - headers.h im_encryption_engine.h im_notif_policy.h info_message.h @@ -63,74 +63,24 @@ set(ROOT_HEADER_FILES video_definition.h wrapper_utils.h xmlrpc.h + headers.h # Deprecated header files - linphone_proxy_config.h - linphone_tunnel.h - linphonecore_utils.h linphonecore.h + linphonecore_utils.h linphonefriend.h linphonepresence.h + linphone_proxy_config.h + linphone_tunnel.h ) -set(C_API_HEADER_FILES - c-address.h - c-api.h - c-event-log.h - c-types.h -) +set(LINPHONE_HEADER_FILES ) +foreach(HEADER_FILE ${HEADER_FILES}) + list(APPEND LINPHONE_HEADER_FILES "${CMAKE_CURRENT_LIST_DIR}/linphone/${HEADER_FILE}") +endforeach() +set(LINPHONE_HEADER_FILES ${LINPHONE_HEADER_FILES} PARENT_SCOPE) -set(ENUMS_HEADER_FILES - event-log-enums.h -) - -set(UTILS_HEADER_FILES - enum-generator.h - general.h - magic-macros.h - utils.h -) - -# ------------------------------------------------------------------------------ - -function (PREPEND OUT_LIST PREFIX) - set(TMP_LIST ) - foreach (FILENAME ${ARGN}) - list(APPEND TMP_LIST "${PREFIX}/${FILENAME}") - endforeach () - set(${OUT_LIST} "${TMP_LIST}" PARENT_SCOPE) -endfunction () - -# ------------------------------------------------------------------------------ - -set(SRC_ROOT_DIRECTORY "${CMAKE_CURRENT_LIST_DIR}/linphone") - -PREPEND(ROOT_HEADER_FILES "${SRC_ROOT_DIRECTORY}" ${ROOT_HEADER_FILES}) -PREPEND(C_API_HEADER_FILES "${SRC_ROOT_DIRECTORY}/api" ${C_API_HEADER_FILES}) -PREPEND(ENUMS_HEADER_FILES "${SRC_ROOT_DIRECTORY}/enums" ${ENUMS_HEADER_FILES}) -PREPEND(UTILS_HEADER_FILES "${SRC_ROOT_DIRECTORY}/utils" ${UTILS_HEADER_FILES}) - -set(LINPHONE_HEADER_FILES ${ROOT_HEADER_FILES} ${C_API_HEADER_FILES} ${ENUMS_HEADER_FILES} ${UTILS_HEADER_FILES} PARENT_SCOPE) - -# ------------------------------------------------------------------------------ - -set(DEST_ROOT_DIRECTORY "${CMAKE_INSTALL_INCLUDEDIR}/linphone") - -install(FILES ${ROOT_HEADER_FILES} - DESTINATION "${DEST_ROOT_DIRECTORY}" - PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ -) - -install(FILES ${C_API_HEADER_FILES} - DESTINATION "${DEST_ROOT_DIRECTORY}/api" - PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ -) -install(FILES ${ENUMS_HEADER_FILES} - DESTINATION "${DEST_ROOT_DIRECTORY}/enums" - PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ -) - -install(FILES ${UTILS_HEADER_FILES} - DESTINATION "${DEST_ROOT_DIRECTORY}/utils" +install(FILES ${LINPHONE_HEADER_FILES} + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/linphone PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ ) diff --git a/include/linphone/address.h b/include/linphone/address.h new file mode 100644 index 000000000..f92ff36f3 --- /dev/null +++ b/include/linphone/address.h @@ -0,0 +1,241 @@ +/* +address.h +Copyright (C) 2010-2016 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_ADDRESS_H +#define LINPHONE_ADDRESS_H + +#include "linphone/types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @addtogroup linphone_address + * @{ + */ + +/** + * Constructs a LinphoneAddress object by parsing the user supplied address, + * given as a string. +**/ +LINPHONE_PUBLIC LinphoneAddress * linphone_address_new(const char *addr); + +/** + * Clones a LinphoneAddress object. +**/ +LINPHONE_PUBLIC LinphoneAddress * linphone_address_clone(const LinphoneAddress *addr); + +/** + * Increment reference count of LinphoneAddress object. +**/ +LINPHONE_PUBLIC LinphoneAddress * linphone_address_ref(LinphoneAddress *addr); + +/** + * Decrement reference count of LinphoneAddress object. When dropped to zero, memory is freed. +**/ +LINPHONE_PUBLIC void linphone_address_unref(LinphoneAddress *addr); + +/** + * Returns the address scheme, normally "sip". +**/ +LINPHONE_PUBLIC const char *linphone_address_get_scheme(const LinphoneAddress *u); + +/** + * Returns the display name. +**/ +LINPHONE_PUBLIC const char *linphone_address_get_display_name(const LinphoneAddress* u); + +/** + * Returns the username. +**/ +LINPHONE_PUBLIC const char *linphone_address_get_username(const LinphoneAddress *u); + +/** + * Returns the domain name. +**/ +LINPHONE_PUBLIC const char *linphone_address_get_domain(const LinphoneAddress *u); + +/** + * Get port number as an integer value, 0 if not present. + */ +LINPHONE_PUBLIC int linphone_address_get_port(const LinphoneAddress *u); + +/** + * Sets the display name. +**/ +LINPHONE_PUBLIC LinphoneStatus linphone_address_set_display_name(LinphoneAddress *u, const char *display_name); + +/** + * Sets the username. +**/ +LINPHONE_PUBLIC LinphoneStatus linphone_address_set_username(LinphoneAddress *uri, const char *username); + +/** + * Sets the domain. +**/ +LINPHONE_PUBLIC LinphoneStatus linphone_address_set_domain(LinphoneAddress *uri, const char *host); + +/** + * Sets the port number. +**/ +LINPHONE_PUBLIC LinphoneStatus linphone_address_set_port(LinphoneAddress *uri, int port); + +/** + * Set a transport. +**/ +LINPHONE_PUBLIC LinphoneStatus linphone_address_set_transport(LinphoneAddress *uri,LinphoneTransportType type); + +/** + * Removes address's tags and uri headers so that it is displayable to the user. +**/ +LINPHONE_PUBLIC void linphone_address_clean(LinphoneAddress *uri); + +/** + * Returns true if address refers to a secure location (sips) + * @deprecated use linphone_address_get_secure() + * @donotwrap +**/ +LINPHONE_DEPRECATED LINPHONE_PUBLIC bool_t linphone_address_is_secure(const LinphoneAddress *addr); + +/** + * Returns true if address refers to a secure location (sips) +**/ +LINPHONE_PUBLIC bool_t linphone_address_get_secure(const LinphoneAddress *addr); + +/** + * Make the address refer to a secure location (sips scheme) + * @param[in] addr A #LinphoneAddress object + * @param[in] enabled TRUE if address is requested to be secure. +**/ +LINPHONE_PUBLIC void linphone_address_set_secure(LinphoneAddress *addr, bool_t enabled); + +/** + * returns true if address is a routable sip address + */ +LINPHONE_PUBLIC bool_t linphone_address_is_sip(const LinphoneAddress *uri); + +/** + * Get the transport. +**/ +LINPHONE_PUBLIC LinphoneTransportType linphone_address_get_transport(const LinphoneAddress *uri); + +/** + * Get the value of the method parameter +**/ +LINPHONE_PUBLIC const char *linphone_address_get_method_param(const LinphoneAddress *addr); + +/** + * Set the value of the method parameter +**/ +LINPHONE_PUBLIC void linphone_address_set_method_param(LinphoneAddress *addr, const char *method); + +/** + * Returns the address as a string. + * The returned char * must be freed by the application. Use ms_free(). +**/ +LINPHONE_PUBLIC char *linphone_address_as_string(const LinphoneAddress *u); + +/** + * Returns the SIP uri only as a string, that is display name is removed. + * The returned char * must be freed by the application. Use ms_free(). +**/ +LINPHONE_PUBLIC char *linphone_address_as_string_uri_only(const LinphoneAddress *u); + +/** + * Compare two LinphoneAddress ignoring tags and headers, basically just domain, username, and port. + * @param[in] a1 LinphoneAddress object + * @param[in] a2 LinphoneAddress object + * @return Boolean value telling if the LinphoneAddress objects are equal. + * @see linphone_address_equal() +**/ +LINPHONE_PUBLIC bool_t linphone_address_weak_equal(const LinphoneAddress *a1, const LinphoneAddress *a2); + +/** + * Compare two LinphoneAddress taking the tags and headers into account. + * @param[in] a1 LinphoneAddress object + * @param[in] a2 LinphoneAddress object + * @return Boolean value telling if the LinphoneAddress objects are equal. + * @see linphone_address_weak_equal() + */ +LINPHONE_PUBLIC bool_t linphone_address_equal(const LinphoneAddress *a1, const LinphoneAddress *a2); + +/** + * Set the password encoded in the address. + * It is used for basic authentication (not recommended). + * @param addr the LinphoneAddress + * @param passwd the password to set. +**/ +LINPHONE_PUBLIC void linphone_address_set_password(LinphoneAddress *addr, const char *passwd); + +/** + * Get the password encoded in the address. + * It is used for basic authentication (not recommended). + * @param addr the address + * @return the password, if any, NULL otherwise. +**/ +LINPHONE_PUBLIC const char *linphone_address_get_password(const LinphoneAddress *addr); + +/** + * Set a header into the address. + * Headers appear in the URI with '?', such as \. + * @param addr the address + * @param header_name the header name + * @param header_value the header value +**/ +LINPHONE_PUBLIC void linphone_address_set_header(LinphoneAddress *addr, const char *header_name, const char *header_value); + +/** + * Get the header encoded in the address. + * @param addr the address +**/ +LINPHONE_PUBLIC const char * linphone_address_get_header(const LinphoneAddress *addr, const char *name); + +LINPHONE_PUBLIC bool_t linphone_address_has_param(const LinphoneAddress *addr, const char *name); + +LINPHONE_PUBLIC const char * linphone_address_get_param(const LinphoneAddress *addr, const char *name); + +LINPHONE_PUBLIC void linphone_address_set_param(LinphoneAddress *addr, const char *name, const char *value); + +LINPHONE_PUBLIC void linphone_address_set_params(LinphoneAddress *addr, const char *params); + +LINPHONE_PUBLIC void linphone_address_set_uri_param(LinphoneAddress *addr, const char *name, const char *value); + +LINPHONE_PUBLIC void linphone_address_set_uri_params(LinphoneAddress *addr, const char *params); + +LINPHONE_PUBLIC bool_t linphone_address_has_uri_param(const LinphoneAddress *addr, const char *name); + +LINPHONE_PUBLIC const char * linphone_address_get_uri_param(const LinphoneAddress *addr, const char *name); + +/** + * Destroys a LinphoneAddress object (actually calls linphone_address_unref()). + * @deprecated Use linphone_address_unref() instead + * @donotwrap +**/ +LINPHONE_DEPRECATED LINPHONE_PUBLIC void linphone_address_destroy(LinphoneAddress *u); + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* LINPHONE_ADDRESS_H */ diff --git a/include/linphone/api/c-address.h b/include/linphone/api/c-address.h deleted file mode 100644 index 29312aa7f..000000000 --- a/include/linphone/api/c-address.h +++ /dev/null @@ -1,242 +0,0 @@ -/* - * c-event-log.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 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef _C_EVENT_LOG_H_ -#define _C_EVENT_LOG_H_ - -#include "linphone/api/c-types.h" - -// ============================================================================= - -#ifdef __cplusplus - extern "C" { -#endif // ifdef __cplusplus - -/** - * @addtogroup linphone_address - * @{ - */ - -/** - * Constructs a LinphoneAddress object by parsing the user supplied address, - * given as a string. - **/ -LINPHONE_PUBLIC LinphoneAddress *linphone_address_new (const char *address); - -/** - * Clones a LinphoneAddress object. - **/ -LINPHONE_PUBLIC LinphoneAddress *linphone_address_clone (const LinphoneAddress *address); - -/** - * Increment reference count of LinphoneAddress object. - **/ -LINPHONE_PUBLIC LinphoneAddress *linphone_address_ref (LinphoneAddress *address); - -/** - * Decrement reference count of LinphoneAddress object. When dropped to zero, memory is freed. - **/ -LINPHONE_PUBLIC void linphone_address_unref (LinphoneAddress *address); - -/** - * Returns the address scheme, normally "sip". - **/ -LINPHONE_PUBLIC const char *linphone_address_get_scheme (const LinphoneAddress *address); - -/** - * Returns the display name. - **/ -LINPHONE_PUBLIC const char *linphone_address_get_display_name (const LinphoneAddress *address); - -/** - * Sets the display name. - **/ -LINPHONE_PUBLIC LinphoneStatus linphone_address_set_display_name (LinphoneAddress *address, const char *display_name); - -/** - * Returns the username. - **/ -LINPHONE_PUBLIC const char *linphone_address_get_username (const LinphoneAddress *address); - -/** - * Sets the username. - **/ -LINPHONE_PUBLIC LinphoneStatus linphone_address_set_username (LinphoneAddress *address, const char *username); - -/** - * Returns the domain name. - **/ -LINPHONE_PUBLIC const char *linphone_address_get_domain (const LinphoneAddress *address); - -/** - * Sets the domain. - **/ -LINPHONE_PUBLIC LinphoneStatus linphone_address_set_domain (LinphoneAddress *address, const char *domain); - -/** - * Get port number as an integer value, 0 if not present. - */ -LINPHONE_PUBLIC int linphone_address_get_port (const LinphoneAddress *address); - -/** - * Sets the port number. - **/ -LINPHONE_PUBLIC LinphoneStatus linphone_address_set_port (LinphoneAddress *address, int port); - -/** - * Get the transport. - **/ -LINPHONE_PUBLIC LinphoneTransportType linphone_address_get_transport (const LinphoneAddress *address); - -/** - * Set a transport. - **/ -LINPHONE_PUBLIC LinphoneStatus linphone_address_set_transport (LinphoneAddress *address, LinphoneTransportType transport); - -/** - * Returns true if address refers to a secure location (sips) - **/ -LINPHONE_PUBLIC bool_t linphone_address_get_secure (const LinphoneAddress *address); - -/** - * Make the address refer to a secure location (sips scheme) - * @param[in] address A #LinphoneAddress object - * @param[in] enabled TRUE if address is requested to be secure. - **/ -LINPHONE_PUBLIC void linphone_address_set_secure (LinphoneAddress *address, bool_t enabled); - -/** - * returns true if address is a routable sip address - */ -LINPHONE_PUBLIC bool_t linphone_address_is_sip (const LinphoneAddress *address); - -/** - * Get the value of the method parameter - **/ -LINPHONE_PUBLIC const char *linphone_address_get_method_param (const LinphoneAddress *address); - -/** - * Set the value of the method parameter - **/ -LINPHONE_PUBLIC void linphone_address_set_method_param (LinphoneAddress *address, const char *method_param); - -/** - * Get the password encoded in the address. - * It is used for basic authentication (not recommended). - * @param address the address - * @return the password, if any, NULL otherwise. - **/ -LINPHONE_PUBLIC const char *linphone_address_get_password (const LinphoneAddress *address); - -/** - * Set the password encoded in the address. - * It is used for basic authentication (not recommended). - * @param address the LinphoneAddress - * @param password the password to set. - **/ -LINPHONE_PUBLIC void linphone_address_set_password (LinphoneAddress *address, const char *password); - -/** - * Removes address's tags and uri headers so that it is displayable to the user. - **/ -LINPHONE_PUBLIC void linphone_address_clean (LinphoneAddress *address); - -/** - * Returns the address as a string. - * The returned char * must be freed by the application. Use ms_free(). - **/ -LINPHONE_PUBLIC char *linphone_address_as_string (const LinphoneAddress *address); - -/** - * Returns the SIP uri only as a string, that is display name is removed. - * The returned char * must be freed by the application. Use ms_free(). - **/ -LINPHONE_PUBLIC char *linphone_address_as_string_uri_only (const LinphoneAddress *address); - -/** - * Compare two LinphoneAddress ignoring tags and headers, basically just domain, username, and port. - * @param[in] address1 LinphoneAddress object - * @param[in] address2 LinphoneAddress object - * @return Boolean value telling if the LinphoneAddress objects are equal. - * @see linphone_address_equal() - **/ -LINPHONE_PUBLIC bool_t linphone_address_weak_equal (const LinphoneAddress *address1, const LinphoneAddress *address2); - -/** - * Compare two LinphoneAddress taking the tags and headers into account. - * @param[in] address1 LinphoneAddress object - * @param[in] address2 LinphoneAddress object - * @return Boolean value telling if the LinphoneAddress objects are equal. - * @see linphone_address_weak_equal() - */ -LINPHONE_PUBLIC bool_t linphone_address_equal (const LinphoneAddress *address1, const LinphoneAddress *address2); - -/** -* Get the header encoded in the address. -* @param address the address -**/ -LINPHONE_PUBLIC const char *linphone_address_get_header (const LinphoneAddress *address, const char *header_name); - -/** - * Set a header into the address. - * Headers appear in the URI with '?', such as \. - * @param address the address - * @param header_name the header name - * @param header_value the header value - **/ -LINPHONE_PUBLIC void linphone_address_set_header (LinphoneAddress *address, const char *header_name, const char *header_value); - -LINPHONE_PUBLIC bool_t linphone_address_has_param (const LinphoneAddress *address, const char *param_name); - -LINPHONE_PUBLIC const char *linphone_address_get_param (const LinphoneAddress *address, const char *param_name); - -LINPHONE_PUBLIC void linphone_address_set_param (LinphoneAddress *address, const char *param_name, const char *param_value); - -LINPHONE_PUBLIC void linphone_address_set_params (LinphoneAddress *address, const char *params); - -LINPHONE_PUBLIC bool_t linphone_address_has_uri_param (const LinphoneAddress *address, const char *uri_param_name); - -LINPHONE_PUBLIC const char *linphone_address_get_uri_param (const LinphoneAddress *address, const char *uri_param_name); - -LINPHONE_PUBLIC void linphone_address_set_uri_param (LinphoneAddress *address, const char *uri_param_name, const char *uri_param_value); - -LINPHONE_PUBLIC void linphone_address_set_uri_params (LinphoneAddress *address, const char *params); - -/** - * Destroys a LinphoneAddress object (actually calls linphone_address_unref()). - * @deprecated Use linphone_address_unref() instead - * @donotwrap - **/ -LINPHONE_DEPRECATED LINPHONE_PUBLIC void linphone_address_destroy (LinphoneAddress *address); - -/** - * Returns true if address refers to a secure location (sips) - * @deprecated use linphone_address_get_secure() - * @donotwrap - **/ -LINPHONE_DEPRECATED LINPHONE_PUBLIC bool_t linphone_address_is_secure (const LinphoneAddress *address); - -/** - * @} - */ - -#ifdef __cplusplus - } -#endif // ifdef __cplusplus - -#endif // ifndef _C_EVENT_LOG_H_ diff --git a/include/linphone/api/c-api.h b/include/linphone/api/c-api.h deleted file mode 100644 index 746ac7c3a..000000000 --- a/include/linphone/api/c-api.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - * c-api.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 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef _C_API_H_ -#define _C_API_H_ - -#include "linphone/api/c-address.h" -#include "linphone/api/c-event-log.h" - -#endif // ifndef _C_API_H_ diff --git a/include/linphone/core.h b/include/linphone/core.h index 17c9e9103..01483b3c9 100644 --- a/include/linphone/core.h +++ b/include/linphone/core.h @@ -34,6 +34,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "linphone/account_creator.h" #include "linphone/account_creator_service.h" +#include "linphone/address.h" #include "linphone/auth_info.h" #include "linphone/buffer.h" #include "linphone/call.h" @@ -65,8 +66,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "linphone/xmlrpc.h" #include "linphone/headers.h" -// For migration purpose. -#include "linphone/api/c-api.h" #ifdef __cplusplus extern "C" { diff --git a/include/linphone/types.h b/include/linphone/types.h index f8a0a7271..177e4c003 100644 --- a/include/linphone/types.h +++ b/include/linphone/types.h @@ -26,8 +26,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "mediastreamer2/msvideo.h" #include "linphone/defs.h" -// For migration purpose. -#include "linphone/api/c-types.h" /** * The LinphoneAccountCreator object used to configure an account on a server via XML-RPC. @@ -171,6 +169,22 @@ typedef enum _LinphoneAccountCreatorStatus { LinphoneAccountCreatorStatusServerError /**< Error server */ } LinphoneAccountCreatorStatus; +struct SalAddress; + +/** + * Object that represents a SIP address. + * + * The LinphoneAddress is an opaque object to represents SIP addresses, ie + * the content of SIP's 'from' and 'to' headers. + * A SIP address is made of display name, username, domain name, port, and various + * uri headers (such as tags). It looks like 'Alice '. + * The LinphoneAddress has methods to extract and manipulate all parts of the address. + * When some part of the address (for example the username) is empty, the accessor methods + * return NULL. + * @ingroup linphone_address + */ +typedef struct SalAddress LinphoneAddress; + /** * Enum describing Ip family. * @ingroup initializing @@ -329,9 +343,7 @@ typedef enum _LinphoneCallStatus { LinphoneCallAborted, /**< The call was aborted */ LinphoneCallMissed, /**< The call was missed (unanswered) */ LinphoneCallDeclined, /**< The call was declined, either locally or by remote end */ - LinphoneCallEarlyAborted, /**. - */ - -#ifndef _ADDRESS_P_H_ -#define _ADDRESS_P_H_ - -#include "address.h" -#include "object/clonable-object-p.h" - -// ============================================================================= - -struct SalAddress; - -LINPHONE_BEGIN_NAMESPACE - -class AddressPrivate : public ClonableObjectPrivate { -public: - inline const SalAddress *getInternalAddress () const { - return internalAddress; - } - -private: - struct AddressCache { - mutable std::string scheme; - mutable std::string displayName; - mutable std::string username; - mutable std::string domain; - mutable std::string methodParam; - mutable std::string password; - - mutable std::unordered_map headers; - mutable std::unordered_map params; - mutable std::unordered_map uriParams; - }; - - SalAddress *internalAddress = nullptr; - AddressCache cache; - - L_DECLARE_PUBLIC(Address); -}; - -LINPHONE_END_NAMESPACE - -#endif diff --git a/src/address/address.cpp b/src/address/address.cpp deleted file mode 100644 index 7bac71911..000000000 --- a/src/address/address.cpp +++ /dev/null @@ -1,354 +0,0 @@ -/* - * address.cpp - * 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 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY {} without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "linphone/utils/utils.h" -#include "sal/sal.h" - -#include "address-p.h" -#include "c-wrapper/c-tools.h" -#include "logger/logger.h" - -#include "address.h" - -// ============================================================================= - -using namespace std; - -LINPHONE_BEGIN_NAMESPACE - -// ----------------------------------------------------------------------------- - -Address::Address (const string &address) : ClonableObject(*new AddressPrivate) { - L_D(Address); - if (!(d->internalAddress = sal_address_new(L_STRING_TO_C(address)))) { - lWarning() << "Cannot create address, bad uri [" << address << "]."; - return; - } -} - -Address::Address (const Address &src) : ClonableObject(*new AddressPrivate) { - L_D(Address); - SalAddress *salAddress = src.getPrivate()->internalAddress; - if (salAddress) - d->internalAddress = sal_address_clone(salAddress); -} - -Address::~Address () { - L_D(Address); - if (d->internalAddress) - sal_address_destroy(d->internalAddress); -} - -Address &Address::operator= (const Address &src) { - L_D(Address); - if (this != &src) { - if (d->internalAddress) - sal_address_destroy(d->internalAddress); - SalAddress *salAddress = src.getPrivate()->internalAddress; - d->internalAddress = salAddress ? sal_address_clone(salAddress) : nullptr; - } - - return *this; -} - -Address::operator bool () const { - L_D(const Address); - return static_cast(d->internalAddress); -} - -bool Address::operator== (const Address &address) const { - return equal(address); -} - -const string &Address::getScheme () const { - L_D(const Address); - d->cache.scheme = L_C_TO_STRING(sal_address_get_scheme(d->internalAddress)); - return d->cache.scheme; -} - -const string &Address::getDisplayName () const { - L_D(const Address); - d->cache.displayName = L_C_TO_STRING(sal_address_get_display_name(d->internalAddress)); - return d->cache.displayName; -} - -bool Address::setDisplayName (const string &displayName) { - L_D(Address); - - if (!d->internalAddress) - return false; - - sal_address_set_display_name(d->internalAddress, L_STRING_TO_C(displayName)); - return true; -} - -const string &Address::getUsername () const { - L_D(const Address); - d->cache.username = L_C_TO_STRING(sal_address_get_username(d->internalAddress)); - return d->cache.username; -} - -bool Address::setUsername (const string &username) { - L_D(Address); - - if (!d->internalAddress) - return false; - - sal_address_set_username(d->internalAddress, L_STRING_TO_C(username)); - return true; -} - -const string &Address::getDomain () const { - L_D(const Address); - d->cache.domain = L_C_TO_STRING(sal_address_get_domain(d->internalAddress)); - return d->cache.domain; -} - -bool Address::setDomain (const string &domain) { - L_D(Address); - - if (!d->internalAddress) - return false; - - sal_address_set_domain(d->internalAddress, L_STRING_TO_C(domain)); - return true; -} - -int Address::getPort () const { - L_D(const Address); - return d->internalAddress ? sal_address_get_port(d->internalAddress) : 0; -} - -bool Address::setPort (int port) { - L_D(const Address); - - if (!d->internalAddress) - return false; - - sal_address_set_port(d->internalAddress, port); - return true; -} - -Transport Address::getTransport () const { - L_D(const Address); - return d->internalAddress ? static_cast(sal_address_get_transport(d->internalAddress)) : Transport::Udp; -} - -bool Address::setTransport (Transport transport) { - L_D(const Address); - - if (!d->internalAddress) - return false; - - sal_address_set_transport(d->internalAddress, static_cast(transport)); - return true; -} - -bool Address::getSecure () const { - L_D(const Address); - return d->internalAddress ? sal_address_is_secure(d->internalAddress) : false; -} - -bool Address::setSecure (bool enabled) { - L_D(const Address); - - if (!d->internalAddress) - return false; - - sal_address_set_secure(d->internalAddress, enabled); - return true; -} - -bool Address::isSip () const { - L_D(const Address); - return d->internalAddress ? sal_address_is_sip(d->internalAddress) : false; -} - -const string &Address::getMethodParam () const { - L_D(const Address); - d->cache.methodParam = L_C_TO_STRING(sal_address_get_method_param(d->internalAddress)); - return d->cache.methodParam; -} - -bool Address::setMethodParam (const string &methodParam) { - L_D(Address); - - if (!d->internalAddress) - return false; - - sal_address_set_method_param(d->internalAddress, L_STRING_TO_C(methodParam)); - return true; -} - -const string &Address::getPassword () const { - L_D(const Address); - d->cache.password = L_C_TO_STRING(sal_address_get_password(d->internalAddress)); - return d->cache.password; -} - -bool Address::setPassword (const string &password) { - L_D(Address); - - if (!d->internalAddress) - return false; - - sal_address_set_password(d->internalAddress, L_STRING_TO_C(password)); - return true; -} - -bool Address::clean () { - L_D(const Address); - - if (!d->internalAddress) - return false; - - sal_address_clean(d->internalAddress); - return true; -} - -string Address::asString () const { - L_D(const Address); - - if (!d->internalAddress) - return ""; - - char *buf = sal_address_as_string(d->internalAddress); - string out = buf; - ms_free(buf); - return out; -} - -string Address::asStringUriOnly () const { - L_D(const Address); - - if (!d->internalAddress) - return ""; - - char *buf = sal_address_as_string_uri_only(d->internalAddress); - string out = buf; - ms_free(buf); - return out; -} - -bool Address::equal (const Address &address) const { - return asString() == address.asString(); -} - -bool Address::weakEqual (const Address &address) const { - return getUsername() == address.getUsername() && - getDomain() == address.getDomain() && - getPort() == address.getPort(); -} - -const string &Address::getHeaderValue (const string &headerName) const { - L_D(const Address); - - const char *value = sal_address_get_header(d->internalAddress, L_STRING_TO_C(headerName)); - if (value) { - d->cache.headers[headerName] = value; - return d->cache.headers[headerName]; - } - - return Utils::getEmptyConstRefObject(); -} - -bool Address::setHeader (const string &headerName, const string &headerValue) { - L_D(Address); - - if (!d->internalAddress) - return false; - - sal_address_set_header(d->internalAddress, L_STRING_TO_C(headerName), L_STRING_TO_C(headerValue)); - return true; -} - -bool Address::hasParam (const string ¶mName) const { - L_D(const Address); - return sal_address_has_param(d->internalAddress, L_STRING_TO_C(paramName)); -} - -const string &Address::getParamValue (const string ¶mName) const { - L_D(const Address); - - const char *value = sal_address_get_param(d->internalAddress, L_STRING_TO_C(paramName)); - if (value) { - d->cache.params[paramName] = value; - return d->cache.params[paramName]; - } - - return Utils::getEmptyConstRefObject(); -} - -bool Address::setParam (const string ¶mName, const string ¶mValue) { - L_D(Address); - - if (!d->internalAddress) - return false; - - sal_address_set_param(d->internalAddress, L_STRING_TO_C(paramName), L_STRING_TO_C(paramValue)); - return true; -} - -bool Address::setParams (const string ¶ms) { - L_D(Address); - - if (!d->internalAddress) - return false; - - sal_address_set_params(d->internalAddress, L_STRING_TO_C(params)); - return true; -} - -bool Address::hasUriParam (const string &uriParamName) const { - L_D(const Address); - return sal_address_has_uri_param(d->internalAddress, L_STRING_TO_C(uriParamName)); -} - -const string &Address::getUriParamValue (const string &uriParamName) const { - L_D(const Address); - - const char *value = sal_address_get_uri_param(d->internalAddress, L_STRING_TO_C(uriParamName)); - if (value) { - d->cache.uriParams[uriParamName] = value; - return d->cache.uriParams[uriParamName]; - } - - return Utils::getEmptyConstRefObject(); -} - -bool Address::setUriParam (const string &uriParamName, const string &uriParamValue) { - L_D(Address); - - if (!d->internalAddress) - return false; - - sal_address_set_uri_param(d->internalAddress, L_STRING_TO_C(uriParamName), L_STRING_TO_C(uriParamValue)); - return true; -} - -bool Address::setUriParams (const string &uriParams) { - L_D(Address); - - if (!d->internalAddress) - return false; - - sal_address_set_uri_params(d->internalAddress, L_STRING_TO_C(uriParams)); - return true; -} - -LINPHONE_END_NAMESPACE diff --git a/src/address/address.h b/src/address/address.h deleted file mode 100644 index 84048a681..000000000 --- a/src/address/address.h +++ /dev/null @@ -1,100 +0,0 @@ -/* - * address.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 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef _ADDRESS_H_ -#define _ADDRESS_H_ - -#include - -#include "enums.h" -#include "object/clonable-object.h" - -// ============================================================================= - -LINPHONE_BEGIN_NAMESPACE - -class AddressPrivate; - -class LINPHONE_PUBLIC Address : public ClonableObject { -public: - Address (const std::string &address = ""); - Address (const Address &src); - ~Address (); - - Address &operator= (const Address &src); - - operator bool () const; - - bool operator== (const Address &address) const; - - const std::string &getScheme () const; - - const std::string &getDisplayName () const; - bool setDisplayName (const std::string &displayName); - - const std::string &getUsername () const; - bool setUsername (const std::string &username); - - const std::string &getDomain () const; - bool setDomain (const std::string &domain); - - int getPort () const; - bool setPort (int port); - - Transport getTransport () const; - bool setTransport (Transport transport); - - bool getSecure () const; - bool setSecure (bool enabled); - - bool isSip () const; - - const std::string &getMethodParam () const; - bool setMethodParam (const std::string &methodParam); - - const std::string &getPassword () const; - bool setPassword (const std::string &password); - - bool clean (); - - std::string asString () const; - std::string asStringUriOnly () const; - - bool equal (const Address &address) const; - bool weakEqual (const Address &address) const; - - const std::string &getHeaderValue (const std::string &headerName) const; - bool setHeader (const std::string &headerName, const std::string &headerValue); - - bool hasParam (const std::string ¶mName) const; - const std::string &getParamValue (const std::string ¶mName) const; - bool setParam (const std::string ¶mName, const std::string ¶mValue); - bool setParams (const std::string ¶ms); - - bool hasUriParam (const std::string &uriParamName) const; - const std::string &getUriParamValue (const std::string &uriParamName) const; - bool setUriParam (const std::string &uriParamName, const std::string &uriParamValue); - bool setUriParams (const std::string &uriParams); - -private: - L_DECLARE_PRIVATE(Address); -}; - -LINPHONE_END_NAMESPACE - -#endif // ifndef _ADDRESS_H_ diff --git a/src/c-wrapper/api/c-address.cpp b/src/c-wrapper/api/c-address.cpp deleted file mode 100644 index 126c416d8..000000000 --- a/src/c-wrapper/api/c-address.cpp +++ /dev/null @@ -1,192 +0,0 @@ -/* - * c-event-log.cpp - * 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 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "linphone/api/c-address.h" - -#include "c-wrapper/c-tools.h" - -#include "address/address.h" - -// ============================================================================= - -using namespace std; - -L_DECLARE_C_STRUCT_IMPL(Address, address); - -LinphoneAddress *linphone_address_new (const char *address) { - shared_ptr cppPtr = make_shared(L_C_TO_STRING(address)); - if (!*cppPtr.get()) - return nullptr; - - LinphoneAddress *object = _linphone_address_init(); - object->cppPtr = cppPtr; - return object; -} - -LinphoneAddress *linphone_address_clone (const LinphoneAddress *address) { - return (LinphoneAddress *)belle_sip_object_clone(BELLE_SIP_OBJECT(address)); -} - -LinphoneAddress *linphone_address_ref (LinphoneAddress *address) { - belle_sip_object_ref(address); - return address; -} - -void linphone_address_unref (LinphoneAddress *address) { - belle_sip_object_unref(address); -} - -const char *linphone_address_get_scheme (const LinphoneAddress *address) { - return L_STRING_TO_C(address->cppPtr->getScheme()); -} - -const char *linphone_address_get_display_name (const LinphoneAddress *address) { - return L_STRING_TO_C(address->cppPtr->getDisplayName()); -} - -LinphoneStatus linphone_address_set_display_name (LinphoneAddress *address, const char *display_name) { - return !address->cppPtr->setDisplayName(L_C_TO_STRING(display_name)); -} - -const char *linphone_address_get_username (const LinphoneAddress *address) { - return L_STRING_TO_C(address->cppPtr->getUsername()); -} - -LinphoneStatus linphone_address_set_username (LinphoneAddress *address, const char *username) { - return !address->cppPtr->setUsername(L_C_TO_STRING(username)); -} - -const char *linphone_address_get_domain (const LinphoneAddress *address) { - return L_STRING_TO_C(address->cppPtr->getDomain()); -} - -LinphoneStatus linphone_address_set_domain (LinphoneAddress *address, const char *domain) { - return !address->cppPtr->setDomain(L_C_TO_STRING(domain)); -} - -int linphone_address_get_port (const LinphoneAddress *address) { - return address->cppPtr->getPort(); -} - -LinphoneStatus linphone_address_set_port (LinphoneAddress *address, int port) { - return !address->cppPtr->setPort(port); -} - -LinphoneTransportType linphone_address_get_transport (const LinphoneAddress *address) { - return static_cast(address->cppPtr->getTransport()); -} - -LinphoneStatus linphone_address_set_transport (LinphoneAddress *address, LinphoneTransportType transport) { - return !address->cppPtr->setTransport(static_cast(transport)); -} - -bool_t linphone_address_get_secure (const LinphoneAddress *address) { - return address->cppPtr->getSecure(); -} - -void linphone_address_set_secure (LinphoneAddress *address, bool_t enabled) { - address->cppPtr->setSecure(enabled); -} - -bool_t linphone_address_is_sip (const LinphoneAddress *address) { - return address->cppPtr->isSip(); -} - -const char *linphone_address_get_method_param (const LinphoneAddress *address) { - return L_STRING_TO_C(address->cppPtr->getMethodParam()); -} - -void linphone_address_set_method_param (LinphoneAddress *address, const char *method_param) { - address->cppPtr->setMethodParam(L_C_TO_STRING(method_param)); -} - -const char *linphone_address_get_password (const LinphoneAddress *address) { - return L_STRING_TO_C(address->cppPtr->getPassword()); -} - -void linphone_address_set_password (LinphoneAddress *address, const char *password) { - address->cppPtr->setPassword(L_C_TO_STRING(password)); -} - -void linphone_address_clean (LinphoneAddress *address) { - address->cppPtr->clean(); -} - -char *linphone_address_as_string (const LinphoneAddress *address) { - return ms_strdup(address->cppPtr->asString().c_str()); -} - -char *linphone_address_as_string_uri_only (const LinphoneAddress *address) { - return ms_strdup(address->cppPtr->asStringUriOnly().c_str()); -} - -bool_t linphone_address_weak_equal (const LinphoneAddress *address1, const LinphoneAddress *address2) { - return address1->cppPtr->weakEqual(*address2->cppPtr.get()); -} - -bool_t linphone_address_equal (const LinphoneAddress *address1, const LinphoneAddress *address2) { - return *address1->cppPtr.get() == *address2->cppPtr.get(); -} - -const char *linphone_address_get_header (const LinphoneAddress *address, const char *header_name) { - return L_STRING_TO_C(address->cppPtr->getHeaderValue(L_C_TO_STRING(header_name))); -} - -void linphone_address_set_header (LinphoneAddress *address, const char *header_name, const char *header_value) { - address->cppPtr->setHeader(L_C_TO_STRING(header_name), L_C_TO_STRING(header_value)); -} - -bool_t linphone_address_has_param (const LinphoneAddress *address, const char *param_name) { - return address->cppPtr->hasParam(L_C_TO_STRING(param_name)); -} - -const char *linphone_address_get_param (const LinphoneAddress *address, const char *param_name) { - return L_STRING_TO_C(address->cppPtr->getParamValue(L_C_TO_STRING(param_name))); -} - -void linphone_address_set_param (LinphoneAddress *address, const char *param_name, const char *param_value) { - address->cppPtr->setParam(L_C_TO_STRING(param_name), L_C_TO_STRING(param_value)); -} - -void linphone_address_set_params (LinphoneAddress *address, const char *params) { - address->cppPtr->setParams(L_C_TO_STRING(params)); -} - -bool_t linphone_address_has_uri_param (const LinphoneAddress *address, const char *uri_param_name) { - return address->cppPtr->hasUriParam(L_C_TO_STRING(uri_param_name)); -} - -const char *linphone_address_get_uri_param (const LinphoneAddress *address, const char *uri_param_name) { - return L_STRING_TO_C(address->cppPtr->getUriParamValue(L_C_TO_STRING(uri_param_name))); -} - -void linphone_address_set_uri_param (LinphoneAddress *address, const char *uri_param_name, const char *uri_param_value) { - address->cppPtr->setUriParam(L_C_TO_STRING(uri_param_name), L_C_TO_STRING(uri_param_value)); -} - -void linphone_address_set_uri_params (LinphoneAddress *address, const char *params) { - address->cppPtr->setUriParams(L_C_TO_STRING(params)); -} - -void linphone_address_destroy (LinphoneAddress *address) { - belle_sip_object_unref(address); -} - -bool_t linphone_address_is_secure (const LinphoneAddress *address) { - return address->cppPtr->getSecure(); -} diff --git a/src/c-wrapper/api/c-event-log.cpp b/src/c-wrapper/api/c-event-log.cpp index 43631882f..2404b5418 100644 --- a/src/c-wrapper/api/c-event-log.cpp +++ b/src/c-wrapper/api/c-event-log.cpp @@ -16,10 +16,10 @@ * along with this program. If not, see . */ -#include "linphone/api/c-event-log.h" - #include "c-wrapper/c-tools.h" +#include "c-event-log.h" + #include "event-log/call-event.h" #include "event-log/conference-participant-event.h" #include "event-log/message-event.h" @@ -28,6 +28,7 @@ using namespace std; +extern "C" { // ----------------------------------------------------------------------------- // Event log. // ----------------------------------------------------------------------------- @@ -111,3 +112,4 @@ const LinphoneAddress *linphone_conference_participant_event_get_participant_add // TODO. return nullptr; } +} diff --git a/include/linphone/api/c-event-log.h b/src/c-wrapper/api/c-event-log.h similarity index 97% rename from include/linphone/api/c-event-log.h rename to src/c-wrapper/api/c-event-log.h index dcc56f76b..a33edbabb 100644 --- a/include/linphone/api/c-event-log.h +++ b/src/c-wrapper/api/c-event-log.h @@ -19,13 +19,13 @@ #ifndef _C_EVENT_LOG_H_ #define _C_EVENT_LOG_H_ -#include "linphone/api/c-types.h" +#include "c-wrapper/c-types.h" // ============================================================================= #ifdef __cplusplus extern "C" { -#endif // ifdef __cplusplus +#endif LINPHONE_PUBLIC LinphoneEventLog *linphone_event_log_new (); LINPHONE_PUBLIC LinphoneEventLogType linphone_event_log_get_type (const LinphoneEventLog *event_log); diff --git a/src/c-wrapper/c-tools.h b/src/c-wrapper/c-tools.h index 8f4b6d738..a63eef594 100644 --- a/src/c-wrapper/c-tools.h +++ b/src/c-wrapper/c-tools.h @@ -19,77 +19,29 @@ #ifndef _C_TOOLS_H_ #define _C_TOOLS_H_ -#include -#include - // From coreapi. #include "private.h" // ============================================================================= -LINPHONE_BEGIN_NAMESPACE - -class Wrapper { -private: - template - struct WrappedObject { - belle_sip_object_t base; - std::shared_ptr cppPtr; - }; - -public: - template - static inline decltype (std::declval().getPrivate()) getPrivate (T *object) { - if (!object) - return nullptr; - return object->getPrivate(); - } - - template - static inline std::shared_ptr getCppPtrFromC (void *object) { - L_ASSERT(object); - return static_cast *>(object)->cppPtr; - } - - template - static inline std::shared_ptr getCppPtrFromC (const void *object) { - L_ASSERT(object); - return static_cast *>(object)->cppPtr; - } - - template - static inline void setCppPtrFromC (void *object, std::shared_ptr &cppPtr) { - L_ASSERT(object); - static_cast *>(object)->cppPtr = cppPtr; - } - -private: - Wrapper (); - - L_DISABLE_COPY(Wrapper); -}; - -LINPHONE_END_NAMESPACE - -// ----------------------------------------------------------------------------- - #define L_DECLARE_C_STRUCT_IMPL(STRUCT, C_NAME) \ struct _Linphone ## STRUCT { \ belle_sip_object_t base; \ - std::shared_ptr cppPtr; \ + shared_ptr cppPtr; \ }; \ BELLE_SIP_DECLARE_VPTR_NO_EXPORT(Linphone ## STRUCT); \ static Linphone ## STRUCT *_linphone_ ## C_NAME ## _init() { \ Linphone ## STRUCT * object = belle_sip_object_new(Linphone ## STRUCT); \ - new(&object->cppPtr) std::shared_ptr(); \ + new(&object->cppPtr) shared_ptr(); \ return object; \ } \ static void _linphone_ ## C_NAME ## _uninit(Linphone ## STRUCT * object) { \ - object->cppPtr.~shared_ptr (); \ + object->cppPtr.reset(); \ + object->cppPtr->~STRUCT (); \ } \ static void _linphone_ ## C_NAME ## _clone(Linphone ## STRUCT * dest, const Linphone ## STRUCT * src) { \ - new(&dest->cppPtr) std::shared_ptr(); \ - dest->cppPtr = std::make_shared(*src->cppPtr.get()); \ + new(&dest->cppPtr) shared_ptr(); \ + dest->cppPtr = make_shared(*src->cppPtr.get()); \ } \ BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(Linphone ## STRUCT); \ BELLE_SIP_INSTANCIATE_VPTR(Linphone ## STRUCT, belle_sip_object_t, \ @@ -102,23 +54,8 @@ LINPHONE_END_NAMESPACE #define L_DECLARE_C_STRUCT_NEW_DEFAULT(STRUCT, C_NAME) \ Linphone ## STRUCT * linphone_ ## C_NAME ## _new() { \ Linphone ## STRUCT * object = _linphone_ ## C_NAME ## _init(); \ - object->cppPtr = std::make_shared(); \ + object->cppPtr = make_shared(); \ return object; \ } -#define L_STRING_TO_C(STR) ((STR).empty() ? NULL : (STR).c_str()) -#define L_C_TO_STRING(STR) ((STR) == NULL ? std::string() : (STR)) - -#define L_GET_CPP_PTR_FROM_C_STRUCT(OBJECT, TYPE) \ - LINPHONE_NAMESPACE::Wrapper::getCppPtrFromC(OBJECT) - -#define L_SET_CPP_PTR_FROM_C_STRUCT(OBJECT, CPP_PTR) \ - LINPHONE_NAMESPACE::Wrapper::setCppPtrFromC(OBJECT, CPP_PTR) - -#define L_GET_PRIVATE(OBJECT) \ - LINPHONE_NAMESPACE::Wrapper::getPrivate(OBJECT) - -#define L_GET_PRIVATE_FROM_C_STRUCT(OBJECT, TYPE) \ - L_GET_PRIVATE(L_GET_CPP_PTR_FROM_C_STRUCT(OBJECT, TYPE).get()) - #endif // ifndef _C_TOOLS_H_ diff --git a/include/linphone/api/c-types.h b/src/c-wrapper/c-types.h similarity index 51% rename from include/linphone/api/c-types.h rename to src/c-wrapper/c-types.h index d71ba795d..933b067b6 100644 --- a/include/linphone/api/c-types.h +++ b/src/c-wrapper/c-types.h @@ -23,63 +23,31 @@ // Enable C enums. #define L_USE_C_ENUM -// TODO: Remove me in the future. -#include "linphone/types.h" - -#include "linphone/enums/event-log-enums.h" +#include "event-log/event-log-enums.h" #define L_DECLARE_C_ENUM(CLASS, ENUM, VALUES) enum Linphone ## CLASS ## ENUM { VALUES } +#define L_DECLARE_C_STRUCT(STRUCT) typedef struct _Linphone ## STRUCT Linphone ## STRUCT; // ============================================================================= #ifdef __cplusplus extern "C" { -#endif // ifdef __cplusplus - -// ============================================================================= -// Misc. -// ============================================================================= - -typedef int LinphoneStatus; - -typedef unsigned char bool_t; - -#ifdef TRUE - #undef TRUE #endif -#ifdef FALSE - #undef FALSE -#endif - -#define TRUE 1 -#define FALSE 0 - // ============================================================================= // C Structures. // ============================================================================= -/** - * Object that represents a SIP address. - * - * The LinphoneAddress is an opaque object to represents SIP addresses, ie - * the content of SIP's 'from' and 'to' headers. - * A SIP address is made of display name, username, domain name, port, and various - * uri headers (such as tags). It looks like 'Alice '. - * The LinphoneAddress has methods to extract and manipulate all parts of the address. - * When some part of the address (for example the username) is empty, the accessor methods - * return NULL. - * @ingroup linphone_address - */ -typedef struct _LinphoneAddress LinphoneAddress; +L_DECLARE_C_STRUCT(Call); +L_DECLARE_C_STRUCT(CallEvent); +L_DECLARE_C_STRUCT(ConferenceEvent); +L_DECLARE_C_STRUCT(ConferenceParticipantEvent); +L_DECLARE_C_STRUCT(EventLog); +L_DECLARE_C_STRUCT(Message); +L_DECLARE_C_STRUCT(MessageEvent); -typedef struct _LinphoneCall LinphoneCall; -typedef struct _LinphoneCallEvent LinphoneCallEvent; -typedef struct _LinphoneConferenceEvent LinphoneConferenceEvent; -typedef struct _LinphoneConferenceParticipantEvent LinphoneConferenceParticipantEvent; -typedef struct _LinphoneEventLog LinphoneEventLog; -typedef struct _LinphoneMessage LinphoneMessage; -typedef struct _LinphoneMessageEvent LinphoneMessageEvent; +// TODO: Remove me in the future. +typedef struct SalAddress LinphoneAddress; // ============================================================================= // C Enums. @@ -89,6 +57,6 @@ L_DECLARE_C_ENUM(EventLog, Type, L_ENUM_VALUES_EVENT_LOG_TYPE); #ifdef __cplusplus } -#endif // ifdef __cplusplus +#endif #endif // ifndef _C_TYPES_H_ diff --git a/src/chat/chat-room-p.h b/src/chat/chat-room-p.h deleted file mode 100644 index 4f7e492d9..000000000 --- a/src/chat/chat-room-p.h +++ /dev/null @@ -1,113 +0,0 @@ -/* - * chat-room-p.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 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef _CHAT_ROOM_P_H_ -#define _CHAT_ROOM_P_H_ - -// From coreapi. -#include "private.h" - -#include "chat-room.h" -#include "is-composing.h" -#include "is-composing-listener.h" -#include "object/object-p.h" - -// ============================================================================= - -LINPHONE_BEGIN_NAMESPACE - -class ChatRoomPrivate : public ObjectPrivate, public IsComposingListener { -public: - ChatRoomPrivate (LinphoneCore *core); - virtual ~ChatRoomPrivate (); - -private: - static int createChatMessageFromDb (void *data, int argc, char **argv, char **colName); - static void onWeakMessageDestroyed (void *obj, belle_sip_object_t *messageBeingDestroyed); - -public: - void addTransientMessage (LinphoneChatMessage *msg); - void addWeakMessage (LinphoneChatMessage *msg); - std::list getTransientMessages () const { - return transientMessages; - } - - void moveTransientMessageToWeakMessages (LinphoneChatMessage *msg); - void removeTransientMessage (LinphoneChatMessage *msg); - - void release (); - void sendImdn (const std::string &content, LinphoneReason reason); - - int getMessagesCount (bool unreadOnly); - void setCBackPointer (LinphoneChatRoom *cr) { - this->cBackPointer = cr; - } - - void setCall (LinphoneCall *call) { - this->call = call; - } - -private: - void sendIsComposingNotification (); - - int createChatMessageFromDb (int argc, char **argv, char **colName); - void onWeakMessageDestroyed (LinphoneChatMessage *messageBeingDestroyed); - LinphoneChatMessage *getTransientMessage (unsigned int storageId) const; - LinphoneChatMessage *getWeakMessage (unsigned int storageId) const; - int sqlRequest (sqlite3 *db, const std::string &stmt); - void sqlRequestMessage (sqlite3 *db, const std::string &stmt); - std::list findMessages (const std::string &messageId); - void storeOrUpdateMessage (LinphoneChatMessage *msg); - -public: - LinphoneReason messageReceived (SalOp *op, const SalMessage *msg); - void realtimeTextReceived (uint32_t character, LinphoneCall *call); - -private: - void chatMessageReceived (LinphoneChatMessage *msg); - void imdnReceived (const std::string &text); - void isComposingReceived (const std::string &text); - -private: - void isComposingStateChanged (bool isComposing); - void isRemoteComposingStateChanged (bool isComposing); - void isComposingRefreshNeeded (); - -public: - LinphoneChatRoom *cBackPointer = nullptr; - LinphoneCore *core = nullptr; - LinphoneCall *call = nullptr; - LinphoneAddress *peerAddress = nullptr; - std::string peer; - int unreadCount = -1; - bool isComposing = false; - bool remoteIsComposing = false; - std::list messages; - std::list transientMessages; - std::list weakMessages; - std::list receivedRttCharacters; - LinphoneChatMessage *pendingMessage = nullptr; - IsComposing isComposingHandler; - -private: - L_DECLARE_PUBLIC(ChatRoom); -}; - -LINPHONE_END_NAMESPACE - -#endif // ifndef _CHAT_ROOM_P_H_ diff --git a/src/chat/chat-room.cpp b/src/chat/chat-room.cpp deleted file mode 100644 index 9ca62c0b3..000000000 --- a/src/chat/chat-room.cpp +++ /dev/null @@ -1,993 +0,0 @@ -/* - * chat-room.cpp - * 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 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include - -#include "linphone/utils/utils.h" - -#include "chat-room-p.h" -#include "imdn.h" -#include "logger/logger.h" -#include "utils/content-type.h" - -#include "chat-room.h" - -// ============================================================================= - -using namespace std; - -LINPHONE_BEGIN_NAMESPACE - -ChatRoomPrivate::ChatRoomPrivate (LinphoneCore *core) - : core(core), isComposingHandler(core, this) {} - -ChatRoomPrivate::~ChatRoomPrivate () { - for (auto it = transientMessages.begin(); it != transientMessages.end(); it++) { - linphone_chat_message_release(*it); - } - if (!receivedRttCharacters.empty()) { - for (auto it = receivedRttCharacters.begin(); it != receivedRttCharacters.end(); it++) - bctbx_free(*it); - } - if (core) { - if (bctbx_list_find(core->chatrooms, cBackPointer)) { - lError() << "LinphoneChatRoom[" << cBackPointer << "] is destroyed while still being used by the LinphoneCore. " << - "This is abnormal. linphone_core_get_chat_room() doesn't give a reference, there is no need to call linphone_chat_room_unref(). " << - "In order to remove a chat room from the core, use linphone_core_delete_chat_room()."; - core->chatrooms = bctbx_list_remove(core->chatrooms, cBackPointer); - } - } - linphone_address_unref(peerAddress); - if (pendingMessage) - linphone_chat_message_destroy(pendingMessage); -} - -// ----------------------------------------------------------------------------- - -int ChatRoomPrivate::createChatMessageFromDb (void *data, int argc, char **argv, char **colName) { - ChatRoomPrivate *d = reinterpret_cast(data); - return d->createChatMessageFromDb(argc, argv, colName); -} - -void ChatRoomPrivate::onWeakMessageDestroyed (void *obj, belle_sip_object_t *messageBeingDestroyed) { - ChatRoomPrivate *d = reinterpret_cast(obj); - d->onWeakMessageDestroyed(reinterpret_cast(messageBeingDestroyed)); -} - -// ----------------------------------------------------------------------------- - -void ChatRoomPrivate::addTransientMessage (LinphoneChatMessage *msg) { - auto iter = find(transientMessages.begin(), transientMessages.end(), msg); - if (iter == transientMessages.end()) - transientMessages.push_back(linphone_chat_message_ref(msg)); -} - -void ChatRoomPrivate::addWeakMessage (LinphoneChatMessage *msg) { - auto iter = find(weakMessages.begin(), weakMessages.end(), msg); - if (iter == weakMessages.end()) - weakMessages.push_back(reinterpret_cast(belle_sip_object_weak_ref(msg, onWeakMessageDestroyed, this))); -} - -void ChatRoomPrivate::moveTransientMessageToWeakMessages (LinphoneChatMessage *msg) { - auto iter = find(transientMessages.begin(), transientMessages.end(), msg); - if (iter != transientMessages.end()) { - /* msg is not transient anymore, we can remove it from our transient list and unref it */ - addWeakMessage(msg); - removeTransientMessage(msg); - } else { - /* msg has already been removed from the transient messages, do nothing */ - } -} - -void ChatRoomPrivate::removeTransientMessage (LinphoneChatMessage *msg) { - auto iter = find(transientMessages.begin(), transientMessages.end(), msg); - if (iter != transientMessages.end()) { - linphone_chat_message_unref(*iter); - transientMessages.erase(iter); - } -} - -// ----------------------------------------------------------------------------- - -void ChatRoomPrivate::release () { - isComposingHandler.stopTimers(); - for (auto it = weakMessages.begin(); it != weakMessages.end(); it++) { - linphone_chat_message_deactivate(*it); - } - for (auto it = transientMessages.begin(); it != transientMessages.end(); it++) { - linphone_chat_message_deactivate(*it); - } - core = nullptr; - linphone_chat_room_unref(cBackPointer); -} - -void ChatRoomPrivate::sendImdn (const string &content, LinphoneReason reason) { - L_Q(ChatRoom); - - const char *identity = nullptr; - LinphoneProxyConfig *proxy = linphone_core_lookup_known_proxy(core, peerAddress); - if (proxy) - identity = linphone_address_as_string(linphone_proxy_config_get_identity_address(proxy)); - else - identity = linphone_core_get_primary_contact(core); - - /* Sending out of call */ - SalOp *op = sal_op_new(core->sal); - linphone_configure_op(core, op, peerAddress, nullptr, lp_config_get_int(core->config, "sip", "chat_msg_with_contact", 0)); - LinphoneChatMessage *msg = q->createMessage(content); - LinphoneAddress *fromAddr = linphone_address_new(identity); - linphone_chat_message_set_from_address(msg, fromAddr); - LinphoneAddress *toAddr = linphone_address_new(peer.c_str()); - linphone_chat_message_set_to_address(msg, toAddr); - linphone_chat_message_set_content_type(msg, "message/imdn+xml"); - - /* Do not try to encrypt the notification when it is reporting an error (maybe it should be bypassed only for some reasons). */ - int retval = -1; - LinphoneImEncryptionEngine *imee = linphone_core_get_im_encryption_engine(core); - if (imee && (reason == LinphoneReasonNone)) { - LinphoneImEncryptionEngineCbs *imeeCbs = linphone_im_encryption_engine_get_callbacks(imee); - LinphoneImEncryptionEngineCbsOutgoingMessageCb cbProcessOutgoingMessage = linphone_im_encryption_engine_cbs_get_process_outgoing_message(imeeCbs); - if (cbProcessOutgoingMessage) { - retval = cbProcessOutgoingMessage(imee, cBackPointer, msg); - } - } - - if (retval <= 0) { - sal_message_send(op, identity, peer.c_str(), msg->content_type, msg->message, nullptr); - } - - linphone_chat_message_unref(msg); - linphone_address_unref(fromAddr); - linphone_address_unref(toAddr); - sal_op_unref(op); -} - -// ----------------------------------------------------------------------------- - -int ChatRoomPrivate::getMessagesCount (bool unreadOnly) { - if (!core->db) return 0; - - /* Optimization: do not read database if the count is already available in memory */ - if (unreadOnly && unreadCount >= 0) return unreadCount; - - char *peer = linphone_address_as_string_uri_only(peerAddress); - char *option = nullptr; - if (unreadOnly) - option = bctbx_strdup_printf("AND status!=%i AND direction=%i", LinphoneChatMessageStateDisplayed, LinphoneChatMessageIncoming); - char *buf = sqlite3_mprintf("SELECT count(*) FROM history WHERE remoteContact = %Q %s;", peer, unreadOnly ? option : ""); - sqlite3_stmt *selectStatement; - int numrows = 0; - int returnValue = sqlite3_prepare_v2(core->db, buf, -1, &selectStatement, nullptr); - if (returnValue == SQLITE_OK) { - if (sqlite3_step(selectStatement) == SQLITE_ROW) { - numrows = sqlite3_column_int(selectStatement, 0); - } - } - sqlite3_finalize(selectStatement); - sqlite3_free(buf); - ms_free(peer); - - /* No need to test the sign of unreadCount here because it has been tested above */ - if (unreadOnly) { - unreadCount = numrows; - } - if (option) bctbx_free(option); - return numrows; -} - -// ----------------------------------------------------------------------------- - -void ChatRoomPrivate::sendIsComposingNotification () { - L_Q(ChatRoom); - LinphoneImNotifPolicy *policy = linphone_core_get_im_notif_policy(core); - if (linphone_im_notif_policy_get_send_is_composing(policy)) { - LinphoneProxyConfig *proxy = linphone_core_lookup_known_proxy(core, peerAddress); - const char *identity = nullptr; - - if (proxy) - identity = linphone_address_as_string(linphone_proxy_config_get_identity_address(proxy)); - else - identity = linphone_core_get_primary_contact(core); - - /* Sending out of call */ - SalOp *op = sal_op_new(core->sal); - linphone_configure_op(core, op, peerAddress, nullptr, lp_config_get_int(core->config, "sip", "chat_msg_with_contact", 0)); - string content = isComposingHandler.marshal(isComposing); - if (!content.empty()) { - int retval = -1; - LinphoneAddress *fromAddr = linphone_address_new(identity); - LinphoneChatMessage *msg = q->createMessage(content); - linphone_chat_message_set_from_address(msg, fromAddr); - linphone_chat_message_set_to_address(msg, peerAddress); - linphone_chat_message_set_content_type(msg, "application/im-iscomposing+xml"); - - LinphoneImEncryptionEngine *imee = linphone_core_get_im_encryption_engine(core); - if (imee) { - LinphoneImEncryptionEngineCbs *imeeCbs = linphone_im_encryption_engine_get_callbacks(imee); - LinphoneImEncryptionEngineCbsOutgoingMessageCb cbProcessOutgoingMessage = linphone_im_encryption_engine_cbs_get_process_outgoing_message(imeeCbs); - if (cbProcessOutgoingMessage) { - retval = cbProcessOutgoingMessage(imee, cBackPointer, msg); - } - } - - if (retval <= 0) { - sal_message_send(op, identity, peer.c_str(), msg->content_type, msg->message, nullptr); - } - - linphone_chat_message_unref(msg); - linphone_address_unref(fromAddr); - sal_op_unref(op); - } - } -} - -// ----------------------------------------------------------------------------- - -/** - * DB layout: - * - * | 0 | storage_id - * | 1 | localContact - * | 2 | remoteContact - * | 3 | direction flag (LinphoneChatMessageDir) - * | 4 | message (text content of the message) - * | 5 | time (unused now, used to be string-based timestamp, replaced by the utc timestamp) - * | 6 | read flag (no longer used, replaced by the LinphoneChatMessageStateDisplayed state) - * | 7 | status (LinphoneChatMessageState) - * | 8 | external body url (deprecated file transfer system) - * | 9 | utc timestamp - * | 10 | app data text - * | 11 | linphone content id (LinphoneContent describing a file transfer) - * | 12 | message id (used for IMDN) - * | 13 | content type (of the message field [must be text representable]) - * | 14 | secured flag - */ -int ChatRoomPrivate::createChatMessageFromDb (int argc, char **argv, char **colName) { - L_Q(ChatRoom); - unsigned int storageId = (unsigned int)atoi(argv[0]); - - /* Check if the message exists in the weak messages list, in which case we should return that one. */ - LinphoneChatMessage *newMessage = getWeakMessage(storageId); - if (!newMessage) { - /* Check if the message exists in the transient list, in which case we should return that one. */ - newMessage = getTransientMessage(storageId); - } - if (!newMessage) { - newMessage = q->createMessage(argv[4] ? argv[4] : ""); - - if (atoi(argv[3]) == LinphoneChatMessageIncoming) { - newMessage->dir = LinphoneChatMessageIncoming; - linphone_chat_message_set_from(newMessage, peerAddress); - newMessage->to = nullptr; /* Will be filled at the end */ - } else { - newMessage->dir = LinphoneChatMessageOutgoing; - newMessage->from = nullptr; /* Will be filled at the end */ - linphone_chat_message_set_to(newMessage, peerAddress); - } - - newMessage->time = (time_t)atol(argv[9]); - newMessage->is_read = atoi(argv[6]); - newMessage->state = static_cast(atoi(argv[7])); - newMessage->storage_id = storageId; - newMessage->external_body_url = ms_strdup(argv[8]); - newMessage->appdata = ms_strdup(argv[10]); - newMessage->message_id = ms_strdup(argv[12]); - linphone_chat_message_set_content_type(newMessage, argv[13]); - newMessage->is_secured = (bool_t)atoi(argv[14]); - - if (argv[11]) { - int id = atoi(argv[11]); - if (id >= 0) - linphone_chat_message_fetch_content_from_database(core->db, newMessage, id); - } - - /* Fix content type for old messages that were stored without it */ - if (!newMessage->content_type) { - if (newMessage->file_transfer_information) { - newMessage->content_type = ms_strdup("application/vnd.gsma.rcs-ft-http+xml"); - } else if (newMessage->external_body_url) { - newMessage->content_type = ms_strdup("message/external-body"); - } else { - newMessage->content_type = ms_strdup("text/plain"); - } - } - - /* Add the new message to the weak messages list. */ - addWeakMessage(newMessage); - } - messages.push_front(newMessage); - return 0; -} - -void ChatRoomPrivate::onWeakMessageDestroyed (LinphoneChatMessage *messageBeingDestroyed) { - auto iter = find(weakMessages.begin(), weakMessages.end(), messageBeingDestroyed); - if (iter != transientMessages.end()) - weakMessages.erase(iter); -} - -LinphoneChatMessage *ChatRoomPrivate::getTransientMessage (unsigned int storageId) const { - for (auto it = transientMessages.begin(); it != transientMessages.end(); it++) { - if (linphone_chat_message_get_storage_id(*it) == storageId) - return linphone_chat_message_ref(*it); - } - return nullptr; -} - -LinphoneChatMessage *ChatRoomPrivate::getWeakMessage (unsigned int storageId) const { - for (auto it = weakMessages.begin(); it != weakMessages.end(); it++) { - if (linphone_chat_message_get_storage_id(*it) == storageId) - return linphone_chat_message_ref(*it); - } - return nullptr; -} - -int ChatRoomPrivate::sqlRequest (sqlite3 *db, const string &stmt) { - char *errmsg = nullptr; - int ret = sqlite3_exec(db, stmt.c_str(), nullptr, nullptr, &errmsg); - if (ret != SQLITE_OK) { - lError() << "ChatRoomPrivate::sqlRequest: statement " << stmt << " -> error sqlite3_exec(): " << errmsg; - sqlite3_free(errmsg); - } - return ret; -} - -void ChatRoomPrivate::sqlRequestMessage (sqlite3 *db, const string &stmt) { - char *errmsg = nullptr; - int ret = sqlite3_exec(db, stmt.c_str(), createChatMessageFromDb, this, &errmsg); - if (ret != SQLITE_OK) { - lError() << "Error in creation: " << errmsg; - sqlite3_free(errmsg); - } -} - -list ChatRoomPrivate::findMessages (const string &messageId) { - if (!core->db) - return list(); - char *peer = linphone_address_as_string_uri_only(peerAddress); - char *buf = sqlite3_mprintf("SELECT * FROM history WHERE remoteContact = %Q AND messageId = %Q", peer, messageId.c_str()); - messages.clear(); - sqlRequestMessage(core->db, buf); - sqlite3_free(buf); - ms_free(peer); - list result = messages; - messages.clear(); - return result; -} - -/** - * TODO: Should be handled directly by the LinphoneChatMessage object! - */ -void ChatRoomPrivate::storeOrUpdateMessage (LinphoneChatMessage *msg) { - if (msg->storage_id != 0) { - /* The message has already been stored (probably because of file transfer), update it */ - linphone_chat_message_store_update(msg); - } else { - /* Store the new message */ - msg->storage_id = linphone_chat_message_store(msg); - } -} - -// ----------------------------------------------------------------------------- - -LinphoneReason ChatRoomPrivate::messageReceived (SalOp *op, const SalMessage *salMsg) { - L_Q(ChatRoom); - - bool increaseMsgCount = true; - LinphoneReason reason = LinphoneReasonNone; - LinphoneChatMessage *msg; - - /* Check if this is a duplicate message */ - if ((msg = q->findMessageWithDirection(sal_op_get_call_id(op), LinphoneChatMessageIncoming))) { - reason = core->chat_deny_code; - if (msg) - linphone_chat_message_unref(msg); - return reason; - } - - msg = q->createMessage(salMsg->text ? salMsg->text : ""); - linphone_chat_message_set_content_type(msg, salMsg->content_type); - linphone_chat_message_set_from(msg, peerAddress); - - LinphoneAddress *to = sal_op_get_to(op) ? linphone_address_new(sal_op_get_to(op)) : linphone_address_new(linphone_core_get_identity(core)); - msg->to = to; - msg->time = salMsg->time; - msg->state = LinphoneChatMessageStateDelivered; - msg->dir = LinphoneChatMessageIncoming; - msg->message_id = ms_strdup(sal_op_get_call_id(op)); - - const SalCustomHeader *ch = sal_op_get_recv_custom_header(op); - if (ch) - msg->custom_headers = sal_custom_header_clone(ch); - if (salMsg->url) - linphone_chat_message_set_external_body_url(msg, salMsg->url); - - int retval = -1; - LinphoneImEncryptionEngine *imee = core->im_encryption_engine; - if (imee) { - LinphoneImEncryptionEngineCbs *imeeCbs = linphone_im_encryption_engine_get_callbacks(imee); - LinphoneImEncryptionEngineCbsIncomingMessageCb cbProcessIncomingMessage = linphone_im_encryption_engine_cbs_get_process_incoming_message(imeeCbs); - if (cbProcessIncomingMessage) { - retval = cbProcessIncomingMessage(imee, cBackPointer, msg); - if (retval == 0) { - msg->is_secured = TRUE; - } else if (retval > 0) { - /* Unable to decrypt message */ - linphone_core_notify_message_received_unable_decrypt(core, cBackPointer, msg); - reason = linphone_error_code_to_reason(retval); - linphone_chat_message_send_delivery_notification(msg, reason); - /* Return LinphoneReasonNone to avoid flexisip resending us a message we can't decrypt */ - reason = LinphoneReasonNone; - goto end; - } - } - } - - if ((retval <= 0) && (linphone_core_is_content_type_supported(core, msg->content_type) == FALSE)) { - retval = 415; - lError() << "Unsupported MESSAGE (content-type " << msg->content_type << " not recognized)"; - } - - if (retval > 0) { - reason = linphone_error_code_to_reason(retval); - linphone_chat_message_send_delivery_notification(msg, reason); - goto end; - } - - if (ContentType::isFileTransfer(msg->content_type)) { - create_file_transfer_information_from_vnd_gsma_rcs_ft_http_xml(msg); - linphone_chat_message_set_to_be_stored(msg, TRUE); - } else if (ContentType::isImIsComposing(msg->content_type)) { - isComposingReceived(msg->message); - linphone_chat_message_set_to_be_stored(msg, FALSE); - increaseMsgCount = FALSE; - if (lp_config_get_int(core->config, "sip", "deliver_imdn", 0) != 1) { - goto end; - } - } else if (ContentType::isImdn(msg->content_type)) { - imdnReceived(msg->message); - linphone_chat_message_set_to_be_stored(msg, FALSE); - increaseMsgCount = FALSE; - if (lp_config_get_int(core->config, "sip", "deliver_imdn", 0) != 1) { - goto end; - } - } else if (ContentType::isText(msg->content_type)) { - linphone_chat_message_set_to_be_stored(msg, TRUE); - } - - if (increaseMsgCount) { - if (unreadCount < 0) - unreadCount = 1; - else - unreadCount++; - /* Mark the message as pending so that if linphone_core_chat_room_mark_as_read() is called - in the linphone_chat_room_message_received() callback, it will effectively be marked as - being read before being stored. */ - pendingMessage = msg; - } - - chatMessageReceived(msg); - - if (linphone_chat_message_get_to_be_stored(msg)) { - msg->storage_id = linphone_chat_message_store(msg); - } - - pendingMessage = nullptr; - -end: - if (msg) - linphone_chat_message_unref(msg); - return reason; -} - -void ChatRoomPrivate::realtimeTextReceived (uint32_t character, LinphoneCall *call) { - L_Q(ChatRoom); - const uint32_t new_line = 0x2028; - const uint32_t crlf = 0x0D0A; - const uint32_t lf = 0x0A; - - if (call && linphone_call_params_realtime_text_enabled(linphone_call_get_current_params(call))) { - LinphoneChatMessageCharacter *cmc = bctbx_new0(LinphoneChatMessageCharacter, 1); - - if (!pendingMessage) - pendingMessage = q->createMessage(""); - - cmc->value = character; - cmc->has_been_read = FALSE; - receivedRttCharacters.push_back(cmc); - - remoteIsComposing = true; - linphone_core_notify_is_composing_received(core, cBackPointer); - - if ((character == new_line) || (character == crlf) || (character == lf)) { - /* End of message */ - lDebug() << "New line received, forge a message with content " << pendingMessage->message; - linphone_chat_message_set_from(pendingMessage, peerAddress); - if (pendingMessage->to) - linphone_address_unref(pendingMessage->to); - pendingMessage->to = call->dest_proxy - ? linphone_address_clone(call->dest_proxy->identity_address) - : linphone_address_new(linphone_core_get_identity(core)); - pendingMessage->time = ms_time(0); - pendingMessage->state = LinphoneChatMessageStateDelivered; - pendingMessage->dir = LinphoneChatMessageIncoming; - - if (lp_config_get_int(core->config, "misc", "store_rtt_messages", 1) == 1) - storeOrUpdateMessage(pendingMessage); - - if (unreadCount < 0) unreadCount = 1; - else unreadCount++; - - chatMessageReceived(pendingMessage); - linphone_chat_message_unref(pendingMessage); - pendingMessage = nullptr; - for (auto it = receivedRttCharacters.begin(); it != receivedRttCharacters.end(); it++) - ms_free(*it); - receivedRttCharacters.clear(); - } else { - char *value = Utils::utf8ToChar(character); - pendingMessage->message = ms_strcat_printf(pendingMessage->message, value); - lDebug() << "Received RTT character: " << value << " (" << character << "), pending text is " << pendingMessage->message; - delete value; - } - } -} - -// ----------------------------------------------------------------------------- - -void ChatRoomPrivate::chatMessageReceived (LinphoneChatMessage *msg) { - if (msg->message) { - /* Legacy API */ - linphone_core_notify_text_message_received(core, cBackPointer, msg->from, msg->message); - } - linphone_core_notify_message_received(core, cBackPointer, msg); - if (!ContentType::isImdn(msg->content_type) && !ContentType::isImIsComposing(msg->content_type)) { - remoteIsComposing = false; - linphone_core_notify_is_composing_received(core, cBackPointer); - linphone_chat_message_send_delivery_notification(msg, LinphoneReasonNone); - } -} - -void ChatRoomPrivate::imdnReceived (const string &text) { - L_Q(ChatRoom); - Imdn::parse(*q, text); -} - -void ChatRoomPrivate::isComposingReceived (const string &text) { - isComposingHandler.parse(text); -} - -// ----------------------------------------------------------------------------- - -void ChatRoomPrivate::isComposingStateChanged (bool isComposing) { - this->isComposing = isComposing; - sendIsComposingNotification(); -} - -void ChatRoomPrivate::isRemoteComposingStateChanged (bool isComposing) { - remoteIsComposing = isComposing; - linphone_core_notify_is_composing_received(core, cBackPointer); -} - -void ChatRoomPrivate::isComposingRefreshNeeded () { - sendIsComposingNotification(); -} - -// ============================================================================= - -ChatRoom::ChatRoom (LinphoneCore *core, LinphoneAddress *peerAddress) : Object(*new ChatRoomPrivate(core)) { - L_D(ChatRoom); - d->peerAddress = peerAddress; - char *peerStr = linphone_address_as_string(d->peerAddress); - d->peer = peerStr; - ms_free(peerStr); -} - -// ----------------------------------------------------------------------------- - -void ChatRoom::compose () { - L_D(ChatRoom); - if (!d->isComposing) { - d->isComposing = true; - d->sendIsComposingNotification(); - d->isComposingHandler.startRefreshTimer(); - } - d->isComposingHandler.startIdleTimer(); -} - -LinphoneChatMessage *ChatRoom::createFileTransferMessage (const LinphoneContent *initialContent) { - L_D(ChatRoom); - LinphoneChatMessage *cm = belle_sip_object_new(LinphoneChatMessage); - cm->callbacks = linphone_chat_message_cbs_new(); - cm->chat_room = d->cBackPointer; - cm->message = nullptr; - cm->file_transfer_information = linphone_content_copy(initialContent); - cm->dir = LinphoneChatMessageOutgoing; - linphone_chat_message_set_to(cm, d->peerAddress); - cm->from = linphone_address_new(linphone_core_get_identity(d->core)); - /* This will be set to application/vnd.gsma.rcs-ft-http+xml when we will transfer the xml reply from server to the peers */ - cm->content_type = nullptr; - /* This will store the http request during file upload to the server */ - cm->http_request = nullptr; - cm->time = ms_time(0); - return cm; -} - -LinphoneChatMessage *ChatRoom::createMessage (const string &msg) { - L_D(ChatRoom); - LinphoneChatMessage *cm = belle_sip_object_new(LinphoneChatMessage); - cm->state = LinphoneChatMessageStateIdle; - cm->callbacks = linphone_chat_message_cbs_new(); - cm->chat_room = d->cBackPointer; - cm->message = msg.empty() ? nullptr : ms_strdup(msg.c_str()); - cm->content_type = ms_strdup("text/plain"); - cm->file_transfer_information = nullptr; /* this property is used only when transfering file */ - cm->http_request = nullptr; - cm->time = ms_time(0); - cm->is_secured = FALSE; - return cm; -} - -void ChatRoom::deleteHistory () { - L_D(ChatRoom); - if (!d->core->db) return; - char *peer = linphone_address_as_string_uri_only(d->peerAddress); - char *buf = sqlite3_mprintf("DELETE FROM history WHERE remoteContact = %Q;", peer); - d->sqlRequest(d->core->db, buf); - sqlite3_free(buf); - ms_free(peer); - if (d->unreadCount > 0) d->unreadCount = 0; -} - -void ChatRoom::deleteMessage (LinphoneChatMessage *msg) { - L_D(ChatRoom); - if (!d->core->db) return; - char *buf = sqlite3_mprintf("DELETE FROM history WHERE id = %u;", msg->storage_id); - d->sqlRequest(d->core->db, buf); - sqlite3_free(buf); - - /* Invalidate unread_count when we modify the database, so that next - time we need it it will be recomputed from latest database state */ - d->unreadCount = -1; -} - -LinphoneChatMessage *ChatRoom::findMessage (const string &messageId) { - L_D(ChatRoom); - LinphoneChatMessage *cm = nullptr; - list l = d->findMessages(messageId); - if (!l.empty()) { - cm = l.front(); - linphone_chat_message_ref(cm); - for (auto it = l.begin(); it != l.end(); it++) - linphone_chat_message_unref(*it); - } - return cm; -} - -LinphoneChatMessage * ChatRoom::findMessageWithDirection (const string &messageId, LinphoneChatMessageDir direction) { - L_D(ChatRoom); - LinphoneChatMessage *ret = nullptr; - list l = d->findMessages(messageId); - for (auto it = l.begin(); it != l.end(); it++) { - LinphoneChatMessage *cm = *it; - if (cm->dir == direction) { - linphone_chat_message_ref(cm); - ret = cm; - break; - } - } - if (!l.empty()) { - for (auto it = l.begin(); it != l.end(); it++) - linphone_chat_message_unref(*it); - } - return ret; -} - -uint32_t ChatRoom::getChar () const { - L_D(const ChatRoom); - if (!d->receivedRttCharacters.empty()) { - for (auto it = d->receivedRttCharacters.begin(); it != d->receivedRttCharacters.end(); it++) { - LinphoneChatMessageCharacter *cmc = *it; - if (!cmc->has_been_read) { - cmc->has_been_read = TRUE; - return cmc->value; - } - } - } - return 0; -} - -list ChatRoom::getHistory (int nbMessages) { - return getHistoryRange(0, nbMessages - 1); -} - -int ChatRoom::getHistorySize () { - L_D(ChatRoom); - return d->getMessagesCount(false); -} - -list ChatRoom::getHistoryRange (int startm, int endm) { - L_D(ChatRoom); - if (!d->core->db) return list(); - char *peer = linphone_address_as_string_uri_only(d->peerAddress); - d->messages.clear(); - - /* Since we want to append query parameters depending on arguments given, we use malloc instead of sqlite3_mprintf */ - const int bufMaxSize = 512; - char *buf = reinterpret_cast(ms_malloc(bufMaxSize)); - buf = sqlite3_snprintf(bufMaxSize - 1, buf, "SELECT * FROM history WHERE remoteContact = %Q ORDER BY id DESC", peer); - - if (startm < 0) startm = 0; - if (((endm > 0) && (endm >= startm)) || ((startm == 0) && (endm == 0))) { - char *buf2 = ms_strdup_printf("%s LIMIT %i ", buf, endm + 1 - startm); - ms_free(buf); - buf = buf2; - } else if (startm > 0) { - ms_message("%s(): end is lower than start (%d < %d). Assuming no end limit.", __FUNCTION__, endm, startm); - char *buf2 = ms_strdup_printf("%s LIMIT -1", buf); - ms_free(buf); - buf = buf2; - } - if (startm > 0) { - char *buf2 = ms_strdup_printf("%s OFFSET %i ", buf, startm); - ms_free(buf); - buf = buf2; - } - - uint64_t begin = ortp_get_cur_time_ms(); - d->sqlRequestMessage(d->core->db, buf); - uint64_t end = ortp_get_cur_time_ms(); - - if ((endm + 1 - startm) > 1) { - /* Display message only if at least 2 messages are loaded */ - ms_message("%s(): completed in %i ms", __FUNCTION__, (int)(end - begin)); - } - ms_free(buf); - - if (!d->messages.empty()) { - /* Fill local addr with core identity instead of per message */ - LinphoneAddress *localAddr = linphone_address_new(linphone_core_get_identity(d->core)); - for (auto it = d->messages.begin(); it != d->messages.end(); it++) { - LinphoneChatMessage *msg = *it; - if (msg->dir == LinphoneChatMessageOutgoing) { - if (msg->from != NULL) linphone_address_unref(msg->from); - msg->from = linphone_address_ref(localAddr); - } else { - msg->to = linphone_address_ref(localAddr); - } - } - linphone_address_unref(localAddr); - } - - list result = d->messages; - d->messages.clear(); - ms_free(peer); - return result; -} - -int ChatRoom::getUnreadMessagesCount () { - L_D(ChatRoom); - return d->getMessagesCount(true); -} - -bool ChatRoom::isRemoteComposing () const { - L_D(const ChatRoom); - return d->remoteIsComposing; -} - -void ChatRoom::markAsRead () { - L_D(ChatRoom); - - if (!d->core->db) return; - - /* Optimization: do not modify the database if no message is marked as unread */ - if (getUnreadMessagesCount() == 0) return; - - char *peer = linphone_address_as_string_uri_only(d->peerAddress); - char *buf = sqlite3_mprintf("SELECT * FROM history WHERE remoteContact = %Q AND direction = %i AND status != %i", peer, LinphoneChatMessageIncoming, LinphoneChatMessageStateDisplayed); - d->sqlRequestMessage(d->core->db, buf); - sqlite3_free(buf); - for (auto it = d->messages.begin(); it != d->messages.end(); it++) { - linphone_chat_message_send_display_notification(*it); - linphone_chat_message_unref(*it); - } - d->messages.clear(); - buf = sqlite3_mprintf("UPDATE history SET status=%i WHERE remoteContact=%Q AND direction=%i;", LinphoneChatMessageStateDisplayed, peer, LinphoneChatMessageIncoming); - d->sqlRequest(d->core->db, buf); - sqlite3_free(buf); - ms_free(peer); - - if (d->pendingMessage) { - linphone_chat_message_set_state(d->pendingMessage, LinphoneChatMessageStateDisplayed); - linphone_chat_message_send_display_notification(d->pendingMessage); - } - - d->unreadCount = 0; -} - -void ChatRoom::sendMessage (LinphoneChatMessage *msg) { - L_D(ChatRoom); - - /* Stubed rtt */ - if (d->call && linphone_call_params_realtime_text_enabled(linphone_call_get_current_params(d->call))) { - uint32_t new_line = 0x2028; - linphone_chat_message_put_char(msg, new_line); - linphone_chat_message_unref(msg); - return; - } - - msg->dir = LinphoneChatMessageOutgoing; - - /* Check if we shall upload a file to a server */ - if (msg->file_transfer_information && !msg->content_type) { - /* Open a transaction with the server and send an empty request(RCS5.1 section 3.5.4.8.3.1) */ - if (linphone_chat_room_upload_file(msg) == 0) { - /* Add to transient list only if message is going out */ - d->addTransientMessage(msg); - /* Store the message so that even if the upload is stopped, it can be done again */ - d->storeOrUpdateMessage(msg); - } else { - linphone_chat_message_unref(msg); - return; - } - } else { - SalOp *op = msg->op; - LinphoneCall *call = nullptr; - const char *identity = nullptr; - char *clearTextMessage = nullptr; - char *clearTextContentType = nullptr; - - if (msg->message) { - clearTextMessage = ms_strdup(msg->message); - } - if (msg->content_type) { - clearTextContentType = ms_strdup(msg->content_type); - } - - /* Add to transient list */ - d->addTransientMessage(msg); - msg->time = ms_time(0); - if (lp_config_get_int(d->core->config, "sip", "chat_use_call_dialogs", 0) != 0) { - call = linphone_core_get_call_by_remote_address(d->core, d->peer.c_str()); - if (call) { - if (call->state == LinphoneCallConnected || call->state == LinphoneCallStreamsRunning || - call->state == LinphoneCallPaused || call->state == LinphoneCallPausing || - call->state == LinphoneCallPausedByRemote) { - ms_message("send SIP msg through the existing call."); - op = call->op; - identity = linphone_core_find_best_identity(d->core, linphone_call_get_remote_address(call)); - } - } - } - - if (!identity) { - LinphoneProxyConfig *proxy = linphone_core_lookup_known_proxy(d->core, d->peerAddress); - if (proxy) { - identity = linphone_address_as_string(linphone_proxy_config_get_identity_address(proxy)); - } else { - identity = linphone_core_get_primary_contact(d->core); - } - } - if (msg->from) { - /* BUG: the file transfer message constructor sets the from, but doesn't do it as well as here */ - linphone_address_unref(msg->from); - } - msg->from = linphone_address_new(identity); - - int retval = -1; - LinphoneImEncryptionEngine *imee = d->core->im_encryption_engine; - if (imee) { - LinphoneImEncryptionEngineCbs *imeeCbs = linphone_im_encryption_engine_get_callbacks(imee); - LinphoneImEncryptionEngineCbsOutgoingMessageCb cbProcessOutgoingMessage = linphone_im_encryption_engine_cbs_get_process_outgoing_message(imeeCbs); - if (cbProcessOutgoingMessage) { - retval = cbProcessOutgoingMessage(imee, d->cBackPointer, msg); - if (retval == 0) { - msg->is_secured = TRUE; - } - } - } - - if (!op) { - /* Sending out of call */ - msg->op = op = sal_op_new(d->core->sal); - linphone_configure_op(d->core, op, d->peerAddress, msg->custom_headers, - lp_config_get_int(d->core->config, "sip", "chat_msg_with_contact", 0)); - sal_op_set_user_pointer(op, msg); /* If out of call, directly store msg */ - } - - if (retval > 0) { - sal_error_info_set((SalErrorInfo *)sal_op_get_error_info(op), SalReasonNotAcceptable, "SIP", retval, "Unable to encrypt IM", nullptr); - d->storeOrUpdateMessage(msg); - linphone_chat_message_update_state(msg, LinphoneChatMessageStateNotDelivered); - linphone_chat_message_unref(msg); - return; - } - - if (msg->external_body_url) { - char *content_type = ms_strdup_printf("message/external-body; access-type=URL; URL=\"%s\"", msg->external_body_url); - sal_message_send(op, identity, d->peer.c_str(), content_type, nullptr, nullptr); - ms_free(content_type); - } else { - char *peerUri = linphone_address_as_string_uri_only(d->peerAddress); - if (msg->content_type) { - sal_message_send(op, identity, d->peer.c_str(), msg->content_type, msg->message, peerUri); - } else { - sal_text_send(op, identity, d->peer.c_str(), msg->message); - } - ms_free(peerUri); - } - - if (msg->message && clearTextMessage && strcmp(msg->message, clearTextMessage) != 0) { - /* We replace the encrypted message by the original one so it can be correctly stored and displayed by the application */ - ms_free(msg->message); - msg->message = ms_strdup(clearTextMessage); - } - if (msg->content_type && clearTextContentType && (strcmp(msg->content_type, clearTextContentType) != 0)) { - /* We replace the encrypted content type by the original one */ - ms_free(msg->content_type); - msg->content_type = ms_strdup(clearTextContentType); - } - msg->message_id = ms_strdup(sal_op_get_call_id(op)); /* must be known at that time */ - d->storeOrUpdateMessage(msg); - - if (d->isComposing) - d->isComposing = false; - d->isComposingHandler.stopIdleTimer(); - d->isComposingHandler.stopRefreshTimer(); - - if (clearTextMessage) { - ms_free(clearTextMessage); - } - if (clearTextContentType) { - ms_free(clearTextContentType); - } - - if (call && call->op == op) { - /* In this case, chat delivery status is not notified, so unrefing chat message right now */ - /* Might be better fixed by delivering status, but too costly for now */ - linphone_chat_room_remove_transient_message(msg->chat_room, msg); - linphone_chat_message_unref(msg); - return; - } - } - - /* If operation failed, we should not change message state */ - if (msg->dir == LinphoneChatMessageOutgoing) { - linphone_chat_message_set_state(msg, LinphoneChatMessageStateInProgress); - } -} - -// ----------------------------------------------------------------------------- - -LinphoneCall *ChatRoom::getCall () const { - L_D(const ChatRoom); - return d->call; -} - -LinphoneCore *ChatRoom::getCore () const { - L_D(const ChatRoom); - return d->core; -} - -// ----------------------------------------------------------------------------- - -const LinphoneAddress *ChatRoom::getPeerAddress () const { - L_D(const ChatRoom); - return d->peerAddress; -} - -LINPHONE_END_NAMESPACE diff --git a/src/chat/chat-room.h b/src/chat/chat-room.h deleted file mode 100644 index 9584b3304..000000000 --- a/src/chat/chat-room.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - * chat-room.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 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef _CHAT_ROOM_H_ -#define _CHAT_ROOM_H_ - -// From coreapi -#include "private.h" - -#include - -#include "object/object.h" - -#include "linphone/types.h" - -// ============================================================================= - -LINPHONE_BEGIN_NAMESPACE - -class ChatRoomPrivate; - -class ChatRoom : public Object { -public: - ChatRoom (LinphoneCore *core, LinphoneAddress *peerAddress); - virtual ~ChatRoom () = default; - - void compose (); - LinphoneChatMessage *createFileTransferMessage (const LinphoneContent *initialContent); - LinphoneChatMessage *createMessage (const std::string &msg); - void deleteHistory (); - void deleteMessage (LinphoneChatMessage *msg); - LinphoneChatMessage * findMessage (const std::string& messageId); - LinphoneChatMessage * findMessageWithDirection (const std::string &messageId, LinphoneChatMessageDir direction); - uint32_t getChar () const; - std::list getHistory (int nbMessages); - int getHistorySize (); - std::list getHistoryRange (int startm, int endm); - int getUnreadMessagesCount (); - bool isRemoteComposing () const; - void markAsRead (); - void sendMessage (LinphoneChatMessage *msg); - - LinphoneCall *getCall () const; - LinphoneCore *getCore () const; - - const LinphoneAddress *getPeerAddress () const; - -private: - L_DECLARE_PRIVATE(ChatRoom); - L_DISABLE_COPY(ChatRoom); -}; - -LINPHONE_END_NAMESPACE - -#endif // ifndef _CHAT_ROOM_H_ diff --git a/src/chat/imdn.cpp b/src/chat/imdn.cpp deleted file mode 100644 index e0c0696ca..000000000 --- a/src/chat/imdn.cpp +++ /dev/null @@ -1,104 +0,0 @@ -/* - * imdn.cpp - * 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 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "logger/logger.h" - -#include "imdn.h" - -// ============================================================================= - -using namespace std; - -LINPHONE_BEGIN_NAMESPACE - -const string Imdn::imdnPrefix = "/imdn:imdn"; - -void Imdn::parse (ChatRoom &cr, const string &text) { - xmlparsing_context_t *xmlCtx = linphone_xmlparsing_context_new(); - xmlSetGenericErrorFunc(xmlCtx, linphone_xmlparsing_genericxml_error); - xmlCtx->doc = xmlReadDoc((const unsigned char *)text.c_str(), 0, nullptr, 0); - if (xmlCtx->doc) - parse(cr, xmlCtx); - else - lWarning() << "Wrongly formatted IMDN XML: " << xmlCtx->errorBuffer; - linphone_xmlparsing_context_destroy(xmlCtx); -} - -void Imdn::parse (ChatRoom &cr, xmlparsing_context_t *xmlCtx) { - char xpathStr[MAX_XPATH_LENGTH]; - char *messageIdStr = nullptr; - char *datetimeStr = nullptr; - if (linphone_create_xml_xpath_context(xmlCtx) < 0) - return; - - xmlXPathRegisterNs(xmlCtx->xpath_ctx, (const xmlChar *)"imdn", (const xmlChar *)"urn:ietf:params:xml:ns:imdn"); - xmlXPathObjectPtr imdnObject = linphone_get_xml_xpath_object_for_node_list(xmlCtx, imdnPrefix.c_str()); - if (imdnObject) { - if (imdnObject->nodesetval && (imdnObject->nodesetval->nodeNr >= 1)) { - snprintf(xpathStr, sizeof(xpathStr), "%s[1]/imdn:message-id", imdnPrefix.c_str()); - messageIdStr = linphone_get_xml_text_content(xmlCtx, xpathStr); - snprintf(xpathStr, sizeof(xpathStr), "%s[1]/imdn:datetime", imdnPrefix.c_str()); - datetimeStr = linphone_get_xml_text_content(xmlCtx, xpathStr); - } - xmlXPathFreeObject(imdnObject); - } - - if (messageIdStr && datetimeStr) { - LinphoneChatMessage *cm = cr.findMessageWithDirection(messageIdStr, LinphoneChatMessageOutgoing); - if (!cm) { - lWarning() << "Received IMDN for unknown message " << messageIdStr; - } else { - LinphoneImNotifPolicy *policy = linphone_core_get_im_notif_policy(cr.getCore()); - snprintf(xpathStr, sizeof(xpathStr), "%s[1]/imdn:delivery-notification/imdn:status", imdnPrefix.c_str()); - xmlXPathObjectPtr deliveryStatusObject = linphone_get_xml_xpath_object_for_node_list(xmlCtx, xpathStr); - snprintf(xpathStr, sizeof(xpathStr), "%s[1]/imdn:display-notification/imdn:status", imdnPrefix.c_str()); - xmlXPathObjectPtr displayStatusObject = linphone_get_xml_xpath_object_for_node_list(xmlCtx, xpathStr); - if (deliveryStatusObject && linphone_im_notif_policy_get_recv_imdn_delivered(policy)) { - if (deliveryStatusObject->nodesetval && (deliveryStatusObject->nodesetval->nodeNr >= 1)) { - xmlNodePtr node = deliveryStatusObject->nodesetval->nodeTab[0]; - if (node->children && node->children->name) { - if (strcmp((const char *)node->children->name, "delivered") == 0) { - linphone_chat_message_update_state(cm, LinphoneChatMessageStateDeliveredToUser); - } else if (strcmp((const char *)node->children->name, "error") == 0) { - linphone_chat_message_update_state(cm, LinphoneChatMessageStateNotDelivered); - } - } - } - xmlXPathFreeObject(deliveryStatusObject); - } - if (displayStatusObject && linphone_im_notif_policy_get_recv_imdn_displayed(policy)) { - if (displayStatusObject->nodesetval && (displayStatusObject->nodesetval->nodeNr >= 1)) { - xmlNodePtr node = displayStatusObject->nodesetval->nodeTab[0]; - if (node->children && node->children->name) { - if (strcmp((const char *)node->children->name, "displayed") == 0) { - linphone_chat_message_update_state(cm, LinphoneChatMessageStateDisplayed); - } - } - } - xmlXPathFreeObject(displayStatusObject); - } - linphone_chat_message_unref(cm); - } - } - if (messageIdStr) - linphone_free_xml_text_content(messageIdStr); - if (datetimeStr) - linphone_free_xml_text_content(datetimeStr); -} - -LINPHONE_END_NAMESPACE diff --git a/src/chat/imdn.h b/src/chat/imdn.h deleted file mode 100644 index 07584fa3f..000000000 --- a/src/chat/imdn.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * imdn.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 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef _IMDN_H_ -#define _IMDN_H_ - -#include - -#include "linphone/utils/general.h" - -#include "chat-room.h" - -#include "private.h" - -// ============================================================================= - -LINPHONE_BEGIN_NAMESPACE - -class Imdn { -public: - static void parse (ChatRoom &cr, const std::string &content); - -private: - static void parse (ChatRoom &cr, xmlparsing_context_t *xmlCtx); - -private: - static const std::string imdnPrefix; -}; - -LINPHONE_END_NAMESPACE - -#endif // ifndef _IMDN_H_ diff --git a/src/chat/is-composing-listener.h b/src/chat/is-composing-listener.h deleted file mode 100644 index 730fc9761..000000000 --- a/src/chat/is-composing-listener.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * is-composing-listener.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 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef _IS_COMPOSING_LISTENER_H_ -#define _IS_COMPOSING_LISTENER_H_ - -#include "linphone/utils/general.h" - -// ============================================================================= - -LINPHONE_BEGIN_NAMESPACE - -class IsComposingListener { -public: - virtual void isComposingStateChanged (bool isComposing) = 0; - virtual void isRemoteComposingStateChanged (bool isComposing) = 0; - virtual void isComposingRefreshNeeded () = 0; -}; - -LINPHONE_END_NAMESPACE - -#endif // ifndef _IS_COMPOSING_LISTENER_H_ diff --git a/src/chat/is-composing.cpp b/src/chat/is-composing.cpp deleted file mode 100644 index efc1c685d..000000000 --- a/src/chat/is-composing.cpp +++ /dev/null @@ -1,267 +0,0 @@ -/* - * is-composing.cpp - * 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 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "linphone/utils/utils.h" - -#include "chat-room-p.h" -#include "logger/logger.h" - -#include "is-composing.h" - -// ============================================================================= - -using namespace std; - -LINPHONE_BEGIN_NAMESPACE - -const string IsComposing::isComposingPrefix = "/xsi:isComposing"; - -// ----------------------------------------------------------------------------- - -IsComposing::IsComposing (LinphoneCore *core, IsComposingListener *listener) - : core(core), listener(listener) {} - -IsComposing::~IsComposing () { - stopTimers(); -} - -// ----------------------------------------------------------------------------- - -std::string IsComposing::marshal (bool isComposing) { - string content; - - xmlBufferPtr buf = xmlBufferCreate(); - if (!buf) { - lError() << "Error creating the XML buffer"; - return content; - } - xmlTextWriterPtr writer = xmlNewTextWriterMemory(buf, 0); - if (!writer) { - lError() << "Error creating the XML writer"; - return content; - } - - int err = xmlTextWriterStartDocument(writer, "1.0", "UTF-8", nullptr); - if (err >= 0) { - err = xmlTextWriterStartElementNS(writer, nullptr, (const xmlChar *)"isComposing", - (const xmlChar *)"urn:ietf:params:xml:ns:im-iscomposing"); - } - if (err >= 0) { - err = xmlTextWriterWriteAttributeNS(writer, (const xmlChar *)"xmlns", (const xmlChar *)"xsi", nullptr, - (const xmlChar *)"http://www.w3.org/2001/XMLSchema-instance"); - } - if (err >= 0) { - err = xmlTextWriterWriteAttributeNS(writer, (const xmlChar *)"xsi", (const xmlChar *)"schemaLocation", nullptr, - (const xmlChar *)"urn:ietf:params:xml:ns:im-composing iscomposing.xsd"); - } - if (err >= 0) { - err = xmlTextWriterWriteElement(writer, (const xmlChar *)"state", - isComposing ? (const xmlChar *)"active" : (const xmlChar *)"idle"); - } - if ((err >= 0) && isComposing) { - int refreshTimeout = lp_config_get_int(core->config, "sip", "composing_refresh_timeout", defaultRefreshTimeout); - err = xmlTextWriterWriteElement(writer, (const xmlChar *)"refresh", (const xmlChar *)Utils::toString(refreshTimeout).c_str()); - } - if (err >= 0) { - /* Close the "isComposing" element. */ - err = xmlTextWriterEndElement(writer); - } - if (err >= 0) { - err = xmlTextWriterEndDocument(writer); - } - if (err > 0) { - /* xmlTextWriterEndDocument returns the size of the content. */ - content = (char *)buf->content; - } - xmlFreeTextWriter(writer); - xmlBufferFree(buf); - return content; -} - -void IsComposing::parse (const string &text) { - xmlparsing_context_t *xmlCtx = linphone_xmlparsing_context_new(); - xmlSetGenericErrorFunc(xmlCtx, linphone_xmlparsing_genericxml_error); - xmlCtx->doc = xmlReadDoc((const unsigned char *)text.c_str(), 0, nullptr, 0); - if (xmlCtx->doc) - parse(xmlCtx); - else - lWarning() << "Wrongly formatted presence XML: " << xmlCtx->errorBuffer; - linphone_xmlparsing_context_destroy(xmlCtx); -} - -void IsComposing::startIdleTimer () { - int duration = getIdleTimerDuration(); - if (!idleTimer) { - idleTimer = sal_create_timer(core->sal, idleTimerExpired, this, - duration * 1000, "composing idle timeout"); - } else { - belle_sip_source_set_timeout(idleTimer, duration * 1000); - } -} - -void IsComposing::startRefreshTimer () { - int duration = getRefreshTimerDuration(); - if (!refreshTimer) { - refreshTimer = sal_create_timer(core->sal, refreshTimerExpired, this, - duration * 1000, "composing refresh timeout"); - } else { - belle_sip_source_set_timeout(refreshTimer, duration * 1000); - } -} - -void IsComposing::startRemoteRefreshTimer (const char *refreshStr) { - int duration = getRemoteRefreshTimerDuration(); - if (refreshStr) - duration = atoi(refreshStr); - if (!remoteRefreshTimer) { - remoteRefreshTimer = sal_create_timer(core->sal, remoteRefreshTimerExpired, this, - duration * 1000, "composing remote refresh timeout"); - } else { - belle_sip_source_set_timeout(remoteRefreshTimer, duration * 1000); - } -} - -#if 0 -void IsComposing::idleTimerExpired () { - stopRefreshTimer(); - stopIdleTimer(); -} -#endif - -void IsComposing::stopTimers () { - stopIdleTimer(); - stopRefreshTimer(); - stopRemoteRefreshTimer(); -} - -// ----------------------------------------------------------------------------- - -void IsComposing::stopIdleTimer () { - if (idleTimer) { - if (core && core->sal) - sal_cancel_timer(core->sal, idleTimer); - belle_sip_object_unref(idleTimer); - idleTimer = nullptr; - } -} - -void IsComposing::stopRefreshTimer () { - if (refreshTimer) { - if (core && core->sal) - sal_cancel_timer(core->sal, refreshTimer); - belle_sip_object_unref(refreshTimer); - refreshTimer = nullptr; - } -} - -void IsComposing::stopRemoteRefreshTimer () { - if (remoteRefreshTimer) { - if (core && core->sal) - sal_cancel_timer(core->sal, remoteRefreshTimer); - belle_sip_object_unref(remoteRefreshTimer); - remoteRefreshTimer = nullptr; - } -} - -// ----------------------------------------------------------------------------- - -int IsComposing::getIdleTimerDuration () { - return lp_config_get_int(core->config, "sip", "composing_idle_timeout", defaultIdleTimeout); -} - -int IsComposing::getRefreshTimerDuration () { - return lp_config_get_int(core->config, "sip", "composing_refresh_timeout", defaultRefreshTimeout); -} - -int IsComposing::getRemoteRefreshTimerDuration () { - return lp_config_get_int(core->config, "sip", "composing_remote_refresh_timeout", defaultRemoteRefreshTimeout); -} - -void IsComposing::parse (xmlparsing_context_t *xmlCtx) { - char xpathStr[MAX_XPATH_LENGTH]; - char *stateStr = nullptr; - char *refreshStr = nullptr; - int i; - bool state = false; - - if (linphone_create_xml_xpath_context(xmlCtx) < 0) - return; - - xmlXPathRegisterNs(xmlCtx->xpath_ctx, (const xmlChar *)"xsi", (const xmlChar *)"urn:ietf:params:xml:ns:im-iscomposing"); - xmlXPathObjectPtr isComposingObject = linphone_get_xml_xpath_object_for_node_list(xmlCtx, isComposingPrefix.c_str()); - if (isComposingObject) { - if (isComposingObject->nodesetval) { - for (i = 1; i <= isComposingObject->nodesetval->nodeNr; i++) { - snprintf(xpathStr, sizeof(xpathStr), "%s[%i]/xsi:state", isComposingPrefix.c_str(), i); - stateStr = linphone_get_xml_text_content(xmlCtx, xpathStr); - if (!stateStr) - continue; - snprintf(xpathStr, sizeof(xpathStr), "%s[%i]/xsi:refresh", isComposingPrefix.c_str(), i); - refreshStr = linphone_get_xml_text_content(xmlCtx, xpathStr); - } - } - xmlXPathFreeObject(isComposingObject); - } - - if (stateStr) { - if (strcmp(stateStr, "active") == 0) { - state = true; - startRemoteRefreshTimer(refreshStr); - } else { - stopRemoteRefreshTimer(); - } - - listener->isRemoteComposingStateChanged(state); - linphone_free_xml_text_content(stateStr); - } - if (refreshStr) - linphone_free_xml_text_content(refreshStr); -} - -int IsComposing::idleTimerExpired (unsigned int revents) { - listener->isComposingStateChanged(false); - return BELLE_SIP_STOP; -} - -int IsComposing::refreshTimerExpired (unsigned int revents) { - listener->isComposingRefreshNeeded(); - return BELLE_SIP_CONTINUE; -} - -int IsComposing::remoteRefreshTimerExpired (unsigned int revents) { - stopRemoteRefreshTimer(); - listener->isRemoteComposingStateChanged(false); - return BELLE_SIP_STOP; -} - -int IsComposing::idleTimerExpired (void *data, unsigned int revents) { - IsComposing *d = reinterpret_cast(data); - return d->idleTimerExpired(revents); -} - -int IsComposing::refreshTimerExpired (void *data, unsigned int revents) { - IsComposing *d = reinterpret_cast(data); - return d->refreshTimerExpired(revents); -} - -int IsComposing::remoteRefreshTimerExpired (void *data, unsigned int revents) { - IsComposing *d = reinterpret_cast(data); - return d->remoteRefreshTimerExpired(revents); -} - -LINPHONE_END_NAMESPACE diff --git a/src/chat/is-composing.h b/src/chat/is-composing.h deleted file mode 100644 index e219ec4f9..000000000 --- a/src/chat/is-composing.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - * is-composing.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 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef _IS_COMPOSING_H_ -#define _IS_COMPOSING_H_ - -#include - -#include "linphone/utils/general.h" - -#include "is-composing-listener.h" - -#include "private.h" - -// ============================================================================= - -LINPHONE_BEGIN_NAMESPACE - -class IsComposing { -public: - IsComposing (LinphoneCore *core, IsComposingListener *listener); - ~IsComposing (); - - std::string marshal (bool isComposing); - void parse (const std::string &content); - void startIdleTimer (); - void startRefreshTimer (); - void startRemoteRefreshTimer (const char *refreshStr); - void stopComposing (); - void stopIdleTimer (); - void stopRefreshTimer (); - void stopRemoteRefreshTimer (); - void stopTimers (); - -private: - int getIdleTimerDuration (); - int getRefreshTimerDuration (); - int getRemoteRefreshTimerDuration (); - void parse (xmlparsing_context_t *xmlCtx); - int idleTimerExpired (unsigned int revents); - int refreshTimerExpired (unsigned int revents); - int remoteRefreshTimerExpired (unsigned int revents); - - static int idleTimerExpired (void *data, unsigned int revents); - static int refreshTimerExpired (void *data, unsigned int revents); - static int remoteRefreshTimerExpired (void *data, unsigned int revents); - -private: - static const int defaultIdleTimeout = 15; - static const int defaultRefreshTimeout = 60; - static const int defaultRemoteRefreshTimeout = 120; - static const std::string isComposingPrefix; - - LinphoneCore *core = nullptr; - IsComposingListener *listener = nullptr; - belle_sip_source_t *remoteRefreshTimer = nullptr; - belle_sip_source_t *idleTimer = nullptr; - belle_sip_source_t *refreshTimer = nullptr; -}; - -LINPHONE_END_NAMESPACE - -#endif // ifndef _IS_COMPOSING_H_ diff --git a/src/cpim/header/cpim-generic-header.cpp b/src/cpim/header/cpim-generic-header.cpp index 7fb7a088f..040a17e7f 100644 --- a/src/cpim/header/cpim-generic-header.cpp +++ b/src/cpim/header/cpim-generic-header.cpp @@ -18,10 +18,9 @@ #include -#include "linphone/utils/utils.h" - #include "cpim-header-p.h" #include "cpim/parser/cpim-parser.h" +#include "utils/utils.h" #include "cpim-generic-header.h" diff --git a/src/cpim/message/cpim-message.cpp b/src/cpim/message/cpim-message.cpp index b3bc56ee9..d005efc40 100644 --- a/src/cpim/message/cpim-message.cpp +++ b/src/cpim/message/cpim-message.cpp @@ -18,10 +18,9 @@ #include -#include "linphone/utils/utils.h" - #include "cpim/parser/cpim-parser.h" #include "object/object-p.h" +#include "utils/utils.h" #include "cpim-message.h" diff --git a/src/cpim/parser/cpim-grammar.h b/src/cpim/parser/cpim-grammar.h index da0c98088..d75cbd008 100644 --- a/src/cpim/parser/cpim-grammar.h +++ b/src/cpim/parser/cpim-grammar.h @@ -19,7 +19,7 @@ #ifndef _CPIM_GRAMMAR_H_ #define _CPIM_GRAMMAR_H_ -#include "linphone/utils/general.h" +#include "utils/general.h" // ============================================================================= diff --git a/src/cpim/parser/cpim-parser.cpp b/src/cpim/parser/cpim-parser.cpp index 1cf503a66..724f4bf68 100644 --- a/src/cpim/parser/cpim-parser.cpp +++ b/src/cpim/parser/cpim-parser.cpp @@ -21,11 +21,10 @@ #include #include -#include "linphone/utils/utils.h" - #include "cpim-grammar.h" #include "logger/logger.h" #include "object/object-p.h" +#include "utils/utils.h" #include "cpim-parser.h" diff --git a/src/db/abstract/abstract-db.cpp b/src/db/abstract/abstract-db.cpp index 9345ec688..81df3a33f 100644 --- a/src/db/abstract/abstract-db.cpp +++ b/src/db/abstract/abstract-db.cpp @@ -18,7 +18,6 @@ #include "abstract-db-p.h" #include "db/provider/db-session-provider.h" -#include "logger/logger.h" #include "abstract-db.h" @@ -33,22 +32,12 @@ AbstractDb::AbstractDb (AbstractDbPrivate &p) : Object(*new AbstractDbPrivate) { bool AbstractDb::connect (Backend backend, const string ¶meters) { L_D(AbstractDb); - d->backend = backend; d->dbSession = DbSessionProvider::getInstance()->getSession( (backend == Mysql ? "mysql://" : "sqlite3://") + parameters ); - if (d->dbSession) { - try { - init(); - } catch (const exception &e) { - lWarning() << "Unable to init database: " << e.what(); - - // Reset session. - d->dbSession = DbSession(); - } - } - + if (d->dbSession) + init(); return d->dbSession; } diff --git a/src/db/events-db.cpp b/src/db/events-db.cpp index 7fdc13037..79e140e5c 100644 --- a/src/db/events-db.cpp +++ b/src/db/events-db.cpp @@ -23,10 +23,10 @@ #endif // ifdef SOCI_ENABLED #include "abstract/abstract-db-p.h" -#include "chat/chat-message.h" #include "event-log/call-event.h" #include "event-log/message-event.h" #include "logger/logger.h" +#include "message/message.h" #include "events-db.h" @@ -75,25 +75,25 @@ EventsDb::EventsDb () : AbstractDb(*new EventsDbPrivate) {} ); } - static constexpr EnumToSql messageStateToSql[] = { - { ChatMessage::Idle, "1" }, - { ChatMessage::InProgress, "2" }, - { ChatMessage::Delivered, "3" }, - { ChatMessage::NotDelivered, "4" }, - { ChatMessage::FileTransferError, "5" }, - { ChatMessage::FileTransferDone, "6" }, - { ChatMessage::DeliveredToUser, "7" }, - { ChatMessage::Displayed, "8" } + static constexpr EnumToSql messageStateToSql[] = { + { Message::Idle, "1" }, + { Message::InProgress, "2" }, + { Message::Delivered, "3" }, + { Message::NotDelivered, "4" }, + { Message::FileTransferError, "5" }, + { Message::FileTransferDone, "6" }, + { Message::DeliveredToUser, "7" }, + { Message::Displayed, "8" } }; - static constexpr const char *mapMessageStateToSql (ChatMessage::State state) { + static constexpr const char *mapMessageStateToSql (Message::State state) { return mapEnumToSql( messageStateToSql, sizeof messageStateToSql / sizeof messageStateToSql[0], state ); } - static constexpr const char *mapMessageDirectionToSql (ChatMessage::Direction direction) { - return direction == ChatMessage::Direction::Incoming ? "1" : "2"; + static constexpr const char *mapMessageDirectionToSql (Message::Direction direction) { + return direction == Message::Direction::Incoming ? "1" : "2"; } // ----------------------------------------------------------------------------- @@ -135,13 +135,13 @@ EventsDb::EventsDb () : AbstractDb(*new EventsDbPrivate) {} *session << "CREATE TABLE IF NOT EXISTS sip_address (" " id" + primaryKeyAutoIncrementStr() + "," - " value VARCHAR(255) UNIQUE NOT NULL" + " value VARCHAR(255) NOT NULL" ")"; *session << "CREATE TABLE IF NOT EXISTS event_type (" - " id TINYINT UNSIGNED," - " value VARCHAR(255) UNIQUE NOT NULL" + " id" + primaryKeyAutoIncrementStr("TINYINT") + "," + " value VARCHAR(255) NOT NULL" ")"; *session << @@ -156,14 +156,14 @@ EventsDb::EventsDb () : AbstractDb(*new EventsDbPrivate) {} *session << "CREATE TABLE IF NOT EXISTS message_state (" - " id TINYINT UNSIGNED," - " value VARCHAR(255) UNIQUE NOT NULL" + " id" + primaryKeyAutoIncrementStr("TINYINT") + "," + " state VARCHAR(255) NOT NULL" ")"; *session << "CREATE TABLE IF NOT EXISTS message_direction (" - " id TINYINT UNSIGNED," - " value VARCHAR(255) UNIQUE NOT NULL" + " id" + primaryKeyAutoIncrementStr("TINYINT") + "," + " direction VARCHAR(255) NOT NULL" ")"; *session << @@ -184,19 +184,13 @@ EventsDb::EventsDb () : AbstractDb(*new EventsDbPrivate) {} *session << "CREATE TABLE IF NOT EXISTS message_event (" " id" + primaryKeyAutoIncrementStr() + "," - " event_id INT UNSIGNED NOT NULL," " dialog_id INT UNSIGNED NOT NULL," " state_id TINYINT UNSIGNED NOT NULL," " direction_id TINYINT UNSIGNED NOT NULL," - " sender_sip_address_id INT UNSIGNED NOT NULL," " imdn_message_id VARCHAR(255) NOT NULL," // See: https://tools.ietf.org/html/rfc5438#section-6.3 + " content_type VARCHAR(255) NOT NULL," " is_secured BOOLEAN NOT NULL," - " content_type VARCHAR(255) NOT NULL," // Content type of text. (Html or text for example.) - " text TEXT," - " app_data VARCHAR(2048)," // App user data. - " FOREIGN KEY (event_id)" - " REFERENCES event(id)" - " ON DELETE CASCADE," + " app_data VARCHAR(2048)," " FOREIGN KEY (dialog_id)" " REFERENCES dialog(id)" " ON DELETE CASCADE," @@ -205,24 +199,6 @@ EventsDb::EventsDb () : AbstractDb(*new EventsDbPrivate) {} " ON DELETE CASCADE," " FOREIGN KEY (direction_id)" " REFERENCES message_direction(id)" - " ON DELETE CASCADE," - " FOREIGN KEY (sender_sip_address_id)" - " REFERENCES sip_address(id)" - " ON DELETE CASCADE" - ")"; - - *session << - "CREATE TABLE IF NOT EXISTS message_file_info (" - " id" + primaryKeyAutoIncrementStr() + "," - " message_id INT UNSIGNED NOT NULL," - " content_type VARCHAR(255) NOT NULL," // File content type. - " name VARCHAR(255) NOT NULL," // File name. - " size INT UNSIGNED NOT NULL," // File size. - " url VARCHAR(255) NOT NULL," // File url. - " key VARCHAR(4096)," - " key_size INT UNSIGNED," - " FOREIGN KEY (message_id)" - " REFERENCES message(id)" " ON DELETE CASCADE" ")"; @@ -274,11 +250,6 @@ EventsDb::EventsDb () : AbstractDb(*new EventsDbPrivate) {} } bool EventsDb::addEvent (const EventLog &eventLog) { - if (!isConnected()) { - lWarning() << "Unable to add event. Not connected."; - return false; - } - // TODO. switch (eventLog.getType()) { case EventLog::TypeNone: @@ -299,22 +270,12 @@ EventsDb::EventsDb () : AbstractDb(*new EventsDbPrivate) {} } bool EventsDb::deleteEvent (const EventLog &eventLog) { - if (!isConnected()) { - lWarning() << "Unable to delete event. Not connected."; - return false; - } - // TODO. (void)eventLog; return true; } void EventsDb::cleanEvents (FilterMask mask) { - if (!isConnected()) { - lWarning() << "Unable to clean events. Not connected."; - return; - } - // TODO. (void)mask; } @@ -322,11 +283,6 @@ EventsDb::EventsDb () : AbstractDb(*new EventsDbPrivate) {} int EventsDb::getEventsCount (FilterMask mask) const { L_D(const EventsDb); - if (!isConnected()) { - lWarning() << "Unable to get events count. Not connected."; - return 0; - } - string query = "SELECT COUNT(*) FROM event" + buildSqlEventFilter({ MessageFilter, CallFilter, ConferenceFilter }, mask); int count = 0; @@ -344,11 +300,6 @@ EventsDb::EventsDb () : AbstractDb(*new EventsDbPrivate) {} int EventsDb::getMessagesCount (const string &remoteAddress) const { L_D(const EventsDb); - if (!isConnected()) { - lWarning() << "Unable to get messages count. Not connected."; - return 0; - } - string query = "SELECT COUNT(*) FROM message_event"; if (!remoteAddress.empty()) query += " WHERE dialog_id = (" @@ -371,11 +322,6 @@ EventsDb::EventsDb () : AbstractDb(*new EventsDbPrivate) {} int EventsDb::getUnreadMessagesCount (const string &remoteAddress) const { L_D(const EventsDb); - if (!isConnected()) { - lWarning() << "Unable to get unread messages count. Not connected."; - return 0; - } - string query = "SELECT COUNT(*) FROM message_event"; if (!remoteAddress.empty()) query += " WHERE dialog_id = (" @@ -383,8 +329,8 @@ EventsDb::EventsDb () : AbstractDb(*new EventsDbPrivate) {} " SELECT id FROM sip_address WHERE value = :remote_address" " )" " )" - " AND direction_id = " + string(mapMessageDirectionToSql(ChatMessage::Incoming)) + - " AND state_id = " + string(mapMessageStateToSql(ChatMessage::Displayed)); + " AND direction_id = " + string(mapMessageDirectionToSql(Message::Incoming)) + + " AND state_id = " + string(mapMessageStateToSql(Message::Displayed)); int count = 0; L_BEGIN_LOG_EXCEPTION @@ -398,11 +344,6 @@ EventsDb::EventsDb () : AbstractDb(*new EventsDbPrivate) {} } list> EventsDb::getHistory (const string &remoteAddress, int nLast, FilterMask mask) const { - if (!isConnected()) { - lWarning() << "Unable to get history. Not connected."; - return list>(); - } - // TODO. (void)remoteAddress; (void)nLast; @@ -411,11 +352,6 @@ EventsDb::EventsDb () : AbstractDb(*new EventsDbPrivate) {} } list> EventsDb::getHistory (const string &remoteAddress, int begin, int end, FilterMask mask) const { - if (!isConnected()) { - lWarning() << "Unable to get history. Not connected."; - return list>(); - } - // TODO. (void)remoteAddress; (void)begin; @@ -425,11 +361,6 @@ EventsDb::EventsDb () : AbstractDb(*new EventsDbPrivate) {} } void EventsDb::cleanHistory (const string &remoteAddress) { - if (!isConnected()) { - lWarning() << "Unable to clean history. Not connected."; - return; - } - // TODO. (void)remoteAddress; } diff --git a/src/enums.h b/src/enums.h deleted file mode 100644 index aab71c83d..000000000 --- a/src/enums.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * enums.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 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef _ENUMS_H_ -#define _ENUMS_H_ - -#include "linphone/utils/general.h" - -// ============================================================================= - -LINPHONE_BEGIN_NAMESPACE - -enum class Transport { - Udp, - Tcp, - Tls, - Dtls -}; - -LINPHONE_END_NAMESPACE - -#endif // ifndef _ENUMS_H_ diff --git a/src/event-log/conference-event.cpp b/src/event-log/conference-event.cpp index 16486a929..cfb4ca69c 100644 --- a/src/event-log/conference-event.cpp +++ b/src/event-log/conference-event.cpp @@ -16,7 +16,6 @@ * along with this program. If not, see . */ -#include "address/address.h" #include "conference-event-p.h" #include "conference-event.h" @@ -32,7 +31,8 @@ ConferenceEvent::ConferenceEvent (Type type, const shared_ptr &ad L_D(ConferenceEvent); L_ASSERT(type == TypeConferenceCreated || type == TypeConferenceDestroyed); L_ASSERT(address); - d->address = make_shared
(*address); + // TODO: Duplicate address. + d->address = address; } ConferenceEvent::ConferenceEvent (const ConferenceEvent &src) : ConferenceEvent(src.getType(), src.getAddress()) {} @@ -41,22 +41,24 @@ ConferenceEvent::ConferenceEvent (ConferenceEventPrivate &p, Type type, const sh EventLog(p, type) { L_D(ConferenceEvent); L_ASSERT(address); - d->address = make_shared
(*address); + // TODO: Duplicate address. + d->address = address; } ConferenceEvent &ConferenceEvent::operator= (const ConferenceEvent &src) { L_D(ConferenceEvent); if (this != &src) { EventLog::operator=(src); - d->address = make_shared
(*src.getPrivate()->address); + // TODO: Duplicate address. + d->address = src.getPrivate()->address; } return *this; } shared_ptr ConferenceEvent::getAddress () const { - L_D(const ConferenceEvent); - return d->address; + // TODO. + return nullptr; } LINPHONE_END_NAMESPACE diff --git a/src/event-log/conference-participant-event.cpp b/src/event-log/conference-participant-event.cpp index d1d647f75..0095da63a 100644 --- a/src/event-log/conference-participant-event.cpp +++ b/src/event-log/conference-participant-event.cpp @@ -16,7 +16,6 @@ * along with this program. If not, see . */ -#include "address/address.h" #include "conference-event-p.h" #include "conference-participant-event.h" @@ -47,7 +46,8 @@ ConferenceParticipantEvent::ConferenceParticipantEvent ( type == TypeConferenceParticipantUnsetAdmin ); L_ASSERT(participantAddress); - d->participantAddress = make_shared
(*participantAddress); + // TODO: Duplicate address. + d->participantAddress = participantAddress; } ConferenceParticipantEvent::ConferenceParticipantEvent (const ConferenceParticipantEvent &src) : @@ -57,15 +57,16 @@ ConferenceParticipantEvent &ConferenceParticipantEvent::operator= (const Confere L_D(ConferenceParticipantEvent); if (this != &src) { ConferenceEvent::operator=(src); - d->participantAddress = make_shared
(*src.getPrivate()->participantAddress); + // TODO: Duplicate address. + d->participantAddress = src.getPrivate()->participantAddress; } return *this; } shared_ptr ConferenceParticipantEvent::getParticipantAddress () const { - L_D(const ConferenceParticipantEvent); - return d->participantAddress; + // TODO. + return nullptr; } LINPHONE_END_NAMESPACE diff --git a/include/linphone/enums/event-log-enums.h b/src/event-log/event-log-enums.h similarity index 96% rename from include/linphone/enums/event-log-enums.h rename to src/event-log/event-log-enums.h index 9a6f41e66..878d1644b 100644 --- a/include/linphone/enums/event-log-enums.h +++ b/src/event-log/event-log-enums.h @@ -19,7 +19,7 @@ #ifndef _EVENT_LOG_ENUMS_H_ #define _EVENT_LOG_ENUMS_H_ -#include "linphone/utils/enum-generator.h" +#include "utils/enum-generator.h" // ============================================================================= diff --git a/src/event-log/event-log.h b/src/event-log/event-log.h index 1ccd6c9a0..831fca24f 100644 --- a/src/event-log/event-log.h +++ b/src/event-log/event-log.h @@ -19,9 +19,8 @@ #ifndef _EVENT_LOG_H_ #define _EVENT_LOG_H_ -#include "linphone/enums/event-log-enums.h" - #include "object/clonable-object.h" +#include "event-log-enums.h" // ============================================================================= diff --git a/src/logger/logger.h b/src/logger/logger.h index daaa0b6a9..2314a9ea9 100644 --- a/src/logger/logger.h +++ b/src/logger/logger.h @@ -51,11 +51,11 @@ private: LINPHONE_END_NAMESPACE -#define lDebug() LINPHONE_NAMESPACE::Logger(LINPHONE_NAMESPACE::Logger::Debug).getOutput() -#define lInfo() LINPHONE_NAMESPACE::Logger(LINPHONE_NAMESPACE::Logger::Info).getOutput() -#define lWarning() LINPHONE_NAMESPACE::Logger(LINPHONE_NAMESPACE::Logger::Warning).getOutput() -#define lError() LINPHONE_NAMESPACE::Logger(LINPHONE_NAMESPACE::Logger::Error).getOutput() -#define lFatal() LINPHONE_NAMESPACE::Logger(LINPHONE_NAMESPACE::Logger::Fatal).getOutput() +#define lDebug() LINPHONE_NAMESPACE::Logger(Logger::Debug).getOutput() +#define lInfo() LINPHONE_NAMESPACE::Logger(Logger::Info).getOutput() +#define lWarning() LINPHONE_NAMESPACE::Logger(Logger::Warning).getOutput() +#define lError() LINPHONE_NAMESPACE::Logger(Logger::Error).getOutput() +#define lFatal() LINPHONE_NAMESPACE::Logger(Logger::Fatal).getOutput() #define L_BEGIN_LOG_EXCEPTION try { #define L_END_LOG_EXCEPTION \ diff --git a/src/chat/chat-message.cpp b/src/message/message.cpp similarity index 53% rename from src/chat/chat-message.cpp rename to src/message/message.cpp index 1e6a987ad..a4e907426 100644 --- a/src/chat/chat-message.cpp +++ b/src/message/message.cpp @@ -1,5 +1,5 @@ /* - * chat-message.cpp + * message.cpp * Copyright (C) 2017 Belledonne Communications SARL * * This program is free software: you can redistribute it and/or modify @@ -21,7 +21,7 @@ #include "db/events-db.h" #include "object/object-p.h" -#include "chat-message.h" +#include "message.h" // ============================================================================= @@ -29,10 +29,10 @@ LINPHONE_BEGIN_NAMESPACE using namespace std; -class ChatMessagePrivate : public ObjectPrivate { +class MessagePrivate : public ObjectPrivate { private: weak_ptr chatRoom; - ChatMessage::Direction direction = ChatMessage::Incoming; + Message::Direction direction = Message::Incoming; // LinphoneAddress *from; // LinphoneAddress *to; shared_ptr errorInfo; @@ -44,18 +44,18 @@ private: string appData; list > contents; unordered_map customHeaders; - ChatMessage::State state = ChatMessage::Idle; + Message::State state = Message::Idle; shared_ptr eventsDb; - L_DECLARE_PUBLIC(ChatMessage); + L_DECLARE_PUBLIC(Message); }; // ----------------------------------------------------------------------------- -ChatMessage::ChatMessage (ChatMessagePrivate &p) : Object(p) {} +Message::Message (MessagePrivate &p) : Object(p) {} -shared_ptr ChatMessage::getChatRoom () const { - L_D(const ChatMessage); +shared_ptr Message::getChatRoom () const { + L_D(const Message); shared_ptr chatRoom = d->chatRoom.lock(); if (!chatRoom) { // TODO. @@ -63,110 +63,110 @@ shared_ptr ChatMessage::getChatRoom () const { return chatRoom; } -ChatMessage::Direction ChatMessage::getDirection () const { - L_D(const ChatMessage); +Message::Direction Message::getDirection () const { + L_D(const Message); return d->direction; } -shared_ptr ChatMessage::getFromAddress () const { +shared_ptr Message::getFromAddress () const { // TODO. return nullptr; } -shared_ptr ChatMessage::getToAddress () const { +shared_ptr Message::getToAddress () const { // TODO. return nullptr; } -shared_ptr ChatMessage::getLocalAddress () const { +shared_ptr Message::getLocalAddress () const { // TODO. return nullptr; } -shared_ptr ChatMessage::getRemoteAddress () const { +shared_ptr Message::getRemoteAddress () const { // TODO. return nullptr; } -ChatMessage::State ChatMessage::getState () const { - L_D(const ChatMessage); +Message::State Message::getState () const { + L_D(const Message); return d->state; } -shared_ptr ChatMessage::getErrorInfo () const { - L_D(const ChatMessage); +shared_ptr Message::getErrorInfo () const { + L_D(const Message); return d->errorInfo; } -string ChatMessage::getContentType () const { - L_D(const ChatMessage); +string Message::getContentType () const { + L_D(const Message); return d->contentType; } -string ChatMessage::getText () const { - L_D(const ChatMessage); +string Message::getText () const { + L_D(const Message); return d->text; } -void ChatMessage::setText (const string &text) { - L_D(ChatMessage); +void Message::setText (const string &text) { + L_D(Message); d->text = text; } -void ChatMessage::send () const { +void Message::send () const { // TODO. } -bool ChatMessage::containsReadableText () const { +bool Message::containsReadableText () const { // TODO: Check content type. return true; } -bool ChatMessage::isSecured () const { - L_D(const ChatMessage); +bool Message::isSecured () const { + L_D(const Message); return d->isSecured; } -time_t ChatMessage::getTime () const { - L_D(const ChatMessage); +time_t Message::getTime () const { + L_D(const Message); return d->time; } -string ChatMessage::getId () const { - L_D(const ChatMessage); +string Message::getId () const { + L_D(const Message); return d->id; } -string ChatMessage::getAppdata () const { - L_D(const ChatMessage); +string Message::getAppdata () const { + L_D(const Message); return d->appData; } -void ChatMessage::setAppdata (const string &appData) { - L_D(ChatMessage); +void Message::setAppdata (const string &appData) { + L_D(Message); d->appData = appData; } -list > ChatMessage::getContents () const { - L_D(const ChatMessage); +list > Message::getContents () const { + L_D(const Message); list > contents; for (const auto &content : d->contents) contents.push_back(content); return contents; } -void ChatMessage::addContent (const shared_ptr &content) { - L_D(ChatMessage); +void Message::addContent (const shared_ptr &content) { + L_D(Message); d->contents.push_back(content); } -void ChatMessage::removeContent (const shared_ptr &content) { - L_D(ChatMessage); +void Message::removeContent (const shared_ptr &content) { + L_D(Message); d->contents.remove(const_pointer_cast(content)); } -string ChatMessage::getCustomHeaderValue (const string &headerName) const { - L_D(const ChatMessage); +string Message::getCustomHeaderValue (const string &headerName) const { + L_D(const Message); try { return d->customHeaders.at(headerName); } catch (const exception &) { @@ -175,13 +175,13 @@ string ChatMessage::getCustomHeaderValue (const string &headerName) const { return ""; } -void ChatMessage::addCustomHeader (const string &headerName, const string &headerValue) { - L_D(ChatMessage); +void Message::addCustomHeader (const string &headerName, const string &headerValue) { + L_D(Message); d->customHeaders[headerName] = headerValue; } -void ChatMessage::removeCustomHeader (const string &headerName) { - L_D(ChatMessage); +void Message::removeCustomHeader (const string &headerName) { + L_D(Message); d->customHeaders.erase(headerName); } diff --git a/src/chat/chat-message.h b/src/message/message.h similarity index 89% rename from src/chat/chat-message.h rename to src/message/message.h index 830cf9991..3bb643315 100644 --- a/src/chat/chat-message.h +++ b/src/message/message.h @@ -1,5 +1,5 @@ /* - * chat-message.h + * message.h * Copyright (C) 2017 Belledonne Communications SARL * * This program is free software: you can redistribute it and/or modify @@ -16,11 +16,12 @@ * along with this program. If not, see . */ -#ifndef _CHAT_MESSAGE_H_ -#define _CHAT_MESSAGE_H_ +#ifndef _MESSAGE_H_ +#define _MESSAGE_H_ #include #include +#include #include "object/object.h" @@ -32,9 +33,9 @@ class Address; class ChatRoom; class Content; class ErrorInfo; -class ChatMessagePrivate; +class MessagePrivate; -class LINPHONE_PUBLIC ChatMessage : public Object { +class LINPHONE_PUBLIC Message : public Object { friend class ChatRoom; public: @@ -94,12 +95,12 @@ public: void removeCustomHeader (const std::string &headerName); private: - ChatMessage (ChatMessagePrivate &p); + Message (MessagePrivate &p); - L_DECLARE_PRIVATE(ChatMessage); - L_DISABLE_COPY(ChatMessage); + L_DECLARE_PRIVATE(Message); + L_DISABLE_COPY(Message); }; LINPHONE_END_NAMESPACE -#endif // ifndef _CHAT_MESSAGE_H_ +#endif // ifndef _MESSAGE_H_ diff --git a/src/object/clonable-object-p.h b/src/object/clonable-object-p.h index 7d507599f..8c099be7b 100644 --- a/src/object/clonable-object-p.h +++ b/src/object/clonable-object-p.h @@ -21,7 +21,7 @@ #include -#include "linphone/utils/general.h" +#include "utils/general.h" // ============================================================================= @@ -29,7 +29,6 @@ LINPHONE_BEGIN_NAMESPACE class ClonableObjectPrivate { public: - ClonableObjectPrivate () = default; virtual ~ClonableObjectPrivate () = default; protected: @@ -42,10 +41,6 @@ private: int nRefs = 0; L_DECLARE_PUBLIC(ClonableObject); - - // It's forbidden to copy directly one Clonable object private. - // To allow copy, you must define copy constructor in inherited object. - L_DISABLE_COPY(ClonableObjectPrivate); }; LINPHONE_END_NAMESPACE diff --git a/src/object/clonable-object.cpp b/src/object/clonable-object.cpp index 45412dc88..1eb46a512 100644 --- a/src/object/clonable-object.cpp +++ b/src/object/clonable-object.cpp @@ -45,7 +45,7 @@ ClonableObject::ClonableObject (ClonableObjectPrivate &p) : mPrivate(&p) { // Q-pointer must be empty. It's a constructor that takes a new private data. L_ASSERT(!mPrivate->mPublic); - mPrivate->mPublic = new remove_pointermPublic)>::type(); + mPrivate->mPublic = new remove_pointermPublic)>::type; (*mPrivate->mPublic)[mPrivate] = this; mPrivate->ref(); } diff --git a/src/object/clonable-object.h b/src/object/clonable-object.h index 34d4771c6..490c5bc71 100644 --- a/src/object/clonable-object.h +++ b/src/object/clonable-object.h @@ -19,7 +19,7 @@ #ifndef _CLONABLE_OBJECT_H_ #define _CLONABLE_OBJECT_H_ -#include "linphone/utils/general.h" +#include "utils/general.h" // ============================================================================= diff --git a/src/object/object-p.h b/src/object/object-p.h index f8c378a7d..ca9111eac 100644 --- a/src/object/object-p.h +++ b/src/object/object-p.h @@ -19,7 +19,7 @@ #ifndef _OBJECT_P_H_ #define _OBJECT_P_H_ -#include "linphone/utils/general.h" +#include "utils/general.h" // ============================================================================= diff --git a/src/object/object.h b/src/object/object.h index f49b0b4f8..d3cc22808 100644 --- a/src/object/object.h +++ b/src/object/object.h @@ -19,7 +19,7 @@ #ifndef _OBJECT_H_ #define _OBJECT_H_ -#include "linphone/utils/general.h" +#include "utils/general.h" // ============================================================================= diff --git a/src/utils/content-type.cpp b/src/utils/content-type.cpp deleted file mode 100644 index ee1aac657..000000000 --- a/src/utils/content-type.cpp +++ /dev/null @@ -1,43 +0,0 @@ -/* - * content-type.cpp - * 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 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "content-type.h" - -// ============================================================================= - -using namespace std; - -LINPHONE_BEGIN_NAMESPACE - -bool ContentType::isFileTransfer (const string &contentType) { - return "application/vnd.gsma.rcs-ft-http+xml" == contentType; -} - -bool ContentType::isImIsComposing (const string &contentType) { - return "application/im-iscomposing+xml" == contentType; -} - -bool ContentType::isImdn (const string &contentType) { - return "message/imdn+xml" == contentType; -} - -bool ContentType::isText (const string &contentType) { - return "text/plain" == contentType; -} - -LINPHONE_END_NAMESPACE diff --git a/src/utils/content-type.h b/src/utils/content-type.h deleted file mode 100644 index e8e736bc5..000000000 --- a/src/utils/content-type.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * content-type.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 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef _CONTENT_TYPE_H_ -#define _CONTENT_TYPE_H_ - -#include - -#include "linphone/utils/general.h" - -// ============================================================================= - -LINPHONE_BEGIN_NAMESPACE - -namespace ContentType { - bool isFileTransfer (const std::string &contentType); - bool isImIsComposing (const std::string &contentType); - bool isImdn (const std::string &contentType); - bool isText (const std::string &contentType); -} - -LINPHONE_END_NAMESPACE - -#endif // ifndef _CONTENT_TYPE_H_ diff --git a/include/linphone/utils/enum-generator.h b/src/utils/enum-generator.h similarity index 96% rename from include/linphone/utils/enum-generator.h rename to src/utils/enum-generator.h index 84ea6453b..994948d57 100644 --- a/include/linphone/utils/enum-generator.h +++ b/src/utils/enum-generator.h @@ -19,7 +19,7 @@ #ifndef _ENUM_GENERATOR_H_ #define _ENUM_GENERATOR_H_ -#include "linphone/utils/magic-macros.h" +#include "magic-macros.h" // ============================================================================= diff --git a/src/utils/general.cpp b/src/utils/general.cpp index 95379f996..9ed357c03 100644 --- a/src/utils/general.cpp +++ b/src/utils/general.cpp @@ -16,10 +16,10 @@ * along with this program. If not, see . */ -#include "linphone/utils/general.h" - #include "logger/logger.h" +#include "general.h" + // ============================================================================= LINPHONE_BEGIN_NAMESPACE diff --git a/include/linphone/utils/general.h b/src/utils/general.h similarity index 92% rename from include/linphone/utils/general.h rename to src/utils/general.h index fca6c903f..fd1ebb9eb 100644 --- a/include/linphone/utils/general.h +++ b/src/utils/general.h @@ -51,14 +51,6 @@ LINPHONE_BEGIN_NAMESPACE #endif #endif -#ifndef LINPHONE_DEPRECATED - #if defined(_MSC_VER) - #define LINPHONE_DEPRECATED __declspec(deprecated) - #else - #define LINPHONE_DEPRECATED __attribute__ ((deprecated)) - #endif -#endif - // ----------------------------------------------------------------------------- #ifdef __cplusplus @@ -71,8 +63,6 @@ void l_assert (const char *condition, const char *file, int line); #define L_ASSERT(CONDITION) ((CONDITION) ? static_cast(0) : l_assert(#CONDITION, __FILE__, __LINE__)) #endif -// Allows access to private internal data. -// Gives a control to C Wrapper. #define L_DECLARE_PRIVATE(CLASS) \ inline CLASS ## Private * getPrivate() { \ return reinterpret_cast(mPrivate); \ @@ -80,8 +70,7 @@ void l_assert (const char *condition, const char *file, int line); inline const CLASS ## Private *getPrivate() const { \ return reinterpret_cast(mPrivate); \ } \ - friend class CLASS ## Private; \ - friend class Wrapper; + friend class CLASS ## Private; class ClonableObject; class ClonableObjectPrivate; diff --git a/include/linphone/utils/magic-macros.h b/src/utils/magic-macros.h similarity index 99% rename from include/linphone/utils/magic-macros.h rename to src/utils/magic-macros.h index 5c4eb2f50..95b2f9774 100644 --- a/include/linphone/utils/magic-macros.h +++ b/src/utils/magic-macros.h @@ -19,7 +19,7 @@ #ifndef _MAGIC_MACROS_H_ #define _MAGIC_MACROS_H_ -#include "linphone/utils/general.h" +#include "general.h" // ============================================================================= // Original header. diff --git a/src/utils/utils.cpp b/src/utils/utils.cpp index 1fea89566..55e8d2026 100644 --- a/src/utils/utils.cpp +++ b/src/utils/utils.cpp @@ -17,11 +17,8 @@ */ #include -#include -#include - -#include "linphone/utils/utils.h" +#include "utils.h" // ============================================================================= @@ -53,30 +50,6 @@ vector Utils::split (const string &str, const string &delimiter) { return out; } -#ifndef __ANDROID__ -#define TO_STRING_IMPL(TYPE) \ - string Utils::toString(TYPE val) { \ - return to_string(val); \ - } -#else -#define TO_STRING_IMPL(TYPE) \ - string Utils::toString(TYPE val) { \ - ostringstream os; \ - os << val; \ - return os.str(); \ - } -#endif // ifndef __ANDROID__ - -TO_STRING_IMPL(int) -TO_STRING_IMPL(long) -TO_STRING_IMPL(long long) -TO_STRING_IMPL(unsigned) -TO_STRING_IMPL(unsigned long) -TO_STRING_IMPL(unsigned long long) -TO_STRING_IMPL(float) -TO_STRING_IMPL(double) -TO_STRING_IMPL(long double) - int Utils::stoi (const string &str, size_t *idx, int base) { char *p; int v = strtol(str.c_str(), &p, base); @@ -87,30 +60,4 @@ int Utils::stoi (const string &str, size_t *idx, int base) { return v; } -char *Utils::utf8ToChar (uint32_t ic) { - char *result = new char[5]; - int size = 0; - if (ic < 0x80) { - result[0] = ic; - size = 1; - } else if (ic < 0x800) { - result[1] = 0x80 + ((ic & 0x3F)); - result[0] = 0xC0 + ((ic >> 6) & 0x1F); - size = 2; - } else if (ic < 0x100000) { - result[2] = 0x80 + (ic & 0x3F); - result[1] = 0x80 + ((ic >> 6) & 0x3F); - result[0] = 0xE0 + ((ic >> 12) & 0xF); - size = 3; - } else if (ic < 0x110000) { - result[3] = 0x80 + (ic & 0x3F); - result[2] = 0x80 + ((ic >> 6) & 0x3F); - result[1] = 0x80 + ((ic >> 12) & 0x3F); - result[0] = 0xF0 + ((ic >> 18) & 0x7); - size = 4; - } - result[size] = '\0'; - return result; -} - LINPHONE_END_NAMESPACE diff --git a/include/linphone/utils/utils.h b/src/utils/utils.h similarity index 65% rename from include/linphone/utils/utils.h rename to src/utils/utils.h index 91897090c..e64dc4e7e 100644 --- a/include/linphone/utils/utils.h +++ b/src/utils/utils.h @@ -22,7 +22,7 @@ #include #include -#include "linphone/utils/general.h" +#include "general.h" // ============================================================================= @@ -37,26 +37,7 @@ namespace Utils { return split(str, std::string(1, delimiter)); } - LINPHONE_PUBLIC std::string toString (int val); - LINPHONE_PUBLIC std::string toString (long val); - LINPHONE_PUBLIC std::string toString (long long val); - LINPHONE_PUBLIC std::string toString (unsigned val); - LINPHONE_PUBLIC std::string toString (unsigned long val); - LINPHONE_PUBLIC std::string toString (unsigned long long val); - LINPHONE_PUBLIC std::string toString (float val); - LINPHONE_PUBLIC std::string toString (double val); - LINPHONE_PUBLIC std::string toString (long double val); - LINPHONE_PUBLIC int stoi (const std::string &str, size_t *idx = 0, int base = 10); - - // Return a buffer allocated with new. - LINPHONE_PUBLIC char *utf8ToChar (uint32_t ic); - - template - LINPHONE_PUBLIC const T &getEmptyConstRefObject () { - static const T object; - return object; - } } LINPHONE_END_NAMESPACE diff --git a/tester/CMakeLists.txt b/tester/CMakeLists.txt index 3cbaf88e1..60b1ab5e2 100644 --- a/tester/CMakeLists.txt +++ b/tester/CMakeLists.txt @@ -76,11 +76,6 @@ set(CERTIFICATE_CLIENT_FILES set(CERTIFICATE_FILES ${CERTIFICATE_ALT_FILES} ${CERTIFICATE_CN_FILES} ${CERTIFICATE_CLIENT_FILES}) -set(DB_FILES - db/linphone.db - db/messages.db -) - set(RC_FILES rcfiles/account_creator_rc rcfiles/assistant_create.rc @@ -151,11 +146,11 @@ set(VCARD_FILES set(OTHER_FILES tester_hosts local_tester_hosts + messages.db ) set(IOS_RESOURCES_FILES ${OTHER_FILES} - ${DB_FILES} certificates images rcfiles @@ -198,9 +193,7 @@ set(SOURCE_FILES_C ) set(SOURCE_FILES_CXX - clonable-object-tester.cpp - cpim-tester.cpp - events-db-tester.cpp + cpim_tester.cpp ) set(SOURCE_FILES_OBJC ) @@ -314,15 +307,14 @@ if (NOT ANDROID AND NOT CMAKE_SYSTEM_NAME STREQUAL "WindowsStore") ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE ) - install(FILES ${CERTIFICATE_ALT_FILES} DESTINATION "${CMAKE_INSTALL_DATADIR}/liblinphone_tester/certificates/altname") - install(FILES ${CERTIFICATE_CLIENT_FILES} DESTINATION "${CMAKE_INSTALL_DATADIR}/liblinphone_tester/certificates/client") - install(FILES ${CERTIFICATE_CN_FILES} DESTINATION "${CMAKE_INSTALL_DATADIR}/liblinphone_tester/certificates/cn") - install(FILES ${DB_FILES} DESTINATION "${CMAKE_INSTALL_DATADIR}/liblinphone_tester/db") - install(FILES ${IMAGE_FILES} DESTINATION "${CMAKE_INSTALL_DATADIR}/liblinphone_tester/images") install(FILES ${OTHER_FILES} DESTINATION "${CMAKE_INSTALL_DATADIR}/liblinphone_tester") - install(FILES ${RC_FILES} DESTINATION "${CMAKE_INSTALL_DATADIR}/liblinphone_tester/rcfiles") - install(FILES ${SIPP_FILES} DESTINATION "${CMAKE_INSTALL_DATADIR}/liblinphone_tester/sipp") install(FILES ${SOUND_FILES} DESTINATION "${CMAKE_INSTALL_DATADIR}/liblinphone_tester/sounds") + install(FILES ${SIPP_FILES} DESTINATION "${CMAKE_INSTALL_DATADIR}/liblinphone_tester/sipp") + install(FILES ${CERTIFICATE_ALT_FILES} DESTINATION "${CMAKE_INSTALL_DATADIR}/liblinphone_tester/certificates/altname") + install(FILES ${CERTIFICATE_CN_FILES} DESTINATION "${CMAKE_INSTALL_DATADIR}/liblinphone_tester/certificates/cn") + install(FILES ${CERTIFICATE_CLIENT_FILES} DESTINATION "${CMAKE_INSTALL_DATADIR}/liblinphone_tester/certificates/client") + install(FILES ${RC_FILES} DESTINATION "${CMAKE_INSTALL_DATADIR}/liblinphone_tester/rcfiles") + install(FILES ${IMAGE_FILES} DESTINATION "${CMAKE_INSTALL_DATADIR}/liblinphone_tester/images") install(FILES ${VCARD_FILES} DESTINATION "${CMAKE_INSTALL_DATADIR}/liblinphone_tester/vcards") endif() endif() diff --git a/tester/call_single_tester.c b/tester/call_single_tester.c index 9d610103a..089ac77d6 100644 --- a/tester/call_single_tester.c +++ b/tester/call_single_tester.c @@ -1044,7 +1044,6 @@ static void terminate_call_with_error(void) { BC_ASSERT_STRING_EQUAL(linphone_error_info_get_phrase(rei), "Call refused for security reason"); BC_ASSERT_STRING_EQUAL(linphone_error_info_get_protocol(ei), "SIP"); } - BC_ASSERT_EQUAL(linphone_call_log_get_status(linphone_call_get_call_log(call_callee)), LinphoneCallAcceptedElsewhere, int, "%d"); BC_ASSERT_TRUE(wait_for(caller_mgr->lc,callee_mgr->lc,&caller_mgr->stat.number_of_LinphoneCallReleased,1)); @@ -1095,7 +1094,6 @@ static void cancel_call_with_error(void) { BC_ASSERT_STRING_EQUAL(linphone_error_info_get_phrase(rei), "Call has been cancelled"); BC_ASSERT_STRING_EQUAL(linphone_error_info_get_protocol(rei), "SIP"); } - BC_ASSERT_EQUAL(linphone_call_log_get_status(linphone_call_get_call_log(call_callee)), LinphoneCallDeclinedElsewhere, int, "%d"); BC_ASSERT_TRUE(wait_for(caller_mgr->lc,callee_mgr->lc,&caller_mgr->stat.number_of_LinphoneCallReleased,1)); @@ -1144,7 +1142,6 @@ static void cancel_other_device_after_accept(void) { BC_ASSERT_STRING_EQUAL(linphone_error_info_get_phrase(rei), "Call completed elsewhere"); BC_ASSERT_STRING_EQUAL(linphone_error_info_get_protocol(rei), "SIP"); } - BC_ASSERT_EQUAL(linphone_call_log_get_status(linphone_call_get_call_log(call_callee_2)), LinphoneCallAcceptedElsewhere, int, "%d"); } linphone_call_terminate(out_call); BC_ASSERT_TRUE(wait_for(caller_mgr->lc,callee_mgr->lc,&caller_mgr->stat.number_of_LinphoneCallEnd,1)); @@ -1182,12 +1179,10 @@ static void cancel_other_device_after_decline(void) { BC_ASSERT_PTR_NOT_NULL(call_callee_2); BC_ASSERT_EQUAL(linphone_call_decline(call_callee, LinphoneReasonDeclined), 0 , int, "%d"); - BC_ASSERT_TRUE(wait_for(caller_mgr->lc,callee_mgr->lc, &caller_mgr->stat.number_of_LinphoneCallEnd,1)); + BC_ASSERT_TRUE(wait_for(caller_mgr->lc,callee_mgr->lc,&caller_mgr->stat.number_of_LinphoneCallEnd,1)); BC_ASSERT_TRUE(wait_for(caller_mgr->lc,callee_mgr->lc, &caller_mgr->stat.number_of_LinphoneCallReleased, 1)); - BC_ASSERT_TRUE(wait_for(caller_mgr->lc,callee_mgr->lc, &callee_mgr->stat.number_of_LinphoneCallEnd,1)); - BC_ASSERT_TRUE(wait_for(caller_mgr->lc,callee_mgr->lc, &callee_mgr->stat.number_of_LinphoneCallReleased, 1)); - BC_ASSERT_TRUE(wait_for(caller_mgr->lc,callee_mgr_2->lc, &callee_mgr_2->stat.number_of_LinphoneCallEnd,1)); - BC_ASSERT_TRUE(wait_for(caller_mgr->lc,callee_mgr_2->lc, &callee_mgr_2->stat.number_of_LinphoneCallReleased,1)); + BC_ASSERT_TRUE(wait_for(caller_mgr->lc,callee_mgr_2->lc,&callee_mgr_2->stat.number_of_LinphoneCallEnd,1)); + BC_ASSERT_TRUE(wait_for(caller_mgr->lc,callee_mgr_2->lc,&callee_mgr_2->stat.number_of_LinphoneCallReleased,1)); rei = linphone_call_get_error_info(call_callee_2); BC_ASSERT_PTR_NOT_NULL(rei); @@ -1197,7 +1192,6 @@ static void cancel_other_device_after_decline(void) { BC_ASSERT_STRING_EQUAL(linphone_error_info_get_phrase(rei), "Busy Everywhere"); BC_ASSERT_STRING_EQUAL(linphone_error_info_get_protocol(rei), "SIP"); } - BC_ASSERT_EQUAL(linphone_call_log_get_status(linphone_call_get_call_log(call_callee_2)), LinphoneCallDeclinedElsewhere, int, "%d"); } if (out_call) linphone_call_unref(out_call); if (call_callee) linphone_call_unref(call_callee); @@ -3427,7 +3421,7 @@ static void call_redirect(void){ LinphoneCoreManager* laure = linphone_core_manager_new("laure_rc_udp"); bctbx_list_t* lcs = NULL; char *laure_url = NULL; - LinphoneCall* marie_call, *laure_call; + LinphoneCall* marie_call; lcs = bctbx_list_append(lcs,marie->lc); lcs = bctbx_list_append(lcs,pauline->lc); @@ -3452,20 +3446,16 @@ static void call_redirect(void){ /* the call should still be ringing on marie's side */ BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneCallOutgoingRinging, 1, int, "%i"); - laure_call = linphone_core_get_current_call(laure->lc); - BC_ASSERT_PTR_NOT_NULL(laure_call); - if (laure_call) { - linphone_call_accept(laure_call); + linphone_call_accept(linphone_core_get_current_call(laure->lc)); - BC_ASSERT_TRUE(wait_for_list(lcs, &marie->stat.number_of_LinphoneCallStreamsRunning, 1,5000)); - BC_ASSERT_TRUE(wait_for_list(lcs, &laure->stat.number_of_LinphoneCallStreamsRunning, 1,5000)); + BC_ASSERT_TRUE(wait_for_list(lcs, &marie->stat.number_of_LinphoneCallStreamsRunning, 1,5000)); + BC_ASSERT_TRUE(wait_for_list(lcs, &laure->stat.number_of_LinphoneCallStreamsRunning, 1,5000)); - BC_ASSERT_PTR_EQUAL(marie_call, linphone_core_get_current_call(marie->lc)); + BC_ASSERT_PTR_EQUAL(marie_call, linphone_core_get_current_call(marie->lc)); - liblinphone_tester_check_rtcp(marie, laure); + liblinphone_tester_check_rtcp(marie, laure); - end_call(laure, marie); - } + end_call(laure, marie); } bctbx_list_free(lcs); diff --git a/tester/clonable-object-tester.cpp b/tester/clonable-object-tester.cpp deleted file mode 100644 index 28264732d..000000000 --- a/tester/clonable-object-tester.cpp +++ /dev/null @@ -1,66 +0,0 @@ -/* - * clonable-object-tester.cpp - * 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 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "object/clonable-object-p.h" -#include "object/clonable-object.h" - -#include "liblinphone_tester.h" - -// ============================================================================= - -using namespace std; - -using namespace LinphonePrivate; - -// ----------------------------------------------------------------------------- - -class TestObjectPrivate : public ClonableObjectPrivate { -public: - TestObjectPrivate () = default; - - TestObjectPrivate (const TestObjectPrivate &) : TestObjectPrivate() {} -}; - -class TestObject : public ClonableObject { -public: - TestObject () : ClonableObject(*new TestObjectPrivate) {} - - TestObject (const TestObject &src) : ClonableObject(*new TestObjectPrivate(*src.getPrivate())) {} - -private: - L_DECLARE_PRIVATE(TestObject); -}; - -// ----------------------------------------------------------------------------- - -static void check_clonable_object_creation () { - TestObject *object = new TestObject(); - TestObject *object2 = new TestObject(*object); - - delete object; - delete object2; -} - -test_t clonable_object_tests[] = { - TEST_NO_TAG("Check clonable object creation", check_clonable_object_creation) -}; - -test_suite_t clonable_object_test_suite = { - "ClonableObject", NULL, NULL, liblinphone_tester_before_each, liblinphone_tester_after_each, - sizeof(clonable_object_tests) / sizeof(clonable_object_tests[0]), clonable_object_tests -}; diff --git a/tester/cpim-tester.cpp b/tester/cpim_tester.cpp similarity index 96% rename from tester/cpim-tester.cpp rename to tester/cpim_tester.cpp index 214453389..27df3690c 100644 --- a/tester/cpim-tester.cpp +++ b/tester/cpim_tester.cpp @@ -1,5 +1,5 @@ /* - * cpim-tester.cpp + * liblinphone_tester - liblinphone test suite * Copyright (C) 2017 Belledonne Communications SARL * * This program is free software: you can redistribute it and/or modify @@ -20,13 +20,13 @@ #include "liblinphone_tester.h" -// ============================================================================= - using namespace std; -using namespace LINPHONE_NAMESPACE; +using namespace LinphonePrivate; -static void parse_minimal_message () { +// ============================================================================= + +static void parse_minimal_message (void) { const string str = "Content-type: Message/CPIM\r\n" "\r\n" "Content-Type: text/plain; charset=utf-8\r\n" @@ -39,7 +39,7 @@ static void parse_minimal_message () { BC_ASSERT_STRING_EQUAL(str2.c_str(), str.c_str()); } -static void set_generic_header_name () { +static void set_generic_header_name (void) { const list > entries = { { "toto", true }, { "george.abitbol", true }, @@ -82,7 +82,7 @@ static void set_generic_header_name () { } } -static void set_generic_header_value () { +static void set_generic_header_value (void) { const list > entries = { { "MyFeatures ", true }, { "2000-12-13T13:40:00-08:00", true }, @@ -106,7 +106,7 @@ static void set_generic_header_value () { } } -static void check_core_header_names () { +static void check_core_header_names (void) { const list, string> > entries = { { make_shared(), "From" }, { make_shared(), "To" }, @@ -123,7 +123,7 @@ static void check_core_header_names () { } } -static void set_core_header_values () { +static void set_core_header_values (void) { const list, list > > > entries = { { make_shared(), { { "Winnie the Pooh ", true }, @@ -196,7 +196,7 @@ static void set_core_header_values () { } } -static void check_subject_header_language () { +static void check_subject_header_language (void) { Cpim::SubjectHeader subjectHeader; // Check for not defined language. @@ -226,7 +226,7 @@ static void check_subject_header_language () { } } -static void parse_rfc_example () { +static void parse_rfc_example (void) { const string str = "Content-type: Message/CPIM\r\n" "\r\n" "From: MR SANDERS \r\n" @@ -253,7 +253,7 @@ static void parse_rfc_example () { BC_ASSERT_STRING_EQUAL(str2.c_str(), str.c_str()); } -static void parse_message_with_generic_header_parameters () { +static void parse_message_with_generic_header_parameters (void) { const string str = "Content-type: Message/CPIM\r\n" "\r\n" "From: MR SANDERS \r\n" @@ -275,7 +275,7 @@ static void parse_message_with_generic_header_parameters () { BC_ASSERT_STRING_EQUAL(str2.c_str(), str.c_str()); } -static void build_message () { +static void build_message (void) { Cpim::Message message; if (!BC_ASSERT_FALSE(message.isValid())) return; diff --git a/tester/db/linphone.db b/tester/db/linphone.db deleted file mode 100644 index 948bb10a2d5072d623865650d9b3c5a006eefe49..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 18432 zcmeHP&u`mQ9QX4#jg#~TV_RiSQ#Du9v_{?3m9>ZoX(CI!644}Gnj(6bER(!e)*L&t zooPkdL^aq2P7@bS{0Us(0Ma;e;I*Mzrtfw;O?Qr@Mo{D-4+D#^l7yHqNBd9<2tr&brUPLqdMV2B3qU- z6I-B9%=mR`-2voB}LGtVt9rb%o5 z%9<<{OBJcOw!ECakcf+g(}>fI8op^?*9km|+H_2}tc1>^%!i7}?Q3yC6h(Ar(bXN_ zz=q@QgpjUoRa-}*pS&cOrIm8NkSVWAugL3CX01}n7s*!&aZJ~o9XQ&62y}y(RN#=)=<=1%_5hp-8tmLvN{br z82uqG*+o7s=1=y6B%qHnZxfe0G)8vg)V;@qaq5CWucl?TF$5R_2LgcCi$$Y z>nQ}uJIJIeZB3!&{_+Z43d1!0sS0o&aZ2YpOfaXSmwX$WI)}a`nQ?a7y_(H}B`#%AG zae|QlX+CePSmq}EjZz@D0F(Kejw%07z%35GhIil=d;lN8@9;f*u{(w{sSE*zfRDg9 zoIw68kT?Rf$amP*Bp@7xvnc58bPkA5!d$4*odQMBR4QM_vuGP zK79@Rh}-l|;xaq2q44hqtNx!tbq`h$^+1nmhraJtv^(|x7`n)zi)f3F^Lg$w?$d6+ z-=j6LI}4+Nc?VjLI!m;KT%A5CKVUg=Fotg2Vb{N-h*E?`m~3F=5CM- z2n*LulCUvo;M%>b7FH?P%7DZPU9}yh*{G2mltEoXITpRHqG+l`K-Ipv7R0cS+@4nc z6TxZf|1AD@kIrvQEr!4@Bf$KBmjPzt83KD40qXyV`-CH}kN2>eU8=?I=EmGS;dhrp zdBSear$>(6!ZSU2v)iLHkEAMVbBEKuDgVG4>yH*PzJA0s0VelG09K1 zh9$aMy=M5i%S6Xe2DF#@OjxF7D>kk+$*<7TrBZ2G&J_Kp8Kkvpl6+>vY31S zj#QCfqnXQUqoEMetai?KZsCP=l+AkBMhUE2KQt%y2Ouh@)iAUiZIlb+2#gY_j#*I-&~E8VEYg1ge+XLJ diff --git a/tester/events-db-tester.cpp b/tester/events-db-tester.cpp deleted file mode 100644 index bf110400f..000000000 --- a/tester/events-db-tester.cpp +++ /dev/null @@ -1,50 +0,0 @@ -/* - * events-db-tester.cpp - * 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 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "db/events-db.h" - -#include "liblinphone_tester.h" - -// ============================================================================= - -using namespace std; - -using namespace LinphonePrivate; - -// ----------------------------------------------------------------------------- - -static const string getDatabasePath () { - static const string path = string(bc_tester_get_resource_dir_prefix()) + "/db/linphone.db"; - return path; -} - -// ----------------------------------------------------------------------------- - -static void open_database () { - EventsDb eventsDb; - BC_ASSERT_TRUE(eventsDb.connect(EventsDb::Sqlite3, getDatabasePath())); -} - -test_t events_db_tests[] = { - TEST_NO_TAG("Open database", open_database) -}; - -test_suite_t events_db_test_suite = { - "EventsDb", NULL, NULL, liblinphone_tester_before_each, liblinphone_tester_after_each, - sizeof(events_db_tests) / sizeof(events_db_tests[0]), events_db_tests -}; diff --git a/tester/flexisip_tester.c b/tester/flexisip_tester.c index 324b82221..1c987a249 100644 --- a/tester/flexisip_tester.c +++ b/tester/flexisip_tester.c @@ -955,7 +955,7 @@ static void dos_module_trigger(void) { // At this point we should be banned for a minute wait_for_until(marie->lc, pauline->lc, &dummy, 1, 65000);; // Wait several seconds to ensure we are not banned anymore - BC_ASSERT_LOWER_STRICT(marie->stat.number_of_LinphoneMessageReceived, number_of_messge_to_send, int, "%d"); + BC_ASSERT_LOWER(marie->stat.number_of_LinphoneMessageReceived, number_of_messge_to_send, int, "%d"); reset_counters(&marie->stat); reset_counters(&pauline->stat); diff --git a/tester/liblinphone_tester.c b/tester/liblinphone_tester.c index 178a8347a..7421a20d0 100644 --- a/tester/liblinphone_tester.c +++ b/tester/liblinphone_tester.c @@ -171,7 +171,6 @@ static void log_handler(int lev, const char *fmt, va_list args) { } void liblinphone_tester_init(void(*ftester_printf)(int level, const char *fmt, va_list args)) { - bctbx_init_logger(FALSE); if (! log_file) { #if defined(__ANDROID__) linphone_core_set_log_handler(liblinphone_android_ortp_log_handler); diff --git a/tester/liblinphone_tester.h b/tester/liblinphone_tester.h index 8bd915e62..95c034e24 100644 --- a/tester/liblinphone_tester.h +++ b/tester/liblinphone_tester.h @@ -42,11 +42,9 @@ extern "C" { extern test_suite_t account_creator_test_suite; extern test_suite_t call_test_suite; extern test_suite_t call_video_test_suite; -extern test_suite_t clonable_object_test_suite; extern test_suite_t cpim_test_suite; extern test_suite_t dtmf_test_suite; extern test_suite_t event_test_suite; -extern test_suite_t events_db_test_suite; extern test_suite_t flexisip_test_suite; extern test_suite_t log_collection_test_suite; extern test_suite_t message_test_suite; diff --git a/tester/message_tester.c b/tester/message_tester.c index ddbf20023..1a1c3ce6d 100644 --- a/tester/message_tester.c +++ b/tester/message_tester.c @@ -161,7 +161,7 @@ void file_transfer_progress_indication(LinphoneChatMessage *msg, const LinphoneC void is_composing_received(LinphoneCore *lc, LinphoneChatRoom *room) { stats *counters = get_stats(lc); - if (linphone_chat_room_is_remote_composing(room)) { + if (room->remote_is_composing == LinphoneIsComposingActive) { counters->number_of_LinphoneIsComposingActiveReceived++; } else { counters->number_of_LinphoneIsComposingIdleReceived++; @@ -236,7 +236,7 @@ LinphoneChatMessage* create_message_from_sintel_trailer(LinphoneChatRoom *chat_r file_size = ftell(file_to_send); fseek(file_to_send, 0, SEEK_SET); - content = linphone_core_create_content(linphone_chat_room_get_core(chat_room)); + content = linphone_core_create_content(chat_room->lc); belle_sip_object_set_name(&content->base, "sintel trailer content"); linphone_content_set_type(content,"video"); linphone_content_set_subtype(content,"mkv"); @@ -262,7 +262,7 @@ LinphoneChatMessage* create_file_transfer_message_from_sintel_trailer(LinphoneCh LinphoneChatMessage* msg; char *send_filepath = bc_tester_res("sounds/sintel_trailer_opus_h264.mkv"); - content = linphone_core_create_content(linphone_chat_room_get_core(chat_room)); + content = linphone_core_create_content(chat_room->lc); belle_sip_object_set_name(&content->base, "sintel trailer content"); linphone_content_set_type(content,"video"); linphone_content_set_subtype(content,"mkv"); @@ -413,15 +413,15 @@ static void text_message_with_send_error(void) { linphone_chat_room_send_chat_message(chat_room,msg); /* check transient msg list: the msg should be in it, and should be the only one */ - BC_ASSERT_EQUAL((unsigned int)bctbx_list_size(linphone_chat_room_get_transient_messages(chat_room)), 1, unsigned int, "%u"); - BC_ASSERT_PTR_EQUAL(bctbx_list_nth_data(linphone_chat_room_get_transient_messages(chat_room),0), msg); + BC_ASSERT_EQUAL((unsigned int)bctbx_list_size(chat_room->transient_messages), 1, unsigned int, "%u"); + BC_ASSERT_PTR_EQUAL(bctbx_list_nth_data(chat_room->transient_messages,0), msg); BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneMessageNotDelivered,1)); /*BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneMessageInProgress,1, int, "%d");*/ BC_ASSERT_EQUAL(pauline->stat.number_of_LinphoneMessageReceived,0, int, "%d"); /* the msg should have been discarded from transient list after an error */ - BC_ASSERT_EQUAL((unsigned int)bctbx_list_size(linphone_chat_room_get_transient_messages(chat_room)), 0, unsigned int, "%u"); + BC_ASSERT_EQUAL((unsigned int)bctbx_list_size(chat_room->transient_messages), 0, unsigned int, "%u"); sal_set_send_error(marie->lc->sal, 0); @@ -446,8 +446,8 @@ static void text_message_with_external_body(void) { linphone_chat_room_send_chat_message(chat_room,msg); /* check transient msg list: the msg should be in it, and should be the only one */ - BC_ASSERT_EQUAL((unsigned int)bctbx_list_size(linphone_chat_room_get_transient_messages(chat_room)), 1, unsigned int, "%u"); - BC_ASSERT_PTR_EQUAL(bctbx_list_nth_data(linphone_chat_room_get_transient_messages(chat_room),0), msg); + BC_ASSERT_EQUAL((unsigned int)bctbx_list_size(chat_room->transient_messages), 1, unsigned int, "%u"); + BC_ASSERT_PTR_EQUAL(bctbx_list_nth_data(chat_room->transient_messages,0), msg); BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneMessageReceived,1)); BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneMessageDelivered,1)); @@ -455,7 +455,7 @@ static void text_message_with_external_body(void) { BC_ASSERT_EQUAL(pauline->stat.number_of_LinphoneMessageInProgress,1, int, "%d"); BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneMessageExtBodyReceived,1, int, "%d"); - BC_ASSERT_EQUAL((unsigned int)bctbx_list_size(linphone_chat_room_get_transient_messages(chat_room)), 0, unsigned int, "%u"); + BC_ASSERT_EQUAL((unsigned int)bctbx_list_size(chat_room->transient_messages), 0, unsigned int, "%u"); linphone_core_manager_destroy(marie); linphone_core_manager_destroy(pauline); diff --git a/tester/db/messages.db b/tester/messages.db similarity index 100% rename from tester/db/messages.db rename to tester/messages.db diff --git a/tester/presence_tester.c b/tester/presence_tester.c index 7de76b692..843d50f65 100644 --- a/tester/presence_tester.c +++ b/tester/presence_tester.c @@ -306,40 +306,6 @@ static void subscribe_failure_handle_by_app(void) { linphone_core_manager_destroy(pauline); } -static void publish_with_network_state_changes(void) { - LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc"); - LinphoneProxyConfig* proxy; - LinphoneCoreCbs *cbs = linphone_factory_create_core_cbs(linphone_factory_get()); - - linphone_core_cbs_set_publish_state_changed(cbs, linphone_publish_state_changed); - _linphone_core_add_callbacks(marie->lc, cbs,TRUE); - linphone_core_cbs_unref(cbs); - - proxy = linphone_core_get_default_proxy_config(marie->lc); - linphone_proxy_config_edit(proxy); - linphone_proxy_config_enable_publish(proxy,TRUE); - linphone_proxy_config_done(proxy); - - BC_ASSERT_TRUE(wait_for(marie->lc,marie->lc,&marie->stat.number_of_LinphonePublishProgress,1)); - BC_ASSERT_TRUE(wait_for(marie->lc,marie->lc,&marie->stat.number_of_LinphonePublishOk,1)); - - linphone_core_set_network_reachable(marie->lc, FALSE); - BC_ASSERT_TRUE(wait_for(marie->lc,marie->lc,&marie->stat.number_of_LinphoneRegistrationNone,1)); - BC_ASSERT_FALSE(wait_for_until(marie->lc,marie->lc,&marie->stat.number_of_LinphonePublishProgress,2,1000)); - BC_ASSERT_EQUAL(marie->stat.number_of_LinphonePublishOk,1,int,"%i"); - BC_ASSERT_EQUAL(marie->stat.number_of_LinphonePublishError,0,int,"%i"); - - linphone_core_set_network_reachable(marie->lc, TRUE); - BC_ASSERT_TRUE(wait_for(marie->lc,marie->lc,&marie->stat.number_of_LinphonePublishProgress,2)); - BC_ASSERT_TRUE(wait_for(marie->lc,marie->lc,&marie->stat.number_of_LinphonePublishOk,2)); - - - linphone_core_manager_stop(marie); - BC_ASSERT_EQUAL(marie->stat.number_of_LinphonePublishCleared,1,int,"%i"); /*yes it is 3 because when we change the expires, a new LinphoneEvent is created*/ - BC_ASSERT_EQUAL(marie->stat.number_of_LinphonePublishOk,2,int,"%i"); - linphone_core_manager_destroy(marie); -} - static void simple_subscribe(void) { LinphoneCoreManager* marie = presence_linphone_core_manager_new("marie"); LinphoneCoreManager* pauline = presence_linphone_core_manager_new("pauline"); @@ -643,11 +609,10 @@ test_t presence_tests[] = { TEST_NO_TAG("Simple Publish", simple_publish), TEST_NO_TAG("Publish with 2 identities", publish_with_dual_identity), TEST_NO_TAG("Simple Publish with expires", publish_with_expires), - TEST_ONE_TAG("Publish with network state changes", publish_with_network_state_changes, "presence"), /*TEST_ONE_TAG("Call with presence", call_with_presence, "LeaksMemory"),*/ TEST_NO_TAG("Unsubscribe while subscribing", unsubscribe_while_subscribing), TEST_NO_TAG("Presence information", presence_information), - TEST_ONE_TAG("App managed presence failure", subscribe_failure_handle_by_app, "LeaksMemory"), + TEST_NO_TAG("App managed presence failure", subscribe_failure_handle_by_app), TEST_NO_TAG("Presence SUBSCRIBE forked", subscribe_presence_forked), TEST_NO_TAG("Presence SUBSCRIBE expired", subscribe_presence_expired), }; diff --git a/tester/register_tester.c b/tester/register_tester.c index aa9b1f52e..c994e8931 100644 --- a/tester/register_tester.c +++ b/tester/register_tester.c @@ -553,7 +553,6 @@ static void network_state_change(void){ linphone_core_set_network_reachable(lc,FALSE); BC_ASSERT_TRUE(wait_for(lc,lc,&counters->number_of_NetworkReachableFalse,1)); BC_ASSERT_TRUE(wait_for(lc,lc,&counters->number_of_LinphoneRegistrationNone,register_ok)); - BC_ASSERT_FALSE(wait_for_until(lc,lc,&counters->number_of_LinphoneRegistrationProgress,register_ok+1,1000)); /*make sure no register is tried*/ linphone_core_set_network_reachable(lc,TRUE); BC_ASSERT_TRUE(wait_for(lc,lc,&counters->number_of_NetworkReachableTrue,1)); wait_for(lc,lc,&counters->number_of_LinphoneRegistrationOk,2*register_ok); @@ -613,7 +612,7 @@ static void transport_dont_bind(void){ LinphoneTransports *tr = linphone_transports_new(); linphone_transports_set_tcp_port(tr, LC_SIP_TRANSPORT_DONTBIND); linphone_transports_set_tls_port(tr, LC_SIP_TRANSPORT_DONTBIND); - + linphone_core_set_transports(pauline->lc, tr); BC_ASSERT_TRUE(wait_for_until(pauline->lc,pauline->lc,&counters->number_of_LinphoneRegistrationOk,2,15000)); linphone_transports_unref(tr); @@ -628,14 +627,14 @@ static void transport_dont_bind(void){ static void transport_busy(void){ LinphoneCoreManager *pauline = linphone_core_manager_new("pauline_tcp_rc"); LCSipTransports tr; - + memset(&tr, 0, sizeof(tr)); tr.udp_port = 5070; tr.tcp_port = 5070; tr.tls_port = 5071; - + linphone_core_set_sip_transports(pauline->lc, &tr); - + { LinphoneCoreManager *marie = linphone_core_manager_new("marie_rc"); linphone_core_set_sip_transports(marie->lc, &tr); @@ -646,7 +645,7 @@ static void transport_busy(void){ BC_ASSERT_EQUAL(tr.tls_port, 0, int, "%i");*/ linphone_core_manager_destroy(marie); } - + linphone_core_manager_destroy(pauline); } @@ -915,7 +914,7 @@ char *read_file(const char *path) { size_t readbytes; char *buffer = NULL; FILE *infile = fopen(path, "rb"); - + BC_ASSERT_PTR_NOT_NULL(infile); if (infile) { fseek(infile, 0L, SEEK_END); diff --git a/tester/setup_tester.c b/tester/setup_tester.c index ba4956e5f..aaff11efb 100644 --- a/tester/setup_tester.c +++ b/tester/setup_tester.c @@ -184,8 +184,8 @@ static void linphone_lpconfig_from_xml_zerolen_value(void){ * This test makes a provisionning by xml outside of the Configuring state of the LinphoneCore. * It is leaking memory because the config is litterally erased and rewritten by the invocation * of the private function linphone_remote_provisioning_load_file . - */ - + */ + BC_ASSERT_EQUAL(linphone_remote_provisioning_load_file(mgr->lc, xml_path), 0, int, "%d"); conf = mgr->lc->config; @@ -349,7 +349,7 @@ static void codec_setup(void){ BC_ASSERT_TRUE(codecs->data == vp8); BC_ASSERT_TRUE(codecs->next->data == h264); linphone_core_manager_destroy(mgr); - + mgr = linphone_core_manager_new2("marie_h264_rc", FALSE); vp8 = linphone_core_find_payload_type(mgr->lc, "VP8", 90000, -1); h264 = linphone_core_find_payload_type(mgr->lc, "H264", 90000, -1); @@ -360,7 +360,7 @@ static void codec_setup(void){ BC_ASSERT_TRUE(codecs->data == vp8); BC_ASSERT_TRUE(codecs->next->data == h264); linphone_core_manager_destroy(mgr); - + mgr = linphone_core_manager_new2("marie_rc", FALSE); vp8 = linphone_core_find_payload_type(mgr->lc, "VP8", 90000, -1); h264 = linphone_core_find_payload_type(mgr->lc, "H264", 90000, -1); @@ -371,13 +371,13 @@ static void codec_setup(void){ BC_ASSERT_TRUE(codecs->data == vp8); BC_ASSERT_TRUE(codecs->next->data == h264); linphone_core_manager_destroy(mgr); - + } static void custom_tones_setup(void){ LinphoneCoreManager *mgr = linphone_core_manager_new2("empty_rc", FALSE); const char *tone; - + linphone_core_set_tone(mgr->lc, LinphoneToneCallOnHold, "callonhold.wav"); tone = linphone_core_get_tone_file(mgr->lc, LinphoneToneCallOnHold); BC_ASSERT_PTR_NOT_NULL(tone); @@ -409,7 +409,7 @@ test_t setup_tests[] = { TEST_NO_TAG("Devices reload", devices_reload_test), TEST_NO_TAG("Codec usability", codec_usability_test), TEST_NO_TAG("Codec setup", codec_setup), - TEST_NO_TAG("Custom tones setup", custom_tones_setup) + TEST_NO_TAG("Custom tones setup", custom_tones_setup) }; test_suite_t setup_test_suite = {"Setup", NULL, NULL, liblinphone_tester_before_each, liblinphone_tester_after_each, diff --git a/tester/tester.c b/tester/tester.c index 0ba670dc7..996c99f81 100644 --- a/tester/tester.c +++ b/tester/tester.c @@ -574,8 +574,6 @@ void liblinphone_tester_add_suites() { bc_tester_add_suite(&player_test_suite); bc_tester_add_suite(&dtmf_test_suite); bc_tester_add_suite(&cpim_test_suite); - bc_tester_add_suite(&clonable_object_test_suite); - bc_tester_add_suite(&events_db_test_suite); #if defined(VIDEO_ENABLED) && defined(HAVE_GTK) bc_tester_add_suite(&video_test_suite); #endif @@ -677,7 +675,6 @@ void liblinphone_tester_uninit(void) { all_leaks_buffer = NULL; } bc_tester_uninit(); - bctbx_uninit_logger(); } static void check_ice_from_rtp(LinphoneCall *c1, LinphoneCall *c2, LinphoneStreamType stream_type) { diff --git a/wrappers/csharp/genwrapper.py b/wrappers/csharp/genwrapper.py index e5aad72a7..2bf303cf6 100644 --- a/wrappers/csharp/genwrapper.py +++ b/wrappers/csharp/genwrapper.py @@ -22,7 +22,7 @@ import sys import pystache sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', '..', 'tools')) -print(sys.path) +print sys.path import genapixml as CApi import abstractapi as AbsApi import metadoc @@ -604,18 +604,17 @@ def main(): interfaces = [] classes = [] - for index in [parser.classesIndex, parser.interfacesIndex]: - for _class in index.values(): - if _class is not None: - try: - if type(_class) is AbsApi.Class: - impl = ClassImpl(_class, translator) - classes.append(impl) - else: - impl = InterfaceImpl(_class, translator) - interfaces.append(impl) - except AbsApi.Error as e: - print('Could not translate {0}: {1}'.format(_class.name.to_camel_case(fullName=True), e.args[0])) + for _class in parser.classesIndex.values() + parser.interfacesIndex.values(): + if _class is not None: + try: + if type(_class) is AbsApi.Class: + impl = ClassImpl(_class, translator) + classes.append(impl) + else: + impl = InterfaceImpl(_class, translator) + interfaces.append(impl) + except AbsApi.Error as e: + print('Could not translate {0}: {1}'.format(_class.name.to_camel_case(fullName=True), e.args[0])) wrapper = WrapperImpl(enums, interfaces, classes) render(renderer, wrapper, args.outputdir + "/" + args.outputfile)