From 86b626d3fe78e8bbc095817be36ea030c9a3c7ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Grisez?= Date: Fri, 29 Sep 2017 17:19:52 +0200 Subject: [PATCH] Migration of Sal and SalOp into C++ classes --- console/linphonec.c | 3 +- coreapi/CMakeLists.txt | 16 +- coreapi/account_creator_private.h | 201 +++ coreapi/authentication.c | 11 +- coreapi/bellesip_sal/sal_impl.c | 1089 ------------ coreapi/bellesip_sal/sal_impl.h | 149 +- coreapi/bellesip_sal/sal_op_call.c | 1240 -------------- coreapi/bellesip_sal/sal_op_call_transfer.c | 273 --- coreapi/bellesip_sal/sal_op_events.c | 385 ----- coreapi/bellesip_sal/sal_op_impl.c | 762 +-------- coreapi/bellesip_sal/sal_op_info.c | 34 - coreapi/bellesip_sal/sal_op_message.c | 216 --- coreapi/bellesip_sal/sal_op_publish.c | 112 -- coreapi/call_log.c | 2 +- coreapi/callbacks.c | 121 +- coreapi/carddav.c | 4 +- coreapi/chat.c | 1 + coreapi/conference.cc | 2 +- coreapi/error_info.c | 6 +- coreapi/event.c | 75 +- coreapi/friend.c | 37 +- coreapi/friendlist.c | 4 +- coreapi/info.c | 6 +- coreapi/linphonecall.c | 2 +- coreapi/linphonecore.c | 185 ++- coreapi/misc.c | 2 +- coreapi/nat_policy.c | 4 +- coreapi/offeranswer.c | 1 + coreapi/presence.c | 28 +- coreapi/private.h | 248 +-- coreapi/proxy.c | 33 +- coreapi/quality_reporting.c | 1 + coreapi/sal.c | 942 ----------- coreapi/sal/call_op.cpp | 1475 +++++++++++++++++ coreapi/sal/call_op.h | 108 ++ coreapi/sal/event_op.cpp | 425 +++++ coreapi/sal/event_op.h | 74 + coreapi/sal/message_op.cpp | 88 + coreapi/sal/message_op.h | 47 + coreapi/sal/message_op_interface.h | 38 + .../sal_op_presence.c => sal/presence_op.cpp} | 324 ++-- coreapi/sal/presence_op.h | 58 + .../register_op.cpp} | 149 +- coreapi/sal/register_op.h | 43 + coreapi/sal/sal.c | 106 ++ coreapi/sal/sal.cpp | 976 +++++++++++ coreapi/sal/sal.h | 477 ++---- coreapi/sal/sal.hpp | 319 ++++ coreapi/sal/sal_op.cpp | 1025 ++++++++++++ coreapi/sal/sal_op.h | 258 +++ coreapi/tester_utils.cpp | 101 ++ coreapi/tester_utils.h | 154 ++ coreapi/vcard.cc | 3 +- src/c-wrapper/api/c-call.cpp | 20 +- src/c-wrapper/api/c-chat-message.cpp | 1 + src/call/call-p.h | 2 +- src/call/call.cpp | 4 +- src/call/call.h | 2 +- src/chat/chat-room.cpp | 37 +- src/chat/client-group-chat-room.cpp | 2 +- src/chat/is-composing.cpp | 12 +- src/conference/params/call-session-params.h | 1 + src/conference/session/call-session-p.h | 5 +- src/conference/session/call-session.cpp | 104 +- src/conference/session/call-session.h | 3 +- src/conference/session/media-session-p.h | 9 +- src/conference/session/media-session.cpp | 138 +- src/conference/session/media-session.h | 2 +- src/nat/ice-agent.cpp | 4 +- tester/account_creator_tester.c | 16 +- tester/accountmanager.c | 9 +- tester/audio_bypass_tester.c | 7 +- tester/call_multi_tester.c | 7 +- tester/call_single_tester.c | 145 +- tester/call_video_tester.c | 29 +- tester/certificates/client/cert.pem | 40 +- tester/complex_sip_case_tester.c | 1 - tester/dtmf_tester.c | 5 +- tester/eventapi_tester.c | 11 +- tester/flexisip_tester.c | 15 +- tester/liblinphone_tester.c | 1 - tester/liblinphone_tester.h | 1 + tester/log_collection_tester.c | 1 - tester/message_tester.c | 69 +- tester/offeranswer_tester.c | 1 - tester/presence_server_tester.c | 72 +- tester/presence_tester.c | 11 +- tester/quality_reporting_tester.c | 17 +- tester/register_tester.c | 71 +- tester/remote_provisioning_tester.c | 13 +- tester/setup_tester.c | 3 +- tester/stun_tester.c | 1 - tester/tester.c | 13 +- tester/tunnel_tester.c | 1 - tester/vcard_tester.c | 76 +- tester/video_tester.c | 1 - 96 files changed, 6659 insertions(+), 6767 deletions(-) create mode 100644 coreapi/account_creator_private.h delete mode 100644 coreapi/bellesip_sal/sal_op_call.c delete mode 100644 coreapi/bellesip_sal/sal_op_call_transfer.c delete mode 100644 coreapi/bellesip_sal/sal_op_events.c delete mode 100644 coreapi/bellesip_sal/sal_op_info.c delete mode 100644 coreapi/bellesip_sal/sal_op_message.c delete mode 100644 coreapi/bellesip_sal/sal_op_publish.c delete mode 100644 coreapi/sal.c create mode 100644 coreapi/sal/call_op.cpp create mode 100644 coreapi/sal/call_op.h create mode 100644 coreapi/sal/event_op.cpp create mode 100644 coreapi/sal/event_op.h create mode 100644 coreapi/sal/message_op.cpp create mode 100644 coreapi/sal/message_op.h create mode 100644 coreapi/sal/message_op_interface.h rename coreapi/{bellesip_sal/sal_op_presence.c => sal/presence_op.cpp} (59%) create mode 100644 coreapi/sal/presence_op.h rename coreapi/{bellesip_sal/sal_op_registration.c => sal/register_op.cpp} (51%) create mode 100644 coreapi/sal/register_op.h create mode 100644 coreapi/sal/sal.cpp create mode 100644 coreapi/sal/sal.hpp create mode 100644 coreapi/sal/sal_op.cpp create mode 100644 coreapi/sal/sal_op.h create mode 100644 coreapi/tester_utils.cpp create mode 100644 coreapi/tester_utils.h diff --git a/console/linphonec.c b/console/linphonec.c index edcd128a8..ca556536b 100644 --- a/console/linphonec.c +++ b/console/linphonec.c @@ -28,7 +28,6 @@ #include #include #include -#include "private.h" /*coreapi/private.h, needed for LINPHONE_VERSION */ #endif /*_WIN32_WCE*/ #include #include @@ -790,7 +789,7 @@ linphonec_prompt_for_auth_final(LinphoneCore *lc) pending_auth=auth_stack.elem[auth_stack.nitems-1]; snprintf(auth_prompt, 256, "Password for %s on %s: ", - pending_auth->username, pending_auth->realm); + linphone_auth_info_get_username(pending_auth), linphone_auth_info_get_realm(pending_auth)); printf("\n"); #ifdef HAVE_READLINE diff --git a/coreapi/CMakeLists.txt b/coreapi/CMakeLists.txt index b1f95067c..b6b473113 100644 --- a/coreapi/CMakeLists.txt +++ b/coreapi/CMakeLists.txt @@ -56,15 +56,7 @@ set(LINPHONE_SOURCE_FILES_C authentication.c bellesip_sal/sal_address_impl.c bellesip_sal/sal_impl.c - bellesip_sal/sal_op_call.c - bellesip_sal/sal_op_call_transfer.c - bellesip_sal/sal_op_events.c bellesip_sal/sal_op_impl.c - bellesip_sal/sal_op_info.c - bellesip_sal/sal_op_message.c - bellesip_sal/sal_op_presence.c - bellesip_sal/sal_op_publish.c - bellesip_sal/sal_op_registration.c bellesip_sal/sal_sdp.c buffer.c callbacks.c @@ -119,6 +111,14 @@ set(LINPHONE_SOURCE_FILES_C ) set(LINPHONE_SOURCE_FILES_CXX conference.cc + sal/call_op.cpp + sal/event_op.cpp + sal/message_op.cpp + sal/presence_op.cpp + sal/register_op.cpp + sal/sal.cpp + sal/sal_op.cpp + tester_utils.cpp ) set(LINPHONE_INCLUDE_DIRS ${LINPHONE_INCLUDE_DIRS}) if(ANDROID) diff --git a/coreapi/account_creator_private.h b/coreapi/account_creator_private.h new file mode 100644 index 000000000..a848d7ccb --- /dev/null +++ b/coreapi/account_creator_private.h @@ -0,0 +1,201 @@ +/* +account_creator.h +Copyright (C) 2017 Belledonne Communications SARL + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef _ACCOUNT_CREATOR_PRIVATE_H_ +#define _ACCOUNT_CREATOR_PRIVATE_H_ + +#include "linphone/defs.h" +#include +#include "linphone/account_creator_service.h" +#include "linphone/account_creator.h" + +struct _LinphoneAccountCreatorService { + belle_sip_object_t base; + void *user_data; + + LinphoneAccountCreatorRequestFunc account_creator_service_constructor_cb; /**< Constructor */ + LinphoneAccountCreatorRequestFunc account_creator_service_destructor_cb; /**< Destructor */ + + LinphoneAccountCreatorRequestFunc create_account_request_cb; /**< Request to create account */ + LinphoneAccountCreatorRequestFunc is_account_exist_request_cb; /**< Request to know if account exist */ + + LinphoneAccountCreatorRequestFunc activate_account_request_cb; /**< Request to activate account */ + LinphoneAccountCreatorRequestFunc is_account_activated_request_cb; /**< Request to know if account is activated */ + + LinphoneAccountCreatorRequestFunc link_account_request_cb; /**< Request to link account with an alias */ + LinphoneAccountCreatorRequestFunc activate_alias_request_cb; /**< Request to activate the link of alias */ + LinphoneAccountCreatorRequestFunc is_alias_used_request_cb; /**< Request to know if alias is used */ + LinphoneAccountCreatorRequestFunc is_account_linked_request_cb; /**< Request to know if account is linked with an alias */ + + LinphoneAccountCreatorRequestFunc recover_account_request_cb; /**< Request to recover account */ + LinphoneAccountCreatorRequestFunc update_account_request_cb; /**< Request to update account */ +}; + +BELLE_SIP_DECLARE_VPTR_NO_EXPORT(LinphoneAccountCreatorService); + +struct _LinphoneAccountCreatorCbs { + belle_sip_object_t base; + void *user_data; + + LinphoneAccountCreatorCbsStatusCb create_account_response_cb; /**< Response of create_account request */ + LinphoneAccountCreatorCbsStatusCb is_account_exist_response_cb; /**< Response of is_account_exist request */ + + LinphoneAccountCreatorCbsStatusCb activate_account_response_cb; /**< Response of activate_account request */ + LinphoneAccountCreatorCbsStatusCb is_account_activated_response_cb; /**< Response of is_account_activated request */ + + LinphoneAccountCreatorCbsStatusCb link_account_response_cb; /**< Response of link_account request */ + LinphoneAccountCreatorCbsStatusCb activate_alias_response_cb; /**< Response of activation alias */ + LinphoneAccountCreatorCbsStatusCb is_alias_used_response_cb; /**< Response of is_alias_used request */ + LinphoneAccountCreatorCbsStatusCb is_account_linked_response_cb; /**< Response of is_account_linked request */ + + LinphoneAccountCreatorCbsStatusCb recover_account_response_cb; /**< Response of recover_account request */ + LinphoneAccountCreatorCbsStatusCb update_account_response_cb; /**< Response of update_account request */ +}; + +BELLE_SIP_DECLARE_VPTR_NO_EXPORT(LinphoneAccountCreatorCbs); + +struct _LinphoneAccountCreator { + belle_sip_object_t base; + void *user_data; + LinphoneCore *core; + + /* AccountCreator */ + LinphoneAccountCreatorService *service; /**< Account creator service */ + LinphoneAccountCreatorCbs *cbs; /**< Account creator cbs */ + LinphoneXmlRpcSession *xmlrpc_session; /**< XML-RPC session */ + LinphoneProxyConfig *proxy_cfg; /**< Default proxy config */ + + /* User */ + char *username; /**< Username */ + char *display_name; /**< Display name */ + /* Password */ + char *password; /**< Plain text password */ + char *ha1; /**< Hash password */ + /* Phone Number(Alias) */ + char *phone_number; /**< User phone number*/ + char *phone_country_code; /**< User phone number country code */ + /* Email(Alias) */ + char *email; /**< User email */ + /* Misc */ + char *language; /**< User language */ + char *activation_code; /**< Account validation code */ + char *domain; /**< Domain */ + LinphoneTransportType transport; /**< Transport used */ + + /* Deprecated */ + char *route; +}; + +BELLE_SIP_DECLARE_VPTR_NO_EXPORT(LinphoneAccountCreator); + + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Account creator custom to set Linphone default values + * @param[in] creator LinphoneAccountCreator object + * @return LinphoneAccountCreatorStatusRequestOk if the request has been sent, LinphoneAccountCreatorStatusRequestFailed otherwise +**/ +LINPHONE_PUBLIC LinphoneAccountCreatorStatus linphone_account_creator_constructor_linphone(LinphoneAccountCreator *creator); + +/** + * Send an XML-RPC request to test the existence of a Linphone account. + * @param[in] creator LinphoneAccountCreator object + * @return LinphoneAccountCreatorStatusRequestOk if the request has been sent, LinphoneAccountCreatorStatusRequestFailed otherwise +**/ +LINPHONE_PUBLIC LinphoneAccountCreatorStatus linphone_account_creator_is_account_exist_linphone(LinphoneAccountCreator *creator); + +/** + * Send an XML-RPC request to create a Linphone account. + * @param[in] creator LinphoneAccountCreator object + * @return LinphoneAccountCreatorStatusRequestOk if the request has been sent, LinphoneAccountCreatorStatusRequestFailed otherwise +**/ +LINPHONE_PUBLIC LinphoneAccountCreatorStatus linphone_account_creator_create_account_linphone(LinphoneAccountCreator *creator); + +/** + * Send an XML-RPC request to activate a Linphone account with phone number. + * @param[in] creator LinphoneAccountCreator object + * @return LinphoneAccountCreatorStatusRequestOk if the request has been sent, LinphoneAccountCreatorStatusRequestFailed otherwise +**/ +LINPHONE_PUBLIC LinphoneAccountCreatorStatus linphone_account_creator_activate_account_linphone(LinphoneAccountCreator *creator); + +/** + * Send an XML-RPC request to activate a Linphone account with email. + * @param[in] creator LinphoneAccountCreator object + * @return LinphoneAccountCreatorStatusRequestOk if the request has been sent, LinphoneAccountCreatorStatusRequestFailed otherwise +**/ +LINPHONE_PUBLIC LinphoneAccountCreatorStatus linphone_account_creator_activate_email_account_linphone(LinphoneAccountCreator *creator); + +/** + * Send an XML-RPC request to test the validation of a Linphone account. + * @param[in] creator LinphoneAccountCreator object + * @return LinphoneAccountCreatorStatusRequestOk if the request has been sent, LinphoneAccountCreatorStatusRequestFailed otherwise +**/ +LINPHONE_PUBLIC LinphoneAccountCreatorStatus linphone_account_creator_is_account_activated_linphone(LinphoneAccountCreator *creator); + +/** + * Send an XML-RPC request to test the existence a phone number with a Linphone account. + * @param[in] creator LinphoneAccountCreator object + * @return LinphoneAccountCreatorStatusRequestOk if the request has been sent, LinphoneAccountCreatorStatusRequestFailed otherwise +**/ +LINPHONE_PUBLIC LinphoneAccountCreatorStatus linphone_account_creator_is_phone_number_used_linphone(LinphoneAccountCreator *creator); + +/** + * Send an XML-RPC request to link a phone number with a Linphone account. + * @param[in] creator LinphoneAccountCreator object + * @return LinphoneAccountCreatorStatusRequestOk if the request has been sent, LinphoneAccountCreatorStatusRequestFailed otherwise +**/ +LINPHONE_PUBLIC LinphoneAccountCreatorStatus linphone_account_creator_link_phone_number_with_account_linphone(LinphoneAccountCreator *creator); + +/** + * Send an XML-RPC request to activate the link of a phone number with a Linphone account. + * @param[in] creator LinphoneAccountCreator object + * @return LinphoneAccountCreatorStatusRequestOk if the request has been sent, LinphoneAccountCreatorStatusRequestFailed otherwise +**/ +LINPHONE_PUBLIC LinphoneAccountCreatorStatus linphone_account_creator_activate_phone_number_link_linphone(LinphoneAccountCreator *creator); + +/** + * Send an XML-RPC request to a Linphone account with the phone number. + * @param[in] creator LinphoneAccountCreator object + * @return LinphoneAccountCreatorStatusRequestOk if the request has been sent, LinphoneAccountCreatorStatusRequestFailed otherwise +**/ +LINPHONE_PUBLIC LinphoneAccountCreatorStatus linphone_account_creator_recover_phone_account_linphone(LinphoneAccountCreator *creator); + +/** + * Send an XML-RPC request to ask if an account is linked with a phone number + * @param[in] creator LinphoneAccountCreator object + * @return if this account is linked with a phone number +**/ +LINPHONE_PUBLIC LinphoneAccountCreatorStatus linphone_account_creator_is_account_linked_linphone(LinphoneAccountCreator *creator); + +/** + * Send an XML-RPC request to ask if an account is linked with a phone number + * @param[in] creator LinphoneAccountCreator object + * @param[in] new_pwd const char * : new password for the account creator + * @return LinphoneAccountCreatorStatusRequestOk if everything is OK, or a specific error otherwise. +**/ +LINPHONE_PUBLIC LinphoneAccountCreatorStatus linphone_account_creator_update_password_linphone(LinphoneAccountCreator *creator); + +#ifdef __cplusplus +} +#endif + +#endif // _ACCOUNT_CREATOR_PRIVATE_H_ diff --git a/coreapi/authentication.c b/coreapi/authentication.c index 8fdf050c4..c79769527 100644 --- a/coreapi/authentication.c +++ b/coreapi/authentication.c @@ -24,9 +24,12 @@ #include "linphone/core.h" #include "linphone/lpconfig.h" +#include "sal/sal.hpp" #include "c-wrapper/c-wrapper.h" +using namespace LINPHONE_NAMESPACE; + static void _linphone_auth_info_uninit(LinphoneAuthInfo *obj); static void _linphone_auth_info_copy(LinphoneAuthInfo *dst, const LinphoneAuthInfo *src); @@ -434,10 +437,10 @@ void linphone_core_add_auth_info(LinphoneCore *lc, const LinphoneAuthInfo *info) lc->auth_info=bctbx_list_append(lc->auth_info,linphone_auth_info_clone(info)); /* retry pending authentication operations */ - for(l=elem=sal_get_pending_auths(lc->sal);elem!=NULL;elem=elem->next){ + for(l=elem=lc->sal->get_pending_auths();elem!=NULL;elem=elem->next){ SalOp *op=(SalOp*)elem->data; LinphoneAuthInfo *ai; - const SalAuthInfo *req_sai=sal_op_get_auth_requested(op); + const SalAuthInfo *req_sai=op->get_auth_requested(); ai=(LinphoneAuthInfo*)_linphone_core_find_auth_info(lc,req_sai->realm,req_sai->username,req_sai->domain, FALSE); if (ai){ SalAuthInfo sai; @@ -456,12 +459,12 @@ void linphone_core_add_auth_info(LinphoneCore *lc, const LinphoneAuthInfo *info) } /*proxy case*/ for (proxy=(bctbx_list_t*)linphone_core_get_proxy_config_list(lc);proxy!=NULL;proxy=proxy->next) { - if (proxy->data == sal_op_get_user_pointer(op)) { + if (proxy->data == op->get_user_pointer()) { linphone_proxy_config_set_state((LinphoneProxyConfig*)(proxy->data),LinphoneRegistrationProgress,"Authentication..."); break; } } - sal_op_authenticate(op,&sai); + op->authenticate(&sai); restarted_op_count++; } } diff --git a/coreapi/bellesip_sal/sal_impl.c b/coreapi/bellesip_sal/sal_impl.c index da8ce0f7d..7803b92a5 100644 --- a/coreapi/bellesip_sal/sal_impl.c +++ b/coreapi/bellesip_sal/sal_impl.c @@ -23,41 +23,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "config.h" #endif -/* -rfc3323 -4.2 Expressing Privacy Preferences -When a Privacy header is constructed, it MUST consist of either the - value 'none', or one or more of the values 'user', 'header' and - 'session' (each of which MUST appear at most once) which MAY in turn - be followed by the 'critical' indicator. - */ -void sal_op_set_privacy_from_message(SalOp* op,belle_sip_message_t* msg) { - belle_sip_header_privacy_t* privacy = belle_sip_message_get_header_by_type(msg,belle_sip_header_privacy_t); - if (!privacy) { - sal_op_set_privacy(op,SalPrivacyNone); - } else { - belle_sip_list_t* privacy_list=belle_sip_header_privacy_get_privacy(privacy); - sal_op_set_privacy(op,0); - for (;privacy_list!=NULL;privacy_list=privacy_list->next) { - char* privacy_value=(char*)privacy_list->data; - if(strcmp(sal_privacy_to_string(SalPrivacyCritical),privacy_value) == 0) - sal_op_set_privacy(op,sal_op_get_privacy(op)|SalPrivacyCritical); - if(strcmp(sal_privacy_to_string(SalPrivacyHeader),privacy_value) == 0) - sal_op_set_privacy(op,sal_op_get_privacy(op)|SalPrivacyHeader); - if(strcmp(sal_privacy_to_string(SalPrivacyId),privacy_value) == 0) - sal_op_set_privacy(op,sal_op_get_privacy(op)|SalPrivacyId); - if(strcmp(sal_privacy_to_string(SalPrivacyNone),privacy_value) == 0) { - sal_op_set_privacy(op,SalPrivacyNone); - break; - } - if(strcmp(sal_privacy_to_string(SalPrivacySession),privacy_value) == 0) - sal_op_set_privacy(op,sal_op_get_privacy(op)|SalPrivacySession); - if(strcmp(sal_privacy_to_string(SalPrivacyUser),privacy_value) == 0) - sal_op_set_privacy(op,sal_op_get_privacy(op)|SalPrivacyUser); - } - } -} -static void set_tls_properties(Sal *ctx); void sal_enable_log(){ sal_set_log_level(ORTP_MESSAGE); @@ -93,817 +58,6 @@ void sal_set_log_handler(BctbxLogFunc log_handler) { _belle_sip_log_handler = log_handler; belle_sip_set_log_handler(log_handler); } -void sal_add_pending_auth(Sal *sal, SalOp *op){ - if (bctbx_list_find(sal->pending_auths,op)==NULL){ - sal->pending_auths=bctbx_list_append(sal->pending_auths,op); - op->has_auth_pending=TRUE; - } -} - -void sal_remove_pending_auth(Sal *sal, SalOp *op){ - if (op->has_auth_pending){ - op->has_auth_pending=FALSE; - if (bctbx_list_find(sal->pending_auths,op)){ - sal->pending_auths=bctbx_list_remove(sal->pending_auths,op); - } - } -} - -void sal_process_authentication(SalOp *op) { - belle_sip_request_t* initial_request=belle_sip_transaction_get_request((belle_sip_transaction_t*)op->pending_auth_transaction); - belle_sip_request_t* new_request; - bool_t is_within_dialog=FALSE; - belle_sip_list_t* auth_list=NULL; - belle_sip_auth_event_t* auth_event; - belle_sip_response_t *response=belle_sip_transaction_get_response((belle_sip_transaction_t*)op->pending_auth_transaction); - belle_sip_header_from_t *from=belle_sip_message_get_header_by_type(initial_request,belle_sip_header_from_t); - belle_sip_uri_t *from_uri=belle_sip_header_address_get_uri((belle_sip_header_address_t*)from); - - if (strcasecmp(belle_sip_uri_get_host(from_uri),"anonymous.invalid")==0){ - /*prefer using the from from the SalOp*/ - from_uri=belle_sip_header_address_get_uri((belle_sip_header_address_t*)sal_op_get_from_address(op)); - } - - if (op->dialog && belle_sip_dialog_get_state(op->dialog)==BELLE_SIP_DIALOG_CONFIRMED) { - new_request = belle_sip_dialog_create_request_from(op->dialog,initial_request); - if (!new_request) - new_request = belle_sip_dialog_create_queued_request_from(op->dialog,initial_request); - is_within_dialog=TRUE; - } else { - new_request=initial_request; - belle_sip_message_remove_header(BELLE_SIP_MESSAGE(new_request),BELLE_SIP_AUTHORIZATION); - belle_sip_message_remove_header(BELLE_SIP_MESSAGE(new_request),BELLE_SIP_PROXY_AUTHORIZATION); - } - if (new_request==NULL) { - ms_error("sal_process_authentication() op=[%p] cannot obtain new request from dialog.",op); - return; - } - - if (belle_sip_provider_add_authorization(op->base.root->prov,new_request,response,from_uri,&auth_list,op->base.realm)) { - if (is_within_dialog) { - sal_op_send_request(op,new_request); - } else { - sal_op_resend_request(op,new_request); - } - sal_remove_pending_auth(op->base.root,op); - }else { - belle_sip_header_from_t *from=belle_sip_message_get_header_by_type(response,belle_sip_header_from_t); - char *tmp=belle_sip_object_to_string(belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(from))); - ms_message("No auth info found for [%s]",tmp); - belle_sip_free(tmp); - sal_add_pending_auth(op->base.root,op); - - if (is_within_dialog) { - belle_sip_object_unref(new_request); - } - } - /*always store auth info, for case of wrong credential*/ - if (op->auth_info) { - sal_auth_info_delete(op->auth_info); - op->auth_info=NULL; - } - if (auth_list){ - auth_event=(belle_sip_auth_event_t*)(auth_list->data); - op->auth_info=sal_auth_info_create(auth_event); - belle_sip_list_free_with_data(auth_list,(void (*)(void*))belle_sip_auth_event_destroy); - } -} - -static void process_dialog_terminated(void *sal, const belle_sip_dialog_terminated_event_t *event){ - belle_sip_dialog_t* dialog = belle_sip_dialog_terminated_event_get_dialog(event); - SalOp* op = reinterpret_cast(belle_sip_dialog_get_application_data(dialog)); - if (op && op->callbacks && op->callbacks->process_dialog_terminated) { - op->callbacks->process_dialog_terminated(op,event); - } else { - ms_error("sal process_dialog_terminated no op found for this dialog [%p], ignoring",dialog); - } -} - -static void process_io_error(void *user_ctx, const belle_sip_io_error_event_t *event){ - belle_sip_client_transaction_t*client_transaction; - SalOp* op; - if (BELLE_SIP_OBJECT_IS_INSTANCE_OF(belle_sip_io_error_event_get_source(event),belle_sip_client_transaction_t)) { - client_transaction=BELLE_SIP_CLIENT_TRANSACTION(belle_sip_io_error_event_get_source(event)); - op = (SalOp*)belle_sip_transaction_get_application_data(BELLE_SIP_TRANSACTION(client_transaction)); - /*also reset auth count on IO error*/ - op->auth_requests=0; - if (op->callbacks && op->callbacks->process_io_error) { - op->callbacks->process_io_error(op,event); - } - } else { - /*ms_error("sal process_io_error not implemented yet for non transaction");*/ - /*nop, because already handle at transaction layer*/ - } -} - -static void process_request_event(void *ud, const belle_sip_request_event_t *event) { - Sal *sal=(Sal*)ud; - SalOp* op=NULL; - belle_sip_request_t* req = belle_sip_request_event_get_request(event); - belle_sip_dialog_t* dialog=belle_sip_request_event_get_dialog(event); - belle_sip_header_address_t* origin_address; - belle_sip_header_address_t* address=NULL; - belle_sip_header_from_t* from_header; - belle_sip_header_to_t* to; - belle_sip_header_diversion_t* diversion; - belle_sip_response_t* resp; - belle_sip_header_t *evh; - const char *method=belle_sip_request_get_method(req); - belle_sip_header_contact_t* remote_contact = belle_sip_message_get_header_by_type(req, belle_sip_header_contact_t); - - from_header=belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req),belle_sip_header_from_t); - - if (dialog) { - op=(SalOp*)belle_sip_dialog_get_application_data(dialog); - - if (op == NULL && strcmp("NOTIFY",method) == 0) { - /*special case for Dialog created by notify mathing subscribe*/ - belle_sip_transaction_t * sub_trans = belle_sip_dialog_get_last_transaction(dialog); - op = (SalOp*)belle_sip_transaction_get_application_data(sub_trans); - } - if (op==NULL || op->state==SalOpStateTerminated){ - ms_warning("Receiving request for null or terminated op [%p], ignored",op); - return; - } - }else{ - /*handle the case where we are receiving a request with to tag but it is not belonging to any dialog*/ - belle_sip_header_to_t *to = belle_sip_message_get_header_by_type(req, belle_sip_header_to_t); - if ((strcmp("INVITE",method)==0 || strcmp("NOTIFY",method)==0) && (belle_sip_header_to_get_tag(to) != NULL)) { - ms_warning("Receiving %s with to-tag but no know dialog here. Rejecting.", method); - resp=belle_sip_response_create_from_request(req,481); - belle_sip_provider_send_response(sal->prov,resp); - return; - /* by default (eg. when a to-tag is present), out of dialog ACK are automatically - handled in lower layers (belle-sip) but in case it misses, it will be forwarded to us */ - } else if (strcmp("ACK",method)==0 && (belle_sip_header_to_get_tag(to) == NULL)) { - ms_warning("Receiving ACK without to-tag but no know dialog here. Ignoring"); - return; - } - - if (strcmp("INVITE",method)==0) { - op=sal_op_new(sal); - op->dir=SalOpDirIncoming; - sal_op_call_fill_cbs(op); - }else if ((strcmp("SUBSCRIBE",method)==0 || strcmp("NOTIFY",method)==0) && (evh=belle_sip_message_get_header(BELLE_SIP_MESSAGE(req),"Event"))!=NULL) { - op=sal_op_new(sal); - op->dir=SalOpDirIncoming; - if (strncmp(belle_sip_header_get_unparsed_value(evh),"presence",strlen("presence"))==0){ - sal_op_presence_fill_cbs(op); - }else - sal_op_subscribe_fill_cbs(op); - }else if (strcmp("MESSAGE",method)==0) { - op=sal_op_new(sal); - op->dir=SalOpDirIncoming; - sal_op_message_fill_cbs(op); - }else if (strcmp("OPTIONS",method)==0) { - resp=belle_sip_response_create_from_request(req,200); - belle_sip_provider_send_response(sal->prov,resp); - return; - }else if (strcmp("INFO",method)==0) { - resp=belle_sip_response_create_from_request(req,481);/*INFO out of call dialogs are not allowed*/ - belle_sip_provider_send_response(sal->prov,resp); - return; - }else if (strcmp("BYE",method)==0) { - resp=belle_sip_response_create_from_request(req,481);/*out of dialog BYE */ - belle_sip_provider_send_response(sal->prov,resp); - return; - }else if (strcmp("CANCEL",method)==0) { - resp=belle_sip_response_create_from_request(req,481);/*out of dialog CANCEL */ - belle_sip_provider_send_response(sal->prov,resp); - return; - }else if (sal->enable_test_features && strcmp("PUBLISH",method)==0) { - resp=belle_sip_response_create_from_request(req,200);/*out of dialog PUBLISH */ - belle_sip_message_add_header((belle_sip_message_t*)resp,belle_sip_header_create("SIP-Etag","4441929FFFZQOA")); - belle_sip_provider_send_response(sal->prov,resp); - return; - }else { - ms_error("sal process_request_event not implemented yet for method [%s]",belle_sip_request_get_method(req)); - resp=belle_sip_response_create_from_request(req,405); - belle_sip_message_add_header(BELLE_SIP_MESSAGE(resp) - ,BELLE_SIP_HEADER(belle_sip_header_allow_create("INVITE, CANCEL, ACK, BYE, SUBSCRIBE, NOTIFY, MESSAGE, OPTIONS, INFO"))); - belle_sip_provider_send_response(sal->prov,resp); - return; - } - } - - if (!op->base.from_address) { - if (belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(from_header))) - address=belle_sip_header_address_create(belle_sip_header_address_get_displayname(BELLE_SIP_HEADER_ADDRESS(from_header)) - ,belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(from_header))); - else if ((belle_sip_header_address_get_absolute_uri(BELLE_SIP_HEADER_ADDRESS(from_header)))) - address=belle_sip_header_address_create2(belle_sip_header_address_get_displayname(BELLE_SIP_HEADER_ADDRESS(from_header)) - ,belle_sip_header_address_get_absolute_uri(BELLE_SIP_HEADER_ADDRESS(from_header))); - else - ms_error("Cannot not find from uri from request [%p]",req); - sal_op_set_from_address(op,(SalAddress*)address); - belle_sip_object_unref(address); - } - - if( remote_contact ){ - __sal_op_set_remote_contact(op, belle_sip_header_get_unparsed_value(BELLE_SIP_HEADER(remote_contact))); - } - - if (!op->base.to_address) { - to=belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req),belle_sip_header_to_t); - if (belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(to))) - address=belle_sip_header_address_create(belle_sip_header_address_get_displayname(BELLE_SIP_HEADER_ADDRESS(to)) - ,belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(to))); - else if ((belle_sip_header_address_get_absolute_uri(BELLE_SIP_HEADER_ADDRESS(to)))) - address=belle_sip_header_address_create2(belle_sip_header_address_get_displayname(BELLE_SIP_HEADER_ADDRESS(to)) - ,belle_sip_header_address_get_absolute_uri(BELLE_SIP_HEADER_ADDRESS(to))); - else - ms_error("Cannot not find to uri from request [%p]",req); - - sal_op_set_to_address(op,(SalAddress*)address); - belle_sip_object_unref(address); - } - - if(!op->base.diversion_address){ - diversion=belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req),belle_sip_header_diversion_t); - if (diversion) { - if (belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(diversion))) - address=belle_sip_header_address_create(belle_sip_header_address_get_displayname(BELLE_SIP_HEADER_ADDRESS(diversion)) - ,belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(diversion))); - else if ((belle_sip_header_address_get_absolute_uri(BELLE_SIP_HEADER_ADDRESS(diversion)))) - address=belle_sip_header_address_create2(belle_sip_header_address_get_displayname(BELLE_SIP_HEADER_ADDRESS(diversion)) - ,belle_sip_header_address_get_absolute_uri(BELLE_SIP_HEADER_ADDRESS(diversion))); - else - ms_warning("Cannot not find diversion header from request [%p]",req); - if (address) { - sal_op_set_diversion_address(op,(SalAddress*)address); - belle_sip_object_unref(address); - } - } - } - - if (!op->base.origin) { - /*set origin uri*/ - origin_address=belle_sip_header_address_create(NULL,belle_sip_request_extract_origin(req)); - __sal_op_set_network_origin_address(op,(SalAddress*)origin_address); - belle_sip_object_unref(origin_address); - } - if (!op->base.remote_ua) { - sal_op_set_remote_ua(op,BELLE_SIP_MESSAGE(req)); - } - - if (!op->base.call_id) { - op->base.call_id=ms_strdup(belle_sip_header_call_id_get_call_id(BELLE_SIP_HEADER_CALL_ID(belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req), belle_sip_header_call_id_t)))); - } - /*It is worth noting that proxies can (and - will) remove this header field*/ - sal_op_set_privacy_from_message(op,(belle_sip_message_t*)req); - - sal_op_assign_recv_headers(op,(belle_sip_message_t*)req); - if (op->callbacks && op->callbacks->process_request_event) { - op->callbacks->process_request_event(op,event); - } else { - ms_error("sal process_request_event not implemented yet"); - } - -} - -static void process_response_event(void *user_ctx, const belle_sip_response_event_t *event){ - belle_sip_client_transaction_t* client_transaction = belle_sip_response_event_get_client_transaction(event); - belle_sip_response_t* response = belle_sip_response_event_get_response(event); - int response_code = belle_sip_response_get_status_code(response); - - if (!client_transaction) { - ms_warning("Discarding stateless response [%i]",response_code); - return; - } else { - SalOp* op = (SalOp*)belle_sip_transaction_get_application_data(BELLE_SIP_TRANSACTION(client_transaction)); - belle_sip_request_t* request=belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(client_transaction)); - belle_sip_header_contact_t* remote_contact = belle_sip_message_get_header_by_type(response, belle_sip_header_contact_t); - - if (op->state == SalOpStateTerminated) { - belle_sip_message("Op [%p] is terminated, nothing to do with this [%i]", op, response_code); - return; - } - /*do it all the time, since we can receive provisional responses from a different instance than the final one*/ - sal_op_set_remote_ua(op,BELLE_SIP_MESSAGE(response)); - - if(remote_contact) { - __sal_op_set_remote_contact(op, belle_sip_header_get_unparsed_value(BELLE_SIP_HEADER(remote_contact))); - } - - if (!op->base.call_id) { - op->base.call_id=ms_strdup(belle_sip_header_call_id_get_call_id(BELLE_SIP_HEADER_CALL_ID(belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(response), belle_sip_header_call_id_t)))); - } - - sal_op_assign_recv_headers(op,(belle_sip_message_t*)response); - - if (op->callbacks && op->callbacks->process_response_event) { - /*handle authorization*/ - switch (response_code) { - case 200: - break; - case 401: - case 407: - if (op->state == SalOpStateTerminating && strcmp("BYE",belle_sip_request_get_method(request))!=0) { - /*only bye are completed*/ - belle_sip_message("Op is in state terminating, nothing else to do "); - } else { - if (op->pending_auth_transaction){ - belle_sip_object_unref(op->pending_auth_transaction); - op->pending_auth_transaction=NULL; - } - if (++op->auth_requests > 2) { - ms_warning("Auth info cannot be found for op [%s/%s] after 2 attempts, giving up",sal_op_get_from(op) - ,sal_op_get_to(op)); - op->base.root->callbacks.auth_failure(op,op->auth_info); - sal_remove_pending_auth(op->base.root,op); - } else { - op->pending_auth_transaction=(belle_sip_client_transaction_t*)belle_sip_object_ref(client_transaction); - sal_process_authentication(op); - return; - } - } - break; - case 403: - if (op->auth_info) op->base.root->callbacks.auth_failure(op,op->auth_info); - break; - } - if (response_code >= 180 && response_code !=401 && response_code !=407 && response_code !=403) { - /*not an auth request*/ - op->auth_requests=0; - } - op->callbacks->process_response_event(op,event); - } else { - ms_error("Unhandled event response [%p]",event); - } - } -} - -static void process_timeout(void *user_ctx, const belle_sip_timeout_event_t *event) { - belle_sip_client_transaction_t* client_transaction = belle_sip_timeout_event_get_client_transaction(event); - SalOp* op = (SalOp*)belle_sip_transaction_get_application_data(BELLE_SIP_TRANSACTION(client_transaction)); - if (op && op->callbacks && op->callbacks->process_timeout) { - op->callbacks->process_timeout(op,event); - } else { - ms_error("Unhandled event timeout [%p]",event); - } -} - -static void process_transaction_terminated(void *user_ctx, const belle_sip_transaction_terminated_event_t *event) { - belle_sip_client_transaction_t* client_transaction = belle_sip_transaction_terminated_event_get_client_transaction(event); - belle_sip_server_transaction_t* server_transaction = belle_sip_transaction_terminated_event_get_server_transaction(event); - belle_sip_transaction_t* trans; - SalOp* op; - - if(client_transaction) - trans=BELLE_SIP_TRANSACTION(client_transaction); - else - trans=BELLE_SIP_TRANSACTION(server_transaction); - - op = (SalOp*)belle_sip_transaction_get_application_data(trans); - if (op && op->callbacks && op->callbacks->process_transaction_terminated) { - op->callbacks->process_transaction_terminated(op,event); - } else { - ms_message("Unhandled transaction terminated [%p]",trans); - } - if (op) { - sal_op_unref(op); /*because every transaction ref op*/ - belle_sip_transaction_set_application_data(trans,NULL); /*no longuer reference something we do not ref to avoid futur access of a released op*/ - } -} - - -static void process_auth_requested(void *sal, belle_sip_auth_event_t *event) { - SalAuthInfo* auth_info = sal_auth_info_create(event); - ((Sal*)sal)->callbacks.auth_requested(reinterpret_cast(sal),auth_info); - belle_sip_auth_event_set_passwd(event,(const char*)auth_info->password); - belle_sip_auth_event_set_ha1(event,(const char*)auth_info->ha1); - belle_sip_auth_event_set_userid(event,(const char*)auth_info->userid); - belle_sip_auth_event_set_signing_key(event,(belle_sip_signing_key_t *)auth_info->key); - belle_sip_auth_event_set_client_certificates_chain(event,(belle_sip_certificates_chain_t* )auth_info->certificates); - sal_auth_info_delete(auth_info); -} - -Sal * sal_init(MSFactory *factory){ - belle_sip_listener_callbacks_t listener_callbacks; - Sal * sal=ms_new0(Sal,1); - - /*belle_sip_object_enable_marshal_check(TRUE);*/ - sal->auto_contacts=TRUE; - sal->factory = factory; - /*first create the stack, which initializes the belle-sip object's pool for this thread*/ - sal->stack = belle_sip_stack_new(NULL); - - sal->user_agent=belle_sip_header_user_agent_new(); -#if defined(PACKAGE_NAME) && defined(LIBLINPHONE_VERSION) - belle_sip_header_user_agent_add_product(sal->user_agent, PACKAGE_NAME "/" LIBLINPHONE_VERSION); -#else - belle_sip_header_user_agent_add_product(sal->user_agent, "Unknown"); -#endif - sal_append_stack_string_to_user_agent(sal); - belle_sip_object_ref(sal->user_agent); - - sal->prov = belle_sip_stack_create_provider(sal->stack,NULL); - sal_nat_helper_enable(sal,TRUE); - memset(&listener_callbacks,0,sizeof(listener_callbacks)); - listener_callbacks.process_dialog_terminated=process_dialog_terminated; - listener_callbacks.process_io_error=process_io_error; - listener_callbacks.process_request_event=process_request_event; - listener_callbacks.process_response_event=process_response_event; - listener_callbacks.process_timeout=process_timeout; - listener_callbacks.process_transaction_terminated=process_transaction_terminated; - listener_callbacks.process_auth_requested=process_auth_requested; - sal->listener=belle_sip_listener_create_from_callbacks(&listener_callbacks,sal); - belle_sip_provider_add_sip_listener(sal->prov,sal->listener); - sal->tls_verify=TRUE; - sal->tls_verify_cn=TRUE; - sal->refresher_retry_after=60000; /*default value in ms*/ - sal->enable_sip_update=TRUE; - sal->pending_trans_checking=TRUE; - sal->ssl_config = NULL; - return sal; -} - -void sal_set_user_pointer(Sal *sal, void *user_data){ - sal->up=user_data; -} - -void *sal_get_user_pointer(const Sal *sal){ - return sal->up; -} - -static void unimplemented_stub(void){ - ms_warning("Unimplemented SAL callback"); -} - -void sal_set_callbacks(Sal *ctx, const SalCallbacks *cbs){ - memcpy(&ctx->callbacks,cbs,sizeof(*cbs)); - if (ctx->callbacks.call_received==NULL) - ctx->callbacks.call_received=(SalOnCallReceived)unimplemented_stub; - if (ctx->callbacks.call_ringing==NULL) - ctx->callbacks.call_ringing=(SalOnCallRinging)unimplemented_stub; - if (ctx->callbacks.call_accepted==NULL) - ctx->callbacks.call_accepted=(SalOnCallAccepted)unimplemented_stub; - if (ctx->callbacks.call_failure==NULL) - ctx->callbacks.call_failure=(SalOnCallFailure)unimplemented_stub; - if (ctx->callbacks.call_terminated==NULL) - ctx->callbacks.call_terminated=(SalOnCallTerminated)unimplemented_stub; - if (ctx->callbacks.call_released==NULL) - ctx->callbacks.call_released=(SalOnCallReleased)unimplemented_stub; - if (ctx->callbacks.call_updating==NULL) - ctx->callbacks.call_updating=(SalOnCallUpdating)unimplemented_stub; - if (ctx->callbacks.auth_failure==NULL) - ctx->callbacks.auth_failure=(SalOnAuthFailure)unimplemented_stub; - if (ctx->callbacks.register_success==NULL) - ctx->callbacks.register_success=(SalOnRegisterSuccess)unimplemented_stub; - if (ctx->callbacks.register_failure==NULL) - ctx->callbacks.register_failure=(SalOnRegisterFailure)unimplemented_stub; - if (ctx->callbacks.dtmf_received==NULL) - ctx->callbacks.dtmf_received=(SalOnDtmfReceived)unimplemented_stub; - if (ctx->callbacks.notify==NULL) - ctx->callbacks.notify=(SalOnNotify)unimplemented_stub; - if (ctx->callbacks.subscribe_received==NULL) - ctx->callbacks.subscribe_received=(SalOnSubscribeReceived)unimplemented_stub; - if (ctx->callbacks.incoming_subscribe_closed==NULL) - ctx->callbacks.incoming_subscribe_closed=(SalOnIncomingSubscribeClosed)unimplemented_stub; - if (ctx->callbacks.parse_presence_requested==NULL) - ctx->callbacks.parse_presence_requested=(SalOnParsePresenceRequested)unimplemented_stub; - if (ctx->callbacks.convert_presence_to_xml_requested==NULL) - ctx->callbacks.convert_presence_to_xml_requested=(SalOnConvertPresenceToXMLRequested)unimplemented_stub; - if (ctx->callbacks.notify_presence==NULL) - ctx->callbacks.notify_presence=(SalOnNotifyPresence)unimplemented_stub; - if (ctx->callbacks.subscribe_presence_received==NULL) - ctx->callbacks.subscribe_presence_received=(SalOnSubscribePresenceReceived)unimplemented_stub; - if (ctx->callbacks.message_received==NULL) - ctx->callbacks.message_received=(SalOnMessageReceived)unimplemented_stub; - if (ctx->callbacks.ping_reply==NULL) - ctx->callbacks.ping_reply=(SalOnPingReply)unimplemented_stub; - if (ctx->callbacks.auth_requested==NULL) - ctx->callbacks.auth_requested=(SalOnAuthRequested)unimplemented_stub; - if (ctx->callbacks.info_received==NULL) - ctx->callbacks.info_received=(SalOnInfoReceived)unimplemented_stub; - if (ctx->callbacks.on_publish_response==NULL) - ctx->callbacks.on_publish_response=(SalOnPublishResponse)unimplemented_stub; - if (ctx->callbacks.on_expire==NULL) - ctx->callbacks.on_expire=(SalOnExpire)unimplemented_stub; -} - - - -void sal_uninit(Sal* sal){ - belle_sip_object_unref(sal->user_agent); - belle_sip_object_unref(sal->prov); - belle_sip_object_unref(sal->stack); - belle_sip_object_unref(sal->listener); - if (sal->supported) belle_sip_object_unref(sal->supported); - bctbx_list_free_with_data(sal->supported_tags,ms_free); - bctbx_list_free_with_data(sal->supported_content_types, ms_free); - if (sal->uuid) ms_free(sal->uuid); - if (sal->root_ca) ms_free(sal->root_ca); - if (sal->root_ca_data) ms_free(sal->root_ca_data); - ms_free(sal); -}; - -int sal_transport_available(Sal *sal, SalTransport t){ - switch(t){ - case SalTransportUDP: - case SalTransportTCP: - return TRUE; - case SalTransportTLS: - return belle_sip_stack_tls_available(sal->stack); - case SalTransportDTLS: - return FALSE; - } - return FALSE; -} - -bool_t sal_content_encoding_available(Sal *sal, const char *content_encoding) { - return (bool_t)belle_sip_stack_content_encoding_available(sal->stack, content_encoding); -} - -static int sal_add_listen_port(Sal *ctx, SalAddress* addr, bool_t is_tunneled){ - int result; - belle_sip_listening_point_t* lp; - if (is_tunneled){ -#ifdef TUNNEL_ENABLED - if (sal_address_get_transport(addr)!=SalTransportUDP){ - ms_error("Tunneled mode is only available for UDP kind of transports."); - return -1; - } - lp = belle_sip_tunnel_listening_point_new(ctx->stack, ctx->tunnel_client); - if (!lp){ - ms_error("Could not create tunnel listening point."); - return -1; - } -#else - ms_error("No tunnel support in library."); - return -1; -#endif - }else{ - lp = belle_sip_stack_create_listening_point(ctx->stack, - sal_address_get_domain(addr), - sal_address_get_port(addr), - sal_transport_to_string(sal_address_get_transport(addr))); - } - if (lp) { - belle_sip_listening_point_set_keep_alive(lp,(int)ctx->keep_alive); - result = belle_sip_provider_add_listening_point(ctx->prov,lp); - if (sal_address_get_transport(addr)==SalTransportTLS) { - set_tls_properties(ctx); - } - } else { - return -1; - } - return result; -} - -int sal_listen_port(Sal *ctx, const char *addr, int port, SalTransport tr, int is_tunneled) { - SalAddress* sal_addr = sal_address_new(NULL); - int result; - sal_address_set_domain(sal_addr,addr); - sal_address_set_port(sal_addr,port); - sal_address_set_transport(sal_addr,tr); - result = sal_add_listen_port(ctx, sal_addr, !!is_tunneled); - sal_address_destroy(sal_addr); - return result; -} - -static void remove_listening_point(belle_sip_listening_point_t* lp,belle_sip_provider_t* prov) { - belle_sip_provider_remove_listening_point(prov,lp); -} - -int sal_get_listening_port(Sal *ctx, SalTransport tr){ - const char *tpn=sal_transport_to_string(tr); - belle_sip_listening_point_t *lp=belle_sip_provider_get_listening_point(ctx->prov, tpn); - if (lp){ - return belle_sip_listening_point_get_port(lp); - } - return 0; -} - -int sal_unlisten_ports(Sal *ctx){ - const belle_sip_list_t * lps = belle_sip_provider_get_listening_points(ctx->prov); - belle_sip_list_t * tmp_list = belle_sip_list_copy(lps); - belle_sip_list_for_each2 (tmp_list,(void (*)(void*,void*))remove_listening_point,ctx->prov); - belle_sip_list_free(tmp_list); - ms_message("sal_unlisten_ports done"); - return 0; -} - -ortp_socket_t sal_get_socket(Sal *ctx){ - ms_warning("sal_get_socket is deprecated"); - return -1; -} - -void sal_set_user_agent(Sal *ctx, const char *user_agent){ - belle_sip_header_user_agent_set_products(ctx->user_agent,NULL); - belle_sip_header_user_agent_add_product(ctx->user_agent,user_agent); - return ; -} - -const char* sal_get_user_agent(Sal *ctx){ - static char user_agent[255]; - belle_sip_header_user_agent_get_products_as_string(ctx->user_agent, user_agent, 254); - return user_agent; -} - -void sal_append_stack_string_to_user_agent(Sal *ctx) { - char stack_string[64]; - snprintf(stack_string, sizeof(stack_string) - 1, "(belle-sip/%s)", belle_sip_version_to_string()); - belle_sip_header_user_agent_add_product(ctx->user_agent, stack_string); -} - -/*keepalive period in ms*/ -void sal_set_keepalive_period(Sal *ctx,unsigned int value){ - const belle_sip_list_t* iterator; - belle_sip_listening_point_t* lp; - ctx->keep_alive=value; - for (iterator=belle_sip_provider_get_listening_points(ctx->prov);iterator!=NULL;iterator=iterator->next) { - lp=(belle_sip_listening_point_t*)iterator->data; - if (ctx->use_tcp_tls_keep_alive || strcasecmp(belle_sip_listening_point_get_transport(lp),"udp")==0) { - belle_sip_listening_point_set_keep_alive(lp,(int)ctx->keep_alive); - } - } -} -int sal_set_tunnel(Sal *ctx, void *tunnelclient) { -#ifdef TUNNEL_ENABLED - ctx->tunnel_client=tunnelclient; - return 0; -#else - return -1; -#endif -} - -/** - * returns keepalive period in ms - * 0 desactiaved - * */ -unsigned int sal_get_keepalive_period(Sal *ctx){ - return ctx->keep_alive; -} -void sal_use_session_timers(Sal *ctx, int expires){ - ctx->session_expires=expires; - return ; -} - -void sal_use_one_matching_codec_policy(Sal *ctx, bool_t one_matching_codec){ - ctx->one_matching_codec=one_matching_codec; -} - -void sal_use_rport(Sal *ctx, bool_t use_rports){ - belle_sip_provider_enable_rport(ctx->prov,use_rports); - ms_message("Sal use rport [%s]",use_rports?"enabled":"disabled"); - return ; -} - -static void set_tls_properties(Sal *ctx){ - belle_sip_listening_point_t *lp=belle_sip_provider_get_listening_point(ctx->prov,"TLS"); - if (lp){ - belle_sip_tls_listening_point_t *tlp=BELLE_SIP_TLS_LISTENING_POINT(lp); - belle_tls_crypto_config_t *crypto_config = belle_tls_crypto_config_new(); - int verify_exceptions = BELLE_TLS_VERIFY_NONE; - if (!ctx->tls_verify) verify_exceptions = BELLE_TLS_VERIFY_ANY_REASON; - else if (!ctx->tls_verify_cn) verify_exceptions = BELLE_TLS_VERIFY_CN_MISMATCH; - belle_tls_crypto_config_set_verify_exceptions(crypto_config, verify_exceptions); - if (ctx->root_ca != NULL) belle_tls_crypto_config_set_root_ca(crypto_config, ctx->root_ca); - if (ctx->root_ca_data != NULL) belle_tls_crypto_config_set_root_ca_data(crypto_config, ctx->root_ca_data); - if (ctx->ssl_config != NULL) belle_tls_crypto_config_set_ssl_config(crypto_config, ctx->ssl_config); - belle_sip_tls_listening_point_set_crypto_config(tlp, crypto_config); - belle_sip_object_unref(crypto_config); - } -} - -void sal_set_root_ca(Sal* ctx, const char* rootCa) { - if (ctx->root_ca) { - ms_free(ctx->root_ca); - ctx->root_ca = NULL; - } - if (rootCa) - ctx->root_ca = ms_strdup(rootCa); - set_tls_properties(ctx); - return; -} - -void sal_set_root_ca_data(Sal* ctx, const char* data) { - if (ctx->root_ca_data) { - ms_free(ctx->root_ca_data); - ctx->root_ca_data = NULL; - } - if (data) - ctx->root_ca_data = ms_strdup(data); - set_tls_properties(ctx); - return; -} - -void sal_verify_server_certificates(Sal *ctx, bool_t verify){ - ctx->tls_verify=verify; - set_tls_properties(ctx); - return ; -} - -void sal_verify_server_cn(Sal *ctx, bool_t verify){ - ctx->tls_verify_cn=verify; - set_tls_properties(ctx); - return ; -} - -void sal_set_ssl_config(Sal *ctx, void *ssl_config) { - ctx->ssl_config = ssl_config; - set_tls_properties(ctx); - return ; -} - -void sal_use_tcp_tls_keepalive(Sal *ctx, bool_t enabled) { - ctx->use_tcp_tls_keep_alive=enabled; -} - -int sal_iterate(Sal *sal){ - belle_sip_stack_sleep(sal->stack,0); - return 0; -} -bctbx_list_t * sal_get_pending_auths(Sal *sal){ - return bctbx_list_copy(sal->pending_auths); -} - -/*misc*/ -void sal_get_default_local_ip(Sal *sal, int address_family, char *ip, size_t iplen){ - strncpy(ip,address_family==AF_INET6 ? "::1" : "127.0.0.1",iplen); - ms_error("sal_get_default_local_ip() is deprecated."); -} - -const char *sal_get_root_ca(Sal* ctx) { - return ctx->root_ca; -} - -int sal_reset_transports(Sal *ctx){ - ms_message("Reseting transports"); - belle_sip_provider_clean_channels(ctx->prov); - return 0; -} - -void sal_set_dscp(Sal *ctx, int dscp){ - belle_sip_stack_set_default_dscp(ctx->stack,dscp); -} - -void sal_set_send_error(Sal *sal,int value) { - belle_sip_stack_set_send_error(sal->stack,value); -} -void sal_set_recv_error(Sal *sal,int value) { - belle_sip_provider_set_recv_error(sal->prov,value); -} -void sal_nat_helper_enable(Sal *sal,bool_t enable) { - sal->nat_helper_enabled=enable; - belle_sip_provider_enable_nat_helper(sal->prov,enable); - ms_message("Sal nat helper [%s]",enable?"enabled":"disabled"); -} -bool_t sal_nat_helper_enabled(Sal *sal) { - return sal->nat_helper_enabled; -} -void sal_set_dns_timeout(Sal* sal,int timeout) { - belle_sip_stack_set_dns_timeout(sal->stack, timeout); -} - -int sal_get_dns_timeout(const Sal* sal) { - return belle_sip_stack_get_dns_timeout(sal->stack); -} - -void sal_set_transport_timeout(Sal* sal,int timeout) { - belle_sip_stack_set_transport_timeout(sal->stack, timeout); -} - -int sal_get_transport_timeout(const Sal* sal) { - return belle_sip_stack_get_transport_timeout(sal->stack); -} - -void sal_set_dns_servers(Sal *sal, const bctbx_list_t *servers){ - belle_sip_list_t *l = NULL; - - /*we have to convert the bctbx_list_t into a belle_sip_list_t first*/ - for (; servers != NULL; servers = servers->next){ - l = belle_sip_list_append(l, servers->data); - } - belle_sip_stack_set_dns_servers(sal->stack, l); - belle_sip_list_free(l); -} - -void sal_enable_dns_srv(Sal *sal, bool_t enable) { - belle_sip_stack_enable_dns_srv(sal->stack, (unsigned char)enable); -} - -bool_t sal_dns_srv_enabled(const Sal *sal) { - return (bool_t)belle_sip_stack_dns_srv_enabled(sal->stack); -} - -void sal_enable_dns_search(Sal *sal, bool_t enable) { - belle_sip_stack_enable_dns_search(sal->stack, (unsigned char)enable); -} - -bool_t sal_dns_search_enabled(const Sal *sal) { - return (bool_t)belle_sip_stack_dns_search_enabled(sal->stack); -} - -void sal_set_dns_user_hosts_file(Sal *sal, const char *hosts_file) { - belle_sip_stack_set_dns_user_hosts_file(sal->stack, hosts_file); -} - -const char * sal_get_dns_user_hosts_file(const Sal *sal) { - return belle_sip_stack_get_dns_user_hosts_file(sal->stack); -} SalAuthInfo* sal_auth_info_create(belle_sip_auth_event_t* event) { SalAuthInfo* auth_info = sal_auth_info_new(); @@ -925,21 +79,6 @@ void sal_signing_key_delete(belle_sip_signing_key_t *key) { belle_sip_object_unref((belle_sip_object_t *)key); } -const char* sal_op_type_to_string(const SalOpType type) { - switch(type) { - case SalOpRegister: return "SalOpRegister"; - case SalOpCall: return "SalOpCall"; - case SalOpMessage: return "SalOpMessage"; - case SalOpPresence: return "SalOpPresence"; - default: - return "SalOpUnknown"; - } -} - -void sal_use_dates(Sal *ctx, bool_t enabled){ - ctx->use_dates=enabled; -} - int sal_auth_compute_ha1(const char* userid,const char* realm,const char* password, char ha1[33]) { return belle_sip_auth_helper_compute_ha1(userid, realm, password, ha1); } @@ -1001,11 +140,6 @@ SalCustomHeader *sal_custom_header_clone(const SalCustomHeader *ch){ return (SalCustomHeader*)belle_sip_object_ref((belle_sip_message_t*)ch); } -const SalCustomHeader *sal_op_get_recv_custom_header(SalOp *op){ - SalOpBase *b=(SalOpBase *)op; - return b->recv_custom_headers; -} - SalCustomSdpAttribute * sal_custom_sdp_attribute_append(SalCustomSdpAttribute *csa, const char *name, const char *value) { belle_sdp_session_description_t *desc = (belle_sdp_session_description_t *)csa; belle_sdp_attribute_t *attr; @@ -1040,167 +174,6 @@ SalCustomSdpAttribute * sal_custom_sdp_attribute_clone(const SalCustomSdpAttribu return (SalCustomSdpAttribute *)belle_sip_object_ref((belle_sdp_session_description_t *)csa); } -void sal_set_uuid(Sal *sal, const char *uuid){ - if (sal->uuid){ - ms_free(sal->uuid); - sal->uuid=NULL; - } - if (uuid) - sal->uuid=ms_strdup(uuid); -} - -typedef struct { - unsigned int time_low; - unsigned short time_mid; - unsigned short time_hi_and_version; - unsigned char clock_seq_hi_and_reserved; - unsigned char clock_seq_low; - unsigned char node[6]; -} sal_uuid_t; - -int sal_generate_uuid(char *uuid, size_t len) { - sal_uuid_t uuid_struct; - int i; - int written; - - if (len==0) return -1; - /*create an UUID as described in RFC4122, 4.4 */ - belle_sip_random_bytes((unsigned char*)&uuid_struct, sizeof(sal_uuid_t)); - uuid_struct.clock_seq_hi_and_reserved&=(unsigned char)~(1<<6); - uuid_struct.clock_seq_hi_and_reserved|=1<<7; - uuid_struct.time_hi_and_version&=(short unsigned int)~(0xf<<12); - uuid_struct.time_hi_and_version|=4<<12; - - written=snprintf(uuid,len,"%8.8x-%4.4x-%4.4x-%2.2x%2.2x-", uuid_struct.time_low, uuid_struct.time_mid, - uuid_struct.time_hi_and_version, uuid_struct.clock_seq_hi_and_reserved, - uuid_struct.clock_seq_low); - if ((written < 0) || ((size_t)written > (len +13))) { - ms_error("sal_create_uuid(): buffer is too short !"); - return -1; - } - for (i = 0; i < 6; i++) - written+=snprintf(uuid+written,len-(size_t)written,"%2.2x", uuid_struct.node[i]); - uuid[len-1]='\0'; - return 0; -} - -int sal_create_uuid(Sal*ctx, char *uuid, size_t len) { - if (sal_generate_uuid(uuid, len) == 0) { - sal_set_uuid(ctx, uuid); - return 0; - } - return -1; -} - -static void make_supported_header(Sal *sal){ - bctbx_list_t *it; - char *alltags=NULL; - size_t buflen=64; - size_t written=0; - - if (sal->supported){ - belle_sip_object_unref(sal->supported); - sal->supported=NULL; - } - for(it=sal->supported_tags;it!=NULL;it=it->next){ - const char *tag=(const char*)it->data; - size_t taglen=strlen(tag); - if (alltags==NULL || (written+taglen+1>=buflen)) alltags=reinterpret_cast(ms_realloc(alltags,(buflen=buflen*2))); - written+=(size_t)snprintf(alltags+written,buflen-written,it->next ? "%s, " : "%s",tag); - } - if (alltags){ - sal->supported=belle_sip_header_create("Supported",alltags); - if (sal->supported){ - belle_sip_object_ref(sal->supported); - } - ms_free(alltags); - } -} - -void sal_set_supported_tags(Sal *ctx, const char* tags){ - ctx->supported_tags=bctbx_list_free_with_data(ctx->supported_tags,ms_free); - if (tags){ - char *iter; - char *buffer=ms_strdup(tags); - char *tag; - char *context=NULL; - iter=buffer; - while((tag=strtok_r(iter,", ",&context))!=NULL){ - iter=NULL; - ctx->supported_tags=bctbx_list_append(ctx->supported_tags,ms_strdup(tag)); - } - ms_free(buffer); - } - make_supported_header(ctx); -} - -const char *sal_get_supported_tags(Sal *ctx){ - if (ctx->supported){ - return belle_sip_header_get_unparsed_value(ctx->supported); - } - return NULL; -} - -void sal_add_supported_tag(Sal *ctx, const char* tag){ - bctbx_list_t *elem=bctbx_list_find_custom(ctx->supported_tags,(bctbx_compare_func)strcasecmp,tag); - if (!elem){ - ctx->supported_tags=bctbx_list_append(ctx->supported_tags,ms_strdup(tag)); - make_supported_header(ctx); - } - -} - -void sal_remove_supported_tag(Sal *ctx, const char* tag){ - bctbx_list_t *elem=bctbx_list_find_custom(ctx->supported_tags,(bctbx_compare_func)strcasecmp,tag); - if (elem){ - ms_free(elem->data); - ctx->supported_tags=bctbx_list_erase_link(ctx->supported_tags,elem); - make_supported_header(ctx); - } -} - - - -belle_sip_response_t* sal_create_response_from_request ( Sal* sal, belle_sip_request_t* req, int code ) { - belle_sip_response_t *resp=belle_sip_response_create_from_request(req,code); - belle_sip_message_add_header(BELLE_SIP_MESSAGE(resp),BELLE_SIP_HEADER(sal->user_agent)); - belle_sip_message_add_header(BELLE_SIP_MESSAGE(resp),sal->supported); - return resp; -} - -void sal_set_refresher_retry_after(Sal *sal,int value) { - sal->refresher_retry_after=value; -} - -int sal_get_refresher_retry_after(const Sal *sal) { - return sal->refresher_retry_after; -} - -void sal_enable_auto_contacts(Sal *ctx, bool_t enabled){ - ctx->auto_contacts=enabled; -} - -void sal_enable_test_features(Sal*ctx, bool_t enabled){ - ctx->enable_test_features=enabled; -} - -void sal_use_no_initial_route(Sal *ctx, bool_t enabled){ - ctx->no_initial_route=enabled; -} - -belle_sip_resolver_context_t * sal_resolve_a(Sal* sal, const char *name, int port, int family, belle_sip_resolver_callback_t cb, void *data){ - return belle_sip_stack_resolve_a(sal->stack,name,port,family,cb,data); -} - -belle_sip_resolver_context_t * sal_resolve(Sal *sal, const char *service, const char *transport, const char *name, int port, int family, belle_sip_resolver_callback_t cb, void *data) { - return belle_sip_stack_resolve(sal->stack, service, transport, name, port, family, cb, data); -} - - -void sal_enable_unconditional_answer(Sal *sal,int value) { - belle_sip_provider_enable_unconditional_answer(sal->prov,value); -} - /** Parse a file containing either a certificate chain order in PEM format or a single DER cert * @param auth_info structure where to store the result of parsing * @param path path to certificate chain file @@ -1296,16 +269,6 @@ unsigned int sal_get_random(void){ return ret; } -belle_sip_source_t * sal_create_timer(Sal *sal, belle_sip_source_func_t func, void *data, unsigned int timeout_value_ms, const char* timer_name) { - belle_sip_main_loop_t *ml = belle_sip_stack_get_main_loop(sal->stack); - return belle_sip_main_loop_create_timeout(ml, func, data, timeout_value_ms, timer_name); -} - -void sal_cancel_timer(Sal *sal, belle_sip_source_t *timer) { - belle_sip_main_loop_t *ml = belle_sip_stack_get_main_loop(sal->stack); - belle_sip_main_loop_remove_source(ml, timer); -} - unsigned long sal_begin_background_task(const char *name, void (*max_time_reached)(void *), void *data){ return belle_sip_begin_background_task(name, max_time_reached, data); } @@ -1314,39 +277,6 @@ void sal_end_background_task(unsigned long id){ belle_sip_end_background_task(id); } - -void sal_enable_sip_update_method(Sal *ctx,bool_t value) { - ctx->enable_sip_update=value; -} - -void sal_default_set_sdp_handling(Sal *sal, SalOpSDPHandling sdp_handling_method) { - if (sdp_handling_method != SalOpSDPNormal ) ms_message("Enabling special SDP handling for all new SalOp in Sal[%p]!", sal); - sal->default_sdp_handling = sdp_handling_method; -} - -bool_t sal_pending_trans_checking_enabled(const Sal *sal) { - return sal->pending_trans_checking; -} - -int sal_enable_pending_trans_checking(Sal *sal, bool_t value) { - sal->pending_trans_checking = value; - return 0; -} -void sal_set_http_proxy_host(Sal *sal, const char *host) { - belle_sip_stack_set_http_proxy_host(sal->stack, host); -} - -void sal_set_http_proxy_port(Sal *sal, int port) { - belle_sip_stack_set_http_proxy_port(sal->stack, port); -} -const char *sal_get_http_proxy_host(const Sal *sal) { - return belle_sip_stack_get_http_proxy_host(sal->stack); -} - -int sal_get_http_proxy_port(const Sal *sal) { - return belle_sip_stack_get_http_proxy_port(sal->stack); -} - static belle_sip_header_t * sal_body_handler_find_header(const SalBodyHandler *body_handler, const char *header_name) { belle_sip_body_handler_t *bsbh = BELLE_SIP_BODY_HANDLER(body_handler); const belle_sip_list_t *l = belle_sip_body_handler_get_headers(bsbh); @@ -1476,22 +406,3 @@ const char * sal_body_handler_get_header(const SalBodyHandler *body_handler, con } return NULL; } - -void *sal_get_stack_impl(Sal *sal) { - return sal->stack; -} - -bool_t sal_is_content_type_supported(const Sal *sal, const char *content_type) { - bctbx_list_t *item; - for (item = sal->supported_content_types; item != NULL; item = bctbx_list_next(item)) { - const char *item_content_type = (const char *)bctbx_list_get_data(item); - if (strcmp(item_content_type, content_type) == 0) return TRUE; - } - return FALSE; -} - -void sal_add_content_type_support(Sal *sal, const char *content_type) { - if ((content_type != NULL) && (sal_is_content_type_supported(sal, content_type) == FALSE)) { - sal->supported_content_types = bctbx_list_append(sal->supported_content_types, ms_strdup(content_type)); - } -} diff --git a/coreapi/bellesip_sal/sal_impl.h b/coreapi/bellesip_sal/sal_impl.h index 6c290ff33..a30f22e5a 100644 --- a/coreapi/bellesip_sal/sal_impl.h +++ b/coreapi/bellesip_sal/sal_impl.h @@ -24,161 +24,14 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "belle-sip/belle-sip.h" #include "belle-sip/belle-sdp.h" -struct Sal{ - MSFactory *factory; - SalCallbacks callbacks; - MSList *pending_auths;/*MSList of SalOp */ - belle_sip_stack_t* stack; - belle_sip_provider_t *prov; - belle_sip_header_user_agent_t* user_agent; - belle_sip_listener_t *listener; - void *tunnel_client; - void *up; /*user pointer*/ - int session_expires; - unsigned int keep_alive; - char *root_ca; - char *root_ca_data; - char *uuid; - int refresher_retry_after; /*retry after value for refresher*/ - MSList *supported_tags;/*list of char * */ - belle_sip_header_t *supported; - bool_t one_matching_codec; - bool_t use_tcp_tls_keep_alive; - bool_t nat_helper_enabled; - bool_t tls_verify; - bool_t tls_verify_cn; - bool_t use_dates; - bool_t auto_contacts; - bool_t enable_test_features; - bool_t no_initial_route; - bool_t enable_sip_update; /*true by default*/ - SalOpSDPHandling default_sdp_handling; - bool_t pending_trans_checking; /*testing purpose*/ - void *ssl_config; - bctbx_list_t *supported_content_types; /* list of char* */ -}; -typedef enum SalOpState { - SalOpStateEarly=0 - ,SalOpStateActive - ,SalOpStateTerminating /*this state is used to wait until a proceeding state, so we can send the cancel*/ - ,SalOpStateTerminated -}SalOpState; - -const char* sal_op_state_to_string(SalOpState value); - -typedef enum SalOpDir { - SalOpDirIncoming=0 - ,SalOpDirOutgoing -}SalOpDir; -typedef enum SalOpType { - SalOpUnknown, - SalOpRegister, - SalOpCall, - SalOpMessage, - SalOpPresence, - SalOpPublish, - SalOpSubscribe -}SalOpType; - -const char* sal_op_type_to_string(SalOpType type); - -struct SalOp{ - SalOpBase base; - const belle_sip_listener_callbacks_t *callbacks; - SalErrorInfo error_info; - SalErrorInfo reason_error_info; - belle_sip_client_transaction_t *pending_auth_transaction; - belle_sip_server_transaction_t* pending_server_trans; - belle_sip_server_transaction_t* pending_update_server_trans; - belle_sip_client_transaction_t* pending_client_trans; - SalAuthInfo* auth_info; - belle_sip_dialog_t* dialog; - belle_sip_header_replaces_t *replaces; - belle_sip_header_referred_by_t *referred_by; - SalMediaDescription *result; - belle_sdp_session_description_t *sdp_answer; - SalOpState state; - SalOpDir dir; - belle_sip_refresher_t* refresher; - int ref; - SalOpType type; - SalPrivacyMask privacy; - belle_sip_header_event_t *event; /*used by SalOpSubscribe kinds*/ - SalOpSDPHandling sdp_handling; - int auth_requests; /*number of auth requested for this op*/ - bool_t cnx_ip_to_0000_if_sendonly_enabled; - bool_t auto_answer_asked; - bool_t sdp_offering; - bool_t call_released; - bool_t manual_refresher; - bool_t has_auth_pending; - bool_t supports_session_timers; - bool_t op_released; -}; - - -belle_sdp_session_description_t * media_description_to_sdp(const SalMediaDescription *sal); +belle_sdp_session_description_t * media_description_to_sdp(const SalMediaDescription *desc); int sdp_to_media_description(belle_sdp_session_description_t *sdp, SalMediaDescription *desc); -belle_sip_request_t* sal_op_build_request(SalOp *op,const char* method); - - -void sal_op_call_fill_cbs(SalOp*op); -void set_or_update_dialog(SalOp* op, belle_sip_dialog_t* dialog); - -/*return reffed op*/ -SalOp* sal_op_ref(SalOp* op); -/*return null, destroy op if ref count =0*/ -void* sal_op_unref(SalOp* op); -void sal_op_release_impl(SalOp *op); - -void sal_op_set_replaces(SalOp* op,belle_sip_header_replaces_t* replaces); -void sal_op_set_remote_ua(SalOp*op,belle_sip_message_t* message); -int sal_op_send_request(SalOp* op, belle_sip_request_t* request); -int sal_op_send_request_with_expires(SalOp* op, belle_sip_request_t* request,int expires); -void sal_op_resend_request(SalOp* op, belle_sip_request_t* request); -int sal_op_send_and_create_refresher(SalOp* op,belle_sip_request_t* req, int expires,belle_sip_refresher_listener_t listener ); -belle_sip_response_t *sal_op_create_response_from_request(SalOp *op, belle_sip_request_t *req, int code); - -/* - * return true if both from and to uri are sips - * */ -bool_t sal_op_is_secure(const SalOp* op); - -void sal_process_authentication(SalOp *op); -belle_sip_header_contact_t* sal_op_create_contact(SalOp *op) ; bool_t _sal_compute_sal_errors(belle_sip_response_t* response, SalReason* sal_reason, char* reason, size_t reason_size); SalReason _sal_reason_from_sip_code(int code); -void sal_op_set_reason_error_info(SalOp *op, belle_sip_message_t *msg); -void sal_op_set_error_info_from_response(SalOp *op, belle_sip_response_t *response); -/*presence*/ -void sal_op_presence_fill_cbs(SalOp*op); -/*messaging*/ -void sal_op_message_fill_cbs(SalOp*op); -void sal_process_incoming_message(SalOp *op,const belle_sip_request_event_t *event); -void sal_op_subscribe_fill_cbs(SalOp*op); - -/*call transfer*/ -void sal_op_process_refer(SalOp *op, const belle_sip_request_event_t *event, belle_sip_server_transaction_t *tr); -void sal_op_call_process_notify(SalOp *op, const belle_sip_request_event_t *event, belle_sip_server_transaction_t *tr); /*create SalAuthInfo by copying username and realm from suth event*/ SalAuthInfo* sal_auth_info_create(belle_sip_auth_event_t* event) ; -void sal_add_pending_auth(Sal *sal, SalOp *op); -void sal_remove_pending_auth(Sal *sal, SalOp *op); -void sal_add_presence_info(SalOp *op, belle_sip_message_t *notify, SalPresenceModel *presence); - -belle_sip_response_t *sal_create_response_from_request(Sal *sal, belle_sip_request_t *req, int code); - -void sal_op_assign_recv_headers(SalOp *op, belle_sip_message_t *incoming); - -SalBodyHandler * sal_op_get_body_handler(SalOp *op, belle_sip_message_t *msg); - -int sal_reason_to_sip_code(SalReason r); - -void _sal_op_add_custom_headers(SalOp *op, belle_sip_message_t *msg); - -SalSubscribeStatus belle_sip_message_get_subscription_state(const belle_sip_message_t *msg); #endif /* SAL_IMPL_H_ */ diff --git a/coreapi/bellesip_sal/sal_op_call.c b/coreapi/bellesip_sal/sal_op_call.c deleted file mode 100644 index d1fff0d83..000000000 --- a/coreapi/bellesip_sal/sal_op_call.c +++ /dev/null @@ -1,1240 +0,0 @@ -/* -linphone -Copyright (C) 2012 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 -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 "sal_impl.h" -#include "offeranswer.h" - -#include - -static int extract_sdp(SalOp* op,belle_sip_message_t* message,belle_sdp_session_description_t** session_desc, SalReason *error); - -/*used for calls terminated before creation of a dialog*/ -static void call_set_released(SalOp* op){ - if (!op->call_released){ - op->state=SalOpStateTerminated; - op->base.root->callbacks.call_released(op); - op->call_released=TRUE; - /*be aware that the following line may destroy the op*/ - set_or_update_dialog(op,NULL); - } -} - -static void call_set_error(SalOp* op,belle_sip_response_t* response, bool_t fatal){ - sal_op_set_error_info_from_response(op,response); - if (fatal) op->state = SalOpStateTerminating; - op->base.root->callbacks.call_failure(op); -} -static void set_addr_to_0000(char value[], size_t sz) { - if (ms_is_ipv6(value)) { - strncpy(value,"::0", sz); - } else { - strncpy(value,"0.0.0.0", sz); - } - return; -} -static void sdp_process(SalOp *h){ - ms_message("Doing SDP offer/answer process of type %s",h->sdp_offering ? "outgoing" : "incoming"); - if (h->result){ - sal_media_description_unref(h->result); - h->result = NULL; - } - - /* if SDP was invalid */ - if (h->base.remote_media == NULL) return; - - h->result=sal_media_description_new(); - if (h->sdp_offering){ - offer_answer_initiate_outgoing(h->base.root->factory, h->base.local_media,h->base.remote_media,h->result); - }else{ - int i; - if (h->sdp_answer){ - belle_sip_object_unref(h->sdp_answer); - } - offer_answer_initiate_incoming(h->base.root->factory, h->base.local_media,h->base.remote_media,h->result,h->base.root->one_matching_codec); - /*for backward compatibility purpose*/ - if(h->cnx_ip_to_0000_if_sendonly_enabled && sal_media_description_has_dir(h->result,SalStreamSendOnly)) { - set_addr_to_0000(h->result->addr, sizeof(h->result->addr)); - for(i=0;iresult->streams[i].dir == SalStreamSendOnly) { - set_addr_to_0000(h->result->streams[i].rtp_addr, sizeof(h->result->streams[i].rtp_addr)); - set_addr_to_0000(h->result->streams[i].rtcp_addr, sizeof(h->result->streams[i].rtcp_addr)); - } - } - } - h->sdp_answer=(belle_sdp_session_description_t *)belle_sip_object_ref(media_description_to_sdp(h->result)); - /*once we have generated the SDP answer, we modify the result description for processing by the upper layer. - It should contains media parameters constraint from the remote offer, not our response*/ - strcpy(h->result->addr,h->base.remote_media->addr); - h->result->bandwidth=h->base.remote_media->bandwidth; - - for(i=0;iresult->streams[i].rtp_port!=0){ /*if stream was accepted*/ - strcpy(h->result->streams[i].rtp_addr,h->base.remote_media->streams[i].rtp_addr); - h->result->streams[i].ptime=h->base.remote_media->streams[i].ptime; - h->result->streams[i].bandwidth=h->base.remote_media->streams[i].bandwidth; - h->result->streams[i].rtp_port=h->base.remote_media->streams[i].rtp_port; - strcpy(h->result->streams[i].rtcp_addr,h->base.remote_media->streams[i].rtcp_addr); - h->result->streams[i].rtcp_port=h->base.remote_media->streams[i].rtcp_port; - - if (sal_stream_description_has_srtp(&h->result->streams[i])) { - h->result->streams[i].crypto[0] = h->base.remote_media->streams[i].crypto[0]; - } - } - } - } -} - -static int set_sdp(belle_sip_message_t *msg,belle_sdp_session_description_t* session_desc) { - belle_sip_header_content_type_t* content_type ; - belle_sip_header_content_length_t* content_length; - belle_sip_error_code error = BELLE_SIP_BUFFER_OVERFLOW; - size_t length = 0; - - if (session_desc) { - size_t bufLen = 2048; - size_t hardlimit = 16*1024; /* 16k SDP limit seems reasonable */ - char* buff = reinterpret_cast(belle_sip_malloc(bufLen)); - content_type = belle_sip_header_content_type_create("application","sdp"); - - /* try to marshal the description. This could go higher than 2k so we iterate */ - while( error != BELLE_SIP_OK && bufLen <= hardlimit && buff != NULL){ - error = belle_sip_object_marshal(BELLE_SIP_OBJECT(session_desc),buff,bufLen,&length); - if( error != BELLE_SIP_OK ){ - bufLen *= 2; - length = 0; - buff = reinterpret_cast(belle_sip_realloc(buff,bufLen)); - } - } - /* give up if hard limit reached */ - if (error != BELLE_SIP_OK || buff == NULL) { - ms_error("Buffer too small (%d) or not enough memory, giving up SDP", (int)bufLen); - return -1; - } - - content_length = belle_sip_header_content_length_create(length); - belle_sip_message_add_header(msg,BELLE_SIP_HEADER(content_type)); - belle_sip_message_add_header(msg,BELLE_SIP_HEADER(content_length)); - belle_sip_message_assign_body(msg,buff,length); - return 0; - } else { - return -1; - } -} -static int set_sdp_from_desc(belle_sip_message_t *msg, const SalMediaDescription *desc){ - int err; - belle_sdp_session_description_t *sdp=media_description_to_sdp(desc); - err=set_sdp(msg,sdp); - belle_sip_object_unref(sdp); - return err; - -} - -static void call_process_io_error(void *user_ctx, const belle_sip_io_error_event_t *event) { - SalOp *op = (SalOp *)user_ctx; - - if (op->state == SalOpStateTerminated) return; - - if (op->pending_client_trans && (belle_sip_transaction_get_state(BELLE_SIP_TRANSACTION(op->pending_client_trans)) == BELLE_SIP_TRANSACTION_INIT)) { - - sal_error_info_set(&op->error_info, SalReasonIOError, "SIP", 503, "IO error", NULL); - op->base.root->callbacks.call_failure(op); - - if (!op->dialog || belle_sip_dialog_get_state(op->dialog) != BELLE_SIP_DIALOG_CONFIRMED){ - /* Call terminated very very early, before INVITE is even sent, probably DNS resolution timeout. */ - op->state = SalOpStateTerminating; - call_set_released(op); - } - } else { - /* Nothing to be done. If the error comes from a connectivity loss, - * the call will be marked as broken, and an attempt to repair it will be done. */ - } -} - -static void process_dialog_terminated(void *ctx, const belle_sip_dialog_terminated_event_t *event) { - SalOp* op=(SalOp*)ctx; - - if (op->dialog && op->dialog==belle_sip_dialog_terminated_event_get_dialog(event)) { - /*belle_sip_transaction_t* trans=belle_sip_dialog_get_last_transaction(op->dialog);*/ - ms_message("Dialog [%p] terminated for op [%p]",belle_sip_dialog_terminated_event_get_dialog(event),op); - - switch(belle_sip_dialog_get_previous_state(op->dialog)) { - case BELLE_SIP_DIALOG_EARLY: - case BELLE_SIP_DIALOG_NULL: - if (op->state!=SalOpStateTerminated && op->state!=SalOpStateTerminating) { - /*this is an early termination due to incorrect response received*/ - op->base.root->callbacks.call_failure(op); - op->state=SalOpStateTerminating; - } - break; - case BELLE_SIP_DIALOG_CONFIRMED: - if (op->state!=SalOpStateTerminated && op->state!=SalOpStateTerminating) { - /*this is probably a normal termination from a BYE*/ - op->base.root->callbacks.call_terminated(op,op->dir==SalOpDirIncoming?sal_op_get_from(op):sal_op_get_to(op)); - op->state=SalOpStateTerminating; - } - break; - default: - break; - } - belle_sip_main_loop_do_later(belle_sip_stack_get_main_loop(op->base.root->stack) - ,(belle_sip_callback_t) call_set_released - , op); - } else { - ms_error("dialog unknown for op "); - } -} - -static void handle_sdp_from_response(SalOp* op,belle_sip_response_t* response) { - belle_sdp_session_description_t* sdp; - SalReason reason; - if (op->base.remote_media){ - sal_media_description_unref(op->base.remote_media); - op->base.remote_media=NULL; - } - if (extract_sdp(op,BELLE_SIP_MESSAGE(response),&sdp,&reason)==0) { - if (sdp){ - op->base.remote_media=sal_media_description_new(); - sdp_to_media_description(sdp,op->base.remote_media); - }/*if no sdp in response, what can we do ?*/ - } - /* process sdp in any case to reset result media description*/ - if (op->base.local_media) sdp_process(op); -} - -void sal_call_cancel_invite(SalOp *op) { - sal_call_cancel_invite_with_info(op,NULL); -} - -static void cancelling_invite(SalOp *op, const SalErrorInfo *info) { - sal_call_cancel_invite_with_info(op, info); - op->state=SalOpStateTerminating; -} - -static int vfu_retry (void *user_data, unsigned int events) { - SalOp *op=(SalOp *)user_data; - sal_call_send_vfu_request(op); - sal_op_unref(op); - return BELLE_SIP_STOP; -} - -static void call_process_response(void *op_base, const belle_sip_response_event_t *event){ - SalOp* op = (SalOp*)op_base; - belle_sip_request_t* ack; - belle_sip_dialog_state_t dialog_state; - belle_sip_client_transaction_t* client_transaction = belle_sip_response_event_get_client_transaction(event); - belle_sip_request_t* req; - belle_sip_response_t* response=belle_sip_response_event_get_response(event); - int code = belle_sip_response_get_status_code(response); - belle_sip_header_content_type_t *header_content_type=NULL; - belle_sip_dialog_t *dialog=belle_sip_response_event_get_dialog(event); - const char *method; - - if (!client_transaction) { - ms_warning("Discarding stateless response [%i] on op [%p]",code,op); - return; - } - req=belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(client_transaction)); - set_or_update_dialog(op,dialog); - dialog_state=dialog ? belle_sip_dialog_get_state(dialog) : BELLE_SIP_DIALOG_NULL; - method=belle_sip_request_get_method(req); - ms_message("Op [%p] receiving call response [%i], dialog is [%p] in state [%s]",op,code,dialog,belle_sip_dialog_state_to_string(dialog_state)); - /*to make sure no cb will destroy op*/ - sal_op_ref(op); - switch(dialog_state) { - case BELLE_SIP_DIALOG_NULL: - case BELLE_SIP_DIALOG_EARLY: { - if (strcmp("INVITE",method)==0 ) { - if (op->state == SalOpStateTerminating) { - /*check if CANCEL was sent before*/ - if (strcmp("CANCEL",belle_sip_request_get_method(belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(op->pending_client_trans))))!=0) { - /*it wasn't sent */ - if (code<200) { - cancelling_invite(op, NULL); - }else{ - /* no need to send the INVITE because the UAS rejected the INVITE*/ - if (op->dialog==NULL) call_set_released(op); - } - } else { - /*it was sent already, so just expect the 487 or any error response to send the call_released() notification*/ - if (code>=300){ - if (op->dialog==NULL) call_set_released(op); - } - } - } else if (code >= 180 && code<200) { - belle_sip_response_t *prev_response=reinterpret_cast(belle_sip_object_data_get(BELLE_SIP_OBJECT(dialog),"early_response")); - if (!prev_response || code>belle_sip_response_get_status_code(prev_response)){ - handle_sdp_from_response(op,response); - op->base.root->callbacks.call_ringing(op); - } - belle_sip_object_data_set(BELLE_SIP_OBJECT(dialog),"early_response",belle_sip_object_ref(response),belle_sip_object_unref); - } else if (code>=300){ - call_set_error(op, response, TRUE); - if (op->dialog==NULL) call_set_released(op); - } - } else if (code >=200 && code<300) { - if (strcmp("UPDATE",method)==0) { - handle_sdp_from_response(op,response); - op->base.root->callbacks.call_accepted(op); - } else if (strcmp("CANCEL", method) == 0) { - op->base.root->callbacks.call_cancel_done(op); - } - } - } - break; - case BELLE_SIP_DIALOG_CONFIRMED: { - switch (op->state) { - case SalOpStateEarly:/*invite case*/ - case SalOpStateActive: /*re-invite, INFO, UPDATE case*/ - if (strcmp("INVITE",method)==0){ - if (code >=200 && code<300) { - handle_sdp_from_response(op,response); - ack=belle_sip_dialog_create_ack(op->dialog,belle_sip_dialog_get_local_seq_number(op->dialog)); - if (ack == NULL) { - ms_error("This call has been already terminated."); - return ; - } - if (op->sdp_answer){ - set_sdp(BELLE_SIP_MESSAGE(ack),op->sdp_answer); - belle_sip_object_unref(op->sdp_answer); - op->sdp_answer=NULL; - } - belle_sip_message_add_header(BELLE_SIP_MESSAGE(ack),BELLE_SIP_HEADER(op->base.root->user_agent)); - op->base.root->callbacks.call_accepted(op); /*INVITE*/ - op->base.root->callbacks.call_ack_being_sent(op, (SalCustomHeader*)ack); - belle_sip_dialog_send_ack(op->dialog,ack); - op->state=SalOpStateActive; - }else if (code >= 300){ - call_set_error(op,response, FALSE); - } - }else if (strcmp("INFO",method)==0){ - if (code == 491 - && (header_content_type = belle_sip_message_get_header_by_type(req,belle_sip_header_content_type_t)) - && strcmp("application",belle_sip_header_content_type_get_type(header_content_type))==0 - && strcmp("media_control+xml",belle_sip_header_content_type_get_subtype(header_content_type))==0) { - unsigned int retry_in = (unsigned int)(1000*((float)rand()/(float)RAND_MAX)); - belle_sip_source_t *s=sal_create_timer(op->base.root,vfu_retry,sal_op_ref(op), retry_in, "vfu request retry"); - ms_message("Rejected vfu request on op [%p], just retry in [%ui] ms",op,retry_in); - belle_sip_object_unref(s); - }else { - /*ignoring*/ - } - }else if (strcmp("UPDATE",method)==0){ - op->base.root->callbacks.call_accepted(op); /*INVITE*/ - }else if (strcmp("CANCEL",method)==0){ - op->base.root->callbacks.call_cancel_done(op); - } - break; - case SalOpStateTerminating: - sal_op_send_request(op,belle_sip_dialog_create_request(op->dialog,"BYE")); - break; - case SalOpStateTerminated: - default: - ms_error("Call op [%p] receives unexpected answer [%i] while in state [%s].",op,code, sal_op_state_to_string(op->state)); - } - } - break; - case BELLE_SIP_DIALOG_TERMINATED: { - if (strcmp("INVITE",method)==0 && code >= 300){ - call_set_error(op,response, TRUE); - } - } - break; - default: { - ms_error("call op [%p] receive answer [%i] not implemented",op,code); - } - break; - } - sal_op_unref(op); -} - -static void call_process_timeout(void *user_ctx, const belle_sip_timeout_event_t *event) { - SalOp* op=(SalOp*)user_ctx; - - if (op->state==SalOpStateTerminated) return; - - if (!op->dialog) { - /*call terminated very early*/ - sal_error_info_set(&op->error_info, SalReasonRequestTimeout, "SIP", 408, "Request timeout", NULL); - op->base.root->callbacks.call_failure(op); - op->state = SalOpStateTerminating; - call_set_released(op); - } else { - /*dialog will terminated shortly, nothing to do*/ - } -} - -static void call_process_transaction_terminated(void *user_ctx, const belle_sip_transaction_terminated_event_t *event) { - SalOp* op = (SalOp*)user_ctx; - belle_sip_client_transaction_t *client_transaction=belle_sip_transaction_terminated_event_get_client_transaction(event); - belle_sip_server_transaction_t *server_transaction=belle_sip_transaction_terminated_event_get_server_transaction(event); - belle_sip_request_t* req; - belle_sip_response_t* resp; - int code = 0; - bool_t release_call=FALSE; - - if (client_transaction) { - req=belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(client_transaction)); - resp=belle_sip_transaction_get_response(BELLE_SIP_TRANSACTION(client_transaction)); - } else { - req=belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(server_transaction)); - resp=belle_sip_transaction_get_response(BELLE_SIP_TRANSACTION(server_transaction)); - } - if (resp) code = belle_sip_response_get_status_code(resp); - - if (op->state == SalOpStateTerminating - && strcmp("BYE",belle_sip_request_get_method(req))==0 - && (!resp || (belle_sip_response_get_status_code(resp) != 401 - && belle_sip_response_get_status_code(resp) != 407)) - && op->dialog==NULL) { - release_call=TRUE; - }else if (op->state == SalOpStateEarly && code < 200){ - /*call terminated early*/ - sal_error_info_set(&op->error_info, SalReasonIOError, "SIP", 503, "I/O error", NULL); - op->state = SalOpStateTerminating; - op->base.root->callbacks.call_failure(op); - release_call=TRUE; - } - if (server_transaction){ - if (op->pending_server_trans==server_transaction){ - belle_sip_object_unref(op->pending_server_trans); - op->pending_server_trans=NULL; - } - if (op->pending_update_server_trans==server_transaction){ - belle_sip_object_unref(op->pending_update_server_trans); - op->pending_update_server_trans=NULL; - } - } - if (release_call) call_set_released(op); -} - -static void call_terminated(SalOp* op,belle_sip_server_transaction_t* server_transaction, int status_code, belle_sip_request_t* cancel_request) { - belle_sip_response_t* resp; - belle_sip_request_t* server_req = belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(server_transaction)); - op->state = SalOpStateTerminating; - sal_op_set_reason_error_info(op, BELLE_SIP_MESSAGE(cancel_request ? cancel_request : server_req)); - resp=sal_op_create_response_from_request(op,server_req,status_code); - belle_sip_server_transaction_send_response(server_transaction,resp); - op->base.root->callbacks.call_terminated(op,op->dir==SalOpDirIncoming?sal_op_get_from(op):sal_op_get_to(op)); -} - -static void unsupported_method(belle_sip_server_transaction_t* server_transaction,belle_sip_request_t* request) { - belle_sip_response_t* resp; - resp=belle_sip_response_create_from_request(request,501); - belle_sip_server_transaction_send_response(server_transaction,resp); - return; -} - -/* - * Extract the sdp from a sip message. - * If there is no body in the message, the session_desc is set to null, 0 is returned. - * If body was present is not a SDP or parsing of SDP failed, -1 is returned and SalReason is set appropriately. - * -**/ -static int extract_sdp(SalOp *op, belle_sip_message_t* message,belle_sdp_session_description_t** session_desc, SalReason *error) { - const char *body; - belle_sip_header_content_type_t* content_type; - - if (op&&op->sdp_handling == SalOpSDPSimulateError){ - ms_error("Simulating SDP parsing error for op %p", op); - *session_desc=NULL; - *error=SalReasonNotAcceptable; - return -1; - } else if( op && op->sdp_handling == SalOpSDPSimulateRemove){ - ms_error("Simulating no SDP for op %p", op); - *session_desc = NULL; - return 0; - } - - body = belle_sip_message_get_body(message); - if(body == NULL) { - *session_desc = NULL; - return 0; - } - - content_type = belle_sip_message_get_header_by_type(message,belle_sip_header_content_type_t); - if (content_type){ - if (strcmp("application",belle_sip_header_content_type_get_type(content_type))==0 - && strcmp("sdp",belle_sip_header_content_type_get_subtype(content_type))==0) { - *session_desc=belle_sdp_session_description_parse(body); - if (*session_desc==NULL) { - ms_error("Failed to parse SDP message."); - *error=SalReasonNotAcceptable; - return -1; - } - }else{ - *error=SalReasonUnsupportedContent; - return -1; - } - }else *session_desc=NULL; - return 0; -} - -static int is_media_description_acceptable(SalMediaDescription *md){ - if (md->nb_streams==0){ - ms_warning("Media description does not define any stream."); - return FALSE; - } - return TRUE; -} - -static SalReason process_sdp_for_invite(SalOp* op,belle_sip_request_t* invite) { - belle_sdp_session_description_t* sdp; - SalReason reason = SalReasonNone; - SalErrorInfo sei; - - memset(&sei, 0, sizeof(sei)); - if (extract_sdp(op,BELLE_SIP_MESSAGE(invite),&sdp,&reason)==0) { - if (sdp){ - op->sdp_offering=FALSE; - op->base.remote_media=sal_media_description_new(); - sdp_to_media_description(sdp,op->base.remote_media); - /*make some sanity check about the SDP received*/ - if (!is_media_description_acceptable(op->base.remote_media)){ - reason=SalReasonNotAcceptable; - } - belle_sip_object_unref(sdp); - }else op->sdp_offering=TRUE; /*INVITE without SDP*/ - } - - if (reason != SalReasonNone){ - sal_error_info_set(&sei, reason,"SIP", 0, NULL, NULL); - sal_call_decline_with_error_info(op, &sei,NULL); - sal_error_info_reset(&sei); - } - return reason; -} - -static void sal_op_reset_descriptions(SalOp *op) { - if (op->base.remote_media){ - sal_media_description_unref(op->base.remote_media); - op->base.remote_media=NULL; - } - if (op->result){ - sal_media_description_unref(op->result); - op->result=NULL; - } -} - -static bool_t is_a_pending_invite_incoming_transaction(belle_sip_transaction_t *tr){ - return BELLE_SIP_OBJECT_IS_INSTANCE_OF(tr, belle_sip_ist_t) && belle_sip_transaction_state_is_transient( - belle_sip_transaction_get_state(tr)); -} - -static void process_request_event(void *op_base, const belle_sip_request_event_t *event) { - SalOp* op = (SalOp*)op_base; - SalReason reason; - belle_sip_server_transaction_t* server_transaction=NULL; - belle_sdp_session_description_t* sdp; - belle_sip_request_t* req = belle_sip_request_event_get_request(event); - belle_sip_dialog_state_t dialog_state; - belle_sip_response_t* resp; - belle_sip_header_t* call_info; - const char *method=belle_sip_request_get_method(req); - bool_t is_update=FALSE; - bool_t drop_op = FALSE; - - if (strcmp("ACK",method)!=0){ /*ACK doesn't create a server transaction*/ - server_transaction = belle_sip_provider_create_server_transaction(op->base.root->prov,belle_sip_request_event_get_request(event)); - belle_sip_object_ref(server_transaction); - belle_sip_transaction_set_application_data(BELLE_SIP_TRANSACTION(server_transaction),sal_op_ref(op)); - } - - if (strcmp("INVITE",method)==0) { - if (op->pending_server_trans) belle_sip_object_unref(op->pending_server_trans); - /*updating pending invite transaction*/ - op->pending_server_trans=server_transaction; - belle_sip_object_ref(op->pending_server_trans); - } - - if (strcmp("UPDATE",method)==0) { - if (op->pending_update_server_trans) belle_sip_object_unref(op->pending_update_server_trans); - /*updating pending update transaction*/ - op->pending_update_server_trans=server_transaction; - belle_sip_object_ref(op->pending_update_server_trans); - } - - if (!op->dialog) { - set_or_update_dialog(op,belle_sip_provider_create_dialog(op->base.root->prov,BELLE_SIP_TRANSACTION(op->pending_server_trans))); - ms_message("new incoming call from [%s] to [%s]",sal_op_get_from(op),sal_op_get_to(op)); - } - dialog_state=belle_sip_dialog_get_state(op->dialog); - switch(dialog_state) { - case BELLE_SIP_DIALOG_NULL: { - if (strcmp("INVITE",method)==0) { - if (!op->replaces && (op->replaces=belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req),belle_sip_header_replaces_t))) { - belle_sip_object_ref(op->replaces); - } else if(op->replaces) { - ms_warning("replace header already set"); - } - - if ( (reason = process_sdp_for_invite(op,req)) == SalReasonNone) { - if ((call_info=belle_sip_message_get_header(BELLE_SIP_MESSAGE(req),"Call-Info"))) { - if( strstr(belle_sip_header_get_unparsed_value(call_info),"answer-after=") != NULL) { - op->auto_answer_asked=TRUE; - ms_message("The caller asked to automatically answer the call(Emergency?)\n"); - } - } - op->base.root->callbacks.call_received(op); - }else{ - sal_error_info_set(&op->error_info, reason, "SIP", 0, NULL, NULL); - op->base.root->callbacks.call_rejected(op); - /*the INVITE was declined by process_sdp_for_invite(). As we are not inside an established dialog, we can drop the op immediately*/ - drop_op = TRUE; - } - break; - }BCTBX_NO_BREAK; /* else same behavior as for EARLY state, thus NO BREAK*/ - } - case BELLE_SIP_DIALOG_EARLY: { - if (strcmp("CANCEL",method)==0) { - if(belle_sip_request_event_get_server_transaction(event)) { - /*first answer 200 ok to cancel*/ - belle_sip_server_transaction_send_response(server_transaction - ,sal_op_create_response_from_request(op,req,200)); - /*terminate invite transaction*/ - call_terminated(op,op->pending_server_trans,487,req); - } else { - /*call leg does not exist*/ - belle_sip_server_transaction_send_response(server_transaction - ,sal_op_create_response_from_request(op,req,481)); - } - } else if (strcmp("PRACK",method)==0) { - resp=sal_op_create_response_from_request(op,req,200); - belle_sip_server_transaction_send_response(server_transaction,resp); - } else if (strcmp("UPDATE",method)==0) { - sal_op_reset_descriptions(op); - if (process_sdp_for_invite(op,req)==SalReasonNone) - op->base.root->callbacks.call_updating(op,TRUE); - } else { - belle_sip_error("Unexpected method [%s] for dialog state BELLE_SIP_DIALOG_EARLY",belle_sip_request_get_method(req)); - unsupported_method(server_transaction,req); - } - break; - } - case BELLE_SIP_DIALOG_CONFIRMED: - /*great ACK received*/ - if (strcmp("ACK",method)==0) { - if (!op->pending_client_trans || - !belle_sip_transaction_state_is_transient(belle_sip_transaction_get_state((belle_sip_transaction_t*)op->pending_client_trans))){ - if (op->sdp_offering){ - SalReason reason; - if (extract_sdp(op,BELLE_SIP_MESSAGE(req),&sdp,&reason)==0){ - if (sdp){ - if (op->base.remote_media) - sal_media_description_unref(op->base.remote_media); - op->base.remote_media=sal_media_description_new(); - sdp_to_media_description(sdp,op->base.remote_media); - sdp_process(op); - belle_sip_object_unref(sdp); - }else{ - ms_warning("SDP expected in ACK but not found."); - } - } - } - op->base.root->callbacks.call_ack_received(op, (SalCustomHeader*)req); - }else{ - ms_message("Ignored received ack since a new client transaction has been started since."); - } - } else if(strcmp("BYE",method)==0) { - call_terminated(op,server_transaction,200,req); - /*call end not notified by dialog deletion because transaction can end before dialog*/ - } else if(strcmp("INVITE",method)==0 || (is_update=(strcmp("UPDATE",method)==0)) ) { - if (is_update && !belle_sip_message_get_body(BELLE_SIP_MESSAGE(req))) { - /*session timer case*/ - /*session expire should be handled. to be done when real session timer (rfc4028) will be implemented*/ - resp=sal_op_create_response_from_request(op,req,200); - belle_sip_server_transaction_send_response(server_transaction,resp); - belle_sip_object_unref(op->pending_update_server_trans); - op->pending_update_server_trans=NULL; - } else { - /*re-invite*/ - sal_op_reset_descriptions(op); - if (process_sdp_for_invite(op,req)==SalReasonNone) - op->base.root->callbacks.call_updating(op,is_update); - } - } else if (strcmp("INFO",method)==0){ - if (belle_sip_message_get_body(BELLE_SIP_MESSAGE(req)) - && strstr(belle_sip_message_get_body(BELLE_SIP_MESSAGE(req)),"picture_fast_update")) { - /*vfu request*/ - ms_message("Receiving VFU request on op [%p]",op); - if (op->base.root->callbacks.vfu_request){ - op->base.root->callbacks.vfu_request(op); - - } - }else{ - belle_sip_message_t *msg = BELLE_SIP_MESSAGE(req); - belle_sip_body_handler_t *body_handler = BELLE_SIP_BODY_HANDLER(sal_op_get_body_handler(op, msg)); - if (body_handler) { - belle_sip_header_content_type_t *content_type = belle_sip_message_get_header_by_type(msg, belle_sip_header_content_type_t); - if (content_type - && (strcmp(belle_sip_header_content_type_get_type(content_type), "application") == 0) - && (strcmp(belle_sip_header_content_type_get_subtype(content_type), "dtmf-relay") == 0)) { - char tmp[10]; - if (sal_lines_get_value(belle_sip_message_get_body(msg), "Signal",tmp, sizeof(tmp))){ - op->base.root->callbacks.dtmf_received(op,tmp[0]); - } - }else - op->base.root->callbacks.info_received(op, (SalBodyHandler *)body_handler); - } else { - op->base.root->callbacks.info_received(op,NULL); - } - } - resp=sal_op_create_response_from_request(op,req,200); - belle_sip_server_transaction_send_response(server_transaction,resp); - }else if (strcmp("REFER",method)==0) { - sal_op_process_refer(op,event,server_transaction); - } else if (strcmp("NOTIFY",method)==0) { - sal_op_call_process_notify(op,event,server_transaction); - } else if (strcmp("OPTIONS",method)==0) { - resp=sal_op_create_response_from_request(op,req,200); - belle_sip_server_transaction_send_response(server_transaction,resp); - } else if (strcmp("CANCEL",method)==0) { - belle_sip_transaction_t *last_transaction = belle_sip_dialog_get_last_transaction(op->dialog); - if (last_transaction == NULL || !is_a_pending_invite_incoming_transaction(last_transaction) ) { - /*call leg does not exist because 200ok already sent*/ - belle_sip_server_transaction_send_response(server_transaction,sal_op_create_response_from_request(op,req,481)); - } else { - /* CANCEL on re-INVITE for which a 200ok has not been sent yet */ - belle_sip_server_transaction_send_response(server_transaction, sal_op_create_response_from_request(op, req, 200)); - belle_sip_server_transaction_send_response(BELLE_SIP_SERVER_TRANSACTION(last_transaction), - sal_op_create_response_from_request(op, belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(last_transaction)), 487)); - } - } else if (strcmp("MESSAGE",method)==0){ - sal_process_incoming_message(op,event); - }else{ - ms_error("unexpected method [%s] for dialog [%p]",belle_sip_request_get_method(req),op->dialog); - unsupported_method(server_transaction,req); - } - break; - default: - ms_error("unexpected dialog state [%s]",belle_sip_dialog_state_to_string(dialog_state)); - break; - } - - if (server_transaction) belle_sip_object_unref(server_transaction); - if (drop_op) sal_op_release(op); -} - - -/*Call API*/ -int sal_call_set_local_media_description(SalOp *op, SalMediaDescription *desc){ - if (desc) - sal_media_description_ref(desc); - if (op->base.local_media) - sal_media_description_unref(op->base.local_media); - op->base.local_media=desc; - - if (op->base.remote_media){ - /*case of an incoming call where we modify the local capabilities between the time - * the call is ringing and it is accepted (for example if you want to accept without video*/ - /*reset the sdp answer so that it is computed again*/ - if (op->sdp_answer){ - belle_sip_object_unref(op->sdp_answer); - op->sdp_answer=NULL; - } - } - return 0; -} - -static belle_sip_header_allow_t *create_allow(bool_t enable_update){ - belle_sip_header_allow_t* header_allow; - char allow [256]; - snprintf(allow,sizeof(allow),"INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, NOTIFY, MESSAGE, SUBSCRIBE, INFO%s",(enable_update?", UPDATE":"")); - header_allow = belle_sip_header_allow_create(allow); - return header_allow; -} - -static void sal_op_fill_invite(SalOp *op, belle_sip_request_t* invite) { - belle_sip_message_add_header(BELLE_SIP_MESSAGE(invite),BELLE_SIP_HEADER(create_allow(op->base.root->enable_sip_update))); - - if (op->base.root->session_expires!=0){ - belle_sip_message_add_header(BELLE_SIP_MESSAGE(invite),belle_sip_header_create( "Session-expires", "600;refresher=uas")); - belle_sip_message_add_header(BELLE_SIP_MESSAGE(invite),belle_sip_header_create( "Supported", "timer")); - } - if (op->base.local_media){ - op->sdp_offering=TRUE; - set_sdp_from_desc(BELLE_SIP_MESSAGE(invite),op->base.local_media); - }else op->sdp_offering=FALSE; - return; -} - -int sal_call(SalOp *op, const char *from, const char *to, const char *subject){ - belle_sip_request_t* invite; - op->dir=SalOpDirOutgoing; - - sal_op_set_from(op,from); - sal_op_set_to(op,to); - - ms_message("[%s] calling [%s] on op [%p]", from, to, op); - invite=sal_op_build_request(op,"INVITE"); - - if( invite == NULL ){ - /* can happen if the op has an invalid address */ - return -1; - } - - sal_op_fill_invite(op,invite); - if (subject) - belle_sip_message_add_header(BELLE_SIP_MESSAGE(invite), belle_sip_header_create("Subject", subject)); - - sal_op_call_fill_cbs(op); - if (op->replaces){ - belle_sip_message_add_header(BELLE_SIP_MESSAGE(invite),BELLE_SIP_HEADER(op->replaces)); - } - if (op->referred_by) - belle_sip_message_add_header(BELLE_SIP_MESSAGE(invite),BELLE_SIP_HEADER(op->referred_by)); - - return sal_op_send_request(op,invite); -} - -static belle_sip_listener_callbacks_t call_op_callbacks={0}; - -void sal_op_call_fill_cbs(SalOp*op) { - if (call_op_callbacks.process_response_event==NULL){ - call_op_callbacks.process_io_error=call_process_io_error; - call_op_callbacks.process_response_event=call_process_response; - call_op_callbacks.process_timeout=call_process_timeout; - call_op_callbacks.process_transaction_terminated=call_process_transaction_terminated; - call_op_callbacks.process_request_event=process_request_event; - call_op_callbacks.process_dialog_terminated=process_dialog_terminated; - } - op->callbacks=&call_op_callbacks; - op->type=SalOpCall; -} - -static void handle_offer_answer_response(SalOp* op, belle_sip_response_t* response) { - if (op->base.local_media){ - /*this is the case where we received an invite without SDP*/ - if (op->sdp_offering) { - set_sdp_from_desc(BELLE_SIP_MESSAGE(response),op->base.local_media); - }else{ - - if ( op->sdp_answer==NULL ) - { - if( op->sdp_handling == SalOpSDPSimulateRemove ){ - ms_warning("Simulating SDP removal in answer for op %p", op); - } else { - sdp_process(op); - } - } - - if (op->sdp_answer){ - set_sdp(BELLE_SIP_MESSAGE(response),op->sdp_answer); - belle_sip_object_unref(op->sdp_answer); - op->sdp_answer=NULL; - } - } - }else{ - ms_error("You are accepting a call but not defined any media capabilities !"); - } -} - -int sal_call_notify_ringing(SalOp *op, bool_t early_media){ - int status_code =early_media?183:180; - belle_sip_request_t* req=belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(op->pending_server_trans)); - belle_sip_response_t* ringing_response = sal_op_create_response_from_request(op,req,status_code); - belle_sip_header_t *require; - const char *tags=NULL; - - if (early_media){ - handle_offer_answer_response(op,ringing_response); - } - require=belle_sip_message_get_header((belle_sip_message_t*)req,"Require"); - if (require) tags=belle_sip_header_get_unparsed_value(require); - /* if client requires 100rel, then add necessary stuff*/ - if (tags && strstr(tags,"100rel")!=0) { - belle_sip_message_add_header((belle_sip_message_t*)ringing_response,belle_sip_header_create("Require","100rel")); - belle_sip_message_add_header((belle_sip_message_t*)ringing_response,belle_sip_header_create("RSeq","1")); - } - -#ifndef SAL_OP_CALL_FORCE_CONTACT_IN_RINGING - if (tags && strstr(tags,"100rel")!=0) -#endif - { - belle_sip_header_address_t* contact= (belle_sip_header_address_t*)sal_op_get_contact_address(op); - belle_sip_header_contact_t* contact_header; - if (contact && (contact_header=belle_sip_header_contact_create(contact))) { - belle_sip_message_add_header(BELLE_SIP_MESSAGE(ringing_response),BELLE_SIP_HEADER(contact_header)); - } - } - belle_sip_server_transaction_send_response(op->pending_server_trans,ringing_response); - return 0; -} - - -/*accept an incoming call or, during a call accept a reINVITE*/ -int sal_call_accept(SalOp*h){ - belle_sip_response_t *response; - belle_sip_header_contact_t* contact_header; - belle_sip_server_transaction_t* transaction; - - /*first check if an UPDATE transaction need to be accepted*/ - if (h->pending_update_server_trans) { - transaction=h->pending_update_server_trans; - } else if (h->pending_server_trans) { - /*so it must be an invite/re-invite*/ - transaction=h->pending_server_trans; - } else { - ms_error("No transaction to accept for op [%p]",h); - return -1; - } - ms_message("Accepting server transaction [%p] on op [%p]", transaction, h); - - /* sends a 200 OK */ - response = sal_op_create_response_from_request(h,belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(transaction)),200); - if (response==NULL){ - ms_error("Fail to build answer for call"); - return -1; - } - belle_sip_message_add_header(BELLE_SIP_MESSAGE(response),BELLE_SIP_HEADER(create_allow(h->base.root->enable_sip_update))); - if (h->base.root->session_expires!=0){ -/* if (h->supports_session_timers) {*/ - belle_sip_message_add_header(BELLE_SIP_MESSAGE(response),belle_sip_header_create("Supported", "timer")); - belle_sip_message_add_header(BELLE_SIP_MESSAGE(response),belle_sip_header_create( "Session-expires", "600;refresher=uac")); - /*}*/ - } - - if ((contact_header=sal_op_create_contact(h))) { - belle_sip_message_add_header(BELLE_SIP_MESSAGE(response),BELLE_SIP_HEADER(contact_header)); - } - - _sal_op_add_custom_headers(h, BELLE_SIP_MESSAGE(response)); - - handle_offer_answer_response(h,response); - - belle_sip_server_transaction_send_response(transaction,response); - if (h->pending_update_server_trans) { - belle_sip_object_unref(h->pending_update_server_trans); - h->pending_update_server_trans=NULL; - } - if (h->state == SalOpStateEarly){ - h->state = SalOpStateActive; - } - return 0; -} - -static belle_sip_header_reason_t *sal_call_make_reason_header( const SalErrorInfo *info){ - if (info != NULL){ - belle_sip_header_reason_t* reason = BELLE_SIP_HEADER_REASON(belle_sip_header_reason_new()); - belle_sip_header_reason_set_text(reason, info->status_string); - belle_sip_header_reason_set_protocol(reason,info->protocol); - belle_sip_header_reason_set_cause(reason,info->protocol_code); - return reason; - } - return NULL; -} - -void sal_call_cancel_invite_with_info(SalOp* op, const SalErrorInfo *info) { - belle_sip_request_t* cancel; - ms_message("Cancelling INVITE request from [%s] to [%s] ",sal_op_get_from(op), sal_op_get_to(op)); - cancel = belle_sip_client_transaction_create_cancel(op->pending_client_trans); - if (cancel){ - if (info != NULL){ - belle_sip_header_reason_t* reason = sal_call_make_reason_header(info); - belle_sip_message_add_header(BELLE_SIP_MESSAGE(cancel),BELLE_SIP_HEADER(reason)); - } - sal_op_send_request(op,cancel); - }else if (op->dialog){ - belle_sip_dialog_state_t state = belle_sip_dialog_get_state(op->dialog);; - /*case where the response received is invalid (could not establish a dialog), but the transaction is not cancellable - * because already terminated*/ - switch(state){ - case BELLE_SIP_DIALOG_EARLY: - case BELLE_SIP_DIALOG_NULL: - /*force kill the dialog*/ - ms_warning("op [%p]: force kill of dialog [%p]", op, op->dialog); - belle_sip_dialog_delete(op->dialog); - break; - default: - break; - } - } -} - -int sal_call_decline(SalOp *op, SalReason reason, const char *redirection /*optional*/){ - belle_sip_response_t* response; - belle_sip_header_contact_t* contact=NULL; - int status=sal_reason_to_sip_code(reason); - belle_sip_transaction_t *trans; - - if (reason==SalReasonRedirect){ - if (redirection!=NULL) { - if (strstr(redirection,"sip:")!=0) status=302; - else status=380; - contact= belle_sip_header_contact_new(); - belle_sip_header_address_set_uri(BELLE_SIP_HEADER_ADDRESS(contact),belle_sip_uri_parse(redirection)); - } else { - ms_error("Cannot redirect to null"); - } - } - trans=(belle_sip_transaction_t*)op->pending_server_trans; - if (!trans) trans=(belle_sip_transaction_t*)op->pending_update_server_trans; - if (!trans){ - ms_error("sal_call_decline(): no pending transaction to decline."); - return -1; - } - response = sal_op_create_response_from_request(op,belle_sip_transaction_get_request(trans),status); - if (contact) belle_sip_message_add_header(BELLE_SIP_MESSAGE(response),BELLE_SIP_HEADER(contact)); - belle_sip_server_transaction_send_response(BELLE_SIP_SERVER_TRANSACTION(trans),response); - return 0; -} - -int sal_call_decline_with_error_info(SalOp *op, const SalErrorInfo *info, const char *redirection /*optional*/){ - belle_sip_response_t* response; - belle_sip_header_contact_t* contact=NULL; - int status = info->protocol_code; - belle_sip_transaction_t *trans; - - if (info->reason==SalReasonRedirect){ - if (redirection!=NULL) { - if (strstr(redirection,"sip:")!=0) status=302; - else status=380; - contact= belle_sip_header_contact_new(); - belle_sip_header_address_set_uri(BELLE_SIP_HEADER_ADDRESS(contact),belle_sip_uri_parse(redirection)); - } else { - ms_error("Cannot redirect to null"); - } - } - trans=(belle_sip_transaction_t*)op->pending_server_trans; - if (!trans) trans=(belle_sip_transaction_t*)op->pending_update_server_trans; - if (!trans){ - ms_error("sal_call_decline_with_error_info(): no pending transaction to decline."); - return -1; - } - response = sal_op_create_response_from_request(op,belle_sip_transaction_get_request(trans),status); - belle_sip_header_reason_t* reason_header = sal_call_make_reason_header(info->sub_sei); - if (reason_header) { - belle_sip_message_add_header(BELLE_SIP_MESSAGE(response),BELLE_SIP_HEADER(reason_header)); - } - - if (contact) { - belle_sip_message_add_header(BELLE_SIP_MESSAGE(response),BELLE_SIP_HEADER(contact)); - } - belle_sip_server_transaction_send_response(BELLE_SIP_SERVER_TRANSACTION(trans),response); - return 0; -} - -int sal_call_update(SalOp *op, const char *subject, bool_t no_user_consent){ - belle_sip_request_t *update; - belle_sip_dialog_state_t state; - - if (op->dialog == NULL) { - /* If the dialog does not exist, this is that we are trying to recover from a connection loss - during a very early state of outgoing call initiation (the dialog has not been created yet). */ - const char *from = sal_op_get_from(op); - const char *to = sal_op_get_to(op); - return sal_call(op, from, to, subject); - } - - state = belle_sip_dialog_get_state(op->dialog); - belle_sip_dialog_enable_pending_trans_checking(op->dialog,op->base.root->pending_trans_checking); - - /*check for dialog state*/ - if ( state == BELLE_SIP_DIALOG_CONFIRMED) { - if (no_user_consent) - update=belle_sip_dialog_create_request(op->dialog,"UPDATE"); - else - update=belle_sip_dialog_create_request(op->dialog,"INVITE"); - } else if (state == BELLE_SIP_DIALOG_EARLY) { - update=belle_sip_dialog_create_request(op->dialog,"UPDATE"); - } else { - ms_error("Cannot update op [%p] with dialog [%p] in state [%s]",op, op->dialog,belle_sip_dialog_state_to_string(state)); - return -1; - } - if (update){ - belle_sip_message_add_header(BELLE_SIP_MESSAGE(update),belle_sip_header_create( "Subject", subject)); - sal_op_fill_invite(op, update); - return sal_op_send_request(op,update); - } - /*it failed why ?*/ - if (belle_sip_dialog_request_pending(op->dialog)) - sal_error_info_set(&op->error_info,SalReasonRequestPending, "SIP", 491,NULL,NULL); - else - sal_error_info_set(&op->error_info,SalReasonUnknown, "SIP", 500,NULL,NULL); - return -1; -} - -SalMediaDescription * sal_call_get_remote_media_description(SalOp *h){ - return h->base.remote_media; -} - -SalMediaDescription * sal_call_get_final_media_description(SalOp *h){ - if (h->base.local_media && h->base.remote_media && !h->result){ - sdp_process(h); - } - return h->result; -} - -int sal_call_send_dtmf(SalOp *h, char dtmf){ - if (h->dialog && (belle_sip_dialog_get_state(h->dialog) == BELLE_SIP_DIALOG_CONFIRMED || belle_sip_dialog_get_state(h->dialog) == BELLE_SIP_DIALOG_EARLY)){ - belle_sip_request_t *req=belle_sip_dialog_create_queued_request(h->dialog,"INFO"); - if (req){ - size_t bodylen; - char dtmf_body[128]={0}; - - snprintf(dtmf_body, sizeof(dtmf_body)-1, "Signal=%c\r\nDuration=250\r\n", dtmf); - bodylen=strlen(dtmf_body); - belle_sip_message_set_body((belle_sip_message_t*)req,dtmf_body,bodylen); - belle_sip_message_add_header((belle_sip_message_t*)req,(belle_sip_header_t*)belle_sip_header_content_length_create(bodylen)); - belle_sip_message_add_header((belle_sip_message_t*)req,(belle_sip_header_t*)belle_sip_header_content_type_create("application", "dtmf-relay")); - sal_op_send_request(h,req); - }else ms_error("sal_call_send_dtmf(): could not build request"); - }else ms_error("sal_call_send_dtmf(): no dialog"); - return 0; -} - - -int sal_call_terminate_with_error(SalOp *op, const SalErrorInfo *info){ - SalErrorInfo sei; - const SalErrorInfo *p_sei; - belle_sip_dialog_state_t dialog_state = op->dialog ? belle_sip_dialog_get_state(op->dialog) : BELLE_SIP_DIALOG_NULL; - int ret = 0; - - memset(&sei, 0, sizeof(sei)); - if (info == NULL && dialog_state != BELLE_SIP_DIALOG_CONFIRMED && op->dir == SalOpDirIncoming){ - /*the purpose of this line is to set a default SalErrorInfo for declining an incoming call (not yet established of course) */ - sal_error_info_set(&sei,SalReasonDeclined, "SIP", 0, NULL, NULL); - p_sei = &sei; - } else{ - p_sei = info; - } - if (op->state==SalOpStateTerminating || op->state==SalOpStateTerminated) { - ms_error("Cannot terminate op [%p] in state [%s]",op,sal_op_state_to_string(op->state)); - ret = -1; - goto end; - } - switch(dialog_state) { - case BELLE_SIP_DIALOG_CONFIRMED: { - belle_sip_request_t * req = belle_sip_dialog_create_request(op->dialog,"BYE"); - if (info != NULL){ - belle_sip_header_reason_t* reason = sal_call_make_reason_header(info); - belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(reason)); - } - sal_op_send_request(op,req); - op->state=SalOpStateTerminating; - break; - } - - case BELLE_SIP_DIALOG_NULL: { - if (op->dir == SalOpDirIncoming) { - sal_call_decline_with_error_info(op, p_sei, NULL); - op->state=SalOpStateTerminated; - } else if (op->pending_client_trans){ - if (belle_sip_transaction_get_state(BELLE_SIP_TRANSACTION(op->pending_client_trans)) == BELLE_SIP_TRANSACTION_PROCEEDING){ - cancelling_invite(op, p_sei); - }else{ - /* Case where the CANCEL cannot be sent because no provisional response was received so far. - * The Op must be kept for the time of the transaction in case a response is received later. - * The state is passed to Terminating to remember to terminate later. - */ - 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; - } - case BELLE_SIP_DIALOG_EARLY: { - if (op->dir == SalOpDirIncoming) { - sal_call_decline_with_error_info(op, p_sei,NULL); - op->state=SalOpStateTerminated; - } else { - cancelling_invite(op, p_sei); - } - break; - } - default: { - ms_error("sal_call_terminate not implemented yet for dialog state [%s]",belle_sip_dialog_state_to_string(dialog_state)); - ret = -1; - goto end; - } - } -end: - sal_error_info_reset(&sei); - return ret; -} - - -int sal_call_terminate(SalOp *op){ - return sal_call_terminate_with_error(op, NULL); -} - - -bool_t sal_call_autoanswer_asked(SalOp *op){ - return op->auto_answer_asked; -} - -void sal_call_send_vfu_request(SalOp *op){ - char info_body[] = - "" - "" - " " - " " - " " - " " - " " - ""; - size_t content_lenth = sizeof(info_body) - 1; - belle_sip_dialog_state_t dialog_state=op->dialog?belle_sip_dialog_get_state(op->dialog):BELLE_SIP_DIALOG_NULL; /*no dialog = dialog in NULL state*/ - if (dialog_state == BELLE_SIP_DIALOG_CONFIRMED) { - belle_sip_request_t* info = belle_sip_dialog_create_queued_request(op->dialog,"INFO"); - int error=TRUE; - if (info) { - belle_sip_message_add_header(BELLE_SIP_MESSAGE(info),BELLE_SIP_HEADER(belle_sip_header_content_type_create("application","media_control+xml"))); - belle_sip_message_add_header(BELLE_SIP_MESSAGE(info),BELLE_SIP_HEADER(belle_sip_header_content_length_create(content_lenth))); - belle_sip_message_set_body(BELLE_SIP_MESSAGE(info),info_body,content_lenth); - error=sal_op_send_request(op,info); - } - if (error) - ms_warning("Cannot send vfu request to [%s] ", sal_op_get_to(op)); - - } else { - ms_warning("Cannot send vfu request to [%s] because dialog [%p] in wrong state [%s]",sal_op_get_to(op) - ,op->dialog - ,belle_sip_dialog_state_to_string(dialog_state)); - } - - return ; -} - -int sal_call_is_offerer(const SalOp *h){ - return h->sdp_offering; -} - -bool_t sal_call_compare_op(const SalOp *op1, const SalOp *op2) { - if (strcmp(op1->base.call_id, op2->base.call_id) == 0) return TRUE; - return FALSE; -} - -bool_t sal_call_dialog_request_pending(const SalOp *op) { - return belle_sip_dialog_request_pending(op->dialog) ? TRUE : FALSE; -} - -const char * sal_call_get_local_tag(SalOp *op) { - return belle_sip_dialog_get_local_tag(op->dialog); -} - -const char * sal_call_get_remote_tag(SalOp *op) { - return belle_sip_dialog_get_remote_tag(op->dialog); -} - -void sal_call_set_replaces(SalOp *op, const char *call_id, const char *from_tag, const char *to_tag) { - belle_sip_header_replaces_t *replaces = belle_sip_header_replaces_create(call_id, from_tag, to_tag); - sal_op_set_replaces(op, replaces); -} diff --git a/coreapi/bellesip_sal/sal_op_call_transfer.c b/coreapi/bellesip_sal/sal_op_call_transfer.c deleted file mode 100644 index 8fe460314..000000000 --- a/coreapi/bellesip_sal/sal_op_call_transfer.c +++ /dev/null @@ -1,273 +0,0 @@ -/* -linphone -Copyright (C) 2012 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 -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 "sal_impl.h" -#include "offeranswer.h" - - - -/*call transfer*/ -static void sal_op_set_referred_by(SalOp* op,belle_sip_header_referred_by_t* referred_by) { - if (op->referred_by){ - belle_sip_object_unref(op->referred_by); - } - op->referred_by=referred_by; - belle_sip_object_ref(op->referred_by); -} - - -int sal_call_refer_to(SalOp *op, belle_sip_header_refer_to_t* refer_to, belle_sip_header_referred_by_t* referred_by){ - char* tmp; - belle_sip_request_t* req=op->dialog?belle_sip_dialog_create_request(op->dialog,"REFER"):sal_op_build_request(op, "REFER"); - if (!req) { - tmp=belle_sip_uri_to_string(belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(refer_to))); - ms_error("Cannot refer to [%s] for op [%p]",tmp,op); - belle_sip_free(tmp); - return -1; - } - belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(refer_to)); - if (referred_by) belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(referred_by)); - return sal_op_send_request(op,req); -} - -int sal_call_refer(SalOp *op, const char *refer_to){ - belle_sip_header_address_t *referred_by; - belle_sip_header_refer_to_t* refer_to_header; - if (op->dialog) { - referred_by=(belle_sip_header_address_t*)belle_sip_object_clone(BELLE_SIP_OBJECT(belle_sip_dialog_get_local_party(op->dialog))); - }else{ - referred_by=BELLE_SIP_HEADER_ADDRESS(sal_op_get_from_address(op)); - } - refer_to_header=belle_sip_header_refer_to_create(belle_sip_header_address_parse(refer_to)); - - return sal_call_refer_to(op,refer_to_header,belle_sip_header_referred_by_create(referred_by)); -} - -int sal_call_refer_with_replaces(SalOp *op, SalOp *other_call_op){ - belle_sip_dialog_state_t other_call_dialog_state=other_call_op->dialog?belle_sip_dialog_get_state(other_call_op->dialog):BELLE_SIP_DIALOG_NULL; - belle_sip_dialog_state_t op_dialog_state=op->dialog?belle_sip_dialog_get_state(op->dialog):BELLE_SIP_DIALOG_NULL; - belle_sip_header_replaces_t* replaces; - belle_sip_header_refer_to_t* refer_to; - belle_sip_header_referred_by_t* referred_by; - const char* from_tag; - const char* to_tag; - char* escaped_replaces; - /*first, build refer to*/ - if ((other_call_dialog_state!=BELLE_SIP_DIALOG_CONFIRMED) && (other_call_dialog_state!=BELLE_SIP_DIALOG_EARLY)) { - ms_error("wrong dialog state [%s] for op [%p], should be BELLE_SIP_DIALOG_CONFIRMED or BELE_SIP_DIALOG_EARLY", - belle_sip_dialog_state_to_string(other_call_dialog_state), - other_call_op); - return -1; - } - if (op_dialog_state!=BELLE_SIP_DIALOG_CONFIRMED) { - ms_error("wrong dialog state [%s] for op [%p], should be BELLE_SIP_DIALOG_CONFIRMED", - belle_sip_dialog_state_to_string(op_dialog_state), - op); - return -1; - } - - refer_to=belle_sip_header_refer_to_create(belle_sip_dialog_get_remote_party(other_call_op->dialog)); - belle_sip_parameters_clean(BELLE_SIP_PARAMETERS(refer_to)); - /*rfc3891 - ... - 4. User Agent Client Behavior: Sending a Replaces Header - - A User Agent that wishes to replace a single existing early or - confirmed dialog with a new dialog of its own, MAY send the target - User Agent an INVITE request containing a Replaces header field. The - User Agent Client (UAC) places the Call-ID, to-tag, and from-tag - information for the target dialog in a single Replaces header field - and sends the new INVITE to the target.*/ - from_tag=belle_sip_dialog_get_local_tag(other_call_op->dialog); - to_tag=belle_sip_dialog_get_remote_tag(other_call_op->dialog); - - replaces=belle_sip_header_replaces_create(belle_sip_header_call_id_get_call_id(belle_sip_dialog_get_call_id(other_call_op->dialog)) - ,from_tag,to_tag); - escaped_replaces=belle_sip_header_replaces_value_to_escaped_string(replaces); - belle_sip_uri_set_header(belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(refer_to)),"Replaces",escaped_replaces); - belle_sip_free(escaped_replaces); - referred_by=belle_sip_header_referred_by_create(belle_sip_dialog_get_local_party(op->dialog)); - belle_sip_parameters_clean(BELLE_SIP_PARAMETERS(referred_by)); - return sal_call_refer_to(op,refer_to,referred_by); -} -/* -int sal_call_accept_refer(SalOp *h){ - ms_fatal("sal_call_accept_refer not implemented yet"); - return -1; -}*/ -/*informs this call is consecutive to an incoming refer */ -int sal_call_set_referer(SalOp *h, SalOp *refered_call){ - if (refered_call->replaces) - sal_op_set_replaces(h,refered_call->replaces); - if (refered_call->referred_by) - sal_op_set_referred_by(h,refered_call->referred_by); - return 0; -} -/* returns the SalOp of a call that should be replaced by h, if any */ -SalOp *sal_call_get_replaces(SalOp *op){ - if (op && op->replaces){ - /*rfc3891 - 3. User Agent Server Behavior: Receiving a Replaces Header - - The Replaces header contains information used to match an existing - SIP dialog (call-id, to-tag, and from-tag). Upon receiving an INVITE - with a Replaces header, the User Agent (UA) attempts to match this - information with a confirmed or early dialog. The User Agent Server - (UAS) matches the to-tag and from-tag parameters as if they were tags - present in an incoming request. In other words, the to-tag parameter - is compared to the local tag, and the from-tag parameter is compared - to the remote tag. - */ - belle_sip_dialog_t* dialog=belle_sip_provider_find_dialog(op->base.root->prov - ,belle_sip_header_replaces_get_call_id(op->replaces) - ,belle_sip_header_replaces_get_to_tag(op->replaces) - ,belle_sip_header_replaces_get_from_tag(op->replaces)); - - if (!dialog) { - /*for backward compatibility with liblinphone <= 3.10.2-243 */ - dialog=belle_sip_provider_find_dialog(op->base.root->prov - ,belle_sip_header_replaces_get_call_id(op->replaces) - ,belle_sip_header_replaces_get_from_tag(op->replaces) - ,belle_sip_header_replaces_get_to_tag(op->replaces)); - } - if (dialog) { - return (SalOp*)belle_sip_dialog_get_application_data(dialog); - } - } - return NULL; -} - -static int send_notify_for_refer(SalOp* op, int code, const char *reason){ - belle_sip_request_t* notify=belle_sip_dialog_create_queued_request(op->dialog,"NOTIFY"); - char *sipfrag=belle_sip_strdup_printf("SIP/2.0 %i %s\r\n",code,reason); - size_t content_length=strlen(sipfrag); - belle_sip_message_add_header(BELLE_SIP_MESSAGE(notify) - ,BELLE_SIP_HEADER(belle_sip_header_subscription_state_create(BELLE_SIP_SUBSCRIPTION_STATE_ACTIVE,-1))); - - belle_sip_message_add_header(BELLE_SIP_MESSAGE(notify),belle_sip_header_create("Event","refer")); - belle_sip_message_add_header(BELLE_SIP_MESSAGE(notify),BELLE_SIP_HEADER(belle_sip_header_content_type_create("message","sipfrag"))); - belle_sip_message_add_header(BELLE_SIP_MESSAGE(notify),BELLE_SIP_HEADER(belle_sip_header_content_length_create(content_length))); - belle_sip_message_assign_body(BELLE_SIP_MESSAGE(notify),sipfrag,content_length); - return sal_op_send_request(op,notify); -} - -static void notify_last_response(SalOp *op, SalOp *newcall){ - belle_sip_client_transaction_t *tr=newcall->pending_client_trans; - belle_sip_response_t *resp=NULL; - if (tr){ - resp=belle_sip_transaction_get_response((belle_sip_transaction_t*)tr); - } - if (resp==NULL){ - send_notify_for_refer(op, 100, "Trying"); - }else{ - send_notify_for_refer(op, belle_sip_response_get_status_code(resp), belle_sip_response_get_reason_phrase(resp)); - } -} - -int sal_call_notify_refer_state(SalOp *op, SalOp *newcall){ - belle_sip_dialog_state_t state; - if(belle_sip_dialog_get_state(op->dialog) == BELLE_SIP_DIALOG_TERMINATED){ - return 0; - } - state = newcall->dialog?belle_sip_dialog_get_state(newcall->dialog):BELLE_SIP_DIALOG_NULL; - switch(state) { - case BELLE_SIP_DIALOG_EARLY: - send_notify_for_refer(op, 100, "Trying"); - break; - case BELLE_SIP_DIALOG_CONFIRMED: - send_notify_for_refer(op, 200, "Ok"); - break; - case BELLE_SIP_DIALOG_TERMINATED: - case BELLE_SIP_DIALOG_NULL: - notify_last_response(op,newcall); - break; - } - return 0; -} - - -void sal_op_process_refer(SalOp *op, const belle_sip_request_event_t *event, belle_sip_server_transaction_t *server_transaction){ - belle_sip_request_t* req = belle_sip_request_event_get_request(event); - belle_sip_header_refer_to_t *refer_to= belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req),belle_sip_header_refer_to_t); - belle_sip_header_referred_by_t *referred_by= belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req),belle_sip_header_referred_by_t); - belle_sip_response_t* resp; - belle_sip_uri_t* refer_to_uri; - char* refer_to_uri_str; - - ms_message("Receiving REFER request on op [%p]",op); - if (refer_to) { - refer_to_uri=belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(refer_to)); - - if (refer_to_uri && belle_sip_uri_get_header(refer_to_uri,"Replaces")) { - sal_op_set_replaces(op,belle_sip_header_replaces_create2(belle_sip_uri_get_header(refer_to_uri,"Replaces"))); - belle_sip_uri_remove_header(refer_to_uri,"Replaces"); - } - if (referred_by){ - sal_op_set_referred_by(op,referred_by); - } - refer_to_uri_str=belle_sip_uri_to_string(refer_to_uri); - resp = sal_op_create_response_from_request(op,req,202); - belle_sip_server_transaction_send_response(server_transaction,resp); - op->base.root->callbacks.refer_received(op->base.root,op,refer_to_uri_str); - belle_sip_free(refer_to_uri_str); - } else { - ms_warning("cannot do anything with the refer without destination\n"); - resp = sal_op_create_response_from_request(op,req,400); - belle_sip_server_transaction_send_response(server_transaction,resp); - } - -} - -void sal_op_call_process_notify(SalOp *op, const belle_sip_request_event_t *event, belle_sip_server_transaction_t* server_transaction){ - belle_sip_request_t* req = belle_sip_request_event_get_request(event); - const char* body = belle_sip_message_get_body(BELLE_SIP_MESSAGE(req)); - belle_sip_header_t* header_event=belle_sip_message_get_header(BELLE_SIP_MESSAGE(req),"Event"); - belle_sip_header_content_type_t* content_type = belle_sip_message_get_header_by_type(req,belle_sip_header_content_type_t); - belle_sip_response_t* resp; - - ms_message("Receiving NOTIFY request on op [%p]",op); - if (header_event - && strncasecmp(belle_sip_header_get_unparsed_value(header_event),"refer",strlen("refer"))==0 - && content_type - && strcmp(belle_sip_header_content_type_get_type(content_type),"message")==0 - && strcmp(belle_sip_header_content_type_get_subtype(content_type),"sipfrag")==0 - && body){ - belle_sip_response_t* sipfrag=BELLE_SIP_RESPONSE(belle_sip_message_parse(body)); - - if (sipfrag){ - int code=belle_sip_response_get_status_code(sipfrag); - SalReferStatus status=SalReferFailed; - if (code<200){ - status=SalReferTrying; - }else if (code<300){ - status=SalReferSuccess; - }else if (code>=400){ - status=SalReferFailed; - } - belle_sip_object_unref(sipfrag); - resp = sal_op_create_response_from_request(op,req,200); - belle_sip_server_transaction_send_response(server_transaction,resp); - op->base.root->callbacks.notify_refer(op,status); - } - }else{ - ms_error("Notify without sipfrag, trashing"); - resp = sal_op_create_response_from_request(op,req,501); - belle_sip_server_transaction_send_response(server_transaction,resp); - } -} - diff --git a/coreapi/bellesip_sal/sal_op_events.c b/coreapi/bellesip_sal/sal_op_events.c deleted file mode 100644 index ef0a2cb17..000000000 --- a/coreapi/bellesip_sal/sal_op_events.c +++ /dev/null @@ -1,385 +0,0 @@ -/* -linphone -Copyright (C) 2012 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 -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 "sal_impl.h" - -SalSubscribeStatus belle_sip_message_get_subscription_state(const belle_sip_message_t *msg){ - belle_sip_header_subscription_state_t* subscription_state_header=belle_sip_message_get_header_by_type(msg,belle_sip_header_subscription_state_t); - SalSubscribeStatus sss=SalSubscribeNone; - if (subscription_state_header){ - if (strcmp(belle_sip_header_subscription_state_get_state(subscription_state_header),BELLE_SIP_SUBSCRIPTION_STATE_TERMINATED)==0) - sss=SalSubscribeTerminated; - else if (strcmp(belle_sip_header_subscription_state_get_state(subscription_state_header),BELLE_SIP_SUBSCRIPTION_STATE_PENDING)==0) - sss=SalSubscribePending; - else if (strcmp(belle_sip_header_subscription_state_get_state(subscription_state_header),BELLE_SIP_SUBSCRIPTION_STATE_ACTIVE)==0) - sss=SalSubscribeActive; - } - return sss; -} - -static void subscribe_refresher_listener (belle_sip_refresher_t* refresher - ,void* user_pointer - ,unsigned int status_code - ,const char* reason_phrase, int will_retry) { - SalOp* op = (SalOp*)user_pointer; - belle_sip_transaction_t *tr=BELLE_SIP_TRANSACTION(belle_sip_refresher_get_transaction(refresher)); - /*belle_sip_response_t* response=belle_sip_transaction_get_response(tr);*/ - SalSubscribeStatus sss=SalSubscribeTerminated; - - ms_message("Subscribe refresher [%i] reason [%s] ",status_code,reason_phrase?reason_phrase:"none"); - if (status_code>=200 && status_code<300){ - if (status_code==200) sss=SalSubscribeActive; - else if (status_code==202) sss=SalSubscribePending; - set_or_update_dialog(op,belle_sip_transaction_get_dialog(tr)); - op->base.root->callbacks.subscribe_response(op,sss, will_retry); - } else if (status_code >= 300) { - SalReason reason = SalReasonUnknown; - if (status_code == 503) { /*refresher returns 503 for IO error*/ - reason = SalReasonIOError; - } - sal_error_info_set(&op->error_info, reason, "SIP", (int)status_code,reason_phrase,NULL); - op->base.root->callbacks.subscribe_response(op,sss, will_retry); - }else if (status_code==0){ - op->base.root->callbacks.on_expire(op); - } - -} - -static void subscribe_process_io_error(void *user_ctx, const belle_sip_io_error_event_t *event){ - SalOp *op = (SalOp*)user_ctx; - belle_sip_object_t *src = belle_sip_io_error_event_get_source(event); - if (BELLE_SIP_OBJECT_IS_INSTANCE_OF(src, belle_sip_client_transaction_t)){ - belle_sip_client_transaction_t *tr = BELLE_SIP_CLIENT_TRANSACTION(src); - belle_sip_request_t* req = belle_sip_transaction_get_request((belle_sip_transaction_t*)tr); - const char *method=belle_sip_request_get_method(req); - - if (!op->dialog) { - /*this is handling outgoing out-of-dialog notifies*/ - if (strcmp(method,"NOTIFY")==0){ - SalErrorInfo *ei=&op->error_info; - sal_error_info_set(ei,SalReasonIOError, "SIP", 0,NULL,NULL); - op->base.root->callbacks.on_notify_response(op); - } - } - } -} - -static void subscribe_process_dialog_terminated(void *ctx, const belle_sip_dialog_terminated_event_t *event) { - belle_sip_dialog_t *dialog = belle_sip_dialog_terminated_event_get_dialog(event); - SalOp* op= (SalOp*)ctx; - if (op->dialog) { - if (belle_sip_dialog_terminated_event_is_expired(event)){ - if (!belle_sip_dialog_is_server(dialog)){ - /*notify the app that our subscription is dead*/ - const char *eventname = NULL; - if (op->event){ - eventname = belle_sip_header_event_get_package_name(op->event); - } - op->base.root->callbacks.notify(op, SalSubscribeTerminated, eventname, NULL); - }else{ - op->base.root->callbacks.incoming_subscribe_closed(op); - } - } - set_or_update_dialog(op, NULL); - } -} - -static void subscribe_response_event(void *op_base, const belle_sip_response_event_t *event){ - SalOp *op = (SalOp*)op_base; - belle_sip_request_t * req; - const char *method; - belle_sip_client_transaction_t *tr = belle_sip_response_event_get_client_transaction(event); - - if (!tr) return; - req = belle_sip_transaction_get_request((belle_sip_transaction_t*)tr); - method = belle_sip_request_get_method(req); - - if (!op->dialog) { - if (strcmp(method,"NOTIFY")==0){ - sal_op_set_error_info_from_response(op,belle_sip_response_event_get_response(event)); - op->base.root->callbacks.on_notify_response(op); - } - } -} - -static void subscribe_process_timeout(void *user_ctx, const belle_sip_timeout_event_t *event) { - SalOp *op = (SalOp*)user_ctx; - belle_sip_request_t * req; - const char *method; - belle_sip_client_transaction_t *tr = belle_sip_timeout_event_get_client_transaction(event); - - if (!tr) return; - req = belle_sip_transaction_get_request((belle_sip_transaction_t*)tr); - method = belle_sip_request_get_method(req); - - if (!op->dialog) { - /*this is handling outgoing out-of-dialog notifies*/ - if (strcmp(method,"NOTIFY")==0){ - SalErrorInfo *ei=&op->error_info; - sal_error_info_set(ei,SalReasonRequestTimeout, "SIP", 0,NULL,NULL); - op->base.root->callbacks.on_notify_response(op); - } - } -} - -static void subscribe_process_transaction_terminated(void *user_ctx, const belle_sip_transaction_terminated_event_t *event) { -} - -static void handle_notify(SalOp *op, belle_sip_request_t *req, const char *eventname, SalBodyHandler* body_handler){ - SalSubscribeStatus sub_state; - belle_sip_header_subscription_state_t* subscription_state_header=belle_sip_message_get_header_by_type(req,belle_sip_header_subscription_state_t); - belle_sip_response_t* resp; - belle_sip_server_transaction_t* server_transaction = op->pending_server_trans; - - if (!subscription_state_header || strcasecmp(BELLE_SIP_SUBSCRIPTION_STATE_TERMINATED,belle_sip_header_subscription_state_get_state(subscription_state_header)) ==0) { - sub_state=SalSubscribeTerminated; - ms_message("Outgoing subscription terminated by remote [%s]",sal_op_get_to(op)); - } else - sub_state=SalSubscribeActive; - sal_op_ref(op); - op->base.root->callbacks.notify(op,sub_state,eventname,body_handler); - resp=sal_op_create_response_from_request(op,req,200); - belle_sip_server_transaction_send_response(server_transaction,resp); - sal_op_unref(op); -} - -static void subscribe_process_request_event(void *op_base, const belle_sip_request_event_t *event) { - SalOp* op = (SalOp*)op_base; - belle_sip_server_transaction_t* server_transaction = belle_sip_provider_create_server_transaction(op->base.root->prov,belle_sip_request_event_get_request(event)); - belle_sip_request_t* req = belle_sip_request_event_get_request(event); - belle_sip_dialog_state_t dialog_state; - belle_sip_header_expires_t* expires = belle_sip_message_get_header_by_type(req,belle_sip_header_expires_t); - belle_sip_header_event_t *event_header; - belle_sip_body_handler_t *body_handler; - belle_sip_response_t* resp; - const char *eventname=NULL; - const char *method=belle_sip_request_get_method(req); - belle_sip_dialog_t *dialog = NULL; - - belle_sip_object_ref(server_transaction); - if (op->pending_server_trans) belle_sip_object_unref(op->pending_server_trans); - op->pending_server_trans=server_transaction; - - event_header=belle_sip_message_get_header_by_type(req,belle_sip_header_event_t); - body_handler = BELLE_SIP_BODY_HANDLER(sal_op_get_body_handler(op, BELLE_SIP_MESSAGE(req))); - - if (event_header==NULL){ - ms_warning("No event header in incoming SUBSCRIBE."); - resp=sal_op_create_response_from_request(op,req,400); - belle_sip_server_transaction_send_response(server_transaction,resp); - if (!op->dialog) sal_op_release(op); - return; - } - if (op->event==NULL) { - op->event=event_header; - belle_sip_object_ref(op->event); - } - eventname=belle_sip_header_event_get_package_name(event_header); - - if (!op->dialog) { - if (strcmp(method,"SUBSCRIBE")==0){ - dialog = belle_sip_provider_create_dialog(op->base.root->prov,BELLE_SIP_TRANSACTION(server_transaction)); - if (!dialog){ - resp=sal_op_create_response_from_request(op,req,481); - belle_sip_server_transaction_send_response(server_transaction,resp); - sal_op_release(op); - return; - } - set_or_update_dialog(op, dialog); - ms_message("new incoming subscription from [%s] to [%s]",sal_op_get_from(op),sal_op_get_to(op)); - }else{ /*this is a NOTIFY*/ - handle_notify(op, req, eventname, (SalBodyHandler *)body_handler); - return; - } - } - dialog_state=belle_sip_dialog_get_state(op->dialog); - switch(dialog_state) { - - case BELLE_SIP_DIALOG_NULL: { - const char *type = NULL; - belle_sip_header_content_type_t *content_type = belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req), belle_sip_header_content_type_t); - if (content_type) type = belle_sip_header_content_type_get_type(content_type); - op->base.root->callbacks.subscribe_received(op, eventname, type ? (SalBodyHandler *)body_handler : NULL); - break; - } - case BELLE_SIP_DIALOG_EARLY: - ms_error("unexpected method [%s] for dialog [%p] in state BELLE_SIP_DIALOG_EARLY ",belle_sip_request_get_method(req),op->dialog); - break; - - case BELLE_SIP_DIALOG_CONFIRMED: - if (strcmp("NOTIFY",method)==0) { - handle_notify(op, req, eventname, (SalBodyHandler *)body_handler); - } else if (strcmp("SUBSCRIBE",method)==0) { - /*either a refresh of an unsubscribe*/ - if (expires && belle_sip_header_expires_get_expires(expires)>0) { - resp=sal_op_create_response_from_request(op,req,200); - belle_sip_server_transaction_send_response(server_transaction,resp); - } else if(expires) { - ms_message("Unsubscribe received from [%s]",sal_op_get_from(op)); - resp=sal_op_create_response_from_request(op,req,200); - belle_sip_server_transaction_send_response(server_transaction,resp); - op->base.root->callbacks.incoming_subscribe_closed(op); - } - } - break; - default: { - ms_error("unexpected dialog state [%s]",belle_sip_dialog_state_to_string(dialog_state)); - } - } -} - -static belle_sip_listener_callbacks_t op_subscribe_callbacks={ 0 }; - -/*Invoke when sal_op_release is called by upper layer*/ -static void sal_op_release_cb(struct SalOpBase* op_base) { - SalOp *op =(SalOp*)op_base; - if(op->refresher) { - belle_sip_refresher_stop(op->refresher); - belle_sip_object_unref(op->refresher); - op->refresher=NULL; - set_or_update_dialog(op,NULL); /*only if we have refresher. else dialog terminated event will remove association*/ - } - -} - -void sal_op_subscribe_fill_cbs(SalOp*op) { - if (op_subscribe_callbacks.process_io_error==NULL){ - op_subscribe_callbacks.process_io_error=subscribe_process_io_error; - op_subscribe_callbacks.process_response_event=subscribe_response_event; - op_subscribe_callbacks.process_timeout=subscribe_process_timeout; - op_subscribe_callbacks.process_transaction_terminated=subscribe_process_transaction_terminated; - op_subscribe_callbacks.process_request_event=subscribe_process_request_event; - op_subscribe_callbacks.process_dialog_terminated=subscribe_process_dialog_terminated; - } - op->callbacks=&op_subscribe_callbacks; - op->type=SalOpSubscribe; - op->base.release_cb=sal_op_release_cb; -} - - -int sal_subscribe(SalOp *op, const char *from, const char *to, const char *eventname, int expires, const SalBodyHandler *body_handler){ - belle_sip_request_t *req=NULL; - - if (from) - sal_op_set_from(op,from); - if (to) - sal_op_set_to(op,to); - - if (!op->dialog){ - sal_op_subscribe_fill_cbs(op); - req=sal_op_build_request(op,"SUBSCRIBE"); - if( req == NULL ) { - return -1; - } - sal_op_set_event(op, eventname); - belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(op->event)); - belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(belle_sip_header_expires_create(expires))); - belle_sip_message_set_body_handler(BELLE_SIP_MESSAGE(req), BELLE_SIP_BODY_HANDLER(body_handler)); - return sal_op_send_and_create_refresher(op,req,expires,subscribe_refresher_listener); - }else if (op->refresher){ - const belle_sip_transaction_t *tr=(const belle_sip_transaction_t*) belle_sip_refresher_get_transaction(op->refresher); - belle_sip_request_t *last_req=belle_sip_transaction_get_request(tr); - /* modify last request to update body*/ - belle_sip_message_set_body_handler(BELLE_SIP_MESSAGE(last_req), BELLE_SIP_BODY_HANDLER(body_handler)); - return belle_sip_refresher_refresh(op->refresher,expires); - } - ms_warning("sal_subscribe(): no dialog and no refresher ?"); - return -1; -} - -int sal_unsubscribe(SalOp *op){ - if (op->refresher){ - const belle_sip_transaction_t *tr=(const belle_sip_transaction_t*) belle_sip_refresher_get_transaction(op->refresher); - belle_sip_request_t *last_req=belle_sip_transaction_get_request(tr); - belle_sip_message_set_body(BELLE_SIP_MESSAGE(last_req), NULL, 0); - belle_sip_refresher_refresh(op->refresher,0); - return 0; - } - return -1; -} - -int sal_subscribe_accept(SalOp *op){ - belle_sip_request_t* req=belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(op->pending_server_trans)); - belle_sip_header_expires_t* expires = belle_sip_message_get_header_by_type(req,belle_sip_header_expires_t); - belle_sip_response_t* resp = sal_op_create_response_from_request(op,req,200); - belle_sip_message_add_header(BELLE_SIP_MESSAGE(resp),BELLE_SIP_HEADER(expires)); - belle_sip_server_transaction_send_response(op->pending_server_trans,resp); - return 0; -} - -int sal_notify_pending_state(SalOp *op){ - - if (op->dialog != NULL && op->pending_server_trans) { - belle_sip_request_t* notify; - belle_sip_header_subscription_state_t* sub_state; - ms_message("Sending NOTIFY with subscription state pending for op [%p]",op); - if (!(notify=belle_sip_dialog_create_request(op->dialog,"NOTIFY"))) { - ms_error("Cannot create NOTIFY on op [%p]",op); - return -1; - } - if (op->event) belle_sip_message_add_header(BELLE_SIP_MESSAGE(notify),BELLE_SIP_HEADER(op->event)); - sub_state=belle_sip_header_subscription_state_new(); - belle_sip_header_subscription_state_set_state(sub_state,BELLE_SIP_SUBSCRIPTION_STATE_PENDING); - belle_sip_message_add_header(BELLE_SIP_MESSAGE(notify), BELLE_SIP_HEADER(sub_state)); - return sal_op_send_request(op,notify); - } else { - ms_warning("NOTIFY with subscription state pending for op [%p] not implemented in this case (either dialog pending trans does not exist",op); - } - - return 0; -} - - -int sal_subscribe_decline(SalOp *op, SalReason reason){ - belle_sip_response_t* resp = belle_sip_response_create_from_request(belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(op->pending_server_trans)), - sal_reason_to_sip_code(reason)); - belle_sip_server_transaction_send_response(op->pending_server_trans,resp); - return 0; -} - -int sal_notify(SalOp *op, const SalBodyHandler *body_handler){ - belle_sip_request_t* notify; - - if (op->dialog){ - if (!(notify=belle_sip_dialog_create_queued_request(op->dialog,"NOTIFY"))) return -1; - }else{ - sal_op_subscribe_fill_cbs(op); - notify = sal_op_build_request(op, "NOTIFY"); - } - - if (op->event) belle_sip_message_add_header(BELLE_SIP_MESSAGE(notify),BELLE_SIP_HEADER(op->event)); - - belle_sip_message_add_header(BELLE_SIP_MESSAGE(notify) - ,op->dialog ? - BELLE_SIP_HEADER(belle_sip_header_subscription_state_create(BELLE_SIP_SUBSCRIPTION_STATE_ACTIVE,600)) : - BELLE_SIP_HEADER(belle_sip_header_subscription_state_create(BELLE_SIP_SUBSCRIPTION_STATE_TERMINATED,0)) - ); - belle_sip_message_set_body_handler(BELLE_SIP_MESSAGE(notify), BELLE_SIP_BODY_HANDLER(body_handler)); - return sal_op_send_request(op,notify); -} - -int sal_notify_close(SalOp *op){ - belle_sip_request_t* notify; - if (!op->dialog) return -1; - if (!(notify=belle_sip_dialog_create_queued_request(op->dialog,"NOTIFY"))) return -1; - if (op->event) belle_sip_message_add_header(BELLE_SIP_MESSAGE(notify),BELLE_SIP_HEADER(op->event)); - belle_sip_message_add_header(BELLE_SIP_MESSAGE(notify) - ,BELLE_SIP_HEADER(belle_sip_header_subscription_state_create(BELLE_SIP_SUBSCRIPTION_STATE_TERMINATED,-1))); - return sal_op_send_request(op,notify); -} - diff --git a/coreapi/bellesip_sal/sal_op_impl.c b/coreapi/bellesip_sal/sal_op_impl.c index d99dbc274..7880fa4c6 100644 --- a/coreapi/bellesip_sal/sal_op_impl.c +++ b/coreapi/bellesip_sal/sal_op_impl.c @@ -17,483 +17,9 @@ along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "sal_impl.h" +#include "sal/sal.hpp" -/*create an operation */ -SalOp * sal_op_new(Sal *sal){ - SalOp *op=ms_new0(SalOp,1); - __sal_op_init(op,sal); - op->type=SalOpUnknown; - op->privacy=SalPrivacyNone; - op->manual_refresher=FALSE;/*tells that requests with expiry (SUBSCRIBE, PUBLISH) will be automatically refreshed*/ - op->sdp_handling=sal->default_sdp_handling; - sal_op_ref(op); - return op; -} - -void sal_op_kill_dialog(SalOp *op) { - ms_warning("op [%p]: force kill of dialog [%p]", op, op->dialog); - belle_sip_dialog_delete(op->dialog); -} - -void sal_op_release(SalOp *op){ - /*if in terminating state, keep this state because it means we are waiting for a response to be able to terminate the operation.*/ - if (op->state!=SalOpStateTerminating) - op->state=SalOpStateTerminated; - sal_op_set_user_pointer(op,NULL);/*mandatory because releasing op doesn't not mean freeing op. Make sure back pointer will not be used later*/ - if (op->base.release_cb) - op->base.release_cb(&op->base); - if (op->refresher) { - belle_sip_refresher_stop(op->refresher); - } - op->op_released = TRUE; - sal_op_unref(op); -} - -void sal_op_release_impl(SalOp *op){ - ms_message("Destroying op [%p] of type [%s]",op,sal_op_type_to_string(op->type)); - if (op->pending_auth_transaction) belle_sip_object_unref(op->pending_auth_transaction); - sal_remove_pending_auth(op->base.root,op); - if (op->auth_info) { - sal_auth_info_delete(op->auth_info); - } - if (op->sdp_answer) belle_sip_object_unref(op->sdp_answer); - if (op->refresher) { - belle_sip_object_unref(op->refresher); - op->refresher=NULL; - } - if (op->result) - sal_media_description_unref(op->result); - if(op->replaces) belle_sip_object_unref(op->replaces); - if(op->referred_by) belle_sip_object_unref(op->referred_by); - - if (op->pending_client_trans) belle_sip_object_unref(op->pending_client_trans); - if (op->pending_server_trans) belle_sip_object_unref(op->pending_server_trans); - if (op->pending_update_server_trans) belle_sip_object_unref(op->pending_update_server_trans); - if (op->event) belle_sip_object_unref(op->event); - sal_error_info_reset(&op->error_info); - __sal_op_free(op); - return ; -} - -void sal_op_authenticate(SalOp *op, const SalAuthInfo *info){ - if (op->type == SalOpRegister) { - /*Registration authenticate is just about registering again*/ - sal_register_refresh(op,-1); - }else { - /*for sure auth info will be accessible from the provider*/ - sal_process_authentication(op); - } - return ; -} - -void sal_op_cancel_authentication(SalOp *h){ - ms_fatal("sal_op_cancel_authentication not implemented yet"); - return ; -} - -SalAuthInfo * sal_op_get_auth_requested(SalOp *op){ - return op->auth_info; -} - -belle_sip_header_contact_t* sal_op_create_contact(SalOp *op){ - belle_sip_header_contact_t* contact_header; - belle_sip_uri_t* contact_uri; - - if (sal_op_get_contact_address(op)) { - contact_header = belle_sip_header_contact_create(BELLE_SIP_HEADER_ADDRESS(sal_op_get_contact_address(op))); - } else { - contact_header= belle_sip_header_contact_new(); - } - - if (!(contact_uri=belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(contact_header)))) { - /*no uri, just creating a new one*/ - contact_uri=belle_sip_uri_new(); - belle_sip_header_address_set_uri(BELLE_SIP_HEADER_ADDRESS(contact_header),contact_uri); - } - - belle_sip_uri_set_user_password(contact_uri,NULL); - belle_sip_uri_set_secure(contact_uri,sal_op_is_secure(op)); - if (op->privacy!=SalPrivacyNone){ - belle_sip_uri_set_user(contact_uri,NULL); - } - belle_sip_header_contact_set_automatic(contact_header,op->base.root->auto_contacts); - if (op->base.root->uuid){ - if (belle_sip_parameters_has_parameter(BELLE_SIP_PARAMETERS(contact_header),"+sip.instance")==0){ - char *instance_id=belle_sip_strdup_printf("\"\"",op->base.root->uuid); - belle_sip_parameters_set_parameter(BELLE_SIP_PARAMETERS(contact_header),"+sip.instance",instance_id); - belle_sip_free(instance_id); - } - } - return contact_header; -} - - - -static void add_initial_route_set(belle_sip_request_t *request, const MSList *list){ - const MSList *elem; - for (elem=list;elem!=NULL;elem=elem->next){ - SalAddress *addr=(SalAddress*)elem->data; - belle_sip_header_route_t *route; - belle_sip_uri_t *uri; - /*Optimization: if the initial route set only contains one URI which is the same as the request URI, ommit it*/ - if (elem==list && list->next==NULL){ - belle_sip_uri_t *requri=belle_sip_request_get_uri(request); - /*skip the first route it is the same as the request uri*/ - if (strcmp(sal_address_get_domain(addr),belle_sip_uri_get_host(requri))==0 ){ - ms_message("Skipping top route of initial route-set because same as request-uri."); - continue; - } - } - - route=belle_sip_header_route_create((belle_sip_header_address_t*)addr); - uri=belle_sip_header_address_get_uri((belle_sip_header_address_t*)route); - belle_sip_uri_set_lr_param(uri,1); - belle_sip_message_add_header((belle_sip_message_t*)request,(belle_sip_header_t*)route); - } -} - -belle_sip_request_t* sal_op_build_request(SalOp *op,const char* method) { - belle_sip_header_from_t* from_header; - belle_sip_header_to_t* to_header; - belle_sip_provider_t* prov=op->base.root->prov; - belle_sip_request_t *req; - belle_sip_uri_t* req_uri; - belle_sip_uri_t* to_uri; - belle_sip_header_call_id_t *call_id_header; - - const SalAddress* to_address; - const MSList *elem=sal_op_get_route_addresses(op); - char token[10]; - - /* check that the op has a correct to address */ - to_address = sal_op_get_to_address(op); - if( to_address == NULL ){ - ms_error("No To: address, cannot build request"); - return NULL; - } - - to_uri = belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(to_address)); - if( to_uri == NULL ){ - ms_error("To: address is invalid, cannot build request"); - return NULL; - } - - if (strcmp("REGISTER",method)==0 || op->privacy==SalPrivacyNone) { - from_header = belle_sip_header_from_create(BELLE_SIP_HEADER_ADDRESS(sal_op_get_from_address(op)) - ,belle_sip_random_token(token,sizeof(token))); - } else { - from_header=belle_sip_header_from_create2("Anonymous ",belle_sip_random_token(token,sizeof(token))); - } - /*make sure to preserve components like headers or port*/ - - req_uri = (belle_sip_uri_t*)belle_sip_object_clone((belle_sip_object_t*)to_uri); - belle_sip_uri_set_secure(req_uri,sal_op_is_secure(op)); - - to_header = belle_sip_header_to_create(BELLE_SIP_HEADER_ADDRESS(to_address),NULL); - call_id_header = belle_sip_provider_create_call_id(prov); - if (sal_op_get_call_id(op)) { - belle_sip_header_call_id_set_call_id(call_id_header, sal_op_get_call_id(op)); - } - - req=belle_sip_request_create( - req_uri, - method, - call_id_header, - belle_sip_header_cseq_create(20,method), - from_header, - to_header, - belle_sip_header_via_new(), - 70); - - if (op->privacy & SalPrivacyId) { - belle_sip_header_p_preferred_identity_t* p_preferred_identity=belle_sip_header_p_preferred_identity_create(BELLE_SIP_HEADER_ADDRESS(sal_op_get_from_address(op))); - belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(p_preferred_identity)); - } - - if (elem && strcmp(method,"REGISTER")!=0 && !op->base.root->no_initial_route){ - add_initial_route_set(req,elem); - } - - if (strcmp("REGISTER",method)!=0 && op->privacy!=SalPrivacyNone ){ - belle_sip_header_privacy_t* privacy_header=belle_sip_header_privacy_new(); - if (op->privacy&SalPrivacyCritical) - belle_sip_header_privacy_add_privacy(privacy_header,sal_privacy_to_string(SalPrivacyCritical)); - if (op->privacy&SalPrivacyHeader) - belle_sip_header_privacy_add_privacy(privacy_header,sal_privacy_to_string(SalPrivacyHeader)); - if (op->privacy&SalPrivacyId) - belle_sip_header_privacy_add_privacy(privacy_header,sal_privacy_to_string(SalPrivacyId)); - if (op->privacy&SalPrivacyNone) - belle_sip_header_privacy_add_privacy(privacy_header,sal_privacy_to_string(SalPrivacyNone)); - if (op->privacy&SalPrivacySession) - belle_sip_header_privacy_add_privacy(privacy_header,sal_privacy_to_string(SalPrivacySession)); - if (op->privacy&SalPrivacyUser) - belle_sip_header_privacy_add_privacy(privacy_header,sal_privacy_to_string(SalPrivacyUser)); - belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(privacy_header)); - } - belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),op->base.root->supported); - return req; -} - -belle_sip_response_t *sal_op_create_response_from_request(SalOp *op, belle_sip_request_t *req, int code){ - return sal_create_response_from_request(op->base.root,req,code); -} - -/*ping: main purpose is to obtain its own contact address behind firewalls*/ -int sal_ping(SalOp *op, const char *from, const char *to){ - sal_op_set_from(op,from); - sal_op_set_to(op,to); - return sal_op_send_request(op,sal_op_build_request(op,"OPTIONS")); -} - -void sal_op_set_replaces(SalOp* op,belle_sip_header_replaces_t* replaces) { - if (op->replaces){ - belle_sip_object_unref(op->replaces); - } - op->replaces=replaces; - belle_sip_object_ref(op->replaces); -} - -void sal_op_set_remote_ua(SalOp*op,belle_sip_message_t* message) { - belle_sip_header_user_agent_t* user_agent=belle_sip_message_get_header_by_type(message,belle_sip_header_user_agent_t); - char user_agent_string[256]; - if (user_agent && belle_sip_header_user_agent_get_products_as_string(user_agent,user_agent_string,sizeof(user_agent_string))>0) { - if (op->base.remote_ua!=NULL){ - ms_free(op->base.remote_ua); - } - op->base.remote_ua=ms_strdup(user_agent_string); - } -} - -int sal_op_send_request_with_expires(SalOp* op, belle_sip_request_t* request,int expires) { - belle_sip_header_expires_t* expires_header=(belle_sip_header_expires_t*)belle_sip_message_get_header(BELLE_SIP_MESSAGE(request),BELLE_SIP_EXPIRES); - - if (!expires_header && expires>=0) { - belle_sip_message_add_header(BELLE_SIP_MESSAGE(request),BELLE_SIP_HEADER(expires_header=belle_sip_header_expires_new())); - } - if (expires_header) belle_sip_header_expires_set_expires(expires_header,expires); - return sal_op_send_request(op,request); -} - -void sal_op_resend_request(SalOp* op, belle_sip_request_t* request) { - belle_sip_header_cseq_t* cseq=(belle_sip_header_cseq_t*)belle_sip_message_get_header(BELLE_SIP_MESSAGE(request),BELLE_SIP_CSEQ); - belle_sip_header_cseq_set_seq_number(cseq,belle_sip_header_cseq_get_seq_number(cseq)+1); - sal_op_send_request(op,request); -} - -static void add_headers(SalOp *op, belle_sip_header_t *h, belle_sip_message_t *msg){ - - if (BELLE_SIP_OBJECT_IS_INSTANCE_OF(h,belle_sip_header_contact_t)){ - belle_sip_header_contact_t* newct; - /*special case for contact, we want to keep everything from the custom contact but set automatic mode and add our own parameters as well*/ - sal_op_set_contact_address(op,(SalAddress*)BELLE_SIP_HEADER_ADDRESS(h)); - newct = sal_op_create_contact(op); - belle_sip_message_set_header(BELLE_SIP_MESSAGE(msg),BELLE_SIP_HEADER(newct)); - return; - } - /*if a header already exists in the message, replace it*/ - belle_sip_message_set_header(msg,h); - -} - -void _sal_op_add_custom_headers(SalOp *op, belle_sip_message_t *msg){ - if (op->base.sent_custom_headers){ - belle_sip_message_t *ch=(belle_sip_message_t*)op->base.sent_custom_headers; - belle_sip_list_t *l=belle_sip_message_get_all_headers(ch); - belle_sip_list_t *elem; - for(elem=l;elem!=NULL;elem=elem->next){ - add_headers(op,(belle_sip_header_t*)elem->data,msg); - } - belle_sip_list_free(l); - } -} - -static int _sal_op_send_request_with_contact(SalOp* op, belle_sip_request_t* request, bool_t add_contact) { - belle_sip_client_transaction_t* client_transaction; - belle_sip_provider_t* prov=op->base.root->prov; - belle_sip_uri_t* outbound_proxy=NULL; - belle_sip_header_contact_t* contact; - int result =-1; - belle_sip_uri_t *next_hop_uri=NULL; - - if (add_contact && !belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(request),belle_sip_header_contact_t)) { - contact = sal_op_create_contact(op); - belle_sip_message_set_header(BELLE_SIP_MESSAGE(request),BELLE_SIP_HEADER(contact)); - } /*keep existing*/ - - _sal_op_add_custom_headers(op, (belle_sip_message_t*)request); - - if (!op->dialog || belle_sip_dialog_get_state(op->dialog) == BELLE_SIP_DIALOG_NULL) { - /*don't put route header if dialog is in confirmed state*/ - const MSList *elem=sal_op_get_route_addresses(op); - const char *transport; - const char *method=belle_sip_request_get_method(request); - belle_sip_listening_point_t *udplp=belle_sip_provider_get_listening_point(prov,"UDP"); - - if (elem) { - outbound_proxy=belle_sip_header_address_get_uri((belle_sip_header_address_t*)elem->data); - next_hop_uri=outbound_proxy; - }else{ - next_hop_uri=(belle_sip_uri_t*)belle_sip_object_clone((belle_sip_object_t*)belle_sip_request_get_uri(request)); - } - transport=belle_sip_uri_get_transport_param(next_hop_uri); - if (transport==NULL){ - /*compatibility mode: by default it should be udp as not explicitely set and if no udp listening point is available, then use - * the first available transport*/ - if (!belle_sip_uri_is_secure(next_hop_uri)){ - if (udplp==NULL){ - if (belle_sip_provider_get_listening_point(prov,"TCP")!=NULL){ - transport="tcp"; - }else if (belle_sip_provider_get_listening_point(prov,"TLS")!=NULL ){ - transport="tls"; - } - } - if (transport){ - belle_sip_message("Transport is not specified, using %s because UDP is not available.",transport); - belle_sip_uri_set_transport_param(next_hop_uri,transport); - } - } - }else{ -#ifdef TUNNEL_ENABLED - if (udplp && BELLE_SIP_OBJECT_IS_INSTANCE_OF(udplp,belle_sip_tunnel_listening_point_t)){ - /* our tunnel mode only supports UDP. Force transport to be set to UDP */ - belle_sip_uri_set_transport_param(next_hop_uri,"udp"); - } -#endif - } - /*because in case of tunnel, transport can be changed*/ - transport=belle_sip_uri_get_transport_param(next_hop_uri); - - if ((strcmp(method,"REGISTER")==0 || strcmp(method,"SUBSCRIBE")==0) && transport && - (strcasecmp(transport,"TCP")==0 || strcasecmp(transport,"TLS")==0)){ - /*RFC 5923: add 'alias' parameter to tell the server that we want it to keep the connection for future requests*/ - belle_sip_header_via_t *via=belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(request),belle_sip_header_via_t); - belle_sip_parameters_set_parameter(BELLE_SIP_PARAMETERS(via),"alias",NULL); - } - } - - client_transaction = belle_sip_provider_create_client_transaction(prov,request); - belle_sip_transaction_set_application_data(BELLE_SIP_TRANSACTION(client_transaction),sal_op_ref(op)); - if (op->pending_client_trans) belle_sip_object_unref(op->pending_client_trans); - op->pending_client_trans=client_transaction; /*update pending inv for being able to cancel*/ - belle_sip_object_ref(op->pending_client_trans); - - if (belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(request),belle_sip_header_user_agent_t)==NULL) - belle_sip_message_add_header(BELLE_SIP_MESSAGE(request),BELLE_SIP_HEADER(op->base.root->user_agent)); - - if (!belle_sip_message_get_header(BELLE_SIP_MESSAGE(request),BELLE_SIP_AUTHORIZATION) - && !belle_sip_message_get_header(BELLE_SIP_MESSAGE(request),BELLE_SIP_PROXY_AUTHORIZATION)) { - /*hmm just in case we already have authentication param in cache*/ - belle_sip_provider_add_authorization(op->base.root->prov,request,NULL,NULL,NULL,op->base.realm); - } - result = belle_sip_client_transaction_send_request_to(client_transaction,next_hop_uri/*might be null*/); - - /*update call id if not set yet for this OP*/ - if (result == 0 && !op->base.call_id) { - op->base.call_id=ms_strdup(belle_sip_header_call_id_get_call_id(BELLE_SIP_HEADER_CALL_ID(belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(request), belle_sip_header_call_id_t)))); - } - - return result; - -} - -int sal_op_send_request(SalOp* op, belle_sip_request_t* request) { - bool_t need_contact=FALSE; - if (request==NULL) { - return -1; /*sanity check*/ - } - /* - Header field where proxy ACK BYE CAN INV OPT REG - ___________________________________________________________ - Contact R o - - m o o - */ - if (strcmp(belle_sip_request_get_method(request),"INVITE")==0 - ||strcmp(belle_sip_request_get_method(request),"REGISTER")==0 - ||strcmp(belle_sip_request_get_method(request),"SUBSCRIBE")==0 - ||strcmp(belle_sip_request_get_method(request),"OPTIONS")==0 - ||strcmp(belle_sip_request_get_method(request),"REFER")==0) /* Despite contact seems not mandatory, call flow example show a Contact in REFER requests*/ - need_contact=TRUE; - - return _sal_op_send_request_with_contact(op, request,need_contact); -} - -int sal_reason_to_sip_code(SalReason r){ - int ret=500; - switch(r){ - case SalReasonNone: - ret=200; - break; - case SalReasonIOError: - ret=503; - break; - case SalReasonUnknown: - ret=400; - break; - case SalReasonBusy: - ret=486; - break; - case SalReasonDeclined: - ret=603; - break; - case SalReasonDoNotDisturb: - ret=600; - break; - case SalReasonForbidden: - ret=403; - break; - case SalReasonUnsupportedContent: - ret=415; - break; - case SalReasonNotFound: - ret=404; - break; - case SalReasonRedirect: - ret=302; - break; - case SalReasonTemporarilyUnavailable: - ret=480; - break; - case SalReasonServiceUnavailable: - ret=503; - break; - case SalReasonRequestPending: - ret=491; - break; - case SalReasonUnauthorized: - ret=401; - break; - case SalReasonNotAcceptable: - ret=488; /*or maybe 606 Not Acceptable ?*/ - break; - case SalReasonNoMatch: - ret=481; - break; - case SalReasonRequestTimeout: - ret=408; - break; - case SalReasonMovedPermanently: - ret=301; - break; - case SalReasonGone: - ret=410; - break; - case SalReasonAddressIncomplete: - ret=484; - break; - case SalReasonNotImplemented: - ret=501; - break; - case SalReasonServerTimeout: - ret=504; - break; - case SalReasonBadGateway: - ret=502; - break; - case SalReasonInternalError: - ret=500; - break; - } - return ret; -} +using namespace LINPHONE_NAMESPACE; SalReason _sal_reason_from_sip_code(int code) { if (code>=100 && code<300) return SalReasonNone; @@ -596,7 +122,7 @@ void sal_error_info_set(SalErrorInfo *ei, SalReason reason, const char *protocol else{ ei->reason=reason; if (code == 0) { - code = sal_reason_to_sip_code(reason); + code = to_sip_code(reason); } } ei->protocol_code=code; @@ -610,286 +136,4 @@ void sal_error_info_set(SalErrorInfo *ei, SalReason reason, const char *protocol } } -void sal_op_set_reason_error_info(SalOp *op, belle_sip_message_t *msg){ - belle_sip_header_reason_t* reason_header = belle_sip_message_get_header_by_type(msg,belle_sip_header_reason_t); - if (reason_header){ - SalErrorInfo *ei=&op->reason_error_info; // ?// - const char *protocol = belle_sip_header_reason_get_protocol(reason_header); - int code = belle_sip_header_reason_get_cause(reason_header); - const char *text = belle_sip_header_reason_get_text(reason_header); - sal_error_info_set(ei, SalReasonUnknown, protocol, code, text, NULL); - } -} - -void sal_op_set_error_info_from_response(SalOp *op, belle_sip_response_t *response){ - int code = belle_sip_response_get_status_code(response); - const char *reason_phrase=belle_sip_response_get_reason_phrase(response); - belle_sip_header_t *warning=belle_sip_message_get_header(BELLE_SIP_MESSAGE(response),"Warning"); - SalErrorInfo *ei=&op->error_info; - const char *warnings; - - warnings=warning ? belle_sip_header_get_unparsed_value(warning) : NULL; - sal_error_info_set(ei,SalReasonUnknown,"SIP", code,reason_phrase,warnings); - sal_op_set_reason_error_info(op, BELLE_SIP_MESSAGE(response)); -} - -const SalErrorInfo *sal_op_get_error_info(const SalOp *op){ - return &op->error_info; -} - -const SalErrorInfo * sal_op_get_reason_error_info(const SalOp *op){ - return &op->reason_error_info; -} - - - - -static void unlink_op_with_dialog(SalOp *op, belle_sip_dialog_t* dialog){ - belle_sip_dialog_set_application_data(dialog,NULL); - sal_op_unref(op); - belle_sip_object_unref(dialog); -} - -static belle_sip_dialog_t *link_op_with_dialog(SalOp *op, belle_sip_dialog_t* dialog){ - belle_sip_dialog_set_application_data(dialog,sal_op_ref(op)); - belle_sip_object_ref(dialog); - return dialog; -} - -void set_or_update_dialog(SalOp* op, belle_sip_dialog_t* dialog) { - ms_message("op [%p] : set_or_update_dialog() current=[%p] new=[%p]",op,op->dialog,dialog); - sal_op_ref(op); - if (op->dialog!=dialog){ - if (op->dialog){ - /*FIXME: shouldn't we delete unconfirmed dialogs ?*/ - unlink_op_with_dialog(op,op->dialog); - op->dialog=NULL; - } - if (dialog) { - op->dialog=link_op_with_dialog(op,dialog); - belle_sip_dialog_enable_pending_trans_checking(dialog,op->base.root->pending_trans_checking); - } - } - sal_op_unref(op); -} -/*return reffed op*/ -SalOp* sal_op_ref(SalOp* op) { - op->ref++; - return op; -} -/*return null, destroy op if ref count =0*/ -void* sal_op_unref(SalOp* op) { - op->ref--; - if (op->ref==0) { - sal_op_release_impl(op); - }else if (op->ref<0){ - ms_fatal("SalOp [%p]: too many unrefs.",op); - } - return NULL; -} - -int sal_op_send_and_create_refresher(SalOp* op,belle_sip_request_t* req, int expires,belle_sip_refresher_listener_t listener ) { - if (sal_op_send_request_with_expires(op,req,expires)==0) { - if (op->refresher) { - belle_sip_refresher_stop(op->refresher); - belle_sip_object_unref(op->refresher); - } - if ((op->refresher = belle_sip_client_transaction_create_refresher(op->pending_client_trans))) { - /*since refresher acquires the transaction, we should remove our context from the transaction, because we won't be notified - * that it is terminated anymore.*/ - sal_op_unref(op);/*loose the reference that was given to the transaction when creating it*/ - /* Note that the refresher will replace our data with belle_sip_transaction_set_application_data(). - Something in the design is not very good here, it makes things complicated to the belle-sip user. - Possible ideas to improve things: refresher shall not use belle_sip_transaction_set_application_data() internally, refresher should let the first transaction - notify the user as a normal transaction*/ - belle_sip_refresher_set_listener(op->refresher,listener,op); - belle_sip_refresher_set_retry_after(op->refresher,op->base.root->refresher_retry_after); - belle_sip_refresher_set_realm(op->refresher,op->base.realm); - belle_sip_refresher_enable_manual_mode(op->refresher,op->manual_refresher); - return 0; - } else { - return -1; - } - } - return -1; -} - -const char* sal_op_state_to_string(const SalOpState value) { - switch(value) { - case SalOpStateEarly: return"SalOpStateEarly"; - case SalOpStateActive: return "SalOpStateActive"; - case SalOpStateTerminating: return "SalOpStateTerminating"; - case SalOpStateTerminated: return "SalOpStateTerminated"; - default: - return "Unknown"; - } -} - -/* - * Warning: this function takes owneship of the custom headers - */ -void sal_op_set_sent_custom_header(SalOp *op, SalCustomHeader* ch){ - SalOpBase *b=(SalOpBase *)op; - if (b->sent_custom_headers){ - sal_custom_header_free(b->sent_custom_headers); - b->sent_custom_headers=NULL; - } - if (ch) belle_sip_object_ref((belle_sip_message_t*)ch); - b->sent_custom_headers=ch; -} - -void sal_op_assign_recv_headers(SalOp *op, belle_sip_message_t *incoming){ - if (incoming) belle_sip_object_ref(incoming); - if (op->base.recv_custom_headers){ - belle_sip_object_unref(op->base.recv_custom_headers); - op->base.recv_custom_headers=NULL; - } - if (incoming){ - op->base.recv_custom_headers=(SalCustomHeader*)incoming; - } -} - -const char *sal_op_get_remote_contact(const SalOp *op){ - /* - * remote contact is filled in process_response - */ - return op->base.remote_contact; -} - -SalBodyHandler * sal_op_get_body_handler(SalOp *op, belle_sip_message_t *msg) { - belle_sip_body_handler_t *body_handler = belle_sip_message_get_body_handler(msg); - if (body_handler != NULL) { - belle_sip_header_content_type_t *content_type = belle_sip_message_get_header_by_type(msg, belle_sip_header_content_type_t); - belle_sip_header_content_length_t *content_length = belle_sip_message_get_header_by_type(msg, belle_sip_header_content_length_t); - belle_sip_header_t *content_encoding = belle_sip_message_get_header(msg, "Content-Encoding"); - if (content_type != NULL) belle_sip_body_handler_add_header(body_handler, BELLE_SIP_HEADER(content_type)); - if (content_length != NULL) belle_sip_body_handler_add_header(body_handler, BELLE_SIP_HEADER(content_length)); - if (content_encoding != NULL) belle_sip_body_handler_add_header(body_handler, content_encoding); - } - return (SalBodyHandler *)body_handler; -} - -void sal_op_set_privacy(SalOp* op,SalPrivacyMask privacy) { - op->privacy=privacy; -} -SalPrivacyMask sal_op_get_privacy(const SalOp* op) { - return op->privacy; -} - -bool_t sal_op_is_secure(const SalOp* op) { - const SalAddress* from = sal_op_get_from_address(op); - const SalAddress* to = sal_op_get_to_address(op); - - return from && to && strcasecmp("sips",sal_address_get_scheme(from))==0 && strcasecmp("sips",sal_address_get_scheme(to))==0; -} - -void sal_op_set_manual_refresher_mode(SalOp *op, bool_t enabled){ - op->manual_refresher=enabled; -} - -int sal_op_get_address_family(SalOp *op){ - belle_sip_transaction_t *tr=NULL; - belle_sip_header_address_t *contact; - - - if (op->refresher) - tr=(belle_sip_transaction_t *)belle_sip_refresher_get_transaction(op->refresher); - - if (tr==NULL) - tr=(belle_sip_transaction_t *)op->pending_client_trans; - if (tr==NULL) - tr=(belle_sip_transaction_t *)op->pending_server_trans; - - if (tr==NULL){ - ms_error("Unable to determine IP version from signaling operation."); - return AF_UNSPEC; - } - - - if (op->refresher) { - belle_sip_response_t *resp = belle_sip_transaction_get_response(tr); - belle_sip_header_via_t *via = resp ?belle_sip_message_get_header_by_type(resp,belle_sip_header_via_t):NULL; - if (!via){ - ms_error("Unable to determine IP version from signaling operation, no via header found."); - return AF_UNSPEC; - } - return (strchr(belle_sip_header_via_get_host(via),':') != NULL) ? AF_INET6 : AF_INET; - } else { - belle_sip_request_t *req = belle_sip_transaction_get_request(tr); - contact=(belle_sip_header_address_t*)belle_sip_message_get_header_by_type(req,belle_sip_header_contact_t); - if (!contact){ - ms_error("Unable to determine IP version from signaling operation, no contact header found."); - } - return sal_address_is_ipv6((SalAddress*)contact) ? AF_INET6 : AF_INET; - } -} - -bool_t sal_op_is_idle(SalOp *op){ - if (op->dialog){ - return !belle_sip_dialog_request_pending(op->dialog); - } - return TRUE; -} - -void sal_op_stop_refreshing(SalOp *op){ - if (op->refresher){ - belle_sip_refresher_stop(op->refresher); - } -} - -void sal_call_set_sdp_handling(SalOp *h, SalOpSDPHandling handling) { - if (handling != SalOpSDPNormal) ms_message("Enabling special SDP handling for SalOp[%p]!", h); - h->sdp_handling = handling; -} -void sal_op_cnx_ip_to_0000_if_sendonly_enable(SalOp *op,bool_t yesno) { - op->cnx_ip_to_0000_if_sendonly_enabled = yesno; -} - -bool_t sal_op_cnx_ip_to_0000_if_sendonly_enabled(SalOp *op) { - return op->cnx_ip_to_0000_if_sendonly_enabled; -} - -bool_t sal_op_is_forked_of(const SalOp *op1, const SalOp *op2){ - return op1->base.call_id && op2->base.call_id && strcmp(op1->base.call_id, op2->base.call_id) == 0; -} -int sal_op_refresh(SalOp *op) { - if (op->refresher) { - belle_sip_refresher_refresh(op->refresher,belle_sip_refresher_get_expires(op->refresher)); - return 0; - } - ms_warning("sal_refresh on op [%p] of type [%s] no refresher",op,sal_op_type_to_string(op->type)); - return -1; -} - -void sal_op_set_event(SalOp *op, const char *eventname){ - belle_sip_header_event_t *header = NULL; - if (op->event) belle_sip_object_unref(op->event); - if (eventname){ - header = belle_sip_header_event_create(eventname); - belle_sip_object_ref(header); - } - op->event = header; -} - -const char* sal_op_get_public_address(SalOp *op, int *port) { - if (op && op->refresher) { - return belle_sip_refresher_get_public_address(op->refresher, port); - } - return NULL; -} - -const char* sal_op_get_local_address(SalOp *op, int *port) { - if (op && op->refresher) { - return belle_sip_refresher_get_local_address(op->refresher, port); - } - return NULL; -} - -char* sal_op_get_dialog_id(const SalOp *op) { - if (op->dialog != NULL) { - return ms_strdup_printf("%s;to-tag=%s;from-tag=%s", ((SalOpBase*)op)->call_id, - belle_sip_dialog_get_remote_tag(op->dialog), belle_sip_dialog_get_local_tag(op->dialog)); - } - return NULL; -} diff --git a/coreapi/bellesip_sal/sal_op_info.c b/coreapi/bellesip_sal/sal_op_info.c deleted file mode 100644 index 7ecf8e68b..000000000 --- a/coreapi/bellesip_sal/sal_op_info.c +++ /dev/null @@ -1,34 +0,0 @@ -/* -linphone -Copyright (C) 2012 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 -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 "sal_impl.h" - - -int sal_send_info(SalOp *op, const char *from, const char *to, const SalBodyHandler *body_handler){ - if (op->dialog && belle_sip_dialog_get_state(op->dialog) == BELLE_SIP_DIALOG_CONFIRMED){ - belle_sip_request_t *req; - belle_sip_dialog_enable_pending_trans_checking(op->dialog,op->base.root->pending_trans_checking); - req=belle_sip_dialog_create_queued_request(op->dialog,"INFO"); - belle_sip_message_set_body_handler(BELLE_SIP_MESSAGE(req), BELLE_SIP_BODY_HANDLER(body_handler)); - return sal_op_send_request(op,req); - }else{ - ms_error("Cannot send INFO message on op [%p] because dialog is not in confirmed state yet.", op); - } - return -1; -} - diff --git a/coreapi/bellesip_sal/sal_op_message.c b/coreapi/bellesip_sal/sal_op_message.c deleted file mode 100644 index cfb73763a..000000000 --- a/coreapi/bellesip_sal/sal_op_message.c +++ /dev/null @@ -1,216 +0,0 @@ -/* -linphone -Copyright (C) 2012 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 -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 "sal_impl.h" - -#include "linphone/core.h" -#include "private.h" -#include - -static void process_error( SalOp* op) { - if (op->dir == SalOpDirOutgoing) { - op->base.root->callbacks.message_delivery_update(op, SalMessageDeliveryFailed); - } else { - ms_warning("unexpected io error for incoming message on op [%p]",op); - } - op->state=SalOpStateTerminated; - -} - -static void process_io_error(void *user_ctx, const belle_sip_io_error_event_t *event){ - SalOp* op = (SalOp*)user_ctx; - sal_error_info_set(&op->error_info,SalReasonIOError, "SIP", 503,"IO Error",NULL); - process_error(op); -} -static void process_timeout(void *user_ctx, const belle_sip_timeout_event_t *event) { - SalOp* op=(SalOp*)user_ctx; - sal_error_info_set(&op->error_info,SalReasonRequestTimeout, "SIP", 408,"Request timeout",NULL); - process_error(op); - -} -static void process_response_event(void *op_base, const belle_sip_response_event_t *event){ - SalOp* op = (SalOp*)op_base; - int code = belle_sip_response_get_status_code(belle_sip_response_event_get_response(event)); - SalMessageDeliveryStatus status; - sal_op_set_error_info_from_response(op,belle_sip_response_event_get_response(event)); - - if (code>=100 && code <200) - status=SalMessageDeliveryInProgress; - else if (code>=200 && code <300) - status=SalMessageDeliveryDone; - else - status=SalMessageDeliveryFailed; - - op->base.root->callbacks.message_delivery_update(op,status); -} - -static bool_t is_external_body(belle_sip_header_content_type_t* content_type) { - return strcmp("message",belle_sip_header_content_type_get_type(content_type))==0 - && strcmp("external-body",belle_sip_header_content_type_get_subtype(content_type))==0; -} - -static void add_message_accept(SalOp *op, belle_sip_message_t *msg) { - bctbx_list_t *item; - const char *str; - char *old; - char *header = ms_strdup("xml/cipher, application/cipher.vnd.gsma.rcs-ft-http+xml"); - - for (item = op->base.root->supported_content_types; item != NULL; item = bctbx_list_next(item)) { - str = (const char *)bctbx_list_get_data(item); - old = header; - header = ms_strdup_printf("%s, %s", old, str); - ms_free(old); - } - - belle_sip_message_add_header(msg, belle_sip_header_create("Accept", header)); - ms_free(header); -} - -void sal_process_incoming_message(SalOp *op,const belle_sip_request_event_t *event){ - belle_sip_request_t* req = belle_sip_request_event_get_request(event); - belle_sip_server_transaction_t* server_transaction = belle_sip_provider_create_server_transaction(op->base.root->prov,req); - belle_sip_header_address_t* address; - belle_sip_header_from_t* from_header; - belle_sip_header_content_type_t* content_type; - belle_sip_response_t* resp; - int errcode = 500; - belle_sip_header_call_id_t* call_id = belle_sip_message_get_header_by_type(req,belle_sip_header_call_id_t); - belle_sip_header_cseq_t* cseq = belle_sip_message_get_header_by_type(req,belle_sip_header_cseq_t); - belle_sip_header_date_t *date=belle_sip_message_get_header_by_type(req,belle_sip_header_date_t); - char* from; - bool_t external_body=FALSE; - - from_header=belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req),belle_sip_header_from_t); - content_type=belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req),belle_sip_header_content_type_t); - - if (content_type) { - SalMessage salmsg; - char message_id[256]={0}; - - if (op->pending_server_trans) belle_sip_object_unref(op->pending_server_trans); - op->pending_server_trans=server_transaction; - belle_sip_object_ref(op->pending_server_trans); - - external_body=is_external_body(content_type); - address=belle_sip_header_address_create(belle_sip_header_address_get_displayname(BELLE_SIP_HEADER_ADDRESS(from_header)) - ,belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(from_header))); - from=belle_sip_object_to_string(BELLE_SIP_OBJECT(address)); - snprintf(message_id,sizeof(message_id)-1,"%s%i" - ,belle_sip_header_call_id_get_call_id(call_id) - ,belle_sip_header_cseq_get_seq_number(cseq)); - salmsg.from=from; - /* if we just deciphered a message, use the deciphered part(which can be a rcs xml body pointing to the file to retreive from server)*/ - salmsg.text=(!external_body)?belle_sip_message_get_body(BELLE_SIP_MESSAGE(req)):NULL; - salmsg.url=NULL; - salmsg.content_type = ms_strdup_printf("%s/%s", belle_sip_header_content_type_get_type(content_type), belle_sip_header_content_type_get_subtype(content_type)); - if (external_body && belle_sip_parameters_get_parameter(BELLE_SIP_PARAMETERS(content_type),"URL")) { - size_t url_length=strlen(belle_sip_parameters_get_parameter(BELLE_SIP_PARAMETERS(content_type),"URL")); - salmsg.url = ms_strdup(belle_sip_parameters_get_parameter(BELLE_SIP_PARAMETERS(content_type),"URL")+1); /* skip first "*/ - ((char*)salmsg.url)[url_length-2]='\0'; /*remove trailing "*/ - } - salmsg.message_id=message_id; - salmsg.time=date ? belle_sip_header_date_get_time(date) : time(NULL); - op->base.root->callbacks.message_received(op,&salmsg); - - belle_sip_object_unref(address); - belle_sip_free(from); - if (salmsg.url) ms_free((char*)salmsg.url); - ms_free((char *)salmsg.content_type); - } else { - ms_error("Unsupported MESSAGE (no Content-Type)"); - resp = belle_sip_response_create_from_request(req, errcode); - add_message_accept(op, (belle_sip_message_t*)resp); - belle_sip_server_transaction_send_response(server_transaction,resp); - sal_op_release(op); - } -} - -static void process_request_event(void *op_base, const belle_sip_request_event_t *event) { - SalOp* op = (SalOp*)op_base; - sal_process_incoming_message(op,event); -} - -int sal_message_send(SalOp *op, const char *from, const char *to, const char* content_type, const char *msg, const char *peer_uri){ - belle_sip_request_t* req; - char content_type_raw[256]; - size_t content_length = msg?strlen(msg):0; - time_t curtime = ms_time(NULL); - const char *body; - int retval; - - if (op->dialog){ - /*for SIP MESSAGE that are sent in call's dialog*/ - req=belle_sip_dialog_create_queued_request(op->dialog,"MESSAGE"); - }else{ - sal_op_message_fill_cbs(op); - if (from) - sal_op_set_from(op,from); - if (to) - sal_op_set_to(op,to); - op->dir=SalOpDirOutgoing; - - req=sal_op_build_request(op,"MESSAGE"); - if (req == NULL ){ - return -1; - } - if (sal_op_get_contact_address(op)){ - belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(sal_op_create_contact(op))); - } - } - - snprintf(content_type_raw,sizeof(content_type_raw),BELLE_SIP_CONTENT_TYPE ": %s",content_type); - belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(belle_sip_header_content_type_parse(content_type_raw))); - belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(belle_sip_header_content_length_create(content_length))); - belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(belle_sip_header_date_create_from_time(&curtime))); - body = msg; - if (body){ - /*don't call set_body() with null argument because it resets content type and content length*/ - belle_sip_message_set_body(BELLE_SIP_MESSAGE(req), body, content_length); - } - retval = sal_op_send_request(op,req); - - return retval; -} - -int sal_message_reply(SalOp *op, SalReason reason){ - if (op->pending_server_trans){ - int code=sal_reason_to_sip_code(reason); - belle_sip_response_t *resp = belle_sip_response_create_from_request( - belle_sip_transaction_get_request((belle_sip_transaction_t*)op->pending_server_trans),code); - belle_sip_server_transaction_send_response(op->pending_server_trans,resp); - return 0; - }else ms_error("sal_message_reply(): no server transaction"); - return -1; -} - -int sal_text_send(SalOp *op, const char *from, const char *to, const char *msg) { - return sal_message_send(op,from,to,"text/plain",msg, NULL); -} - -static belle_sip_listener_callbacks_t op_message_callbacks={0}; - -void sal_op_message_fill_cbs(SalOp*op) { - if (op_message_callbacks.process_io_error==NULL){ - op_message_callbacks.process_io_error=process_io_error; - op_message_callbacks.process_response_event=process_response_event; - op_message_callbacks.process_timeout=process_timeout; - op_message_callbacks.process_request_event=process_request_event; - } - op->callbacks=&op_message_callbacks; - op->type=SalOpMessage; -} diff --git a/coreapi/bellesip_sal/sal_op_publish.c b/coreapi/bellesip_sal/sal_op_publish.c deleted file mode 100644 index 5907c2cd6..000000000 --- a/coreapi/bellesip_sal/sal_op_publish.c +++ /dev/null @@ -1,112 +0,0 @@ -/* -linphone -Copyright (C) 2012 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 -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 "sal_impl.h" - - -static void publish_refresher_listener (belle_sip_refresher_t* refresher - ,void* user_pointer - ,unsigned int status_code - ,const char* reason_phrase, int will_retry) { - SalOp* op = (SalOp*)user_pointer; - const belle_sip_client_transaction_t* last_publish_trans=belle_sip_refresher_get_transaction(op->refresher); - belle_sip_response_t *response=belle_sip_transaction_get_response(BELLE_SIP_TRANSACTION(last_publish_trans)); - ms_message("Publish refresher [%i] reason [%s] for proxy [%s]",status_code,reason_phrase?reason_phrase:"none",sal_op_get_proxy(op)); - if (status_code==0){ - op->base.root->callbacks.on_expire(op); - }else if (status_code>=200){ - belle_sip_header_t *sip_etag; - const char *sip_etag_string = NULL; - if (response && (sip_etag = belle_sip_message_get_header(BELLE_SIP_MESSAGE(response), "SIP-ETag"))) { - sip_etag_string = belle_sip_header_get_unparsed_value(sip_etag); - } - sal_op_set_entity_tag(op, sip_etag_string); - sal_error_info_set(&op->error_info,SalReasonUnknown, "SIP", (int)status_code,reason_phrase,NULL); - sal_op_assign_recv_headers(op,(belle_sip_message_t*)response); - op->base.root->callbacks.on_publish_response(op); - } -} - -static void publish_response_event(void *userctx, const belle_sip_response_event_t *event){ - SalOp *op=(SalOp*)userctx; - sal_op_set_error_info_from_response(op,belle_sip_response_event_get_response(event)); - if (op->error_info.protocol_code>=200){ - op->base.root->callbacks.on_publish_response(op); - } -} - -static belle_sip_listener_callbacks_t op_publish_callbacks={0}; - -void sal_op_publish_fill_cbs(SalOp *op) { - if (op_publish_callbacks.process_response_event==NULL){ - op_publish_callbacks.process_response_event=publish_response_event; - } - op->callbacks=&op_publish_callbacks; - op->type=SalOpPublish; -} - -int sal_publish(SalOp *op, const char *from, const char *to, const char *eventname, int expires, const SalBodyHandler *body_handler){ - belle_sip_request_t *req=NULL; - if(!op->refresher || !belle_sip_refresher_get_transaction(op->refresher)) { - if (from) - sal_op_set_from(op,from); - if (to) - sal_op_set_to(op,to); - - sal_op_publish_fill_cbs(op); - req=sal_op_build_request(op,"PUBLISH"); - if( req == NULL ){ - return -1; - } - - if (sal_op_get_entity_tag(op)) { - belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),belle_sip_header_create("SIP-If-Match", sal_op_get_entity_tag(op))); - } - - if (sal_op_get_contact_address(op)){ - belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(sal_op_create_contact(op))); - } - belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),belle_sip_header_create("Event",eventname)); - belle_sip_message_set_body_handler(BELLE_SIP_MESSAGE(req), BELLE_SIP_BODY_HANDLER(body_handler)); - if (expires!=-1) - return sal_op_send_and_create_refresher(op,req,expires,publish_refresher_listener); - else return sal_op_send_request(op,req); - } else { - /*update status*/ - const belle_sip_client_transaction_t* last_publish_trans=belle_sip_refresher_get_transaction(op->refresher); - belle_sip_request_t* last_publish=belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(last_publish_trans)); - /*update body*/ - if (expires == 0) { - belle_sip_message_set_body(BELLE_SIP_MESSAGE(last_publish), NULL, 0); - } else { - belle_sip_message_set_body_handler(BELLE_SIP_MESSAGE(last_publish), BELLE_SIP_BODY_HANDLER(body_handler)); - } - return belle_sip_refresher_refresh(op->refresher,expires==-1 ? BELLE_SIP_REFRESHER_REUSE_EXPIRES : expires); - } -} - -int sal_op_unpublish(SalOp *op){ - if (op->refresher){ - const belle_sip_transaction_t *tr=(const belle_sip_transaction_t*) belle_sip_refresher_get_transaction(op->refresher); - belle_sip_request_t *last_req=belle_sip_transaction_get_request(tr); - belle_sip_message_set_body(BELLE_SIP_MESSAGE(last_req), NULL, 0); - belle_sip_refresher_refresh(op->refresher,0); - return 0; - } - return -1; -} diff --git a/coreapi/call_log.c b/coreapi/call_log.c index c1f24ea10..abed37602 100644 --- a/coreapi/call_log.c +++ b/coreapi/call_log.c @@ -114,7 +114,7 @@ void call_logs_write_to_config_file(LinphoneCore *lc){ } } -bctbx_list_t * call_logs_read_from_config_file(LinphoneCore *lc){ +bctbx_list_t * linphone_core_read_call_logs_from_config_file(LinphoneCore *lc){ char logsection[32]; int i; const char *tmp; diff --git a/coreapi/callbacks.c b/coreapi/callbacks.c index e52a3199e..8a70e1718 100644 --- a/coreapi/callbacks.c +++ b/coreapi/callbacks.c @@ -19,6 +19,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "sal/sal.h" +#include "sal/call_op.h" +#include "sal/message_op.h" #include "linphone/core.h" #include "private.h" @@ -40,6 +42,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "conference/session/media-session.h" #include "conference/session/media-session-p.h" +using namespace LINPHONE_NAMESPACE; + static void register_failure(SalOp *op); static bool_t already_a_call_with_remote_address(const LinphoneCore *lc, const LinphoneAddress *remote) { @@ -58,7 +62,7 @@ static bool_t already_a_call_with_remote_address(const LinphoneCore *lc, const L } -static LinphoneCall * look_for_broken_call_to_replace(SalOp *h, LinphoneCore *lc) { +static LinphoneCall * look_for_broken_call_to_replace(LINPHONE_NAMESPACE::SalOp *h, LinphoneCore *lc) { const bctbx_list_t *calls = linphone_core_get_calls(lc); const bctbx_list_t *it = calls; while (it != NULL) { @@ -78,9 +82,9 @@ static LinphoneCall * look_for_broken_call_to_replace(SalOp *h, LinphoneCore *lc return NULL; } -static void call_received(SalOp *h) { +static void call_received(SalCallOp *h) { /* Look if this INVITE is for a call that has already been notified but broken because of network failure */ - LinphoneCore *lc = reinterpret_cast(sal_get_user_pointer(sal_op_get_sal(h))); + LinphoneCore *lc = reinterpret_cast(h->get_sal()->get_user_pointer()); LinphoneCall *replacedCall = look_for_broken_call_to_replace(h, lc); if (replacedCall) { linphone_call_replace_op(replacedCall, h); @@ -88,13 +92,13 @@ static void call_received(SalOp *h) { } LinphoneAddress *fromAddr = nullptr; - const char *pAssertedId = sal_custom_header_find(sal_op_get_recv_custom_header(h), "P-Asserted-Identity"); + const char *pAssertedId = sal_custom_header_find(h->get_recv_custom_header(), "P-Asserted-Identity"); /* In some situation, better to trust the network rather than the UAC */ if (lp_config_get_int(linphone_core_get_config(lc), "sip", "call_logs_use_asserted_id_instead_of_from", 0)) { if (pAssertedId) { LinphoneAddress *pAssertedIdAddr = linphone_address_new(pAssertedId); if (pAssertedIdAddr) { - ms_message("Using P-Asserted-Identity [%s] instead of from [%s] for op [%p]", pAssertedId, sal_op_get_from(h), h); + ms_message("Using P-Asserted-Identity [%s] instead of from [%s] for op [%p]", pAssertedId, h->get_from(), h); fromAddr = pAssertedIdAddr; } else ms_warning("Unsupported P-Asserted-Identity header for op [%p] ", h); @@ -103,8 +107,8 @@ static void call_received(SalOp *h) { } if (!fromAddr) - fromAddr = linphone_address_new(sal_op_get_from(h)); - LinphoneAddress *toAddr = linphone_address_new(sal_op_get_to(h)); + fromAddr = linphone_address_new(h->get_from()); + LinphoneAddress *toAddr = linphone_address_new(h->get_to()); /* First check if we can answer successfully to this invite */ LinphonePresenceActivity *activity = nullptr; @@ -118,12 +122,12 @@ static void call_received(SalOp *h) { SalErrorInfo sei; memset(&sei, 0, sizeof(sei)); sal_error_info_set(&sei, SalReasonRedirect, "SIP", 0, nullptr, nullptr); - sal_call_decline_with_error_info(h, &sei, altContact); + h->decline_with_error_info(&sei, altContact); ms_free(altContact); LinphoneErrorInfo *ei = linphone_error_info_new(); linphone_error_info_set(ei, nullptr, LinphoneReasonMovedPermanently, 302, "Moved permanently", nullptr); linphone_core_report_early_failed_call(lc, LinphoneCallIncoming, fromAddr, toAddr, ei); - sal_op_release(h); + h->release(); sal_error_info_reset(&sei); return; } @@ -135,17 +139,17 @@ static void call_received(SalOp *h) { } if (!linphone_core_can_we_add_call(lc)) { /* Busy */ - sal_call_decline(h, SalReasonBusy, nullptr); + h->decline(SalReasonBusy, nullptr); LinphoneErrorInfo *ei = linphone_error_info_new(); linphone_error_info_set(ei, nullptr, LinphoneReasonBusy, 486, "Busy - too many calls", nullptr); linphone_core_report_early_failed_call(lc, LinphoneCallIncoming, fromAddr, toAddr, ei); - sal_op_release(h); + h->release(); return; } /* Check if I'm the caller */ LinphoneAddress *fromAddressToSearchIfMe = nullptr; - if (sal_op_get_privacy(h) == SalPrivacyNone) + if (h->get_privacy() == SalPrivacyNone) fromAddressToSearchIfMe = linphone_address_clone(fromAddr); else if (pAssertedId) fromAddressToSearchIfMe = linphone_address_new(pAssertedId); @@ -154,11 +158,11 @@ static void call_received(SalOp *h) { if (fromAddressToSearchIfMe && already_a_call_with_remote_address(lc, fromAddressToSearchIfMe)) { char *addr = linphone_address_as_string(fromAddr); ms_warning("Receiving a call while one with same address [%s] is initiated, refusing this one with busy message", addr); - sal_call_decline(h, SalReasonBusy, nullptr); + h->decline(SalReasonBusy, nullptr); LinphoneErrorInfo *ei = linphone_error_info_new(); linphone_error_info_set(ei, nullptr, LinphoneReasonBusy, 486, "Busy - duplicated call", nullptr); linphone_core_report_early_failed_call(lc, LinphoneCallIncoming, fromAddr, toAddr, ei); - sal_op_release(h); + h->release(); linphone_address_unref(fromAddressToSearchIfMe); ms_free(addr); return; @@ -172,11 +176,11 @@ static void call_received(SalOp *h) { L_GET_PRIVATE_FROM_C_OBJECT(call)->startIncomingNotification(); } -static void call_rejected(SalOp *h){ - LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(h)); +static void call_rejected(SalCallOp *h){ + LinphoneCore *lc=(LinphoneCore *)h->get_sal()->get_user_pointer(); LinphoneErrorInfo *ei = linphone_error_info_new(); linphone_error_info_from_sal_op(ei, h); - linphone_core_report_early_failed_call(lc, LinphoneCallIncoming, linphone_address_new(sal_op_get_from(h)), linphone_address_new(sal_op_get_to(h)), ei); + linphone_core_report_early_failed_call(lc, LinphoneCallIncoming, linphone_address_new(h->get_from()), linphone_address_new(h->get_to()), ei); } #if 0 @@ -195,7 +199,7 @@ static void start_remote_ring(LinphoneCore *lc, LinphoneCall *call) { #endif static void call_ringing(SalOp *h) { - LinphonePrivate::CallSession *session = reinterpret_cast(sal_op_get_user_pointer(h)); + LinphonePrivate::CallSession *session = reinterpret_cast(h->get_user_pointer()); if (!session) return; L_GET_PRIVATE(session)->remoteRinging(); } @@ -212,7 +216,7 @@ static void start_pending_refer(LinphoneCall *call){ * - when a request is accepted (pause, resume) */ static void call_accepted(SalOp *op) { - LinphonePrivate::CallSession *session = reinterpret_cast(sal_op_get_user_pointer(op)); + LinphonePrivate::CallSession *session = reinterpret_cast(op->get_user_pointer()); if (!session) { ms_warning("call_accepted: CallSession no longer exists"); return; @@ -222,7 +226,7 @@ static void call_accepted(SalOp *op) { /* this callback is called when an incoming re-INVITE/ SIP UPDATE modifies the session*/ static void call_updating(SalOp *op, bool_t is_update) { - LinphonePrivate::CallSession *session = reinterpret_cast(sal_op_get_user_pointer(op)); + LinphonePrivate::CallSession *session = reinterpret_cast(op->get_user_pointer()); if (!session) { ms_warning("call_updating: CallSession no longer exists"); return; @@ -232,7 +236,7 @@ static void call_updating(SalOp *op, bool_t is_update) { static void call_ack_received(SalOp *op, SalCustomHeader *ack) { - LinphonePrivate::CallSession *session = reinterpret_cast(sal_op_get_user_pointer(op)); + LinphonePrivate::CallSession *session = reinterpret_cast(op->get_user_pointer()); if (!session) { ms_warning("call_ack_received(): no CallSession for which an ack is expected"); return; @@ -242,7 +246,7 @@ static void call_ack_received(SalOp *op, SalCustomHeader *ack) { static void call_ack_being_sent(SalOp *op, SalCustomHeader *ack) { - LinphonePrivate::CallSession *session = reinterpret_cast(sal_op_get_user_pointer(op)); + LinphonePrivate::CallSession *session = reinterpret_cast(op->get_user_pointer()); if (!session) { ms_warning("call_ack_being_sent(): no CallSession for which an ack is supposed to be sent"); return; @@ -251,7 +255,7 @@ static void call_ack_being_sent(SalOp *op, SalCustomHeader *ack) { } static void call_terminated(SalOp *op, const char *from) { - LinphonePrivate::CallSession *session = reinterpret_cast(sal_op_get_user_pointer(op)); + LinphonePrivate::CallSession *session = reinterpret_cast(op->get_user_pointer()); if (!session) return; L_GET_PRIVATE(session)->terminated(); @@ -276,7 +280,7 @@ static int resume_call_after_failed_transfer(LinphoneCall *call){ #endif static void call_failure(SalOp *op) { - LinphonePrivate::CallSession *session = reinterpret_cast(sal_op_get_user_pointer(op)); + LinphonePrivate::CallSession *session = reinterpret_cast(op->get_user_pointer()); if (!session) { ms_warning("Failure reported on already terminated CallSession"); return; @@ -285,7 +289,7 @@ static void call_failure(SalOp *op) { } static void call_released(SalOp *op) { - LinphonePrivate::CallSession *session = reinterpret_cast(sal_op_get_user_pointer(op)); + LinphonePrivate::CallSession *session = reinterpret_cast(op->get_user_pointer()); if (!session) { /* We can get here when the core manages call at Sal level without creating a Call object. Typicially, * when declining an incoming call with busy because maximum number of calls is reached. */ @@ -305,7 +309,7 @@ static void call_cancel_done(SalOp *op) { } static void auth_failure(SalOp *op, SalAuthInfo* info) { - LinphoneCore *lc = (LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op)); + LinphoneCore *lc = reinterpret_cast(op->get_sal()->get_user_pointer()); LinphoneAuthInfo *ai = NULL; if (info != NULL) { @@ -324,7 +328,7 @@ static void auth_failure(SalOp *op, SalAuthInfo* info) { } static void register_success(SalOp *op, bool_t registered){ - LinphoneProxyConfig *cfg=(LinphoneProxyConfig*)sal_op_get_user_pointer(op); + LinphoneProxyConfig *cfg=(LinphoneProxyConfig *)op->get_user_pointer(); if (!cfg){ ms_message("Registration success for deleted proxy config, ignored"); return; @@ -334,8 +338,8 @@ static void register_success(SalOp *op, bool_t registered){ } static void register_failure(SalOp *op){ - LinphoneProxyConfig *cfg=(LinphoneProxyConfig*)sal_op_get_user_pointer(op); - const SalErrorInfo *ei=sal_op_get_error_info(op); + LinphoneProxyConfig *cfg=(LinphoneProxyConfig*)op->get_user_pointer(); + const SalErrorInfo *ei=op->get_error_info(); const char *details=ei->full_string; if (cfg==NULL){ @@ -360,7 +364,7 @@ static void register_failure(SalOp *op){ } static void vfu_request(SalOp *op) { - LinphonePrivate::CallSession *session = reinterpret_cast(sal_op_get_user_pointer(op)); + LinphonePrivate::CallSession *session = reinterpret_cast(op->get_user_pointer()); if (!session) return; LinphonePrivate::MediaSession *mediaSession = dynamic_cast(session); @@ -406,14 +410,15 @@ static void refer_received(Sal *sal, SalOp *op, const char *referto){ } static void message_received(SalOp *op, const SalMessage *msg){ - LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op)); - LinphoneCall *call=(LinphoneCall*)sal_op_get_user_pointer(op); + LinphoneCore *lc=(LinphoneCore *)op->get_sal()->get_user_pointer(); + LinphoneCall *call=(LinphoneCall*)op->get_user_pointer(); LinphoneReason reason = lc->chat_deny_code; if (reason == LinphoneReasonNone) { linphone_core_message_received(lc, op, msg); } - sal_message_reply(op, linphone_reason_to_sal(reason)); - if (!call) sal_op_release(op); + auto messageOp = dynamic_cast(op); + messageOp->reply(linphone_reason_to_sal(reason)); + if (!call) op->release(); } static void parse_presence_requested(SalOp *op, const char *content_type, const char *content_subtype, const char *body, SalPresenceModel **result) { @@ -432,22 +437,22 @@ static void convert_presence_to_xml_requested(SalOp *op, SalPresenceModel *prese } static void notify_presence(SalOp *op, SalSubscribeStatus ss, SalPresenceModel *model, const char *msg){ - LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op)); + LinphoneCore *lc=(LinphoneCore *)op->get_sal()->get_user_pointer(); linphone_notify_recv(lc,op,ss,model); } -static void subscribe_presence_received(SalOp *op, const char *from){ - LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op)); +static void subscribe_presence_received(SalPresenceOp *op, const char *from){ + LinphoneCore *lc=(LinphoneCore *)op->get_sal()->get_user_pointer(); linphone_subscription_new(lc,op,from); } -static void subscribe_presence_closed(SalOp *op, const char *from){ - LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op)); +static void subscribe_presence_closed(SalPresenceOp *op, const char *from){ + LinphoneCore *lc=(LinphoneCore *)op->get_sal()->get_user_pointer(); linphone_subscription_closed(lc,op); } static void ping_reply(SalOp *op) { - LinphonePrivate::CallSession *session = reinterpret_cast(sal_op_get_user_pointer(op)); + LinphonePrivate::CallSession *session = reinterpret_cast(op->get_user_pointer()); if (!session) { ms_warning("Ping reply without CallSession attached..."); return; @@ -519,7 +524,7 @@ static bool_t fill_auth_info(LinphoneCore *lc, SalAuthInfo* sai) { } } static bool_t auth_requested(Sal* sal, SalAuthInfo* sai) { - LinphoneCore *lc = (LinphoneCore *)sal_get_user_pointer(sal); + LinphoneCore *lc = (LinphoneCore *)sal->get_user_pointer(); if (fill_auth_info(lc,sai)) { return TRUE; } else { @@ -537,7 +542,7 @@ static bool_t auth_requested(Sal* sal, SalAuthInfo* sai) { } static void notify_refer(SalOp *op, SalReferStatus status){ - LinphoneCall *call=(LinphoneCall*) sal_op_get_user_pointer(op); + LinphoneCall *call=(LinphoneCall*) op->get_user_pointer(); LinphoneCallState cstate; if (call==NULL) { ms_warning("Receiving notify_refer for unknown call."); @@ -576,7 +581,7 @@ static LinphoneChatMessageState chatStatusSal2Linphone(SalMessageDeliveryStatus } static void message_delivery_update(SalOp *op, SalMessageDeliveryStatus status){ - LinphoneChatMessage *chat_msg=(LinphoneChatMessage* )sal_op_get_user_pointer(op); + LinphoneChatMessage *chat_msg=(LinphoneChatMessage* )op->get_user_pointer(); if (chat_msg == NULL) { // Do not handle delivery status for isComposing messages. @@ -592,12 +597,12 @@ static void message_delivery_update(SalOp *op, SalMessageDeliveryStatus status){ } static void info_received(SalOp *op, SalBodyHandler *body_handler){ - LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op)); + LinphoneCore *lc=(LinphoneCore *)op->get_sal()->get_user_pointer(); linphone_core_notify_info_message(lc,op,body_handler); } static void subscribe_response(SalOp *op, SalSubscribeStatus status, int will_retry){ - LinphoneEvent *lev=(LinphoneEvent*)sal_op_get_user_pointer(op); + LinphoneEvent *lev=(LinphoneEvent*)op->get_user_pointer(); if (lev==NULL) return; @@ -613,9 +618,9 @@ static void subscribe_response(SalOp *op, SalSubscribeStatus status, int will_re } } -static void notify(SalOp *op, SalSubscribeStatus st, const char *eventname, SalBodyHandler *body_handler){ - LinphoneEvent *lev=(LinphoneEvent*)sal_op_get_user_pointer(op); - LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op)); +static void notify(SalSubscribeOp *op, SalSubscribeStatus st, const char *eventname, SalBodyHandler *body_handler){ + LinphoneEvent *lev=(LinphoneEvent*)op->get_user_pointer(); + LinphoneCore *lc=(LinphoneCore *)op->get_sal()->get_user_pointer(); bool_t out_of_dialog = (lev==NULL); if (out_of_dialog) { /*out of dialog notify */ @@ -636,9 +641,9 @@ static void notify(SalOp *op, SalSubscribeStatus st, const char *eventname, SalB } } -static void subscribe_received(SalOp *op, const char *eventname, const SalBodyHandler *body_handler){ - LinphoneEvent *lev=(LinphoneEvent*)sal_op_get_user_pointer(op); - LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op)); +static void subscribe_received(SalSubscribeOp *op, const char *eventname, const SalBodyHandler *body_handler){ + LinphoneEvent *lev=(LinphoneEvent*)op->get_user_pointer(); + LinphoneCore *lc=(LinphoneCore *)op->get_sal()->get_user_pointer(); if (lev==NULL) { lev=linphone_event_new_with_op(lc,op,LinphoneSubscriptionIncoming,eventname); @@ -650,14 +655,14 @@ static void subscribe_received(SalOp *op, const char *eventname, const SalBodyHa } static void incoming_subscribe_closed(SalOp *op){ - LinphoneEvent *lev=(LinphoneEvent*)sal_op_get_user_pointer(op); + LinphoneEvent *lev=(LinphoneEvent*)op->get_user_pointer(); linphone_event_set_state(lev,LinphoneSubscriptionTerminated); } static void on_publish_response(SalOp* op){ - LinphoneEvent *lev=(LinphoneEvent*)sal_op_get_user_pointer(op); - const SalErrorInfo *ei=sal_op_get_error_info(op); + LinphoneEvent *lev=(LinphoneEvent*)op->get_user_pointer(); + const SalErrorInfo *ei=op->get_error_info(); if (lev==NULL) return; if (ei->reason==SalReasonNone){ @@ -676,7 +681,7 @@ static void on_publish_response(SalOp* op){ static void on_expire(SalOp *op){ - LinphoneEvent *lev=(LinphoneEvent*)sal_op_get_user_pointer(op); + LinphoneEvent *lev=(LinphoneEvent*)op->get_user_pointer(); if (lev==NULL) return; @@ -688,14 +693,14 @@ static void on_expire(SalOp *op){ } static void on_notify_response(SalOp *op){ - LinphoneEvent *lev=(LinphoneEvent*)sal_op_get_user_pointer(op); + LinphoneEvent *lev=(LinphoneEvent*)op->get_user_pointer(); if (lev==NULL) return; /*this is actually handling out of dialogs notify - for the moment*/ if (!lev->is_out_of_dialog_op) return; switch (linphone_event_get_subscription_state(lev)){ case LinphoneSubscriptionIncomingReceived: - if (sal_op_get_error_info(op)->reason == SalReasonNone){ + if (op->get_error_info()->reason == SalReasonNone){ linphone_event_set_state(lev, LinphoneSubscriptionTerminated); }else{ linphone_event_set_state(lev, LinphoneSubscriptionError); @@ -706,7 +711,7 @@ static void on_notify_response(SalOp *op){ } } -SalCallbacks linphone_sal_callbacks={ +Sal::Callbacks linphone_sal_callbacks={ call_received, call_rejected, call_ringing, diff --git a/coreapi/carddav.c b/coreapi/carddav.c index 75dc7afd5..f874b325e 100644 --- a/coreapi/carddav.c +++ b/coreapi/carddav.c @@ -20,6 +20,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "linphone/core.h" #include "private.h" +using namespace LINPHONE_NAMESPACE; + LinphoneCardDavContext* linphone_carddav_context_new(LinphoneFriendList *lfl) { LinphoneCardDavContext *carddav_context = NULL; @@ -573,7 +575,7 @@ static char* generate_url_from_server_address_and_uid(const char *server_url) { char *result = NULL; if (server_url) { char *uuid = reinterpret_cast(ms_malloc(64)); - if (sal_generate_uuid(uuid, 64) == 0) { + if (Sal::generate_uuid(uuid, 64) == 0) { char *url = reinterpret_cast(ms_malloc(300)); snprintf(url, 300, "%s/linphone-%s.vcf", server_url, uuid); ms_debug("Generated url is %s", url); diff --git a/coreapi/chat.c b/coreapi/chat.c index a458facac..3797ce69a 100644 --- a/coreapi/chat.c +++ b/coreapi/chat.c @@ -43,6 +43,7 @@ #include "content/content-type.h" using namespace std; +using namespace LINPHONE_NAMESPACE; void linphone_core_disable_chat(LinphoneCore *lc, LinphoneReason deny_reason) { lc->chat_deny_code = deny_reason; diff --git a/coreapi/conference.cc b/coreapi/conference.cc index 0acc08e8d..eb88aa5a1 100644 --- a/coreapi/conference.cc +++ b/coreapi/conference.cc @@ -795,7 +795,7 @@ int RemoteConference::removeParticipant(const LinphoneAddress *uri) { linphone_address_set_method_param(refer_to_addr, "BYE"); refer_to = linphone_address_as_string(refer_to_addr); linphone_address_unref(refer_to_addr); - res = sal_call_refer(linphone_call_get_op(m_focusCall), refer_to); + res = linphone_call_get_op(m_focusCall)->refer(refer_to); ms_free(refer_to); if(res == 0) { diff --git a/coreapi/error_info.c b/coreapi/error_info.c index b70f96837..cbbaab7b0 100644 --- a/coreapi/error_info.c +++ b/coreapi/error_info.c @@ -197,16 +197,16 @@ void linphone_error_info_from_sal_reason_ei(LinphoneErrorInfo *ei, const SalErro } } -void linphone_error_info_from_sal_op(LinphoneErrorInfo *ei, const SalOp *op){ +void linphone_error_info_from_sal_op(LinphoneErrorInfo *ei, const LINPHONE_NAMESPACE::SalOp *op){ if (op==NULL) { /*leave previous values in LinphoneErrorInfo, the op may have been released already.*/ return; }else{ const SalErrorInfo *sei; linphone_error_info_reset(ei); - sei = sal_op_get_error_info(op); + sei = op->get_error_info(); linphone_error_info_from_sal(ei, sei); - sei = sal_op_get_reason_error_info(op); + sei = op->get_reason_error_info(); linphone_error_info_from_sal_reason_ei(ei, sei); } } diff --git a/coreapi/event.c b/coreapi/event.c index 100fa2e5c..1f7ebe2c5 100644 --- a/coreapi/event.c +++ b/coreapi/event.c @@ -19,9 +19,12 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "linphone/event.h" #include "linphone/lpconfig.h" +#include "sal/event_op.h" #include "c-wrapper/c-wrapper.h" +using namespace LINPHONE_NAMESPACE; + const char * linphone_subscription_dir_to_string(LinphoneSubscriptionDir dir){ switch(dir){ case LinphoneSubscriptionIncoming: @@ -73,12 +76,12 @@ LINPHONE_PUBLIC const char *linphone_publish_state_to_string(LinphonePublishStat static void linphone_event_release(LinphoneEvent *lev){ if (lev->op) { /*this will stop the refresher*/ - sal_op_stop_refreshing(lev->op); + lev->op->stop_refreshing(); } linphone_event_unref(lev); } -static LinphoneEvent * linphone_event_new_base(LinphoneCore *lc, LinphoneSubscriptionDir dir, const char *name, SalOp *op){ +static LinphoneEvent * linphone_event_new_base(LinphoneCore *lc, LinphoneSubscriptionDir dir, const char *name, LINPHONE_NAMESPACE::SalEventOp *op){ LinphoneEvent *lev=belle_sip_object_new(LinphoneEvent); lev->lc=lc; lev->dir=dir; @@ -86,27 +89,27 @@ static LinphoneEvent * linphone_event_new_base(LinphoneCore *lc, LinphoneSubscri lev->name=ms_strdup(name); if (strcmp(lev->name, "conference") == 0) lev->internal = TRUE; - sal_op_set_user_pointer(lev->op,lev); + lev->op->set_user_pointer(lev); return lev; } LinphoneEvent *linphone_event_new(LinphoneCore *lc, LinphoneSubscriptionDir dir, const char *name, int expires){ - LinphoneEvent *lev=linphone_event_new_base(lc, dir, name, sal_op_new(lc->sal)); + LinphoneEvent *lev=linphone_event_new_base(lc, dir, name, new SalSubscribeOp(lc->sal)); lev->expires=expires; return lev; } -static LinphoneEvent *linphone_event_new_with_op_base(LinphoneCore *lc, SalOp *op, LinphoneSubscriptionDir dir, const char *name, bool_t is_out_of_dialog){ +static LinphoneEvent *linphone_event_new_with_op_base(LinphoneCore *lc, SalEventOp *op, LinphoneSubscriptionDir dir, const char *name, bool_t is_out_of_dialog){ LinphoneEvent *lev=linphone_event_new_base(lc, dir, name, op); lev->is_out_of_dialog_op=is_out_of_dialog; return lev; } -LinphoneEvent *linphone_event_new_with_op(LinphoneCore *lc, SalOp *op, LinphoneSubscriptionDir dir, const char *name) { +LinphoneEvent *linphone_event_new_with_op(LinphoneCore *lc, SalEventOp *op, LinphoneSubscriptionDir dir, const char *name) { return linphone_event_new_with_op_base(lc,op,dir,name,FALSE); } -LinphoneEvent *linphone_event_new_with_out_of_dialog_op(LinphoneCore *lc, SalOp *op, LinphoneSubscriptionDir dir, const char *name) { +LinphoneEvent *linphone_event_new_with_out_of_dialog_op(LinphoneCore *lc, SalEventOp *op, LinphoneSubscriptionDir dir, const char *name) { return linphone_event_new_with_op_base(lc,op,dir,name,TRUE); } @@ -174,7 +177,7 @@ LinphoneReason linphone_event_get_reason(const LinphoneEvent *lev){ LinphoneEvent *linphone_core_create_subscribe(LinphoneCore *lc, const LinphoneAddress *resource, const char *event, int expires){ LinphoneEvent *lev=linphone_event_new(lc, LinphoneSubscriptionOutgoing, event, expires); linphone_configure_op(lc,lev->op,resource,NULL,TRUE); - sal_op_set_manual_refresher_mode(lev->op,!lp_config_get_int(lc->config,"sip","refresh_generic_subscribe",1)); + lev->op->set_manual_refresher_mode(!lp_config_get_int(lc->config,"sip","refresh_generic_subscribe",1)); return lev; } @@ -182,7 +185,7 @@ LinphoneEvent *linphone_core_create_notify(LinphoneCore *lc, const LinphoneAddre LinphoneEvent *lev=linphone_event_new(lc, LinphoneSubscriptionIncoming, event, -1); linphone_configure_op(lc,lev->op,resource,NULL,TRUE); lev->subscription_state = LinphoneSubscriptionIncomingReceived; - sal_op_set_event(lev->op, event); + lev->op->set_event(event); lev->is_out_of_dialog_op = TRUE; return lev; } @@ -218,13 +221,14 @@ LinphoneStatus linphone_event_send_subscribe(LinphoneEvent *lev, const LinphoneC } if (lev->send_custom_headers){ - sal_op_set_sent_custom_header(lev->op,lev->send_custom_headers); + lev->op->set_sent_custom_header(lev->send_custom_headers); sal_custom_header_free(lev->send_custom_headers); lev->send_custom_headers=NULL; - }else sal_op_set_sent_custom_header(lev->op,NULL); + }else lev->op->set_sent_custom_header(NULL); body_handler = sal_body_handler_from_content(body); - err=sal_subscribe(lev->op,NULL,NULL,lev->name,lev->expires,body_handler); + auto subscribeOp = dynamic_cast(lev->op); + err=subscribeOp->subscribe(NULL,NULL,lev->name,lev->expires,body_handler); if (err==0){ if (lev->subscription_state==LinphoneSubscriptionNone) linphone_event_set_state(lev,LinphoneSubscriptionOutgoingProgress); @@ -237,7 +241,7 @@ LinphoneStatus linphone_event_update_subscribe(LinphoneEvent *lev, const Linphon } LinphoneStatus linphone_event_refresh_subscribe(LinphoneEvent *lev) { - return sal_op_refresh(lev->op); + return lev->op->refresh(); } LinphoneStatus linphone_event_accept_subscription(LinphoneEvent *lev){ @@ -246,7 +250,8 @@ LinphoneStatus linphone_event_accept_subscription(LinphoneEvent *lev){ ms_error("linphone_event_accept_subscription(): cannot accept subscription if subscription wasn't just received."); return -1; } - err=sal_subscribe_accept(lev->op); + auto subscribeOp = dynamic_cast(lev->op); + err=subscribeOp->accept(); if (err==0){ linphone_event_set_state(lev,LinphoneSubscriptionActive); } @@ -259,7 +264,8 @@ LinphoneStatus linphone_event_deny_subscription(LinphoneEvent *lev, LinphoneReas ms_error("linphone_event_deny_subscription(): cannot deny subscription if subscription wasn't just received."); return -1; } - err=sal_subscribe_decline(lev->op,linphone_reason_to_sal(reason)); + auto subscribeOp = dynamic_cast(lev->op); + err=subscribeOp->decline(linphone_reason_to_sal(reason)); linphone_event_set_state(lev,LinphoneSubscriptionTerminated); return err; } @@ -275,7 +281,8 @@ LinphoneStatus linphone_event_notify(LinphoneEvent *lev, const LinphoneContent * return -1; } body_handler = sal_body_handler_from_content(body); - return sal_notify(lev->op, body_handler); + auto subscribeOp = dynamic_cast(lev->op); + return subscribeOp->notify(body_handler); } static LinphoneEvent *_linphone_core_create_publish(LinphoneCore *core, LinphoneProxyConfig *cfg, const LinphoneAddress *resource, const char *event, int expires){ @@ -295,7 +302,7 @@ static LinphoneEvent *_linphone_core_create_publish(LinphoneCore *core, Linphone 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)); + lev->op->set_manual_refresher_mode(!lp_config_get_int(lc->config,"sip","refresh_generic_publish",1)); return lev; } LinphoneEvent *linphone_core_create_publish(LinphoneCore *lc, const LinphoneAddress *resource, const char *event, int expires){ @@ -322,12 +329,13 @@ static int _linphone_event_send_publish(LinphoneEvent *lev, const LinphoneConten return -1; } if (lev->send_custom_headers){ - sal_op_set_sent_custom_header(lev->op,lev->send_custom_headers); + lev->op->set_sent_custom_header(lev->send_custom_headers); sal_custom_header_free(lev->send_custom_headers); lev->send_custom_headers=NULL; - }else sal_op_set_sent_custom_header(lev->op,NULL); + }else lev->op->set_sent_custom_header(NULL); body_handler = sal_body_handler_from_content(body); - err=sal_publish(lev->op,NULL,NULL,lev->name,lev->expires,body_handler); + auto publishOp = dynamic_cast(lev->op); + err=publishOp->publish(NULL,NULL,lev->name,lev->expires,body_handler); if (err==0){ linphone_event_set_publish_state(lev,LinphonePublishProgress); }else if (notify_err){ @@ -357,14 +365,17 @@ LinphoneStatus linphone_event_update_publish(LinphoneEvent* lev, const LinphoneC } LinphoneStatus linphone_event_refresh_publish(LinphoneEvent *lev) { - return sal_op_refresh(lev->op); + return lev->op->refresh(); } void linphone_event_pause_publish(LinphoneEvent *lev) { - if (lev->op) sal_op_stop_refreshing(lev->op); + if (lev->op) lev->op->stop_refreshing(); } void linphone_event_unpublish(LinphoneEvent *lev) { lev->terminating = TRUE; /* needed to get clear event*/ - if (lev->op) sal_op_unpublish(lev->op); + if (lev->op) { + auto op = dynamic_cast(lev->op); + op->unpublish(); + } } void linphone_event_set_user_data(LinphoneEvent *ev, void *up){ ev->userdata=up; @@ -379,7 +390,7 @@ void linphone_event_add_custom_header(LinphoneEvent *ev, const char *name, const } const char* linphone_event_get_custom_header(LinphoneEvent* ev, const char* name){ - const SalCustomHeader *ch=sal_op_get_recv_custom_header(ev->op); + const SalCustomHeader *ch=ev->op->get_recv_custom_header(); return sal_custom_header_find(ch,name); } @@ -395,16 +406,18 @@ void linphone_event_terminate(LinphoneEvent *lev){ } lev->terminating=TRUE; - if (lev->dir==LinphoneSubscriptionIncoming){ - sal_notify_close(lev->op); + auto op = dynamic_cast(lev->op); + op->close_notify(); }else if (lev->dir==LinphoneSubscriptionOutgoing){ - sal_unsubscribe(lev->op); + auto op = dynamic_cast(lev->op); + op->unsubscribe(); } if (lev->publish_state!=LinphonePublishNone){ if (lev->publish_state==LinphonePublishOk && lev->expires!=-1){ - sal_op_unpublish(lev->op); + auto op = dynamic_cast(lev->op); + op->unpublish(); } linphone_event_set_publish_state(lev,LinphonePublishCleared); return; @@ -424,7 +437,7 @@ LinphoneEvent *linphone_event_ref(LinphoneEvent *lev){ 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->op) lev->op->release(); 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); @@ -451,7 +464,7 @@ const char *linphone_event_get_name(const LinphoneEvent *lev){ 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)); + char *buf = sal_address_as_string(lev->op->get_to_address()); ((LinphoneEvent *)lev)->to_address = linphone_address_new(buf); ms_free(buf); return lev->to_address; @@ -460,7 +473,7 @@ static const LinphoneAddress *_linphone_event_cache_to (const LinphoneEvent *lev 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)); + char *buf = sal_address_as_string(lev->op->get_from_address()); ((LinphoneEvent *)lev)->from_address = linphone_address_new(buf); ms_free(buf); return lev->from_address; diff --git a/coreapi/friend.c b/coreapi/friend.c index 45f640072..20e7a1f8e 100644 --- a/coreapi/friend.c +++ b/coreapi/friend.c @@ -42,6 +42,9 @@ #include "c-wrapper/c-wrapper.h" +using namespace std; +using namespace LINPHONE_NAMESPACE; + const char *linphone_online_status_to_string(LinphoneOnlineStatus ss){ const char *str=NULL; switch(ss){ @@ -185,12 +188,12 @@ void __linphone_friend_do_subscribe(LinphoneFriend *fr){ fr->lc->vtable.notify_recv(fr->lc,(LinphoneFriend*)fr); */ }else{ - sal_op_release(fr->outsub); + fr->outsub->release(); fr->outsub=NULL; } - fr->outsub=sal_op_new(lc->sal); + fr->outsub=new SalPresenceOp(lc->sal); linphone_configure_op(lc,fr->outsub,addr,NULL,TRUE); - sal_subscribe_presence(fr->outsub,NULL,NULL,lp_config_get_int(lc->config,"sip","subscribe_expires",600)); + fr->outsub->subscribe(NULL,NULL,lp_config_get_int(lc->config,"sip","subscribe_expires",600)); fr->subscribe_active=TRUE; } } @@ -468,8 +471,8 @@ void linphone_friend_notify(LinphoneFriend *lf, LinphonePresenceModel *presence) } } for(elem=lf->insubs; elem!=NULL; elem=bctbx_list_next(elem)){ - SalOp *op = (SalOp*)bctbx_list_get_data(elem); - sal_notify_presence(op,(SalPresenceModel *)presence); + auto op = reinterpret_cast(bctbx_list_get_data(elem)); + op->notify_presence((SalPresenceModel *)presence); } } @@ -480,14 +483,14 @@ void linphone_friend_add_incoming_subscription(LinphoneFriend *lf, SalOp *op){ void linphone_friend_remove_incoming_subscription(LinphoneFriend *lf, SalOp *op){ if (bctbx_list_find(lf->insubs, op)){ - sal_op_release(op); + op->release(); lf->insubs = bctbx_list_remove(lf->insubs, op); } } static void linphone_friend_unsubscribe(LinphoneFriend *lf){ if (lf->outsub!=NULL) { - sal_unsubscribe(lf->outsub); + lf->outsub->unsubscribe(); } /* for friend list there is no necessary outsub*/ lf->subscribe_active=FALSE; @@ -498,7 +501,7 @@ void linphone_friend_invalidate_subscription(LinphoneFriend *lf){ LinphoneCore *lc=lf->lc; if (lf->outsub!=NULL) { - sal_op_release(lf->outsub); + lf->outsub->release(); lf->outsub=NULL; } @@ -521,9 +524,17 @@ void linphone_friend_invalidate_subscription(LinphoneFriend *lf){ lf->initial_subscribes_sent=FALSE; } +static void close_presence_notification(SalPresenceOp *op) { + op->notify_presence_close(); +} + +static void release_sal_op(SalOp *op) { + op->release(); +} + static void linphone_friend_close_incoming_subscriptions(LinphoneFriend *lf) { - bctbx_list_for_each(lf->insubs, (MSIterateFunc) sal_notify_presence_close); - lf->insubs = bctbx_list_free_with_data(lf->insubs, (MSIterateFunc)sal_op_release); + bctbx_list_for_each(lf->insubs, (MSIterateFunc) close_presence_notification); + lf->insubs = bctbx_list_free_with_data(lf->insubs, (MSIterateFunc)release_sal_op); } void linphone_friend_close_subscriptions(LinphoneFriend *lf){ @@ -532,9 +543,9 @@ void linphone_friend_close_subscriptions(LinphoneFriend *lf){ } static void _linphone_friend_release_ops(LinphoneFriend *lf){ - lf->insubs = bctbx_list_free_with_data(lf->insubs, (MSIterateFunc) sal_op_release); + lf->insubs = bctbx_list_free_with_data(lf->insubs, (MSIterateFunc) release_sal_op); if (lf->outsub){ - sal_op_release(lf->outsub); + lf->outsub->release(); lf->outsub=NULL; } } @@ -756,7 +767,7 @@ void linphone_friend_update_subscribes(LinphoneFriend *fr, bool_t only_when_regi linphone_friend_unsubscribe(fr); }else if (!can_subscribe && fr->outsub){ fr->subscribe_active=FALSE; - sal_op_stop_refreshing(fr->outsub); + fr->outsub->stop_refreshing(); } } diff --git a/coreapi/friendlist.c b/coreapi/friendlist.c index a03536994..113ca9ff4 100644 --- a/coreapi/friendlist.c +++ b/coreapi/friendlist.c @@ -23,6 +23,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "c-wrapper/c-wrapper.h" +using namespace LINPHONE_NAMESPACE; + BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(LinphoneFriendListCbs); BELLE_SIP_INSTANCIATE_VPTR(LinphoneFriendListCbs, belle_sip_object_t, @@ -807,7 +809,7 @@ LinphoneFriend * linphone_friend_list_find_friend_by_out_subscribe(const Linphon const bctbx_list_t *elem; for (elem = list->friends; elem != NULL; elem = bctbx_list_next(elem)) { LinphoneFriend *lf = (LinphoneFriend *)bctbx_list_get_data(elem); - if (lf->outsub && ((lf->outsub == op) || sal_op_is_forked_of(lf->outsub, op))) return lf; + if (lf->outsub && ((lf->outsub == op) || lf->outsub->is_forked_of(op))) return lf; } return NULL; } diff --git a/coreapi/info.c b/coreapi/info.c index ad37a9a30..d4bd92623 100644 --- a/coreapi/info.c +++ b/coreapi/info.c @@ -28,6 +28,8 @@ #include "c-wrapper/c-wrapper.h" +using namespace LINPHONE_NAMESPACE; + struct _LinphoneInfoMessage{ belle_sip_object_t base; LinphoneContent *content; @@ -97,10 +99,10 @@ SalCustomHeader *linphone_info_message_get_headers (const LinphoneInfoMessage *i } void linphone_core_notify_info_message(LinphoneCore* lc,SalOp *op, SalBodyHandler *body_handler){ - LinphoneCall *call=(LinphoneCall*)sal_op_get_user_pointer(op); + LinphoneCall *call=(LinphoneCall*)op->get_user_pointer(); if (call){ LinphoneInfoMessage *info=linphone_core_create_info_message(lc); - info->headers=sal_custom_header_clone(sal_op_get_recv_custom_header(op)); + info->headers=sal_custom_header_clone(op->get_recv_custom_header()); if (body_handler) info->content=linphone_content_from_sal_body_handler(body_handler); linphone_call_notify_info_message_received(call, info); linphone_info_message_unref(info); diff --git a/coreapi/linphonecall.c b/coreapi/linphonecall.c index 6afea2b22..9962d373a 100644 --- a/coreapi/linphonecall.c +++ b/coreapi/linphonecall.c @@ -125,4 +125,4 @@ void set_playback_gain_db(AudioStream *st, float gain){ if (st->volrecv){ ms_filter_call_method(st->volrecv,MS_VOLUME_SET_DB_GAIN,&gain); }else ms_warning("Could not apply playback gain: gain control wasn't activated."); -} \ No newline at end of file +} diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index f80b56b43..069ec68fd 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -130,6 +130,9 @@ void linphone_core_zrtp_cache_db_init(LinphoneCore *lc, const char *fileName); #include "contact_providers_priv.h" +using namespace LINPHONE_NAMESPACE; + + const char *linphone_core_get_nat_address_resolved(LinphoneCore *lc); static void toggle_video_preview(LinphoneCore *lc, bool_t val); @@ -143,7 +146,7 @@ static void toggle_video_preview(LinphoneCore *lc, bool_t val); #define HOLD_MUSIC_WAV "toy-mono.wav" #define HOLD_MUSIC_MKV "dont_wait_too_long.mkv" -extern SalCallbacks linphone_sal_callbacks; +extern Sal::Callbacks linphone_sal_callbacks; static void _linphone_core_cbs_uninit(LinphoneCoreCbs *cbs); @@ -1286,11 +1289,11 @@ static void sip_config_read(LinphoneCore *lc) { int ipv6_default = TRUE; if (lp_config_get_int(lc->config,"sip","use_session_timers",0)==1){ - sal_use_session_timers(lc->sal,200); + lc->sal->use_session_timers(200); } - sal_use_no_initial_route(lc->sal, !!lp_config_get_int(lc->config,"sip","use_no_initial_route",0)); - sal_use_rport(lc->sal, !!lp_config_get_int(lc->config,"sip","use_rport",1)); + lc->sal->use_no_initial_route(!!lp_config_get_int(lc->config,"sip","use_no_initial_route",0)); + lc->sal->use_rport(!!lp_config_get_int(lc->config,"sip","use_rport",1)); if (!lp_config_get_int(lc->config,"sip","ipv6_migration_done",FALSE) && lp_config_has_entry(lc->config,"sip","use_ipv6")) { lp_config_clean_entry(lc->config,"sip","use_ipv6"); @@ -1309,7 +1312,7 @@ static void sip_config_read(LinphoneCore *lc) { certificates_config_read(lc); /*setting the dscp must be done before starting the transports, otherwise it is not taken into effect*/ - sal_set_dscp(lc->sal,linphone_core_get_sip_dscp(lc)); + lc->sal->set_dscp(linphone_core_get_sip_dscp(lc)); /*start listening on ports*/ linphone_core_set_sip_transports(lc,&tr); @@ -1385,12 +1388,12 @@ static void sip_config_read(LinphoneCore *lc) { lc->sip_conf.keepalive_period = (unsigned int)lp_config_get_int(lc->config,"sip","keepalive_period",10000); lc->sip_conf.tcp_tls_keepalive = !!lp_config_get_int(lc->config,"sip","tcp_tls_keepalive",0); linphone_core_enable_keep_alive(lc, (lc->sip_conf.keepalive_period > 0)); - sal_use_one_matching_codec_policy(lc->sal, !!lp_config_get_int(lc->config,"sip","only_one_codec",0)); - sal_use_dates(lc->sal, !!lp_config_get_int(lc->config,"sip","put_date",0)); - sal_enable_sip_update_method(lc->sal, !!lp_config_get_int(lc->config,"sip","sip_update",1)); + lc->sal->use_one_matching_codec_policy(!!lp_config_get_int(lc->config,"sip","only_one_codec",0)); + lc->sal->use_dates(!!lp_config_get_int(lc->config,"sip","put_date",0)); + lc->sal->enable_sip_update_method(!!lp_config_get_int(lc->config,"sip","sip_update",1)); lc->sip_conf.vfu_with_info = !!lp_config_get_int(lc->config,"sip","vfu_with_info",1); linphone_core_set_sip_transport_timeout(lc, lp_config_get_int(lc->config, "sip", "transport_timeout", 63000)); - sal_set_supported_tags(lc->sal,lp_config_get_string(lc->config,"sip","supported","replaces, outbound, gruu")); + lc->sal->set_supported_tags(lp_config_get_string(lc->config,"sip","supported","replaces, outbound, gruu")); lc->sip_conf.save_auth_info = !!lp_config_get_int(lc->config, "sip", "save_auth_info", 1); linphone_core_create_im_notif_policy(lc); } @@ -1769,7 +1772,7 @@ static void ui_config_read(LinphoneCore *lc) read_friends_from_rc(lc); } if (!lc->logs_db) { - lc->call_logs = call_logs_read_from_config_file(lc); + lc->call_logs = linphone_core_read_call_logs_from_config_file(lc); } #endif } @@ -1842,37 +1845,37 @@ void linphone_core_set_expected_bandwidth(LinphoneCore *lc, int bw){ } void linphone_core_set_sip_transport_timeout(LinphoneCore *lc, int timeout_ms) { - sal_set_transport_timeout(lc->sal, timeout_ms); + lc->sal->set_transport_timeout(timeout_ms); if (linphone_core_ready(lc)) lp_config_set_int(lc->config, "sip", "transport_timeout", timeout_ms); } int linphone_core_get_sip_transport_timeout(LinphoneCore *lc) { - return sal_get_transport_timeout(lc->sal); + return lc->sal->get_transport_timeout(); } void linphone_core_set_dns_servers(LinphoneCore *lc, const bctbx_list_t *servers){ - sal_set_dns_servers(lc->sal, servers); + lc->sal->set_dns_servers(servers); } void linphone_core_enable_dns_srv(LinphoneCore *lc, bool_t enable) { - sal_enable_dns_srv(lc->sal, enable); + lc->sal->enable_dns_srv(enable); if (linphone_core_ready(lc)) lp_config_set_int(lc->config, "net", "dns_srv_enabled", enable ? 1 : 0); } bool_t linphone_core_dns_srv_enabled(const LinphoneCore *lc) { - return sal_dns_srv_enabled(lc->sal); + return lc->sal->dns_srv_enabled(); } void linphone_core_enable_dns_search(LinphoneCore *lc, bool_t enable) { - sal_enable_dns_search(lc->sal, enable); + lc->sal->enable_dns_search(enable); if (linphone_core_ready(lc)) lp_config_set_int(lc->config, "net", "dns_search_enabled", enable ? 1 : 0); } bool_t linphone_core_dns_search_enabled(const LinphoneCore *lc) { - return sal_dns_search_enabled(lc->sal); + return lc->sal->dns_search_enabled(); } int linphone_core_get_download_bandwidth(const LinphoneCore *lc){ @@ -1958,10 +1961,10 @@ static void misc_config_read(LinphoneCore *lc) { uuid=lp_config_get_string(config,"misc","uuid",NULL); if (!uuid){ char tmp[64]; - sal_create_uuid(lc->sal,tmp,sizeof(tmp)); + lc->sal->create_uuid(tmp,sizeof(tmp)); lp_config_set_string(config,"misc","uuid",tmp); }else if (strcmp(uuid,"0")!=0) /*to allow to disable sip.instance*/ - sal_set_uuid(lc->sal, uuid); + lc->sal->set_uuid(uuid); lc->user_certificates_path=ms_strdup(lp_config_get_string(config,"misc","user_certificates_path",".")); lc->send_call_stats_periodical_updates = !!lp_config_get_int(config, "misc", "send_call_stats_periodical_updates", 0); @@ -2211,12 +2214,12 @@ static void linphone_core_init(LinphoneCore * lc, LinphoneCoreCbs *cbs, LpConfig /* This allows to run event's callback in linphone_core_iterate() */ lc->msevq=ms_factory_create_event_queue(lc->factory); - lc->sal=sal_init(lc->factory); - sal_set_http_proxy_host(lc->sal, linphone_core_get_http_proxy_host(lc)); - sal_set_http_proxy_port(lc->sal, linphone_core_get_http_proxy_port(lc)); + lc->sal=new Sal(lc->factory); + lc->sal->set_http_proxy_host(linphone_core_get_http_proxy_host(lc)); + lc->sal->set_http_proxy_port(linphone_core_get_http_proxy_port(lc)); - sal_set_user_pointer(lc->sal,lc); - sal_set_callbacks(lc->sal,&linphone_sal_callbacks); + lc->sal->set_user_pointer(lc); + lc->sal->set_callbacks(&linphone_sal_callbacks); #ifdef TUNNEL_ENABLED lc->tunnel=linphone_core_tunnel_new(lc); @@ -2228,7 +2231,7 @@ static void linphone_core_init(LinphoneCore * lc, LinphoneCoreCbs *cbs, LpConfig /* Create the http provider in dual stack mode (ipv4 and ipv6. * If this creates problem, we may need to implement parallel ipv6/ ipv4 http requests in belle-sip. */ - lc->http_provider = belle_sip_stack_create_http_provider(reinterpret_cast(sal_get_stack_impl(lc->sal)), "::0"); + lc->http_provider = belle_sip_stack_create_http_provider(reinterpret_cast(lc->sal->get_stack_impl()), "::0"); lc->http_crypto_config = belle_tls_crypto_config_new(); belle_http_provider_set_tls_crypto_config(lc->http_provider,lc->http_crypto_config); @@ -2733,12 +2736,12 @@ void linphone_core_set_user_agent(LinphoneCore *lc, const char *name, const char char ua_string[256]; snprintf(ua_string, sizeof(ua_string) - 1, "%s/%s", name?name:"", ver?ver:""); if (lc->sal) { - sal_set_user_agent(lc->sal, ua_string); - sal_append_stack_string_to_user_agent(lc->sal); + lc->sal->set_user_agent(ua_string); + lc->sal->append_stack_string_to_user_agent(); } } const char *linphone_core_get_user_agent(LinphoneCore *lc){ - return sal_get_user_agent(lc->sal); + return lc->sal->get_user_agent(); } const char *linphone_core_get_user_agent_name(void){ @@ -2781,32 +2784,32 @@ int _linphone_core_apply_transports(LinphoneCore *lc){ else anyaddr="0.0.0.0"; - sal_unlisten_ports(sal); + sal->unlisten_ports(); listening_address = lp_config_get_string(lc->config,"sip","bind_address",anyaddr); if (linphone_core_get_http_proxy_host(lc)) { - sal_set_http_proxy_host(sal, linphone_core_get_http_proxy_host(lc)); - sal_set_http_proxy_port(sal,linphone_core_get_http_proxy_port(lc)); + sal->set_http_proxy_host(linphone_core_get_http_proxy_host(lc)); + sal->set_http_proxy_port(linphone_core_get_http_proxy_port(lc)); } if (lc->tunnel && linphone_tunnel_sip_enabled(lc->tunnel) && linphone_tunnel_get_activated(lc->tunnel)){ - sal_listen_port(sal,anyaddr,tr->udp_port,SalTransportUDP,TRUE); + sal->set_listen_port(anyaddr,tr->udp_port,SalTransportUDP,TRUE); }else{ if (tr->udp_port!=0){ - sal_listen_port(sal,listening_address,tr->udp_port,SalTransportUDP,FALSE); + sal->set_listen_port(listening_address,tr->udp_port,SalTransportUDP,FALSE); } if (tr->tcp_port!=0){ - sal_listen_port (sal,listening_address,tr->tcp_port,SalTransportTCP,FALSE); + sal->set_listen_port (listening_address,tr->tcp_port,SalTransportTCP,FALSE); } if (linphone_core_sip_transport_supported(lc,LinphoneTransportTls)){ if (tr->tls_port!=0) - sal_listen_port (sal,listening_address,tr->tls_port,SalTransportTLS,FALSE); + sal->set_listen_port (listening_address,tr->tls_port,SalTransportTLS,FALSE); } } return 0; } bool_t linphone_core_sip_transport_supported(const LinphoneCore *lc, LinphoneTransportType tp){ - return !!sal_transport_available(lc->sal,(SalTransport)tp); + return !!lc->sal->transport_available((SalTransport)tp); } BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(LinphoneTransports); @@ -2946,17 +2949,17 @@ LinphoneTransports *linphone_core_get_transports(LinphoneCore *lc){ } void linphone_core_get_sip_transports_used(LinphoneCore *lc, LinphoneSipTransports *tr){ - tr->udp_port=sal_get_listening_port(lc->sal,SalTransportUDP); - tr->tcp_port=sal_get_listening_port(lc->sal,SalTransportTCP); - tr->tls_port=sal_get_listening_port(lc->sal,SalTransportTLS); + tr->udp_port=lc->sal->get_listening_port(SalTransportUDP); + tr->tcp_port=lc->sal->get_listening_port(SalTransportTCP); + tr->tls_port=lc->sal->get_listening_port(SalTransportTLS); } LinphoneTransports *linphone_core_get_transports_used(LinphoneCore *lc){ LinphoneTransports *transports = linphone_transports_new(); - transports->udp_port = sal_get_listening_port(lc->sal, SalTransportUDP); - transports->tcp_port = sal_get_listening_port(lc->sal, SalTransportTCP); - transports->tls_port = sal_get_listening_port(lc->sal, SalTransportTLS); - transports->dtls_port = sal_get_listening_port(lc->sal, SalTransportDTLS); + transports->udp_port = lc->sal->get_listening_port(SalTransportUDP); + transports->tcp_port = lc->sal->get_listening_port(SalTransportTCP); + transports->tls_port = lc->sal->get_listening_port(SalTransportTLS); + transports->dtls_port = lc->sal->get_listening_port(SalTransportDTLS); return transports; } @@ -2988,7 +2991,7 @@ void linphone_core_enable_ipv6(LinphoneCore *lc, bool_t val){ bool_t linphone_core_content_encoding_supported(const LinphoneCore *lc, const char *content_encoding) { const char *handle_content_encoding = lp_config_get_string(lc->config, "sip", "handle_content_encoding", "deflate"); - return (strcmp(handle_content_encoding, content_encoding) == 0) && sal_content_encoding_available(lc->sal, content_encoding); + return (strcmp(handle_content_encoding, content_encoding) == 0) && lc->sal->content_encoding_available(content_encoding); } static void monitor_network_state(LinphoneCore *lc, time_t curtime){ @@ -3122,8 +3125,8 @@ void linphone_core_iterate(LinphoneCore *lc){ } } if (linphone_core_get_global_state(lc) == LinphoneGlobalStartup) { - if (sal_get_root_ca(lc->sal)) { - belle_tls_crypto_config_set_root_ca(lc->http_crypto_config, sal_get_root_ca(lc->sal)); + if (lc->sal->get_root_ca()) { + belle_tls_crypto_config_set_root_ca(lc->http_crypto_config, lc->sal->get_root_ca()); belle_http_provider_set_tls_crypto_config(lc->http_provider, lc->http_crypto_config); } @@ -3190,7 +3193,7 @@ void linphone_core_iterate(LinphoneCore *lc){ } } - sal_iterate(lc->sal); + lc->sal->iterate(); if (lc->msevq) ms_event_queue_pump(lc->msevq); if (lc->auto_net_state_mon) monitor_network_state(lc, current_real_time); @@ -3438,7 +3441,7 @@ static void linphone_transfer_routes_to_op(bctbx_list_t *routes, SalOp *op){ bctbx_list_t *it; for(it=routes;it!=NULL;it=it->next){ SalAddress *addr=(SalAddress*)it->data; - sal_op_add_route_address(op,addr); + op->add_route_address(addr); sal_address_destroy(addr); } bctbx_list_free(routes); @@ -3450,7 +3453,7 @@ void linphone_configure_op_with_proxy(LinphoneCore *lc, SalOp *op, const Linphon if (proxy){ identity=linphone_proxy_config_get_identity(proxy); if (linphone_proxy_config_get_privacy(proxy)!=LinphonePrivacyDefault) { - sal_op_set_privacy(op,linphone_proxy_config_get_privacy(proxy)); + op->set_privacy(linphone_proxy_config_get_privacy(proxy)); } }else identity=linphone_core_get_primary_contact(lc); /*sending out of calls*/ @@ -3459,19 +3462,19 @@ void linphone_configure_op_with_proxy(LinphoneCore *lc, SalOp *op, const Linphon linphone_transfer_routes_to_op(routes,op); } char *addr = linphone_address_as_string(dest); - sal_op_set_to(op,addr); + op->set_to(addr); ms_free(addr); - 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)); + op->set_from(identity); + op->set_sent_custom_header(headers); + op->set_realm(linphone_proxy_config_get_realm(proxy)); if (with_contact && proxy && proxy->op){ const LinphoneAddress *contact = linphone_proxy_config_get_contact(proxy); SalAddress *salAddress = nullptr; if (contact) salAddress = sal_address_clone(const_cast(L_GET_PRIVATE_FROM_C_OBJECT(contact)->getInternalAddress())); - sal_op_set_contact_address(op, salAddress); + op->set_contact_address(salAddress); } - sal_op_cnx_ip_to_0000_if_sendonly_enable(op, !!lp_config_get_default_int(lc->config,"sip","cnx_ip_to_0000_if_sendonly_enabled",0)); /*also set in linphone_call_new_incoming*/ + op->enable_cnx_ip_to_0000_if_sendonly(!!lp_config_get_default_int(lc->config,"sip","cnx_ip_to_0000_if_sendonly_enabled",0)); /*also set in linphone_call_new_incoming*/ } void linphone_configure_op(LinphoneCore *lc, SalOp *op, const LinphoneAddress *dest, SalCustomHeader *headers, bool_t with_contact) { linphone_configure_op_with_proxy(lc, op, dest, headers,with_contact,linphone_core_lookup_known_proxy(lc,dest)); @@ -4216,7 +4219,7 @@ const char *linphone_core_get_ring(const LinphoneCore *lc){ } void linphone_core_set_root_ca(LinphoneCore *lc, const char *path) { - sal_set_root_ca(lc->sal, path); + lc->sal->set_root_ca(path); if (lc->http_crypto_config) { belle_tls_crypto_config_set_root_ca(lc->http_crypto_config, path); } @@ -4224,8 +4227,8 @@ void linphone_core_set_root_ca(LinphoneCore *lc, const char *path) { } void linphone_core_set_root_ca_data(LinphoneCore *lc, const char *data) { - sal_set_root_ca(lc->sal, NULL); - sal_set_root_ca_data(lc->sal, data); + lc->sal->set_root_ca(NULL); + lc->sal->set_root_ca_data(data); if (lc->http_crypto_config) { belle_tls_crypto_config_set_root_ca_data(lc->http_crypto_config, data); } @@ -4236,7 +4239,7 @@ const char *linphone_core_get_root_ca(LinphoneCore *lc){ } void linphone_core_verify_server_certificates(LinphoneCore *lc, bool_t yesno){ - sal_verify_server_certificates(lc->sal,yesno); + lc->sal->verify_server_certificates(yesno); if (lc->http_crypto_config){ belle_tls_crypto_config_set_verify_exceptions(lc->http_crypto_config, yesno ? 0 : BELLE_TLS_VERIFY_ANY_REASON); } @@ -4244,7 +4247,7 @@ void linphone_core_verify_server_certificates(LinphoneCore *lc, bool_t yesno){ } void linphone_core_verify_server_cn(LinphoneCore *lc, bool_t yesno){ - sal_verify_server_cn(lc->sal,yesno); + lc->sal->verify_server_cn(yesno); if (lc->http_crypto_config){ belle_tls_crypto_config_set_verify_exceptions(lc->http_crypto_config, yesno ? 0 : BELLE_TLS_VERIFY_CN_MISMATCH); } @@ -4252,7 +4255,7 @@ void linphone_core_verify_server_cn(LinphoneCore *lc, bool_t yesno){ } void linphone_core_set_ssl_config(LinphoneCore *lc, void *ssl_config) { - sal_set_ssl_config(lc->sal, ssl_config); + lc->sal->set_ssl_config(ssl_config); if (lc->http_crypto_config) { belle_tls_crypto_config_set_ssl_config(lc->http_crypto_config, ssl_config); } @@ -4549,9 +4552,9 @@ void linphone_core_set_nat_policy(LinphoneCore *lc, LinphoneNatPolicy *policy) { linphone_nat_policy_save_to_config(lc->nat_policy); } - sal_nat_helper_enable(lc->sal, !!lp_config_get_int(lc->config, "net", "enable_nat_helper", 1)); - sal_enable_auto_contacts(lc->sal, TRUE); - sal_use_rport(lc->sal, !!lp_config_get_int(lc->config, "sip", "use_rport", 1)); + lc->sal->enable_nat_helper(!!lp_config_get_int(lc->config, "net", "enable_nat_helper", 1)); + lc->sal->enable_auto_contacts(TRUE); + lc->sal->use_rport(!!lp_config_get_int(lc->config, "sip", "use_rport", 1)); if (lc->sip_conf.contact) update_primary_contact(lc); } @@ -4653,7 +4656,7 @@ void linphone_core_migrate_logs_from_rc_to_db(LinphoneCore *lc) { return; } - logs_to_migrate = call_logs_read_from_config_file(lc); + logs_to_migrate = linphone_core_read_call_logs_from_config_file(lc); if (!logs_to_migrate) { ms_warning("nothing to migrate, skipping..."); return; @@ -5730,7 +5733,7 @@ void sip_config_uninit(LinphoneCore *lc) for (i=0;i<20&&still_registered;i++){ still_registered=FALSE; - sal_iterate(lc->sal); + lc->sal->iterate(); for(elem=config->proxies;elem!=NULL;elem=bctbx_list_next(elem)){ LinphoneProxyConfig *cfg=(LinphoneProxyConfig*)(elem->data); LinphoneRegistrationState state = linphone_proxy_config_get_state(cfg); @@ -5754,8 +5757,8 @@ void sip_config_uninit(LinphoneCore *lc) linphone_vcard_context_destroy(lc->vcard_context); } - sal_reset_transports(lc->sal); - sal_unlisten_ports(lc->sal); /*to make sure no new messages are received*/ + lc->sal->reset_transports(); + lc->sal->unlisten_ports(); /*to make sure no new messages are received*/ if (lc->http_provider) { belle_sip_object_unref(lc->http_provider); lc->http_provider=NULL; @@ -5774,8 +5777,8 @@ void sip_config_uninit(LinphoneCore *lc) } #endif - sal_iterate(lc->sal); /*make sure event are purged*/ - sal_uninit(lc->sal); + lc->sal->iterate(); /*make sure event are purged*/ + delete lc->sal; lc->sal=NULL; if (lc->sip_conf.guessed_contact) @@ -6054,7 +6057,7 @@ static void set_sip_network_reachable(LinphoneCore* lc,bool_t is_sip_reachable, if (!lc->sip_network_reachable){ linphone_core_invalidate_friend_subscriptions(lc); - sal_reset_transports(lc->sal); + lc->sal->reset_transports(); /*mark all calls as broken, so that they can be either dropped immediately or restaured when network will be back*/ bctbx_list_for_each(lc->calls, (MSIterateFunc) linphone_call_set_broken); } @@ -6133,7 +6136,7 @@ bool_t linphone_core_is_network_reachable(LinphoneCore* lc) { } ortp_socket_t linphone_core_get_sip_socket(LinphoneCore *lc){ - return sal_get_socket(lc->sal); + return lc->sal->get_socket(); } void linphone_core_destroy(LinphoneCore *lc){ @@ -6320,15 +6323,15 @@ const char *linphone_error_to_string(LinphoneReason err){ void linphone_core_enable_keep_alive(LinphoneCore* lc,bool_t enable) { if (enable > 0) { - sal_use_tcp_tls_keepalive(lc->sal,lc->sip_conf.tcp_tls_keepalive); - sal_set_keepalive_period(lc->sal,lc->sip_conf.keepalive_period); + lc->sal->use_tcp_tls_keepalive(lc->sip_conf.tcp_tls_keepalive); + lc->sal->set_keepalive_period(lc->sip_conf.keepalive_period); } else { - sal_set_keepalive_period(lc->sal,0); + lc->sal->set_keepalive_period(0); } } bool_t linphone_core_keep_alive_enabled(LinphoneCore* lc) { - return sal_get_keepalive_period(lc->sal) > 0; + return lc->sal->get_keepalive_period() > 0; } void linphone_core_start_dtmf_stream(LinphoneCore* lc) { @@ -6665,7 +6668,7 @@ const char* linphone_core_get_device_identifier(const LinphoneCore *lc) { } void linphone_core_set_sip_dscp(LinphoneCore *lc, int dscp){ - sal_set_dscp(lc->sal,dscp); + lc->sal->set_dscp(dscp); if (linphone_core_ready(lc)){ lp_config_set_int_hex(lc->config,"sip","dscp",dscp); _linphone_core_apply_transports(lc); @@ -6727,13 +6730,13 @@ const char * linphone_core_get_file_transfer_server(LinphoneCore *core) { } void linphone_core_add_supported_tag(LinphoneCore *lc, const char *tag){ - sal_add_supported_tag(lc->sal,tag); - lp_config_set_string(lc->config,"sip","supported",sal_get_supported_tags(lc->sal)); + lc->sal->add_supported_tag(tag); + lp_config_set_string(lc->config,"sip","supported",lc->sal->get_supported_tags()); } void linphone_core_remove_supported_tag(LinphoneCore *lc, const char *tag){ - sal_remove_supported_tag(lc->sal,tag); - lp_config_set_string(lc->config,"sip","supported",sal_get_supported_tags(lc->sal)); + lc->sal->remove_supported_tag(tag); + lp_config_set_string(lc->config,"sip","supported",lc->sal->get_supported_tags()); } void linphone_core_set_avpf_mode(LinphoneCore *lc, LinphoneAVPFMode mode){ @@ -6895,15 +6898,15 @@ void linphone_core_enable_realtime_text(LinphoneCore *lc, bool_t value) { void linphone_core_set_http_proxy_host(LinphoneCore *lc, const char *host) { lp_config_set_string(lc->config,"sip","http_proxy_host",host); if (lc->sal) { - sal_set_http_proxy_host(lc->sal,host); - sal_set_http_proxy_port(lc->sal,linphone_core_get_http_proxy_port(lc)); /*to make sure default value is set*/ + lc->sal->set_http_proxy_host(host); + lc->sal->set_http_proxy_port(linphone_core_get_http_proxy_port(lc)); /*to make sure default value is set*/ } } void linphone_core_set_http_proxy_port(LinphoneCore *lc, int port) { lp_config_set_int(lc->config,"sip","http_proxy_port",port); if (lc->sal) - sal_set_http_proxy_port(lc->sal,port); + lc->sal->set_http_proxy_port(port); } const char *linphone_core_get_http_proxy_host(const LinphoneCore *lc) { @@ -7132,19 +7135,19 @@ LinphoneImEncryptionEngine *linphone_core_get_im_encryption_engine(const Linphon } void linphone_core_initialize_supported_content_types(LinphoneCore *lc) { - sal_add_content_type_support(lc->sal, "text/plain"); - sal_add_content_type_support(lc->sal, "message/external-body"); - sal_add_content_type_support(lc->sal, "application/vnd.gsma.rcs-ft-http+xml"); - sal_add_content_type_support(lc->sal, "application/im-iscomposing+xml"); - sal_add_content_type_support(lc->sal, "message/imdn+xml"); + lc->sal->add_content_type_support("text/plain"); + lc->sal->add_content_type_support("message/external-body"); + lc->sal->add_content_type_support("application/vnd.gsma.rcs-ft-http+xml"); + lc->sal->add_content_type_support("application/im-iscomposing+xml"); + lc->sal->add_content_type_support("message/imdn+xml"); } bool_t linphone_core_is_content_type_supported(const LinphoneCore *lc, const char *content_type) { - return sal_is_content_type_supported(lc->sal, content_type); + return lc->sal->is_content_type_supported(content_type); } void linphone_core_add_content_type_support(LinphoneCore *lc, const char *content_type) { - sal_add_content_type_support(lc->sal, content_type); + lc->sal->add_content_type_support(content_type); } #ifdef ENABLE_UPDATE_CHECK diff --git a/coreapi/misc.c b/coreapi/misc.c index cf1bd497b..c14a8b4c8 100644 --- a/coreapi/misc.c +++ b/coreapi/misc.c @@ -508,7 +508,7 @@ const char * linphone_core_get_echo_canceller_filter_name(const LinphoneCore *lc * task_fun must return BELLE_SIP_STOP when job is finished. **/ void linphone_core_queue_task(LinphoneCore *lc, belle_sip_source_func_t task_fun, void *data, const char *task_description){ - belle_sip_source_t *s=sal_create_timer(lc->sal,task_fun,data, 20, task_description); + belle_sip_source_t *s=lc->sal->create_timer(task_fun,data, 20, task_description); belle_sip_object_unref(s); } diff --git a/coreapi/nat_policy.c b/coreapi/nat_policy.c index 4d96016df..86f676412 100644 --- a/coreapi/nat_policy.c +++ b/coreapi/nat_policy.c @@ -230,7 +230,7 @@ void linphone_nat_policy_resolve_stun_server(LinphoneNatPolicy *policy) { int family = AF_INET; if (linphone_core_ipv6_enabled(policy->lc) == TRUE) family = AF_INET6; ms_message("Starting stun server resolution [%s]", host); - policy->stun_resolver_context = sal_resolve(policy->lc->sal, service, "udp", host, port, family, stun_server_resolved, policy); + policy->stun_resolver_context = policy->lc->sal->resolve(service, "udp", host, port, family, stun_server_resolved, policy); if (policy->stun_resolver_context) belle_sip_object_ref(policy->stun_resolver_context); } } @@ -252,7 +252,7 @@ const struct addrinfo * linphone_nat_policy_get_stun_server_addrinfo(LinphoneNat int wait_limit = 1000; linphone_nat_policy_resolve_stun_server(policy); while ((policy->stun_addrinfo == NULL) && (policy->stun_resolver_context != NULL) && (wait_ms < wait_limit)) { - sal_iterate(policy->lc->sal); + policy->lc->sal->iterate(); ms_usleep(50000); wait_ms += 50; } diff --git a/coreapi/offeranswer.c b/coreapi/offeranswer.c index 2e657b9a5..a24e9b418 100644 --- a/coreapi/offeranswer.c +++ b/coreapi/offeranswer.c @@ -18,6 +18,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "sal/sal.h" +#include "sal/sal.hpp" #include "offeranswer.h" #include "private.h" diff --git a/coreapi/presence.c b/coreapi/presence.c index 0ffa56d5d..7546b756d 100644 --- a/coreapi/presence.c +++ b/coreapi/presence.c @@ -23,6 +23,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "c-wrapper/c-wrapper.h" +using namespace LINPHONE_NAMESPACE; + extern const char *__policy_enum_to_str(LinphoneSubscribePolicy pol); struct _LinphonePresenceNote { @@ -1540,7 +1542,7 @@ void linphone_core_notify_all_friends(LinphoneCore *lc, LinphonePresenceModel *p } } -void linphone_subscription_new(LinphoneCore *lc, SalOp *op, const char *from){ +void linphone_subscription_new(LinphoneCore *lc, SalSubscribeOp *op, const char *from){ LinphoneFriend *lf=NULL; char *tmp; LinphoneAddress *uri; @@ -1557,12 +1559,12 @@ void linphone_subscription_new(LinphoneCore *lc, SalOp *op, const char *from){ linphone_friend_add_incoming_subscription(lf, op); lf->inc_subscribe_pending=TRUE; if (lp_config_get_int(lc->config,"sip","notify_pending_state",0)) { - sal_notify_pending_state(op); + op->notify_pending_state(); } - sal_subscribe_accept(op); + op->accept(); } else { ms_message("%s is not authorized to subscribe", from); - sal_subscribe_decline(op, SalReasonDeclined); + op->decline(SalReasonDeclined); } linphone_friend_done(lf); /*this will do all necessary actions */ }else{ @@ -1570,14 +1572,14 @@ void linphone_subscription_new(LinphoneCore *lc, SalOp *op, const char *from){ if (linphone_find_friend_by_address(lc->subscribers,uri,&lf)){ if (lf->pol==LinphoneSPDeny){ ms_message("Rejecting %s because we already rejected it once.",from); - sal_subscribe_decline(op,SalReasonDeclined); + op->decline(SalReasonDeclined); } else { /* else it is in wait for approval state, because otherwise it is in the friend list.*/ ms_message("New subscriber found in subscriber list, in %s state.",__policy_enum_to_str(lf->pol)); } }else { - sal_subscribe_accept(op); + op->accept(); linphone_core_add_subscriber(lc,tmp,op); } } @@ -1930,7 +1932,7 @@ 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)); + char *buf = sal_address_as_string_uri_only(op->get_from_address()); LinphoneAddress *addr = linphone_address_new(buf); lf = linphone_core_find_friend(lc, addr); ms_free(buf); @@ -1959,27 +1961,27 @@ void linphone_notify_recv(LinphoneCore *lc, SalOp *op, SalSubscribeStatus ss, Sa linphone_core_notify_notify_presence_received(lc,(LinphoneFriend*)lf); if (op != lf->outsub){ /*case of a NOTIFY received out of any dialog*/ - sal_op_release(op); + op->release(); return; } }else{ ms_message("But this person is not part of our friend list, so we don't care."); linphone_presence_model_unref(presence); - sal_op_release(op); + op->release(); return ; } if (ss==SalSubscribeTerminated){ if (lf){ if (lf->outsub != op){ - sal_op_release(op); + op->release(); } if (lf->outsub){ - sal_op_release(lf->outsub); + lf->outsub->release(); lf->outsub=NULL; } lf->subscribe_active=FALSE; }else{ - sal_op_release(op); + op->release(); } } } @@ -1994,7 +1996,7 @@ void linphone_subscription_closed(LinphoneCore *lc, SalOp *op){ linphone_friend_remove_incoming_subscription(lf, op); }else{ /*case of an op that we already released because the friend was destroyed*/ - ms_message("Receiving unsuscribe for unknown in-subscribtion from %s", sal_op_get_from(op)); + ms_message("Receiving unsuscribe for unknown in-subscribtion from %s", op->get_from()); } } diff --git a/coreapi/private.h b/coreapi/private.h index 67e886c52..ce5b184a4 100644 --- a/coreapi/private.h +++ b/coreapi/private.h @@ -32,12 +32,19 @@ #include "linphone/core_utils.h" #include "linphone/conference.h" #include "sal/sal.h" +#include "sal/call_op.h" +#include "sal/event_op.h" +#include "sal/message_op.h" +#include "sal/presence_op.h" +#include "sal/register_op.h" #include "linphone/sipsetup.h" #include "quality_reporting.h" #include "linphone/ringtoneplayer.h" #include "vcard_private.h" #include "carddav.h" #include "linphone/player.h" +#include "account_creator_private.h" +#include "tester_utils.h" #include "bctoolbox/port.h" #include "bctoolbox/map.h" @@ -164,7 +171,7 @@ typedef struct _CallCallbackObj bool_t is_read; unsigned int storage_id; char *message_id; - SalOp *op; + MessageOp *op; LinphoneContent *file_transfer_information; //< used to store file transfer information when the message is of file transfer type char *content_type; //< is used to specified the type of message to be sent, used only for file transfer message bool_t to_be_stored; @@ -214,7 +221,7 @@ void linphone_call_notify_info_message_received(LinphoneCall *call, const Linpho void linphone_call_notify_ack_processing(LinphoneCall *call, LinphoneHeaders *msg, bool_t is_received); LinphoneCall * linphone_call_new_outgoing(struct _LinphoneCore *lc, const LinphoneAddress *from, const LinphoneAddress *to, const LinphoneCallParams *params, LinphoneProxyConfig *cfg); -LinphoneCall * linphone_call_new_incoming(struct _LinphoneCore *lc, const LinphoneAddress *from, const LinphoneAddress *to, SalOp *op); +LinphoneCall * linphone_call_new_incoming(struct _LinphoneCore *lc, const LinphoneAddress *from, const LinphoneAddress *to, LINPHONE_NAMESPACE::SalCallOp *op); void _linphone_call_set_new_params(LinphoneCall *call, const LinphoneCallParams *params); void linphone_call_set_state(LinphoneCall *call, LinphoneCallState cstate, const char *message); /* private: */ @@ -222,12 +229,12 @@ LinphoneCallLog * linphone_call_log_new(LinphoneCallDir dir, LinphoneAddress *fr void linphone_call_set_transfer_state(LinphoneCall* call, LinphoneCallState state); LinphonePlayer *linphone_call_build_player(LinphoneCall*call); void linphone_call_refresh_sockets(LinphoneCall *call); -void linphone_call_replace_op(LinphoneCall *call, SalOp *op); +void linphone_call_replace_op(LinphoneCall *call, LINPHONE_NAMESPACE::SalOp *op); void linphone_call_reinvite_to_recover_from_connection_loss(LinphoneCall *call); -SalOp * linphone_call_get_op(const LinphoneCall *call); +LINPHONE_NAMESPACE::SalCallOp *linphone_call_get_op(const LinphoneCall *call); LinphoneProxyConfig * linphone_call_get_dest_proxy(const LinphoneCall *call); -MediaStream * linphone_call_get_stream(LinphoneCall *call, LinphoneStreamType type); +LINPHONE_PUBLIC MediaStream * linphone_call_get_stream(LinphoneCall *call, LinphoneStreamType type); LinphoneCallLog * linphone_call_get_log(const LinphoneCall *call); IceSession * linphone_call_get_ice_session(const LinphoneCall *call); bool_t linphone_call_get_audio_muted(const LinphoneCall *call); @@ -311,15 +318,15 @@ void _linphone_friend_release(LinphoneFriend *lf); LINPHONE_PUBLIC void linphone_friend_update_subscribes(LinphoneFriend *fr, bool_t only_when_registered); void linphone_friend_notify(LinphoneFriend *lf, LinphonePresenceModel *presence); void linphone_friend_apply(LinphoneFriend *fr, LinphoneCore *lc); -void linphone_friend_add_incoming_subscription(LinphoneFriend *lf, SalOp *op); -void linphone_friend_remove_incoming_subscription(LinphoneFriend *lf, SalOp *op); +void linphone_friend_add_incoming_subscription(LinphoneFriend *lf, LINPHONE_NAMESPACE::SalOp *op); +void linphone_friend_remove_incoming_subscription(LinphoneFriend *lf, LINPHONE_NAMESPACE::SalOp *op); const char * linphone_friend_phone_number_to_sip_uri(LinphoneFriend *lf, const char *phone_number); const char * linphone_friend_sip_uri_to_phone_number(LinphoneFriend *lf, const char *uri); void linphone_friend_clear_presence_models(LinphoneFriend *lf); -LinphoneFriend *linphone_friend_list_find_friend_by_inc_subscribe(const LinphoneFriendList *list, SalOp *op); -LinphoneFriend *linphone_friend_list_find_friend_by_out_subscribe(const LinphoneFriendList *list, SalOp *op); -LinphoneFriend *linphone_core_find_friend_by_out_subscribe(const LinphoneCore *lc, SalOp *op); -LinphoneFriend *linphone_core_find_friend_by_inc_subscribe(const LinphoneCore *lc, SalOp *op); +LinphoneFriend *linphone_friend_list_find_friend_by_inc_subscribe(const LinphoneFriendList *list, LINPHONE_NAMESPACE::SalOp *op); +LinphoneFriend *linphone_friend_list_find_friend_by_out_subscribe(const LinphoneFriendList *list, LINPHONE_NAMESPACE::SalOp *op); +LinphoneFriend *linphone_core_find_friend_by_out_subscribe(const LinphoneCore *lc, LINPHONE_NAMESPACE::SalOp *op); +LinphoneFriend *linphone_core_find_friend_by_inc_subscribe(const LinphoneCore *lc, LINPHONE_NAMESPACE::SalOp *op); MSList *linphone_find_friend_by_address(MSList *fl, const LinphoneAddress *addr, LinphoneFriend **lf); bool_t linphone_core_should_subscribe_friends_only_when_registered(const LinphoneCore *lc); void linphone_core_update_friends_subscriptions(LinphoneCore *lc); @@ -354,19 +361,19 @@ static MS2_INLINE void set_string(char **dest, const char *src, bool_t lowercase } } -void linphone_process_authentication(LinphoneCore* lc, SalOp *op); -void linphone_authentication_ok(LinphoneCore *lc, SalOp *op); -void linphone_subscription_new(LinphoneCore *lc, SalOp *op, const char *from); +void linphone_process_authentication(LinphoneCore* lc, LINPHONE_NAMESPACE::SalOp *op); +void linphone_authentication_ok(LinphoneCore *lc, LINPHONE_NAMESPACE::SalOp *op); +void linphone_subscription_new(LinphoneCore *lc, LINPHONE_NAMESPACE::SalSubscribeOp *op, const char *from); void linphone_core_send_presence(LinphoneCore *lc, LinphonePresenceModel *presence); void linphone_notify_parse_presence(const char *content_type, const char *content_subtype, const char *body, SalPresenceModel **result); -void linphone_notify_convert_presence_to_xml(SalOp *op, SalPresenceModel *presence, const char *contact, char **content); -void linphone_notify_recv(LinphoneCore *lc, SalOp *op, SalSubscribeStatus ss, SalPresenceModel *model); -void linphone_proxy_config_process_authentication_failure(LinphoneCore *lc, SalOp *op); +void linphone_notify_convert_presence_to_xml(LINPHONE_NAMESPACE::SalOp *op, SalPresenceModel *presence, const char *contact, char **content); +void linphone_notify_recv(LinphoneCore *lc, LINPHONE_NAMESPACE::SalOp *op, SalSubscribeStatus ss, SalPresenceModel *model); +void linphone_proxy_config_process_authentication_failure(LinphoneCore *lc, LINPHONE_NAMESPACE::SalOp *op); void linphone_core_soundcard_hint_check(LinphoneCore* lc); -void linphone_subscription_answered(LinphoneCore *lc, SalOp *op); -void linphone_subscription_closed(LinphoneCore *lc, SalOp *op); +void linphone_subscription_answered(LinphoneCore *lc, LINPHONE_NAMESPACE::SalOp *op); +void linphone_subscription_closed(LinphoneCore *lc, LINPHONE_NAMESPACE::SalOp *op); void linphone_core_update_allocated_audio_bandwidth(LinphoneCore *lc); @@ -415,7 +422,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); +int linphone_core_message_received(LinphoneCore *lc, LINPHONE_NAMESPACE::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_media_streams(LinphoneCall *call); @@ -439,17 +446,12 @@ int linphone_call_start_update(LinphoneCall *call); int linphone_call_start_accept_update(LinphoneCall *call, LinphoneCallState next_state, const char *state_info); void linphone_core_notify_incoming_call(LinphoneCore *lc, LinphoneCall *call); bool_t linphone_core_incompatible_security(LinphoneCore *lc, SalMediaDescription *md); -extern SalCallbacks linphone_sal_callbacks; +extern LINPHONE_NAMESPACE::Sal::Callbacks linphone_sal_callbacks; LINPHONE_PUBLIC bool_t linphone_core_rtcp_enabled(const LinphoneCore *lc); LINPHONE_PUBLIC bool_t linphone_core_symmetric_rtp_enabled(LinphoneCore*lc); void linphone_core_queue_task(LinphoneCore *lc, belle_sip_source_func_t task_fun, void *data, const char *task_description); -typedef enum _LinphoneProxyConfigAddressComparisonResult{ - LinphoneProxyConfigAddressDifferent, - LinphoneProxyConfigAddressEqual, - LinphoneProxyConfigAddressWeakEqual -} LinphoneProxyConfigAddressComparisonResult; LINPHONE_PUBLIC LinphoneProxyConfigAddressComparisonResult linphone_proxy_config_address_equal(const LinphoneAddress *a, const LinphoneAddress *b); LINPHONE_PUBLIC LinphoneProxyConfigAddressComparisonResult linphone_proxy_config_is_server_config_changed(const LinphoneProxyConfig* obj); @@ -486,7 +488,7 @@ struct _LinphoneProxyConfig char *contact_uri_params; int expires; int publish_expires; - SalOp *op; + LINPHONE_NAMESPACE::SalRegisterOp *op; SalCustomHeader *sent_headers; char *type; struct _SipSetupContext *ssctx; @@ -565,7 +567,7 @@ struct _LinphoneFriend{ void *user_data; LinphoneAddress *uri; MSList *insubs; /*list of SalOp. There can be multiple instances of a same Friend that subscribe to our presence*/ - SalOp *outsub; + LINPHONE_NAMESPACE::SalPresenceOp *outsub; LinphoneSubscribePolicy pol; MSList *presence_models; /* list of LinphoneFriendPresence. It associates SIP URIs and phone numbers with their respective presence models. */ MSList *phone_number_sip_uri_map; /* list of LinphoneFriendPhoneNumberSipUri. It associates phone numbers with their corresponding SIP URIs. */ @@ -803,7 +805,7 @@ struct _LinphoneCore MSFactory* factory; MSList* vtable_refs; int vtable_notify_recursion; - Sal *sal; + LINPHONE_NAMESPACE::Sal *sal; LinphoneGlobalState state; struct _LpConfig *config; MSList *default_audio_codecs; @@ -939,7 +941,7 @@ struct _LinphoneEvent{ LinphoneErrorInfo *ei; LinphoneSubscriptionDir dir; LinphoneCore *lc; - SalOp *op; + LINPHONE_NAMESPACE::SalEventOp *op; SalCustomHeader *send_custom_headers; LinphoneSubscriptionState subscription_state; LinphonePublishState publish_state; @@ -1053,7 +1055,7 @@ void _linphone_core_codec_config_write(LinphoneCore *lc); #endif #endif -LINPHONE_PUBLIC bctbx_list_t * call_logs_read_from_config_file(LinphoneCore *lc); +LINPHONE_PUBLIC bctbx_list_t * linphone_core_read_call_logs_from_config_file(LinphoneCore *lc); void call_logs_write_to_config_file(LinphoneCore *lc); void linphone_core_call_log_storage_init(LinphoneCore *lc); void linphone_core_call_log_storage_close(LinphoneCore *lc); @@ -1097,8 +1099,8 @@ belle_http_request_t * linphone_chat_message_get_http_request(const LinphoneChat void linphone_chat_message_set_http_request(LinphoneChatMessage *msg, belle_http_request_t *request); void linphone_chat_message_set_file_transfer_information(LinphoneChatMessage *msg, LinphoneContent *content); LinphoneChatMessageDir linphone_chat_message_get_direction(const LinphoneChatMessage *msg); -SalOp * linphone_chat_message_get_sal_op(const LinphoneChatMessage *msg); -void linphone_chat_message_set_sal_op(LinphoneChatMessage *msg, SalOp *op); +LINPHONE_NAMESPACE::SalOp * linphone_chat_message_get_sal_op(const LinphoneChatMessage *msg); +void linphone_chat_message_set_sal_op(LinphoneChatMessage *msg, LINPHONE_NAMESPACE::SalOp *op); void linphone_chat_message_destroy(LinphoneChatMessage* msg); void linphone_chat_message_update_state(LinphoneChatMessage *msg, LinphoneChatMessageState new_state); void linphone_chat_message_set_is_secured(LinphoneChatMessage *msg, bool_t secured); @@ -1117,10 +1119,10 @@ void linphone_chat_message_send_imdn(LinphoneChatMessage *cm, ImdnType imdn_type void linphone_core_play_named_tone(LinphoneCore *lc, LinphoneToneID id); bool_t linphone_core_tone_indications_enabled(LinphoneCore*lc); const char *linphone_core_create_uuid(LinphoneCore *lc); -void linphone_configure_op(LinphoneCore *lc, SalOp *op, const LinphoneAddress *dest, SalCustomHeader *headers, bool_t with_contact); -void linphone_configure_op_with_proxy(LinphoneCore *lc, SalOp *op, const LinphoneAddress *dest, SalCustomHeader *headers, bool_t with_contact, LinphoneProxyConfig *proxy); +void linphone_configure_op(LinphoneCore *lc, LINPHONE_NAMESPACE::SalOp *op, const LinphoneAddress *dest, SalCustomHeader *headers, bool_t with_contact); +void linphone_configure_op_with_proxy(LinphoneCore *lc, LINPHONE_NAMESPACE::SalOp *op, const LinphoneAddress *dest, SalCustomHeader *headers, bool_t with_contact, LinphoneProxyConfig *proxy); void linphone_call_create_op(LinphoneCall *call); -void linphone_core_notify_info_message(LinphoneCore* lc,SalOp *op, SalBodyHandler *body); +void linphone_core_notify_info_message(LinphoneCore* lc,LINPHONE_NAMESPACE::SalOp *op, SalBodyHandler *body); LinphoneContent * linphone_content_new(void); LinphoneContent * linphone_content_copy(const LinphoneContent *ref); SalBodyHandler *sal_body_handler_from_content(const LinphoneContent *content); @@ -1128,12 +1130,12 @@ SalReason linphone_reason_to_sal(LinphoneReason reason); LinphoneReason linphone_reason_from_sal(SalReason reason); void linphone_error_info_to_sal(const LinphoneErrorInfo* ei, SalErrorInfo* sei); LinphoneEvent *linphone_event_new(LinphoneCore *lc, LinphoneSubscriptionDir dir, const char *name, int expires); -LinphoneEvent *linphone_event_new_with_op(LinphoneCore *lc, SalOp *op, LinphoneSubscriptionDir dir, const char *name); +LinphoneEvent *linphone_event_new_with_op(LinphoneCore *lc, LINPHONE_NAMESPACE::SalEventOp *op, LinphoneSubscriptionDir dir, const char *name); void linphone_event_unpublish(LinphoneEvent *lev); /** * Useful for out of dialog notify * */ -LinphoneEvent *linphone_event_new_with_out_of_dialog_op(LinphoneCore *lc, SalOp *op, LinphoneSubscriptionDir dir, const char *name); +LinphoneEvent *linphone_event_new_with_out_of_dialog_op(LinphoneCore *lc, LINPHONE_NAMESPACE::SalEventOp *op, LinphoneSubscriptionDir dir, const char *name); void linphone_event_set_internal(LinphoneEvent *lev, bool_t internal); bool_t linphone_event_is_internal(LinphoneEvent *lev); void linphone_event_set_state(LinphoneEvent *lev, LinphoneSubscriptionState state); @@ -1247,174 +1249,6 @@ struct _LinphoneXmlRpcSession { BELLE_SIP_DECLARE_VPTR_NO_EXPORT(LinphoneXmlRpcSession); -/***************************************************************************** - * Account creator interface * - ****************************************************************************/ - -struct _LinphoneAccountCreatorService { - belle_sip_object_t base; - void *user_data; - - LinphoneAccountCreatorRequestFunc account_creator_service_constructor_cb; /**< Constructor */ - LinphoneAccountCreatorRequestFunc account_creator_service_destructor_cb; /**< Destructor */ - - LinphoneAccountCreatorRequestFunc create_account_request_cb; /**< Request to create account */ - LinphoneAccountCreatorRequestFunc is_account_exist_request_cb; /**< Request to know if account exist */ - - LinphoneAccountCreatorRequestFunc activate_account_request_cb; /**< Request to activate account */ - LinphoneAccountCreatorRequestFunc is_account_activated_request_cb; /**< Request to know if account is activated */ - - LinphoneAccountCreatorRequestFunc link_account_request_cb; /**< Request to link account with an alias */ - LinphoneAccountCreatorRequestFunc activate_alias_request_cb; /**< Request to activate the link of alias */ - LinphoneAccountCreatorRequestFunc is_alias_used_request_cb; /**< Request to know if alias is used */ - LinphoneAccountCreatorRequestFunc is_account_linked_request_cb; /**< Request to know if account is linked with an alias */ - - LinphoneAccountCreatorRequestFunc recover_account_request_cb; /**< Request to recover account */ - LinphoneAccountCreatorRequestFunc update_account_request_cb; /**< Request to update account */ -}; - -BELLE_SIP_DECLARE_VPTR_NO_EXPORT(LinphoneAccountCreatorService); - -struct _LinphoneAccountCreatorCbs { - belle_sip_object_t base; - void *user_data; - - LinphoneAccountCreatorCbsStatusCb create_account_response_cb; /**< Response of create_account request */ - LinphoneAccountCreatorCbsStatusCb is_account_exist_response_cb; /**< Response of is_account_exist request */ - - LinphoneAccountCreatorCbsStatusCb activate_account_response_cb; /**< Response of activate_account request */ - LinphoneAccountCreatorCbsStatusCb is_account_activated_response_cb; /**< Response of is_account_activated request */ - - LinphoneAccountCreatorCbsStatusCb link_account_response_cb; /**< Response of link_account request */ - LinphoneAccountCreatorCbsStatusCb activate_alias_response_cb; /**< Response of activation alias */ - LinphoneAccountCreatorCbsStatusCb is_alias_used_response_cb; /**< Response of is_alias_used request */ - LinphoneAccountCreatorCbsStatusCb is_account_linked_response_cb; /**< Response of is_account_linked request */ - - LinphoneAccountCreatorCbsStatusCb recover_account_response_cb; /**< Response of recover_account request */ - LinphoneAccountCreatorCbsStatusCb update_account_response_cb; /**< Response of update_account request */ -}; - -BELLE_SIP_DECLARE_VPTR_NO_EXPORT(LinphoneAccountCreatorCbs); - -struct _LinphoneAccountCreator { - belle_sip_object_t base; - void *user_data; - LinphoneCore *core; - - /* AccountCreator */ - LinphoneAccountCreatorService *service; /**< Account creator service */ - LinphoneAccountCreatorCbs *cbs; /**< Account creator cbs */ - LinphoneXmlRpcSession *xmlrpc_session; /**< XML-RPC session */ - LinphoneProxyConfig *proxy_cfg; /**< Default proxy config */ - - /* User */ - char *username; /**< Username */ - char *display_name; /**< Display name */ - /* Password */ - char *password; /**< Plain text password */ - char *ha1; /**< Hash password */ - /* Phone Number(Alias) */ - char *phone_number; /**< User phone number*/ - char *phone_country_code; /**< User phone number country code */ - /* Email(Alias) */ - char *email; /**< User email */ - /* Misc */ - char *language; /**< User language */ - char *activation_code; /**< Account validation code */ - char *domain; /**< Domain */ - LinphoneTransportType transport; /**< Transport used */ - - /* Deprecated */ - char *route; -}; - -BELLE_SIP_DECLARE_VPTR_NO_EXPORT(LinphoneAccountCreator); - -/** - * Account creator custom to set Linphone default values - * @param[in] creator LinphoneAccountCreator object - * @return LinphoneAccountCreatorStatusRequestOk if the request has been sent, LinphoneAccountCreatorStatusRequestFailed otherwise -**/ -LINPHONE_PUBLIC LinphoneAccountCreatorStatus linphone_account_creator_constructor_linphone(LinphoneAccountCreator *creator); - -/** - * Send an XML-RPC request to test the existence of a Linphone account. - * @param[in] creator LinphoneAccountCreator object - * @return LinphoneAccountCreatorStatusRequestOk if the request has been sent, LinphoneAccountCreatorStatusRequestFailed otherwise -**/ -LINPHONE_PUBLIC LinphoneAccountCreatorStatus linphone_account_creator_is_account_exist_linphone(LinphoneAccountCreator *creator); - -/** - * Send an XML-RPC request to create a Linphone account. - * @param[in] creator LinphoneAccountCreator object - * @return LinphoneAccountCreatorStatusRequestOk if the request has been sent, LinphoneAccountCreatorStatusRequestFailed otherwise -**/ -LINPHONE_PUBLIC LinphoneAccountCreatorStatus linphone_account_creator_create_account_linphone(LinphoneAccountCreator *creator); - -/** - * Send an XML-RPC request to activate a Linphone account with phone number. - * @param[in] creator LinphoneAccountCreator object - * @return LinphoneAccountCreatorStatusRequestOk if the request has been sent, LinphoneAccountCreatorStatusRequestFailed otherwise -**/ -LINPHONE_PUBLIC LinphoneAccountCreatorStatus linphone_account_creator_activate_account_linphone(LinphoneAccountCreator *creator); - -/** - * Send an XML-RPC request to activate a Linphone account with email. - * @param[in] creator LinphoneAccountCreator object - * @return LinphoneAccountCreatorStatusRequestOk if the request has been sent, LinphoneAccountCreatorStatusRequestFailed otherwise -**/ -LINPHONE_PUBLIC LinphoneAccountCreatorStatus linphone_account_creator_activate_email_account_linphone(LinphoneAccountCreator *creator); - -/** - * Send an XML-RPC request to test the validation of a Linphone account. - * @param[in] creator LinphoneAccountCreator object - * @return LinphoneAccountCreatorStatusRequestOk if the request has been sent, LinphoneAccountCreatorStatusRequestFailed otherwise -**/ -LINPHONE_PUBLIC LinphoneAccountCreatorStatus linphone_account_creator_is_account_activated_linphone(LinphoneAccountCreator *creator); - -/** - * Send an XML-RPC request to test the existence a phone number with a Linphone account. - * @param[in] creator LinphoneAccountCreator object - * @return LinphoneAccountCreatorStatusRequestOk if the request has been sent, LinphoneAccountCreatorStatusRequestFailed otherwise -**/ -LINPHONE_PUBLIC LinphoneAccountCreatorStatus linphone_account_creator_is_phone_number_used_linphone(LinphoneAccountCreator *creator); - -/** - * Send an XML-RPC request to link a phone number with a Linphone account. - * @param[in] creator LinphoneAccountCreator object - * @return LinphoneAccountCreatorStatusRequestOk if the request has been sent, LinphoneAccountCreatorStatusRequestFailed otherwise -**/ -LINPHONE_PUBLIC LinphoneAccountCreatorStatus linphone_account_creator_link_phone_number_with_account_linphone(LinphoneAccountCreator *creator); - -/** - * Send an XML-RPC request to activate the link of a phone number with a Linphone account. - * @param[in] creator LinphoneAccountCreator object - * @return LinphoneAccountCreatorStatusRequestOk if the request has been sent, LinphoneAccountCreatorStatusRequestFailed otherwise -**/ -LINPHONE_PUBLIC LinphoneAccountCreatorStatus linphone_account_creator_activate_phone_number_link_linphone(LinphoneAccountCreator *creator); - -/** - * Send an XML-RPC request to a Linphone account with the phone number. - * @param[in] creator LinphoneAccountCreator object - * @return LinphoneAccountCreatorStatusRequestOk if the request has been sent, LinphoneAccountCreatorStatusRequestFailed otherwise -**/ -LINPHONE_PUBLIC LinphoneAccountCreatorStatus linphone_account_creator_recover_phone_account_linphone(LinphoneAccountCreator *creator); - -/** - * Send an XML-RPC request to ask if an account is linked with a phone number - * @param[in] creator LinphoneAccountCreator object - * @return if this account is linked with a phone number -**/ -LINPHONE_PUBLIC LinphoneAccountCreatorStatus linphone_account_creator_is_account_linked_linphone(LinphoneAccountCreator *creator); - -/** - * Send an XML-RPC request to ask if an account is linked with a phone number - * @param[in] creator LinphoneAccountCreator object - * @param[in] new_pwd const char * : new password for the account creator - * @return LinphoneAccountCreatorStatusRequestOk if everything is OK, or a specific error otherwise. -**/ -LINPHONE_PUBLIC LinphoneAccountCreatorStatus linphone_account_creator_update_password_linphone(LinphoneAccountCreator *creator); - /***************************************************************************** * CardDAV interface * @@ -1524,7 +1358,7 @@ void linphone_xml_xpath_context_init_carddav_ns(xmlparsing_context_t *xml_ctx); char * linphone_timestamp_to_rfc3339_string(time_t timestamp); -void linphone_error_info_from_sal_op(LinphoneErrorInfo *ei, const SalOp *op); +void linphone_error_info_from_sal_op(LinphoneErrorInfo *ei, const LINPHONE_NAMESPACE::SalOp *op); void payload_type_set_enable(OrtpPayloadType *pt, bool_t value); bool_t payload_type_enabled(const OrtpPayloadType *pt); diff --git a/coreapi/proxy.c b/coreapi/proxy.c index a74eefa0b..590b144e5 100644 --- a/coreapi/proxy.c +++ b/coreapi/proxy.c @@ -33,6 +33,8 @@ Copyright (C) 2000 Simon MORLAT (simon.morlat@linphone.org) #include "address/address-p.h" #include "c-wrapper/c-wrapper.h" +using namespace LINPHONE_NAMESPACE; + /*store current config related to server location*/ static void linphone_proxy_config_store_server_config(LinphoneProxyConfig* cfg) { if (cfg->saved_identity) linphone_address_unref(cfg->saved_identity); @@ -213,7 +215,7 @@ LinphoneProxyConfig * linphone_core_create_proxy_config(LinphoneCore *lc) { void _linphone_proxy_config_release_ops(LinphoneProxyConfig *cfg){ if (cfg->op) { - sal_op_release(cfg->op); + cfg->op->release(); cfg->op=NULL; } if (cfg->presence_publish_event){ @@ -387,7 +389,7 @@ void linphone_proxy_config_enable_publish(LinphoneProxyConfig *cfg, bool_t val){ } void linphone_proxy_config_pause_register(LinphoneProxyConfig *cfg){ - if (cfg->op) sal_op_stop_refreshing(cfg->op); + if (cfg->op) cfg->op->stop_refreshing(); } void linphone_proxy_config_edit(LinphoneProxyConfig *cfg){ @@ -410,7 +412,7 @@ 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) + ? cfg->op->get_contact_address() : NULL; if (sal_addr) { char *buf = sal_address_as_string(sal_addr); @@ -435,7 +437,7 @@ void linphone_proxy_config_stop_refreshing(LinphoneProxyConfig * cfg){ } if (cfg->op){ - sal_op_release(cfg->op); + cfg->op->release(); cfg->op=NULL; } } @@ -473,7 +475,7 @@ static void guess_contact_for_register (LinphoneProxyConfig *cfg) { void _linphone_proxy_config_unregister(LinphoneProxyConfig *obj) { if (obj->op && (obj->state == LinphoneRegistrationOk || (obj->state == LinphoneRegistrationProgress && obj->expires != 0))) { - sal_unregister(obj->op); + obj->op->unregister(); } } @@ -486,18 +488,17 @@ static void linphone_proxy_config_register(LinphoneProxyConfig *cfg){ proxy_string=linphone_address_as_string_uri_only(proxy); linphone_address_unref(proxy); if (cfg->op) - sal_op_release(cfg->op); - cfg->op=sal_op_new(cfg->lc->sal); + cfg->op->release(); + cfg->op=new SalRegisterOp(cfg->lc->sal); linphone_configure_op(cfg->lc, cfg->op, cfg->identity_address, cfg->sent_headers, FALSE); guess_contact_for_register(cfg); if (cfg->contact_address) - sal_op_set_contact_address(cfg->op, L_GET_PRIVATE_FROM_C_OBJECT(cfg->contact_address)->getInternalAddress()); - sal_op_set_user_pointer(cfg->op, cfg); + cfg->op->set_contact_address(L_GET_PRIVATE_FROM_C_OBJECT(cfg->contact_address)->getInternalAddress()); + cfg->op->set_user_pointer(cfg); - if (sal_register( - cfg->op, + if (cfg->op->register_( proxy_string, cfg->reg_identity, cfg->expires, @@ -524,7 +525,7 @@ static void linphone_proxy_config_register(LinphoneProxyConfig *cfg){ void linphone_proxy_config_refresh_register(LinphoneProxyConfig *cfg){ if (cfg->reg_sendregister && cfg->op && cfg->state!=LinphoneRegistrationProgress){ - if (sal_register_refresh(cfg->op,cfg->expires) == 0) { + if (cfg->op->register_refresh(cfg->expires) == 0) { linphone_proxy_config_set_state(cfg,LinphoneRegistrationProgress, "Refresh registration"); } } @@ -795,8 +796,8 @@ LinphoneStatus linphone_proxy_config_done(LinphoneProxyConfig *cfg) if (res == LinphoneProxyConfigAddressDifferent) { _linphone_proxy_config_unregister(cfg); } - sal_op_set_user_pointer(cfg->op,NULL); /*we don't want to receive status for this un register*/ - sal_op_unref(cfg->op); /*but we keep refresher to handle authentication if needed*/ + cfg->op->set_user_pointer(NULL); /*we don't want to receive status for this un register*/ + cfg->op->unref(); /*but we keep refresher to handle authentication if needed*/ cfg->op=NULL; } if (cfg->presence_publish_event) { @@ -989,7 +990,7 @@ struct _LinphoneCore * linphone_proxy_config_get_core(const LinphoneProxyConfig const char *linphone_proxy_config_get_custom_header(LinphoneProxyConfig *cfg, const char *header_name){ const SalCustomHeader *ch; if (!cfg->op) return NULL; - ch = sal_op_get_recv_custom_header(cfg->op); + ch = cfg->op->get_recv_custom_header(); return sal_custom_header_find(ch, header_name); } @@ -1353,7 +1354,7 @@ const LinphoneErrorInfo *linphone_proxy_config_get_error_info(const LinphoneProx } const LinphoneAddress* linphone_proxy_config_get_service_route(const LinphoneProxyConfig* cfg) { - return cfg->op?(const LinphoneAddress*) sal_op_get_service_route(cfg->op):NULL; + return cfg->op?(const LinphoneAddress*) cfg->op->get_service_route():NULL; } const char* linphone_proxy_config_get_transport(const LinphoneProxyConfig *cfg) { const char* addr=NULL; diff --git a/coreapi/quality_reporting.c b/coreapi/quality_reporting.c index 2175baa07..fd2e393fd 100644 --- a/coreapi/quality_reporting.c +++ b/coreapi/quality_reporting.c @@ -24,6 +24,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "linphone/core.h" #include "private.h" #include "sal/sal.h" +#include "sal/sal.hpp" #include "ortp/rtpsession.h" #include diff --git a/coreapi/sal.c b/coreapi/sal.c deleted file mode 100644 index 3870e59e3..000000000 --- a/coreapi/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/sal/call_op.cpp b/coreapi/sal/call_op.cpp new file mode 100644 index 000000000..aa7ecf193 --- /dev/null +++ b/coreapi/sal/call_op.cpp @@ -0,0 +1,1475 @@ +#include "call_op.h" +#include "bellesip_sal/sal_impl.h" +#include "offeranswer.h" +#include +#include + +using namespace std; + +#define SIP_MESSAGE_BODY_LIMIT 16*1024 // 16kB + +LINPHONE_BEGIN_NAMESPACE + +int SalCallOp::set_local_media_description(SalMediaDescription *desc) { + if (this->custom_body) { + bctbx_error("cannot set local media description on SalOp [%p] because a custom body is already set", this); + return -1; + } + + if (desc) sal_media_description_ref(desc); + if (this->local_media) sal_media_description_unref(this->local_media); + this->local_media=desc; + + if (this->remote_media){ + /*case of an incoming call where we modify the local capabilities between the time + * the call is ringing and it is accepted (for example if you want to accept without video*/ + /*reset the sdp answer so that it is computed again*/ + if (this->sdp_answer){ + belle_sip_object_unref(this->sdp_answer); + this->sdp_answer=NULL; + } + } + return 0; +} + +int SalCallOp::set_local_custom_body(SalCustomBody *body) { + if (this->local_media) { + bctbx_error("cannot set custom body on SalOp [%p] because a local media description is already set", this); + return -1; + } + if (this->custom_body) sal_custom_body_unref(this->custom_body); + this->custom_body = sal_custom_body_ref(body ? body : NULL); + return 0; +} + +belle_sip_header_allow_t *SalCallOp::create_allow(bool_t enable_update) { + belle_sip_header_allow_t* header_allow; + char allow [256]; + snprintf(allow,sizeof(allow),"INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, NOTIFY, MESSAGE, SUBSCRIBE, INFO%s",(enable_update?", UPDATE":"")); + header_allow = belle_sip_header_allow_create(allow); + return header_allow; +} + +int SalCallOp::set_custom_body(belle_sip_message_t *msg, const SalCustomBody *body) { + if (body->data_length > SIP_MESSAGE_BODY_LIMIT) { + bctbx_error("trying to add a body greater than %dkB to message [%p]", SIP_MESSAGE_BODY_LIMIT/1024, msg); + return -1; + } + if (body->data_length == 0 || body->raw_data == NULL) { + bctbx_error("trying to add an empty custom body to message [%p]", msg); + return -1; + } + + belle_sip_header_content_type_t *content_type = belle_sip_header_content_type_create(body->type->type, body->type->subtype); + belle_sip_header_content_length_t *content_length = belle_sip_header_content_length_create(body->data_length); + belle_sip_message_add_header(msg, BELLE_SIP_HEADER(content_type)); + belle_sip_message_add_header(msg, BELLE_SIP_HEADER(content_length)); + + char *buffer = bctbx_new(char, body->data_length); + memcpy(buffer, body->raw_data, body->data_length); + belle_sip_message_assign_body(msg, buffer, body->data_length); + + return 0; +} + +int SalCallOp::set_sdp(belle_sip_message_t *msg,belle_sdp_session_description_t* session_desc) { + belle_sip_error_code error = BELLE_SIP_BUFFER_OVERFLOW; + size_t length = 0; + + if (session_desc == NULL) return -1; + + size_t bufLen = 2048; + char *buff = reinterpret_cast(belle_sip_malloc(bufLen)); + + /* try to marshal the description. This could go higher than 2k so we iterate */ + while( error != BELLE_SIP_OK && bufLen <= SIP_MESSAGE_BODY_LIMIT && buff != NULL){ + error = belle_sip_object_marshal(BELLE_SIP_OBJECT(session_desc),buff,bufLen,&length); + if( error != BELLE_SIP_OK ){ + bufLen *= 2; + length = 0; + buff = reinterpret_cast(belle_sip_realloc(buff,bufLen)); + } + } + /* give up if hard limit reached */ + if (error != BELLE_SIP_OK || buff == NULL) { + ms_error("Buffer too small (%d) or not enough memory, giving up SDP", (int)bufLen); + return -1; + } + + SalMimeType *mimetype = sal_mime_type_new("application", "sdp"); + SalCustomBody *body = sal_custom_body_new_with_buffer_moving(mimetype, buff, length); + set_custom_body(msg, body); + sal_custom_body_unref(body); + + return 0; +} + +int SalCallOp::set_sdp_from_desc(belle_sip_message_t *msg, const SalMediaDescription *desc) { + int err; + belle_sdp_session_description_t *sdp=media_description_to_sdp(desc); + err=set_sdp(msg,sdp); + belle_sip_object_unref(sdp); + return err; + +} + +void SalCallOp::fill_invite(belle_sip_request_t* invite) { + belle_sip_message_add_header(BELLE_SIP_MESSAGE(invite),BELLE_SIP_HEADER(create_allow(this->root->enable_sip_update))); + + if (this->root->session_expires!=0){ + belle_sip_message_add_header(BELLE_SIP_MESSAGE(invite),belle_sip_header_create( "Session-expires", "600;refresher=uas")); + belle_sip_message_add_header(BELLE_SIP_MESSAGE(invite),belle_sip_header_create( "Supported", "timer")); + } + if (this->local_media){ + this->sdp_offering=TRUE; + set_sdp_from_desc(BELLE_SIP_MESSAGE(invite),this->local_media); + } else this->sdp_offering=FALSE; + if (this->custom_body) { + set_custom_body(BELLE_SIP_MESSAGE(invite), this->custom_body); + } +} + +void SalCallOp::set_released() { + if (!this->call_released){ + this->state=State::Terminated; + this->root->callbacks.call_released(this); + this->call_released=TRUE; + /*be aware that the following line may destroy the op*/ + set_or_update_dialog(NULL); + } +} + +void SalCallOp::process_io_error_cb(void *user_ctx, const belle_sip_io_error_event_t *event) { + SalCallOp *op = (SalCallOp *)user_ctx; + + if (op->state == State::Terminated) return; + + if (op->pending_client_trans && (belle_sip_transaction_get_state(BELLE_SIP_TRANSACTION(op->pending_client_trans)) == BELLE_SIP_TRANSACTION_INIT)) { + + sal_error_info_set(&op->error_info, SalReasonIOError, "SIP", 503, "IO error", NULL); + op->root->callbacks.call_failure(op); + + if (!op->dialog || belle_sip_dialog_get_state(op->dialog) != BELLE_SIP_DIALOG_CONFIRMED){ + /* Call terminated very very early, before INVITE is even sent, probably DNS resolution timeout. */ + op->state = State::Terminating; + op->set_released(); + } + } else { + /* Nothing to be done. If the error comes from a connectivity loss, + * the call will be marked as broken, and an attempt to repair it will be done. */ + } +} + +void SalCallOp::cancelling_invite(const SalErrorInfo *info) { + cancel_invite_with_info(info); + this->state=State::Terminating; +} + +SalCustomBody *SalCallOp::extract_body(belle_sip_message_t *message) { + const char *body_str = belle_sip_message_get_body(message); + belle_sip_header_content_type_t *content_type = belle_sip_message_get_header_by_type(message, belle_sip_header_content_type_t); + belle_sip_header_content_length_t *content_length = belle_sip_message_get_header_by_type(message, belle_sip_header_content_length_t); + if (!(body_str && content_type && content_length)) return NULL; + const char *type_str = belle_sip_header_content_type_get_type(content_type); + const char *subtype_str = belle_sip_header_content_type_get_subtype(content_type); + size_t length = belle_sip_header_content_length_get_content_length(content_length); + SalMimeType *mime_type = sal_mime_type_new(type_str, subtype_str); + SalCustomBody *body = sal_custom_body_new_with_buffer_copy(mime_type, body_str, length); + return body; +} + +int SalCallOp::extract_sdp(belle_sip_message_t* message,belle_sdp_session_description_t** session_desc, SalReason *error) { + *session_desc = NULL; + *error = SalReasonNone; + + if (this->sdp_handling == SalOpSDPSimulateError) { + ms_error("Simulating SDP parsing error for op %p", this); + *error = SalReasonNotAcceptable; + return -1; + } + + if (this->sdp_handling == SalOpSDPSimulateRemove) { + ms_error("Simulating no SDP for op %p", this); + return 0; + } + + SalCustomBody *body = extract_body(message); + if (body == NULL) return 0; + + if (strcmp("application", body->type->type) != 0 || strcmp("sdp", body->type->subtype) != 0) { + sal_custom_body_unref(body); + *error = SalReasonUnsupportedContent; + return -1; + } + + *session_desc = belle_sdp_session_description_parse(string(body->raw_data, body->data_length).c_str()); + sal_custom_body_unref(body); + + if (*session_desc == NULL) { + ms_error("Failed to parse SDP message."); + *error = SalReasonNotAcceptable; + return -1; + } + + return 0; +} + +void SalCallOp::set_addr_to_0000(char value[], size_t sz) { + if (ms_is_ipv6(value)) { + strncpy(value,"::0", sz); + } else { + strncpy(value,"0.0.0.0", sz); + } + return; +} + +void SalCallOp::sdp_process(){ + ms_message("Doing SDP offer/answer process of type %s", this->sdp_offering ? "outgoing" : "incoming"); + if (this->result){ + sal_media_description_unref(this->result); + this->result = NULL; + } + + /* if SDP was invalid */ + if (this->remote_media == NULL) return; + + this->result=sal_media_description_new(); + if (this->sdp_offering){ + offer_answer_initiate_outgoing(this->root->factory, this->local_media,this->remote_media,this->result); + }else{ + int i; + if (this->sdp_answer){ + belle_sip_object_unref(this->sdp_answer); + } + offer_answer_initiate_incoming(this->root->factory, this->local_media,this->remote_media,this->result,this->root->one_matching_codec); + /*for backward compatibility purpose*/ + if(this->_cnx_ip_to_0000_if_sendonly_enabled && sal_media_description_has_dir(this->result,SalStreamSendOnly)) { + set_addr_to_0000(this->result->addr, sizeof(this->result->addr)); + for(i=0;iresult->streams[i].dir == SalStreamSendOnly) { + set_addr_to_0000(this->result->streams[i].rtp_addr, sizeof(this->result->streams[i].rtp_addr)); + set_addr_to_0000(this->result->streams[i].rtcp_addr, sizeof(this->result->streams[i].rtcp_addr)); + } + } + } + + this->sdp_answer=(belle_sdp_session_description_t *)belle_sip_object_ref(media_description_to_sdp(this->result)); + /*once we have generated the SDP answer, we modify the result description for processing by the upper layer. + It should contains media parameters constraint from the remote offer, not our response*/ + strcpy(this->result->addr,this->remote_media->addr); + this->result->bandwidth=this->remote_media->bandwidth; + + for(i=0;iresult->streams[i].rtp_port!=0){ /*if stream was accepted*/ + strcpy(this->result->streams[i].rtp_addr,this->remote_media->streams[i].rtp_addr); + this->result->streams[i].ptime=this->remote_media->streams[i].ptime; + this->result->streams[i].bandwidth=this->remote_media->streams[i].bandwidth; + this->result->streams[i].rtp_port=this->remote_media->streams[i].rtp_port; + strcpy(this->result->streams[i].rtcp_addr,this->remote_media->streams[i].rtcp_addr); + this->result->streams[i].rtcp_port=this->remote_media->streams[i].rtcp_port; + + if (sal_stream_description_has_srtp(&this->result->streams[i])) { + this->result->streams[i].crypto[0] = this->remote_media->streams[i].crypto[0]; + } + } + } + } +} + +void SalCallOp::handle_sdp_from_response(belle_sip_response_t* response) { + belle_sdp_session_description_t* sdp; + SalReason reason; + if (this->remote_media){ + sal_media_description_unref(this->remote_media); + this->remote_media=NULL; + } + if (extract_sdp(BELLE_SIP_MESSAGE(response),&sdp,&reason)==0) { + if (sdp){ + this->remote_media=sal_media_description_new(); + sdp_to_media_description(sdp,this->remote_media); + }/*if no sdp in response, what can we do ?*/ + } + /* process sdp in any case to reset result media description*/ + if (this->local_media) sdp_process(); +} + +void SalCallOp::set_error(belle_sip_response_t* response, bool_t fatal){ + set_error_info_from_response(response); + if (fatal) this->state = State::Terminating; + this->root->callbacks.call_failure(this); +} + +int SalCallOp::vfu_retry_cb (void *user_data, unsigned int events) { + SalCallOp *op=(SalCallOp *)user_data; + op->send_vfu_request(); + op->ref(); + return BELLE_SIP_STOP; +} + +void SalCallOp::process_response_cb(void *op_base, const belle_sip_response_event_t *event) { + SalCallOp * op = (SalCallOp *)op_base; + belle_sip_request_t* ack; + belle_sip_dialog_state_t dialog_state; + belle_sip_client_transaction_t* client_transaction = belle_sip_response_event_get_client_transaction(event); + belle_sip_request_t* req; + belle_sip_response_t* response=belle_sip_response_event_get_response(event); + int code = belle_sip_response_get_status_code(response); + belle_sip_header_content_type_t *header_content_type=NULL; + belle_sip_dialog_t *dialog=belle_sip_response_event_get_dialog(event); + const char *method; + + if (!client_transaction) { + ms_warning("Discarding stateless response [%i] on op [%p]",code,op); + return; + } + req=belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(client_transaction)); + op->set_or_update_dialog(dialog); + dialog_state=dialog ? belle_sip_dialog_get_state(dialog) : BELLE_SIP_DIALOG_NULL; + method=belle_sip_request_get_method(req); + ms_message("Op [%p] receiving call response [%i], dialog is [%p] in state [%s]",op,code,dialog,belle_sip_dialog_state_to_string(dialog_state)); + /*to make sure no cb will destroy op*/ + op->ref(); + switch(dialog_state) { + case BELLE_SIP_DIALOG_NULL: + case BELLE_SIP_DIALOG_EARLY: { + if (strcmp("INVITE",method)==0 ) { + if (op->state == State::Terminating) { + /*check if CANCEL was sent before*/ + if (strcmp("CANCEL",belle_sip_request_get_method(belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(op->pending_client_trans))))!=0) { + /*it wasn't sent */ + if (code<200) { + op->cancelling_invite(NULL); + }else{ + /* no need to send the INVITE because the UAS rejected the INVITE*/ + if (op->dialog==NULL) op->set_released(); + } + } else { + /*it was sent already, so just expect the 487 or any error response to send the call_released() notification*/ + if (code>=300){ + if (op->dialog==NULL) op->set_released(); + } + } + } else if (code >= 180 && code<200) { + belle_sip_response_t *prev_response=reinterpret_cast(belle_sip_object_data_get(BELLE_SIP_OBJECT(dialog),"early_response")); + if (!prev_response || code>belle_sip_response_get_status_code(prev_response)){ + op->handle_sdp_from_response(response); + op->root->callbacks.call_ringing(op); + } + belle_sip_object_data_set(BELLE_SIP_OBJECT(dialog),"early_response",belle_sip_object_ref(response),belle_sip_object_unref); + } else if (code>=300){ + op->set_error(response, TRUE); + if (op->dialog==NULL) op->set_released(); + } + } else if (code >=200 && code<300) { + if (strcmp("UPDATE",method)==0) { + op->handle_sdp_from_response(response); + op->root->callbacks.call_accepted(op); + } else if (strcmp("CANCEL", method) == 0) { + op->root->callbacks.call_cancel_done(op); + } + } + } + break; + case BELLE_SIP_DIALOG_CONFIRMED: { + switch (op->state) { + case State::Early:/*invite case*/ + case State::Active: /*re-invite, INFO, UPDATE case*/ + if (strcmp("INVITE",method)==0){ + if (code >=200 && code<300) { + op->handle_sdp_from_response(response); + ack=belle_sip_dialog_create_ack(op->dialog,belle_sip_dialog_get_local_seq_number(op->dialog)); + if (ack == NULL) { + ms_error("This call has been already terminated."); + return ; + } + if (op->sdp_answer){ + set_sdp(BELLE_SIP_MESSAGE(ack),op->sdp_answer); + belle_sip_object_unref(op->sdp_answer); + op->sdp_answer=NULL; + } + belle_sip_message_add_header(BELLE_SIP_MESSAGE(ack),BELLE_SIP_HEADER(op->root->user_agent)); + op->root->callbacks.call_accepted(op); /*INVITE*/ + op->root->callbacks.call_ack_being_sent(op, (SalCustomHeader*)ack); + belle_sip_dialog_send_ack(op->dialog,ack); + op->state=State::Active; + }else if (code >= 300){ + op->set_error(response, FALSE); + } + }else if (strcmp("INFO",method)==0){ + if (code == 491 + && (header_content_type = belle_sip_message_get_header_by_type(req,belle_sip_header_content_type_t)) + && strcmp("application",belle_sip_header_content_type_get_type(header_content_type))==0 + && strcmp("media_control+xml",belle_sip_header_content_type_get_subtype(header_content_type))==0) { + unsigned int retry_in = rand() % 1001; // [0;1000] + belle_sip_source_t *s=op->root->create_timer(vfu_retry_cb,op->ref(), retry_in, "vfu request retry"); + ms_message("Rejected vfu request on op [%p], just retry in [%ui] ms",op,retry_in); + belle_sip_object_unref(s); + }else { + /*ignoring*/ + } + }else if (strcmp("UPDATE",method)==0){ + op->root->callbacks.call_accepted(op); /*INVITE*/ + }else if (strcmp("CANCEL",method)==0){ + op->root->callbacks.call_cancel_done(op); + } + break; + case State::Terminating: + op->send_request(belle_sip_dialog_create_request(op->dialog,"BYE")); + break; + case State::Terminated: + default: + ms_error("Call op [%p] receives unexpected answer [%i] while in state [%s].",op,code, to_string(op->state)); + } + } + break; + case BELLE_SIP_DIALOG_TERMINATED: { + if (strcmp("INVITE",method)==0 && code >= 300){ + op->set_error(response, TRUE); + } + } + break; + default: { + ms_error("call op [%p] receive answer [%i] not implemented",op,code); + } + break; + } + op->unref(); +} + +void SalCallOp::process_timeout_cb(void *user_ctx, const belle_sip_timeout_event_t *event) { + SalCallOp * op=(SalCallOp *)user_ctx; + + if (op->state==State::Terminated) return; + + if (!op->dialog) { + /*call terminated very early*/ + sal_error_info_set(&op->error_info, SalReasonRequestTimeout, "SIP", 408, "Request timeout", NULL); + op->root->callbacks.call_failure(op); + op->state = State::Terminating; + op->set_released(); + } else { + /*dialog will terminated shortly, nothing to do*/ + } +} + +void SalCallOp::process_transaction_terminated_cb(void *user_ctx, const belle_sip_transaction_terminated_event_t *event) { + SalCallOp * op = (SalCallOp *)user_ctx; + belle_sip_client_transaction_t *client_transaction=belle_sip_transaction_terminated_event_get_client_transaction(event); + belle_sip_server_transaction_t *server_transaction=belle_sip_transaction_terminated_event_get_server_transaction(event); + belle_sip_request_t* req; + belle_sip_response_t* resp; + int code = 0; + bool_t release_call=FALSE; + + if (client_transaction) { + req=belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(client_transaction)); + resp=belle_sip_transaction_get_response(BELLE_SIP_TRANSACTION(client_transaction)); + } else { + req=belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(server_transaction)); + resp=belle_sip_transaction_get_response(BELLE_SIP_TRANSACTION(server_transaction)); + } + if (resp) code = belle_sip_response_get_status_code(resp); + + if (op->state == State::Terminating + && strcmp("BYE",belle_sip_request_get_method(req))==0 + && (!resp || (belle_sip_response_get_status_code(resp) != 401 + && belle_sip_response_get_status_code(resp) != 407)) + && op->dialog==NULL) { + release_call=TRUE; + }else if (op->state == State::Early && code < 200){ + /*call terminated early*/ + sal_error_info_set(&op->error_info, SalReasonIOError, "SIP", 503, "I/O error", NULL); + op->state = State::Terminating; + op->root->callbacks.call_failure(op); + release_call=TRUE; + } + if (server_transaction){ + if (op->pending_server_trans==server_transaction){ + belle_sip_object_unref(op->pending_server_trans); + op->pending_server_trans=NULL; + } + if (op->pending_update_server_trans==server_transaction){ + belle_sip_object_unref(op->pending_update_server_trans); + op->pending_update_server_trans=NULL; + } + } + if (release_call) op->set_released(); +} + +int SalCallOp::is_media_description_acceptable(SalMediaDescription *md) { + if (md->nb_streams==0){ + ms_warning("Media description does not define any stream."); + return FALSE; + } + return TRUE; +} + +SalReason SalCallOp::process_sdp_for_invite(belle_sip_request_t* invite) { + belle_sdp_session_description_t* sdp; + SalReason reason = SalReasonNone; + SalErrorInfo sei; + + memset(&sei, 0, sizeof(sei)); + if (extract_sdp(BELLE_SIP_MESSAGE(invite),&sdp,&reason)==0) { + if (sdp){ + this->sdp_offering=FALSE; + this->remote_media=sal_media_description_new(); + sdp_to_media_description(sdp,this->remote_media); + /*make some sanity check about the SDP received*/ + if (!is_media_description_acceptable(this->remote_media)){ + reason=SalReasonNotAcceptable; + } + belle_sip_object_unref(sdp); + }else this->sdp_offering=TRUE; /*INVITE without SDP*/ + } + + if (reason != SalReasonNone){ + sal_error_info_set(&sei, reason,"SIP", 0, NULL, NULL); + decline_with_error_info(&sei,NULL); + sal_error_info_reset(&sei); + } + return reason; +} + +void SalCallOp::call_terminated(belle_sip_server_transaction_t* server_transaction, int status_code, belle_sip_request_t* cancel_request) { + belle_sip_response_t* resp; + belle_sip_request_t* server_req = belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(server_transaction)); + this->state = State::Terminating; + set_reason_error_info(BELLE_SIP_MESSAGE(cancel_request ? cancel_request : server_req)); + resp=create_response_from_request(server_req,status_code); + belle_sip_server_transaction_send_response(server_transaction,resp); + this->root->callbacks.call_terminated(this,this->dir==Dir::Incoming?this->get_from():this->get_to()); +} + +void SalCallOp::reset_descriptions() { + if (this->remote_media){ + sal_media_description_unref(this->remote_media); + this->remote_media=NULL; + } + if (this->result){ + sal_media_description_unref(this->result); + this->result=NULL; + } +} + +void SalCallOp::unsupported_method(belle_sip_server_transaction_t* server_transaction,belle_sip_request_t* request) { + belle_sip_response_t* resp; + resp=belle_sip_response_create_from_request(request,501); + belle_sip_server_transaction_send_response(server_transaction,resp); +} + +bool_t SalCallOp::is_a_pending_invite_incoming_transaction(belle_sip_transaction_t *tr){ + return BELLE_SIP_OBJECT_IS_INSTANCE_OF(tr, belle_sip_ist_t) && belle_sip_transaction_state_is_transient( + belle_sip_transaction_get_state(tr)); +} + +void SalCallOp::process_request_event_cb(void *op_base, const belle_sip_request_event_t *event) { + SalCallOp * op = (SalCallOp *)op_base; + SalReason reason; + belle_sip_server_transaction_t* server_transaction=NULL; + belle_sdp_session_description_t* sdp; + belle_sip_request_t* req = belle_sip_request_event_get_request(event); + belle_sip_dialog_state_t dialog_state; + belle_sip_response_t* resp; + belle_sip_header_t* call_info; + const char *method=belle_sip_request_get_method(req); + bool_t is_update=FALSE; + bool_t drop_op = FALSE; + + if (strcmp("ACK",method)!=0){ /*ACK doesn't create a server transaction*/ + server_transaction = belle_sip_provider_create_server_transaction(op->root->prov,belle_sip_request_event_get_request(event)); + belle_sip_object_ref(server_transaction); + belle_sip_transaction_set_application_data(BELLE_SIP_TRANSACTION(server_transaction),op->ref()); + } + + if (strcmp("INVITE",method)==0) { + if (op->pending_server_trans) belle_sip_object_unref(op->pending_server_trans); + /*updating pending invite transaction*/ + op->pending_server_trans=server_transaction; + belle_sip_object_ref(op->pending_server_trans); + } + + if (strcmp("UPDATE",method)==0) { + if (op->pending_update_server_trans) belle_sip_object_unref(op->pending_update_server_trans); + /*updating pending update transaction*/ + op->pending_update_server_trans=server_transaction; + belle_sip_object_ref(op->pending_update_server_trans); + } + + if (!op->dialog) { + op->set_or_update_dialog(belle_sip_provider_create_dialog(op->root->prov, BELLE_SIP_TRANSACTION(op->pending_server_trans))); + ms_message("new incoming call from [%s] to [%s]",op->get_from(),op->get_to()); + } + dialog_state=belle_sip_dialog_get_state(op->dialog); + switch(dialog_state) { + case BELLE_SIP_DIALOG_NULL: { + if (strcmp("INVITE",method)==0) { + if (!op->replaces && (op->replaces=belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req),belle_sip_header_replaces_t))) { + belle_sip_object_ref(op->replaces); + } else if(op->replaces) { + ms_warning("replace header already set"); + } + + if ( (reason = op->process_sdp_for_invite(req)) == SalReasonNone) { + if ((call_info=belle_sip_message_get_header(BELLE_SIP_MESSAGE(req),"Call-Info"))) { + if( strstr(belle_sip_header_get_unparsed_value(call_info),"answer-after=") != NULL) { + op->auto_answer_asked=TRUE; + ms_message("The caller asked to automatically answer the call(Emergency?)\n"); + } + } + op->root->callbacks.call_received(op); + }else{ + sal_error_info_set(&op->error_info, reason, "SIP", 0, NULL, NULL); + op->root->callbacks.call_rejected(op); + /*the INVITE was declined by process_sdp_for_invite(). As we are not inside an established dialog, we can drop the op immediately*/ + drop_op = TRUE; + } + break; + }BCTBX_NO_BREAK; /* else same behavior as for EARLY state, thus NO BREAK*/ + } + case BELLE_SIP_DIALOG_EARLY: { + if (strcmp("CANCEL",method)==0) { + if(belle_sip_request_event_get_server_transaction(event)) { + /*first answer 200 ok to cancel*/ + belle_sip_server_transaction_send_response(server_transaction + ,op->create_response_from_request(req,200)); + /*terminate invite transaction*/ + op->call_terminated(op->pending_server_trans,487,req); + } else { + /*call leg does not exist*/ + belle_sip_server_transaction_send_response(server_transaction + ,op->create_response_from_request(req,481)); + } + } else if (strcmp("PRACK",method)==0) { + resp=op->create_response_from_request(req,200); + belle_sip_server_transaction_send_response(server_transaction,resp); + } else if (strcmp("UPDATE",method)==0) { + op->reset_descriptions(); + if (op->process_sdp_for_invite(req)==SalReasonNone) + op->root->callbacks.call_updating(op,TRUE); + } else { + belle_sip_error("Unexpected method [%s] for dialog state BELLE_SIP_DIALOG_EARLY",belle_sip_request_get_method(req)); + unsupported_method(server_transaction,req); + } + break; + } + case BELLE_SIP_DIALOG_CONFIRMED: + /*great ACK received*/ + if (strcmp("ACK",method)==0) { + if (!op->pending_client_trans || + !belle_sip_transaction_state_is_transient(belle_sip_transaction_get_state((belle_sip_transaction_t*)op->pending_client_trans))){ + if (op->sdp_offering){ + SalReason reason; + if (op->extract_sdp(BELLE_SIP_MESSAGE(req),&sdp,&reason)==0) { + if (sdp){ + if (op->remote_media) + sal_media_description_unref(op->remote_media); + op->remote_media=sal_media_description_new(); + sdp_to_media_description(sdp,op->remote_media); + op->sdp_process(); + belle_sip_object_unref(sdp); + }else{ + ms_warning("SDP expected in ACK but not found."); + } + } + } + op->root->callbacks.call_ack_received(op, (SalCustomHeader*)req); + }else{ + ms_message("Ignored received ack since a new client transaction has been started since."); + } + } else if(strcmp("BYE",method)==0) { + op->call_terminated(server_transaction,200,req); + /*call end not notified by dialog deletion because transaction can end before dialog*/ + } else if(strcmp("INVITE",method)==0 || (is_update=(strcmp("UPDATE",method)==0)) ) { + if (is_update && !belle_sip_message_get_body(BELLE_SIP_MESSAGE(req))) { + /*session timer case*/ + /*session expire should be handled. to be done when real session timer (rfc4028) will be implemented*/ + resp=op->create_response_from_request(req,200); + belle_sip_server_transaction_send_response(server_transaction,resp); + belle_sip_object_unref(op->pending_update_server_trans); + op->pending_update_server_trans=NULL; + } else { + /*re-invite*/ + op->reset_descriptions(); + if (op->process_sdp_for_invite(req)==SalReasonNone) + op->root->callbacks.call_updating(op,is_update); + } + } else if (strcmp("INFO",method)==0){ + if (belle_sip_message_get_body(BELLE_SIP_MESSAGE(req)) + && strstr(belle_sip_message_get_body(BELLE_SIP_MESSAGE(req)),"picture_fast_update")) { + /*vfu request*/ + ms_message("Receiving VFU request on op [%p]",op); + if (op->root->callbacks.vfu_request){ + op->root->callbacks.vfu_request(op); + + } + }else{ + belle_sip_message_t *msg = BELLE_SIP_MESSAGE(req); + belle_sip_body_handler_t *body_handler = BELLE_SIP_BODY_HANDLER(op->get_body_handler(msg)); + if (body_handler) { + belle_sip_header_content_type_t *content_type = belle_sip_message_get_header_by_type(msg, belle_sip_header_content_type_t); + if (content_type + && (strcmp(belle_sip_header_content_type_get_type(content_type), "application") == 0) + && (strcmp(belle_sip_header_content_type_get_subtype(content_type), "dtmf-relay") == 0)) { + char tmp[10]; + if (sal_lines_get_value(belle_sip_message_get_body(msg), "Signal",tmp, sizeof(tmp))){ + op->root->callbacks.dtmf_received(op,tmp[0]); + } + }else + op->root->callbacks.info_received(op, (SalBodyHandler *)body_handler); + } else { + op->root->callbacks.info_received(op,NULL); + } + } + resp=op->create_response_from_request(req,200); + belle_sip_server_transaction_send_response(server_transaction,resp); + }else if (strcmp("REFER",method)==0) { + op->process_refer(event,server_transaction); + } else if (strcmp("NOTIFY",method)==0) { + op->process_notify(event,server_transaction); + } else if (strcmp("OPTIONS",method)==0) { + resp=op->create_response_from_request(req,200); + belle_sip_server_transaction_send_response(server_transaction,resp); + } else if (strcmp("CANCEL",method)==0) { + belle_sip_transaction_t *last_transaction = belle_sip_dialog_get_last_transaction(op->dialog); + if (last_transaction == NULL || !is_a_pending_invite_incoming_transaction(last_transaction) ) { + /*call leg does not exist because 200ok already sent*/ + belle_sip_server_transaction_send_response(server_transaction,op->create_response_from_request(req,481)); + } else { + /* CANCEL on re-INVITE for which a 200ok has not been sent yet */ + belle_sip_server_transaction_send_response(server_transaction, op->create_response_from_request(req, 200)); + belle_sip_server_transaction_send_response(BELLE_SIP_SERVER_TRANSACTION(last_transaction), + op->create_response_from_request(belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(last_transaction)), 487)); + } + } else if (strcmp("MESSAGE",method)==0){ + op->process_incoming_message(event); + }else{ + ms_error("unexpected method [%s] for dialog [%p]",belle_sip_request_get_method(req),op->dialog); + unsupported_method(server_transaction,req); + } + break; + default: + ms_error("unexpected dialog state [%s]",belle_sip_dialog_state_to_string(dialog_state)); + break; + } + + if (server_transaction) belle_sip_object_unref(server_transaction); + if (drop_op) op->release(); +} + +void SalCallOp::set_call_as_released(SalCallOp *op) { + op->set_released(); +} + +void SalCallOp::process_dialog_terminated_cb(void *ctx, const belle_sip_dialog_terminated_event_t *event) { + SalCallOp * op=(SalCallOp *)ctx; + + if (op->dialog && op->dialog==belle_sip_dialog_terminated_event_get_dialog(event)) { + /*belle_sip_transaction_t* trans=belle_sip_dialog_get_last_transaction(op->dialog);*/ + ms_message("Dialog [%p] terminated for op [%p]",belle_sip_dialog_terminated_event_get_dialog(event),op); + + switch(belle_sip_dialog_get_previous_state(op->dialog)) { + case BELLE_SIP_DIALOG_EARLY: + case BELLE_SIP_DIALOG_NULL: + if (op->state!=State::Terminated && op->state!=State::Terminating) { + /*this is an early termination due to incorrect response received*/ + op->root->callbacks.call_failure(op); + op->state=State::Terminating; + } + break; + case BELLE_SIP_DIALOG_CONFIRMED: + if (op->state!=State::Terminated && op->state!=State::Terminating) { + /*this is probably a normal termination from a BYE*/ + op->root->callbacks.call_terminated(op,op->dir==Dir::Incoming?op->get_from():op->get_to()); + op->state=State::Terminating; + } + break; + default: + break; + } + belle_sip_main_loop_do_later(belle_sip_stack_get_main_loop(op->root->stack) + ,(belle_sip_callback_t) set_call_as_released + , op); + } else { + ms_error("dialog unknown for op "); + } +} + +void SalCallOp::fill_cbs() { + static belle_sip_listener_callbacks_t call_op_callbacks = {0}; + if (call_op_callbacks.process_response_event==NULL){ + call_op_callbacks.process_io_error=process_io_error_cb; + call_op_callbacks.process_response_event=process_response_cb; + call_op_callbacks.process_timeout=process_timeout_cb; + call_op_callbacks.process_transaction_terminated=process_transaction_terminated_cb; + call_op_callbacks.process_request_event=process_request_event_cb; + call_op_callbacks.process_dialog_terminated=process_dialog_terminated_cb; + } + this->callbacks=&call_op_callbacks; + this->type=Type::Call; +} + +int SalCallOp::call(const char *from, const char *to, const char *subject) { + belle_sip_request_t* invite; + this->dir=Dir::Outgoing; + + set_from(from); + set_to(to); + + ms_message("[%s] calling [%s] on op [%p]", from, to, this); + invite=build_request("INVITE"); + + if( invite == NULL ){ + /* can happen if the op has an invalid address */ + return -1; + } + + fill_invite(invite); + if (subject) belle_sip_message_add_header(BELLE_SIP_MESSAGE(invite), belle_sip_header_create("Subject", subject)); + + fill_cbs(); + if (this->replaces){ + belle_sip_message_add_header(BELLE_SIP_MESSAGE(invite),BELLE_SIP_HEADER(this->replaces)); + } + if (this->referred_by) + belle_sip_message_add_header(BELLE_SIP_MESSAGE(invite),BELLE_SIP_HEADER(this->referred_by)); + + return send_request(invite); +} + +int SalCallOp::notify_ringing(bool_t early_media){ + int status_code =early_media?183:180; + belle_sip_request_t* req=belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(this->pending_server_trans)); + belle_sip_response_t* ringing_response = create_response_from_request(req,status_code); + belle_sip_header_t *require; + const char *tags=NULL; + + if (early_media){ + handle_offer_answer_response(ringing_response); + } + require=belle_sip_message_get_header((belle_sip_message_t*)req,"Require"); + if (require) tags=belle_sip_header_get_unparsed_value(require); + /* if client requires 100rel, then add necessary stuff*/ + if (tags && strstr(tags,"100rel")!=0) { + belle_sip_message_add_header((belle_sip_message_t*)ringing_response,belle_sip_header_create("Require","100rel")); + belle_sip_message_add_header((belle_sip_message_t*)ringing_response,belle_sip_header_create("RSeq","1")); + } + +#ifndef SAL_OP_CALL_FORCE_CONTACT_IN_RINGING + if (tags && strstr(tags,"100rel")!=0) +#endif + { + belle_sip_header_address_t* contact= (belle_sip_header_address_t*)get_contact_address(); + belle_sip_header_contact_t* contact_header; + if (contact && (contact_header=belle_sip_header_contact_create(contact))) { + belle_sip_message_add_header(BELLE_SIP_MESSAGE(ringing_response),BELLE_SIP_HEADER(contact_header)); + } + } + belle_sip_server_transaction_send_response(this->pending_server_trans,ringing_response); + return 0; +} + +int SalCallOp::accept() { + belle_sip_response_t *response; + belle_sip_header_contact_t* contact_header; + belle_sip_server_transaction_t* transaction; + + /*first check if an UPDATE transaction need to be accepted*/ + if (this->pending_update_server_trans) { + transaction= this->pending_update_server_trans; + } else if (this->pending_server_trans) { + /*so it must be an invite/re-invite*/ + transaction= this->pending_server_trans; + } else { + ms_error("No transaction to accept for op [%p]", this); + return -1; + } + ms_message("Accepting server transaction [%p] on op [%p]", transaction, this); + + /* sends a 200 OK */ + response = create_response_from_request(belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(transaction)),200); + if (response==NULL){ + ms_error("Fail to build answer for call"); + return -1; + } + belle_sip_message_add_header(BELLE_SIP_MESSAGE(response),BELLE_SIP_HEADER(create_allow(this->root->enable_sip_update))); + if (this->root->session_expires!=0){ +/* if (h->supports_session_timers) {*/ + belle_sip_message_add_header(BELLE_SIP_MESSAGE(response),belle_sip_header_create("Supported", "timer")); + belle_sip_message_add_header(BELLE_SIP_MESSAGE(response),belle_sip_header_create( "Session-expires", "600;refresher=uac")); + /*}*/ + } + + if ((contact_header=create_contact())) { + belle_sip_message_add_header(BELLE_SIP_MESSAGE(response),BELLE_SIP_HEADER(contact_header)); + } + + add_custom_headers(BELLE_SIP_MESSAGE(response)); + + handle_offer_answer_response(response); + + belle_sip_server_transaction_send_response(transaction,response); + if (this->pending_update_server_trans) { + belle_sip_object_unref(this->pending_update_server_trans); + this->pending_update_server_trans=NULL; + } + if (this->state == State::Early){ + this->state = State::Active; + } + return 0; +} + +int SalCallOp::decline(SalReason reason, const char *redirection /*optional*/){ + belle_sip_response_t* response; + belle_sip_header_contact_t* contact=NULL; + int status=to_sip_code(reason); + belle_sip_transaction_t *trans; + + if (reason==SalReasonRedirect){ + if (redirection!=NULL) { + if (strstr(redirection,"sip:")!=0) status=302; + else status=380; + contact= belle_sip_header_contact_new(); + belle_sip_header_address_set_uri(BELLE_SIP_HEADER_ADDRESS(contact),belle_sip_uri_parse(redirection)); + } else { + ms_error("Cannot redirect to null"); + } + } + trans=(belle_sip_transaction_t*)this->pending_server_trans; + if (!trans) trans=(belle_sip_transaction_t*)this->pending_update_server_trans; + if (!trans){ + ms_error("sal_call_decline(): no pending transaction to decline."); + return -1; + } + response = create_response_from_request(belle_sip_transaction_get_request(trans),status); + if (contact) belle_sip_message_add_header(BELLE_SIP_MESSAGE(response),BELLE_SIP_HEADER(contact)); + belle_sip_server_transaction_send_response(BELLE_SIP_SERVER_TRANSACTION(trans),response); + return 0; +} + +belle_sip_header_reason_t *SalCallOp::make_reason_header( const SalErrorInfo *info){ + if (info != NULL){ + belle_sip_header_reason_t* reason = BELLE_SIP_HEADER_REASON(belle_sip_header_reason_new()); + belle_sip_header_reason_set_text(reason, info->status_string); + belle_sip_header_reason_set_protocol(reason,info->protocol); + belle_sip_header_reason_set_cause(reason,info->protocol_code); + return reason; + } + return NULL; +} + +int SalCallOp::decline_with_error_info(const SalErrorInfo *info, const char *redirection /*optional*/){ + belle_sip_response_t* response; + belle_sip_header_contact_t* contact=NULL; + int status = info->protocol_code; + belle_sip_transaction_t *trans; + + if (info->reason==SalReasonRedirect){ + if (redirection!=NULL) { + if (strstr(redirection,"sip:")!=0) status=302; + else status=380; + contact= belle_sip_header_contact_new(); + belle_sip_header_address_set_uri(BELLE_SIP_HEADER_ADDRESS(contact),belle_sip_uri_parse(redirection)); + } else { + ms_error("Cannot redirect to null"); + } + } + trans=(belle_sip_transaction_t*)this->pending_server_trans; + if (!trans) trans=(belle_sip_transaction_t*)this->pending_update_server_trans; + if (!trans){ + ms_error("sal_call_decline_with_error_info(): no pending transaction to decline."); + return -1; + } + response = create_response_from_request(belle_sip_transaction_get_request(trans),status); + belle_sip_header_reason_t* reason_header = make_reason_header(info->sub_sei); + if (reason_header) { + belle_sip_message_add_header(BELLE_SIP_MESSAGE(response),BELLE_SIP_HEADER(reason_header)); + } + + if (contact) { + belle_sip_message_add_header(BELLE_SIP_MESSAGE(response),BELLE_SIP_HEADER(contact)); + } + belle_sip_server_transaction_send_response(BELLE_SIP_SERVER_TRANSACTION(trans),response); + return 0; +} + +int SalCallOp::update(const char *subject, bool_t no_user_consent) { + belle_sip_request_t *update; + belle_sip_dialog_state_t state; + + if (this->dialog == NULL) { + /* If the dialog does not exist, this is that we are trying to recover from a connection loss + during a very early state of outgoing call initiation (the dialog has not been created yet). */ + const char *from = get_from(); + const char *to = get_to(); + return call(from, to, subject); + } + + state = belle_sip_dialog_get_state(this->dialog); + belle_sip_dialog_enable_pending_trans_checking(this->dialog,this->root->pending_trans_checking); + + /*check for dialog state*/ + if ( state == BELLE_SIP_DIALOG_CONFIRMED) { + if (no_user_consent) + update=belle_sip_dialog_create_request(this->dialog,"UPDATE"); + else + update=belle_sip_dialog_create_request(this->dialog,"INVITE"); + } else if (state == BELLE_SIP_DIALOG_EARLY) { + update=belle_sip_dialog_create_request(this->dialog,"UPDATE"); + } else { + ms_error("Cannot update op [%p] with dialog [%p] in state [%s]", this, this->dialog,belle_sip_dialog_state_to_string(state)); + return -1; + } + if (update){ + belle_sip_message_add_header(BELLE_SIP_MESSAGE(update),belle_sip_header_create( "Subject", subject)); + fill_invite(update); + return send_request(update); + } + /*it failed why ?*/ + if (belle_sip_dialog_request_pending(this->dialog)) + sal_error_info_set(&this->error_info,SalReasonRequestPending, "SIP", 491,NULL,NULL); + else + sal_error_info_set(&this->error_info,SalReasonUnknown, "SIP", 500,NULL,NULL); + return -1; +} + +void SalCallOp::cancel_invite_with_info(const SalErrorInfo *info) { + belle_sip_request_t* cancel; + ms_message("Cancelling INVITE request from [%s] to [%s] ",get_from(), get_to()); + cancel = belle_sip_client_transaction_create_cancel(this->pending_client_trans); + if (cancel){ + if (info != NULL){ + belle_sip_header_reason_t* reason = make_reason_header(info); + belle_sip_message_add_header(BELLE_SIP_MESSAGE(cancel),BELLE_SIP_HEADER(reason)); + } + send_request(cancel); + }else if (this->dialog){ + belle_sip_dialog_state_t state = belle_sip_dialog_get_state(this->dialog);; + /*case where the response received is invalid (could not establish a dialog), but the transaction is not cancellable + * because already terminated*/ + switch(state){ + case BELLE_SIP_DIALOG_EARLY: + case BELLE_SIP_DIALOG_NULL: + /*force kill the dialog*/ + ms_warning("op [%p]: force kill of dialog [%p]", this, this->dialog); + belle_sip_dialog_delete(this->dialog); + break; + default: + break; + } + } +} + +SalMediaDescription *SalCallOp::get_final_media_description() { + if (this->local_media && this->remote_media && !this->result){ + sdp_process(); + } + return this->result; +} + +int SalCallOp::refer_to(belle_sip_header_refer_to_t* refer_to, belle_sip_header_referred_by_t* referred_by) { + char* tmp; + belle_sip_request_t* req=this->dialog?belle_sip_dialog_create_request(this->dialog,"REFER"):build_request("REFER"); + if (!req) { + tmp=belle_sip_uri_to_string(belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(refer_to))); + ms_error("Cannot refer to [%s] for op [%p]",tmp, this); + belle_sip_free(tmp); + return -1; + } + belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(refer_to)); + if (referred_by) belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(referred_by)); + return send_request(req); +} + +int SalCallOp::refer(const char *refer_to_){ + belle_sip_header_address_t *referred_by; + belle_sip_header_refer_to_t* refer_to_header; + if (this->dialog) { + referred_by=(belle_sip_header_address_t*)belle_sip_object_clone(BELLE_SIP_OBJECT(belle_sip_dialog_get_local_party(this->dialog))); + }else{ + referred_by=BELLE_SIP_HEADER_ADDRESS(get_from_address()); + } + refer_to_header=belle_sip_header_refer_to_create(belle_sip_header_address_parse(refer_to_)); + + return refer_to(refer_to_header,belle_sip_header_referred_by_create(referred_by)); +} + +int SalCallOp::refer_with_replaces(SalCallOp *other_call_op) { + belle_sip_dialog_state_t other_call_dialog_state=other_call_op->dialog?belle_sip_dialog_get_state(other_call_op->dialog):BELLE_SIP_DIALOG_NULL; + belle_sip_dialog_state_t op_dialog_state= this->dialog?belle_sip_dialog_get_state(this->dialog):BELLE_SIP_DIALOG_NULL; + belle_sip_header_replaces_t* replaces; + belle_sip_header_refer_to_t* refer_to_; + belle_sip_header_referred_by_t* referred_by; + const char* from_tag; + const char* to_tag; + char* escaped_replaces; + /*first, build refer to*/ + if ((other_call_dialog_state!=BELLE_SIP_DIALOG_CONFIRMED) && (other_call_dialog_state!=BELLE_SIP_DIALOG_EARLY)) { + ms_error("wrong dialog state [%s] for op [%p], should be BELLE_SIP_DIALOG_CONFIRMED or BELE_SIP_DIALOG_EARLY", + belle_sip_dialog_state_to_string(other_call_dialog_state), + other_call_op); + return -1; + } + if (op_dialog_state!=BELLE_SIP_DIALOG_CONFIRMED) { + ms_error("wrong dialog state [%s] for op [%p], should be BELLE_SIP_DIALOG_CONFIRMED", + belle_sip_dialog_state_to_string(op_dialog_state), + this); + return -1; + } + + refer_to_ =belle_sip_header_refer_to_create(belle_sip_dialog_get_remote_party(other_call_op->dialog)); + belle_sip_parameters_clean(BELLE_SIP_PARAMETERS(refer_to_)); + /*rfc3891 + ... + 4. User Agent Client Behavior: Sending a Replaces Header + + A User Agent that wishes to replace a single existing early or + confirmed dialog with a new dialog of its own, MAY send the target + User Agent an INVITE request containing a Replaces header field. The + User Agent Client (UAC) places the Call-ID, to-tag, and from-tag + information for the target dialog in a single Replaces header field + and sends the new INVITE to the target.*/ + from_tag=belle_sip_dialog_get_local_tag(other_call_op->dialog); + to_tag=belle_sip_dialog_get_remote_tag(other_call_op->dialog); + + replaces=belle_sip_header_replaces_create(belle_sip_header_call_id_get_call_id(belle_sip_dialog_get_call_id(other_call_op->dialog)) + ,from_tag,to_tag); + escaped_replaces=belle_sip_header_replaces_value_to_escaped_string(replaces); + belle_sip_uri_set_header(belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(refer_to_)),"Replaces",escaped_replaces); + belle_sip_free(escaped_replaces); + referred_by=belle_sip_header_referred_by_create(belle_sip_dialog_get_local_party(this->dialog)); + belle_sip_parameters_clean(BELLE_SIP_PARAMETERS(referred_by)); + return refer_to(refer_to_,referred_by); +} + +int SalCallOp::set_referer(SalCallOp *refered_call){ + if (refered_call->replaces) + SalOp::set_replaces(refered_call->replaces); + if (refered_call->referred_by) + set_referred_by(refered_call->referred_by); + return 0; +} + +SalCallOp *SalCallOp::get_replaces() { + if (this->replaces){ + /*rfc3891 + 3. User Agent Server Behavior: Receiving a Replaces Header + + The Replaces header contains information used to match an existing + SIP dialog (call-id, to-tag, and from-tag). Upon receiving an INVITE + with a Replaces header, the User Agent (UA) attempts to match this + information with a confirmed or early dialog. The User Agent Server + (UAS) matches the to-tag and from-tag parameters as if they were tags + present in an incoming request. In other words, the to-tag parameter + is compared to the local tag, and the from-tag parameter is compared + to the remote tag. + */ + belle_sip_dialog_t* dialog=belle_sip_provider_find_dialog(this->root->prov + ,belle_sip_header_replaces_get_call_id(this->replaces) + ,belle_sip_header_replaces_get_to_tag(this->replaces) + ,belle_sip_header_replaces_get_from_tag(this->replaces)); + + if (!dialog) { + /*for backward compatibility with liblinphone <= 3.10.2-243 */ + dialog=belle_sip_provider_find_dialog(this->root->prov + ,belle_sip_header_replaces_get_call_id(this->replaces) + ,belle_sip_header_replaces_get_from_tag(this->replaces) + ,belle_sip_header_replaces_get_to_tag(this->replaces)); + } + if (dialog) { + return (SalCallOp*)belle_sip_dialog_get_application_data(dialog); + } + } + return NULL; +} + +int SalCallOp::send_dtmf(char dtmf){ + if (this->dialog && (belle_sip_dialog_get_state(this->dialog) == BELLE_SIP_DIALOG_CONFIRMED || belle_sip_dialog_get_state(this->dialog) == BELLE_SIP_DIALOG_EARLY)){ + belle_sip_request_t *req=belle_sip_dialog_create_queued_request(this->dialog,"INFO"); + if (req){ + size_t bodylen; + char dtmf_body[128]={0}; + + snprintf(dtmf_body, sizeof(dtmf_body)-1, "Signal=%c\r\nDuration=250\r\n", dtmf); + bodylen=strlen(dtmf_body); + belle_sip_message_set_body((belle_sip_message_t*)req,dtmf_body,bodylen); + belle_sip_message_add_header((belle_sip_message_t*)req,(belle_sip_header_t*)belle_sip_header_content_length_create(bodylen)); + belle_sip_message_add_header((belle_sip_message_t*)req,(belle_sip_header_t*)belle_sip_header_content_type_create("application", "dtmf-relay")); + send_request(req); + }else ms_error("sal_call_send_dtmf(): could not build request"); + }else ms_error("sal_call_send_dtmf(): no dialog"); + return 0; +} + +int SalCallOp::terminate_with_error(const SalErrorInfo *info) { + SalErrorInfo sei; + const SalErrorInfo *p_sei; + belle_sip_dialog_state_t dialog_state = this->dialog ? belle_sip_dialog_get_state(this->dialog) : BELLE_SIP_DIALOG_NULL; + int ret = 0; + + memset(&sei, 0, sizeof(sei)); + if (info == NULL && dialog_state != BELLE_SIP_DIALOG_CONFIRMED && this->dir == Dir::Incoming){ + /*the purpose of this line is to set a default SalErrorInfo for declining an incoming call (not yet established of course) */ + sal_error_info_set(&sei,SalReasonDeclined, "SIP", 0, NULL, NULL); + p_sei = &sei; + } else{ + p_sei = info; + } + if (this->state==State::Terminating || this->state==State::Terminated) { + ms_error("Cannot terminate op [%p] in state [%s]",this,to_string(this->state)); + ret = -1; + goto end; + } + switch(dialog_state) { + case BELLE_SIP_DIALOG_CONFIRMED: { + belle_sip_request_t * req = belle_sip_dialog_create_request(this->dialog,"BYE"); + if (info != NULL){ + belle_sip_header_reason_t* reason = make_reason_header(info); + belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(reason)); + } + send_request(req); + this->state=State::Terminating; + break; + } + + case BELLE_SIP_DIALOG_NULL: { + if (this->dir == Dir::Incoming) { + decline_with_error_info(p_sei, NULL); + this->state=State::Terminated; + } else if (this->pending_client_trans){ + if (belle_sip_transaction_get_state(BELLE_SIP_TRANSACTION(this->pending_client_trans)) == BELLE_SIP_TRANSACTION_PROCEEDING){ + cancelling_invite(p_sei); + }else{ + /* Case where the CANCEL cannot be sent because no provisional response was received so far. + * The Op must be kept for the time of the transaction in case a response is received later. + * The state is passed to Terminating to remember to terminate later. + */ + this->state=State::Terminating; + /* 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(this->pending_client_trans); + } + } + break; + } + case BELLE_SIP_DIALOG_EARLY: { + if (this->dir == Dir::Incoming) { + decline_with_error_info(p_sei,NULL); + this->state=State::Terminated; + } else { + cancelling_invite(p_sei); + } + break; + } + default: { + ms_error("sal_call_terminate not implemented yet for dialog state [%s]",belle_sip_dialog_state_to_string(dialog_state)); + ret = -1; + goto end; + } + } +end: + sal_error_info_reset(&sei); + return ret; +} + +void SalCallOp::send_vfu_request() { + char info_body[] = + "" + "" + " " + " " + " " + " " + " " + ""; + size_t content_lenth = sizeof(info_body) - 1; + belle_sip_dialog_state_t dialog_state= this->dialog?belle_sip_dialog_get_state(this->dialog):BELLE_SIP_DIALOG_NULL; /*no dialog = dialog in NULL state*/ + if (dialog_state == BELLE_SIP_DIALOG_CONFIRMED) { + belle_sip_request_t* info = belle_sip_dialog_create_queued_request(this->dialog,"INFO"); + int error=TRUE; + if (info) { + belle_sip_message_add_header(BELLE_SIP_MESSAGE(info),BELLE_SIP_HEADER(belle_sip_header_content_type_create("application","media_control+xml"))); + belle_sip_message_add_header(BELLE_SIP_MESSAGE(info),BELLE_SIP_HEADER(belle_sip_header_content_length_create(content_lenth))); + belle_sip_message_set_body(BELLE_SIP_MESSAGE(info),info_body,content_lenth); + error=send_request(info); + } + if (error) + ms_warning("Cannot send vfu request to [%s] ", get_to()); + + } else { + ms_warning("Cannot send vfu request to [%s] because dialog [%p] in wrong state [%s]",get_to() + ,this->dialog + ,belle_sip_dialog_state_to_string(dialog_state)); + } + + return ; +} + +int SalCallOp::send_notify_for_refer(int code, const char *reason) { + belle_sip_request_t* notify=belle_sip_dialog_create_queued_request(this->dialog,"NOTIFY"); + char *sipfrag=belle_sip_strdup_printf("SIP/2.0 %i %s\r\n",code,reason); + size_t content_length=strlen(sipfrag); + belle_sip_message_add_header(BELLE_SIP_MESSAGE(notify) + ,BELLE_SIP_HEADER(belle_sip_header_subscription_state_create(BELLE_SIP_SUBSCRIPTION_STATE_ACTIVE,-1))); + + belle_sip_message_add_header(BELLE_SIP_MESSAGE(notify),belle_sip_header_create("Event","refer")); + belle_sip_message_add_header(BELLE_SIP_MESSAGE(notify),BELLE_SIP_HEADER(belle_sip_header_content_type_create("message","sipfrag"))); + belle_sip_message_add_header(BELLE_SIP_MESSAGE(notify),BELLE_SIP_HEADER(belle_sip_header_content_length_create(content_length))); + belle_sip_message_assign_body(BELLE_SIP_MESSAGE(notify),sipfrag,content_length); + return send_request(notify); +} + +void SalCallOp::notify_last_response(SalCallOp *newcall) { + belle_sip_client_transaction_t *tr=newcall->pending_client_trans; + belle_sip_response_t *resp=NULL; + if (tr){ + resp=belle_sip_transaction_get_response((belle_sip_transaction_t*)tr); + } + if (resp==NULL){ + send_notify_for_refer(100, "Trying"); + }else{ + send_notify_for_refer(belle_sip_response_get_status_code(resp), belle_sip_response_get_reason_phrase(resp)); + } +} + +int SalCallOp::notify_refer_state(SalCallOp *newcall) { + belle_sip_dialog_state_t state; + if(belle_sip_dialog_get_state(this->dialog) == BELLE_SIP_DIALOG_TERMINATED){ + return 0; + } + state = this->dialog?belle_sip_dialog_get_state(this->dialog):BELLE_SIP_DIALOG_NULL; + switch(state) { + case BELLE_SIP_DIALOG_EARLY: + send_notify_for_refer(100, "Trying"); + break; + case BELLE_SIP_DIALOG_CONFIRMED: + send_notify_for_refer(200, "Ok"); + break; + case BELLE_SIP_DIALOG_TERMINATED: + case BELLE_SIP_DIALOG_NULL: + notify_last_response(newcall); + break; + } + return 0; +} + +void SalCallOp::set_replaces(const char *call_id, const char *from_tag, const char *to_tag) { + belle_sip_header_replaces_t *replaces = belle_sip_header_replaces_create(call_id, from_tag, to_tag); + SalOp::set_replaces(replaces); +} + +void SalCallOp::set_sdp_handling(SalOpSDPHandling handling) { + if (handling != SalOpSDPNormal) ms_message("Enabling special SDP handling for SalOp[%p]!", this); + this->sdp_handling = handling; +} + +void SalCallOp::process_refer(const belle_sip_request_event_t *event, belle_sip_server_transaction_t *server_transaction) { + belle_sip_request_t* req = belle_sip_request_event_get_request(event); + belle_sip_header_refer_to_t *refer_to= belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req),belle_sip_header_refer_to_t); + belle_sip_header_referred_by_t *referred_by= belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req),belle_sip_header_referred_by_t); + belle_sip_response_t* resp; + belle_sip_uri_t* refer_to_uri; + char* refer_to_uri_str; + + ms_message("Receiving REFER request on op [%p]", this); + if (refer_to) { + refer_to_uri=belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(refer_to)); + + if (refer_to_uri && belle_sip_uri_get_header(refer_to_uri,"Replaces")) { + SalOp::set_replaces(belle_sip_header_replaces_create2(belle_sip_uri_get_header(refer_to_uri,"Replaces"))); + belle_sip_uri_remove_header(refer_to_uri,"Replaces"); + } + if (referred_by){ + set_referred_by(referred_by); + } + refer_to_uri_str=belle_sip_uri_to_string(refer_to_uri); + resp = create_response_from_request(req,202); + belle_sip_server_transaction_send_response(server_transaction,resp); + this->root->callbacks.refer_received(this->root,this,refer_to_uri_str); + belle_sip_free(refer_to_uri_str); + } else { + ms_warning("cannot do anything with the refer without destination\n"); + resp = create_response_from_request(req,400); + belle_sip_server_transaction_send_response(server_transaction,resp); + } + +} + +void SalCallOp::process_notify(const belle_sip_request_event_t *event, belle_sip_server_transaction_t* server_transaction) { + belle_sip_request_t* req = belle_sip_request_event_get_request(event); + const char* body = belle_sip_message_get_body(BELLE_SIP_MESSAGE(req)); + belle_sip_header_t* header_event=belle_sip_message_get_header(BELLE_SIP_MESSAGE(req),"Event"); + belle_sip_header_content_type_t* content_type = belle_sip_message_get_header_by_type(req,belle_sip_header_content_type_t); + belle_sip_response_t* resp; + + ms_message("Receiving NOTIFY request on op [%p]", this); + if (header_event + && strncasecmp(belle_sip_header_get_unparsed_value(header_event),"refer",strlen("refer"))==0 + && content_type + && strcmp(belle_sip_header_content_type_get_type(content_type),"message")==0 + && strcmp(belle_sip_header_content_type_get_subtype(content_type),"sipfrag")==0 + && body){ + belle_sip_response_t* sipfrag=BELLE_SIP_RESPONSE(belle_sip_message_parse(body)); + + if (sipfrag){ + int code=belle_sip_response_get_status_code(sipfrag); + SalReferStatus status=SalReferFailed; + if (code<200){ + status=SalReferTrying; + }else if (code<300){ + status=SalReferSuccess; + }else if (code>=400){ + status=SalReferFailed; + } + belle_sip_object_unref(sipfrag); + resp = create_response_from_request(req,200); + belle_sip_server_transaction_send_response(server_transaction,resp); + this->root->callbacks.notify_refer(this,status); + } + }else{ + ms_error("Notify without sipfrag, trashing"); + resp = create_response_from_request(req,501); + belle_sip_server_transaction_send_response(server_transaction,resp); + } +} + +int SalCallOp::send_message(const char *from, const char *to, const char* content_type, const char *msg, const char *peer_uri) { + if (!this->dialog) return -1; + belle_sip_request_t* req=belle_sip_dialog_create_queued_request(this->dialog,"MESSAGE"); + prepare_message_request(req, content_type, msg, peer_uri); + return send_request(req); +} + +bool_t SalCallOp::compare_op(const SalCallOp *op2) const { + return (strcmp(this->call_id, op2->call_id) == 0); +} + +void SalCallOp::handle_offer_answer_response(belle_sip_response_t* response) { + if (this->local_media){ + /*this is the case where we received an invite without SDP*/ + if (this->sdp_offering) { + set_sdp_from_desc(BELLE_SIP_MESSAGE(response),this->local_media); + }else{ + + if ( this->sdp_answer==NULL ) + { + if( this->sdp_handling == SalOpSDPSimulateRemove ){ + ms_warning("Simulating SDP removal in answer for op %p", this); + } else { + sdp_process(); + } + } + + if (this->sdp_answer){ + set_sdp(BELLE_SIP_MESSAGE(response),this->sdp_answer); + belle_sip_object_unref(this->sdp_answer); + this->sdp_answer=NULL; + } + } + }else{ + ms_error("You are accepting a call but not defined any media capabilities !"); + } +} + +LINPHONE_END_NAMESPACE diff --git a/coreapi/sal/call_op.h b/coreapi/sal/call_op.h new file mode 100644 index 000000000..2f773ae83 --- /dev/null +++ b/coreapi/sal/call_op.h @@ -0,0 +1,108 @@ +/* +sal_op.h +Copyright (C) 2017 Belledonne Communications + +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 _SAL_CALL_OP_H_ +#define _SAL_CALL_OP_H_ + +#include "sal_op.h" +#include "message_op_interface.h" + +LINPHONE_BEGIN_NAMESPACE + +class SalCallOp: public SalOp, public SalMessageOpInterface { +public: + SalCallOp(Sal *sal): SalOp(sal) {} + + int set_local_media_description(SalMediaDescription *desc); + int set_local_custom_body(SalCustomBody *body); + + SalMediaDescription *get_remote_media_description() {return this->remote_media;} + SalMediaDescription *get_final_media_description(); + + int call(const char *from, const char *to, const char *subject); + int notify_ringing(bool_t early_media); + int accept(); + int decline(SalReason reason, const char *redirection /*optional*/); + int decline_with_error_info(const SalErrorInfo *info, const char *redirection /*optional*/); + int update(const char *subject, bool_t no_user_consent); + void cancel_invite() {cancel_invite_with_info(NULL);} + void cancel_invite_with_info(const SalErrorInfo *info); + int refer(const char *refer_to_); + int refer_with_replaces(SalCallOp *other_call_op); + int set_referer(SalCallOp *refered_call); + SalCallOp *get_replaces(); + int send_dtmf(char dtmf); + int terminate() {return terminate_with_error(NULL);} + int terminate_with_error(const SalErrorInfo *info); + bool_t autoanswer_asked() const {return this->auto_answer_asked;} + void send_vfu_request(); + int is_offerer() const {return this->sdp_offering;} + int notify_refer_state(SalCallOp *newcall); + bool_t compare_op(const SalCallOp *op2) const; + bool_t dialog_request_pending() const {return (belle_sip_dialog_request_pending(this->dialog) != 0);} + const char *get_local_tag() {return belle_sip_dialog_get_local_tag(this->dialog);} + const char *get_remote_tag() {return belle_sip_dialog_get_remote_tag(this->dialog);} + void set_replaces(const char *call_id, const char *from_tag, const char *to_tag); + void set_sdp_handling(SalOpSDPHandling handling); + +// int send_message(const char *from, const char *to, const char *msg) override {return MessageOpInterface::send_message(from, to, msg);} + int send_message(const char *from, const char *to, const char* content_type, const char *msg, const char *peer_uri) override; + int reply(SalReason reason) override {return SalOp::reply_message(reason);} + +private: + static belle_sip_header_allow_t *create_allow(bool_t enable_update); + static int set_custom_body(belle_sip_message_t *msg, const SalCustomBody *body); + static int set_sdp(belle_sip_message_t *msg,belle_sdp_session_description_t* session_desc); + static int set_sdp_from_desc(belle_sip_message_t *msg, const SalMediaDescription *desc); + void set_released(); + static void process_io_error_cb(void *user_ctx, const belle_sip_io_error_event_t *event); + void cancelling_invite(const SalErrorInfo *info); + static SalCustomBody *extract_body(belle_sip_message_t *message); + int extract_sdp(belle_sip_message_t* message,belle_sdp_session_description_t** session_desc, SalReason *error); + static void set_addr_to_0000(char value[], size_t sz); + void sdp_process(); + void handle_sdp_from_response(belle_sip_response_t* response); + void set_error(belle_sip_response_t* response, bool_t fatal); + static int vfu_retry_cb (void *user_data, unsigned int events); + static void process_response_cb(void *op_base, const belle_sip_response_event_t *event); + static void process_timeout_cb(void *user_ctx, const belle_sip_timeout_event_t *event); + static void process_transaction_terminated_cb(void *user_ctx, const belle_sip_transaction_terminated_event_t *event); + static int is_media_description_acceptable(SalMediaDescription *md); + SalReason process_sdp_for_invite(belle_sip_request_t* invite); + void call_terminated(belle_sip_server_transaction_t* server_transaction, int status_code, belle_sip_request_t* cancel_request); + void reset_descriptions(); + static void unsupported_method(belle_sip_server_transaction_t* server_transaction,belle_sip_request_t* request); + static bool_t is_a_pending_invite_incoming_transaction(belle_sip_transaction_t *tr); + static void process_request_event_cb(void *op_base, const belle_sip_request_event_t *event); + static void set_call_as_released(SalCallOp *op); + static void process_dialog_terminated_cb(void *ctx, const belle_sip_dialog_terminated_event_t *event); + virtual void fill_cbs() override; + void fill_invite(belle_sip_request_t* invite); + static belle_sip_header_reason_t *make_reason_header( const SalErrorInfo *info); + int refer_to(belle_sip_header_refer_to_t* refer_to, belle_sip_header_referred_by_t* referred_by); + void notify_last_response(SalCallOp *newcall); + int send_notify_for_refer(int code, const char *reason); + void process_refer(const belle_sip_request_event_t *event, belle_sip_server_transaction_t *server_transaction); + void process_notify(const belle_sip_request_event_t *event, belle_sip_server_transaction_t* server_transaction); + void handle_offer_answer_response(belle_sip_response_t* response); +}; + +LINPHONE_END_NAMESPACE + +#endif diff --git a/coreapi/sal/event_op.cpp b/coreapi/sal/event_op.cpp new file mode 100644 index 000000000..d3f3b8ca6 --- /dev/null +++ b/coreapi/sal/event_op.cpp @@ -0,0 +1,425 @@ +#include "event_op.h" + +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +void SalSubscribeOp::subscribe_process_io_error_cb(void *user_ctx, const belle_sip_io_error_event_t *event) { + SalSubscribeOp *op = (SalSubscribeOp *)user_ctx; + belle_sip_object_t *src = belle_sip_io_error_event_get_source(event); + if (BELLE_SIP_OBJECT_IS_INSTANCE_OF(src, belle_sip_client_transaction_t)){ + belle_sip_client_transaction_t *tr = BELLE_SIP_CLIENT_TRANSACTION(src); + belle_sip_request_t* req = belle_sip_transaction_get_request((belle_sip_transaction_t*)tr); + const char *method=belle_sip_request_get_method(req); + + if (!op->dialog) { + /*this is handling outgoing out-of-dialog notifies*/ + if (strcmp(method,"NOTIFY")==0){ + SalErrorInfo *ei=&op->error_info; + sal_error_info_set(ei,SalReasonIOError, "SIP", 0,NULL,NULL); + op->root->callbacks.on_notify_response(op); + } + } + } +} + +void SalSubscribeOp::subscribe_response_event_cb(void *op_base, const belle_sip_response_event_t *event){ + SalSubscribeOp *op = (SalSubscribeOp *)op_base; + belle_sip_request_t * req; + const char *method; + belle_sip_client_transaction_t *tr = belle_sip_response_event_get_client_transaction(event); + + if (!tr) return; + req = belle_sip_transaction_get_request((belle_sip_transaction_t*)tr); + method = belle_sip_request_get_method(req); + + if (!op->dialog) { + if (strcmp(method,"NOTIFY")==0){ + op->set_error_info_from_response(belle_sip_response_event_get_response(event)); + op->root->callbacks.on_notify_response(op); + } + } +} + +void SalSubscribeOp::subscribe_process_timeout_cb(void *user_ctx, const belle_sip_timeout_event_t *event) { + SalSubscribeOp *op = (SalSubscribeOp *)user_ctx; + belle_sip_request_t * req; + const char *method; + belle_sip_client_transaction_t *tr = belle_sip_timeout_event_get_client_transaction(event); + + if (!tr) return; + req = belle_sip_transaction_get_request((belle_sip_transaction_t*)tr); + method = belle_sip_request_get_method(req); + + if (!op->dialog) { + /*this is handling outgoing out-of-dialog notifies*/ + if (strcmp(method,"NOTIFY")==0){ + SalErrorInfo *ei=&op->error_info; + sal_error_info_set(ei,SalReasonRequestTimeout, "SIP", 0,NULL,NULL); + op->root->callbacks.on_notify_response(op); + } + } +} + +void SalSubscribeOp::handle_notify(belle_sip_request_t *req, const char *eventname, SalBodyHandler* body_handler){ + SalSubscribeStatus sub_state; + belle_sip_header_subscription_state_t* subscription_state_header=belle_sip_message_get_header_by_type(req,belle_sip_header_subscription_state_t); + belle_sip_response_t* resp; + belle_sip_server_transaction_t* server_transaction = this->pending_server_trans; + + if (!subscription_state_header || strcasecmp(BELLE_SIP_SUBSCRIPTION_STATE_TERMINATED,belle_sip_header_subscription_state_get_state(subscription_state_header)) ==0) { + sub_state=SalSubscribeTerminated; + ms_message("Outgoing subscription terminated by remote [%s]",get_to()); + } else + sub_state=SalSubscribeActive; + ref(); + this->root->callbacks.notify(this,sub_state,eventname,body_handler); + resp=create_response_from_request(req,200); + belle_sip_server_transaction_send_response(server_transaction,resp); + unref(); +} + +void SalSubscribeOp::subscribe_process_request_event_cb(void *op_base, const belle_sip_request_event_t *event) { + SalSubscribeOp * op = (SalSubscribeOp *)op_base; + belle_sip_server_transaction_t* server_transaction = belle_sip_provider_create_server_transaction(op->root->prov,belle_sip_request_event_get_request(event)); + belle_sip_request_t* req = belle_sip_request_event_get_request(event); + belle_sip_dialog_state_t dialog_state; + belle_sip_header_expires_t* expires = belle_sip_message_get_header_by_type(req,belle_sip_header_expires_t); + belle_sip_header_event_t *event_header; + belle_sip_body_handler_t *body_handler; + belle_sip_response_t* resp; + const char *eventname=NULL; + const char *method=belle_sip_request_get_method(req); + belle_sip_dialog_t *dialog = NULL; + + belle_sip_object_ref(server_transaction); + if (op->pending_server_trans) belle_sip_object_unref(op->pending_server_trans); + op->pending_server_trans=server_transaction; + + event_header=belle_sip_message_get_header_by_type(req,belle_sip_header_event_t); + body_handler = BELLE_SIP_BODY_HANDLER(op->get_body_handler(BELLE_SIP_MESSAGE(req))); + + if (event_header==NULL){ + ms_warning("No event header in incoming SUBSCRIBE."); + resp=op->create_response_from_request(req,400); + belle_sip_server_transaction_send_response(server_transaction,resp); + if (!op->dialog) op->release(); + return; + } + if (op->event==NULL) { + op->event=event_header; + belle_sip_object_ref(op->event); + } + eventname=belle_sip_header_event_get_package_name(event_header); + + if (!op->dialog) { + if (strcmp(method,"SUBSCRIBE")==0){ + dialog = belle_sip_provider_create_dialog(op->root->prov,BELLE_SIP_TRANSACTION(server_transaction)); + if (!dialog){ + resp=op->create_response_from_request(req,481); + belle_sip_server_transaction_send_response(server_transaction,resp); + op->release(); + return; + } + op->set_or_update_dialog(dialog); + ms_message("new incoming subscription from [%s] to [%s]",op->get_from(),op->get_to()); + }else{ /*this is a NOTIFY*/ + op->handle_notify(req, eventname, (SalBodyHandler *)body_handler); + return; + } + } + dialog_state=belle_sip_dialog_get_state(op->dialog); + switch(dialog_state) { + + case BELLE_SIP_DIALOG_NULL: { + const char *type = NULL; + belle_sip_header_content_type_t *content_type = belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req), belle_sip_header_content_type_t); + if (content_type) type = belle_sip_header_content_type_get_type(content_type); + op->root->callbacks.subscribe_received(op, eventname, type ? (SalBodyHandler *)body_handler : NULL); + break; + } + case BELLE_SIP_DIALOG_EARLY: + ms_error("unexpected method [%s] for dialog [%p] in state BELLE_SIP_DIALOG_EARLY ",belle_sip_request_get_method(req),op->dialog); + break; + + case BELLE_SIP_DIALOG_CONFIRMED: + if (strcmp("NOTIFY",method)==0) { + op->handle_notify(req, eventname, (SalBodyHandler *)body_handler); + } else if (strcmp("SUBSCRIBE",method)==0) { + /*either a refresh of an unsubscribe*/ + if (expires && belle_sip_header_expires_get_expires(expires)>0) { + resp=op->create_response_from_request(req,200); + belle_sip_server_transaction_send_response(server_transaction,resp); + } else if(expires) { + ms_message("Unsubscribe received from [%s]",op->get_from()); + resp=op->create_response_from_request(req,200); + belle_sip_server_transaction_send_response(server_transaction,resp); + op->root->callbacks.incoming_subscribe_closed(op); + } + } + break; + default: { + ms_error("unexpected dialog state [%s]",belle_sip_dialog_state_to_string(dialog_state)); + } + } +} + +void SalSubscribeOp::subscribe_process_dialog_terminated_cb(void *ctx, const belle_sip_dialog_terminated_event_t *event) { + belle_sip_dialog_t *dialog = belle_sip_dialog_terminated_event_get_dialog(event); + SalSubscribeOp * op= (SalSubscribeOp *)ctx; + if (op->dialog) { + if (belle_sip_dialog_terminated_event_is_expired(event)){ + if (!belle_sip_dialog_is_server(dialog)){ + /*notify the app that our subscription is dead*/ + const char *eventname = NULL; + if (op->event){ + eventname = belle_sip_header_event_get_package_name(op->event); + } + op->root->callbacks.notify(op, SalSubscribeTerminated, eventname, NULL); + }else{ + op->root->callbacks.incoming_subscribe_closed(op); + } + } + op->set_or_update_dialog(NULL); + } +} + +void SalSubscribeOp::_release_cb(SalOp *op_base) { + auto *op =reinterpret_cast(op_base); + if(op->refresher) { + belle_sip_refresher_stop(op->refresher); + belle_sip_object_unref(op->refresher); + op->refresher=NULL; + op->set_or_update_dialog(NULL); /*only if we have refresher. else dialog terminated event will remove association*/ + } +} + +void SalSubscribeOp::fill_cbs() { + static belle_sip_listener_callbacks_t op_subscribe_callbacks={0}; + if (op_subscribe_callbacks.process_io_error==NULL){ + op_subscribe_callbacks.process_io_error=subscribe_process_io_error_cb; + op_subscribe_callbacks.process_response_event=subscribe_response_event_cb; + op_subscribe_callbacks.process_timeout=subscribe_process_timeout_cb; + op_subscribe_callbacks.process_transaction_terminated=subscribe_process_transaction_terminated_cb; + op_subscribe_callbacks.process_request_event=subscribe_process_request_event_cb; + op_subscribe_callbacks.process_dialog_terminated=subscribe_process_dialog_terminated_cb; + } + this->callbacks=&op_subscribe_callbacks; + this->type=Type::Subscribe; + this->release_cb=release_cb; +} + +void SalSubscribeOp::subscribe_refresher_listener_cb (belle_sip_refresher_t* refresher,void* user_pointer,unsigned int status_code,const char* reason_phrase, int will_retry) { + SalSubscribeOp * op = (SalSubscribeOp *)user_pointer; + belle_sip_transaction_t *tr=BELLE_SIP_TRANSACTION(belle_sip_refresher_get_transaction(refresher)); + /*belle_sip_response_t* response=belle_sip_transaction_get_response(tr);*/ + SalSubscribeStatus sss=SalSubscribeTerminated; + + ms_message("Subscribe refresher [%i] reason [%s] ",status_code,reason_phrase?reason_phrase:"none"); + if (status_code>=200 && status_code<300){ + if (status_code==200) sss=SalSubscribeActive; + else if (status_code==202) sss=SalSubscribePending; + op->set_or_update_dialog(belle_sip_transaction_get_dialog(tr)); + op->root->callbacks.subscribe_response(op,sss, will_retry); + } else if (status_code >= 300) { + SalReason reason = SalReasonUnknown; + if (status_code == 503) { /*refresher returns 503 for IO error*/ + reason = SalReasonIOError; + } + sal_error_info_set(&op->error_info, reason, "SIP", status_code,reason_phrase,NULL); + op->root->callbacks.subscribe_response(op,sss, will_retry); + }else if (status_code==0){ + op->root->callbacks.on_expire(op); + } + +} + +int SalSubscribeOp::subscribe(const char *from, const char *to, const char *eventname, int expires, const SalBodyHandler *body_handler) { + belle_sip_request_t *req=NULL; + + if (from) + set_from(from); + if (to) + set_to(to); + + if (!this->dialog){ + fill_cbs(); + req=build_request("SUBSCRIBE"); + if( req == NULL ) { + return -1; + } + set_event(eventname); + belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(this->event)); + belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(belle_sip_header_expires_create(expires))); + belle_sip_message_set_body_handler(BELLE_SIP_MESSAGE(req), BELLE_SIP_BODY_HANDLER(body_handler)); + return send_and_create_refresher(req,expires,subscribe_refresher_listener_cb); + }else if (this->refresher){ + const belle_sip_transaction_t *tr=(const belle_sip_transaction_t*) belle_sip_refresher_get_transaction(this->refresher); + belle_sip_request_t *last_req=belle_sip_transaction_get_request(tr); + /* modify last request to update body*/ + belle_sip_message_set_body_handler(BELLE_SIP_MESSAGE(last_req), BELLE_SIP_BODY_HANDLER(body_handler)); + return belle_sip_refresher_refresh(this->refresher,expires); + } + ms_warning("sal_subscribe(): no dialog and no refresher ?"); + return -1; +} + +int SalSubscribeOp::accept() { + belle_sip_request_t* req=belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(this->pending_server_trans)); + belle_sip_header_expires_t* expires = belle_sip_message_get_header_by_type(req,belle_sip_header_expires_t); + belle_sip_response_t* resp = create_response_from_request(req,200); + belle_sip_message_add_header(BELLE_SIP_MESSAGE(resp),BELLE_SIP_HEADER(expires)); + belle_sip_server_transaction_send_response(this->pending_server_trans,resp); + return 0; +} + +int SalSubscribeOp::decline(SalReason reason) { + belle_sip_response_t* resp = belle_sip_response_create_from_request(belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(this->pending_server_trans)), + to_sip_code(reason)); + belle_sip_server_transaction_send_response(this->pending_server_trans,resp); + return 0; +} + +int SalSubscribeOp::notify_pending_state() { + + if (this->dialog != NULL && this->pending_server_trans) { + belle_sip_request_t* notify; + belle_sip_header_subscription_state_t* sub_state; + ms_message("Sending NOTIFY with subscription state pending for op [%p]", this); + if (!(notify=belle_sip_dialog_create_request(this->dialog,"NOTIFY"))) { + ms_error("Cannot create NOTIFY on op [%p]", this); + return -1; + } + if (this->event) belle_sip_message_add_header(BELLE_SIP_MESSAGE(notify),BELLE_SIP_HEADER(this->event)); + sub_state=belle_sip_header_subscription_state_new(); + belle_sip_header_subscription_state_set_state(sub_state,BELLE_SIP_SUBSCRIPTION_STATE_PENDING); + belle_sip_message_add_header(BELLE_SIP_MESSAGE(notify), BELLE_SIP_HEADER(sub_state)); + return send_request(notify); + } else { + ms_warning("NOTIFY with subscription state pending for op [%p] not implemented in this case (either dialog pending trans does not exist", this); + } + + return 0; +} + +int SalSubscribeOp::notify(const SalBodyHandler *body_handler) { + belle_sip_request_t* notify; + + if (this->dialog){ + if (!(notify=belle_sip_dialog_create_queued_request(this->dialog,"NOTIFY"))) return -1; + }else{ + fill_cbs(); + notify = build_request("NOTIFY"); + } + + if (this->event) belle_sip_message_add_header(BELLE_SIP_MESSAGE(notify),BELLE_SIP_HEADER(this->event)); + + belle_sip_message_add_header(BELLE_SIP_MESSAGE(notify) + , this->dialog ? + BELLE_SIP_HEADER(belle_sip_header_subscription_state_create(BELLE_SIP_SUBSCRIPTION_STATE_ACTIVE,600)) : + BELLE_SIP_HEADER(belle_sip_header_subscription_state_create(BELLE_SIP_SUBSCRIPTION_STATE_TERMINATED,0)) + ); + belle_sip_message_set_body_handler(BELLE_SIP_MESSAGE(notify), BELLE_SIP_BODY_HANDLER(body_handler)); + return send_request(notify); +} + +int SalSubscribeOp::close_notify() { + belle_sip_request_t* notify; + if (!this->dialog) return -1; + if (!(notify=belle_sip_dialog_create_queued_request(this->dialog,"NOTIFY"))) return -1; + if (this->event) belle_sip_message_add_header(BELLE_SIP_MESSAGE(notify),BELLE_SIP_HEADER(this->event)); + belle_sip_message_add_header(BELLE_SIP_MESSAGE(notify) + ,BELLE_SIP_HEADER(belle_sip_header_subscription_state_create(BELLE_SIP_SUBSCRIPTION_STATE_TERMINATED,-1))); + return send_request(notify); +} + +void SalPublishOp::publish_response_event_cb(void *userctx, const belle_sip_response_event_t *event) { + SalPublishOp *op=(SalPublishOp *)userctx; + op->set_error_info_from_response(belle_sip_response_event_get_response(event)); + if (op->error_info.protocol_code>=200){ + op->root->callbacks.on_publish_response(op); + } +} + +void SalPublishOp::fill_cbs() { + static belle_sip_listener_callbacks_t op_publish_callbacks={0}; + if (op_publish_callbacks.process_response_event==NULL){ + op_publish_callbacks.process_response_event=publish_response_event_cb; + } + + this->callbacks=&op_publish_callbacks; + this->type=Type::Publish; +} + +void SalPublishOp::publish_refresher_listener_cb (belle_sip_refresher_t* refresher,void* user_pointer,unsigned int status_code,const char* reason_phrase, int will_retry) { + SalPublishOp * op = (SalPublishOp *)user_pointer; + const belle_sip_client_transaction_t* last_publish_trans=belle_sip_refresher_get_transaction(op->refresher); + belle_sip_response_t *response=belle_sip_transaction_get_response(BELLE_SIP_TRANSACTION(last_publish_trans)); + ms_message("Publish refresher [%i] reason [%s] for proxy [%s]",status_code,reason_phrase?reason_phrase:"none",op->get_proxy()); + if (status_code==0){ + op->root->callbacks.on_expire(op); + }else if (status_code>=200){ + belle_sip_header_t *sip_etag; + const char *sip_etag_string = NULL; + if (response && (sip_etag = belle_sip_message_get_header(BELLE_SIP_MESSAGE(response), "SIP-ETag"))) { + sip_etag_string = belle_sip_header_get_unparsed_value(sip_etag); + } + op->set_entity_tag(sip_etag_string); + sal_error_info_set(&op->error_info,SalReasonUnknown, "SIP", status_code,reason_phrase,NULL); + op->assign_recv_headers((belle_sip_message_t*)response); + op->root->callbacks.on_publish_response(op); + } +} + +int SalPublishOp::publish(const char *from, const char *to, const char *eventname, int expires, const SalBodyHandler *body_handler) { + belle_sip_request_t *req=NULL; + if(!this->refresher || !belle_sip_refresher_get_transaction(this->refresher)) { + if (from) + set_from(from); + if (to) + set_to(to); + + fill_cbs(); + req=build_request("PUBLISH"); + if( req == NULL ){ + return -1; + } + + if (get_entity_tag()) { + belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),belle_sip_header_create("SIP-If-Match", get_entity_tag())); + } + + if (get_contact_address()){ + belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(create_contact())); + } + belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),belle_sip_header_create("Event",eventname)); + belle_sip_message_set_body_handler(BELLE_SIP_MESSAGE(req), BELLE_SIP_BODY_HANDLER(body_handler)); + if (expires!=-1) + return send_and_create_refresher(req,expires,publish_refresher_listener_cb); + else return send_request(req); + } else { + /*update status*/ + const belle_sip_client_transaction_t* last_publish_trans=belle_sip_refresher_get_transaction(this->refresher); + belle_sip_request_t* last_publish=belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(last_publish_trans)); + /*update body*/ + if (expires == 0) { + belle_sip_message_set_body(BELLE_SIP_MESSAGE(last_publish), NULL, 0); + } else { + belle_sip_message_set_body_handler(BELLE_SIP_MESSAGE(last_publish), BELLE_SIP_BODY_HANDLER(body_handler)); + } + return belle_sip_refresher_refresh(this->refresher,expires==-1 ? BELLE_SIP_REFRESHER_REUSE_EXPIRES : expires); + } +} + +int SalPublishOp::unpublish() { + if (this->refresher){ + const belle_sip_transaction_t *tr=(const belle_sip_transaction_t*) belle_sip_refresher_get_transaction(this->refresher); + belle_sip_request_t *last_req=belle_sip_transaction_get_request(tr); + belle_sip_message_set_body(BELLE_SIP_MESSAGE(last_req), NULL, 0); + belle_sip_refresher_refresh(this->refresher,0); + return 0; + } + return -1; +} + +LINPHONE_END_NAMESPACE diff --git a/coreapi/sal/event_op.h b/coreapi/sal/event_op.h new file mode 100644 index 000000000..0084c508a --- /dev/null +++ b/coreapi/sal/event_op.h @@ -0,0 +1,74 @@ +/* +event_op.h +Copyright (C) 2017 Belledonne Communications + +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 _SAL_EVENT_OP_H_ +#define _SAL_EVENT_OP_H_ + +#include "sal_op.h" + +LINPHONE_BEGIN_NAMESPACE + +class SalEventOp: public SalOp { +public: + SalEventOp(Sal *sal): SalOp(sal) {} +}; + +class SalSubscribeOp: public SalEventOp { +public: + SalSubscribeOp(Sal *sal): SalEventOp(sal) {} + + int subscribe(const char *from, const char *to, const char *eventname, int expires, const SalBodyHandler *body_handler); + int unsubscribe() {return SalOp::unsubscribe();} + int accept(); + int decline(SalReason reason); + int notify_pending_state(); + int notify(const SalBodyHandler *body_handler); + int close_notify(); + +private: + virtual void fill_cbs() override; + void handle_notify(belle_sip_request_t *req, const char *eventname, SalBodyHandler* body_handler); + + static void subscribe_process_io_error_cb(void *user_ctx, const belle_sip_io_error_event_t *event); + static void subscribe_response_event_cb(void *op_base, const belle_sip_response_event_t *event); + static void subscribe_process_timeout_cb(void *user_ctx, const belle_sip_timeout_event_t *event); + static void subscribe_process_transaction_terminated_cb(void *user_ctx, const belle_sip_transaction_terminated_event_t *event) {} + static void subscribe_process_request_event_cb(void *op_base, const belle_sip_request_event_t *event); + static void subscribe_process_dialog_terminated_cb(void *ctx, const belle_sip_dialog_terminated_event_t *event); + static void _release_cb(SalOp *op_base); + static void subscribe_refresher_listener_cb (belle_sip_refresher_t* refresher,void* user_pointer,unsigned int status_code,const char* reason_phrase, int will_retry); +}; + +class SalPublishOp: public SalEventOp { +public: + SalPublishOp(Sal *sal): SalEventOp(sal) {} + + int publish(const char *from, const char *to, const char *eventname, int expires, const SalBodyHandler *body_handler); + int unpublish(); + +private: + virtual void fill_cbs() override; + + static void publish_response_event_cb(void *userctx, const belle_sip_response_event_t *event); + static void publish_refresher_listener_cb (belle_sip_refresher_t* refresher,void* user_pointer,unsigned int status_code,const char* reason_phrase, int will_retry); +}; + +LINPHONE_END_NAMESPACE + +#endif diff --git a/coreapi/sal/message_op.cpp b/coreapi/sal/message_op.cpp new file mode 100644 index 000000000..a97a088e0 --- /dev/null +++ b/coreapi/sal/message_op.cpp @@ -0,0 +1,88 @@ +#include "message_op.h" + +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +void SalMessageOp::process_error() { + if (this->dir == Dir::Outgoing) { + this->root->callbacks.message_delivery_update(this, SalMessageDeliveryFailed); + } else { + ms_warning("unexpected io error for incoming message on op [%p]", this); + } + this->state=State::Terminated; +} + +void SalMessageOp::process_io_error_cb(void *user_ctx, const belle_sip_io_error_event_t *event) { + SalMessageOp * op = (SalMessageOp *)user_ctx; + sal_error_info_set(&op->error_info,SalReasonIOError, "SIP", 503,"IO Error",NULL); + op->process_error(); +} + +void SalMessageOp::process_response_event_cb(void *op_base, const belle_sip_response_event_t *event) { + SalMessageOp * op = (SalMessageOp *)op_base; + int code = belle_sip_response_get_status_code(belle_sip_response_event_get_response(event)); + SalMessageDeliveryStatus status; + op->set_error_info_from_response(belle_sip_response_event_get_response(event)); + + if (code>=100 && code <200) + status=SalMessageDeliveryInProgress; + else if (code>=200 && code <300) + status=SalMessageDeliveryDone; + else + status=SalMessageDeliveryFailed; + + op->root->callbacks.message_delivery_update(op,status); +} + +void SalMessageOp::process_timeout_cb(void *user_ctx, const belle_sip_timeout_event_t *event) { + SalMessageOp * op=(SalMessageOp *)user_ctx; + sal_error_info_set(&op->error_info,SalReasonRequestTimeout, "SIP", 408,"Request timeout",NULL); + op->process_error(); +} + +void SalMessageOp::process_request_event_cb(void *op_base, const belle_sip_request_event_t *event) { + SalMessageOp * op = (SalMessageOp *)op_base; + op->process_incoming_message(event); +} + +void SalMessageOp::fill_cbs() { + static belle_sip_listener_callbacks_t op_message_callbacks = {0}; + if (op_message_callbacks.process_io_error==NULL) { + op_message_callbacks.process_io_error=process_io_error_cb; + op_message_callbacks.process_response_event=process_response_event_cb; + op_message_callbacks.process_timeout=process_timeout_cb; + op_message_callbacks.process_request_event=process_request_event_cb; + } + this->callbacks=&op_message_callbacks; + this->type=Type::Message; +} + +void SalMessageOpInterface::prepare_message_request(belle_sip_request_t *req, const char* content_type, const char *msg, const char *peer_uri) { + char content_type_raw[256]; + size_t content_length = msg?strlen(msg):0; + time_t curtime = ms_time(NULL); + snprintf(content_type_raw,sizeof(content_type_raw),BELLE_SIP_CONTENT_TYPE ": %s",content_type); + belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(belle_sip_header_content_type_parse(content_type_raw))); + belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(belle_sip_header_content_length_create(content_length))); + belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(belle_sip_header_date_create_from_time(&curtime))); + if (msg){ + /*don't call set_body() with null argument because it resets content type and content length*/ + belle_sip_message_set_body(BELLE_SIP_MESSAGE(req), msg, content_length); + } +} + +int SalMessageOp::send_message(const char *from, const char *to, const char* content_type, const char *msg, const char *peer_uri) { + fill_cbs(); + if (from) set_from(from); + if (to) set_to(to); + this->dir=Dir::Outgoing; + + belle_sip_request_t* req=build_request("MESSAGE"); + if (req == NULL ) return -1; + if (get_contact_address()) belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(create_contact())); + prepare_message_request(req, content_type, msg, peer_uri); + return send_request(req); +} + +LINPHONE_END_NAMESPACE diff --git a/coreapi/sal/message_op.h b/coreapi/sal/message_op.h new file mode 100644 index 000000000..22d7e3d7f --- /dev/null +++ b/coreapi/sal/message_op.h @@ -0,0 +1,47 @@ +/* +message_op.h +Copyright (C) 2017 Belledonne Communications + +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 _SAL_MASSAGE_OP_H_ +#define _SAL_MASSAGE_OP_H_ + +#include "sal_op.h" +#include "message_op_interface.h" + +LINPHONE_BEGIN_NAMESPACE + +class SalMessageOp: public SalOp, public SalMessageOpInterface { +public: + SalMessageOp(Sal *sal): SalOp(sal) {} + + int send_message(const char *from, const char *to, const char* content_type, const char *msg, const char *peer_uri) override; + int reply(SalReason reason) override {return SalOp::reply_message(reason);} + +private: + virtual void fill_cbs() override; + void process_error(); + + static void process_io_error_cb(void *user_ctx, const belle_sip_io_error_event_t *event); + static void process_response_event_cb(void *op_base, const belle_sip_response_event_t *event); + static void process_timeout_cb(void *user_ctx, const belle_sip_timeout_event_t *event); + static void process_request_event_cb(void *op_base, const belle_sip_request_event_t *event); +}; + +LINPHONE_END_NAMESPACE + +#endif diff --git a/coreapi/sal/message_op_interface.h b/coreapi/sal/message_op_interface.h new file mode 100644 index 000000000..1e5abee82 --- /dev/null +++ b/coreapi/sal/message_op_interface.h @@ -0,0 +1,38 @@ +/* +message_op_interface.h +Copyright (C) 2017 Belledonne Communications + +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 _SAL_MESSAGE_OP_INTERFACE_H_ +#define _SAL_MESSAGE_OP_INTERFACE_H_ + +LINPHONE_BEGIN_NAMESPACE + +class SalMessageOpInterface { +public: + virtual ~SalMessageOpInterface() = default; + int send_message(const char *from, const char *to, const char *msg) {return send_message(from,to,"text/plain",msg, nullptr);} + virtual int send_message(const char *from, const char *to, const char* content_type, const char *msg, const char *peer_uri) = 0; + virtual int reply(SalReason reason) = 0; + +protected: + void prepare_message_request(belle_sip_request_t *req, const char* content_type, const char *msg, const char *peer_uri); +}; + +LINPHONE_END_NAMESPACE + +#endif diff --git a/coreapi/bellesip_sal/sal_op_presence.c b/coreapi/sal/presence_op.cpp similarity index 59% rename from coreapi/bellesip_sal/sal_op_presence.c rename to coreapi/sal/presence_op.cpp index ba0624bfb..853017160 100644 --- a/coreapi/bellesip_sal/sal_op_presence.c +++ b/coreapi/sal/presence_op.cpp @@ -1,53 +1,11 @@ -/* -linphone -Copyright (C) 2012 Belledonne Communications, Grenoble, France +#include "presence_op.h" -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. +using namespace std; -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. +LINPHONE_BEGIN_NAMESPACE -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 "sal_impl.h" - - -void sal_add_presence_info(SalOp *op, belle_sip_message_t *notify, SalPresenceModel *presence) { - char *contact_info; - char *content = NULL; - size_t content_length; - - if (presence){ - belle_sip_header_from_t *from=belle_sip_message_get_header_by_type(notify,belle_sip_header_from_t); - contact_info=belle_sip_uri_to_string(belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(from))); - op->base.root->callbacks.convert_presence_to_xml_requested(op, presence, contact_info, &content); - belle_sip_free(contact_info); - if (content == NULL) return; - } - - belle_sip_message_remove_header(BELLE_SIP_MESSAGE(notify),BELLE_SIP_CONTENT_TYPE); - belle_sip_message_remove_header(BELLE_SIP_MESSAGE(notify),BELLE_SIP_CONTENT_LENGTH); - belle_sip_message_set_body(BELLE_SIP_MESSAGE(notify),NULL,0); - - if (content){ - belle_sip_message_add_header(BELLE_SIP_MESSAGE(notify) - ,BELLE_SIP_HEADER(belle_sip_header_content_type_create("application","pidf+xml"))); - belle_sip_message_add_header(BELLE_SIP_MESSAGE(notify) - ,BELLE_SIP_HEADER(belle_sip_header_content_length_create(content_length=strlen(content)))); - belle_sip_message_set_body(BELLE_SIP_MESSAGE(notify),content,content_length); - ms_free(content); - } -} - -static void presence_process_io_error(void *user_ctx, const belle_sip_io_error_event_t *event){ - SalOp* op = (SalOp*)user_ctx; +void SalPresenceOp::presence_process_io_error_cb(void *user_ctx, const belle_sip_io_error_event_t *event) { + SalPresenceOp * op = (SalPresenceOp *)user_ctx; belle_sip_request_t* request; belle_sip_client_transaction_t* client_transaction = NULL; @@ -65,55 +23,43 @@ static void presence_process_io_error(void *user_ctx, const belle_sip_io_error_e ms_warning("presence_process_io_error() refresher is present, should not happen"); return; } - ms_message("subscription to [%s] io error",sal_op_get_to(op)); + ms_message("subscription to [%s] io error",op->get_to()); if (!op->op_released){ - op->base.root->callbacks.notify_presence(op,SalSubscribeTerminated, NULL,NULL); /*NULL = offline*/ + op->root->callbacks.notify_presence(op,SalSubscribeTerminated, NULL,NULL); /*NULL = offline*/ } } } -static void presence_process_dialog_terminated(void *ctx, const belle_sip_dialog_terminated_event_t *event) { - SalOp* op= (SalOp*)ctx; - if (op->dialog && belle_sip_dialog_is_server(op->dialog)) { - ms_message("Incoming subscribtion from [%s] terminated",sal_op_get_from(op)); - if (!op->op_released){ - op->base.root->callbacks.subscribe_presence_closed(op, sal_op_get_from(op)); - } - set_or_update_dialog(op, NULL); - }/* else client dialog is managed by refresher*/ -} - -static void presence_refresher_listener(belle_sip_refresher_t* refresher, void* user_pointer, unsigned int status_code, const char* reason_phrase, int will_retry){ - SalOp* op = (SalOp*)user_pointer; +void SalPresenceOp::presence_refresher_listener_cb(belle_sip_refresher_t* refresher, void* user_pointer, unsigned int status_code, const char* reason_phrase, int will_retry) { + SalPresenceOp * op = (SalPresenceOp *)user_pointer; if (status_code >= 300) { ms_message("The SUBSCRIBE dialog no longer works. Let's restart a new one."); belle_sip_refresher_stop(op->refresher); if (op->dialog) { /*delete previous dialog if any*/ - set_or_update_dialog(op, NULL); + op->set_or_update_dialog(NULL); } - if (sal_op_get_contact_address(op)) { + if (op->get_contact_address()) { /*contact is also probably not good*/ - SalAddress* contact=sal_address_clone(sal_op_get_contact_address(op)); + SalAddress* contact=sal_address_clone(op->get_contact_address()); sal_address_set_port(contact,-1); sal_address_set_domain(contact,NULL); - sal_op_set_contact_address(op,contact); + op->set_contact_address(contact); sal_address_destroy(contact); } /*send a new SUBSCRIBE, that will attempt to establish a new dialog*/ - sal_subscribe_presence(op,NULL,NULL,-1); + op->subscribe(NULL,NULL,-1); } if (status_code == 0 || status_code == 503){ /*timeout or io error: the remote doesn't seem reachable.*/ if (!op->op_released){ - op->base.root->callbacks.notify_presence(op,SalSubscribeActive, NULL,NULL); /*NULL = offline*/ + op->root->callbacks.notify_presence(op,SalSubscribeActive, NULL,NULL); /*NULL = offline*/ } } } - -static void presence_response_event(void *op_base, const belle_sip_response_event_t *event){ - SalOp* op = (SalOp*)op_base; +void SalPresenceOp::presence_response_event_cb(void *op_base, const belle_sip_response_event_t *event) { + SalPresenceOp * op = (SalPresenceOp *)op_base; belle_sip_dialog_state_t dialog_state; belle_sip_client_transaction_t* client_transaction = belle_sip_response_event_get_client_transaction(event); belle_sip_response_t* response=belle_sip_response_event_get_response(event); @@ -121,18 +67,18 @@ static void presence_response_event(void *op_base, const belle_sip_response_even int code = belle_sip_response_get_status_code(response); belle_sip_header_expires_t* expires; - sal_op_set_error_info_from_response(op,response); + op->set_error_info_from_response(response); if (code>=300) { if (strcmp("SUBSCRIBE",belle_sip_request_get_method(request))==0){ - ms_message("subscription to [%s] rejected",sal_op_get_to(op)); + ms_message("subscription to [%s] rejected",op->get_to()); if (!op->op_released){ - op->base.root->callbacks.notify_presence(op,SalSubscribeTerminated, NULL,NULL); /*NULL = offline*/ + op->root->callbacks.notify_presence(op,SalSubscribeTerminated, NULL,NULL); /*NULL = offline*/ } return; } } - set_or_update_dialog(reinterpret_cast(op_base),belle_sip_response_event_get_dialog(event)); + op->set_or_update_dialog(belle_sip_response_event_get_dialog(event)); if (!op->dialog) { ms_message("presence op [%p] receive out of dialog answer [%i]",op,code); return; @@ -155,8 +101,8 @@ static void presence_response_event(void *op_base, const belle_sip_response_even } if ((expires != NULL) && (belle_sip_header_expires_get_expires(expires) > 0)) { op->refresher=belle_sip_client_transaction_create_refresher(client_transaction); - belle_sip_refresher_set_listener(op->refresher,presence_refresher_listener,op); - belle_sip_refresher_set_realm(op->refresher,op->base.realm); + belle_sip_refresher_set_listener(op->refresher,presence_refresher_listener_cb,op); + belle_sip_refresher_set_realm(op->refresher,op->realm); } } break; @@ -168,8 +114,8 @@ static void presence_response_event(void *op_base, const belle_sip_response_even } } -static void presence_process_timeout(void *user_ctx, const belle_sip_timeout_event_t *event) { - SalOp* op = (SalOp*)user_ctx; +void SalPresenceOp::presence_process_timeout_cb(void *user_ctx, const belle_sip_timeout_event_t *event) { + SalPresenceOp * op = (SalPresenceOp *)user_ctx; belle_sip_client_transaction_t* client_transaction = belle_sip_timeout_event_get_client_transaction(event); belle_sip_request_t* request; @@ -178,18 +124,18 @@ static void presence_process_timeout(void *user_ctx, const belle_sip_timeout_eve request = belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(client_transaction)); if (strcmp("SUBSCRIBE",belle_sip_request_get_method(request))==0){ - ms_message("subscription to [%s] timeout",sal_op_get_to(op)); + ms_message("subscription to [%s] timeout",op->get_to()); if (!op->op_released){ - op->base.root->callbacks.notify_presence(op,SalSubscribeTerminated, NULL,NULL); /*NULL = offline*/ + op->root->callbacks.notify_presence(op,SalSubscribeTerminated, NULL,NULL); /*NULL = offline*/ } } } -static void presence_process_transaction_terminated(void *user_ctx, const belle_sip_transaction_terminated_event_t *event) { +void SalPresenceOp::presence_process_transaction_terminated_cb(void *user_ctx, const belle_sip_transaction_terminated_event_t *event) { ms_message("presence_process_transaction_terminated not implemented yet"); } -static SalPresenceModel * process_presence_notification(SalOp *op, belle_sip_request_t *req) { +SalPresenceModel *SalPresenceOp::process_presence_notification(belle_sip_request_t *req) { belle_sip_header_content_type_t *content_type = belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req), belle_sip_header_content_type_t); belle_sip_header_content_length_t *content_length = belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req), belle_sip_header_content_length_t); const char *body = belle_sip_message_get_body(BELLE_SIP_MESSAGE(req)); @@ -201,8 +147,8 @@ static SalPresenceModel * process_presence_notification(SalOp *op, belle_sip_req return NULL; if (body==NULL) return NULL; - if (!op->op_released){ - op->base.root->callbacks.parse_presence_requested(op, + if (!this->op_released){ + this->root->callbacks.parse_presence_requested(this, belle_sip_header_content_type_get_type(content_type), belle_sip_header_content_type_get_subtype(content_type), body, @@ -212,9 +158,9 @@ static SalPresenceModel * process_presence_notification(SalOp *op, belle_sip_req return result; } -static void handle_notify(SalOp *op, belle_sip_request_t *req, belle_sip_dialog_t *dialog){ +void SalPresenceOp::handle_notify(belle_sip_request_t *req, belle_sip_dialog_t *dialog) { belle_sip_response_t* resp=NULL; - belle_sip_server_transaction_t* server_transaction=op->pending_server_trans; + belle_sip_server_transaction_t* server_transaction= this->pending_server_trans; belle_sip_header_subscription_state_t* subscription_state_header=belle_sip_message_get_header_by_type(req,belle_sip_header_subscription_state_t); SalSubscribeStatus sub_state; @@ -222,35 +168,35 @@ static void handle_notify(SalOp *op, belle_sip_request_t *req, belle_sip_dialog_ SalPresenceModel *presence_model = NULL; const char* body = belle_sip_message_get_body(BELLE_SIP_MESSAGE(req)); - if (op->dialog !=NULL && dialog != op->dialog){ - ms_warning("Receiving a NOTIFY from a dialog we haven't stored (op->dialog=%p dialog=%p)", op->dialog, dialog); + if (this->dialog !=NULL && dialog != this->dialog){ + ms_warning("Receiving a NOTIFY from a dialog we haven't stored (op->dialog=%p dialog=%p)", this->dialog, dialog); } if (!subscription_state_header || strcasecmp(BELLE_SIP_SUBSCRIPTION_STATE_TERMINATED,belle_sip_header_subscription_state_get_state(subscription_state_header)) ==0) { sub_state=SalSubscribeTerminated; - ms_message("Outgoing subscription terminated by remote [%s]",sal_op_get_to(op)); + ms_message("Outgoing subscription terminated by remote [%s]",get_to()); } else { sub_state=belle_sip_message_get_subscription_state(BELLE_SIP_MESSAGE(req)); } - presence_model = process_presence_notification(op, req); + presence_model = process_presence_notification(req); if (presence_model != NULL || body==NULL) { /* Presence notification body parsed successfully. */ - resp = sal_op_create_response_from_request(op, req, 200); /*create first because the op may be destroyed by notify_presence */ - if (!op->op_released){ - op->base.root->callbacks.notify_presence(op, sub_state, presence_model, NULL); + resp = create_response_from_request(req, 200); /*create first because the op may be destroyed by notify_presence */ + if (!this->op_released){ + this->root->callbacks.notify_presence(this, sub_state, presence_model, NULL); } } else if (body){ /* Formatting error in presence notification body. */ ms_warning("Wrongly formatted presence document."); - resp = sal_op_create_response_from_request(op, req, 488); + resp = create_response_from_request(req, 488); } if (resp) belle_sip_server_transaction_send_response(server_transaction,resp); } } -static void presence_process_request_event(void *op_base, const belle_sip_request_event_t *event) { - SalOp* op = (SalOp*)op_base; - belle_sip_server_transaction_t* server_transaction = belle_sip_provider_create_server_transaction(op->base.root->prov,belle_sip_request_event_get_request(event)); +void SalPresenceOp::presence_process_request_event_cb(void *op_base, const belle_sip_request_event_t *event) { + SalPresenceOp * op = (SalPresenceOp *)op_base; + belle_sip_server_transaction_t* server_transaction = belle_sip_provider_create_server_transaction(op->root->prov,belle_sip_request_event_get_request(event)); belle_sip_request_t* req = belle_sip_request_event_get_request(event); belle_sip_dialog_state_t dialog_state; belle_sip_response_t* resp; @@ -263,9 +209,9 @@ static void presence_process_request_event(void *op_base, const belle_sip_reques if (event_header==NULL){ ms_warning("No event header in incoming SUBSCRIBE."); - resp=sal_op_create_response_from_request(op,req,400); + resp=op->create_response_from_request(req,400); belle_sip_server_transaction_send_response(server_transaction,resp); - if (!op->dialog) sal_op_release(op); + if (!op->dialog) op->release(); return; } if (op->event==NULL) { @@ -276,21 +222,21 @@ static void presence_process_request_event(void *op_base, const belle_sip_reques if (!op->dialog) { if (strcmp(method,"SUBSCRIBE")==0){ - belle_sip_dialog_t *dialog = belle_sip_provider_create_dialog(op->base.root->prov,BELLE_SIP_TRANSACTION(server_transaction)); + belle_sip_dialog_t *dialog = belle_sip_provider_create_dialog(op->root->prov,BELLE_SIP_TRANSACTION(server_transaction)); if (!dialog){ - resp=sal_op_create_response_from_request(op,req,481); + resp=op->create_response_from_request(req,481); belle_sip_server_transaction_send_response(server_transaction,resp); - sal_op_release(op); + op->release(); return; } - set_or_update_dialog(op, dialog); - ms_message("new incoming subscription from [%s] to [%s]",sal_op_get_from(op),sal_op_get_to(op)); + op->set_or_update_dialog(dialog); + ms_message("new incoming subscription from [%s] to [%s]",op->get_from(),op->get_to()); }else if (strcmp(method,"NOTIFY")==0 && belle_sip_request_event_get_dialog(event)) { /*special case of dialog created by notify matching subscribe*/ - set_or_update_dialog(op, belle_sip_request_event_get_dialog(event)); + op->set_or_update_dialog(belle_sip_request_event_get_dialog(event)); } else {/* this is a NOTIFY */ ms_message("Receiving out of dialog notify"); - handle_notify(op, req, belle_sip_request_event_get_dialog(event)); + op->handle_notify(req, belle_sip_request_event_get_dialog(event)); return; } } @@ -298,9 +244,9 @@ static void presence_process_request_event(void *op_base, const belle_sip_reques switch(dialog_state) { case BELLE_SIP_DIALOG_NULL: { if (strcmp("NOTIFY",method)==0) { - handle_notify(op, req, belle_sip_request_event_get_dialog(event)); + op->handle_notify(req, belle_sip_request_event_get_dialog(event)); } else if (strcmp("SUBSCRIBE",method)==0) { - op->base.root->callbacks.subscribe_presence_received(op,sal_op_get_from(op)); + op->root->callbacks.subscribe_presence_received(op,op->get_from()); } break; } @@ -310,12 +256,12 @@ static void presence_process_request_event(void *op_base, const belle_sip_reques case BELLE_SIP_DIALOG_CONFIRMED: if (strcmp("NOTIFY",method)==0) { - handle_notify(op, req, belle_sip_request_event_get_dialog(event)); + op->handle_notify(req, belle_sip_request_event_get_dialog(event)); } else if (strcmp("SUBSCRIBE",method)==0) { /*either a refresh or an unsubscribe. If it is a refresh there is nothing to notify to the app. If it is an unSUBSCRIBE, then the dialog will be terminated shortly, and this will be notified to the app through the dialog_terminated callback.*/ - resp=sal_op_create_response_from_request(op,req,200); + resp=op->create_response_from_request(req,200); belle_sip_server_transaction_send_response(server_transaction,resp); } break; @@ -325,117 +271,163 @@ static void presence_process_request_event(void *op_base, const belle_sip_reques } } -static belle_sip_listener_callbacks_t op_presence_callbacks={0}; +void SalPresenceOp::presence_process_dialog_terminated_cb(void *ctx, const belle_sip_dialog_terminated_event_t *event) { + SalPresenceOp * op= (SalPresenceOp *)ctx; + if (op->dialog && belle_sip_dialog_is_server(op->dialog)) { + ms_message("Incoming subscribtion from [%s] terminated",op->get_from()); + if (!op->op_released){ + op->root->callbacks.subscribe_presence_closed(op, op->get_from()); + } + op->set_or_update_dialog(NULL); + }/* else client dialog is managed by refresher*/ +} -/*Invoke when sal_op_release is called by upper layer*/ -static void sal_op_release_cb(struct SalOpBase* op_base) { - SalOp *op =(SalOp*)op_base; +void SalPresenceOp::_release_cb(SalOp *op_base) { + SalPresenceOp *op =(SalPresenceOp *)op_base; if(op->refresher) { belle_sip_refresher_stop(op->refresher); belle_sip_object_unref(op->refresher); op->refresher=NULL; - set_or_update_dialog(op,NULL); /*only if we have refresher. else dialog terminated event will remove association*/ + op->set_or_update_dialog(NULL); /*only if we have refresher. else dialog terminated event will remove association*/ } - } -void sal_op_presence_fill_cbs(SalOp*op) { + +void SalPresenceOp::fill_cbs() { + static belle_sip_listener_callbacks_t op_presence_callbacks={0}; if (op_presence_callbacks.process_request_event==NULL){ - op_presence_callbacks.process_io_error=presence_process_io_error; - op_presence_callbacks.process_response_event=presence_response_event; - op_presence_callbacks.process_timeout=presence_process_timeout; - op_presence_callbacks.process_transaction_terminated=presence_process_transaction_terminated; - op_presence_callbacks.process_request_event=presence_process_request_event; - op_presence_callbacks.process_dialog_terminated=presence_process_dialog_terminated; + op_presence_callbacks.process_io_error=presence_process_io_error_cb; + op_presence_callbacks.process_response_event=presence_response_event_cb; + op_presence_callbacks.process_timeout= presence_process_timeout_cb; + op_presence_callbacks.process_transaction_terminated=presence_process_transaction_terminated_cb; + op_presence_callbacks.process_request_event=presence_process_request_event_cb; + op_presence_callbacks.process_dialog_terminated=presence_process_dialog_terminated_cb; } - op->callbacks=&op_presence_callbacks; - op->type=SalOpPresence; - op->base.release_cb=sal_op_release_cb; + this->callbacks=&op_presence_callbacks; + this->type=Type::Presence; + this->release_cb=_release_cb; } - -/*presence Subscribe/notify*/ -int sal_subscribe_presence(SalOp *op, const char *from, const char *to, int expires){ +int SalPresenceOp::subscribe(const char *from, const char *to, int expires) { belle_sip_request_t *req=NULL; if (from) - sal_op_set_from(op,from); + set_from(from); if (to) - sal_op_set_to(op,to); + set_to(to); - sal_op_presence_fill_cbs(op); + fill_cbs(); if (expires==-1){ - if (op->refresher){ - expires=belle_sip_refresher_get_expires(op->refresher); - belle_sip_object_unref(op->refresher); - op->refresher=NULL; + if (this->refresher){ + expires=belle_sip_refresher_get_expires(this->refresher); + belle_sip_object_unref(this->refresher); + this->refresher=NULL; }else{ ms_error("sal_subscribe_presence(): cannot guess expires from previous refresher."); return -1; } } - if (!op->event){ - op->event=belle_sip_header_event_create("presence"); - belle_sip_object_ref(op->event); + if (!this->event){ + this->event=belle_sip_header_event_create("presence"); + belle_sip_object_ref(this->event); } - belle_sip_parameters_remove_parameter(BELLE_SIP_PARAMETERS(op->base.from_address),"tag"); - belle_sip_parameters_remove_parameter(BELLE_SIP_PARAMETERS(op->base.to_address),"tag"); - req=sal_op_build_request(op,"SUBSCRIBE"); + belle_sip_parameters_remove_parameter(BELLE_SIP_PARAMETERS(this->from_address),"tag"); + belle_sip_parameters_remove_parameter(BELLE_SIP_PARAMETERS(this->to_address),"tag"); + req=build_request("SUBSCRIBE"); if( req ){ - belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(op->event)); + belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(this->event)); belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(belle_sip_header_expires_create(expires))); } - return sal_op_send_request(op,req); + return send_request(req); } +int SalPresenceOp::check_dialog_state() { + belle_sip_dialog_state_t state= this->dialog?belle_sip_dialog_get_state(this->dialog): BELLE_SIP_DIALOG_NULL; + if (state != BELLE_SIP_DIALOG_CONFIRMED) { + ms_warning("Cannot notify presence for op [%p] because dialog in state [%s]", this, belle_sip_dialog_state_to_string(state)); + return -1; + } else + return 0; +} -static belle_sip_request_t *create_presence_notify(SalOp *op){ - belle_sip_request_t* notify=belle_sip_dialog_create_queued_request(op->dialog,"NOTIFY"); +belle_sip_request_t *SalPresenceOp::create_presence_notify() { + belle_sip_request_t* notify=belle_sip_dialog_create_queued_request(this->dialog,"NOTIFY"); if (!notify) return NULL; belle_sip_message_add_header((belle_sip_message_t*)notify,belle_sip_header_create("Event","presence")); return notify; } -static int sal_op_check_dialog_state(SalOp *op) { - belle_sip_dialog_state_t state=op->dialog?belle_sip_dialog_get_state(op->dialog): BELLE_SIP_DIALOG_NULL; - if (state != BELLE_SIP_DIALOG_CONFIRMED) { - ms_warning("Cannot notify presence for op [%p] because dialog in state [%s]",op, belle_sip_dialog_state_to_string(state)); - return -1; - } else - return 0; +void SalPresenceOp::add_presence_info(belle_sip_message_t *notify, SalPresenceModel *presence) { + char *contact_info; + char *content = NULL; + size_t content_length; + + if (presence){ + belle_sip_header_from_t *from=belle_sip_message_get_header_by_type(notify,belle_sip_header_from_t); + contact_info=belle_sip_uri_to_string(belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(from))); + this->root->callbacks.convert_presence_to_xml_requested(this, presence, contact_info, &content); + belle_sip_free(contact_info); + if (content == NULL) return; + } + + belle_sip_message_remove_header(BELLE_SIP_MESSAGE(notify),BELLE_SIP_CONTENT_TYPE); + belle_sip_message_remove_header(BELLE_SIP_MESSAGE(notify),BELLE_SIP_CONTENT_LENGTH); + belle_sip_message_set_body(BELLE_SIP_MESSAGE(notify),NULL,0); + + if (content){ + belle_sip_message_add_header(BELLE_SIP_MESSAGE(notify) + ,BELLE_SIP_HEADER(belle_sip_header_content_type_create("application","pidf+xml"))); + belle_sip_message_add_header(BELLE_SIP_MESSAGE(notify) + ,BELLE_SIP_HEADER(belle_sip_header_content_length_create(content_length=strlen(content)))); + belle_sip_message_set_body(BELLE_SIP_MESSAGE(notify),content,content_length); + ms_free(content); + } } -int sal_notify_presence(SalOp *op, SalPresenceModel *presence){ +int SalPresenceOp::notify_presence(SalPresenceModel *presence) { belle_sip_request_t* notify=NULL; - if (sal_op_check_dialog_state(op)) { + if (check_dialog_state()) { return -1; } - notify=create_presence_notify(op); + notify=create_presence_notify(); if (!notify) return-1; - sal_add_presence_info(op,BELLE_SIP_MESSAGE(notify),presence); /*FIXME, what about expires ??*/ + add_presence_info(BELLE_SIP_MESSAGE(notify),presence); /*FIXME, what about expires ??*/ belle_sip_message_add_header(BELLE_SIP_MESSAGE(notify) ,BELLE_SIP_HEADER(belle_sip_header_subscription_state_create(BELLE_SIP_SUBSCRIPTION_STATE_ACTIVE,600))); - return sal_op_send_request(op,notify); + return send_request(notify); } -int sal_notify_presence_close(SalOp *op){ +int SalPresenceOp::notify_presence_close() { belle_sip_request_t* notify=NULL; int status; - if (sal_op_check_dialog_state(op)) { + if (check_dialog_state()) { return -1; } - notify=create_presence_notify(op); + notify=create_presence_notify(); if (!notify) return-1; - sal_add_presence_info(op,BELLE_SIP_MESSAGE(notify),NULL); /*FIXME, what about expires ??*/ + add_presence_info(BELLE_SIP_MESSAGE(notify),NULL); /*FIXME, what about expires ??*/ belle_sip_message_add_header(BELLE_SIP_MESSAGE(notify) ,BELLE_SIP_HEADER(belle_sip_header_subscription_state_create(BELLE_SIP_SUBSCRIPTION_STATE_TERMINATED,-1))); - status = sal_op_send_request(op,notify); - set_or_update_dialog(op,NULL); /*because we may be chalanged for the notify, so we must release dialog right now*/ + status = send_request(notify); + set_or_update_dialog(NULL); /*because we may be chalanged for the notify, so we must release dialog right now*/ return status; } +SalSubscribeStatus SalPresenceOp::belle_sip_message_get_subscription_state(const belle_sip_message_t *msg) { + belle_sip_header_subscription_state_t* subscription_state_header=belle_sip_message_get_header_by_type(msg,belle_sip_header_subscription_state_t); + SalSubscribeStatus sss=SalSubscribeNone; + if (subscription_state_header){ + if (strcmp(belle_sip_header_subscription_state_get_state(subscription_state_header),BELLE_SIP_SUBSCRIPTION_STATE_TERMINATED)==0) + sss=SalSubscribeTerminated; + else if (strcmp(belle_sip_header_subscription_state_get_state(subscription_state_header),BELLE_SIP_SUBSCRIPTION_STATE_PENDING)==0) + sss=SalSubscribePending; + else if (strcmp(belle_sip_header_subscription_state_get_state(subscription_state_header),BELLE_SIP_SUBSCRIPTION_STATE_ACTIVE)==0) + sss=SalSubscribeActive; + } + return sss; +} - +LINPHONE_END_NAMESPACE diff --git a/coreapi/sal/presence_op.h b/coreapi/sal/presence_op.h new file mode 100644 index 000000000..f8eebd9e7 --- /dev/null +++ b/coreapi/sal/presence_op.h @@ -0,0 +1,58 @@ +/* +presence_op.h +Copyright (C) 2017 Belledonne Communications + +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 _SAL_PRESENCE_OP_H_ +#define _SAL_PRESENCE_OP_H_ + +#include "event_op.h" + +LINPHONE_BEGIN_NAMESPACE + +class SalPresenceOp: public SalSubscribeOp { +public: + SalPresenceOp(Sal *sal): SalSubscribeOp(sal) {} + + int subscribe(const char *from, const char *to, int expires); + int unsubscribe() {return SalOp::unsubscribe();} + int notify_presence(SalPresenceModel *presence); + int notify_presence_close(); + +private: + virtual void fill_cbs() override; + void handle_notify(belle_sip_request_t *req, belle_sip_dialog_t *dialog); + SalPresenceModel * process_presence_notification(belle_sip_request_t *req); + int check_dialog_state(); + belle_sip_request_t *create_presence_notify(); + void add_presence_info(belle_sip_message_t *notify, SalPresenceModel *presence); + + static SalSubscribeStatus belle_sip_message_get_subscription_state(const belle_sip_message_t *msg); + + static void presence_process_io_error_cb(void *user_ctx, const belle_sip_io_error_event_t *event); + static void presence_response_event_cb(void *op_base, const belle_sip_response_event_t *event); + static void presence_refresher_listener_cb(belle_sip_refresher_t* refresher, void* user_pointer, unsigned int status_code, const char* reason_phrase, int will_retry); + static void presence_process_timeout_cb(void *user_ctx, const belle_sip_timeout_event_t *event); + static void presence_process_transaction_terminated_cb(void *user_ctx, const belle_sip_transaction_terminated_event_t *event); + static void presence_process_request_event_cb(void *op_base, const belle_sip_request_event_t *event); + static void presence_process_dialog_terminated_cb(void *ctx, const belle_sip_dialog_terminated_event_t *event); + static void _release_cb(SalOp *op_base); +}; + +LINPHONE_END_NAMESPACE + +#endif diff --git a/coreapi/bellesip_sal/sal_op_registration.c b/coreapi/sal/register_op.cpp similarity index 51% rename from coreapi/bellesip_sal/sal_op_registration.c rename to coreapi/sal/register_op.cpp index e21e88803..d06875a22 100644 --- a/coreapi/bellesip_sal/sal_op_registration.c +++ b/coreapi/sal/register_op.cpp @@ -1,40 +1,64 @@ -/* -linphone -Copyright (C) 2012 Belledonne Communications, Grenoble, France +#include "register_op.h" +#include "bellesip_sal/sal_impl.h" -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. +using namespace std; -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. +LINPHONE_BEGIN_NAMESPACE -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 "sal_impl.h" +int SalRegisterOp::register_(const char *proxy, const char *from, int expires, const SalAddress* old_contact) { + belle_sip_request_t *req; + belle_sip_uri_t* req_uri; + belle_sip_header_t* accept_header; + if (this->refresher){ + belle_sip_refresher_stop(this->refresher); + belle_sip_object_unref(this->refresher); + this->refresher=NULL; + } -static void register_refresher_listener (belle_sip_refresher_t* refresher - ,void* user_pointer - ,unsigned int status_code - ,const char* reason_phrase, int will_retry) { - SalOp* op = (SalOp*)user_pointer; + this->type=Type::Register; + set_from(from); + set_to(from); + set_route(proxy); + req = build_request("REGISTER"); + req_uri = belle_sip_request_get_uri(req); + belle_sip_uri_set_user(req_uri,NULL); /*remove userinfo if any*/ + if (this->root->_use_dates) { + time_t curtime=time(NULL); + belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(belle_sip_header_date_create_from_time(&curtime))); + } + accept_header = belle_sip_header_create("Accept", "application/sdp, text/plain, application/vnd.gsma.rcs-ft-http+xml"); + belle_sip_message_add_header(BELLE_SIP_MESSAGE(req), accept_header); + belle_sip_message_set_header(BELLE_SIP_MESSAGE(req),(belle_sip_header_t*)create_contact()); + if (old_contact) { + belle_sip_header_contact_t *contact=belle_sip_header_contact_create((const belle_sip_header_address_t *)old_contact); + if (contact) { + char * tmp; + belle_sip_header_contact_set_expires(contact,0); /*remove old aor*/ + belle_sip_message_add_header(BELLE_SIP_MESSAGE(req), BELLE_SIP_HEADER(contact)); + tmp = belle_sip_object_to_string(contact); + ms_message("Clearing contact [%s] for op [%p]",tmp,this); + ms_free(tmp); + } else { + ms_error("Cannot add old contact header to op [%p]",this); + } + } + return send_and_create_refresher(req,expires,register_refresher_listener); +} + +void SalRegisterOp::register_refresher_listener(belle_sip_refresher_t* refresher, void* user_pointer, unsigned int status_code, const char* reason_phrase, int will_retry) { + SalRegisterOp * op = (SalRegisterOp *)user_pointer; belle_sip_response_t* response=belle_sip_transaction_get_response(BELLE_SIP_TRANSACTION(belle_sip_refresher_get_transaction(refresher))); - ms_message("Register refresher [%i] reason [%s] for proxy [%s]",status_code,reason_phrase,sal_op_get_proxy(op)); + ms_message("Register refresher [%i] reason [%s] for proxy [%s]",status_code,reason_phrase,op->get_proxy()); if (belle_sip_refresher_get_auth_events(refresher)) { if (op->auth_info) sal_auth_info_delete(op->auth_info); /*only take first one for now*/ op->auth_info=sal_auth_info_create((belle_sip_auth_event_t*)(belle_sip_refresher_get_auth_events(refresher)->data)); } - sal_error_info_set(&op->error_info,SalReasonUnknown, "SIP", (int)status_code,reason_phrase,NULL); + sal_error_info_set(&op->error_info,SalReasonUnknown, "SIP", status_code,reason_phrase,NULL); if (status_code>=200){ - sal_op_assign_recv_headers(op,(belle_sip_message_t*)response); + op->assign_recv_headers((belle_sip_message_t*)response); } if(status_code == 200) { /*check service route rfc3608*/ @@ -44,23 +68,24 @@ static void register_refresher_listener (belle_sip_refresher_t* refresher if ((service_route=belle_sip_message_get_header_by_type(response,belle_sip_header_service_route_t))) { service_route_address=belle_sip_header_address_create(NULL,belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(service_route))); } - sal_op_set_service_route(op,(const SalAddress*)service_route_address); + op->set_service_route((const SalAddress*)service_route_address); if (service_route_address) belle_sip_object_unref(service_route_address); - sal_remove_pending_auth(op->base.root,op); /*just in case*/ + op->root->remove_pending_auth(op); /*just in case*/ if (contact) { const char *gruu; belle_sip_parameters_t* p = (BELLE_SIP_PARAMETERS(contact)); if((gruu = belle_sip_parameters_get_parameter(p, "pub-gruu"))) { char *unquoted = belle_sip_unquote_strdup(gruu); - sal_op_set_contact_address(op, (SalAddress*)belle_sip_header_address_parse(unquoted)); + op->set_contact_address((SalAddress*)belle_sip_header_address_parse(unquoted)); + bctbx_free(unquoted); belle_sip_parameters_remove_parameter(p, "pub-gruu"); } else { - sal_op_set_contact_address(op, (SalAddress*)(BELLE_SIP_HEADER_ADDRESS(contact))); /*update contact with real value*/ + op->set_contact_address((SalAddress*)(BELLE_SIP_HEADER_ADDRESS(contact))); /*update contact with real value*/ } } - op->base.root->callbacks.register_success(op,belle_sip_refresher_get_expires(op->refresher)>0); + op->root->callbacks.register_success(op,belle_sip_refresher_get_expires(op->refresher)>0); } else if (status_code>=400) { /* from rfc3608, 6.1. If the UA refreshes the registration, the stored value of the Service- @@ -71,67 +96,17 @@ static void register_refresher_listener (belle_sip_refresher_t* refresher request is refused or if an existing registration expires and the UA chooses not to re-register, the UA SHOULD discard any stored service route for that address-of-record. */ - sal_op_set_service_route(op,NULL); - sal_op_ref(op); /*take a ref while invoking the callback to make sure the operations done after are valid*/ - op->base.root->callbacks.register_failure(op); - if (op->state!=SalOpStateTerminated && op->auth_info) { + op->set_service_route(NULL); + op->ref(); /*take a ref while invoking the callback to make sure the operations done after are valid*/ + op->root->callbacks.register_failure(op); + if (op->state!=State::Terminated && op->auth_info) { /*add pending auth*/ - sal_add_pending_auth(op->base.root,op); + op->root->add_pending_auth(op); if (status_code==403 || status_code==401 || status_code==407 ) - op->base.root->callbacks.auth_failure(op,op->auth_info); + op->root->callbacks.auth_failure(op,op->auth_info); } - sal_op_unref(op); + op->unref(); } } -int sal_register(SalOp *op, const char *proxy, const char *from, int expires, const SalAddress* old_contact){ - belle_sip_request_t *req; - belle_sip_uri_t* req_uri; - belle_sip_header_t* accept_header; - - if (op->refresher){ - belle_sip_refresher_stop(op->refresher); - belle_sip_object_unref(op->refresher); - op->refresher=NULL; - } - - op->type=SalOpRegister; - sal_op_set_from(op,from); - sal_op_set_to(op,from); - sal_op_set_route(op,proxy); - req = sal_op_build_request(op,"REGISTER"); - req_uri = belle_sip_request_get_uri(req); - belle_sip_uri_set_user(req_uri,NULL); /*remove userinfo if any*/ - if (op->base.root->use_dates){ - time_t curtime=time(NULL); - belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(belle_sip_header_date_create_from_time(&curtime))); - } - accept_header = belle_sip_header_create("Accept", "application/sdp, text/plain, application/vnd.gsma.rcs-ft-http+xml"); - belle_sip_message_add_header(BELLE_SIP_MESSAGE(req), accept_header); - belle_sip_message_set_header(BELLE_SIP_MESSAGE(req),(belle_sip_header_t*)sal_op_create_contact(op)); - if (old_contact) { - belle_sip_header_contact_t *contact=belle_sip_header_contact_create((const belle_sip_header_address_t *)old_contact); - if (contact) { - char * tmp; - belle_sip_header_contact_set_expires(contact,0); /*remove old aor*/ - belle_sip_message_add_header(BELLE_SIP_MESSAGE(req), BELLE_SIP_HEADER(contact)); - tmp = belle_sip_object_to_string(contact); - ms_message("Clearing contact [%s] for op [%p]",tmp,op); - ms_free(tmp); - } else { - ms_error("Cannot add old contact header to op [%p]",op); - } - } - return sal_op_send_and_create_refresher(op,req,expires,register_refresher_listener); -} - -int sal_register_refresh(SalOp *op, int expires){ - if (op->refresher) - return belle_sip_refresher_refresh(op->refresher,expires); - else - return -1; -} - -int sal_unregister(SalOp *op){ - return sal_register_refresh(op,0); -} +LINPHONE_END_NAMESPACE diff --git a/coreapi/sal/register_op.h b/coreapi/sal/register_op.h new file mode 100644 index 000000000..a8f2c03c0 --- /dev/null +++ b/coreapi/sal/register_op.h @@ -0,0 +1,43 @@ +/* +register_op.h +Copyright (C) 2017 Belledonne Communications + +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 _SAL_REGISTER_OP_H_ +#define _SAL_REGISTER_OP_H_ + +#include "sal_op.h" + +LINPHONE_BEGIN_NAMESPACE + +class SalRegisterOp: public SalOp { +public: + SalRegisterOp(Sal *sal): SalOp(sal) {} + int register_(const char *proxy, const char *from, int expires, const SalAddress* old_contact); + int register_refresh(int expires) {return this->refresher ? belle_sip_refresher_refresh(this->refresher,expires) : -1;} + int unregister() {return register_refresh(0);} + + virtual void authenticate(const SalAuthInfo *info) override {register_refresh(-1);} + +private: + virtual void fill_cbs() override {}; + static void register_refresher_listener(belle_sip_refresher_t* refresher, void* user_pointer, unsigned int status_code, const char* reason_phrase, int will_retry); +}; + +LINPHONE_END_NAMESPACE + +#endif diff --git a/coreapi/sal/sal.c b/coreapi/sal/sal.c index e61232fc9..4dee10831 100644 --- a/coreapi/sal/sal.c +++ b/coreapi/sal/sal.c @@ -174,6 +174,98 @@ int sal_media_description_get_nb_active_streams(const SalMediaDescription *md) { return nb; } +SalMimeType *sal_mime_type_new(const char *type, const char *subtype) { + SalMimeType *mime_type = bctbx_new0(SalMimeType, 1); + if (type) mime_type->type = bctbx_strdup(type); + if (subtype) mime_type->subtype = bctbx_strdup(subtype); + return mime_type; +} + +SalMimeType *sal_mime_type_copy(const SalMimeType *mime_type) { + SalMimeType *new_mime_type = bctbx_new0(SalMimeType, 1); + if (mime_type->type) new_mime_type->type = bctbx_strdup(mime_type->type); + if (mime_type->subtype) new_mime_type->subtype = bctbx_strdup(mime_type->subtype); + return new_mime_type; +} + +SalMimeType *sal_mime_type_ref(SalMimeType *mime_type) { + if (!mime_type) return NULL; + mime_type->ref++; + return mime_type; +} + +void sal_mime_type_unref(SalMimeType *mime_type) { + mime_type->ref--; + if (mime_type->ref <= 0) { + if (mime_type->type) bctbx_free(mime_type->type); + if (mime_type->subtype) bctbx_free(mime_type->subtype); + } + bctbx_free(mime_type); +} + +SalCustomBody *sal_custom_body_new(SalMimeType *type) { + if (type == NULL) { + bctbx_error("creating a SalCustomBody from NULL SalMimeType"); + return NULL; + } + SalCustomBody *body = bctbx_new0(SalCustomBody, 1); + body->type = sal_mime_type_ref(type); + return body; +} + +SalCustomBody *sal_custom_body_new_with_buffer_copy(SalMimeType *type, const char *raw_data, size_t data_length) { + SalCustomBody *body = sal_custom_body_new(type); + if (body == NULL) return NULL; + body->data_length = data_length; + if (data_length > 0 && raw_data) { + body->raw_data = bctbx_new(char, data_length); + memcpy(body->raw_data, raw_data, data_length); + } + return body; +} + +SalCustomBody *sal_custom_body_new_with_buffer_moving(SalMimeType *type, char *raw_data, size_t data_length) { + SalCustomBody *body = sal_custom_body_new(type); + if (body == NULL) return NULL; + sal_custom_body_set_buffer_by_moving(body, raw_data, data_length); + return body; +} + +SalCustomBody *sal_custom_body_ref(SalCustomBody *body) { + if (!body) return NULL; + body->ref++; + return body; +} + +void sal_custom_body_unref(SalCustomBody *body) { + body->ref--; + if (body->ref <= 0) { + if (body->type) sal_mime_type_unref(body->type); + if (body->raw_data) bctbx_free(body->raw_data); + } + bctbx_free(body); +} + +void sal_custom_body_set_buffer_by_copy(SalCustomBody *body, const char *buffer, size_t length) { + char *buff_copy = NULL; + if (buffer && length > 0) { + buff_copy = bctbx_new(char, length); + memcpy(buff_copy, buffer, length); + } else length = 0; + sal_custom_body_set_buffer_by_moving(body, buff_copy, length); +} + +void sal_custom_body_set_buffer_by_moving(SalCustomBody *body, char *buffer, size_t length) { + if (body->raw_data) bctbx_free(body->raw_data); + if (length > 0 && buffer) { + body->raw_data = buffer; + body->data_length = length; + } else { + body->raw_data = NULL; + body->data_length = length; + } +} + static bool_t is_null_address(const char *addr){ return strcmp(addr,"0.0.0.0")==0 || strcmp(addr,"::0")==0; } @@ -495,6 +587,7 @@ int sal_media_description_equals(const SalMediaDescription *md1, const SalMediaD return result; } +#if 0 static void assign_address(SalAddress** address, const char *value){ if (*address){ sal_address_destroy(*address); @@ -552,9 +645,11 @@ void sal_op_set_route(SalOp *op, const char *route){ 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); @@ -606,6 +701,7 @@ Sal *sal_op_get_sal(const SalOp *op){ 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; } @@ -637,6 +733,7 @@ const char *sal_op_get_proxy(const SalOp *op){ 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; } @@ -721,6 +818,9 @@ void __sal_op_free(SalOp *op){ sal_media_description_unref(b->local_media); if (b->remote_media) sal_media_description_unref(b->remote_media); + if (b->custom_body) { + sal_custom_body_unref(b->custom_body); + } if (b->call_id) ms_free((void*)b->call_id); if (b->service_route) { @@ -741,6 +841,7 @@ void __sal_op_free(SalOp *op){ } ms_free(op); } +#endif SalAuthInfo* sal_auth_info_new() { return ms_new0(SalAuthInfo,1); @@ -829,15 +930,18 @@ const char* sal_reason_to_string(const SalReason reason) { default: return "Unkown reason"; } } +#if 0 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; } +#endif const char* sal_presence_status_to_string(const SalPresenceStatus status) { switch (status) { @@ -911,6 +1015,7 @@ int sal_lines_get_value(const char *data, const char *key, char *value, size_t v return FALSE; } +#if 0 const char *sal_op_get_entity_tag(const SalOp* op) { SalOpBase* op_base = (SalOpBase*)op; return op_base->entity_tag; @@ -927,3 +1032,4 @@ void sal_op_set_entity_tag(SalOp *op, const char* entity_tag) { else op_base->entity_tag = NULL; } +#endif diff --git a/coreapi/sal/sal.cpp b/coreapi/sal/sal.cpp new file mode 100644 index 000000000..200ca30ad --- /dev/null +++ b/coreapi/sal/sal.cpp @@ -0,0 +1,976 @@ +#include "sal.hpp" +#include "call_op.h" +#include "presence_op.h" +#include "event_op.h" +#include "message_op.h" +#include "bellesip_sal/sal_impl.h" +#include "tester_utils.h" +#include "private.h" + +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +void Sal::process_dialog_terminated_cb(void *sal, const belle_sip_dialog_terminated_event_t *event) { + belle_sip_dialog_t* dialog = belle_sip_dialog_terminated_event_get_dialog(event); + SalOp* op = reinterpret_cast(belle_sip_dialog_get_application_data(dialog)); + if (op && op->callbacks && op->callbacks->process_dialog_terminated) { + op->callbacks->process_dialog_terminated(op,event); + } else { + ms_error("sal process_dialog_terminated no op found for this dialog [%p], ignoring",dialog); + } +} + +void Sal::process_io_error_cb(void *user_ctx, const belle_sip_io_error_event_t *event){ + belle_sip_client_transaction_t*client_transaction; + SalOp* op; + if (BELLE_SIP_OBJECT_IS_INSTANCE_OF(belle_sip_io_error_event_get_source(event),belle_sip_client_transaction_t)) { + client_transaction=BELLE_SIP_CLIENT_TRANSACTION(belle_sip_io_error_event_get_source(event)); + op = (SalOp*)belle_sip_transaction_get_application_data(BELLE_SIP_TRANSACTION(client_transaction)); + /*also reset auth count on IO error*/ + op->auth_requests=0; + if (op->callbacks && op->callbacks->process_io_error) { + op->callbacks->process_io_error(op,event); + } + } else { + /*ms_error("sal process_io_error not implemented yet for non transaction");*/ + /*nop, because already handle at transaction layer*/ + } +} + +void Sal::process_request_event_cb(void *ud, const belle_sip_request_event_t *event) { + Sal *sal=(Sal*)ud; + SalOp* op=NULL; + belle_sip_request_t* req = belle_sip_request_event_get_request(event); + belle_sip_dialog_t* dialog=belle_sip_request_event_get_dialog(event); + belle_sip_header_address_t* origin_address; + belle_sip_header_address_t* address=NULL; + belle_sip_header_from_t* from_header; + belle_sip_header_to_t* to; + belle_sip_header_diversion_t* diversion; + belle_sip_response_t* resp; + belle_sip_header_t *evh; + const char *method=belle_sip_request_get_method(req); + belle_sip_header_contact_t* remote_contact = belle_sip_message_get_header_by_type(req, belle_sip_header_contact_t); + + from_header=belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req),belle_sip_header_from_t); + + if (dialog) { + op=(SalOp*)belle_sip_dialog_get_application_data(dialog); + + if (op == NULL && strcmp("NOTIFY",method) == 0) { + /*special case for Dialog created by notify mathing subscribe*/ + belle_sip_transaction_t * sub_trans = belle_sip_dialog_get_last_transaction(dialog); + op = (SalOp*)belle_sip_transaction_get_application_data(sub_trans); + } + if (op==NULL || op->state==SalOp::State::Terminated){ + ms_warning("Receiving request for null or terminated op [%p], ignored",op); + return; + } + }else{ + /*handle the case where we are receiving a request with to tag but it is not belonging to any dialog*/ + belle_sip_header_to_t *to = belle_sip_message_get_header_by_type(req, belle_sip_header_to_t); + if ((strcmp("INVITE",method)==0 || strcmp("NOTIFY",method)==0) && (belle_sip_header_to_get_tag(to) != NULL)) { + ms_warning("Receiving %s with to-tag but no know dialog here. Rejecting.", method); + resp=belle_sip_response_create_from_request(req,481); + belle_sip_provider_send_response(sal->prov,resp); + return; + /* by default (eg. when a to-tag is present), out of dialog ACK are automatically + handled in lower layers (belle-sip) but in case it misses, it will be forwarded to us */ + } else if (strcmp("ACK",method)==0 && (belle_sip_header_to_get_tag(to) == NULL)) { + ms_warning("Receiving ACK without to-tag but no know dialog here. Ignoring"); + return; + } + + if (strcmp("INVITE",method)==0) { + op=new SalCallOp(sal); + op->dir=SalOp::Dir::Incoming; + op->fill_cbs(); + }else if ((strcmp("SUBSCRIBE",method)==0 || strcmp("NOTIFY",method)==0) && (evh=belle_sip_message_get_header(BELLE_SIP_MESSAGE(req),"Event"))!=NULL) { + if (strncmp(belle_sip_header_get_unparsed_value(evh),"presence",strlen("presence"))==0){ + op=new SalPresenceOp(sal); + } else { + op=new SalSubscribeOp(sal); + } + op->dir=SalOp::Dir::Incoming; + op->fill_cbs(); + }else if (strcmp("MESSAGE",method)==0) { + op=new SalMessageOp(sal); + op->dir=SalOp::Dir::Incoming; + op->fill_cbs(); + }else if (strcmp("OPTIONS",method)==0) { + resp=belle_sip_response_create_from_request(req,200); + belle_sip_provider_send_response(sal->prov,resp); + return; + }else if (strcmp("INFO",method)==0) { + resp=belle_sip_response_create_from_request(req,481);/*INFO out of call dialogs are not allowed*/ + belle_sip_provider_send_response(sal->prov,resp); + return; + }else if (strcmp("BYE",method)==0) { + resp=belle_sip_response_create_from_request(req,481);/*out of dialog BYE */ + belle_sip_provider_send_response(sal->prov,resp); + return; + }else if (strcmp("CANCEL",method)==0) { + resp=belle_sip_response_create_from_request(req,481);/*out of dialog CANCEL */ + belle_sip_provider_send_response(sal->prov,resp); + return; + }else if (sal->_enable_test_features && strcmp("PUBLISH",method)==0) { + resp=belle_sip_response_create_from_request(req,200);/*out of dialog PUBLISH */ + belle_sip_message_add_header((belle_sip_message_t*)resp,belle_sip_header_create("SIP-Etag","4441929FFFZQOA")); + belle_sip_provider_send_response(sal->prov,resp); + return; + }else { + ms_error("sal process_request_event not implemented yet for method [%s]",belle_sip_request_get_method(req)); + resp=belle_sip_response_create_from_request(req,405); + belle_sip_message_add_header(BELLE_SIP_MESSAGE(resp) + ,BELLE_SIP_HEADER(belle_sip_header_allow_create("INVITE, CANCEL, ACK, BYE, SUBSCRIBE, NOTIFY, MESSAGE, OPTIONS, INFO"))); + belle_sip_provider_send_response(sal->prov,resp); + return; + } + } + + if (!op->from_address) { + if (belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(from_header))) + address=belle_sip_header_address_create(belle_sip_header_address_get_displayname(BELLE_SIP_HEADER_ADDRESS(from_header)) + ,belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(from_header))); + else if ((belle_sip_header_address_get_absolute_uri(BELLE_SIP_HEADER_ADDRESS(from_header)))) + address=belle_sip_header_address_create2(belle_sip_header_address_get_displayname(BELLE_SIP_HEADER_ADDRESS(from_header)) + ,belle_sip_header_address_get_absolute_uri(BELLE_SIP_HEADER_ADDRESS(from_header))); + else + ms_error("Cannot not find from uri from request [%p]",req); + op->set_from_address((SalAddress*)address); + belle_sip_object_unref(address); + } + + if( remote_contact ){ + op->set_remote_contact(belle_sip_header_get_unparsed_value(BELLE_SIP_HEADER(remote_contact))); + } + + if (!op->to_address) { + to=belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req),belle_sip_header_to_t); + if (belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(to))) + address=belle_sip_header_address_create(belle_sip_header_address_get_displayname(BELLE_SIP_HEADER_ADDRESS(to)) + ,belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(to))); + else if ((belle_sip_header_address_get_absolute_uri(BELLE_SIP_HEADER_ADDRESS(to)))) + address=belle_sip_header_address_create2(belle_sip_header_address_get_displayname(BELLE_SIP_HEADER_ADDRESS(to)) + ,belle_sip_header_address_get_absolute_uri(BELLE_SIP_HEADER_ADDRESS(to))); + else + ms_error("Cannot not find to uri from request [%p]",req); + + op->set_to_address((SalAddress*)address); + belle_sip_object_unref(address); + } + + if(!op->diversion_address){ + diversion=belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req),belle_sip_header_diversion_t); + if (diversion) { + if (belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(diversion))) + address=belle_sip_header_address_create(belle_sip_header_address_get_displayname(BELLE_SIP_HEADER_ADDRESS(diversion)) + ,belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(diversion))); + else if ((belle_sip_header_address_get_absolute_uri(BELLE_SIP_HEADER_ADDRESS(diversion)))) + address=belle_sip_header_address_create2(belle_sip_header_address_get_displayname(BELLE_SIP_HEADER_ADDRESS(diversion)) + ,belle_sip_header_address_get_absolute_uri(BELLE_SIP_HEADER_ADDRESS(diversion))); + else + ms_warning("Cannot not find diversion header from request [%p]",req); + if (address) { + op->set_diversion_address((SalAddress*)address); + belle_sip_object_unref(address); + } + } + } + + if (!op->origin) { + /*set origin uri*/ + origin_address=belle_sip_header_address_create(NULL,belle_sip_request_extract_origin(req)); + op->set_network_origin_address((SalAddress*)origin_address); + belle_sip_object_unref(origin_address); + } + if (!op->remote_ua) { + op->set_remote_ua(BELLE_SIP_MESSAGE(req)); + } + + if (!op->call_id) { + op->call_id=ms_strdup(belle_sip_header_call_id_get_call_id(BELLE_SIP_HEADER_CALL_ID(belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req), belle_sip_header_call_id_t)))); + } + /*It is worth noting that proxies can (and + will) remove this header field*/ + op->set_privacy_from_message((belle_sip_message_t*)req); + + op->assign_recv_headers((belle_sip_message_t*)req); + if (op->callbacks && op->callbacks->process_request_event) { + op->callbacks->process_request_event(op,event); + } else { + ms_error("sal process_request_event not implemented yet"); + } + +} + +void Sal::process_response_event_cb(void *user_ctx, const belle_sip_response_event_t *event) { + belle_sip_client_transaction_t* client_transaction = belle_sip_response_event_get_client_transaction(event); + belle_sip_response_t* response = belle_sip_response_event_get_response(event); + int response_code = belle_sip_response_get_status_code(response); + + if (!client_transaction) { + ms_warning("Discarding stateless response [%i]",response_code); + return; + } else { + SalOp* op = (SalOp*)belle_sip_transaction_get_application_data(BELLE_SIP_TRANSACTION(client_transaction)); + belle_sip_request_t* request=belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(client_transaction)); + belle_sip_header_contact_t* remote_contact = belle_sip_message_get_header_by_type(response, belle_sip_header_contact_t); + + if (op->state == SalOp::State::Terminated) { + belle_sip_message("Op [%p] is terminated, nothing to do with this [%i]", op, response_code); + return; + } + /*do it all the time, since we can receive provisional responses from a different instance than the final one*/ + op->set_remote_ua(BELLE_SIP_MESSAGE(response)); + + if(remote_contact) { + op->set_remote_contact(belle_sip_header_get_unparsed_value(BELLE_SIP_HEADER(remote_contact))); + } + + if (!op->call_id) { + op->call_id=ms_strdup(belle_sip_header_call_id_get_call_id(BELLE_SIP_HEADER_CALL_ID(belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(response), belle_sip_header_call_id_t)))); + } + + op->assign_recv_headers((belle_sip_message_t*)response); + + if (op->callbacks && op->callbacks->process_response_event) { + /*handle authorization*/ + switch (response_code) { + case 200: + break; + case 401: + case 407: + if (op->state == SalOp::State::Terminating && strcmp("BYE",belle_sip_request_get_method(request))!=0) { + /*only bye are completed*/ + belle_sip_message("Op is in state terminating, nothing else to do "); + } else { + if (op->pending_auth_transaction){ + belle_sip_object_unref(op->pending_auth_transaction); + op->pending_auth_transaction=NULL; + } + if (++op->auth_requests > 2) { + ms_warning("Auth info cannot be found for op [%s/%s] after 2 attempts, giving up",op->get_from() + ,op->get_to()); + op->root->callbacks.auth_failure(op,op->auth_info); + op->root->remove_pending_auth(op); + } else { + op->pending_auth_transaction=(belle_sip_client_transaction_t*)belle_sip_object_ref(client_transaction); + op->process_authentication(); + return; + } + } + break; + case 403: + if (op->auth_info) op->root->callbacks.auth_failure(op,op->auth_info); + break; + } + if (response_code >= 180 && response_code !=401 && response_code !=407 && response_code !=403) { + /*not an auth request*/ + op->auth_requests=0; + } + op->callbacks->process_response_event(op,event); + } else { + ms_error("Unhandled event response [%p]",event); + } + } +} + +void Sal::process_timeout_cb(void *user_ctx, const belle_sip_timeout_event_t *event) { + belle_sip_client_transaction_t* client_transaction = belle_sip_timeout_event_get_client_transaction(event); + SalOp* op = (SalOp*)belle_sip_transaction_get_application_data(BELLE_SIP_TRANSACTION(client_transaction)); + if (op && op->callbacks && op->callbacks->process_timeout) { + op->callbacks->process_timeout(op,event); + } else { + ms_error("Unhandled event timeout [%p]",event); + } +} + +void Sal::process_transaction_terminated_cb(void *user_ctx, const belle_sip_transaction_terminated_event_t *event) { + belle_sip_client_transaction_t* client_transaction = belle_sip_transaction_terminated_event_get_client_transaction(event); + belle_sip_server_transaction_t* server_transaction = belle_sip_transaction_terminated_event_get_server_transaction(event); + belle_sip_transaction_t* trans; + SalOp* op; + + if(client_transaction) + trans=BELLE_SIP_TRANSACTION(client_transaction); + else + trans=BELLE_SIP_TRANSACTION(server_transaction); + + op = (SalOp*)belle_sip_transaction_get_application_data(trans); + if (op && op->callbacks && op->callbacks->process_transaction_terminated) { + op->callbacks->process_transaction_terminated(op,event); + } else { + ms_message("Unhandled transaction terminated [%p]",trans); + } + if (op) { + op->unref(); /*because every transaction ref op*/ + belle_sip_transaction_set_application_data(trans,NULL); /*no longuer reference something we do not ref to avoid futur access of a released op*/ + } +} + +void Sal::process_auth_requested_cb(void *sal, belle_sip_auth_event_t *event) { + SalAuthInfo* auth_info = sal_auth_info_create(event); + ((Sal*)sal)->callbacks.auth_requested(reinterpret_cast(sal),auth_info); + belle_sip_auth_event_set_passwd(event,(const char*)auth_info->password); + belle_sip_auth_event_set_ha1(event,(const char*)auth_info->ha1); + belle_sip_auth_event_set_userid(event,(const char*)auth_info->userid); + belle_sip_auth_event_set_signing_key(event,(belle_sip_signing_key_t *)auth_info->key); + belle_sip_auth_event_set_client_certificates_chain(event,(belle_sip_certificates_chain_t* )auth_info->certificates); + sal_auth_info_delete(auth_info); +} + +Sal::Sal(MSFactory *factory){ + belle_sip_listener_callbacks_t listener_callbacks = {0}; + + /*belle_sip_object_enable_marshal_check(TRUE);*/ + this->factory = factory; + /*first create the stack, which initializes the belle-sip object's pool for this thread*/ + this->stack = belle_sip_stack_new(NULL); + + this->user_agent=belle_sip_header_user_agent_new(); +#if defined(PACKAGE_NAME) && defined(LIBLINPHONE_VERSION) + belle_sip_header_user_agent_add_product(this->user_agent, PACKAGE_NAME "/" LIBLINPHONE_VERSION); +#else + belle_sip_header_user_agent_add_product(this->user_agent, "Unknown"); +#endif + append_stack_string_to_user_agent(); + belle_sip_object_ref(this->user_agent); + + this->prov = belle_sip_stack_create_provider(this->stack,NULL); + enable_nat_helper(TRUE); + + listener_callbacks.process_dialog_terminated=process_dialog_terminated_cb; + listener_callbacks.process_io_error=process_io_error_cb; + listener_callbacks.process_request_event=process_request_event_cb; + listener_callbacks.process_response_event=process_response_event_cb; + listener_callbacks.process_timeout=process_timeout_cb; + listener_callbacks.process_transaction_terminated=process_transaction_terminated_cb; + listener_callbacks.process_auth_requested=process_auth_requested_cb; + this->listener=belle_sip_listener_create_from_callbacks(&listener_callbacks, this); + belle_sip_provider_add_sip_listener(this->prov, this->listener); +} + +Sal::~Sal() { + belle_sip_object_unref(this->user_agent); + belle_sip_object_unref(this->prov); + belle_sip_object_unref(this->stack); + belle_sip_object_unref(this->listener); + if (this->supported) belle_sip_object_unref(this->supported); + bctbx_list_free_with_data(this->supported_tags,ms_free); + bctbx_list_free_with_data(this->supported_content_types, ms_free); + if (this->uuid) ms_free(this->uuid); + if (this->root_ca) ms_free(this->root_ca); + if (this->root_ca_data) ms_free(this->root_ca_data); +} + +void Sal::set_callbacks(const Callbacks *cbs) { + memcpy(&this->callbacks,cbs,sizeof(*cbs)); + if (this->callbacks.call_received==NULL) + this->callbacks.call_received=(OnCallReceivedCb)unimplemented_stub; + if (this->callbacks.call_ringing==NULL) + this->callbacks.call_ringing=(OnCallRingingCb)unimplemented_stub; + if (this->callbacks.call_accepted==NULL) + this->callbacks.call_accepted=(OnCallAcceptedCb)unimplemented_stub; + if (this->callbacks.call_failure==NULL) + this->callbacks.call_failure=(OnCallFailureCb)unimplemented_stub; + if (this->callbacks.call_terminated==NULL) + this->callbacks.call_terminated=(OnCallTerminatedCb)unimplemented_stub; + if (this->callbacks.call_released==NULL) + this->callbacks.call_released=(OnCallReleasedCb)unimplemented_stub; + if (this->callbacks.call_updating==NULL) + this->callbacks.call_updating=(OnCallUpdatingCb)unimplemented_stub; + if (this->callbacks.auth_failure==NULL) + this->callbacks.auth_failure=(OnAuthFailureCb)unimplemented_stub; + if (this->callbacks.register_success==NULL) + this->callbacks.register_success=(OnRegisterSuccessCb)unimplemented_stub; + if (this->callbacks.register_failure==NULL) + this->callbacks.register_failure=(OnRegisterFailureCb)unimplemented_stub; + if (this->callbacks.dtmf_received==NULL) + this->callbacks.dtmf_received=(OnDtmfReceivedCb)unimplemented_stub; + if (this->callbacks.notify==NULL) + this->callbacks.notify=(OnNotifyCb)unimplemented_stub; + if (this->callbacks.subscribe_received==NULL) + this->callbacks.subscribe_received=(OnSubscribeReceivedCb)unimplemented_stub; + if (this->callbacks.incoming_subscribe_closed==NULL) + this->callbacks.incoming_subscribe_closed=(OnIncomingSubscribeClosedCb)unimplemented_stub; + if (this->callbacks.parse_presence_requested==NULL) + this->callbacks.parse_presence_requested=(OnParsePresenceRequestedCb)unimplemented_stub; + if (this->callbacks.convert_presence_to_xml_requested==NULL) + this->callbacks.convert_presence_to_xml_requested=(OnConvertPresenceToXMLRequestedCb)unimplemented_stub; + if (this->callbacks.notify_presence==NULL) + this->callbacks.notify_presence=(OnNotifyPresenceCb)unimplemented_stub; + if (this->callbacks.subscribe_presence_received==NULL) + this->callbacks.subscribe_presence_received=(OnSubscribePresenceReceivedCb)unimplemented_stub; + if (this->callbacks.message_received==NULL) + this->callbacks.message_received=(OnMessageReceivedCb)unimplemented_stub; + if (this->callbacks.ping_reply==NULL) + this->callbacks.ping_reply=(OnPingReplyCb)unimplemented_stub; + if (this->callbacks.auth_requested==NULL) + this->callbacks.auth_requested=(OnAuthRequestedCb)unimplemented_stub; + if (this->callbacks.info_received==NULL) + this->callbacks.info_received=(OnInfoReceivedCb)unimplemented_stub; + if (this->callbacks.on_publish_response==NULL) + this->callbacks.on_publish_response=(OnPublishResponseCb)unimplemented_stub; + if (this->callbacks.on_expire==NULL) + this->callbacks.on_expire=(OnExpireCb)unimplemented_stub; +} + +void Sal::set_tls_properties(){ + belle_sip_listening_point_t *lp=belle_sip_provider_get_listening_point(this->prov,"TLS"); + if (lp){ + belle_sip_tls_listening_point_t *tlp=BELLE_SIP_TLS_LISTENING_POINT(lp); + belle_tls_crypto_config_t *crypto_config = belle_tls_crypto_config_new(); + int verify_exceptions = BELLE_TLS_VERIFY_NONE; + if (!this->tls_verify) verify_exceptions = BELLE_TLS_VERIFY_ANY_REASON; + else if (!this->tls_verify_cn) verify_exceptions = BELLE_TLS_VERIFY_CN_MISMATCH; + belle_tls_crypto_config_set_verify_exceptions(crypto_config, verify_exceptions); + if (this->root_ca != NULL) belle_tls_crypto_config_set_root_ca(crypto_config, this->root_ca); + if (this->root_ca_data != NULL) belle_tls_crypto_config_set_root_ca_data(crypto_config, this->root_ca_data); + if (this->ssl_config != NULL) belle_tls_crypto_config_set_ssl_config(crypto_config, this->ssl_config); + belle_sip_tls_listening_point_set_crypto_config(tlp, crypto_config); + belle_sip_object_unref(crypto_config); + } +} + +int Sal::add_listen_port(SalAddress* addr, bool_t is_tunneled) { + int result; + belle_sip_listening_point_t* lp; + if (is_tunneled){ +#ifdef TUNNEL_ENABLED + if (sal_address_get_transport(addr)!=SalTransportUDP){ + ms_error("Tunneled mode is only available for UDP kind of transports."); + return -1; + } + lp = belle_sip_tunnel_listening_point_new(this->stack, this->tunnel_client); + if (!lp){ + ms_error("Could not create tunnel listening point."); + return -1; + } +#else + ms_error("No tunnel support in library."); + return -1; +#endif + }else{ + lp = belle_sip_stack_create_listening_point(this->stack, + sal_address_get_domain(addr), + sal_address_get_port(addr), + sal_transport_to_string(sal_address_get_transport(addr))); + } + if (lp) { + belle_sip_listening_point_set_keep_alive(lp,this->keep_alive); + result = belle_sip_provider_add_listening_point(this->prov,lp); + if (sal_address_get_transport(addr)==SalTransportTLS) { + set_tls_properties(); + } + } else { + return -1; + } + return result; +} + +int Sal::set_listen_port(const char *addr, int port, SalTransport tr, bool_t is_tunneled) { + SalAddress* sal_addr = sal_address_new(NULL); + int result; + sal_address_set_domain(sal_addr,addr); + sal_address_set_port(sal_addr,port); + sal_address_set_transport(sal_addr,tr); + result = add_listen_port(sal_addr, is_tunneled); + sal_address_destroy(sal_addr); + return result; +} + +int Sal::get_listening_port(SalTransport tr){ + const char *tpn=sal_transport_to_string(tr); + belle_sip_listening_point_t *lp=belle_sip_provider_get_listening_point(this->prov, tpn); + if (lp){ + return belle_sip_listening_point_get_port(lp); + } + return 0; +} + +int Sal::unlisten_ports(){ + const belle_sip_list_t * lps = belle_sip_provider_get_listening_points(this->prov); + belle_sip_list_t * tmp_list = belle_sip_list_copy(lps); + belle_sip_list_for_each2 (tmp_list,(void (*)(void*,void*))remove_listening_point,this->prov); + belle_sip_list_free(tmp_list); + ms_message("sal_unlisten_ports done"); + return 0; +} + +int Sal::transport_available(SalTransport t) { + switch(t){ + case SalTransportUDP: + case SalTransportTCP: + return TRUE; + case SalTransportTLS: + return belle_sip_stack_tls_available(this->stack); + case SalTransportDTLS: + return FALSE; + } + return FALSE; +} + +void Sal::make_supported_header(){ + bctbx_list_t *it; + char *alltags=NULL; + size_t buflen=64; + size_t written=0; + + if (this->supported){ + belle_sip_object_unref(this->supported); + this->supported=NULL; + } + for(it=this->supported_tags;it!=NULL;it=it->next){ + const char *tag=(const char*)it->data; + size_t taglen=strlen(tag); + if (alltags==NULL || (written+taglen+1>=buflen)) alltags=reinterpret_cast(ms_realloc(alltags,(buflen=buflen*2))); + written+=snprintf(alltags+written,buflen-written,it->next ? "%s, " : "%s",tag); + } + if (alltags){ + this->supported=belle_sip_header_create("Supported",alltags); + if (this->supported){ + belle_sip_object_ref(this->supported); + } + ms_free(alltags); + } +} + +void Sal::set_supported_tags(const char* tags){ + this->supported_tags=bctbx_list_free_with_data(this->supported_tags,ms_free); + if (tags){ + char *iter; + char *buffer=ms_strdup(tags); + char *tag; + char *context=NULL; + iter=buffer; + while((tag=strtok_r(iter,", ",&context))!=NULL){ + iter=NULL; + this->supported_tags=bctbx_list_append(this->supported_tags,ms_strdup(tag)); + } + ms_free(buffer); + } + make_supported_header(); +} + +void Sal::add_supported_tag(const char* tag){ + bctbx_list_t *elem=bctbx_list_find_custom(this->supported_tags,(bctbx_compare_func)strcasecmp,tag); + if (!elem){ + this->supported_tags=bctbx_list_append(this->supported_tags,ms_strdup(tag)); + make_supported_header(); + } +} + +void Sal::remove_supported_tag(const char* tag){ + bctbx_list_t *elem=bctbx_list_find_custom(this->supported_tags,(bctbx_compare_func)strcasecmp,tag); + if (elem){ + ms_free(elem->data); + this->supported_tags=bctbx_list_erase_link(this->supported_tags,elem); + make_supported_header(); + } +} + +int Sal::reset_transports() { + ms_message("Reseting transports"); + belle_sip_provider_clean_channels(this->prov); + return 0; +} + +ortp_socket_t Sal::get_socket() const { + ms_warning("sal_get_socket is deprecated"); + return -1; +} + +void Sal::set_user_agent(const char *user_agent) { + belle_sip_header_user_agent_set_products(this->user_agent,NULL); + belle_sip_header_user_agent_add_product(this->user_agent,user_agent); +} + +const char* Sal::get_user_agent() const { + static char user_agent[255]; + belle_sip_header_user_agent_get_products_as_string(this->user_agent, user_agent, 254); + return user_agent; +} + +void Sal::append_stack_string_to_user_agent() { + char stack_string[64]; + snprintf(stack_string, sizeof(stack_string) - 1, "(belle-sip/%s)", belle_sip_version_to_string()); + belle_sip_header_user_agent_add_product(this->user_agent, stack_string); +} + +void Sal::set_keepalive_period(unsigned int value) { + const belle_sip_list_t* iterator; + belle_sip_listening_point_t* lp; + this->keep_alive=value; + for (iterator=belle_sip_provider_get_listening_points(this->prov);iterator!=NULL;iterator=iterator->next) { + lp=(belle_sip_listening_point_t*)iterator->data; + if (this->use_tcp_tls_keep_alive || strcasecmp(belle_sip_listening_point_get_transport(lp),"udp")==0) { + belle_sip_listening_point_set_keep_alive(lp,this->keep_alive); + } + } +} + +int Sal::set_tunnel(void *tunnelclient) { +#ifdef TUNNEL_ENABLED + this->tunnel_client=tunnelclient; + return 0; +#else + return -1; +#endif +} + +bool_t Sal::is_content_type_supported(const char *content_type) const { + bctbx_list_t *item; + for (item = this->supported_content_types; item != NULL; item = bctbx_list_next(item)) { + const char *item_content_type = (const char *)bctbx_list_get_data(item); + if (strcmp(item_content_type, content_type) == 0) return TRUE; + } + return FALSE; +} + +void Sal::add_content_type_support(const char *content_type) { + if ((content_type != NULL) && (is_content_type_supported(content_type) == FALSE)) { + this->supported_content_types = bctbx_list_append(this->supported_content_types, ms_strdup(content_type)); + } +} + +void Sal::use_rport(bool_t use_rports) { + belle_sip_provider_enable_rport(this->prov,use_rports); + ms_message("Sal use rport [%s]", use_rports ? "enabled" : "disabled"); +} + +void Sal::set_root_ca(const char* rootCa) { + if (this->root_ca) { + ms_free(this->root_ca); + this->root_ca = NULL; + } + if (rootCa) + this->root_ca = ms_strdup(rootCa); + set_tls_properties(); +} + +void Sal::set_root_ca_data(const char* data) { + if (this->root_ca_data) { + ms_free(this->root_ca_data); + this->root_ca_data = NULL; + } + if (data) + this->root_ca_data = ms_strdup(data); + set_tls_properties(); +} + +void Sal::verify_server_certificates(bool_t verify) { + this->tls_verify=verify; + set_tls_properties(); +} + +void Sal::verify_server_cn(bool_t verify) { + this->tls_verify_cn = verify; + set_tls_properties(); +} + +void Sal::set_ssl_config(void *ssl_config) { + this->ssl_config = ssl_config; + set_tls_properties(); +} + +void Sal::set_uuid(const char *uuid){ + if (this->uuid){ + ms_free(this->uuid); + this->uuid=NULL; + } + if (uuid) + this->uuid=ms_strdup(uuid); +} + +int Sal::create_uuid(char *uuid, size_t len) { + if (generate_uuid(uuid, len) == 0) { + set_uuid(uuid); + return 0; + } + return -1; +} + +int Sal::generate_uuid(char *uuid, size_t len) { + sal_uuid_t uuid_struct; + int i; + int written; + + if (len==0) return -1; + /*create an UUID as described in RFC4122, 4.4 */ + belle_sip_random_bytes((unsigned char*)&uuid_struct, sizeof(sal_uuid_t)); + uuid_struct.clock_seq_hi_and_reserved&=(unsigned char)~(1<<6); + uuid_struct.clock_seq_hi_and_reserved|=(unsigned char)1<<7; + uuid_struct.time_hi_and_version&=(unsigned char)~(0xf<<12); + uuid_struct.time_hi_and_version|=(unsigned char)4<<12; + + written=snprintf(uuid,len,"%8.8x-%4.4x-%4.4x-%2.2x%2.2x-", uuid_struct.time_low, uuid_struct.time_mid, + uuid_struct.time_hi_and_version, uuid_struct.clock_seq_hi_and_reserved, + uuid_struct.clock_seq_low); + if ((written < 0) || ((size_t)written > (len +13))) { + ms_error("sal_create_uuid(): buffer is too short !"); + return -1; + } + for (i = 0; i < 6; i++) + written+=snprintf(uuid+written,len-written,"%2.2x", uuid_struct.node[i]); + uuid[len-1]='\0'; + return 0; +} + +void Sal::add_pending_auth(SalOp *op){ + if (bctbx_list_find(this->pending_auths,op)==NULL){ + this->pending_auths=bctbx_list_append(this->pending_auths,op); + op->has_auth_pending=TRUE; + } +} + +void Sal::remove_pending_auth(SalOp *op){ + if (op->has_auth_pending){ + op->has_auth_pending=FALSE; + if (bctbx_list_find(this->pending_auths,op)){ + this->pending_auths=bctbx_list_remove(this->pending_auths,op); + } + } +} + +void Sal::set_default_sdp_handling(SalOpSDPHandling sdp_handling_method) { + if (sdp_handling_method != SalOpSDPNormal ) ms_message("Enabling special SDP handling for all new SalOp in Sal[%p]!", this); + this->default_sdp_handling = sdp_handling_method; +} + +void Sal::enable_nat_helper(bool_t enable) { + this->_nat_helper_enabled=enable; + belle_sip_provider_enable_nat_helper(this->prov,enable); + ms_message("Sal nat helper [%s]",enable?"enabled":"disabled"); +} + +void Sal::get_default_local_ip(int address_family, char *ip, size_t iplen) { + strncpy(ip,address_family==AF_INET6 ? "::1" : "127.0.0.1",iplen); + ms_error("sal_get_default_local_ip() is deprecated."); +} + +void Sal::set_dns_servers(const bctbx_list_t *servers){ + belle_sip_list_t *l = NULL; + + /*we have to convert the bctbx_list_t into a belle_sip_list_t first*/ + for (; servers != NULL; servers = servers->next){ + l = belle_sip_list_append(l, servers->data); + } + belle_sip_stack_set_dns_servers(this->stack, l); + belle_sip_list_free(l); +} + +belle_sip_source_t *Sal::create_timer(belle_sip_source_func_t func, void *data, unsigned int timeout_value_ms, const char* timer_name) { + belle_sip_main_loop_t *ml = belle_sip_stack_get_main_loop(this->stack); + return belle_sip_main_loop_create_timeout(ml, func, data, timeout_value_ms, timer_name); +} + +void Sal::cancel_timer(belle_sip_source_t *timer) { + belle_sip_main_loop_t *ml = belle_sip_stack_get_main_loop(this->stack); + belle_sip_main_loop_remove_source(ml, timer); +} + +belle_sip_response_t* Sal::create_response_from_request (belle_sip_request_t* req, int code ) { + belle_sip_response_t *resp=belle_sip_response_create_from_request(req,code); + belle_sip_message_add_header(BELLE_SIP_MESSAGE(resp),BELLE_SIP_HEADER(this->user_agent)); + belle_sip_message_add_header(BELLE_SIP_MESSAGE(resp), this->supported); + return resp; +} + + + + +/***********************************/ +/* Global functions implementation */ +/***********************************/ + +int to_sip_code(SalReason r) { + int ret=500; + switch(r){ + case SalReasonNone: + ret=200; + break; + case SalReasonIOError: + ret=503; + break; + case SalReasonUnknown: + ret=400; + break; + case SalReasonBusy: + ret=486; + break; + case SalReasonDeclined: + ret=603; + break; + case SalReasonDoNotDisturb: + ret=600; + break; + case SalReasonForbidden: + ret=403; + break; + case SalReasonUnsupportedContent: + ret=415; + break; + case SalReasonNotFound: + ret=404; + break; + case SalReasonRedirect: + ret=302; + break; + case SalReasonTemporarilyUnavailable: + ret=480; + break; + case SalReasonServiceUnavailable: + ret=503; + break; + case SalReasonRequestPending: + ret=491; + break; + case SalReasonUnauthorized: + ret=401; + break; + case SalReasonNotAcceptable: + ret=488; /*or maybe 606 Not Acceptable ?*/ + break; + case SalReasonNoMatch: + ret=481; + break; + case SalReasonRequestTimeout: + ret=408; + break; + case SalReasonMovedPermanently: + ret=301; + break; + case SalReasonGone: + ret=410; + break; + case SalReasonAddressIncomplete: + ret=484; + break; + case SalReasonNotImplemented: + ret=501; + break; + case SalReasonServerTimeout: + ret=504; + break; + case SalReasonBadGateway: + ret=502; + break; + case SalReasonInternalError: + ret=500; + break; + } + return ret; +} + +LINPHONE_END_NAMESPACE + +/*******************************/ +/* C++ to C wrapping functions */ +/*******************************/ + +using namespace LINPHONE_NAMESPACE; + +extern "C" { + +Sal *linphone_core_get_sal(const LinphoneCore *lc) { + return lc->sal; +} + +SalOp *linphone_proxy_config_get_sal_op(const LinphoneProxyConfig *cfg) { + return cfg->op; +} + +SalOp *linphone_call_get_op_as_sal_op(const LinphoneCall *call) { + return linphone_call_get_op(call); +} + +Sal *sal_init(MSFactory *factory) { + return new Sal(factory); +} + +void sal_uninit(Sal* sal) { + delete sal; +} + +int sal_create_uuid(Sal *ctx, char *uuid, size_t len) { + return ctx->create_uuid(uuid, len); +} + +void sal_set_uuid(Sal *ctx, const char *uuid) { + ctx->set_uuid(uuid); +} + +void sal_default_set_sdp_handling(Sal* h, SalOpSDPHandling handling_method) { + h->set_default_sdp_handling(handling_method); +} + +void sal_set_send_error(Sal *sal,int value) { + sal->set_send_error(value); +} + +void sal_set_recv_error(Sal *sal,int value) { + sal->set_recv_error(value); +} + +int sal_enable_pending_trans_checking(Sal *sal, bool_t value) { + return sal->enable_pending_trans_checking(value); +} + +void sal_enable_unconditional_answer(Sal *sal,int value) { + sal->enable_unconditional_answer(value); +} + +void sal_set_dns_timeout(Sal* sal,int timeout) { + sal->set_dns_timeout(timeout); +} + +void sal_set_dns_user_hosts_file(Sal *sal, const char *hosts_file) { + sal->set_dns_user_hosts_file(hosts_file); +} + +void *sal_get_stack_impl(Sal *sal) { + return sal->get_stack_impl(); +} + +void sal_set_refresher_retry_after(Sal *sal,int value) { + sal->set_refresher_retry_after(value); +} + +int sal_get_refresher_retry_after(const Sal *sal) { + return sal->get_refresher_retry_after(); +} + +void sal_set_transport_timeout(Sal* sal,int timeout) { + sal->set_transport_timeout(timeout); +} + +void sal_enable_test_features(Sal*ctx, bool_t enabled) { + ctx->enable_test_features(enabled); +} + +int sal_transport_available(Sal *ctx, SalTransport t) { + return ctx->transport_available(t); +} + +const SalErrorInfo *sal_op_get_error_info(const SalOp *op) { + return op->get_error_info(); +} + +bool_t sal_call_dialog_request_pending(const SalOp *op) { + auto callOp = dynamic_cast(op); + return callOp->dialog_request_pending(); +} + +void sal_call_set_sdp_handling(SalOp *h, SalOpSDPHandling handling) { + auto callOp = dynamic_cast(h); + callOp->set_sdp_handling(handling); +} + +SalMediaDescription * sal_call_get_final_media_description(SalOp *h) { + auto callOp = dynamic_cast(h); + return callOp->get_final_media_description(); +} + +} diff --git a/coreapi/sal/sal.h b/coreapi/sal/sal.h index 1fda7a38a..e45e170cf 100644 --- a/coreapi/sal/sal.h +++ b/coreapi/sal/sal.h @@ -46,22 +46,11 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #endif #endif -#ifdef __cplusplus -extern "C" { -#endif - /*Dirty hack, keep in sync with mediastreamer2/include/mediastream.h */ #ifndef PAYLOAD_TYPE_FLAG_CAN_RECV #define PAYLOAD_TYPE_FLAG_CAN_RECV PAYLOAD_TYPE_USER_FLAG_1 #define PAYLOAD_TYPE_FLAG_CAN_SEND PAYLOAD_TYPE_USER_FLAG_2 #endif -struct Sal; - -typedef struct Sal Sal; - -struct SalOp; - -typedef struct SalOp SalOp; struct SalAddress; @@ -98,7 +87,9 @@ typedef enum { #define SAL_MEDIA_DESCRIPTION_FORCE_STREAM_RECONSTRUCTION (1<<6) /* use force graph reconstruction*/ #define SAL_MEDIA_DESCRIPTION_ICE_RESTART_DETECTED (1<<7) - +#ifdef __cplusplus +extern "C" { +#endif const char* sal_transport_to_string(SalTransport transport); SalTransport sal_transport_parse(const char*); @@ -146,12 +137,12 @@ const char *sal_address_get_password(const SalAddress *addr); void sal_address_set_header(SalAddress *addr, const char *header_name, const char *header_value); const char *sal_address_get_header(const SalAddress *addr, const char *name); -LINPHONE_PUBLIC Sal * sal_init(MSFactory *factory); -LINPHONE_PUBLIC void sal_uninit(Sal* sal); void sal_set_log_handler(BctbxLogFunc log_handler); -void sal_set_user_pointer(Sal *sal, void *user_data); -void *sal_get_user_pointer(const Sal *sal); + +#ifdef __cplusplus +} +#endif typedef enum { @@ -160,7 +151,7 @@ typedef enum { SalText, SalOther } SalStreamType; -const char* sal_stream_type_to_string(SalStreamType type); + typedef enum{ SalProtoRtpAvp, @@ -171,7 +162,6 @@ typedef enum{ SalProtoUdpTlsRtpSavpf, SalProtoOther }SalMediaProto; -const char* sal_media_proto_to_string(SalMediaProto type); typedef enum{ SalStreamSendRecv, @@ -179,8 +169,18 @@ typedef enum{ SalStreamRecvOnly, SalStreamInactive }SalStreamDir; + +#ifdef __cplusplus +extern "C" { +#endif + +const char* sal_stream_type_to_string(SalStreamType type); +const char* sal_media_proto_to_string(SalMediaProto type); const char* sal_stream_dir_to_string(SalStreamDir type); +#ifdef __cplusplus +} +#endif #define SAL_ENDPOINT_CANDIDATE_MAX 2 @@ -254,8 +254,8 @@ typedef struct SalStreamDescription{ char rtcp_cname[256]; int rtp_port; int rtcp_port; - MSList *payloads; /*user_data=(void*)((intptr_t)n); #define payload_type_get_number(pt) ((int)(intptr_t)(pt)->user_data) -/*misc*/ -void sal_get_default_local_ip(Sal *sal, int address_family, char *ip, size_t iplen); +#ifdef __cplusplus +extern "C" { +#endif -LINPHONE_PUBLIC belle_sip_resolver_context_t * sal_resolve_a(Sal* sal, const char *name, int port, int family, belle_sip_resolver_callback_t cb, void *data); -LINPHONE_PUBLIC belle_sip_resolver_context_t * sal_resolve(Sal *sal, const char *service, const char *transport, const char *name, int port, int family, belle_sip_resolver_callback_t cb, void *data); - SalCustomHeader *sal_custom_header_ref(SalCustomHeader *ch); void sal_custom_header_unref(SalCustomHeader *ch); SalCustomHeader *sal_custom_header_append(SalCustomHeader *ch, const char *name, const char *value); @@ -861,9 +638,6 @@ SalCustomHeader *sal_custom_header_remove(SalCustomHeader *ch, const char *name) void sal_custom_header_free(SalCustomHeader *ch); SalCustomHeader *sal_custom_header_clone(const SalCustomHeader *ch); -const SalCustomHeader *sal_op_get_recv_custom_header(SalOp *op); - -void sal_op_set_sent_custom_header(SalOp *op, SalCustomHeader* ch); SalCustomSdpAttribute * sal_custom_sdp_attribute_append(SalCustomSdpAttribute *csa, const char *name, const char *value); @@ -877,50 +651,13 @@ void sal_enable_log(void); void sal_disable_log(void); void sal_set_log_level(OrtpLogLevel level); -/*internal API */ -void __sal_op_init(SalOp *b, Sal *sal); -void __sal_op_set_network_origin(SalOp *op, const char *origin /*a sip uri*/); -void __sal_op_set_network_origin_address(SalOp *op, SalAddress *origin); -void __sal_op_set_remote_contact(SalOp *op, const char *ct); -void __sal_op_free(SalOp *b); - -/*test api*/ -/*0 for no error*/ -LINPHONE_PUBLIC void sal_set_send_error(Sal *sal,int value); -/*1 for no error*/ -LINPHONE_PUBLIC void sal_set_recv_error(Sal *sal,int value); - -/*always answer 480 if value=true*/ -LINPHONE_PUBLIC void sal_enable_unconditional_answer(Sal *sal,int value); - -LINPHONE_PUBLIC bool_t sal_pending_trans_checking_enabled(const Sal *sal) ; -LINPHONE_PUBLIC int sal_enable_pending_trans_checking(Sal *sal, bool_t value) ; - - - -/*refresher retry after value in ms*/ -LINPHONE_PUBLIC void sal_set_refresher_retry_after(Sal *sal,int value); -LINPHONE_PUBLIC int sal_get_refresher_retry_after(const Sal *sal); -/*enable contact fixing*/ -void sal_nat_helper_enable(Sal *sal,bool_t enable); -bool_t sal_nat_helper_enabled(Sal *sal); - -LINPHONE_PUBLIC void sal_set_dns_timeout(Sal* sal,int timeout); -LINPHONE_PUBLIC int sal_get_dns_timeout(const Sal* sal); -LINPHONE_PUBLIC void sal_set_transport_timeout(Sal* sal,int timeout); -LINPHONE_PUBLIC int sal_get_transport_timeout(const Sal* sal); -void sal_set_dns_servers(Sal *sal, const MSList *servers); -LINPHONE_PUBLIC void sal_enable_dns_srv(Sal *sal, bool_t enable); -LINPHONE_PUBLIC bool_t sal_dns_srv_enabled(const Sal *sal); -LINPHONE_PUBLIC void sal_enable_dns_search(Sal *sal, bool_t enable); -LINPHONE_PUBLIC bool_t sal_dns_search_enabled(const Sal *sal); -LINPHONE_PUBLIC void sal_set_dns_user_hosts_file(Sal *sal, const char *hosts_file); -LINPHONE_PUBLIC const char *sal_get_dns_user_hosts_file(const Sal *sal); unsigned int sal_get_random(void); LINPHONE_PUBLIC char *sal_get_random_token(int size); unsigned char * sal_get_random_bytes(unsigned char *ret, size_t size); +#if 0 belle_sip_source_t * sal_create_timer(Sal *sal, belle_sip_source_func_t func, void *data, unsigned int timeout_value_ms, const char* timer_name); void sal_cancel_timer(Sal *sal, belle_sip_source_t *timer); +#endif //SalBodyHandler * sal_body_handler_new(const char *type, const char *subtype, void *data, size_t size, const char *encoding); SalBodyHandler * sal_body_handler_new(void); @@ -944,21 +681,11 @@ const char * sal_body_handler_get_header(const SalBodyHandler *body_handler, con /*this function parses a document with key=value pairs separated by new lines, and extracts the value for a given key*/ int sal_lines_get_value(const char *data, const char *key, char *value, size_t value_size); -LINPHONE_PUBLIC void *sal_get_stack_impl(Sal *sal); -const char* sal_op_get_public_address(SalOp *sal, int *port); -const char* sal_op_get_local_address(SalOp *sal, int *port); unsigned long sal_begin_background_task(const char *name, void (*max_time_reached)(void *), void *data); void sal_end_background_task(unsigned long id); /*Some old equipment may not only rely on attribute sendonly/recvonly/sendrecv/inative*/ -void sal_op_cnx_ip_to_0000_if_sendonly_enable(SalOp *sal,bool_t yesno); -bool_t sal_op_cnx_ip_to_0000_if_sendonly_enabled(SalOp *sal); - -void sal_set_http_proxy_host(Sal *sal, const char *host) ; -void sal_set_http_proxy_port(Sal *sal, int port) ; -const char *sal_get_http_proxy_host(const Sal *sal); -int sal_get_http_proxy_port(const Sal *sal); #ifdef __cplusplus } diff --git a/coreapi/sal/sal.hpp b/coreapi/sal/sal.hpp new file mode 100644 index 000000000..4cc74563b --- /dev/null +++ b/coreapi/sal/sal.hpp @@ -0,0 +1,319 @@ +/* +sal.hpp +Copyright (C) 2017 Belledonne Communications + +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 _SAL_HPP_ +#define _SAL_HPP_ + +#include "sal/sal.h" +#include "linphone/utils/general.h" + +LINPHONE_BEGIN_NAMESPACE + +class SalOp; +class SalCallOp; +class SalMessageOp; +class SalSubscribeOp; +class SalPresenceOp; + +class Sal{ +public: + typedef void (*OnCallReceivedCb)(SalCallOp *op); + typedef void (*OnCallRingingCb)(SalOp *op); + typedef void (*OnCallAcceptedCb)(SalOp *op); + typedef void (*OnCallAckReceivedCb)(SalOp *op, SalCustomHeader *ack); + typedef void (*OnCallAckBeingSentCb)(SalOp *op, SalCustomHeader *ack); + typedef void (*OnCallUpdatingCb)(SalOp *op, bool_t is_update);/* Called when a reINVITE/UPDATE is received*/ + typedef void (*OnCallTerminatedCb)(SalOp *op, const char *from); + typedef void (*OnCallFailureCb)(SalOp *op); + typedef void (*OnCallReleasedCb)(SalOp *salop); + typedef void (*OnCallCancelDoneCb)(SalOp *salop); + typedef void (*OnAuthRequestedLegacyCb)(SalOp *op, const char *realm, const char *username); + typedef bool_t (*OnAuthRequestedCb)(Sal *sal,SalAuthInfo* info); + typedef void (*OnAuthFailureCb)(SalOp *op, SalAuthInfo* info); + typedef void (*OnRegisterSuccessCb)(SalOp *op, bool_t registered); + typedef void (*OnRegisterFailureCb)(SalOp *op); + typedef void (*OnVfuRequestCb)(SalOp *op); + typedef void (*OnDtmfReceivedCb)(SalOp *op, char dtmf); + typedef void (*OnReferCb)(Sal *sal, SalOp *op, const char *referto); + typedef void (*OnMessageReceivedCb)(SalOp *op, const SalMessage *msg); + typedef void (*OnMessageDeliveryUpdateCb)(SalOp *op, SalMessageDeliveryStatus); + typedef void (*OnNotifyReferCb)(SalOp *op, SalReferStatus state); + typedef void (*OnSubscribeResponseCb)(SalOp *op, SalSubscribeStatus status, int will_retry); + typedef void (*OnNotifyCb)(SalSubscribeOp *op, SalSubscribeStatus status, const char *event, SalBodyHandler *body); + typedef void (*OnSubscribeReceivedCb)(SalSubscribeOp *salop, const char *event, const SalBodyHandler *body); + typedef void (*OnIncomingSubscribeClosedCb)(SalOp *salop); + typedef void (*OnParsePresenceRequestedCb)(SalOp *salop, const char *content_type, const char *content_subtype, const char *content, SalPresenceModel **result); + typedef void (*OnConvertPresenceToXMLRequestedCb)(SalOp *salop, SalPresenceModel *presence, const char *contact, char **content); + typedef void (*OnNotifyPresenceCb)(SalOp *op, SalSubscribeStatus ss, SalPresenceModel *model, const char *msg); + typedef void (*OnSubscribePresenceReceivedCb)(SalPresenceOp *salop, const char *from); + typedef void (*OnSubscribePresenceClosedCb)(SalPresenceOp *salop, const char *from); + typedef void (*OnPingReplyCb)(SalOp *salop); + typedef void (*OnInfoReceivedCb)(SalOp *salop, SalBodyHandler *body); + typedef void (*OnPublishResponseCb)(SalOp *salop); + typedef void (*OnNotifyResponseCb)(SalOp *salop); + typedef void (*OnExpireCb)(SalOp *salop); + + struct Callbacks { + OnCallReceivedCb call_received; + OnCallReceivedCb call_rejected; + OnCallRingingCb call_ringing; + OnCallAcceptedCb call_accepted; + OnCallAckReceivedCb call_ack_received; + OnCallAckBeingSentCb call_ack_being_sent; + OnCallUpdatingCb call_updating; + OnCallTerminatedCb call_terminated; + OnCallFailureCb call_failure; + OnCallReleasedCb call_released; + OnCallCancelDoneCb call_cancel_done; + OnAuthFailureCb auth_failure; + OnRegisterSuccessCb register_success; + OnRegisterFailureCb register_failure; + OnVfuRequestCb vfu_request; + OnDtmfReceivedCb dtmf_received; + OnReferCb refer_received; + OnMessageReceivedCb message_received; + OnMessageDeliveryUpdateCb message_delivery_update; + OnNotifyReferCb notify_refer; + OnSubscribeReceivedCb subscribe_received; + OnIncomingSubscribeClosedCb incoming_subscribe_closed; + OnSubscribeResponseCb subscribe_response; + OnNotifyCb notify; + OnSubscribePresenceReceivedCb subscribe_presence_received; + OnSubscribePresenceClosedCb subscribe_presence_closed; + OnParsePresenceRequestedCb parse_presence_requested; + OnConvertPresenceToXMLRequestedCb convert_presence_to_xml_requested; + OnNotifyPresenceCb notify_presence; + OnPingReplyCb ping_reply; + OnAuthRequestedCb auth_requested; + OnInfoReceivedCb info_received; + OnPublishResponseCb on_publish_response; + OnExpireCb on_expire; + OnNotifyResponseCb on_notify_response; + }; + + Sal(MSFactory *factory); + ~Sal(); + + void set_user_pointer(void *user_data) {this->up=user_data;} + void *get_user_pointer() const {return this->up;} + + void set_callbacks(const Callbacks *cbs); + + void *get_stack_impl() {return this->stack;} + + int iterate() {belle_sip_stack_sleep(this->stack,0); return 0;} + + void set_send_error(int value) {belle_sip_stack_set_send_error(this->stack,value);} + void set_recv_error(int value) {belle_sip_provider_set_recv_error(this->prov,value);} + + + /******************/ + /* SIP parameters */ + /******************/ + void set_supported_tags(const char* tags); + const char *get_supported_tags() const {return this->supported ? belle_sip_header_get_unparsed_value(this->supported) : NULL;} + void add_supported_tag(const char* tag); + void remove_supported_tag(const char* tag); + + void set_user_agent(const char *user_agent); + const char* get_user_agent() const; + void append_stack_string_to_user_agent(); + + bool_t content_encoding_available(const char *content_encoding) {return (bool_t)belle_sip_stack_content_encoding_available(this->stack, content_encoding);} + bool_t is_content_type_supported(const char *content_type) const; + void add_content_type_support(const char *content_type); + + void set_default_sdp_handling(SalOpSDPHandling sdp_handling_method); + + void set_uuid(const char *uuid); + int create_uuid(char *uuid, size_t len); + static int generate_uuid(char *uuid, size_t len); + + void enable_nat_helper(bool_t enable); + bool_t nat_helper_enabled() const {return this->_nat_helper_enabled;} + + bool_t pending_trans_checking_enabled() const {return this->pending_trans_checking;} + int enable_pending_trans_checking(bool_t value) {this->pending_trans_checking = value; return 0;} + + void set_refresher_retry_after(int value) {this->refresher_retry_after=value;} + int get_refresher_retry_after() const {return this->refresher_retry_after;} + + void enable_sip_update_method(bool_t value) {this->enable_sip_update=value;} + void use_session_timers(int expires) {this->session_expires=expires;} + void use_dates(bool_t enabled) {this->_use_dates=enabled;} + void use_one_matching_codec_policy(bool_t one_matching_codec) {this->one_matching_codec=one_matching_codec;} + void use_rport(bool_t use_rports); + void enable_auto_contacts(bool_t enabled) {this->auto_contacts=enabled;} + void enable_test_features(bool_t enabled) {this->_enable_test_features=enabled;} + void use_no_initial_route(bool_t enabled) {this->no_initial_route=enabled;} + void enable_unconditional_answer(int value) {belle_sip_provider_enable_unconditional_answer(this->prov,value);} + + bctbx_list_t *get_pending_auths() const {return bctbx_list_copy(this->pending_auths);} + + + /**********************/ + /* Network parameters */ + /**********************/ + int set_listen_port(const char *addr, int port, SalTransport tr, bool_t is_tunneled); + int get_listening_port(SalTransport tr); + int transport_available(SalTransport t); + + void get_default_local_ip(int address_family, char *ip, size_t iplen); + + void set_transport_timeout(int timeout) {belle_sip_stack_set_transport_timeout(this->stack, timeout);} + int get_transport_timeout() const {return belle_sip_stack_get_transport_timeout(this->stack);} + + void set_keepalive_period(unsigned int value); + unsigned int get_keepalive_period() const {return this->keep_alive;} + void use_tcp_tls_keepalive(bool_t enabled) {this->use_tcp_tls_keep_alive=enabled;} + + void set_dscp(int dscp) {belle_sip_stack_set_default_dscp(this->stack,dscp);} + + int set_tunnel(void *tunnelclient); + + void set_http_proxy_host(const char *host) {belle_sip_stack_set_http_proxy_host(this->stack, host);} + const char *get_http_proxy_host() const {return belle_sip_stack_get_http_proxy_host(this->stack);} + + void set_http_proxy_port(int port) {belle_sip_stack_set_http_proxy_port(this->stack, port);} + int get_http_proxy_port() const {return belle_sip_stack_get_http_proxy_port(this->stack);} + + ortp_socket_t get_socket() const; + + int unlisten_ports(); + int reset_transports(); + + + /******************/ + /* TLS parameters */ + /******************/ + void set_ssl_config(void *ssl_config); + void set_root_ca(const char* rootCa); + void set_root_ca_data(const char* data); + const char *get_root_ca() const {return this->root_ca;} + + void verify_server_certificates(bool_t verify); + void verify_server_cn(bool_t verify); + + + /******************/ + /* DNS resolution */ + /******************/ + void set_dns_timeout(int timeout) {belle_sip_stack_set_dns_timeout(this->stack, timeout);} + int get_dns_timeout() const {return belle_sip_stack_get_dns_timeout(this->stack);} + + void set_dns_servers(const bctbx_list_t *servers); + + void enable_dns_search(bool_t enable) {belle_sip_stack_enable_dns_search(this->stack, (unsigned char)enable);} + bool_t dns_search_enabled() const {return (bool_t)belle_sip_stack_dns_search_enabled(this->stack);} + + void enable_dns_srv(bool_t enable) {belle_sip_stack_enable_dns_srv(this->stack, (unsigned char)enable);} + bool_t dns_srv_enabled() const {return (bool_t)belle_sip_stack_dns_srv_enabled(this->stack);} + + void set_dns_user_hosts_file(const char *hosts_file) {belle_sip_stack_set_dns_user_hosts_file(this->stack, hosts_file);} + const char *get_dns_user_hosts_file() const {return belle_sip_stack_get_dns_user_hosts_file(this->stack);} + + belle_sip_resolver_context_t *resolve_a(const char *name, int port, int family, belle_sip_resolver_callback_t cb, void *data) + {return belle_sip_stack_resolve_a(this->stack,name,port,family,cb,data);} + belle_sip_resolver_context_t *resolve(const char *service, const char *transport, const char *name, int port, int family, belle_sip_resolver_callback_t cb, void *data) + {return belle_sip_stack_resolve(this->stack, service, transport, name, port, family, cb, data);} + + + /**********/ + /* Timers */ + /**********/ + belle_sip_source_t *create_timer(belle_sip_source_func_t func, void *data, unsigned int timeout_value_ms, const char* timer_name); + void cancel_timer(belle_sip_source_t *timer); + + +private: + struct sal_uuid_t { + unsigned int time_low; + unsigned short time_mid; + unsigned short time_hi_and_version; + unsigned char clock_seq_hi_and_reserved; + unsigned char clock_seq_low; + unsigned char node[6]; + }; + + void set_tls_properties(); + int add_listen_port(SalAddress* addr, bool_t is_tunneled); + void make_supported_header(); + void add_pending_auth(SalOp *op); + void remove_pending_auth(SalOp *op); + belle_sip_response_t* create_response_from_request (belle_sip_request_t* req, int code ); + + static void unimplemented_stub() {ms_warning("Unimplemented SAL callback");} + static void remove_listening_point(belle_sip_listening_point_t* lp,belle_sip_provider_t* prov) {belle_sip_provider_remove_listening_point(prov,lp);} + + /* Internal callbacks */ + static void process_dialog_terminated_cb(void *sal, const belle_sip_dialog_terminated_event_t *event); + static void process_io_error_cb(void *user_ctx, const belle_sip_io_error_event_t *event); + static void process_request_event_cb(void *ud, const belle_sip_request_event_t *event); + static void process_response_event_cb(void *user_ctx, const belle_sip_response_event_t *event); + static void process_timeout_cb(void *user_ctx, const belle_sip_timeout_event_t *event); + static void process_transaction_terminated_cb(void *user_ctx, const belle_sip_transaction_terminated_event_t *event); + static void process_auth_requested_cb(void *sal, belle_sip_auth_event_t *event); + + MSFactory *factory = NULL; + Callbacks callbacks = {0}; + MSList *pending_auths = NULL;/*MSList of SalOp */ + belle_sip_stack_t* stack = NULL; + belle_sip_provider_t *prov = NULL; + belle_sip_header_user_agent_t* user_agent = NULL; + belle_sip_listener_t *listener = NULL; + void *tunnel_client = NULL; + void *up = NULL; /*user pointer*/ + int session_expires = 0; + unsigned int keep_alive = 0; + char *root_ca = NULL; + char *root_ca_data = NULL; + char *uuid = NULL; + int refresher_retry_after = 60000; /*retry after value for refresher*/ + MSList *supported_tags = NULL;/*list of char * */ + belle_sip_header_t *supported = NULL; + bool_t one_matching_codec = FALSE; + bool_t use_tcp_tls_keep_alive = FALSE; + bool_t _nat_helper_enabled = FALSE; + bool_t tls_verify = TRUE; + bool_t tls_verify_cn = TRUE; + bool_t _use_dates = FALSE; + bool_t auto_contacts = TRUE; + bool_t _enable_test_features = FALSE; + bool_t no_initial_route = FALSE; + bool_t enable_sip_update = TRUE; /*true by default*/ + SalOpSDPHandling default_sdp_handling = SalOpSDPNormal; + bool_t pending_trans_checking = TRUE; /*testing purpose*/ + void *ssl_config = NULL; + bctbx_list_t *supported_content_types = NULL; /* list of char* */ + + friend class SalOp; + friend class SalCallOp; + friend class SalRegisterOp; + friend class SalMessageOp; + friend class SalPresenceOp; + friend class SalSubscribeOp; + friend class SalPublishOp; +}; + +int to_sip_code(SalReason r); + +LINPHONE_END_NAMESPACE + + +#endif // _LINPHONE_SAL_HH diff --git a/coreapi/sal/sal_op.cpp b/coreapi/sal/sal_op.cpp new file mode 100644 index 000000000..e2fa78e09 --- /dev/null +++ b/coreapi/sal/sal_op.cpp @@ -0,0 +1,1025 @@ +#include +#include "sal_op.h" +#include "bellesip_sal/sal_impl.h" + +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +SalOp::SalOp(Sal *sal) { + this->root = sal; + this->sdp_handling = sal->default_sdp_handling; + memset(&this->error_info, 0, sizeof(this->error_info)); + memset(&this->reason_error_info, 0, sizeof(this->reason_error_info)); + ref(); +} + +SalOp::~SalOp() { + ms_message("Destroying op [%p] of type [%s]",this,to_string(this->type)); + + if (this->pending_auth_transaction) belle_sip_object_unref(this->pending_auth_transaction); + this->root->remove_pending_auth(this); + if (this->auth_info) { + sal_auth_info_delete(this->auth_info); + } + if (this->sdp_answer) belle_sip_object_unref(this->sdp_answer); + if (this->refresher) { + belle_sip_object_unref(this->refresher); + this->refresher=NULL; + } + if (this->result) + sal_media_description_unref(this->result); + if(this->replaces) belle_sip_object_unref(this->replaces); + if(this->referred_by) belle_sip_object_unref(this->referred_by); + + if (this->pending_client_trans) belle_sip_object_unref(this->pending_client_trans); + if (this->pending_server_trans) belle_sip_object_unref(this->pending_server_trans); + if (this->pending_update_server_trans) belle_sip_object_unref(this->pending_update_server_trans); + if (this->event) belle_sip_object_unref(this->event); + + sal_error_info_reset(&this->error_info); + if (this->from_address){ + sal_address_destroy(this->from_address); + this->from_address=NULL; + } + if (this->to_address){ + sal_address_destroy(this->to_address); + this->to_address=NULL; + } + + if (this->service_route){ + sal_address_destroy(this->service_route); + this->service_route=NULL; + } + + if (this->origin_address){ + sal_address_destroy(this->origin_address); + this->origin_address=NULL; + } + + if (this->from) { + ms_free(this->from); + this->from=NULL; + } + if (this->to) { + ms_free(this->to); + this->to=NULL; + } + if (this->route) { + ms_free(this->route); + this->route=NULL; + } + if (this->realm) { + ms_free(this->realm); + this->realm=NULL; + } + if (this->contact_address) { + sal_address_destroy(this->contact_address); + } + if (this->origin){ + ms_free(this->origin); + this->origin=NULL; + } + if (this->remote_ua){ + ms_free(this->remote_ua); + this->remote_ua=NULL; + } + if (this->remote_contact){ + ms_free(this->remote_contact); + this->remote_contact=NULL; + } + if (this->remote_contact_address){ + sal_address_destroy(this->remote_contact_address); + } + if (this->local_media) + sal_media_description_unref(this->local_media); + if (this->remote_media) + sal_media_description_unref(this->remote_media); + if (this->custom_body) { + sal_custom_body_unref(this->custom_body); + } + if (this->call_id) + ms_free((void *)this->call_id); + if (this->service_route) { + sal_address_destroy(this->service_route); + } + if (this->route_addresses){ + bctbx_list_for_each(this->route_addresses,(void (*)(void*)) sal_address_destroy); + this->route_addresses=bctbx_list_free(this->route_addresses); + } + if (this->recv_custom_headers) + sal_custom_header_free(this->recv_custom_headers); + if (this->sent_custom_headers) + sal_custom_header_free(this->sent_custom_headers); + + if (this->entity_tag != NULL){ + ms_free(this->entity_tag); + this->entity_tag = NULL; + } +} + +SalOp *SalOp::ref() { + _ref++; + return this; +} + +void *SalOp::unref() { + _ref--; + if (_ref==0) { + delete this; + } else if (_ref<0) { + ms_fatal("SalOp [%p]: too many unrefs.",this); + } + return NULL; +} + +void SalOp::set_contact_address(const SalAddress *address) { + if (this->contact_address) sal_address_destroy(this->contact_address); + this->contact_address=address?sal_address_clone(address):NULL; +} + +void SalOp::assign_address(SalAddress** address, const char *value) { + if (*address){ + sal_address_destroy(*address); + *address=NULL; + } + if (value) + *address=sal_address_new(value); +} + +void SalOp::assign_string(char **str, const char *arg) { + if (*str){ + ms_free(*str); + *str=NULL; + } + if (arg) + *str=ms_strdup(arg); +} + +void SalOp::set_route(const char *route) { + char* route_string=NULL; + if (this->route_addresses) { + bctbx_list_for_each(this->route_addresses,(void (*)(void *))sal_address_destroy); + this->route_addresses=bctbx_list_free(this->route_addresses); + } + if (route) { + this->route_addresses=bctbx_list_append(NULL,NULL); + assign_address((SalAddress**)&(this->route_addresses->data),route); + route_string=sal_address_as_string((SalAddress*)this->route_addresses->data); + } + assign_string(&this->route,route_string); + if(route_string) ms_free(route_string); +} + +void SalOp::set_route_address(const SalAddress *address){ + char* address_string=sal_address_as_string(address); /*can probably be optimized*/ + set_route(address_string); + ms_free(address_string); +} + +void SalOp::add_route_address(const SalAddress *address) { + if (this->route_addresses) { + this->route_addresses=bctbx_list_append(this->route_addresses,(void*)sal_address_clone(address)); + } else { + set_route_address(address); + } +} + +void SalOp::set_realm(const char *realm) { + if (this->realm != NULL){ + ms_free(this->realm); + } + this->realm = ms_strdup(realm); +} + +#define SET_PARAM(name) \ + char* name##_string=NULL; \ + assign_address(&this->name##_address,name); \ + if (this->name##_address) { \ + name##_string=sal_address_as_string(this->name##_address); \ + }\ + assign_string(&this->name,name##_string); \ + if(name##_string) ms_free(name##_string); + +void SalOp::set_from(const char *from){ + SET_PARAM(from); +} + +void SalOp::set_from_address(const SalAddress *from) { + char* address_string=sal_address_as_string(from); /*can probably be optimized*/ + set_from(address_string); + ms_free(address_string); +} + +void SalOp::set_to(const char *to) { + SET_PARAM(to); +} + +void SalOp::set_to_address(const SalAddress *to) { + char* address_string=sal_address_as_string(to); /*can probably be optimized*/ + set_to(address_string); + ms_free(address_string); +} + +void SalOp::set_diversion_address(const SalAddress *diversion) { + if (this->diversion_address) sal_address_destroy(this->diversion_address); + this->diversion_address=diversion ? sal_address_clone(diversion) : NULL; +} + +int SalOp::refresh() { + if (this->refresher) { + belle_sip_refresher_refresh(this->refresher,belle_sip_refresher_get_expires(this->refresher)); + return 0; + } + ms_warning("sal_refresh on op [%p] of type [%s] no refresher",this,to_string(this->type)); + return -1; +} + +void SalOp::kill_dialog() { + ms_warning("op [%p]: force kill of dialog [%p]", this, this->dialog); + belle_sip_dialog_delete(this->dialog); +} + +void SalOp::release() { + /*if in terminating state, keep this state because it means we are waiting for a response to be able to terminate the operation.*/ + if (this->state!=State::Terminating) + this->state=State::Terminated; + set_user_pointer(NULL);/*mandatory because releasing op doesn't not mean freeing op. Make sure back pointer will not be used later*/ + if (this->release_cb) + this->release_cb(this); + if (this->refresher) { + belle_sip_refresher_stop(this->refresher); + } + this->op_released = TRUE; + unref(); +} + +int SalOp::send_request_with_contact(belle_sip_request_t* request, bool_t add_contact) { + belle_sip_client_transaction_t* client_transaction; + belle_sip_provider_t* prov=this->root->prov; + belle_sip_uri_t* outbound_proxy=NULL; + belle_sip_header_contact_t* contact; + int result =-1; + belle_sip_uri_t *next_hop_uri=NULL; + + if (add_contact && !belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(request),belle_sip_header_contact_t)) { + contact = create_contact(); + belle_sip_message_set_header(BELLE_SIP_MESSAGE(request),BELLE_SIP_HEADER(contact)); + } /*keep existing*/ + + add_custom_headers((belle_sip_message_t*)request); + + if (!this->dialog || belle_sip_dialog_get_state(this->dialog) == BELLE_SIP_DIALOG_NULL) { + /*don't put route header if dialog is in confirmed state*/ + const MSList *elem=get_route_addresses(); + const char *transport; + const char *method=belle_sip_request_get_method(request); + belle_sip_listening_point_t *udplp=belle_sip_provider_get_listening_point(prov,"UDP"); + + if (elem) { + outbound_proxy=belle_sip_header_address_get_uri((belle_sip_header_address_t*)elem->data); + next_hop_uri=outbound_proxy; + }else{ + next_hop_uri=(belle_sip_uri_t*)belle_sip_object_clone((belle_sip_object_t*)belle_sip_request_get_uri(request)); + } + transport=belle_sip_uri_get_transport_param(next_hop_uri); + if (transport==NULL){ + /*compatibility mode: by default it should be udp as not explicitely set and if no udp listening point is available, then use + * the first available transport*/ + if (!belle_sip_uri_is_secure(next_hop_uri)){ + if (udplp==NULL){ + if (belle_sip_provider_get_listening_point(prov,"TCP")!=NULL){ + transport="tcp"; + }else if (belle_sip_provider_get_listening_point(prov,"TLS")!=NULL ){ + transport="tls"; + } + } + if (transport){ + belle_sip_message("Transport is not specified, using %s because UDP is not available.",transport); + belle_sip_uri_set_transport_param(next_hop_uri,transport); + } + } + }else{ +#ifdef TUNNEL_ENABLED + if (udplp && BELLE_SIP_OBJECT_IS_INSTANCE_OF(udplp,belle_sip_tunnel_listening_point_t)){ + /* our tunnel mode only supports UDP. Force transport to be set to UDP */ + belle_sip_uri_set_transport_param(next_hop_uri,"udp"); + } +#endif + } + /*because in case of tunnel, transport can be changed*/ + transport=belle_sip_uri_get_transport_param(next_hop_uri); + + if ((strcmp(method,"REGISTER")==0 || strcmp(method,"SUBSCRIBE")==0) && transport && + (strcasecmp(transport,"TCP")==0 || strcasecmp(transport,"TLS")==0)){ + /*RFC 5923: add 'alias' parameter to tell the server that we want it to keep the connection for future requests*/ + belle_sip_header_via_t *via=belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(request),belle_sip_header_via_t); + belle_sip_parameters_set_parameter(BELLE_SIP_PARAMETERS(via),"alias",NULL); + } + } + + client_transaction = belle_sip_provider_create_client_transaction(prov,request); + belle_sip_transaction_set_application_data(BELLE_SIP_TRANSACTION(client_transaction),ref()); + if (this->pending_client_trans) belle_sip_object_unref(this->pending_client_trans); + + this->pending_client_trans=client_transaction; /*update pending inv for being able to cancel*/ + belle_sip_object_ref(this->pending_client_trans); + + if (belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(request),belle_sip_header_user_agent_t)==NULL) + belle_sip_message_add_header(BELLE_SIP_MESSAGE(request),BELLE_SIP_HEADER(this->root->user_agent)); + + if (!belle_sip_message_get_header(BELLE_SIP_MESSAGE(request),BELLE_SIP_AUTHORIZATION) + && !belle_sip_message_get_header(BELLE_SIP_MESSAGE(request),BELLE_SIP_PROXY_AUTHORIZATION)) { + /*hmm just in case we already have authentication param in cache*/ + belle_sip_provider_add_authorization(this->root->prov,request,NULL,NULL,NULL,this->realm); + } + result = belle_sip_client_transaction_send_request_to(client_transaction,next_hop_uri/*might be null*/); + + /*update call id if not set yet for this OP*/ + if (result == 0 && !this->call_id) { + this->call_id=ms_strdup(belle_sip_header_call_id_get_call_id(BELLE_SIP_HEADER_CALL_ID(belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(request), belle_sip_header_call_id_t)))); + } + + return result; + +} + +int SalOp::send_request(belle_sip_request_t* request) { + bool_t need_contact=FALSE; + if (request==NULL) { + return -1; /*sanity check*/ + } + /* + Header field where proxy ACK BYE CAN INV OPT REG + ___________________________________________________________ + Contact R o - - m o o + */ + if (strcmp(belle_sip_request_get_method(request),"INVITE")==0 + ||strcmp(belle_sip_request_get_method(request),"REGISTER")==0 + ||strcmp(belle_sip_request_get_method(request),"SUBSCRIBE")==0 + ||strcmp(belle_sip_request_get_method(request),"OPTIONS")==0 + ||strcmp(belle_sip_request_get_method(request),"REFER")==0) /* Despite contact seems not mandatory, call flow example show a Contact in REFER requests*/ + need_contact=TRUE; + + return send_request_with_contact(request,need_contact); +} + +void SalOp::resend_request(belle_sip_request_t* request) { + belle_sip_header_cseq_t* cseq=(belle_sip_header_cseq_t*)belle_sip_message_get_header(BELLE_SIP_MESSAGE(request),BELLE_SIP_CSEQ); + belle_sip_header_cseq_set_seq_number(cseq,belle_sip_header_cseq_get_seq_number(cseq)+1); + send_request(request); +} + +void SalOp::process_authentication() { + belle_sip_request_t* initial_request=belle_sip_transaction_get_request((belle_sip_transaction_t*)this->pending_auth_transaction); + belle_sip_request_t* new_request; + bool_t is_within_dialog=FALSE; + belle_sip_list_t* auth_list=NULL; + belle_sip_auth_event_t* auth_event; + belle_sip_response_t *response=belle_sip_transaction_get_response((belle_sip_transaction_t*)this->pending_auth_transaction); + belle_sip_header_from_t *from=belle_sip_message_get_header_by_type(initial_request,belle_sip_header_from_t); + belle_sip_uri_t *from_uri=belle_sip_header_address_get_uri((belle_sip_header_address_t*)from); + + if (strcasecmp(belle_sip_uri_get_host(from_uri),"anonymous.invalid")==0){ + /*prefer using the from from the SalOp*/ + from_uri=belle_sip_header_address_get_uri((belle_sip_header_address_t*)get_from_address()); + } + + if (this->dialog && belle_sip_dialog_get_state(this->dialog)==BELLE_SIP_DIALOG_CONFIRMED) { + new_request = belle_sip_dialog_create_request_from(this->dialog,initial_request); + if (!new_request) + new_request = belle_sip_dialog_create_queued_request_from(this->dialog,initial_request); + is_within_dialog=TRUE; + } else { + new_request=initial_request; + belle_sip_message_remove_header(BELLE_SIP_MESSAGE(new_request),BELLE_SIP_AUTHORIZATION); + belle_sip_message_remove_header(BELLE_SIP_MESSAGE(new_request),BELLE_SIP_PROXY_AUTHORIZATION); + } + if (new_request==NULL) { + ms_error("sal_process_authentication() op=[%p] cannot obtain new request from dialog.",this); + return; + } + + if (belle_sip_provider_add_authorization(this->root->prov,new_request,response,from_uri,&auth_list,this->realm)) { + if (is_within_dialog) { + send_request(new_request); + } else { + resend_request(new_request); + } + this->root->remove_pending_auth(this); + }else { + belle_sip_header_from_t *from=belle_sip_message_get_header_by_type(response,belle_sip_header_from_t); + char *tmp=belle_sip_object_to_string(belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(from))); + ms_message("No auth info found for [%s]",tmp); + belle_sip_free(tmp); + this->root->add_pending_auth(this); + + if (is_within_dialog) { + belle_sip_object_unref(new_request); + } + } + /*always store auth info, for case of wrong credential*/ + if (this->auth_info) { + sal_auth_info_delete(this->auth_info); + this->auth_info=NULL; + } + if (auth_list){ + auth_event=(belle_sip_auth_event_t*)(auth_list->data); + this->auth_info=sal_auth_info_create(auth_event); + belle_sip_list_free_with_data(auth_list,(void (*)(void*))belle_sip_auth_event_destroy); + } +} + +char *SalOp::get_dialog_id() const { + if (this->dialog != NULL) { + return ms_strdup_printf("%s;to-tag=%s;from-tag=%s", this->call_id, + belle_sip_dialog_get_remote_tag(this->dialog), belle_sip_dialog_get_local_tag(this->dialog)); + } + return NULL; +} + +int SalOp::get_address_family() const { + belle_sip_transaction_t *tr=NULL; + belle_sip_header_address_t *contact; + + + if (this->refresher) + tr=(belle_sip_transaction_t *)belle_sip_refresher_get_transaction(this->refresher); + + if (tr==NULL) + tr=(belle_sip_transaction_t *)this->pending_client_trans; + if (tr==NULL) + tr=(belle_sip_transaction_t *)this->pending_server_trans; + + if (tr==NULL){ + ms_error("Unable to determine IP version from signaling operation."); + return AF_UNSPEC; + } + + + if (this->refresher) { + belle_sip_response_t *resp = belle_sip_transaction_get_response(tr); + belle_sip_header_via_t *via = resp ?belle_sip_message_get_header_by_type(resp,belle_sip_header_via_t):NULL; + if (!via){ + ms_error("Unable to determine IP version from signaling operation, no via header found."); + return AF_UNSPEC; + } + return (strchr(belle_sip_header_via_get_host(via),':') != NULL) ? AF_INET6 : AF_INET; + } else { + belle_sip_request_t *req = belle_sip_transaction_get_request(tr); + contact=(belle_sip_header_address_t*)belle_sip_message_get_header_by_type(req,belle_sip_header_contact_t); + if (!contact){ + ms_error("Unable to determine IP version from signaling operation, no contact header found."); + } + return sal_address_is_ipv6((SalAddress*)contact) ? AF_INET6 : AF_INET; + } +} + +bool_t SalOp::is_idle() const { + if (this->dialog){ + return !belle_sip_dialog_request_pending(this->dialog); + } + return TRUE; +} + +void SalOp::set_entity_tag(const char* entity_tag) { + if (this->entity_tag != NULL) ms_free(this->entity_tag); + this->entity_tag = entity_tag ? ms_strdup(entity_tag) : NULL; +} + +void SalOp::set_event(const char *eventname) { + belle_sip_header_event_t *header = NULL; + if (this->event) belle_sip_object_unref(this->event); + if (eventname){ + header = belle_sip_header_event_create(eventname); + belle_sip_object_ref(header); + } + this->event = header; +} + +void SalOp::add_initial_route_set(belle_sip_request_t *request, const MSList *list) { + const MSList *elem; + for (elem=list;elem!=NULL;elem=elem->next){ + SalAddress *addr=(SalAddress*)elem->data; + belle_sip_header_route_t *route; + belle_sip_uri_t *uri; + /*Optimization: if the initial route set only contains one URI which is the same as the request URI, ommit it*/ + if (elem==list && list->next==NULL){ + belle_sip_uri_t *requri=belle_sip_request_get_uri(request); + /*skip the first route it is the same as the request uri*/ + if (strcmp(sal_address_get_domain(addr),belle_sip_uri_get_host(requri))==0 ){ + ms_message("Skipping top route of initial route-set because same as request-uri."); + continue; + } + } + + route=belle_sip_header_route_create((belle_sip_header_address_t*)addr); + uri=belle_sip_header_address_get_uri((belle_sip_header_address_t*)route); + belle_sip_uri_set_lr_param(uri,1); + belle_sip_message_add_header((belle_sip_message_t*)request,(belle_sip_header_t*)route); + } +} + +belle_sip_request_t* SalOp::build_request(const char* method) { + belle_sip_header_from_t* from_header; + belle_sip_header_to_t* to_header; + belle_sip_provider_t* prov=this->root->prov; + belle_sip_request_t *req; + belle_sip_uri_t* req_uri; + belle_sip_uri_t* to_uri; + belle_sip_header_call_id_t *call_id_header; + + const SalAddress* to_address; + const MSList *elem=get_route_addresses(); + char token[10]; + + /* check that the op has a correct to address */ + to_address = get_to_address(); + if( to_address == NULL ){ + ms_error("No To: address, cannot build request"); + return NULL; + } + + to_uri = belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(to_address)); + if( to_uri == NULL ){ + ms_error("To: address is invalid, cannot build request"); + return NULL; + } + + if (strcmp("REGISTER",method)==0 || this->privacy==SalPrivacyNone) { + from_header = belle_sip_header_from_create(BELLE_SIP_HEADER_ADDRESS(get_from_address()) + ,belle_sip_random_token(token,sizeof(token))); + } else { + from_header=belle_sip_header_from_create2("Anonymous ",belle_sip_random_token(token,sizeof(token))); + } + /*make sure to preserve components like headers or port*/ + + req_uri = (belle_sip_uri_t*)belle_sip_object_clone((belle_sip_object_t*)to_uri); + belle_sip_uri_set_secure(req_uri,is_secure()); + + to_header = belle_sip_header_to_create(BELLE_SIP_HEADER_ADDRESS(to_address),NULL); + call_id_header = belle_sip_provider_create_call_id(prov); + if (get_call_id()) { + belle_sip_header_call_id_set_call_id(call_id_header, get_call_id()); + } + + req=belle_sip_request_create( + req_uri, + method, + call_id_header, + belle_sip_header_cseq_create(20,method), + from_header, + to_header, + belle_sip_header_via_new(), + 70); + + if (this->privacy & SalPrivacyId) { + belle_sip_header_p_preferred_identity_t* p_preferred_identity=belle_sip_header_p_preferred_identity_create(BELLE_SIP_HEADER_ADDRESS(get_from_address())); + belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(p_preferred_identity)); + } + + if (elem && strcmp(method,"REGISTER")!=0 && !this->root->no_initial_route){ + add_initial_route_set(req,elem); + } + + if (strcmp("REGISTER",method)!=0 && this->privacy!=SalPrivacyNone ){ + belle_sip_header_privacy_t* privacy_header=belle_sip_header_privacy_new(); + if (this->privacy&SalPrivacyCritical) + belle_sip_header_privacy_add_privacy(privacy_header,sal_privacy_to_string(SalPrivacyCritical)); + if (this->privacy&SalPrivacyHeader) + belle_sip_header_privacy_add_privacy(privacy_header,sal_privacy_to_string(SalPrivacyHeader)); + if (this->privacy&SalPrivacyId) + belle_sip_header_privacy_add_privacy(privacy_header,sal_privacy_to_string(SalPrivacyId)); + if (this->privacy&SalPrivacyNone) + belle_sip_header_privacy_add_privacy(privacy_header,sal_privacy_to_string(SalPrivacyNone)); + if (this->privacy&SalPrivacySession) + belle_sip_header_privacy_add_privacy(privacy_header,sal_privacy_to_string(SalPrivacySession)); + if (this->privacy&SalPrivacyUser) + belle_sip_header_privacy_add_privacy(privacy_header,sal_privacy_to_string(SalPrivacyUser)); + belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(privacy_header)); + } + belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),this->root->supported); + return req; +} + +void SalOp::set_error_info_from_response(belle_sip_response_t *response) { + int code = belle_sip_response_get_status_code(response); + const char *reason_phrase=belle_sip_response_get_reason_phrase(response); + belle_sip_header_t *warning=belle_sip_message_get_header(BELLE_SIP_MESSAGE(response),"Warning"); + SalErrorInfo *ei=&this->error_info; + const char *warnings; + + warnings=warning ? belle_sip_header_get_unparsed_value(warning) : NULL; + sal_error_info_set(ei,SalReasonUnknown,"SIP", code,reason_phrase,warnings); + set_reason_error_info(BELLE_SIP_MESSAGE(response)); +} + +const char* SalOp::to_string(const State value) { + switch(value) { + case State::Early: return"SalOpStateEarly"; + case State::Active: return "SalOpStateActive"; + case State::Terminating: return "SalOpStateTerminating"; + case State::Terminated: return "SalOpStateTerminated"; + default: + return "Unknown"; + } +} + +void SalOp::set_reason_error_info(belle_sip_message_t *msg) { + belle_sip_header_reason_t* reason_header = belle_sip_message_get_header_by_type(msg,belle_sip_header_reason_t); + if (reason_header){ + SalErrorInfo *ei=&this->reason_error_info; // ?// + const char *protocol = belle_sip_header_reason_get_protocol(reason_header); + int code = belle_sip_header_reason_get_cause(reason_header); + const char *text = belle_sip_header_reason_get_text(reason_header); + sal_error_info_set(ei, SalReasonUnknown, protocol, code, text, NULL); + } +} + +void SalOp::set_referred_by(belle_sip_header_referred_by_t* referred_by) { + if (this->referred_by){ + belle_sip_object_unref(this->referred_by); + } + + this->referred_by=referred_by; + belle_sip_object_ref(this->referred_by); +} + +void SalOp::set_replaces(belle_sip_header_replaces_t* replaces) { + if (this->replaces){ + belle_sip_object_unref(this->replaces); + } + + this->replaces=replaces; + belle_sip_object_ref(this->replaces); +} + +int SalOp::send_request_with_expires(belle_sip_request_t* request,int expires) { + belle_sip_header_expires_t* expires_header=(belle_sip_header_expires_t*)belle_sip_message_get_header(BELLE_SIP_MESSAGE(request),BELLE_SIP_EXPIRES); + + if (!expires_header && expires>=0) { + belle_sip_message_add_header(BELLE_SIP_MESSAGE(request),BELLE_SIP_HEADER(expires_header=belle_sip_header_expires_new())); + } + if (expires_header) belle_sip_header_expires_set_expires(expires_header,expires); + return send_request(request); +} + +int SalOp::send_and_create_refresher(belle_sip_request_t* req, int expires,belle_sip_refresher_listener_t listener) { + if (send_request_with_expires(req,expires)==0) { + if (this->refresher) { + belle_sip_refresher_stop(this->refresher); + belle_sip_object_unref(this->refresher); + } + if ((this->refresher = belle_sip_client_transaction_create_refresher(this->pending_client_trans))) { + /*since refresher acquires the transaction, we should remove our context from the transaction, because we won't be notified + * that it is terminated anymore.*/ + unref();/*loose the reference that was given to the transaction when creating it*/ + /* Note that the refresher will replace our data with belle_sip_transaction_set_application_data(). + Something in the design is not very good here, it makes things complicated to the belle-sip user. + Possible ideas to improve things: refresher shall not use belle_sip_transaction_set_application_data() internally, refresher should let the first transaction + notify the user as a normal transaction*/ + belle_sip_refresher_set_listener(this->refresher,listener, this); + belle_sip_refresher_set_retry_after(this->refresher,this->root->refresher_retry_after); + belle_sip_refresher_set_realm(this->refresher,this->realm); + belle_sip_refresher_enable_manual_mode(this->refresher, this->manual_refresher); + return 0; + } else { + return -1; + } + } + return -1; +} + +belle_sip_header_contact_t *SalOp::create_contact() { + belle_sip_header_contact_t* contact_header; + belle_sip_uri_t* contact_uri; + + if (get_contact_address()) { + contact_header = belle_sip_header_contact_create(BELLE_SIP_HEADER_ADDRESS(get_contact_address())); + } else { + contact_header= belle_sip_header_contact_new(); + } + + if (!(contact_uri=belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(contact_header)))) { + /*no uri, just creating a new one*/ + contact_uri=belle_sip_uri_new(); + belle_sip_header_address_set_uri(BELLE_SIP_HEADER_ADDRESS(contact_header),contact_uri); + } + + belle_sip_uri_set_user_password(contact_uri,NULL); + belle_sip_uri_set_secure(contact_uri,is_secure()); + if (this->privacy!=SalPrivacyNone){ + belle_sip_uri_set_user(contact_uri,NULL); + } + belle_sip_header_contact_set_automatic(contact_header,this->root->auto_contacts); + if (this->root->uuid){ + if (belle_sip_parameters_has_parameter(BELLE_SIP_PARAMETERS(contact_header),"+sip.instance")==0){ + char *instance_id=belle_sip_strdup_printf("\"\"",this->root->uuid); + belle_sip_parameters_set_parameter(BELLE_SIP_PARAMETERS(contact_header),"+sip.instance",instance_id); + belle_sip_free(instance_id); + } + } + return contact_header; +} + +void SalOp::unlink_op_with_dialog(belle_sip_dialog_t* dialog) { + belle_sip_dialog_set_application_data(dialog,NULL); + unref(); + belle_sip_object_unref(dialog); +} + +belle_sip_dialog_t *SalOp::link_op_with_dialog(belle_sip_dialog_t* dialog) { + belle_sip_dialog_set_application_data(dialog,ref()); + belle_sip_object_ref(dialog); + return dialog; +} + +void SalOp::set_or_update_dialog(belle_sip_dialog_t* dialog) { + ms_message("op [%p] : set_or_update_dialog() current=[%p] new=[%p]", this, this->dialog,dialog); + ref(); + if (this->dialog!=dialog){ + if (this->dialog){ + /*FIXME: shouldn't we delete unconfirmed dialogs ?*/ + unlink_op_with_dialog(this->dialog); + this->dialog=NULL; + } + if (dialog) { + this->dialog=link_op_with_dialog(dialog); + belle_sip_dialog_enable_pending_trans_checking(dialog,this->root->pending_trans_checking); + } + } + unref(); +} + +int SalOp::ping(const char *from, const char *to) { + set_from(from); + set_to(to); + return send_request(build_request("OPTIONS")); +} + +int SalOp::send_info(const char *from, const char *to, const SalBodyHandler *body_handler) { + if (this->dialog && belle_sip_dialog_get_state(this->dialog) == BELLE_SIP_DIALOG_CONFIRMED) { + belle_sip_request_t *req; + belle_sip_dialog_enable_pending_trans_checking(this->dialog,this->root->pending_trans_checking); + req=belle_sip_dialog_create_queued_request(this->dialog,"INFO"); + belle_sip_message_set_body_handler(BELLE_SIP_MESSAGE(req), BELLE_SIP_BODY_HANDLER(body_handler)); + return send_request(req); + }else{ + ms_error("Cannot send INFO message on op [%p] because dialog is not in confirmed state yet.", this); + } + return -1; +} + +SalBodyHandler *SalOp::get_body_handler(belle_sip_message_t *msg) { + belle_sip_body_handler_t *body_handler = belle_sip_message_get_body_handler(msg); + if (body_handler != NULL) { + belle_sip_header_content_type_t *content_type = belle_sip_message_get_header_by_type(msg, belle_sip_header_content_type_t); + belle_sip_header_content_length_t *content_length = belle_sip_message_get_header_by_type(msg, belle_sip_header_content_length_t); + belle_sip_header_t *content_encoding = belle_sip_message_get_header(msg, "Content-Encoding"); + if (content_type != NULL) belle_sip_body_handler_add_header(body_handler, BELLE_SIP_HEADER(content_type)); + if (content_length != NULL) belle_sip_body_handler_add_header(body_handler, BELLE_SIP_HEADER(content_length)); + if (content_encoding != NULL) belle_sip_body_handler_add_header(body_handler, content_encoding); + } + return (SalBodyHandler *)body_handler; +} + +void SalOp::assign_recv_headers(belle_sip_message_t *incoming) { + if (incoming) belle_sip_object_ref(incoming); + if (this->recv_custom_headers){ + belle_sip_object_unref(this->recv_custom_headers); + this->recv_custom_headers=NULL; + } + if (incoming){ + this->recv_custom_headers=(SalCustomHeader*)incoming; + } +} + +void SalOp::set_remote_contact(const char* remote_contact) { + assign_address(&this->remote_contact_address,remote_contact); + /*to preserve header params*/ + assign_string(&this->remote_contact,remote_contact); +} + +void SalOp::set_network_origin(const char *origin) { + SET_PARAM(origin); +} + +void SalOp::set_network_origin_address(SalAddress *origin){ + char* address_string=sal_address_as_string(origin); /*can probably be optimized*/ + set_network_origin(address_string); + ms_free(address_string); +} + +/* +rfc3323 +4.2 Expressing Privacy Preferences +When a Privacy header is constructed, it MUST consist of either the + value 'none', or one or more of the values 'user', 'header' and + 'session' (each of which MUST appear at most once) which MAY in turn + be followed by the 'critical' indicator. + */ +void SalOp::set_privacy_from_message(belle_sip_message_t* msg) { + belle_sip_header_privacy_t* privacy = belle_sip_message_get_header_by_type(msg,belle_sip_header_privacy_t); + if (!privacy) { + set_privacy(SalPrivacyNone); + } else { + belle_sip_list_t* privacy_list=belle_sip_header_privacy_get_privacy(privacy); + set_privacy(0); + for (;privacy_list!=NULL;privacy_list=privacy_list->next) { + char* privacy_value=(char*)privacy_list->data; + if(strcmp(sal_privacy_to_string(SalPrivacyCritical),privacy_value) == 0) + set_privacy(get_privacy()|SalPrivacyCritical); + if(strcmp(sal_privacy_to_string(SalPrivacyHeader),privacy_value) == 0) + set_privacy(get_privacy()|SalPrivacyHeader); + if(strcmp(sal_privacy_to_string(SalPrivacyId),privacy_value) == 0) + set_privacy(get_privacy()|SalPrivacyId); + if(strcmp(sal_privacy_to_string(SalPrivacyNone),privacy_value) == 0) { + set_privacy(SalPrivacyNone); + break; + } + if(strcmp(sal_privacy_to_string(SalPrivacySession),privacy_value) == 0) + set_privacy(get_privacy()|SalPrivacySession); + if(strcmp(sal_privacy_to_string(SalPrivacyUser),privacy_value) == 0) + set_privacy(get_privacy()|SalPrivacyUser); + } + } +} + +void SalOp::set_remote_ua(belle_sip_message_t* message) { + belle_sip_header_user_agent_t* user_agent=belle_sip_message_get_header_by_type(message,belle_sip_header_user_agent_t); + char user_agent_string[256]; + if (user_agent && belle_sip_header_user_agent_get_products_as_string(user_agent,user_agent_string,sizeof(user_agent_string))>0) { + if (this->remote_ua!=NULL){ + ms_free(this->remote_ua); + } + this->remote_ua=ms_strdup(user_agent_string); + } +} + +const char *SalOp::to_string(const Type type) { + switch(type) { + case Type::Register: return "SalOpRegister"; + case Type::Call: return "SalOpCall"; + case Type::Message: return "SalOpMessage"; + case Type::Presence: return "SalOpPresence"; + default: return "SalOpUnknown"; + } +} + +bool_t SalOp::is_secure() const { + const SalAddress* from = get_from_address(); + const SalAddress* to = get_to_address(); + return from && to && strcasecmp("sips",sal_address_get_scheme(from))==0 && strcasecmp("sips",sal_address_get_scheme(to))==0; +} + +/* + * Warning: this function takes owneship of the custom headers + */ +void SalOp::set_sent_custom_header(SalCustomHeader* ch){ + if (this->sent_custom_headers){ + sal_custom_header_free(this->sent_custom_headers); + this->sent_custom_headers=NULL; + } + if (ch) belle_sip_object_ref((belle_sip_message_t*)ch); + this->sent_custom_headers=ch; +} + +void SalOp::add_headers(belle_sip_header_t *h, belle_sip_message_t *msg){ + + if (BELLE_SIP_OBJECT_IS_INSTANCE_OF(h,belle_sip_header_contact_t)){ + belle_sip_header_contact_t* newct; + /*special case for contact, we want to keep everything from the custom contact but set automatic mode and add our own parameters as well*/ + set_contact_address((SalAddress*)BELLE_SIP_HEADER_ADDRESS(h)); + newct = create_contact(); + belle_sip_message_set_header(BELLE_SIP_MESSAGE(msg),BELLE_SIP_HEADER(newct)); + return; + } + /*if a header already exists in the message, replace it*/ + belle_sip_message_set_header(msg,h); + +} + +void SalOp::add_custom_headers(belle_sip_message_t *msg){ + if (this->sent_custom_headers){ + belle_sip_message_t *ch=(belle_sip_message_t*)this->sent_custom_headers; + belle_sip_list_t *l=belle_sip_message_get_all_headers(ch); + belle_sip_list_t *elem; + for(elem=l;elem!=NULL;elem=elem->next){ + add_headers((belle_sip_header_t*)elem->data,msg); + } + belle_sip_list_free(l); + } +} + +int SalOp::unsubscribe(){ + if (this->refresher){ + const belle_sip_transaction_t *tr=(const belle_sip_transaction_t*) belle_sip_refresher_get_transaction(this->refresher); + belle_sip_request_t *last_req=belle_sip_transaction_get_request(tr); + belle_sip_message_set_body(BELLE_SIP_MESSAGE(last_req), NULL, 0); + belle_sip_refresher_refresh(this->refresher,0); + return 0; + } + return -1; +} + +void SalOp::process_incoming_message(const belle_sip_request_event_t *event) { + belle_sip_request_t* req = belle_sip_request_event_get_request(event); + belle_sip_server_transaction_t* server_transaction = belle_sip_provider_create_server_transaction(this->root->prov,req); + belle_sip_header_address_t* address; + belle_sip_header_from_t* from_header; + belle_sip_header_content_type_t* content_type; + belle_sip_response_t* resp; + int errcode = 500; + belle_sip_header_call_id_t* call_id = belle_sip_message_get_header_by_type(req,belle_sip_header_call_id_t); + belle_sip_header_cseq_t* cseq = belle_sip_message_get_header_by_type(req,belle_sip_header_cseq_t); + belle_sip_header_date_t *date=belle_sip_message_get_header_by_type(req,belle_sip_header_date_t); + char* from; + bool_t external_body=FALSE; + + from_header=belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req),belle_sip_header_from_t); + content_type=belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req),belle_sip_header_content_type_t); + + if (content_type) { + SalMessage salmsg; + char message_id[256]={0}; + + if (this->pending_server_trans) belle_sip_object_unref(this->pending_server_trans); + + this->pending_server_trans=server_transaction; + belle_sip_object_ref(this->pending_server_trans); + + external_body=is_external_body(content_type); + address=belle_sip_header_address_create(belle_sip_header_address_get_displayname(BELLE_SIP_HEADER_ADDRESS(from_header)) + ,belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(from_header))); + from=belle_sip_object_to_string(BELLE_SIP_OBJECT(address)); + snprintf(message_id,sizeof(message_id)-1,"%s%i" + ,belle_sip_header_call_id_get_call_id(call_id) + ,belle_sip_header_cseq_get_seq_number(cseq)); + salmsg.from=from; + /* if we just deciphered a message, use the deciphered part(which can be a rcs xml body pointing to the file to retreive from server)*/ + salmsg.text=(!external_body)?belle_sip_message_get_body(BELLE_SIP_MESSAGE(req)):NULL; + salmsg.url=NULL; + salmsg.content_type = ms_strdup_printf("%s/%s", belle_sip_header_content_type_get_type(content_type), belle_sip_header_content_type_get_subtype(content_type)); + if (external_body && belle_sip_parameters_get_parameter(BELLE_SIP_PARAMETERS(content_type),"URL")) { + size_t url_length=strlen(belle_sip_parameters_get_parameter(BELLE_SIP_PARAMETERS(content_type),"URL")); + salmsg.url = ms_strdup(belle_sip_parameters_get_parameter(BELLE_SIP_PARAMETERS(content_type),"URL")+1); /* skip first "*/ + ((char*)salmsg.url)[url_length-2]='\0'; /*remove trailing "*/ + } + salmsg.message_id=message_id; + salmsg.time=date ? belle_sip_header_date_get_time(date) : time(NULL); + this->root->callbacks.message_received(this,&salmsg); + + belle_sip_object_unref(address); + belle_sip_free(from); + if (salmsg.url) ms_free((char*)salmsg.url); + ms_free((char *)salmsg.content_type); + } else { + ms_error("Unsupported MESSAGE (no Content-Type)"); + resp = belle_sip_response_create_from_request(req, errcode); + add_message_accept((belle_sip_message_t*)resp); + belle_sip_server_transaction_send_response(server_transaction,resp); + release(); + } +} + +bool_t SalOp::is_external_body(belle_sip_header_content_type_t* content_type) { + return strcmp("message",belle_sip_header_content_type_get_type(content_type))==0 + && strcmp("external-body",belle_sip_header_content_type_get_subtype(content_type))==0; +} + +int SalOp::reply_message(SalReason reason) { + if (this->pending_server_trans){ + int code=to_sip_code(reason); + belle_sip_response_t *resp = belle_sip_response_create_from_request( + belle_sip_transaction_get_request((belle_sip_transaction_t*)this->pending_server_trans),code); + belle_sip_server_transaction_send_response(this->pending_server_trans,resp); + return 0; + }else ms_error("sal_message_reply(): no server transaction"); + return -1; +} + +void SalOp::add_message_accept(belle_sip_message_t *msg) { + bctbx_list_t *item; + const char *str; + char *old; + char *header = ms_strdup("xml/cipher, application/cipher.vnd.gsma.rcs-ft-http+xml"); + + for (item = this->root->supported_content_types; item != NULL; item = bctbx_list_next(item)) { + str = (const char *)bctbx_list_get_data(item); + old = header; + header = ms_strdup_printf("%s, %s", old, str); + ms_free(old); + } + + belle_sip_message_add_header(msg, belle_sip_header_create("Accept", header)); + ms_free(header); +} + +void SalOp::set_service_route(const SalAddress* service_route) { + if (this->service_route) + sal_address_destroy(this->service_route); + + this->service_route=service_route?sal_address_clone(service_route):NULL; +} + +LINPHONE_END_NAMESPACE diff --git a/coreapi/sal/sal_op.h b/coreapi/sal/sal_op.h new file mode 100644 index 000000000..1a58b2b43 --- /dev/null +++ b/coreapi/sal/sal_op.h @@ -0,0 +1,258 @@ +/* +sal_op.h +Copyright (C) 2017 Belledonne Communications + +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 _SAL_OP_H_ +#define _SAL_OP_H_ + +#include +#include +#include +#include "sal.h" +#include "sal.hpp" + +LINPHONE_BEGIN_NAMESPACE + +class SalOp { +public: + SalOp(Sal *sal); + virtual ~SalOp(); + + SalOp *ref(); + void *unref(); + + Sal *get_sal() const {return this->root;} + + void set_user_pointer(void *up) {this->user_pointer=up;} + void *get_user_pointer() const {return this->user_pointer;} + + + void set_from(const char *from); + void set_from_address(const SalAddress *from); + const char *get_from() const {return this->from;} + const SalAddress *get_from_address() const {return this->from_address;} + + void set_to(const char *to); + void set_to_address(const SalAddress *to); + const char *get_to() const {return this->to;} + const SalAddress *get_to_address() const {return this->to_address;} + + void set_contact_address(const SalAddress* address); + const SalAddress *get_contact_address() const {return this->contact_address;} + + void set_route(const char *route); + void set_route_address(const SalAddress* address); + const bctbx_list_t *get_route_addresses() const {return this->route_addresses;} + void add_route_address(const SalAddress* address); + + void set_diversion_address(const SalAddress *diversion); + const SalAddress *get_diversion_address() const {return this->diversion_address;} + + void set_service_route(const SalAddress* service_route); + const SalAddress *get_service_route() const {return this->service_route;} + + void set_manual_refresher_mode(bool_t enabled) {this->manual_refresher=enabled;} + + void set_entity_tag(const char* entity_tag); + const char *get_entity_tag() const {return this->entity_tag;} + + void set_event(const char *eventname); + + void set_privacy(SalPrivacyMask privacy) {this->privacy=privacy;} + SalPrivacyMask get_privacy() const {return this->privacy;} + + void set_realm(const char *realm); + + void set_sent_custom_header(SalCustomHeader* ch); + + void enable_cnx_ip_to_0000_if_sendonly(bool_t yesno) {this->_cnx_ip_to_0000_if_sendonly_enabled = yesno;} + bool_t cnx_ip_to_0000_if_sendonly_enabled() const {return this->_cnx_ip_to_0000_if_sendonly_enabled;} + + const char *get_proxy() const {return this->route;} + const char *get_network_origin() const {return this->origin;} + const char* get_call_id() const {return this->call_id;} + char* get_dialog_id() const; + int get_address_family() const; + const SalCustomHeader *get_recv_custom_header() const {return this->recv_custom_headers;} + const char *get_remote_contact() const {return this->remote_contact;} + const SalAddress *get_remote_contact_address() const {return this->remote_contact_address;} + const char *get_remote_ua() const {return this->remote_ua;} + + const char *get_public_address(int *port) {return this->refresher ? belle_sip_refresher_get_public_address(this->refresher, port) : NULL;} + const char *get_local_address(int *port) {return this->refresher ? belle_sip_refresher_get_local_address(this->refresher, port) : NULL;} + + const SalErrorInfo *get_error_info() const {return &this->error_info;} + const SalErrorInfo *get_reason_error_info() const {return &this->reason_error_info;} + + bool_t is_forked_of(const SalOp *op2) const {return this->call_id && op2->call_id && strcmp(this->call_id, op2->call_id) == 0;} + bool_t is_idle() const ; + + void stop_refreshing() {if (this->refresher) belle_sip_refresher_stop(this->refresher);} + int refresh(); + void kill_dialog(); + void release(); + + virtual void authenticate(const SalAuthInfo *info) {process_authentication();} + void cancel_authentication() {ms_fatal("sal_op_cancel_authentication not implemented yet");} + SalAuthInfo *get_auth_requested() {return this->auth_info;} + + int ping(const char *from, const char *to); + int send_info(const char *from, const char *to, const SalBodyHandler *body_handler); + +protected: + enum class State { + Early = 0, + Active, + Terminating, /*this state is used to wait until a proceeding state, so we can send the cancel*/ + Terminated + }; + + static const char* to_string(const State value); + + enum class Dir { + Incoming = 0, + Outgoing + }; + + enum class Type { + Unknown, + Register, + Call, + Message, + Presence, + Publish, + Subscribe + }; + + static const char *to_string(const SalOp::Type type); + + typedef void (*ReleaseCb)(SalOp *op); + + virtual void fill_cbs() {} + void release_impl(); + void process_authentication(); + + belle_sip_request_t* build_request(const char* method); + int send_request(belle_sip_request_t* request); + int send_request_with_contact(belle_sip_request_t* request, bool_t add_contact); + int send_request_with_expires(belle_sip_request_t* request,int expires); + void resend_request(belle_sip_request_t* request); + int send_and_create_refresher(belle_sip_request_t* req, int expires,belle_sip_refresher_listener_t listener); + + void set_reason_error_info(belle_sip_message_t *msg); + void set_error_info_from_response(belle_sip_response_t *response); + + void set_referred_by(belle_sip_header_referred_by_t* referred_by); + void set_replaces(belle_sip_header_replaces_t* replaces); + + void set_remote_contact(const char* remote_contact); + void set_network_origin(const char *origin); + void set_network_origin_address(SalAddress *origin); + void set_privacy_from_message(belle_sip_message_t* msg); + void set_remote_ua(belle_sip_message_t* message); + + belle_sip_response_t *create_response_from_request(belle_sip_request_t *req, int code) {return this->root->create_response_from_request(req,code);} + belle_sip_header_contact_t *create_contact(); + + void set_or_update_dialog(belle_sip_dialog_t* dialog); + belle_sip_dialog_t *link_op_with_dialog(belle_sip_dialog_t* dialog); + void unlink_op_with_dialog(belle_sip_dialog_t* dialog); + + SalBodyHandler *get_body_handler(belle_sip_message_t *msg); + + void assign_recv_headers(belle_sip_message_t *incoming); + + bool_t is_secure() const; + void add_headers(belle_sip_header_t *h, belle_sip_message_t *msg); + void add_custom_headers(belle_sip_message_t *msg); + int unsubscribe(); + + void process_incoming_message(const belle_sip_request_event_t *event); + int reply_message(SalReason reason); + void add_message_accept(belle_sip_message_t *msg); + static bool_t is_external_body(belle_sip_header_content_type_t* content_type); + + static void assign_address(SalAddress** address, const char *value); + static void assign_string(char **str, const char *arg); + static void add_initial_route_set(belle_sip_request_t *request, const MSList *list); + + // SalOpBase + Sal *root = NULL; + char *route = NULL; /*or request-uri for REGISTER*/ + MSList* route_addresses = NULL; /*list of SalAddress* */ + SalAddress* contact_address = NULL; + char *from = NULL; + SalAddress* from_address = NULL; + char *to = NULL; + SalAddress* to_address = NULL; + char *origin = NULL; + SalAddress* origin_address = NULL; + SalAddress* diversion_address = NULL; + char *remote_ua = NULL; + SalAddress* remote_contact_address = NULL; + char *remote_contact = NULL; + SalMediaDescription *local_media = NULL; + SalMediaDescription *remote_media = NULL; + SalCustomBody *custom_body = NULL; + void *user_pointer = NULL; + const char* call_id = NULL; + char* realm = NULL; + SalAddress* service_route = NULL; /*as defined by rfc3608, might be a list*/ + SalCustomHeader *sent_custom_headers = NULL; + SalCustomHeader *recv_custom_headers = NULL; + char* entity_tag = NULL; /*as defined by rfc3903 (I.E publih)*/ + ReleaseCb release_cb = NULL; + + // BelleSip implementation + const belle_sip_listener_callbacks_t *callbacks = NULL; + SalErrorInfo error_info; + SalErrorInfo reason_error_info; + belle_sip_client_transaction_t *pending_auth_transaction = NULL; + belle_sip_server_transaction_t* pending_server_trans = NULL; + belle_sip_server_transaction_t* pending_update_server_trans = NULL; + belle_sip_client_transaction_t* pending_client_trans = NULL; + SalAuthInfo* auth_info = NULL; + belle_sip_dialog_t* dialog = NULL; + belle_sip_header_replaces_t *replaces = NULL; + belle_sip_header_referred_by_t *referred_by = NULL; + SalMediaDescription *result = NULL; + belle_sdp_session_description_t *sdp_answer = NULL; + State state = State::Early; + Dir dir = Dir::Incoming; + belle_sip_refresher_t* refresher = NULL; + int _ref = 0; + Type type = Type::Unknown; + SalPrivacyMask privacy = SalPrivacyNone; + belle_sip_header_event_t *event = NULL; /*used by SalOpSubscribe kinds*/ + SalOpSDPHandling sdp_handling = SalOpSDPNormal; + int auth_requests = 0; /*number of auth requested for this op*/ + bool_t _cnx_ip_to_0000_if_sendonly_enabled = FALSE; + bool_t auto_answer_asked = FALSE; + bool_t sdp_offering = FALSE; + bool_t call_released = FALSE; + bool_t manual_refresher = FALSE; + bool_t has_auth_pending = FALSE; + bool_t supports_session_timers = FALSE; + bool_t op_released = FALSE; + + friend class Sal; +}; + +LINPHONE_END_NAMESPACE + +#endif diff --git a/coreapi/tester_utils.cpp b/coreapi/tester_utils.cpp new file mode 100644 index 000000000..77c30ad4c --- /dev/null +++ b/coreapi/tester_utils.cpp @@ -0,0 +1,101 @@ +/* +tester_utils.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 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 "tester_utils.h" +#include "private.h" + +LinphoneVcardContext *linphone_core_get_vcard_context(const LinphoneCore *lc) { + return lc->vcard_context; +} + +void linphone_core_set_zrtp_not_available_simulation(LinphoneCore *lc, bool_t enabled) { + lc->zrtp_not_available_simulation = enabled; +} + +belle_http_provider_t *linphone_core_get_http_provider(const LinphoneCore *lc) { + return lc->http_provider; +} + +void linphone_core_enable_send_call_stats_periodical_updates(LinphoneCore *lc, bool_t enabled) { + lc->send_call_stats_periodical_updates = enabled; +} + +sqlite3 *linphone_core_get_sqlite_database(const LinphoneCore *lc) { + return lc->db; +} + +void linphone_core_set_zrtp_cache_db(LinphoneCore *lc, sqlite3 *cache_db) { + lc->zrtp_cache_db = cache_db; +} + +LinphoneCoreCbs *linphone_core_get_first_callbacks(const LinphoneCore *lc) { + return ((VTableReference *)lc->vtable_refs->data)->cbs; +} + +bctbx_list_t **linphone_core_get_call_logs_attribute(LinphoneCore *lc) { + return &lc->call_logs; +} + +void linphone_core_cbs_set_auth_info_requested(LinphoneCoreCbs *cbs, LinphoneCoreAuthInfoRequestedCb cb) { + cbs->vtable->auth_info_requested = cb; +} + +LinphoneQualityReporting *linphone_call_log_get_quality_reporting(LinphoneCallLog *call_log) { + return &call_log->reporting; +} + +reporting_session_report_t **linphone_quality_reporting_get_reports(LinphoneQualityReporting *qreporting) { + return &qreporting->reports[0]; +} + +const bctbx_list_t *linphone_friend_get_insubs(const LinphoneFriend *fr) { + return fr->insubs; +} + +int linphone_friend_list_get_expected_notification_version(const LinphoneFriendList *list) { + return list->expected_notification_version; +} + +unsigned int linphone_friend_list_get_storage_id(const LinphoneFriendList *list) { + return list->storage_id; +} + +unsigned int linphone_friend_get_storage_id(const LinphoneFriend *lf) { + return lf->storage_id; +} + +void linphone_friend_set_core(LinphoneFriend *lf, LinphoneCore *lc) { + lf->lc = lc; +} + +LinphoneFriendList *linphone_friend_get_friend_list(const LinphoneFriend *lf) { + return lf->friend_list; +} + +bctbx_list_t **linphone_friend_list_get_friends_attribute(LinphoneFriendList *lfl) { + return &lfl->friends; +} + +const bctbx_list_t *linphone_friend_list_get_dirty_friends_to_update(const LinphoneFriendList *lfl) { + return lfl->dirty_friends_to_update; +} + +int linphone_friend_list_get_revision(const LinphoneFriendList *lfl) { + return lfl->revision; +} diff --git a/coreapi/tester_utils.h b/coreapi/tester_utils.h new file mode 100644 index 000000000..26ac68756 --- /dev/null +++ b/coreapi/tester_utils.h @@ -0,0 +1,154 @@ +/* +tester_utils.h +Copyright (C) 2017 Belledonne Communications SARL + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef _TESTER_UTILS_H_ +#define _TESTER_UTILS_H_ + +#include "account_creator_private.h" +#include "linphone/core.h" +#include "linphone/tunnel.h" +#include "sal/sal.h" +#include +#include "quality_reporting.h" +#include "vcard_private.h" + +#ifndef __cplusplus +typedef struct _Sal Sal; +typedef struct _SalOp SalOp; +#endif + +typedef struct _LinphoneQualityReporting LinphoneQualityReporting; + +typedef enum _LinphoneProxyConfigAddressComparisonResult{ + LinphoneProxyConfigAddressDifferent, + LinphoneProxyConfigAddressEqual, + LinphoneProxyConfigAddressWeakEqual +} LinphoneProxyConfigAddressComparisonResult; + +#ifdef __cplusplus +extern "C" { +#endif + +LINPHONE_PUBLIC LinphoneVcardContext *linphone_core_get_vcard_context(const LinphoneCore *lc); +LINPHONE_PUBLIC bool_t linphone_core_rtcp_enabled(const LinphoneCore *lc); +LINPHONE_PUBLIC void linphone_core_get_local_ip(LinphoneCore *lc, int af, const char *dest, char *result); +LINPHONE_PUBLIC void linphone_core_enable_forced_ice_relay(LinphoneCore *lc, bool_t enable); +LINPHONE_PUBLIC void linphone_core_set_zrtp_not_available_simulation(LinphoneCore *lc, bool_t enabled); +LINPHONE_PUBLIC belle_http_provider_t *linphone_core_get_http_provider(const LinphoneCore *lc); +LINPHONE_PUBLIC const char *linphone_core_get_tone_file(const LinphoneCore *lc, LinphoneToneID id); +LINPHONE_PUBLIC IceSession * linphone_call_get_ice_session(const LinphoneCall *call); +LINPHONE_PUBLIC const struct addrinfo *linphone_core_get_stun_server_addrinfo(LinphoneCore *lc); +LINPHONE_PUBLIC void linphone_core_enable_send_call_stats_periodical_updates(LinphoneCore *lc, bool_t enabled); + +LINPHONE_PUBLIC int linphone_run_stun_tests(LinphoneCore *lc, int audioPort, int videoPort, int textPort, + char *audioCandidateAddr, int *audioCandidatePort, char *videoCandidateAddr, int *videoCandidatePort, char *textCandidateAddr, int *textCandidatePort); +LINPHONE_PUBLIC void linphone_core_enable_short_turn_refresh(LinphoneCore *lc, bool_t enable); + +LINPHONE_PUBLIC sqlite3 *linphone_core_get_sqlite_database(const LinphoneCore *lc); +LINPHONE_PUBLIC void linphone_core_set_zrtp_cache_db(LinphoneCore *lc, sqlite3 *cache_db); + +LINPHONE_PUBLIC LinphoneCoreCbs *linphone_core_get_first_callbacks(const LinphoneCore *lc); +LINPHONE_PUBLIC void _linphone_core_add_callbacks(LinphoneCore *lc, LinphoneCoreCbs *vtable, bool_t internal); + +LINPHONE_PUBLIC bctbx_list_t * linphone_core_read_call_logs_from_config_file(LinphoneCore *lc); +LINPHONE_PUBLIC bctbx_list_t **linphone_core_get_call_logs_attribute(LinphoneCore *lc); +LINPHONE_PUBLIC void linphone_core_delete_call_log(LinphoneCore *lc, LinphoneCallLog *log); + +LINPHONE_PUBLIC const MSList *linphone_core_get_call_history(LinphoneCore *lc); +LINPHONE_PUBLIC void linphone_core_delete_call_history(LinphoneCore *lc); +LINPHONE_PUBLIC int linphone_core_get_call_history_size(LinphoneCore *lc); + +LINPHONE_DEPRECATED LINPHONE_PUBLIC void linphone_core_cbs_set_auth_info_requested(LinphoneCoreCbs *cbs, LinphoneCoreAuthInfoRequestedCb cb); + +LINPHONE_PUBLIC LinphoneProxyConfigAddressComparisonResult linphone_proxy_config_is_server_config_changed(const LinphoneProxyConfig* obj); +LINPHONE_PUBLIC LinphoneProxyConfigAddressComparisonResult linphone_proxy_config_address_equal(const LinphoneAddress *a, const LinphoneAddress *b); + +LINPHONE_PUBLIC LinphoneCallLog *linphone_call_get_log(const LinphoneCall *call); +LINPHONE_PUBLIC MediaStream * linphone_call_get_stream(LinphoneCall *call, LinphoneStreamType type); +LINPHONE_PUBLIC bool_t linphone_call_get_all_muted(const LinphoneCall *call); +LINPHONE_PUBLIC LinphoneProxyConfig * linphone_call_get_dest_proxy(const LinphoneCall *call); + +LINPHONE_PUBLIC void linphone_call_params_set_no_user_consent(LinphoneCallParams *params, bool_t value); +LINPHONE_PUBLIC bool_t linphone_call_params_get_update_call_when_ice_completed(const LinphoneCallParams *params); + +LINPHONE_PUBLIC int _linphone_call_stats_get_updated(const LinphoneCallStats *stats); +LINPHONE_PUBLIC bool_t _linphone_call_stats_rtcp_received_via_mux(const LinphoneCallStats *stats); +LINPHONE_PUBLIC mblk_t *_linphone_call_stats_get_received_rtcp (const LinphoneCallStats *stats); + +LINPHONE_PUBLIC LinphoneQualityReporting *linphone_call_log_get_quality_reporting(LinphoneCallLog *call_log); +LINPHONE_PUBLIC reporting_session_report_t **linphone_quality_reporting_get_reports(LinphoneQualityReporting *qreporting); + +LINPHONE_PUBLIC bctbx_list_t * linphone_chat_room_get_transient_messages(const LinphoneChatRoom *cr); + +LINPHONE_PUBLIC MSList* linphone_core_fetch_friends_from_db(LinphoneCore *lc, LinphoneFriendList *list); +LINPHONE_PUBLIC MSList* linphone_core_fetch_friends_lists_from_db(LinphoneCore *lc); +LINPHONE_PUBLIC void linphone_friend_invalidate_subscription(LinphoneFriend *lf); +LINPHONE_PUBLIC void linphone_friend_update_subscribes(LinphoneFriend *fr, bool_t only_when_registered); +LINPHONE_PUBLIC const bctbx_list_t *linphone_friend_get_insubs(const LinphoneFriend *fr); +LINPHONE_PUBLIC int linphone_friend_list_get_expected_notification_version(const LinphoneFriendList *list); +LINPHONE_PUBLIC unsigned int linphone_friend_list_get_storage_id(const LinphoneFriendList *list); +LINPHONE_PUBLIC unsigned int linphone_friend_get_storage_id(const LinphoneFriend *lf); +LINPHONE_PUBLIC void linphone_friend_set_core(LinphoneFriend *lf, LinphoneCore *lc); +LINPHONE_PUBLIC LinphoneFriendList *linphone_friend_get_friend_list(const LinphoneFriend *lf); +LINPHONE_PUBLIC bctbx_list_t **linphone_friend_list_get_friends_attribute(LinphoneFriendList *lfl); +LINPHONE_PUBLIC const bctbx_list_t *linphone_friend_list_get_dirty_friends_to_update(const LinphoneFriendList *lfl); +LINPHONE_PUBLIC int linphone_friend_list_get_revision(const LinphoneFriendList *lfl); + +LINPHONE_PUBLIC int linphone_remote_provisioning_load_file( LinphoneCore* lc, const char* file_path); + + +#ifndef __cplusplus +LINPHONE_PUBLIC Sal *linphone_core_get_sal(const LinphoneCore *lc); +LINPHONE_PUBLIC SalOp *linphone_proxy_config_get_sal_op(const LinphoneProxyConfig *cfg); +LINPHONE_PUBLIC SalOp *linphone_call_get_op_as_sal_op(const LinphoneCall *call); + +LINPHONE_PUBLIC Sal * sal_init(MSFactory *factory); +LINPHONE_PUBLIC void sal_uninit(Sal* sal); + +LINPHONE_PUBLIC int sal_create_uuid(Sal *ctx, char *uuid, size_t len); +LINPHONE_PUBLIC char *sal_get_random_token(int size); +LINPHONE_PUBLIC void sal_set_uuid(Sal *ctx, const char *uuid); + +LINPHONE_PUBLIC void sal_default_set_sdp_handling(Sal* h, SalOpSDPHandling handling_method) ; +LINPHONE_PUBLIC void sal_set_send_error(Sal *sal,int value); +LINPHONE_PUBLIC void sal_set_recv_error(Sal *sal,int value); +LINPHONE_PUBLIC int sal_enable_pending_trans_checking(Sal *sal, bool_t value); +LINPHONE_PUBLIC void sal_enable_unconditional_answer(Sal *sal,int value); +LINPHONE_PUBLIC void sal_set_dns_timeout(Sal* sal,int timeout); +LINPHONE_PUBLIC void sal_set_dns_user_hosts_file(Sal *sal, const char *hosts_file); +LINPHONE_PUBLIC void *sal_get_stack_impl(Sal *sal); +LINPHONE_PUBLIC void sal_set_refresher_retry_after(Sal *sal,int value); +LINPHONE_PUBLIC int sal_get_refresher_retry_after(const Sal *sal); +LINPHONE_PUBLIC void sal_set_transport_timeout(Sal* sal,int timeout); +LINPHONE_PUBLIC void sal_enable_test_features(Sal*ctx, bool_t enabled); +LINPHONE_PUBLIC int sal_transport_available(Sal *ctx, SalTransport t); + +LINPHONE_PUBLIC const SalErrorInfo *sal_op_get_error_info(const SalOp *op); +LINPHONE_PUBLIC bool_t sal_call_dialog_request_pending(const SalOp *op); +LINPHONE_PUBLIC void sal_call_set_sdp_handling(SalOp *h, SalOpSDPHandling handling); +LINPHONE_PUBLIC SalMediaDescription * sal_call_get_final_media_description(SalOp *h); +#endif + +#ifdef __cplusplus +} +#endif + + + +#endif // _TESTER_UTILS_H_ diff --git a/coreapi/vcard.cc b/coreapi/vcard.cc index b002a28c6..0bd71534d 100644 --- a/coreapi/vcard.cc +++ b/coreapi/vcard.cc @@ -32,6 +32,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #define VCARD_MD5_HASH_SIZE 16 using namespace std; +using namespace LINPHONE_NAMESPACE; struct _LinphoneVcardContext { shared_ptr parser; @@ -367,7 +368,7 @@ bool_t linphone_vcard_generate_unique_id(LinphoneVcard *vCard) { if (linphone_vcard_get_uid(vCard)) { return FALSE; } - if (sal_generate_uuid(uuid, sizeof(uuid)) == 0) { + if (Sal::generate_uuid(uuid, sizeof(uuid)) == 0) { char vcard_uuid[sizeof(uuid)+4]; snprintf(vcard_uuid, sizeof(vcard_uuid), "urn:%s", uuid); linphone_vcard_set_uid(vCard, vcard_uuid); diff --git a/src/c-wrapper/api/c-call.cpp b/src/c-wrapper/api/c-call.cpp index a14f73f65..0a83d27b9 100644 --- a/src/c-wrapper/api/c-call.cpp +++ b/src/c-wrapper/api/c-call.cpp @@ -48,8 +48,8 @@ L_DECLARE_C_OBJECT_IMPL_WITH_XTORS(Call, SalMediaDescription *localdesc; SalMediaDescription *resultdesc; struct _LinphoneCallLog *log; - SalOp *op; - SalOp *ping_op; + LINPHONE_NAMESPACE::SalOp *op; + LINPHONE_NAMESPACE::SalOp *ping_op; LinphoneCallState transfer_state; /*idle if no transfer*/ struct _AudioStream *audiostream; /**/ struct _VideoStream *videostream; @@ -113,7 +113,7 @@ static void _linphone_call_destructor (LinphoneCall *call) { call->text_stats = nullptr; } if (call->op) { - sal_op_release(call->op); + call->op->release(); call->op=nullptr; } if (call->resultdesc) { @@ -125,7 +125,7 @@ static void _linphone_call_destructor (LinphoneCall *call) { call->localdesc=nullptr; } if (call->ping_op) { - sal_op_release(call->ping_op); + call->ping_op->release(); call->ping_op=nullptr; } if (call->refer_to){ @@ -325,7 +325,7 @@ int linphone_call_start_invite (LinphoneCall *call, const LinphoneAddress *desti return 0; } -void linphone_call_replace_op (LinphoneCall *call, SalOp *op) { +void linphone_call_replace_op (LinphoneCall *call, LINPHONE_NAMESPACE::SalOp *op) { #if 0 SalOp *oldop = call->op; LinphoneCallState oldstate = linphone_call_get_state(call); @@ -507,7 +507,7 @@ void linphone_call_refresh_sockets (LinphoneCall *call) { #endif } -SalOp * linphone_call_get_op (const LinphoneCall *call) { +LINPHONE_NAMESPACE::SalCallOp * linphone_call_get_op (const LinphoneCall *call) { return L_GET_PRIVATE_FROM_C_OBJECT(call)->getOp(); } @@ -593,7 +593,7 @@ LinphoneCallState linphone_call_get_state (const LinphoneCall *call) { bool_t linphone_call_asked_to_autoanswer (LinphoneCall *call) { //return TRUE if the unique(for the moment) incoming call asked to be autoanswered if (call) - return sal_call_autoanswer_asked(linphone_call_get_op(call)); + return linphone_call_get_op(call)->autoanswer_asked(); return FALSE; } @@ -1107,8 +1107,8 @@ void linphone_call_ogl_render (const LinphoneCall *call) { LinphoneStatus linphone_call_send_info_message (LinphoneCall *call, const LinphoneInfoMessage *info) { SalBodyHandler *body_handler = sal_body_handler_from_content(linphone_info_message_get_content(info)); - sal_op_set_sent_custom_header(linphone_call_get_op(call), linphone_info_message_get_headers(info)); - return sal_send_info(linphone_call_get_op(call), nullptr, nullptr, body_handler); + linphone_call_get_op(call)->set_sent_custom_header(linphone_info_message_get_headers(info)); + return linphone_call_get_op(call)->send_info(nullptr, nullptr, body_handler); } LinphoneCallStats *linphone_call_get_stats (LinphoneCall *call, LinphoneStreamType type) { @@ -1193,7 +1193,7 @@ LinphoneCall *linphone_call_new_outgoing (LinphoneCore *lc, const LinphoneAddres return call; } -LinphoneCall *linphone_call_new_incoming (LinphoneCore *lc, const LinphoneAddress *from, const LinphoneAddress *to, SalOp *op) { +LinphoneCall *linphone_call_new_incoming (LinphoneCore *lc, const LinphoneAddress *from, const LinphoneAddress *to, LINPHONE_NAMESPACE::SalCallOp *op) { LinphoneCall *call = L_INIT(Call); L_SET_CPP_PTR_FROM_C_OBJECT(call, make_shared(call, lc, LinphoneCallIncoming, *L_GET_CPP_PTR_FROM_C_OBJECT(from), *L_GET_CPP_PTR_FROM_C_OBJECT(to), diff --git a/src/c-wrapper/api/c-chat-message.cpp b/src/c-wrapper/api/c-chat-message.cpp index 9ddc5c0e7..1f66d709a 100644 --- a/src/c-wrapper/api/c-chat-message.cpp +++ b/src/c-wrapper/api/c-chat-message.cpp @@ -34,6 +34,7 @@ // ============================================================================= using namespace std; +using namespace LINPHONE_NAMESPACE; static void _linphone_chat_message_constructor (LinphoneChatMessage *msg); static void _linphone_chat_message_destructor (LinphoneChatMessage *msg); diff --git a/src/call/call-p.h b/src/call/call-p.h index c655c9052..69586713c 100644 --- a/src/call/call-p.h +++ b/src/call/call-p.h @@ -61,7 +61,7 @@ public: LinphoneProxyConfig *getDestProxy () const; IceSession *getIceSession () const; MediaStream *getMediaStream (LinphoneStreamType type) const; - SalOp *getOp () const; + SalCallOp *getOp () const; void setAudioMuted (bool value); private: diff --git a/src/call/call.cpp b/src/call/call.cpp index b474f60ee..369f2bfd7 100644 --- a/src/call/call.cpp +++ b/src/call/call.cpp @@ -70,7 +70,7 @@ MediaStream *CallPrivate::getMediaStream (LinphoneStreamType type) const { return static_pointer_cast(getActiveSession())->getPrivate()->getMediaStream(type); } -SalOp *CallPrivate::getOp () const { +SalCallOp * CallPrivate::getOp () const { return getActiveSession()->getPrivate()->getOp(); } @@ -219,7 +219,7 @@ Call::Call ( const Address &from, const Address &to, LinphoneProxyConfig *cfg, - SalOp *op, + SalCallOp *op, const MediaSessionParams *msp ) : Object(*new CallPrivate(call, core, direction, from, to, cfg, op, msp)) { L_D(); diff --git a/src/call/call.h b/src/call/call.h index d809c3563..b42780fb1 100644 --- a/src/call/call.h +++ b/src/call/call.h @@ -43,7 +43,7 @@ public: const Address &from, const Address &to, LinphoneProxyConfig *cfg, - SalOp *op, + SalCallOp *op, const MediaSessionParams *msp ); diff --git a/src/chat/chat-room.cpp b/src/chat/chat-room.cpp index 2ea8fb67f..b29f39575 100644 --- a/src/chat/chat-room.cpp +++ b/src/chat/chat-room.cpp @@ -29,6 +29,7 @@ #include "chat-message-p.h" #include "chat-room.h" +#include "sal/message_op.h" // ============================================================================= @@ -118,7 +119,7 @@ void ChatRoomPrivate::sendImdn (const string &content, LinphoneReason reason) { identity = linphone_core_get_primary_contact(core); /* Sending out of call */ - SalOp *op = sal_op_new(core->sal); + SalMessageOp *op = new SalMessageOp(core->sal); linphone_configure_op(core, op, peer, nullptr, !!lp_config_get_int(core->config, "sip", "chat_msg_with_contact", 0)); LinphoneChatMessage *msg = q->createMessage(content); LinphoneAddress *fromAddr = linphone_address_new(identity); @@ -139,14 +140,14 @@ void ChatRoomPrivate::sendImdn (const string &content, LinphoneReason reason) { } if (retval <= 0) { - sal_message_send(op, identity, peerAddress.asString().c_str(), linphone_chat_message_get_content_type(msg), linphone_chat_message_get_text(msg), nullptr); + op->send_message(identity, peerAddress.asString().c_str(), linphone_chat_message_get_content_type(msg), linphone_chat_message_get_text(msg), nullptr); } linphone_chat_message_unref(msg); linphone_address_unref(fromAddr); linphone_address_unref(toAddr); linphone_address_unref(peer); - sal_op_unref(op); + op->unref(); } // ----------------------------------------------------------------------------- @@ -207,7 +208,7 @@ void ChatRoomPrivate::sendIsComposingNotification () { identity = linphone_core_get_primary_contact(core); /* Sending out of call */ - SalOp *op = sal_op_new(core->sal); + SalMessageOp *op = new SalMessageOp(core->sal); linphone_configure_op(core, op, peer, nullptr, !!lp_config_get_int(core->config, "sip", "chat_msg_with_contact", 0)); string content = isComposingHandler.marshal(isComposing); if (!content.empty()) { @@ -228,12 +229,12 @@ void ChatRoomPrivate::sendIsComposingNotification () { } if (retval <= 0) { - sal_message_send(op, identity, peerAddress.asString().c_str(), linphone_chat_message_get_content_type(msg), linphone_chat_message_get_text(msg), nullptr); + op->send_message(identity, peerAddress.asString().c_str(), linphone_chat_message_get_content_type(msg), linphone_chat_message_get_text(msg), nullptr); } linphone_chat_message_unref(msg); linphone_address_unref(fromAddr); - sal_op_unref(op); + op->unref(); } linphone_address_unref(peer); } @@ -393,7 +394,7 @@ LinphoneReason ChatRoomPrivate::messageReceived (SalOp *op, const SalMessage *sa LinphoneChatMessage *msg; /* Check if this is a duplicate message */ - if ((msg = q->findMessageWithDirection(sal_op_get_call_id(op), LinphoneChatMessageIncoming))) { + if ((msg = q->findMessageWithDirection(op->get_call_id(), LinphoneChatMessageIncoming))) { reason = core->chat_deny_code; if (msg) linphone_chat_message_unref(msg); @@ -406,14 +407,14 @@ LinphoneReason ChatRoomPrivate::messageReceived (SalOp *op, const SalMessage *sa linphone_chat_message_set_from_address(msg, peer); linphone_address_unref(peer); - LinphoneAddress *to = sal_op_get_to(op) ? linphone_address_new(sal_op_get_to(op)) : linphone_address_new(linphone_core_get_identity(core)); + LinphoneAddress *to = op->get_to() ? linphone_address_new(op->get_to()) : linphone_address_new(linphone_core_get_identity(core)); linphone_chat_message_set_to_address(msg, to); linphone_chat_message_set_time(msg, salMsg->time); linphone_chat_message_set_state(msg, LinphoneChatMessageStateDelivered); linphone_chat_message_set_incoming(msg); - linphone_chat_message_set_message_id(msg, ms_strdup(sal_op_get_call_id(op))); + linphone_chat_message_set_message_id(msg, ms_strdup(op->get_call_id())); - const SalCustomHeader *ch = sal_op_get_recv_custom_header(op); + const SalCustomHeader *ch = op->get_recv_custom_header(); if (ch) linphone_chat_message_set_sal_custom_headers(msg, sal_custom_header_clone(ch)); if (salMsg->url) @@ -844,16 +845,16 @@ void ChatRoom::sendMessage (LinphoneChatMessage *msg) { if (!op) { /* Sending out of call */ - linphone_chat_message_set_sal_op(msg, op = sal_op_new(d->core->sal)); + linphone_chat_message_set_sal_op(msg, op = new SalMessageOp(d->core->sal)); linphone_configure_op( d->core, op, peer, linphone_chat_message_get_sal_custom_headers(msg), !!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 */ + op->set_user_pointer(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); + sal_error_info_set((SalErrorInfo *)op->get_error_info(), SalReasonNotAcceptable, "SIP", retval, "Unable to encrypt IM", nullptr); d->storeOrUpdateMessage(msg); linphone_chat_message_update_state(msg, LinphoneChatMessageStateNotDelivered); linphone_chat_message_unref(msg); @@ -863,13 +864,15 @@ void ChatRoom::sendMessage (LinphoneChatMessage *msg) { if (linphone_chat_message_get_external_body_url(msg)) { char *content_type = ms_strdup_printf("message/external-body; access-type=URL; URL=\"%s\"", linphone_chat_message_get_external_body_url(msg)); - sal_message_send(op, identity.c_str(), d->peerAddress.asString().c_str(), content_type, nullptr, nullptr); + auto msgOp = dynamic_cast(op); + msgOp->send_message(identity.c_str(), d->peerAddress.asString().c_str(), content_type, nullptr, nullptr); ms_free(content_type); } else { + auto msgOp = dynamic_cast(op); if (linphone_chat_message_get_content_type(msg)) { - sal_message_send(op, identity.c_str(), d->peerAddress.asString().c_str(), linphone_chat_message_get_content_type(msg), linphone_chat_message_get_text(msg), d->peerAddress.asStringUriOnly().c_str()); + msgOp->send_message(identity.c_str(), d->peerAddress.asString().c_str(), linphone_chat_message_get_content_type(msg), linphone_chat_message_get_text(msg), d->peerAddress.asStringUriOnly().c_str()); } else { - sal_text_send(op, identity.c_str(), d->peerAddress.asString().c_str(), linphone_chat_message_get_text(msg)); + msgOp->send_message(identity.c_str(), d->peerAddress.asString().c_str(), linphone_chat_message_get_text(msg)); } } @@ -881,7 +884,7 @@ void ChatRoom::sendMessage (LinphoneChatMessage *msg) { /* We replace the encrypted content type by the original one */ linphone_chat_message_set_content_type(msg, ms_strdup(clearTextContentType)); } - linphone_chat_message_set_message_id(msg, ms_strdup(sal_op_get_call_id(op))); /* must be known at that time */ + linphone_chat_message_set_message_id(msg, ms_strdup(op->get_call_id())); /* must be known at that time */ d->storeOrUpdateMessage(msg); if (d->isComposing) diff --git a/src/chat/client-group-chat-room.cpp b/src/chat/client-group-chat-room.cpp index 961adb590..57e65cdc1 100644 --- a/src/chat/client-group-chat-room.cpp +++ b/src/chat/client-group-chat-room.cpp @@ -72,7 +72,7 @@ void ClientGroupChatRoom::addParticipants (const list
&addresses, const session->initiateOutgoing(); Address addr = me->getAddress(); addr.setParam("text", ""); - sal_op_set_contact_address(session->getPrivate()->getOp(), addr.getPrivate()->getInternalAddress()); + session->getPrivate()->getOp()->set_contact_address(addr.getPrivate()->getInternalAddress()); session->startInvite(nullptr, d->subject); d->setState(ChatRoom::State::CreationPending); } diff --git a/src/chat/is-composing.cpp b/src/chat/is-composing.cpp index e1ef360b1..7b13a214b 100644 --- a/src/chat/is-composing.cpp +++ b/src/chat/is-composing.cpp @@ -107,7 +107,7 @@ void IsComposing::parse (const string &text) { void IsComposing::startIdleTimer () { unsigned int duration = getIdleTimerDuration(); if (!idleTimer) { - idleTimer = sal_create_timer(core->sal, idleTimerExpired, this, + idleTimer = core->sal->create_timer(idleTimerExpired, this, duration * 1000, "composing idle timeout"); } else { belle_sip_source_set_timeout(idleTimer, duration * 1000); @@ -117,7 +117,7 @@ void IsComposing::startIdleTimer () { void IsComposing::startRefreshTimer () { unsigned int duration = getRefreshTimerDuration(); if (!refreshTimer) { - refreshTimer = sal_create_timer(core->sal, refreshTimerExpired, this, + refreshTimer = core->sal->create_timer(refreshTimerExpired, this, duration * 1000, "composing refresh timeout"); } else { belle_sip_source_set_timeout(refreshTimer, duration * 1000); @@ -129,7 +129,7 @@ void IsComposing::startRemoteRefreshTimer (const char *refreshStr) { if (refreshStr) duration = static_cast(stoi(refreshStr)); if (!remoteRefreshTimer) { - remoteRefreshTimer = sal_create_timer(core->sal, remoteRefreshTimerExpired, this, + remoteRefreshTimer = core->sal->create_timer(remoteRefreshTimerExpired, this, duration * 1000, "composing remote refresh timeout"); } else { belle_sip_source_set_timeout(remoteRefreshTimer, duration * 1000); @@ -154,7 +154,7 @@ void IsComposing::stopTimers () { void IsComposing::stopIdleTimer () { if (idleTimer) { if (core && core->sal) - sal_cancel_timer(core->sal, idleTimer); + core->sal->cancel_timer(idleTimer); belle_sip_object_unref(idleTimer); idleTimer = nullptr; } @@ -163,7 +163,7 @@ void IsComposing::stopIdleTimer () { void IsComposing::stopRefreshTimer () { if (refreshTimer) { if (core && core->sal) - sal_cancel_timer(core->sal, refreshTimer); + core->sal->cancel_timer(refreshTimer); belle_sip_object_unref(refreshTimer); refreshTimer = nullptr; } @@ -172,7 +172,7 @@ void IsComposing::stopRefreshTimer () { void IsComposing::stopRemoteRefreshTimer () { if (remoteRefreshTimer) { if (core && core->sal) - sal_cancel_timer(core->sal, remoteRefreshTimer); + core->sal->cancel_timer(remoteRefreshTimer); belle_sip_object_unref(remoteRefreshTimer); remoteRefreshTimer = nullptr; } diff --git a/src/conference/params/call-session-params.h b/src/conference/params/call-session-params.h index d666afac9..2b01dcfe8 100644 --- a/src/conference/params/call-session-params.h +++ b/src/conference/params/call-session-params.h @@ -23,6 +23,7 @@ #include "linphone/types.h" #include "sal/sal.h" +#include "sal/sal.hpp" // ============================================================================= diff --git a/src/conference/session/call-session-p.h b/src/conference/session/call-session-p.h index 790776151..c1b68870f 100644 --- a/src/conference/session/call-session-p.h +++ b/src/conference/session/call-session-p.h @@ -22,6 +22,7 @@ #include "object/object-p.h" #include "call-session.h" +#include "sal/call_op.h" // ============================================================================= @@ -39,7 +40,7 @@ public: void setPingTime (int value) { pingTime = value; } LinphoneProxyConfig * getDestProxy () const { return destProxy; } - SalOp * getOp () const { return op; } + SalCallOp * getOp () const { return op; } virtual void abort (const std::string &errorMsg); virtual void accepted (); @@ -92,7 +93,7 @@ protected: LinphoneErrorInfo *ei = nullptr; LinphoneCallLog *log = nullptr; - SalOp *op = nullptr; + SalCallOp *op = nullptr; SalOp *pingOp = nullptr; bool pingReplied = false; diff --git a/src/conference/session/call-session.cpp b/src/conference/session/call-session.cpp index 5dd173e5d..eb1922516 100644 --- a/src/conference/session/call-session.cpp +++ b/src/conference/session/call-session.cpp @@ -60,7 +60,7 @@ CallSessionPrivate::~CallSessionPrivate () { if (log) linphone_call_log_unref(log); if (op) - sal_op_release(op); + op->release(); } // ----------------------------------------------------------------------------- @@ -76,7 +76,7 @@ int CallSessionPrivate::computeDuration () const { * end apparently does not support. This features are: privacy, video... */ void CallSessionPrivate::initializeParamsAccordingToIncomingCallParams () { - currentParams->setPrivacy((LinphonePrivacyMask)sal_op_get_privacy(op)); + currentParams->setPrivacy((LinphonePrivacyMask)op->get_privacy()); } void CallSessionPrivate::setState(LinphoneCallState newState, const string &message) { @@ -186,21 +186,21 @@ bool CallSessionPrivate::startPing () { * send an option request back to the caller so that we get a chance to discover our nat'd address * before answering for incoming call */ pingReplied = false; - pingOp = sal_op_new(core->sal); + pingOp = new SalOp(core->sal); if (direction == LinphoneCallIncoming) { - const char *from = sal_op_get_from(pingOp); - const char *to = sal_op_get_to(pingOp); + const char *from = pingOp->get_from(); + const char *to = pingOp->get_to(); linphone_configure_op(core, pingOp, log->from, nullptr, false); - sal_op_set_route(pingOp, sal_op_get_network_origin(op)); - sal_ping(pingOp, from, to); + pingOp->set_route(op->get_network_origin()); + pingOp->ping(from, to); } else if (direction == LinphoneCallOutgoing) { char *from = linphone_address_as_string(log->from); char *to = linphone_address_as_string(log->to); - sal_ping(pingOp, from, to); + pingOp->ping(from, to); ms_free(from); ms_free(to); } - sal_op_set_user_pointer(pingOp, this); + pingOp->set_user_pointer(this); return true; } return false; @@ -209,7 +209,7 @@ bool CallSessionPrivate::startPing () { // ----------------------------------------------------------------------------- void CallSessionPrivate::abort (const string &errorMsg) { - sal_call_terminate(op); + op->terminate(); setState(LinphoneCallError, errorMsg); } @@ -225,7 +225,7 @@ void CallSessionPrivate::accepted () { default: break; } - currentParams->setPrivacy((LinphonePrivacyMask)sal_op_get_privacy(op)); + currentParams->setPrivacy((LinphonePrivacyMask)op->get_privacy()); } void CallSessionPrivate::ackBeingSent (LinphoneHeaders *headers) { @@ -242,12 +242,12 @@ void CallSessionPrivate::ackReceived (LinphoneHeaders *headers) { bool CallSessionPrivate::failure () { L_Q(); - const SalErrorInfo *ei = sal_op_get_error_info(op); + const SalErrorInfo *ei = op->get_error_info(); switch (ei->reason) { case SalReasonRedirect: if ((state == LinphoneCallOutgoingInit) || (state == LinphoneCallOutgoingProgress) || (state == LinphoneCallOutgoingRinging) /* Push notification case */ || (state == LinphoneCallOutgoingEarlyMedia)) { - const SalAddress *redirectionTo = sal_op_get_remote_contact_address(op); + const SalAddress *redirectionTo = op->get_remote_contact_address(); if (redirectionTo) { char *url = sal_address_as_string(redirectionTo); lWarning() << "Redirecting CallSession [" << q << "] to " << url; @@ -285,9 +285,9 @@ bool CallSessionPrivate::failure () { setState(LinphoneCallEnd, "Call declined"); else { if (linphone_call_state_is_early(state)) - setState(LinphoneCallError, ei->full_string); + setState(LinphoneCallError, ei->full_string ? ei->full_string : ""); else - setState(LinphoneCallEnd, ei->full_string); + setState(LinphoneCallEnd, ei->full_string ? ei->full_string : ""); } #if 0 // TODO: handle in Call class if (ei->reason != SalReasonNone) @@ -318,7 +318,7 @@ void CallSessionPrivate::pingReply () { void CallSessionPrivate::remoteRinging () { L_Q(); /* Set privacy */ - q->getCurrentParams()->setPrivacy((LinphonePrivacyMask)sal_op_get_privacy(op)); + q->getCurrentParams()->setPrivacy((LinphonePrivacyMask)op->get_privacy()); #if 0 if (lc->ringstream == NULL) start_remote_ring(lc, call); #endif @@ -334,7 +334,7 @@ void CallSessionPrivate::terminated () { return; case LinphoneCallIncomingReceived: case LinphoneCallIncomingEarlyMedia: - if (!sal_op_get_reason_error_info(op)->protocol || strcmp(sal_op_get_reason_error_info(op)->protocol, "") == 0) { + if (!op->get_reason_error_info()->protocol || strcmp(op->get_reason_error_info()->protocol, "") == 0) { linphone_error_info_set(ei, nullptr, LinphoneReasonNotAnswered, 0, "Incoming call cancelled", nullptr); nonOpError = true; } @@ -383,7 +383,7 @@ void CallSessionPrivate::updated (bool isUpdate) { case LinphoneCallPausing: case LinphoneCallResuming: sal_error_info_set(&sei, SalReasonInternalError, "SIP", 0, nullptr, nullptr); - sal_call_decline_with_error_info(op, &sei, nullptr); + op->decline_with_error_info(&sei, nullptr); BCTBX_NO_BREAK; /* no break */ case LinphoneCallIdle: case LinphoneCallOutgoingInit: @@ -428,10 +428,10 @@ void CallSessionPrivate::accept (const CallSessionParams *params) { setContactOp(); if (params) { this->params = new CallSessionParams(*params); - sal_op_set_sent_custom_header(op, this->params->getPrivate()->getCustomHeaders()); + op->set_sent_custom_header(this->params->getPrivate()->getCustomHeaders()); } - sal_call_accept(op); + op->accept(); if (listener) listener->onSetCurrentSession(*q); setState(LinphoneCallConnected, "Connected"); @@ -455,9 +455,9 @@ LinphoneStatus CallSessionPrivate::checkForAcceptation () const { listener->onCheckForAcceptation(*q); /* Check if this call is supposed to replace an already running one */ - SalOp *replaced = sal_call_get_replaces(op); + SalOp *replaced = op->get_replaces(); if (replaced) { - CallSession *session = reinterpret_cast(sal_op_get_user_pointer(replaced)); + CallSession *session = reinterpret_cast(replaced->get_user_pointer()); if (session) { lInfo() << "CallSession " << q << " replaces CallSession " << session << ". This last one is going to be terminated automatically"; session->terminate(); @@ -470,8 +470,8 @@ void CallSessionPrivate::handleIncomingReceivedStateInIncomingNotification () { L_Q(); /* Try to be best-effort in giving real local or routable contact address for 100Rel case */ setContactOp(); - sal_call_notify_ringing(op, false); - if (sal_call_get_replaces(op) && lp_config_get_int(linphone_core_get_config(core), "sip", "auto_answer_replacing_calls", 1)) + op->notify_ringing(false); + if (op->get_replaces() && lp_config_get_int(linphone_core_get_config(core), "sip", "auto_answer_replacing_calls", 1)) q->accept(); } @@ -524,7 +524,7 @@ void CallSessionPrivate::setReleased () { if (!nonOpError) linphone_error_info_from_sal_op(ei, op); /* So that we cannot have anymore upcalls for SAL concerning this call */ - sal_op_release(op); + op->release(); op = nullptr; } #if 0 @@ -558,8 +558,8 @@ void CallSessionPrivate::setTerminated() { listener->onCallSessionSetTerminated(*q); } -LinphoneStatus CallSessionPrivate::startAcceptUpdate (LinphoneCallState nextState, const string &stateInfo) { - sal_call_accept(op); +LinphoneStatus CallSessionPrivate::startAcceptUpdate (LinphoneCallState nextState, const std::string &stateInfo) { + op->accept(); setState(nextState, stateInfo); return 0; } @@ -577,10 +577,10 @@ LinphoneStatus CallSessionPrivate::startUpdate () { subject = "Media change"; if (destProxy && destProxy->op) { /* Give a chance to update the contact address if connectivity has changed */ - sal_op_set_contact_address(op, sal_op_get_contact_address(destProxy->op)); + op->set_contact_address(destProxy->op->get_contact_address()); } else - sal_op_set_contact_address(op, nullptr); - return sal_call_update(op, subject.c_str(), q->getParams()->getPrivate()->getNoUserConsent()); + op->set_contact_address(nullptr); + return op->update(subject.c_str(), q->getParams()->getPrivate()->getNoUserConsent()); } void CallSessionPrivate::terminate () { @@ -600,7 +600,7 @@ void CallSessionPrivate::setContactOp () { LinphoneAddress *contact = getFixedContact(); if (contact) { salAddress = const_cast(L_GET_PRIVATE_FROM_C_OBJECT(contact)->getInternalAddress()); - sal_op_set_contact_address(op, salAddress); + op->set_contact_address(salAddress); linphone_address_unref(contact); } } @@ -618,16 +618,16 @@ void CallSessionPrivate::completeLog () { void CallSessionPrivate::createOpTo (const LinphoneAddress *to) { L_Q(); if (op) - sal_op_release(op); - op = sal_op_new(core->sal); - sal_op_set_user_pointer(op, q); + op->release(); + op = new SalCallOp(core->sal); + op->set_user_pointer(q); #if 0 if (linphone_call_params_get_referer(call->params)) sal_call_set_referer(call->op,linphone_call_params_get_referer(call->params)->op); #endif linphone_configure_op(core, op, to, q->getParams()->getPrivate()->getCustomHeaders(), false); if (q->getParams()->getPrivacy() != LinphonePrivacyDefault) - sal_op_set_privacy(op, (SalPrivacyMask)q->getParams()->getPrivacy()); + op->set_privacy((SalPrivacyMask)q->getParams()->getPrivacy()); /* else privacy might be set by proxy */ } @@ -635,13 +635,13 @@ void CallSessionPrivate::createOpTo (const LinphoneAddress *to) { LinphoneAddress * CallSessionPrivate::getFixedContact () const { LinphoneAddress *result = nullptr; - if (op && sal_op_get_contact_address(op)) { + if (op && op->get_contact_address()) { /* If already choosed, don't change it */ return nullptr; - } else if (pingOp && sal_op_get_contact_address(pingOp)) { + } else if (pingOp && pingOp->get_contact_address()) { /* If the ping OPTIONS request succeeded use the contact guessed from the received, rport */ lInfo() << "Contact has been fixed using OPTIONS"; - char *addr = sal_address_as_string(sal_op_get_contact_address(pingOp)); + char *addr = sal_address_as_string(pingOp->get_contact_address()); result = linphone_address_new(addr); ms_free(addr); } else if (destProxy && destProxy->op && _linphone_proxy_config_get_contact_without_params(destProxy)) { @@ -688,7 +688,7 @@ LinphoneStatus CallSession::acceptUpdate (const CallSessionParams *csp) { return d->acceptUpdate(csp, d->prevState, linphone_call_state_to_string(d->prevState)); } -void CallSession::configure (LinphoneCallDir direction, LinphoneProxyConfig *cfg, SalOp *op, const Address &from, const Address &to) { +void CallSession::configure (LinphoneCallDir direction, LinphoneProxyConfig *cfg, SalCallOp *op, const Address &from, const Address &to) { L_D(); d->direction = direction; d->destProxy = cfg; @@ -703,10 +703,10 @@ void CallSession::configure (LinphoneCallDir direction, LinphoneProxyConfig *cfg if (op) { /* We already have an op for incoming calls */ d->op = op; - sal_op_set_user_pointer(d->op, this); - sal_op_cnx_ip_to_0000_if_sendonly_enable(op, !!lp_config_get_default_int(linphone_core_get_config(d->core), + d->op->set_user_pointer(this); + op->enable_cnx_ip_to_0000_if_sendonly(!!lp_config_get_default_int(linphone_core_get_config(d->core), "sip", "cnx_ip_to_0000_if_sendonly_enabled", 0)); - d->log->call_id = ms_strdup(sal_op_get_call_id(op)); /* Must be known at that time */ + d->log->call_id = ms_strdup(op->get_call_id()); /* Must be known at that time */ } if (direction == LinphoneCallOutgoing) { @@ -738,9 +738,9 @@ LinphoneStatus CallSession::decline (const LinphoneErrorInfo *ei) { } if (ei) { linphone_error_info_to_sal(ei, &sei); - sal_call_decline_with_error_info(d->op, &sei , nullptr); + d->op->decline_with_error_info(&sei , nullptr); } else - sal_call_decline(d->op, SalReasonDeclined, nullptr); + d->op->decline(SalReasonDeclined, nullptr); sal_error_info_reset(&sei); sal_error_info_reset(&sub_sei); d->terminate(); @@ -841,7 +841,7 @@ int CallSession::startInvite (const Address *destination, const string &subject) char *from = linphone_address_as_string(d->log->from); /* Take a ref because sal_call() may destroy the CallSession if no SIP transport is available */ shared_ptr ref = static_pointer_cast(shared_from_this()); - int result = sal_call(d->op, from, destinationStr.c_str(), subject.empty() ? nullptr : subject.c_str()); + int result = d->op->call(from, destinationStr.c_str(), subject.empty() ? nullptr : subject.c_str()); ms_free(from); if (result < 0) { if ((d->state != LinphoneCallError) && (d->state != LinphoneCallReleased)) { @@ -850,7 +850,7 @@ int CallSession::startInvite (const Address *destination, const string &subject) d->setState(LinphoneCallError, "Call failed"); } } else { - d->log->call_id = ms_strdup(sal_op_get_call_id(d->op)); /* Must be known at that time */ + d->log->call_id = ms_strdup(d->op->get_call_id()); /* Must be known at that time */ d->setState(LinphoneCallOutgoingProgress, "Outgoing call in progress"); } return result; @@ -872,16 +872,16 @@ LinphoneStatus CallSession::terminate (const LinphoneErrorInfo *ei) { return decline(ei); case LinphoneCallOutgoingInit: /* In state OutgoingInit, op has to be destroyed */ - sal_op_release(d->op); + d->op->release(); d->op = nullptr; break; default: if (ei) { linphone_error_info_to_sal(ei, &sei); - sal_call_terminate_with_error(d->op, &sei); + d->op->terminate_with_error(&sei); sal_error_info_reset(&sei); } else - sal_call_terminate(d->op); + d->op->terminate(); break; } @@ -954,7 +954,7 @@ string CallSession::getRemoteContact () const { L_D(); if (d->op) { /* sal_op_get_remote_contact preserves header params */ - return sal_op_get_remote_contact(d->op); + return d->op->get_remote_contact(); } return string(); } @@ -962,7 +962,7 @@ string CallSession::getRemoteContact () const { const CallSessionParams * CallSession::getRemoteParams () { L_D(); if (d->op){ - const SalCustomHeader *ch = sal_op_get_recv_custom_header(d->op); + const SalCustomHeader *ch = d->op->get_recv_custom_header(); if (ch) { /* Instanciate a remote_params only if a SIP message was received before (custom headers indicates this) */ if (!d->remoteParams) @@ -984,7 +984,7 @@ LinphoneCallState CallSession::getState () const { string CallSession::getRemoteUserAgent () const { L_D(); if (d->op) - return sal_op_get_remote_ua(d->op); + return d->op->get_remote_ua(); return string(); } diff --git a/src/conference/session/call-session.h b/src/conference/session/call-session.h index cd5484cc2..74b95461b 100644 --- a/src/conference/session/call-session.h +++ b/src/conference/session/call-session.h @@ -24,6 +24,7 @@ #include "conference/conference.h" #include "conference/params/call-session-params.h" #include "conference/session/call-session-listener.h" +#include "sal/call_op.h" // ============================================================================= @@ -41,7 +42,7 @@ public: LinphoneStatus accept (const CallSessionParams *csp = nullptr); LinphoneStatus acceptUpdate (const CallSessionParams *csp); - virtual void configure (LinphoneCallDir direction, LinphoneProxyConfig *cfg, SalOp *op, const Address &from, const Address &to); + virtual void configure (LinphoneCallDir direction, LinphoneProxyConfig *cfg, SalCallOp *op, const Address &from, const Address &to); LinphoneStatus decline (LinphoneReason reason); LinphoneStatus decline (const LinphoneErrorInfo *ei); virtual void initiateIncoming (); diff --git a/src/conference/session/media-session-p.h b/src/conference/session/media-session-p.h index 7d9cfbe6d..b9e75b401 100644 --- a/src/conference/session/media-session-p.h +++ b/src/conference/session/media-session-p.h @@ -90,13 +90,8 @@ public: LinphoneCallStats *getStats (LinphoneStreamType type) const; int getStreamIndex (LinphoneStreamType type) const; int getStreamIndex (MediaStream *ms) const; - SalOp *getOp () const { - return op; - } - - void setAudioMuted (bool value) { - audioMuted = value; - } + SalCallOp * getOp () const { return op; } + void setAudioMuted (bool value) { audioMuted = value; } private: static OrtpJitterBufferAlgorithm jitterBufferNameToAlgo (const std::string &name); diff --git a/src/conference/session/media-session.cpp b/src/conference/session/media-session.cpp index 5a2ce5942..9137f16dd 100644 --- a/src/conference/session/media-session.cpp +++ b/src/conference/session/media-session.cpp @@ -132,8 +132,8 @@ void MediaSessionPrivate::accepted () { linphone_task_list_init(&tl); /* Reset the internal call update flag, so it doesn't risk to be copied and used in further re-INVITEs */ params->getPrivate()->setInternalCallUpdate(false); - SalMediaDescription *rmd = sal_call_get_remote_media_description(op); - SalMediaDescription *md = sal_call_get_final_media_description(op); + SalMediaDescription *rmd = op->get_remote_media_description(); + SalMediaDescription *md = op->get_final_media_description(); if (!md && (prevState == LinphoneCallOutgoingEarlyMedia) && resultDesc) { lInfo() << "Using early media SDP since none was received with the 200 OK"; md = resultDesc; @@ -144,7 +144,7 @@ void MediaSessionPrivate::accepted () { /* There is a valid SDP in the response, either offer or answer, and we're able to start/update the streams */ if (rmd) { /* Handle remote ICE attributes if any. */ - iceAgent->updateFromRemoteMediaDescription(localDesc, rmd, !sal_call_is_offerer(op)); + iceAgent->updateFromRemoteMediaDescription(localDesc, rmd, !op->is_offerer()); } LinphoneCallState nextState = LinphoneCallIdle; string nextStateMsg; @@ -246,7 +246,7 @@ void MediaSessionPrivate::ackReceived (LinphoneHeaders *headers) { bool MediaSessionPrivate::failure () { L_Q(); - const SalErrorInfo *ei = sal_op_get_error_info(op); + const SalErrorInfo *ei = op->get_error_info(); switch (ei->reason) { case SalReasonRedirect: stopStreams(); @@ -328,8 +328,8 @@ void MediaSessionPrivate::pausedByRemote () { void MediaSessionPrivate::remoteRinging () { L_Q(); /* Set privacy */ - q->getCurrentParams()->setPrivacy((LinphonePrivacyMask)sal_op_get_privacy(op)); - SalMediaDescription *md = sal_call_get_final_media_description(op); + q->getCurrentParams()->setPrivacy((LinphonePrivacyMask)op->get_privacy()); + SalMediaDescription *md = op->get_final_media_description(); if (md) { /* Initialize the remote call params by invoking linphone_call_get_remote_params(). This is useful as the SDP may not be present in the 200Ok */ q->getRemoteParams(); @@ -385,7 +385,7 @@ void MediaSessionPrivate::terminated () { /* This callback is called when an incoming re-INVITE/ SIP UPDATE modifies the session */ void MediaSessionPrivate::updated (bool isUpdate) { - SalMediaDescription *rmd = sal_call_get_remote_media_description(op); + SalMediaDescription *rmd = op->get_remote_media_description(); switch (state) { case LinphoneCallPausedByRemote: if (sal_media_description_has_dir(rmd, SalStreamSendRecv) || sal_media_description_has_dir(rmd, SalStreamRecvOnly)) { @@ -410,7 +410,7 @@ void MediaSessionPrivate::updated (bool isUpdate) { void MediaSessionPrivate::updating (bool isUpdate) { L_Q(); - SalMediaDescription *rmd = sal_call_get_remote_media_description(op); + SalMediaDescription *rmd = op->get_remote_media_description(); fixCallParams(rmd); if (state != LinphoneCallPaused) { /* Refresh the local description, but in paused state, we don't change anything. */ @@ -420,16 +420,16 @@ void MediaSessionPrivate::updating (bool isUpdate) { params->initDefault(core); } makeLocalMediaDescription(); - sal_call_set_local_media_description(op, localDesc); + op->set_local_media_description(localDesc); } if (rmd) { SalErrorInfo sei; memset(&sei, 0, sizeof(sei)); expectMediaInAck = false; - SalMediaDescription *md = sal_call_get_final_media_description(op); + SalMediaDescription *md = op->get_final_media_description(); if (md && (sal_media_description_empty(md) || linphone_core_incompatible_security(core, md))) { sal_error_info_set(&sei, SalReasonNotAcceptable, "SIP", 0, nullptr, nullptr); - sal_call_decline_with_error_info(op, &sei, nullptr); + op->decline_with_error_info(&sei, nullptr); sal_error_info_reset(&sei); return; } @@ -439,7 +439,7 @@ void MediaSessionPrivate::updating (bool isUpdate) { if (diff & (SAL_MEDIA_DESCRIPTION_CRYPTO_POLICY_CHANGED | SAL_MEDIA_DESCRIPTION_STREAMS_CHANGED)) { lWarning() << "Cannot accept this update, it is changing parameters that require user approval"; sal_error_info_set(&sei, SalReasonUnknown, "SIP", 504, "Cannot change the session parameters without prompting the user", nullptr); - sal_call_decline_with_error_info(op, &sei, nullptr); + op->decline_with_error_info(&sei, nullptr); sal_error_info_reset(&sei); return; } @@ -448,7 +448,7 @@ void MediaSessionPrivate::updating (bool isUpdate) { } else { /* Case of a reINVITE or UPDATE without SDP */ expectMediaInAck = true; - sal_call_accept(op); /* Respond with an offer */ + op->accept(); /* Respond with an offer */ /* Don't do anything else in this case, wait for the ACK to receive to notify the app */ } } @@ -767,12 +767,12 @@ void MediaSessionPrivate::initializeParamsAccordingToIncomingCallParams () { CallSessionPrivate::initializeParamsAccordingToIncomingCallParams(); currentParams->getPrivate()->setUpdateCallWhenIceCompleted(params->getPrivate()->getUpdateCallWhenIceCompleted()); params->enableVideo(linphone_core_video_enabled(core) && core->video_policy.automatically_accept); - SalMediaDescription *md = sal_call_get_remote_media_description(op); + SalMediaDescription *md = op->get_remote_media_description(); if (md) { /* It is licit to receive an INVITE without SDP, in this case WE choose the media parameters according to policy */ setCompatibleIncomingCallParams(md); /* Set multicast role & address if any */ - if (!sal_call_is_offerer(op)) { + if (!op->is_offerer()) { for (int i = 0; i < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; i++) { if (md->streams[i].dir == SalStreamInactive) continue; @@ -824,7 +824,7 @@ void MediaSessionPrivate::updateBiggestDesc (SalMediaDescription *md) { } void MediaSessionPrivate::updateRemoteSessionIdAndVer () { - SalMediaDescription *desc = sal_call_get_remote_media_description(op); + SalMediaDescription *desc = op->get_remote_media_description(); if (desc) { remoteSessionId = desc->session_id; remoteSessionVer = desc->session_ver; @@ -1026,7 +1026,7 @@ void MediaSessionPrivate::getLocalIp (const Address &remoteAddr) { /* If a known proxy was identified for this call, then we may have a chance to take the local ip address * from the socket that connects to this proxy */ if (destProxy && destProxy->op) { - ip = sal_op_get_local_address(destProxy->op, nullptr); + ip = destProxy->op->get_local_address(nullptr); if (ip) { lInfo() << "Found media local-ip from signaling."; mediaLocalIp = ip; @@ -1085,9 +1085,9 @@ void MediaSessionPrivate::runStunTestsIfNeeded () { void MediaSessionPrivate::selectIncomingIpVersion () { if (linphone_core_ipv6_enabled(core)) { if (destProxy && destProxy->op) - af = sal_op_get_address_family(destProxy->op); + af = destProxy->op->get_address_family(); else - af = sal_op_get_address_family(op); + af = op->get_address_family(); } else af = AF_INET; } @@ -1110,7 +1110,7 @@ void MediaSessionPrivate::selectOutgoingIpVersion () { if (sal_address_is_ipv6(L_GET_PRIVATE_FROM_C_OBJECT(to)->getInternalAddress())) af = AF_INET6; else if (destProxy && destProxy->op) - af = sal_op_get_address_family(destProxy->op); + af = destProxy->op->get_address_family(); else { char ipv4[LINPHONE_IPADDR_SIZE]; char ipv6[LINPHONE_IPADDR_SIZE]; @@ -1531,15 +1531,15 @@ SalMulticastRole MediaSessionPrivate::getMulticastRole (SalStreamType type) { SalMulticastRole multicastRole = SalMulticastInactive; if (op) { SalStreamDescription *streamDesc = nullptr; - SalMediaDescription *remoteDesc = sal_call_get_remote_media_description(op); + SalMediaDescription *remoteDesc = op->get_remote_media_description(); if (!localDesc && !remoteDesc && (direction == LinphoneCallOutgoing)) { /* Well using call dir */ if (((type == SalAudio) && params->audioMulticastEnabled()) || ((type == SalVideo) && params->videoMulticastEnabled())) multicastRole = SalMulticastSender; - } else if (localDesc && (!remoteDesc || sal_call_is_offerer(op))) { + } else if (localDesc && (!remoteDesc || op->is_offerer())) { streamDesc = sal_media_description_find_best_stream(localDesc, type); - } else if (!sal_call_is_offerer(op) && remoteDesc) { + } else if (!op->is_offerer() && remoteDesc) { streamDesc = sal_media_description_find_best_stream(remoteDesc, type); } @@ -1581,8 +1581,8 @@ void MediaSessionPrivate::setDtlsFingerprint (MSMediaStreamSessions *sessions, c } void MediaSessionPrivate::setDtlsFingerprintOnAllStreams () { - SalMediaDescription *remote = sal_call_get_remote_media_description(op); - SalMediaDescription *result = sal_call_get_final_media_description(op); + SalMediaDescription *remote = op->get_remote_media_description(); + SalMediaDescription *result = op->get_final_media_description(); if (!remote || !result) { /* This can happen in some tricky cases (early-media without SDP in the 200). In that case, simply skip DTLS code */ return; @@ -1692,8 +1692,8 @@ void MediaSessionPrivate::startDtls (MSMediaStreamSessions *sessions, const SalS } void MediaSessionPrivate::startDtlsOnAllStreams () { - SalMediaDescription *remote = sal_call_get_remote_media_description(op); - SalMediaDescription *result = sal_call_get_final_media_description(op); + SalMediaDescription *remote = op->get_remote_media_description(); + SalMediaDescription *result = op->get_final_media_description(); if (!remote || !result) { /* This can happen in some tricky cases (early-media without SDP in the 200). In that case, simply skip DTLS code */ return; @@ -1958,7 +1958,7 @@ void MediaSessionPrivate::configureRtpSessionForRtcpFb (const SalStreamDescripti } void MediaSessionPrivate::configureRtpSessionForRtcpXr (SalStreamType type) { - SalMediaDescription *remote = sal_call_get_remote_media_description(op); + SalMediaDescription *remote = op->get_remote_media_description(); if (!remote) return; const SalStreamDescription *localStream = sal_media_description_find_best_stream(localDesc, type); @@ -2095,7 +2095,7 @@ void MediaSessionPrivate::handleIceEvents (OrtpEvent *ev) { case LinphoneCallIdle: stopStreamsForIceGathering(); updateLocalMediaDescriptionFromIce(); - sal_call_set_local_media_description(op, localDesc); + op->set_local_media_description(localDesc); deferIncomingNotification = false; static_cast(q)->startIncomingNotification(); break; @@ -2194,7 +2194,7 @@ void MediaSessionPrivate::initializeAudioStream () { SalMediaDescription *remoteDesc = nullptr; SalStreamDescription *streamDesc = nullptr; if (op) - remoteDesc = sal_call_get_remote_media_description(op); + remoteDesc = op->get_remote_media_description(); if (remoteDesc) streamDesc = sal_media_description_find_best_stream(remoteDesc, SalAudio); @@ -2303,7 +2303,7 @@ void MediaSessionPrivate::initializeTextStream () { SalMediaDescription *remoteDesc = nullptr; SalStreamDescription *streamDesc = nullptr; if (op) - remoteDesc = sal_call_get_remote_media_description(op); + remoteDesc = op->get_remote_media_description(); if (remoteDesc) streamDesc = sal_media_description_find_best_stream(remoteDesc, SalText); @@ -2347,7 +2347,7 @@ void MediaSessionPrivate::initializeVideoStream () { SalMediaDescription *remoteDesc = nullptr; SalStreamDescription *streamDesc = nullptr; if (op) - remoteDesc = sal_call_get_remote_media_description(op); + remoteDesc = op->get_remote_media_description(); if (remoteDesc) streamDesc = sal_media_description_find_best_stream(remoteDesc, SalVideo); @@ -2678,7 +2678,7 @@ void MediaSessionPrivate::startAudioStream (LinphoneCallState targetState, bool currentParams->getPrivate()->setInConference(params->getPrivate()->getInConference()); currentParams->enableLowBandwidth(params->lowBandwidthEnabled()); /* Start ZRTP engine if needed : set here or remote have a zrtp-hash attribute */ - SalMediaDescription *remote = sal_call_get_remote_media_description(op); + SalMediaDescription *remote = op->get_remote_media_description(); const SalStreamDescription *remoteStream = sal_media_description_find_best_stream(remote, SalAudio); if (linphone_core_media_encryption_supported(core, LinphoneMediaEncryptionZRTP) && ((params->getMediaEncryption() == LinphoneMediaEncryptionZRTP) || (remoteStream->haveZrtpHash == 1))) { @@ -2929,7 +2929,7 @@ void MediaSessionPrivate::startVideoStream (LinphoneCallState targetState) { if (listener) listener->onResetFirstVideoFrameDecoded(*q); /* Start ZRTP engine if needed : set here or remote have a zrtp-hash attribute */ - SalMediaDescription *remote = sal_call_get_remote_media_description(op); + SalMediaDescription *remote = op->get_remote_media_description(); const SalStreamDescription *remoteStream = sal_media_description_find_best_stream(remote, SalVideo); if ((params->getMediaEncryption() == LinphoneMediaEncryptionZRTP) || (remoteStream->haveZrtpHash == 1)) { /* Audio stream is already encrypted and video stream is active */ @@ -3310,7 +3310,7 @@ uint16_t MediaSessionPrivate::getAvpfRrInterval () const { unsigned int MediaSessionPrivate::getNbActiveStreams () const { SalMediaDescription *md = nullptr; if (op) - md = sal_call_get_remote_media_description(op); + md = op->get_remote_media_description(); if (!md) return 0; return sal_media_description_nb_active_streams_of_type(md, SalAudio) + sal_media_description_nb_active_streams_of_type(md, SalVideo) + sal_media_description_nb_active_streams_of_type(md, SalText); @@ -3450,7 +3450,7 @@ void MediaSessionPrivate::updateReportingMediaInfo (int statsType) { if (!op || !mediaReportEnabled(statsType)) return; - char *dialogId = sal_op_get_dialog_id(op); + char *dialogId = op->get_dialog_id(); reporting_session_report_t * report = log->reporting.reports[statsType]; STR_REASSIGN(report->info.call_id, ms_strdup(log->call_id)); @@ -3638,8 +3638,8 @@ void MediaSessionPrivate::handleIncomingReceivedStateInIncomingNotification () { if (proposeEarlyMedia) q->acceptEarlyMedia(); else - sal_call_notify_ringing(op, false); - if (sal_call_get_replaces(op) && !!lp_config_get_int(linphone_core_get_config(core), "sip", "auto_answer_replacing_calls", 1)) + op->notify_ringing(false); + if (op->get_replaces() && !!lp_config_get_int(linphone_core_get_config(core), "sip", "auto_answer_replacing_calls", 1)) q->accept(); } @@ -3674,8 +3674,8 @@ LinphoneStatus MediaSessionPrivate::pause () { #endif setState(LinphoneCallPausing, "Pausing call"); makeLocalMediaDescription(); - sal_call_set_local_media_description(op, localDesc); - sal_call_update(op, subject.c_str(), false); + op->set_local_media_description(localDesc); + op->update(subject.c_str(), false); if (listener) listener->onResetCurrentSession(*q); if (audioStream || videoStream || textStream) @@ -3696,9 +3696,9 @@ LinphoneStatus MediaSessionPrivate::startAcceptUpdate (LinphoneCallState nextSta } makeLocalMediaDescription(); updateRemoteSessionIdAndVer(); - sal_call_set_local_media_description(op, localDesc); - sal_call_accept(op); - SalMediaDescription *md = sal_call_get_final_media_description(op); + op->set_local_media_description(localDesc); + op->accept(); + SalMediaDescription *md = op->get_final_media_description(); iceAgent->stopIceForInactiveStreams(md); if (md && !sal_media_description_empty(md)) updateStreams(md, nextState); @@ -3711,14 +3711,14 @@ LinphoneStatus MediaSessionPrivate::startUpdate () { if (!params->getPrivate()->getNoUserConsent()) makeLocalMediaDescription(); if (!core->sip_conf.sdp_200_ack) - sal_call_set_local_media_description(op, localDesc); + op->set_local_media_description(localDesc); else - sal_call_set_local_media_description(op, nullptr); + op->set_local_media_description(nullptr); LinphoneStatus result = CallSessionPrivate::startUpdate(); if (core->sip_conf.sdp_200_ack) { /* We are NOT offering, set local media description after sending the call so that we are ready to * process the remote offer when it will arrive. */ - sal_call_set_local_media_description(op, localDesc); + op->set_local_media_description(localDesc); } return result; } @@ -3842,7 +3842,7 @@ void MediaSessionPrivate::accept (const MediaSessionParams *csp) { params = new MediaSessionParams(*csp); iceAgent->prepare(localDesc, true); makeLocalMediaDescription(); - sal_call_set_local_media_description(op, localDesc); + op->set_local_media_description(localDesc); } updateRemoteSessionIdAndVer(); @@ -3864,7 +3864,7 @@ void MediaSessionPrivate::accept (const MediaSessionParams *csp) { CallSessionPrivate::accept(params); - SalMediaDescription *newMd = sal_call_get_final_media_description(op); + SalMediaDescription *newMd = op->get_final_media_description(); iceAgent->stopIceForInactiveStreams(newMd); if (newMd) { updateStreams(newMd, LinphoneCallStreamsRunning); @@ -3875,19 +3875,19 @@ void MediaSessionPrivate::accept (const MediaSessionParams *csp) { LinphoneStatus MediaSessionPrivate::acceptUpdate (const CallSessionParams *csp, LinphoneCallState nextState, const string &stateInfo) { L_Q(); - SalMediaDescription *desc = sal_call_get_remote_media_description(op); + SalMediaDescription *desc = op->get_remote_media_description(); bool keepSdpVersion = !!lp_config_get_int(linphone_core_get_config(core), "sip", "keep_sdp_version", 0); if (keepSdpVersion && (desc->session_id == remoteSessionId) && (desc->session_ver == remoteSessionVer)) { /* Remote has sent an INVITE with the same SDP as before, so send a 200 OK with the same SDP as before. */ lWarning() << "SDP version has not changed, send same SDP as before"; - sal_call_accept(op); + op->accept(); setState(nextState, stateInfo); return 0; } if (csp) params = new MediaSessionParams(*static_cast(csp)); else { - if (!sal_call_is_offerer(op)) { + if (!op->is_offerer()) { /* Reset call params for multicast because this param is only relevant when offering */ params->enableAudioMulticast(false); params->enableVideoMulticast(false); @@ -4047,12 +4047,12 @@ LinphoneStatus MediaSession::acceptEarlyMedia (const MediaSessionParams *msp) { if (msp) { d->params = new MediaSessionParams(*msp); d->makeLocalMediaDescription(); - sal_call_set_local_media_description(d->op, d->localDesc); - sal_op_set_sent_custom_header(d->op, d->params->getPrivate()->getCustomHeaders()); + d->op->set_local_media_description(d->localDesc); + d->op->set_sent_custom_header(d->params->getPrivate()->getCustomHeaders()); } - sal_call_notify_ringing(d->op, true); + d->op->notify_ringing(true); d->setState(LinphoneCallIncomingEarlyMedia, "Incoming call early media"); - SalMediaDescription *md = sal_call_get_final_media_description(d->op); + SalMediaDescription *md = d->op->get_final_media_description(); if (md) d->updateStreams(md, d->state); return 0; @@ -4069,7 +4069,7 @@ LinphoneStatus MediaSession::acceptUpdate (const MediaSessionParams *msp) { // ----------------------------------------------------------------------------- -void MediaSession::configure (LinphoneCallDir direction, LinphoneProxyConfig *cfg, SalOp *op, const Address &from, const Address &to) { +void MediaSession::configure (LinphoneCallDir direction, LinphoneProxyConfig *cfg, SalCallOp *op, const Address &from, const Address &to) { L_D(); CallSession::configure (direction, cfg, op, from, to); @@ -4103,7 +4103,7 @@ void MediaSession::configure (LinphoneCallDir direction, LinphoneProxyConfig *cf d->params = new MediaSessionParams(); d->params->initDefault(d->core); d->initializeParamsAccordingToIncomingCallParams(); - SalMediaDescription *md = sal_call_get_remote_media_description(d->op); + SalMediaDescription *md = d->op->get_remote_media_description(); if (d->natPolicy && linphone_nat_policy_ice_enabled(d->natPolicy)) { if (md) { /* Create the ice session now if ICE is required */ @@ -4189,14 +4189,14 @@ LinphoneStatus MediaSession::resume () { audio_stream_play(d->audioStream, nullptr); d->makeLocalMediaDescription(); if (!d->core->sip_conf.sdp_200_ack) - sal_call_set_local_media_description(d->op, d->localDesc); + d->op->set_local_media_description(d->localDesc); else - sal_call_set_local_media_description(d->op, nullptr); + d->op->set_local_media_description(nullptr); sal_media_description_set_dir(d->localDesc, SalStreamSendRecv); string subject = "Call resuming"; if (d->params->getPrivate()->getInConference() && !getCurrentParams()->getPrivate()->getInConference()) subject = "Conference"; - if (sal_call_update(d->op, subject.c_str(), false) != 0) + if (d->op->update(subject.c_str(), false) != 0) return -1; d->setState(LinphoneCallResuming,"Resuming"); if (!d->params->getPrivate()->getInConference() && d->listener) @@ -4204,7 +4204,7 @@ LinphoneStatus MediaSession::resume () { if (d->core->sip_conf.sdp_200_ack) { /* We are NOT offering, set local media description after sending the call so that we are ready to * process the remote offer when it will arrive. */ - sal_call_set_local_media_description(d->op, d->localDesc); + d->op->set_local_media_description(d->localDesc); } return 0; } @@ -4220,7 +4220,7 @@ void MediaSession::sendVfuRequest () { } else if (d->core->sip_conf.vfu_with_info) { lInfo() << "Request SIP INFO FIR on CallSession [" << this << "]"; if (d->state == LinphoneCallStreamsRunning) - sal_call_send_vfu_request(d->op); + d->op->send_vfu_request(); } else lInfo() << "vfu request using sip disabled from config [sip,vfu_with_info]"; #endif @@ -4229,8 +4229,8 @@ void MediaSession::sendVfuRequest () { void MediaSession::startIncomingNotification () { L_D(); d->makeLocalMediaDescription(); - sal_call_set_local_media_description(d->op, d->localDesc); - SalMediaDescription *md = sal_call_get_final_media_description(d->op); + d->op->set_local_media_description(d->localDesc); + SalMediaDescription *md = d->op->get_final_media_description(); if (md) { if (sal_media_description_empty(md) || linphone_core_incompatible_security(d->core, md)) { LinphoneErrorInfo *ei = linphone_error_info_new(); @@ -4238,7 +4238,7 @@ void MediaSession::startIncomingNotification () { #if 0 linphone_core_report_early_failed_call(d->core, LinphoneCallIncoming, linphone_address_ref(from_addr), linphone_address_ref(to_addr), ei); #endif - sal_call_decline(d->op, SalReasonNotAcceptable, nullptr); + d->op->decline(SalReasonNotAcceptable, nullptr); #if 0 linphone_call_unref(call); #endif @@ -4262,7 +4262,7 @@ int MediaSession::startInvite (const Address *destination, const string &subject } if (!d->core->sip_conf.sdp_200_ack) { /* We are offering, set local media description before sending the call */ - sal_call_set_local_media_description(d->op, d->localDesc); + d->op->set_local_media_description(d->localDesc); } int result = CallSession::startInvite(destination, subject); @@ -4274,7 +4274,7 @@ int MediaSession::startInvite (const Address *destination, const string &subject if (d->core->sip_conf.sdp_200_ack) { /* We are NOT offering, set local media description after sending the call so that we are ready to process the remote offer when it will arrive. */ - sal_call_set_local_media_description(d->op, d->localDesc); + d->op->set_local_media_description(d->localDesc); } return result; } @@ -4585,7 +4585,7 @@ float MediaSession::getRecordVolume () const { const MediaSessionParams * MediaSession::getRemoteParams () { L_D(); if (d->op){ - SalMediaDescription *md = sal_call_get_remote_media_description(d->op); + SalMediaDescription *md = d->op->get_remote_media_description(); if (md) { if (d->remoteParams) delete d->remoteParams; @@ -4623,7 +4623,7 @@ const MediaSessionParams * MediaSession::getRemoteParams () { d->remoteParams->getPrivate()->setCustomSdpMediaAttributes(LinphoneStreamTypeVideo, md->streams[d->mainVideoStreamIndex].custom_sdp_attributes); d->remoteParams->getPrivate()->setCustomSdpMediaAttributes(LinphoneStreamTypeText, md->streams[d->mainTextStreamIndex].custom_sdp_attributes); } - const SalCustomHeader *ch = sal_op_get_recv_custom_header(d->op); + const SalCustomHeader *ch = d->op->get_recv_custom_header(); if (ch) { /* Instanciate a remote_params only if a SIP message was received before (custom headers indicates this) */ if (!d->remoteParams) diff --git a/src/conference/session/media-session.h b/src/conference/session/media-session.h index 27770ebb1..00aeebdfe 100644 --- a/src/conference/session/media-session.h +++ b/src/conference/session/media-session.h @@ -40,7 +40,7 @@ public: LinphoneStatus accept (const MediaSessionParams *msp = nullptr); LinphoneStatus acceptEarlyMedia (const MediaSessionParams *msp = nullptr); LinphoneStatus acceptUpdate (const MediaSessionParams *msp); - void configure (LinphoneCallDir direction, LinphoneProxyConfig *cfg, SalOp *op, const Address &from, const Address &to) override; + void configure (LinphoneCallDir direction, LinphoneProxyConfig *cfg, SalCallOp *op, const Address &from, const Address &to) override; void initiateIncoming () override; bool initiateOutgoing () override; void iterate (time_t currentRealTime, bool oneSecondElapsed) override; diff --git a/src/nat/ice-agent.cpp b/src/nat/ice-agent.cpp index 0a8e19c10..d002234c2 100644 --- a/src/nat/ice-agent.cpp +++ b/src/nat/ice-agent.cpp @@ -73,7 +73,7 @@ void IceAgent::deleteSession () { } void IceAgent::gatheringFinished () { - const SalMediaDescription *rmd = sal_call_get_remote_media_description(mediaSession.getPrivate()->getOp()); + const SalMediaDescription *rmd = mediaSession.getPrivate()->getOp()->get_remote_media_description(); if (rmd) clearUnusedIceCandidates(mediaSession.getPrivate()->getLocalDesc(), rmd); if (!iceSession) @@ -126,7 +126,7 @@ bool IceAgent::prepare (const SalMediaDescription *localDesc, bool incomingOffer SalMediaDescription *remoteDesc = nullptr; bool hasVideo = false; if (incomingOffer) { - remoteDesc = sal_call_get_remote_media_description(mediaSession.getPrivate()->getOp()); + remoteDesc = mediaSession.getPrivate()->getOp()->get_remote_media_description(); hasVideo = linphone_core_video_enabled(mediaSession.getPrivate()->getCore()) && linphone_core_media_description_contains_video_stream(remoteDesc); } else diff --git a/tester/account_creator_tester.c b/tester/account_creator_tester.c index dadf2c3ef..5588ae4c1 100644 --- a/tester/account_creator_tester.c +++ b/tester/account_creator_tester.c @@ -17,7 +17,7 @@ */ #include "liblinphone_tester.h" -#include "private.h" +#include static const char XMLRPC_URL[] = "https://sip2.linphone.org:446/xmlrpc.php"; @@ -338,6 +338,20 @@ static void account_creator_cb(LinphoneAccountCreator *creator, LinphoneAccountC account_creator_set_cb_done(cbs); } +static void set_string(char **dest, const char *src, bool_t lowercase) { + if (*dest) { + ms_free(*dest); + *dest = NULL; + } + if (src) { + *dest = ms_strdup(src); + if (lowercase) { + char *cur = *dest; + for (; *cur; cur++) *cur = tolower(*cur); + } + } +} + static void _get_activation_code_cb(LinphoneXmlRpcRequest *request) { LinphoneAccountCreator *creator = (LinphoneAccountCreator *)linphone_xml_rpc_request_get_user_data(request); LinphoneAccountCreatorStatus status = LinphoneAccountCreatorStatusRequestFailed; diff --git a/tester/accountmanager.c b/tester/accountmanager.c index 3fc4e265a..a26f3f94f 100644 --- a/tester/accountmanager.c +++ b/tester/accountmanager.c @@ -16,8 +16,9 @@ along with this program. If not, see . */ +#include #include "liblinphone_tester.h" -#include "private.h" +#include "tester_utils.h" struct _Account{ LinphoneAddress *identity; @@ -100,7 +101,7 @@ static void account_created_on_server_cb(LinphoneCore *lc, LinphoneProxyConfig * Account *account=(Account*)linphone_core_get_user_data(lc); switch(state){ case LinphoneRegistrationOk: { - char * phrase = sal_op_get_error_info((SalOp*)cfg->op)->full_string; + char * phrase = sal_op_get_error_info(linphone_proxy_config_get_sal_op(cfg))->full_string; if (phrase && strcasecmp("Test account created", phrase) == 0) { account->created=1; } else { @@ -236,10 +237,10 @@ static LinphoneAddress *account_manager_check_account(AccountManager *m, Linphon /* create and/or set uuid */ if (account->uuid == NULL) { char tmp[64]; - sal_create_uuid(cm->lc->sal, tmp, sizeof(tmp)); + sal_create_uuid(linphone_core_get_sal(cm->lc), tmp, sizeof(tmp)); account->uuid = bctbx_strdup(tmp); } - sal_set_uuid(cm->lc->sal, account->uuid); + sal_set_uuid(linphone_core_get_sal(cm->lc), account->uuid); } /*remove previous auth info to avoid mismatching*/ diff --git a/tester/audio_bypass_tester.c b/tester/audio_bypass_tester.c index 1d85bdbef..98809f1f3 100644 --- a/tester/audio_bypass_tester.c +++ b/tester/audio_bypass_tester.c @@ -17,7 +17,6 @@ */ #include "liblinphone_tester.h" -#include "private.h" #include "audio_bypass_wav_header.h" // This is a copy of mediastreamer2/src/audiofilters/wav_header.h /********************************************************************** @@ -436,7 +435,7 @@ static void only_enable_payload(LinphoneCore *lc, const char *mime, int rate, in * This is important so that the audio comparison is succesful*/ static void set_jitter_buffer_params(LinphoneCore *lc){ int jitter_buffer_ms = 300; - lp_config_set_int(lc->config, "rtp", "jitter_buffer_min_size", jitter_buffer_ms); + lp_config_set_int(linphone_core_get_config(lc), "rtp", "jitter_buffer_min_size", jitter_buffer_ms); linphone_core_set_audio_jittcomp(lc, jitter_buffer_ms); } @@ -457,8 +456,8 @@ static void audio_bypass(void) { double similar=1; const double threshold = 0.85; - lp_config_set_string(marie_lc->config, "sound", "features", "None"); - lp_config_set_string(pauline_lc->config, "sound", "features", "None"); + lp_config_set_string(linphone_core_get_config(marie_lc), "sound", "features", "None"); + lp_config_set_string(linphone_core_get_config(pauline_lc), "sound", "features", "None"); /*make sure the record file doesn't already exists, otherwise this test will append new samples to it*/ unlink(recordpath); diff --git a/tester/call_multi_tester.c b/tester/call_multi_tester.c index 11c0718a5..56581a1e8 100644 --- a/tester/call_multi_tester.c +++ b/tester/call_multi_tester.c @@ -21,7 +21,6 @@ #include #include "linphone/core.h" #include "linphone/lpconfig.h" -#include "private.h" #include "liblinphone_tester.h" #include "mediastreamer2/msutils.h" #include "belle-sip/sipstack.h" @@ -259,7 +258,7 @@ static void simple_conference_base(LinphoneCoreManager* marie, LinphoneCoreManag lcs=bctbx_list_append(lcs,laure->lc); if (focus) lcs=bctbx_list_append(lcs,focus->lc); - is_remote_conf = (strcmp(lp_config_get_string(marie->lc->config, "misc", "conference_type", "local"), "remote") == 0); + is_remote_conf = (strcmp(lp_config_get_string(linphone_core_get_config(marie->lc), "misc", "conference_type", "local"), "remote") == 0); if(is_remote_conf) BC_ASSERT_PTR_NOT_NULL(focus); if (!BC_ASSERT_TRUE(call(marie,pauline))) goto end; @@ -836,7 +835,7 @@ static void eject_from_3_participants_conference(LinphoneCoreManager *marie, Lin lcs=bctbx_list_append(lcs,laure->lc); if(focus) lcs=bctbx_list_append(lcs,focus->lc); - is_remote_conf = (strcmp(lp_config_get_string(marie->lc->config, "misc", "conference_type", "local"), "remote") == 0); + is_remote_conf = (strcmp(lp_config_get_string(linphone_core_get_config(marie->lc), "misc", "conference_type", "local"), "remote") == 0); if(is_remote_conf) BC_ASSERT_PTR_NOT_NULL(focus); BC_ASSERT_TRUE(call(marie,pauline)); @@ -1130,7 +1129,7 @@ void do_not_stop_ringing_when_declining_one_of_two_incoming_calls(void) { linphone_call_decline(pauline_called_by_laure, LinphoneReasonDeclined); BC_ASSERT_TRUE(wait_for(laure->lc,pauline->lc,&pauline->stat.number_of_LinphoneCallEnd,1)); - BC_ASSERT_TRUE(linphone_ringtoneplayer_is_started(pauline->lc->ringtoneplayer)); + BC_ASSERT_TRUE(linphone_ringtoneplayer_is_started(linphone_core_get_ringtoneplayer(pauline->lc))); linphone_call_terminate(pauline_called_by_marie); BC_ASSERT_TRUE(wait_for(marie->lc,pauline->lc,&pauline->stat.number_of_LinphoneCallEnd,2)); diff --git a/tester/call_single_tester.c b/tester/call_single_tester.c index cf7f0969c..c658917d8 100644 --- a/tester/call_single_tester.c +++ b/tester/call_single_tester.c @@ -21,7 +21,6 @@ #include #include "linphone/core.h" #include "linphone/lpconfig.h" -#include "private.h" #include "liblinphone_tester.h" #include "mediastreamer2/msutils.h" #include "belle-sip/sipstack.h" @@ -45,10 +44,11 @@ extern void libmsopenh264_init(MSFactory *factory); void call_state_changed(LinphoneCore *lc, LinphoneCall *call, LinphoneCallState cstate, const char *msg){ - char* to=linphone_address_as_string(linphone_call_get_call_log(call)->to); - char* from=linphone_address_as_string(linphone_call_get_call_log(call)->from); + LinphoneCallLog *calllog = linphone_call_get_call_log(call); + char* to=linphone_address_as_string(linphone_call_log_get_to(calllog)); + char* from=linphone_address_as_string(linphone_call_log_get_from(calllog)); stats* counters; - ms_message(" %s call from [%s] to [%s], new state is [%s]" ,linphone_call_get_call_log(call)->dir==LinphoneCallIncoming?"Incoming":"Outgoing" + ms_message(" %s call from [%s] to [%s], new state is [%s]" ,linphone_call_log_get_dir(calllog)==LinphoneCallIncoming?"Incoming":"Outgoing" ,from ,to ,linphone_call_state_to_string(cstate)); @@ -131,10 +131,11 @@ void call_stats_updated(LinphoneCore *lc, LinphoneCall *call, const LinphoneCall } void linphone_call_encryption_changed(LinphoneCore *lc, LinphoneCall *call, bool_t on, const char *authentication_token) { - char* to=linphone_address_as_string(linphone_call_get_call_log(call)->to); - char* from=linphone_address_as_string(linphone_call_get_call_log(call)->from); + LinphoneCallLog *calllog = linphone_call_get_call_log(call); + char* to=linphone_address_as_string(linphone_call_log_get_to(calllog)); + char* from=linphone_address_as_string(linphone_call_log_get_from(calllog)); stats* counters; - ms_message(" %s call from [%s] to [%s], is now [%s]",linphone_call_get_call_log(call)->dir==LinphoneCallIncoming?"Incoming":"Outgoing" + ms_message(" %s call from [%s] to [%s], is now [%s]",linphone_call_log_get_dir(calllog)==LinphoneCallIncoming?"Incoming":"Outgoing" ,from ,to ,(on?"encrypted":"unencrypted")); @@ -148,8 +149,9 @@ void linphone_call_encryption_changed(LinphoneCore *lc, LinphoneCall *call, bool } void linphone_transfer_state_changed(LinphoneCore *lc, LinphoneCall *transfered, LinphoneCallState new_call_state) { - char* to=linphone_address_as_string(linphone_call_get_call_log(transfered)->to); - char* from=linphone_address_as_string(linphone_call_get_call_log(transfered)->from); + LinphoneCallLog *clog = linphone_call_get_call_log(transfered); + char* to=linphone_address_as_string(linphone_call_log_get_to(clog)); + char* from=linphone_address_as_string(linphone_call_log_get_to(clog)); stats* counters; ms_message("Transferred call from [%s] to [%s], new state is [%s]",from,to,linphone_call_state_to_string(new_call_state)); ms_free(to); @@ -171,8 +173,9 @@ void linphone_transfer_state_changed(LinphoneCore *lc, LinphoneCall *transfered, void linphone_call_iframe_decoded_cb(LinphoneCall *call,void * user_data) { - char* to=linphone_address_as_string(linphone_call_get_call_log(call)->to); - char* from=linphone_address_as_string(linphone_call_get_call_log(call)->from); + LinphoneCallLog *calllog = linphone_call_get_call_log(call); + char* to=linphone_address_as_string(linphone_call_log_get_to(calllog)); + char* from=linphone_address_as_string(linphone_call_log_get_from(calllog)); stats* counters; LinphoneCore* lc=(LinphoneCore*)user_data; ms_message("call from [%s] to [%s] receive iFrame",from,to); @@ -265,9 +268,9 @@ void liblinphone_tester_check_rtcp(LinphoneCoreManager* caller, LinphoneCoreMana static void setup_sdp_handling(const LinphoneCallTestParams* params, LinphoneCoreManager* mgr ){ if( params->sdp_removal ){ - sal_default_set_sdp_handling(mgr->lc->sal, SalOpSDPSimulateRemove); + sal_default_set_sdp_handling(linphone_core_get_sal(mgr->lc), SalOpSDPSimulateRemove); } else if( params->sdp_simulate_error ){ - sal_default_set_sdp_handling(mgr->lc->sal, SalOpSDPSimulateError); + sal_default_set_sdp_handling(linphone_core_get_sal(mgr->lc), SalOpSDPSimulateError); } } @@ -318,8 +321,8 @@ bool_t call_with_params2(LinphoneCoreManager* caller_mgr ,initial_callee.number_of_LinphoneCallIncomingReceived+1); BC_ASSERT_EQUAL(did_receive_call, !callee_test_params->sdp_simulate_error, int, "%d"); - sal_default_set_sdp_handling(caller_mgr->lc->sal, SalOpSDPNormal); - sal_default_set_sdp_handling(callee_mgr->lc->sal, SalOpSDPNormal); + sal_default_set_sdp_handling(linphone_core_get_sal(caller_mgr->lc), SalOpSDPNormal); + sal_default_set_sdp_handling(linphone_core_get_sal(caller_mgr->lc), SalOpSDPNormal); if (!did_receive_call) return 0; @@ -354,7 +357,7 @@ bool_t call_with_params2(LinphoneCoreManager* caller_mgr if (linphone_call_params_get_privacy(linphone_call_get_current_params(linphone_core_get_current_call(caller_mgr->lc))) == LinphonePrivacyNone) { /*don't check in case of p asserted id*/ - if (!lp_config_get_int(callee_mgr->lc->config,"sip","call_logs_use_asserted_id_instead_of_from",0)) + if (!lp_config_get_int(linphone_core_get_config(callee_mgr->lc),"sip","call_logs_use_asserted_id_instead_of_from",0)) BC_ASSERT_TRUE(linphone_address_weak_equal(callee_from,linphone_call_get_remote_address(callee_call))); } else { BC_ASSERT_FALSE(linphone_address_weak_equal(callee_from,linphone_call_get_remote_address(linphone_core_get_current_call(callee_mgr->lc)))); @@ -416,8 +419,8 @@ bool_t call_with_params2(LinphoneCoreManager* caller_mgr if (linphone_core_get_firewall_policy(caller_mgr->lc) == LinphonePolicyUseIce && linphone_core_get_firewall_policy(callee_mgr->lc) == LinphonePolicyUseIce && !linphone_core_sdp_200_ack_enabled(caller_mgr->lc) /*ice does not work with sdp less invite*/ - && lp_config_get_int(callee_mgr->lc->config, "sip", "update_call_when_ice_completed", TRUE) - && lp_config_get_int(caller_mgr->lc->config, "sip", "update_call_when_ice_completed", TRUE) + && lp_config_get_int(linphone_core_get_config(callee_mgr->lc), "sip", "update_call_when_ice_completed", TRUE) + && lp_config_get_int(linphone_core_get_config(callee_mgr->lc), "sip", "update_call_when_ice_completed", TRUE) && linphone_core_get_media_encryption(caller_mgr->lc) != LinphoneMediaEncryptionDTLS /*no ice-reinvite with DTLS*/) { BC_ASSERT_TRUE(wait_for(callee_mgr->lc,caller_mgr->lc,&caller_mgr->stat.number_of_LinphoneCallStreamsRunning,initial_caller.number_of_LinphoneCallStreamsRunning+2)); BC_ASSERT_TRUE(wait_for(callee_mgr->lc,caller_mgr->lc,&callee_mgr->stat.number_of_LinphoneCallStreamsRunning,initial_callee.number_of_LinphoneCallStreamsRunning+2)); @@ -655,19 +658,19 @@ static void call_with_timed_out_bye(void) { BC_ASSERT_TRUE(call(marie,pauline)); - sal_set_send_error(pauline->lc->sal,1500); /*to trash the message without generating error*/ + sal_set_send_error(linphone_core_get_sal(pauline->lc),1500); /*to trash the message without generating error*/ timer_config.T1=50; /*to have timer F = 3s*/ timer_config.T2=4000; timer_config.T3=0; timer_config.T4=5000; - belle_sip_stack_set_timer_config(sal_get_stack_impl(pauline->lc->sal),&timer_config); + belle_sip_stack_set_timer_config(sal_get_stack_impl(linphone_core_get_sal(pauline->lc)),&timer_config); linphone_core_terminate_all_calls(pauline->lc); BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallEnd,1)); BC_ASSERT_TRUE(wait_for_until(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallReleased,1,timer_config.T1*84)); - sal_set_send_error(pauline->lc->sal,0); + sal_set_send_error(linphone_core_get_sal(pauline->lc),0); linphone_core_terminate_all_calls(marie->lc); BC_ASSERT_TRUE(wait_for_until(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneCallEnd,1,5000)); @@ -1269,7 +1272,7 @@ static void call_with_dns_time_out(void) { linphone_core_set_sip_transports(marie->lc,&transport); linphone_core_iterate(marie->lc); - sal_set_dns_timeout(marie->lc->sal,0); + sal_set_dns_timeout(linphone_core_get_sal(marie->lc),0); linphone_core_invite(marie->lc,"\"t\x8et\x8e\" "); /*just to use non ascii values*/ for(i=0;i<10;i++){ ms_usleep(200000); @@ -1503,7 +1506,7 @@ static void call_with_no_sdp_ack_without_sdp(void){ BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallIncomingReceived,1)); call=linphone_core_get_current_call(pauline->lc); if (call){ - sal_call_set_sdp_handling(linphone_call_get_op(call), SalOpSDPSimulateError); /*this will have the effect that the SDP received in the ACK will be ignored*/ + sal_call_set_sdp_handling(linphone_call_get_op_as_sal_op(call), SalOpSDPSimulateError); /*this will have the effect that the SDP received in the ACK will be ignored*/ linphone_call_accept(call); BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallError,1)); BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneCallEnd,1)); @@ -1954,8 +1957,8 @@ static void call_caller_with_custom_header_or_sdp_attributes(void) { linphone_call_params_unref(caller_params); - sal_default_set_sdp_handling(caller_mgr->lc->sal, SalOpSDPNormal); - sal_default_set_sdp_handling(callee_mgr->lc->sal, SalOpSDPNormal); + sal_default_set_sdp_handling(linphone_core_get_sal(caller_mgr->lc), SalOpSDPNormal); + sal_default_set_sdp_handling(linphone_core_get_sal(caller_mgr->lc), SalOpSDPNormal); // Wait for Outgoing Progress if (linphone_core_get_calls_nb(callee_mgr->lc)<=1) @@ -2074,8 +2077,8 @@ static void call_callee_with_custom_header_or_sdp_attributes(void) { - sal_default_set_sdp_handling(caller_mgr->lc->sal, SalOpSDPNormal); - sal_default_set_sdp_handling(callee_mgr->lc->sal, SalOpSDPNormal); + sal_default_set_sdp_handling(linphone_core_get_sal(caller_mgr->lc), SalOpSDPNormal); + sal_default_set_sdp_handling(linphone_core_get_sal(caller_mgr->lc), SalOpSDPNormal); // Wait for Outgoing Progress if (linphone_core_get_calls_nb(callee_mgr->lc)<=1) @@ -2140,14 +2143,14 @@ void call_paused_resumed_base(bool_t multicast, bool_t with_losses) { wait_for_until(pauline->lc, marie->lc, NULL, 5, 3000); if (with_losses) { - sal_set_send_error(marie->lc->sal,1500); /*to trash 200ok without generating error*/ + sal_set_send_error(linphone_core_get_sal(marie->lc),1500); /*to trash 200ok without generating error*/ } linphone_call_pause(call_pauline); BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallPausing,1)); if (with_losses) { BC_ASSERT_FALSE(wait_for_until(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallPaused,1,1000)); - sal_set_send_error(marie->lc->sal,0); /*to trash 200ok without generating error*/ + sal_set_send_error(linphone_core_get_sal(marie->lc),0); /*to trash 200ok without generating error*/ } @@ -2175,12 +2178,12 @@ void call_paused_resumed_base(bool_t multicast, bool_t with_losses) { if (with_losses) { /* now we want to loose the ack*/ linphone_call_pause(call_pauline); - sal_set_send_error(pauline->lc->sal,1500); /*to trash ACK without generating error*/ + sal_set_send_error(linphone_core_get_sal(pauline->lc),1500); /*to trash ACK without generating error*/ BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallPausing,2)); BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneCallPausedByRemote,2)); BC_ASSERT_TRUE(wait_for_until(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallPaused,2,1000)); /*now try to resume, it should be OK*/ - sal_set_send_error(pauline->lc->sal,0); + sal_set_send_error(linphone_core_get_sal(pauline->lc),0); linphone_call_resume(call_pauline); BC_ASSERT_TRUE(wait_for_until(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallStreamsRunning,3,2000)); BC_ASSERT_TRUE(wait_for_until(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneCallStreamsRunning,3,2000)); @@ -2820,7 +2823,7 @@ static void call_with_mkv_file_player(void) { linphone_player_cbs_set_user_data(cbs, marie); int res = linphone_player_open(player,hellomkv); //if(!ms_filter_codec_supported("opus")) { - if(!ms_factory_codec_supported(marie->lc->factory, "opus") && !ms_factory_codec_supported(pauline->lc->factory, "opus")){ + if(!ms_factory_codec_supported(linphone_core_get_ms_factory(marie->lc), "opus") && !ms_factory_codec_supported(linphone_core_get_ms_factory(pauline->lc), "opus")){ BC_ASSERT_EQUAL(res, -1, int, "%d"); end_call(marie, pauline); goto end; @@ -2911,13 +2914,13 @@ static void _call_base_with_configfile(LinphoneMediaEncryption mode, bool_t enab linphone_core_set_media_encryption(pauline->lc,mode); if (mode==LinphoneMediaEncryptionDTLS) { /* for DTLS we must access certificates or at least have a directory to store them */ char *path = bc_tester_file("certificates-marie"); - marie->lc->user_certificates_path = ms_strdup(path); + linphone_core_set_user_certificates_path(marie->lc, path); bc_free(path); path = bc_tester_file("certificates-pauline"); - pauline->lc->user_certificates_path = ms_strdup(path); + linphone_core_set_user_certificates_path(pauline->lc, path); bc_free(path); - belle_sip_mkdir(marie->lc->user_certificates_path); - belle_sip_mkdir(pauline->lc->user_certificates_path); + belle_sip_mkdir(linphone_core_get_user_certificates_path(marie->lc)); + belle_sip_mkdir(linphone_core_get_user_certificates_path(pauline->lc)); } linphone_core_set_firewall_policy(marie->lc,policy); @@ -3249,14 +3252,14 @@ static void call_established_with_rejected_info(void) { BC_ASSERT_TRUE((call_ok=call(pauline,marie))); if (call_ok){ - sal_enable_unconditional_answer(marie->lc->sal,TRUE); + sal_enable_unconditional_answer(linphone_core_get_sal(marie->lc),TRUE); im1 = linphone_core_create_info_message(pauline->lc); linphone_call_send_info_message(linphone_core_get_current_call(pauline->lc),im1); wait_for_until(marie->lc,pauline->lc,&dummy,1,1000); /*just to sleep while iterating 1s*/ linphone_info_message_unref(im1); - sal_enable_unconditional_answer(marie->lc->sal,FALSE); + sal_enable_unconditional_answer(linphone_core_get_sal(marie->lc),FALSE); im2 = linphone_core_create_info_message(pauline->lc); linphone_call_send_info_message(linphone_core_get_current_call(pauline->lc),im2); @@ -3319,7 +3322,7 @@ static void call_established_with_complex_rejected_operation(void) { linphone_info_message_unref(info); params=linphone_core_create_call_params(marie->lc,linphone_core_get_current_call(marie->lc)); - sal_enable_pending_trans_checking(marie->lc->sal,FALSE); /*to allow // transactions*/ + sal_enable_pending_trans_checking(linphone_core_get_sal(marie->lc),FALSE); /*to allow // transactions*/ linphone_core_enable_payload_type(marie->lc,linphone_core_find_payload_type(marie->lc,"PCMU",8000,1),TRUE); linphone_core_enable_payload_type(marie->lc,linphone_core_find_payload_type(marie->lc,"PCMA",8000,1),FALSE); @@ -3515,7 +3518,7 @@ static void call_established_with_rejected_reinvite_with_error_base(bool_t trans linphone_info_message_unref(info); } else - sal_enable_unconditional_answer(marie->lc->sal,TRUE); + sal_enable_unconditional_answer(linphone_core_get_sal(marie->lc),TRUE); result = linphone_call_update(linphone_core_get_current_call(pauline->lc),linphone_call_get_current_params(linphone_core_get_current_call(pauline->lc))); @@ -3533,7 +3536,7 @@ static void call_established_with_rejected_reinvite_with_error_base(bool_t trans check_call_state(marie,LinphoneCallStreamsRunning); if (!trans_pending) - sal_enable_unconditional_answer(marie->lc->sal,FALSE); + sal_enable_unconditional_answer(linphone_core_get_sal(marie->lc),FALSE); end_call(pauline, marie); } @@ -3563,7 +3566,9 @@ static void call_rejected_because_wrong_credentials_with_params(const char* user linphone_core_set_user_agent(marie->lc,user_agent,NULL); } if (!enable_auth_req_cb) { - ((VTableReference*)(marie->lc->vtable_refs->data))->cbs->vtable->auth_info_requested=NULL; + // ((VTableReference*)(marie->lc->vtable_refs->data))->cbs->vtable->auth_info_requested=NULL; + LinphoneCoreCbs *cbs = linphone_core_get_first_callbacks(marie->lc); + linphone_core_cbs_set_auth_info_requested(cbs, NULL); linphone_core_add_auth_info(marie->lc,wrong_auth_info); } @@ -4080,7 +4085,7 @@ void early_media_without_sdp_in_200_base( bool_t use_video, bool_t use_ice ){ liblinphone_tester_check_rtcp(marie, pauline); /* will send the 200OK _without_ SDP. We expect the early-media SDP to be used instead */ - sal_call_set_sdp_handling(linphone_call_get_op(pauline_call), SalOpSDPSimulateRemove); + sal_call_set_sdp_handling(linphone_call_get_op_as_sal_op(pauline_call), SalOpSDPSimulateRemove); linphone_call_accept(pauline_call); BC_ASSERT_TRUE(wait_for_list(lcs, &marie->stat.number_of_LinphoneCallConnected, 1,1000)); @@ -4175,9 +4180,10 @@ static void call_state_changed_2(LinphoneCore *lc, LinphoneCall *call, LinphoneC static void call_state_changed_3(LinphoneCore *lc, LinphoneCall *call, LinphoneCallState cstate, const char *msg){ /*just to check multi listener in such situation*/ - char* to=linphone_address_as_string(linphone_call_get_call_log(call)->to); - char* from=linphone_address_as_string(linphone_call_get_call_log(call)->from); - ms_message("Third call listener reports: %s call from [%s] to [%s], new state is [%s]" ,linphone_call_get_call_log(call)->dir==LinphoneCallIncoming?"Incoming":"Outgoing" + LinphoneCallLog *clog = linphone_call_get_call_log(call); + char* to=linphone_address_as_string(linphone_call_log_get_to(clog)); + char* from=linphone_address_as_string(linphone_call_log_get_from(clog)); + ms_message("Third call listener reports: %s call from [%s] to [%s], new state is [%s]" ,linphone_call_log_get_dir(clog)==LinphoneCallIncoming?"Incoming":"Outgoing" ,from ,to ,linphone_call_state_to_string(cstate)); @@ -4268,8 +4274,8 @@ static void simple_stereo_call(const char *codec_name, int clock_rate, int bitra linphone_core_set_record_file(pauline->lc, recordpath); /*stereo is supported only without volume control, echo canceller...*/ - lp_config_set_string(marie->lc->config,"sound","features","REMOTE_PLAYING"); - lp_config_set_string(pauline->lc->config,"sound","features","REMOTE_PLAYING"); + lp_config_set_string(linphone_core_get_config(marie->lc),"sound","features","REMOTE_PLAYING"); + lp_config_set_string(linphone_core_get_config(pauline->lc),"sound","features","REMOTE_PLAYING"); if (!BC_ASSERT_TRUE(call(pauline,marie))) goto end; wait_for_until(marie->lc, pauline->lc, NULL, 0, 6000); @@ -4486,12 +4492,12 @@ static void call_with_rtp_io_mode(void) { /* The callee uses the RTP IO mode with the PCMU codec to send back audio to the caller. */ disable_all_audio_codecs_except_one(pauline->lc, "pcmu", -1); - lp_config_set_int(pauline->lc->config, "sound", "rtp_io", 1); - lp_config_set_string(pauline->lc->config, "sound", "rtp_local_addr", linphone_core_ipv6_enabled(pauline->lc) ? "::1" : "127.0.0.1"); - lp_config_set_string(pauline->lc->config, "sound", "rtp_remote_addr", linphone_core_ipv6_enabled(pauline->lc) ? "::1" : "127.0.0.1"); - lp_config_set_int(pauline->lc->config, "sound", "rtp_local_port", 17076); - lp_config_set_int(pauline->lc->config, "sound", "rtp_remote_port", 17076); - lp_config_set_string(pauline->lc->config, "sound", "rtp_map", "pcmu/8000/1"); + lp_config_set_int(linphone_core_get_config(pauline->lc), "sound", "rtp_io", 1); + lp_config_set_string(linphone_core_get_config(pauline->lc), "sound", "rtp_local_addr", linphone_core_ipv6_enabled(pauline->lc) ? "::1" : "127.0.0.1"); + lp_config_set_string(linphone_core_get_config(pauline->lc), "sound", "rtp_remote_addr", linphone_core_ipv6_enabled(pauline->lc) ? "::1" : "127.0.0.1"); + lp_config_set_int(linphone_core_get_config(pauline->lc), "sound", "rtp_local_port", 17076); + lp_config_set_int(linphone_core_get_config(pauline->lc), "sound", "rtp_remote_port", 17076); + lp_config_set_string(linphone_core_get_config(pauline->lc), "sound", "rtp_map", "pcmu/8000/1"); BC_ASSERT_TRUE((call_ok = call(marie, pauline))); if (!call_ok) goto end; @@ -5020,9 +5026,9 @@ static void recovered_call_on_network_switch_in_early_state_4(void) { BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &marie->stat.number_of_LinphoneCallStreamsRunning, 1)); BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &pauline->stat.number_of_LinphoneCallStreamsRunning, 1)); - BC_ASSERT_TRUE(sal_call_dialog_request_pending(linphone_call_get_op(incoming_call))); + BC_ASSERT_TRUE(sal_call_dialog_request_pending(linphone_call_get_op_as_sal_op(incoming_call))); wait_for_until(marie->lc, pauline->lc, NULL, 1, 2000); - BC_ASSERT_FALSE(sal_call_dialog_request_pending(linphone_call_get_op(incoming_call))); + BC_ASSERT_FALSE(sal_call_dialog_request_pending(linphone_call_get_op_as_sal_op(incoming_call))); linphone_call_terminate(incoming_call); BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &pauline->stat.number_of_LinphoneCallEnd, 1)); BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &marie->stat.number_of_LinphoneCallReleased, 1)); @@ -5075,7 +5081,7 @@ static void configure_video_policies_for_network_switch(LinphoneCore *marie, Lin linphone_core_enable_video_display(pauline, TRUE); linphone_core_set_video_policy(marie, &policy); linphone_core_set_video_policy(pauline, &policy); - lp_config_set_int(pauline->config, "sip", "defer_update_default", TRUE); + lp_config_set_int(linphone_core_get_config(pauline), "sip", "defer_update_default", TRUE); } static void recovered_call_on_network_switch_during_reinvite_2(void) { @@ -5479,13 +5485,13 @@ end: static void call_logs_if_no_db_set(void) { LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc"); LinphoneCoreManager* laure = linphone_core_manager_new("laure_call_logs_rc"); - BC_ASSERT_TRUE(bctbx_list_size(laure->lc->call_logs) == 10); + BC_ASSERT_TRUE(bctbx_list_size(linphone_core_get_call_logs(laure->lc)) == 10); BC_ASSERT_TRUE(call(marie, laure)); wait_for_until(marie->lc, laure->lc, NULL, 5, 1000); end_call(marie, laure); - BC_ASSERT_TRUE(bctbx_list_size(laure->lc->call_logs) == 11); + BC_ASSERT_TRUE(bctbx_list_size(linphone_core_get_call_logs(laure->lc)) == 11); linphone_core_manager_destroy(marie); linphone_core_manager_destroy(laure); } @@ -5495,15 +5501,16 @@ static void call_logs_migrate(void) { char *logs_db = bc_tester_file("call_logs.db"); size_t i = 0; int incoming_count = 0, outgoing_count = 0, missed_count = 0, aborted_count = 0, decline_count = 0, video_enabled_count = 0; + bctbx_list_t **call_logs_attr = NULL; unlink(logs_db); - BC_ASSERT_TRUE(bctbx_list_size(laure->lc->call_logs) == 10); + BC_ASSERT_TRUE(bctbx_list_size(linphone_core_get_call_logs(laure->lc)) == 10); linphone_core_set_call_logs_database_path(laure->lc, logs_db); BC_ASSERT_TRUE(linphone_core_get_call_history_size(laure->lc) == 10); - for (; i < bctbx_list_size(laure->lc->call_logs); i++) { - LinphoneCallLog *log = bctbx_list_nth_data(laure->lc->call_logs, (int)i); + for (; i < bctbx_list_size(linphone_core_get_call_logs(laure->lc)); i++) { + LinphoneCallLog *log = bctbx_list_nth_data(linphone_core_get_call_logs(laure->lc), (int)i); LinphoneCallStatus state = linphone_call_log_get_status(log); LinphoneCallDir direction = linphone_call_log_get_dir(log); @@ -5536,15 +5543,16 @@ static void call_logs_migrate(void) { LinphoneCallLog *log = linphone_core_get_last_outgoing_call_log(laure->lc); BC_ASSERT_PTR_NOT_NULL(log); if (log) { - BC_ASSERT_EQUAL((int)log->start_date_time, 1441738272, int, "%d"); + BC_ASSERT_EQUAL((int)linphone_call_log_get_start_date(log), 1441738272, int, "%d"); linphone_call_log_unref(log); log = NULL; } } - laure->lc->call_logs = bctbx_list_free_with_data(laure->lc->call_logs, (void (*)(void*))linphone_call_log_unref); - laure->lc->call_logs = call_logs_read_from_config_file(laure->lc); - BC_ASSERT_TRUE(bctbx_list_size(laure->lc->call_logs) == 0); + call_logs_attr = linphone_core_get_call_logs_attribute(laure->lc); + *call_logs_attr = bctbx_list_free_with_data(*call_logs_attr, (void (*)(void*))linphone_call_log_unref); + *call_logs_attr = linphone_core_read_call_logs_from_config_file(laure->lc); + BC_ASSERT_TRUE(bctbx_list_size(linphone_core_get_call_logs(laure->lc)) == 0); unlink(logs_db); ms_free(logs_db); @@ -5823,7 +5831,7 @@ static void call_with_ice_with_default_candidate_not_stun(void){ char localip[LINPHONE_IPADDR_SIZE]; bool_t call_ok; - lp_config_set_int(marie->lc->config, "net", "dont_default_to_stun_candidates", 1); + lp_config_set_int(linphone_core_get_config(marie->lc), "net", "dont_default_to_stun_candidates", 1); linphone_core_set_firewall_policy(marie->lc, LinphonePolicyUseIce); linphone_core_set_firewall_policy(pauline->lc, LinphonePolicyUseIce); linphone_core_get_local_ip(marie->lc, AF_INET, NULL, localip); @@ -5931,7 +5939,8 @@ static void call_with_encryption_mandatory(bool_t caller_has_encryption_mandator LinphoneCoreManager* pauline = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc"); LinphoneCallStats *marie_stats, *pauline_stats; /*marie doesn't support ZRTP at all*/ - marie->lc->zrtp_not_available_simulation=1; + // marie->lc->zrtp_not_available_simulation=1; + linphone_core_set_zrtp_not_available_simulation(marie->lc, TRUE); /*pauline requests encryption to be mandatory*/ linphone_core_set_media_encryption(pauline->lc, LinphoneMediaEncryptionZRTP); diff --git a/tester/call_video_tester.c b/tester/call_video_tester.c index 1588d5b76..1f3872d05 100644 --- a/tester/call_video_tester.c +++ b/tester/call_video_tester.c @@ -18,7 +18,6 @@ #include "linphone/core.h" #include "liblinphone_tester.h" -#include "private.h" #ifdef VIDEO_ENABLED static void call_paused_resumed_with_video_base_call_cb(LinphoneCore *lc, LinphoneCall *call, LinphoneCallState cstate, const char *message) { @@ -235,7 +234,7 @@ bool_t request_video(LinphoneCoreManager* caller,LinphoneCoreManager* callee, bo BC_ASSERT_TRUE(wait_for(caller->lc,callee->lc,&caller->stat.number_of_LinphoneCallStreamsRunning,initial_caller_stat.number_of_LinphoneCallStreamsRunning+1)); video_policy = linphone_core_get_video_activation_policy(caller->lc); - if (video_policy->automatically_accept || accept_with_params) { + if (linphone_video_activation_policy_get_automatically_accept(video_policy) || accept_with_params) { video_added = BC_ASSERT_TRUE(linphone_call_params_video_enabled(linphone_call_get_current_params(linphone_core_get_current_call(callee->lc)))); video_added = BC_ASSERT_TRUE(linphone_call_params_video_enabled(linphone_call_get_current_params(linphone_core_get_current_call(caller->lc)))) @@ -567,13 +566,13 @@ void video_call_base_2(LinphoneCoreManager* caller,LinphoneCoreManager* callee, if (mode==LinphoneMediaEncryptionDTLS) { /* for DTLS we must access certificates or at least have a directory to store them */ char *path = bc_tester_file("certificates-marie"); - callee->lc->user_certificates_path = ms_strdup(path); + linphone_core_set_user_certificates_path(callee->lc, path); bc_free(path); path = bc_tester_file("certificates-pauline"); - caller->lc->user_certificates_path = ms_strdup(path); + linphone_core_set_user_certificates_path(caller->lc, path); bc_free(path); - belle_sip_mkdir(callee->lc->user_certificates_path); - belle_sip_mkdir(caller->lc->user_certificates_path); + belle_sip_mkdir(linphone_core_get_user_certificates_path(callee->lc)); + belle_sip_mkdir(linphone_core_get_user_certificates_path(caller->lc)); } linphone_core_set_media_encryption(callee->lc,mode); @@ -682,13 +681,13 @@ void video_call_base_3(LinphoneCoreManager* caller,LinphoneCoreManager* callee, if (mode==LinphoneMediaEncryptionDTLS) { /* for DTLS we must access certificates or at least have a directory to store them */ char *path = bc_tester_file("certificates-marie"); - callee->lc->user_certificates_path = ms_strdup(path); + linphone_core_set_user_certificates_path(callee->lc, path); bc_free(path); path = bc_tester_file("certificates-pauline"); - caller->lc->user_certificates_path = ms_strdup(path); + linphone_core_set_user_certificates_path(caller->lc, path); bc_free(path); - belle_sip_mkdir(callee->lc->user_certificates_path); - belle_sip_mkdir(caller->lc->user_certificates_path); + belle_sip_mkdir(linphone_core_get_user_certificates_path(callee->lc)); + belle_sip_mkdir(linphone_core_get_user_certificates_path(caller->lc)); } linphone_core_set_media_encryption(callee->lc,mode); @@ -1331,7 +1330,7 @@ static void accept_call_in_send_only_base(LinphoneCoreManager* pauline, Linphone linphone_core_set_video_device(marie->lc,liblinphone_tester_mire_id); /*The send-only client shall set rtp symmetric in absence of media relay for this test.*/ - lp_config_set_int(marie->lc->config,"rtp","symmetric",1); + lp_config_set_int(linphone_core_get_config(marie->lc),"rtp","symmetric",1); linphone_call_set_next_video_frame_decoded_callback(linphone_core_invite_address(pauline->lc,marie->identity) ,linphone_call_iframe_decoded_cb @@ -1842,7 +1841,7 @@ static void incoming_reinvite_with_invalid_ack_sdp(void){ const LinphoneCallParams *caller_params; stats initial_caller_stat=caller->stat; stats initial_callee_stat=callee->stat; - sal_call_set_sdp_handling(linphone_call_get_op(inc_call), SalOpSDPSimulateError); /* will force a parse error for the ACK SDP*/ + sal_call_set_sdp_handling(linphone_call_get_op_as_sal_op(inc_call), SalOpSDPSimulateError); /* will force a parse error for the ACK SDP*/ BC_ASSERT_PTR_NOT_NULL(_request_video(caller, callee, TRUE)); BC_ASSERT_TRUE(wait_for(caller->lc,callee->lc,&callee->stat.number_of_LinphoneCallUpdating,initial_callee_stat.number_of_LinphoneCallUpdating+1)); BC_ASSERT_TRUE(wait_for(caller->lc,callee->lc,&callee->stat.number_of_LinphoneCallStreamsRunning,initial_callee_stat.number_of_LinphoneCallStreamsRunning+1)); @@ -1858,7 +1857,7 @@ static void incoming_reinvite_with_invalid_ack_sdp(void){ caller_params = linphone_call_get_current_params(linphone_core_get_current_call(caller->lc)); // TODO [refactoring]: BC_ASSERT_TRUE(wait_for(caller->lc,callee->lc,(int*)&caller_params->has_video,FALSE)); (void)caller_params; - sal_call_set_sdp_handling(linphone_call_get_op(inc_call), SalOpSDPNormal); + sal_call_set_sdp_handling(linphone_call_get_op_as_sal_op(inc_call), SalOpSDPNormal); } end_call(caller, callee); @@ -1877,7 +1876,7 @@ static void outgoing_reinvite_with_invalid_ack_sdp(void) { if (out_call) { stats initial_caller_stat=caller->stat; stats initial_callee_stat=callee->stat; - sal_call_set_sdp_handling(linphone_call_get_op(out_call), SalOpSDPSimulateError); /* will force a parse error for the ACK SDP*/ + sal_call_set_sdp_handling(linphone_call_get_op_as_sal_op(out_call), SalOpSDPSimulateError); /* will force a parse error for the ACK SDP*/ BC_ASSERT_PTR_NOT_NULL(_request_video(caller, callee, TRUE)); BC_ASSERT_TRUE(wait_for(caller->lc,callee->lc,&callee->stat.number_of_LinphoneCallUpdating,initial_callee_stat.number_of_LinphoneCallUpdating+1)); BC_ASSERT_TRUE(wait_for(caller->lc,callee->lc,&callee->stat.number_of_LinphoneCallStreamsRunning,initial_callee_stat.number_of_LinphoneCallStreamsRunning+1)); @@ -1891,7 +1890,7 @@ static void outgoing_reinvite_with_invalid_ack_sdp(void) { BC_ASSERT_FALSE(linphone_call_params_video_enabled(linphone_call_get_current_params(linphone_core_get_current_call(callee->lc)))); BC_ASSERT_FALSE(linphone_call_params_video_enabled(linphone_call_get_current_params(linphone_core_get_current_call(caller->lc)))); - sal_call_set_sdp_handling(linphone_call_get_op(out_call), SalOpSDPNormal); + sal_call_set_sdp_handling(linphone_call_get_op_as_sal_op(out_call), SalOpSDPNormal); } end_call(caller, callee); diff --git a/tester/certificates/client/cert.pem b/tester/certificates/client/cert.pem index 0893135ad..3fd0cd0d8 100644 --- a/tester/certificates/client/cert.pem +++ b/tester/certificates/client/cert.pem @@ -2,16 +2,16 @@ Certificate: Data: Version: 3 (0x2) Serial Number: 14 (0xe) - Signature Algorithm: sha256WithRSAEncryption + Signature Algorithm: sha1WithRSAEncryption Issuer: C=FR, ST=Some-State, L=Grenoble, O=Belledonne Communications, OU=LAB, CN=Jehan Monnier/emailAddress=jehan.monnier@belledonne-communications.com Validity - Not Before: Sep 20 14:00:00 2016 GMT - Not After : Sep 20 14:00:00 2017 GMT + Not Before: Sep 25 08:36:50 2017 GMT + Not After : Sep 23 08:36:50 2027 GMT Subject: C=FR, ST=Rhone-Alpes Auvergne, L=Grenoble, O=Belledonne Communications, CN=sip:sip.example.org/emailAddress=info@belledonne-communications.com Subject Public Key Info: Public Key Algorithm: rsaEncryption - Public-Key: (2048 bit) - Modulus: + RSA Public Key: (2048 bit) + Modulus (2048 bit): 00:9e:31:b6:30:07:0e:de:8b:dd:41:66:ec:52:84: 37:2c:bf:98:bc:8f:d3:8e:0d:0f:97:de:b0:4a:c6: 26:c3:c5:29:4d:4e:ed:6c:0c:fe:06:61:49:16:67: @@ -41,22 +41,22 @@ Certificate: X509v3 Authority Key Identifier: keyid:06:5F:5D:C7:16:AF:62:F8:2D:6E:71:03:88:A0:D6:1D:2B:04:7F:BA - Signature Algorithm: sha256WithRSAEncryption - 3e:6c:d5:87:db:04:2b:1b:73:93:9e:ea:fe:10:4a:38:9b:3e: - 63:8f:f2:8d:8a:d0:bc:b2:4a:63:e0:3c:31:71:00:cf:81:4a: - ae:4c:51:fc:5d:51:b7:0a:86:48:5b:1f:a6:cc:ca:d2:c3:95: - da:4b:34:dc:8c:dd:1b:27:fb:d2:a8:e4:5e:5a:cc:01:f0:63: - 58:74:72:1b:5f:c9:51:87:49:dd:ff:13:77:4c:2f:59:38:7f: - 0a:48:94:17:67:b9:7e:6a:1f:c8:29:67:e0:d4:79:c9:8c:5b: - 25:09:1d:46:f2:3a:e4:29:85:73:32:c5:94:72:59:31:57:9c: - 65:d5 + Signature Algorithm: sha1WithRSAEncryption + 93:16:99:16:33:aa:1c:cd:44:b0:cd:05:fb:11:de:eb:15:ec: + b9:a3:f1:bc:93:71:5b:6d:86:5a:f8:a1:91:96:60:52:7e:5f: + 11:a8:aa:41:aa:d8:96:07:5a:b6:8d:a6:5f:e0:db:60:58:50: + a8:b2:53:5d:e1:14:db:b5:de:8c:00:9c:83:66:b9:88:12:67: + 50:79:70:06:03:5c:eb:5a:d8:98:b2:af:39:15:ad:b9:65:ad: + 45:ef:1c:30:b1:27:6d:88:2f:2f:c6:cb:d3:a6:41:4a:95:f2: + 52:7e:d2:7f:3e:99:7e:72:43:92:e2:3b:5a:e0:3f:28:30:db: + d3:c0 -----BEGIN CERTIFICATE----- -MIID5jCCA0+gAwIBAgIBDjANBgkqhkiG9w0BAQsFADCBuzELMAkGA1UEBhMCRlIx +MIID5jCCA0+gAwIBAgIBDjANBgkqhkiG9w0BAQUFADCBuzELMAkGA1UEBhMCRlIx EzARBgNVBAgMClNvbWUtU3RhdGUxETAPBgNVBAcMCEdyZW5vYmxlMSIwIAYDVQQK DBlCZWxsZWRvbm5lIENvbW11bmljYXRpb25zMQwwCgYDVQQLDANMQUIxFjAUBgNV BAMMDUplaGFuIE1vbm5pZXIxOjA4BgkqhkiG9w0BCQEWK2plaGFuLm1vbm5pZXJA -YmVsbGVkb25uZS1jb21tdW5pY2F0aW9ucy5jb20wHhcNMTYwOTIwMTQwMDAwWhcN -MTcwOTIwMTQwMDAwWjCBtDELMAkGA1UEBhMCRlIxHTAbBgNVBAgMFFJob25lLUFs +YmVsbGVkb25uZS1jb21tdW5pY2F0aW9ucy5jb20wHhcNMTcwOTI1MDgzNjUwWhcN +MjcwOTIzMDgzNjUwWjCBtDELMAkGA1UEBhMCRlIxHTAbBgNVBAgMFFJob25lLUFs cGVzIEF1dmVyZ25lMREwDwYDVQQHDAhHcmVub2JsZTEiMCAGA1UECgwZQmVsbGVk b25uZSBDb21tdW5pY2F0aW9uczEcMBoGA1UEAwwTc2lwOnNpcC5leGFtcGxlLm9y ZzExMC8GCSqGSIb3DQEJARYiaW5mb0BiZWxsZWRvbm5lLWNvbW11bmljYXRpb25z @@ -69,7 +69,7 @@ dA7hxP32w0HFTB75i5zHfoBZ+Vvnq3b9Wp3YvW/5WHjkcoJEhTJ9wif2Umlp6OZw AKpkRW8CAwEAAaN7MHkwCQYDVR0TBAIwADAsBglghkgBhvhCAQ0EHxYdT3BlblNT TCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0OBBYEFMtXv4mv2dvM4Ph5ca1/ A2MgCkljMB8GA1UdIwQYMBaAFAZfXccWr2L4LW5xA4ig1h0rBH+6MA0GCSqGSIb3 -DQEBCwUAA4GBAD5s1YfbBCsbc5Oe6v4QSjibPmOP8o2K0LyySmPgPDFxAM+BSq5M -UfxdUbcKhkhbH6bMytLDldpLNNyM3Rsn+9Ko5F5azAHwY1h0chtfyVGHSd3/E3dM -L1k4fwpIlBdnuX5qH8gpZ+DUecmMWyUJHUbyOuQphXMyxZRyWTFXnGXV +DQEBBQUAA4GBAJMWmRYzqhzNRLDNBfsR3usV7Lmj8byTcVtthlr4oZGWYFJ+XxGo +qkGq2JYHWraNpl/g22BYUKiyU13hFNu13owAnINmuYgSZ1B5cAYDXOta2JiyrzkV +rbllrUXvHDCxJ22ILy/Gy9OmQUqV8lJ+0n8+mX5yQ5LiO1rgPygw29PA -----END CERTIFICATE----- diff --git a/tester/complex_sip_case_tester.c b/tester/complex_sip_case_tester.c index e9cbeb7df..2a572acdb 100644 --- a/tester/complex_sip_case_tester.c +++ b/tester/complex_sip_case_tester.c @@ -20,7 +20,6 @@ #include "linphone/core.h" #include "liblinphone_tester.h" #include "linphone/lpconfig.h" -#include "private.h" #if HAVE_SIPP diff --git a/tester/dtmf_tester.c b/tester/dtmf_tester.c index 3ac461e12..58723d9b9 100644 --- a/tester/dtmf_tester.c +++ b/tester/dtmf_tester.c @@ -17,7 +17,6 @@ */ #include "liblinphone_tester.h" -#include "private.h" void dtmf_received(LinphoneCore *lc, LinphoneCall *call, int dtmf) { stats* counters = get_stats(lc); @@ -37,7 +36,7 @@ void send_dtmf_base(LinphoneCoreManager **pmarie, LinphoneCoreManager **ppauline if (use_opus) { //if (!ms_filter_codec_supported("opus")) { - if(!ms_factory_codec_supported(marie->lc->factory, "opus") && !ms_factory_codec_supported(pauline->lc->factory, "opus")){ + if(!ms_factory_codec_supported(linphone_core_get_ms_factory(marie->lc), "opus") && !ms_factory_codec_supported(linphone_core_get_ms_factory(pauline->lc), "opus")){ ms_warning("Opus not supported, skipping test."); return; @@ -69,7 +68,7 @@ void send_dtmf_base(LinphoneCoreManager **pmarie, LinphoneCoreManager **ppauline } if (dtmf_seq != NULL) { - int dtmf_delay_ms = lp_config_get_int(linphone_call_get_core(marie_call)->config,"net","dtmf_delay_ms",200); + int dtmf_delay_ms = lp_config_get_int(linphone_core_get_config(linphone_call_get_core(marie_call)),"net","dtmf_delay_ms",200); dtmf_count_prev = pauline->stat.dtmf_count; linphone_call_send_dtmfs(marie_call, dtmf_seq); diff --git a/tester/eventapi_tester.c b/tester/eventapi_tester.c index 205aa3935..7bbdbf24e 100644 --- a/tester/eventapi_tester.c +++ b/tester/eventapi_tester.c @@ -19,7 +19,6 @@ #include "linphone/core.h" -#include "private.h" #include "linphone/lpconfig.h" #include #include "liblinphone_tester.h" @@ -181,7 +180,7 @@ static void subscribe_test_with_args(bool_t terminated_by_subscriber, RefreshTes lcs=bctbx_list_append(lcs,pauline->lc); if (refresh_type==ManualRefresh){ - lp_config_set_int(marie->lc->config,"sip","refresh_generic_subscribe",0); + lp_config_set_int(linphone_core_get_config(marie->lc),"sip","refresh_generic_subscribe",0); } content = linphone_core_create_content(marie->lc); @@ -239,7 +238,7 @@ static void subscribe_test_with_args2(bool_t terminated_by_subscriber, RefreshTe lcs=bctbx_list_append(lcs,pauline->lc); if (refresh_type==ManualRefresh){ - lp_config_set_int(marie->lc->config,"sip","refresh_generic_subscribe",0); + lp_config_set_int(linphone_core_get_config(marie->lc),"sip","refresh_generic_subscribe",0); } content = linphone_core_create_content(marie->lc); @@ -414,11 +413,11 @@ static void subscribe_with_io_error(void) { BC_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_NotifyReceived,1,5000)); /* now marie gets network errors when refreshing*/ - sal_set_send_error(marie->lc->sal, -1); + sal_set_send_error(linphone_core_get_sal(marie->lc), -1); /*marie will retry the subscription*/ BC_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneSubscriptionOutgoingProgress,2,8000)); - sal_set_send_error(marie->lc->sal, 0); + sal_set_send_error(linphone_core_get_sal(marie->lc), 0); /*and get it accepted again*/ BC_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneSubscriptionActive,2,10000)); @@ -498,7 +497,7 @@ static void publish_test_with_args(bool_t refresh, int expires){ linphone_content_set_subtype(content,"somexml"); linphone_content_set_buffer(content,subscribe_content,strlen(subscribe_content)); - lp_config_set_int(marie->lc->config,"sip","refresh_generic_publish",refresh); + lp_config_set_int(linphone_core_get_config(marie->lc),"sip","refresh_generic_publish",refresh); lev=linphone_core_create_publish(marie->lc,pauline->identity,"dodo",expires); linphone_event_add_custom_header(lev,"CustomHeader","someValue"); diff --git a/tester/flexisip_tester.c b/tester/flexisip_tester.c index bc03161fa..07c9d14d8 100644 --- a/tester/flexisip_tester.c +++ b/tester/flexisip_tester.c @@ -19,7 +19,6 @@ #include "linphone/core.h" #include "linphone/lpconfig.h" -#include "private.h" #include "liblinphone_tester.h" static void setPublish(LinphoneProxyConfig * proxy_config, bool_t enable) { @@ -793,12 +792,12 @@ static void file_transfer_message_rcs_to_external_body_client(void) { linphone_core_set_network_reachable(marie->lc, FALSE); linphone_core_set_network_reachable(pauline->lc, FALSE); - linphone_proxy_config_set_custom_header(marie->lc->default_proxy, "Accept", "application/sdp"); + linphone_proxy_config_set_custom_header(linphone_core_get_default_proxy_config(marie->lc), "Accept", "application/sdp"); linphone_core_set_network_reachable(marie->lc, TRUE); linphone_core_manager_start(marie, TRUE); - linphone_proxy_config_set_custom_header(pauline->lc->default_proxy, "Accept", "application/sdp, text/plain, application/vnd.gsma.rcs-ft-http+xml"); + linphone_proxy_config_set_custom_header(linphone_core_get_default_proxy_config(pauline->lc), "Accept", "application/sdp, text/plain, application/vnd.gsma.rcs-ft-http+xml"); linphone_core_set_network_reachable(pauline->lc, TRUE); linphone_core_manager_start(pauline, TRUE); @@ -891,10 +890,10 @@ static void file_transfer_message_external_body_to_external_body_client(void) { LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc"); LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc"); - linphone_proxy_config_set_custom_header(marie->lc->default_proxy, "Accept", "application/sdp"); + linphone_proxy_config_set_custom_header(linphone_core_get_default_proxy_config(marie->lc), "Accept", "application/sdp"); linphone_core_manager_start(marie, TRUE); - linphone_proxy_config_set_custom_header(pauline->lc->default_proxy, "Accept", "application/sdp"); + linphone_proxy_config_set_custom_header(linphone_core_get_default_proxy_config(pauline->lc), "Accept", "application/sdp"); linphone_core_manager_start(pauline, TRUE); reset_counters(&marie->stat); @@ -915,10 +914,10 @@ static void file_transfer_message_external_body_to_rcs_client(void) { LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc"); LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc"); - linphone_proxy_config_set_custom_header(marie->lc->default_proxy, "Accept", "application/sdp"); + linphone_proxy_config_set_custom_header(linphone_core_get_default_proxy_config(marie->lc), "Accept", "application/sdp"); linphone_core_manager_start(marie, TRUE); - linphone_proxy_config_set_custom_header(pauline->lc->default_proxy, "Accept", "application/sdp, text/plain, application/vnd.gsma.rcs-ft-http+xml"); + linphone_proxy_config_set_custom_header(linphone_core_get_default_proxy_config(pauline->lc), "Accept", "application/sdp, text/plain, application/vnd.gsma.rcs-ft-http+xml"); linphone_core_manager_start(pauline, TRUE); reset_counters(&marie->stat); @@ -1368,7 +1367,7 @@ void test_removing_old_tport(void) { marie2 = ms_new0(LinphoneCoreManager, 1); linphone_core_manager_init(marie2, "marie_rc", NULL); - sal_set_uuid(marie2->lc->sal, linphone_config_get_string(linphone_core_get_config(marie1->lc),"misc", "uuid", "0")); + sal_set_uuid(linphone_core_get_sal(marie2->lc), linphone_config_get_string(linphone_core_get_config(marie1->lc),"misc", "uuid", "0")); linphone_core_manager_start(marie2, TRUE); lcs=bctbx_list_append(lcs, marie2->lc); linphone_core_refresh_registers(marie2->lc); diff --git a/tester/liblinphone_tester.c b/tester/liblinphone_tester.c index 178a8347a..67c17d71f 100644 --- a/tester/liblinphone_tester.c +++ b/tester/liblinphone_tester.c @@ -18,7 +18,6 @@ #include "linphone/core.h" -#include "private.h" #include "liblinphone_tester.h" #if __clang__ || ((__GNUC__ == 4 && __GNUC_MINOR__ >= 6) || __GNUC__ > 4) diff --git a/tester/liblinphone_tester.h b/tester/liblinphone_tester.h index 8de7b8b61..de8174668 100644 --- a/tester/liblinphone_tester.h +++ b/tester/liblinphone_tester.h @@ -25,6 +25,7 @@ #include #include "linphone/core.h" #include +#include "tester_utils.h" #ifdef HAVE_CONFIG_H #include "config.h" #endif diff --git a/tester/log_collection_tester.c b/tester/log_collection_tester.c index f4f59c82f..15c9f6256 100644 --- a/tester/log_collection_tester.c +++ b/tester/log_collection_tester.c @@ -21,7 +21,6 @@ #endif #include #include "linphone/core.h" -#include "private.h" #include "liblinphone_tester.h" #ifdef HAVE_ZLIB diff --git a/tester/message_tester.c b/tester/message_tester.c index 3b661a342..1e93ca046 100644 --- a/tester/message_tester.c +++ b/tester/message_tester.c @@ -19,10 +19,11 @@ #include "linphone/core.h" -#include "private.h" #include "liblinphone_tester.h" #include "lime.h" #include "bctoolbox/crypto.h" +#include +#include #ifdef SQLITE_STORAGE_ENABLED #include @@ -237,7 +238,7 @@ LinphoneChatMessage* create_message_from_sintel_trailer(LinphoneChatRoom *chat_r fseek(file_to_send, 0, SEEK_SET); content = linphone_core_create_content(linphone_chat_room_get_core(chat_room)); - belle_sip_object_set_name(&content->base, "sintel trailer content"); + belle_sip_object_set_name(BELLE_SIP_OBJECT(content), "sintel trailer content"); linphone_content_set_type(content,"video"); linphone_content_set_subtype(content,"mkv"); linphone_content_set_size(content,file_size); /*total size to be transfered*/ @@ -263,7 +264,7 @@ LinphoneChatMessage* create_file_transfer_message_from_sintel_trailer(LinphoneCh char *send_filepath = bc_tester_res("sounds/sintel_trailer_opus_h264.mkv"); content = linphone_core_create_content(linphone_chat_room_get_core(chat_room)); - belle_sip_object_set_name(&content->base, "sintel trailer content"); + belle_sip_object_set_name(BELLE_SIP_OBJECT(content), "sintel trailer content"); linphone_content_set_type(content,"video"); linphone_content_set_subtype(content,"mkv"); linphone_content_set_name(content,"sintel_trailer_opus_h264.mkv"); @@ -312,7 +313,7 @@ static void text_message(void) { static void text_message_within_call_dialog(void) { LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc"); LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_tcp_rc"); - lp_config_set_int(pauline->lc->config,"sip","chat_use_call_dialogs",1); + lp_config_set_int(linphone_core_get_config(pauline->lc),"sip","chat_use_call_dialogs",1); BC_ASSERT_TRUE(call(marie,pauline)); linphone_chat_room_send_message(linphone_core_get_chat_room(pauline->lc, marie->identity),"Bla bla bla bla"); @@ -408,7 +409,7 @@ static void text_message_with_send_error(void) { LinphoneChatMessageCbs *cbs = linphone_chat_message_get_callbacks(msg); /*simulate a network error*/ - sal_set_send_error(marie->lc->sal, -1); + sal_set_send_error(linphone_core_get_sal(marie->lc), -1); linphone_chat_message_cbs_set_msg_state_changed(cbs,liblinphone_tester_chat_message_msg_state_changed); linphone_chat_room_send_chat_message(chat_room,msg); @@ -423,7 +424,7 @@ static void text_message_with_send_error(void) { /* 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"); - sal_set_send_error(marie->lc->sal, 0); + sal_set_send_error(linphone_core_get_sal(marie->lc), 0); /*give a chance to register again to allow linphone_core_manager_destroy to properly unregister*/ linphone_core_refresh_registers(marie->lc); @@ -503,14 +504,14 @@ void transfer_message_base2(LinphoneCoreManager* marie, LinphoneCoreManager* pau BC_ASSERT_EQUAL((int)linphone_chat_message_get_state(sent_msg), (int)LinphoneChatMessageStateInProgress, int, "%d"); bctbx_list_free_with_data(history, (bctbx_list_free_func)linphone_chat_message_unref); } - sal_set_send_error(pauline->lc->sal, -1); + sal_set_send_error(linphone_core_get_sal(pauline->lc), -1); BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneMessageNotDelivered,1)); BC_ASSERT_EQUAL(pauline->stat.number_of_LinphoneMessageNotDelivered,1, int, "%d"); BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneFileTransferDownloadSuccessful,0, int, "%d"); - sal_set_send_error(pauline->lc->sal, 0); + sal_set_send_error(linphone_core_get_sal(pauline->lc), 0); linphone_core_refresh_registers(pauline->lc); /*to make sure registration is back in registered and so it can be later unregistered*/ BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneRegistrationOk,pauline->stat.number_of_LinphoneRegistrationOk+1)); @@ -550,9 +551,9 @@ void transfer_message_base2(LinphoneCoreManager* marie, LinphoneCoreManager* pau /* wait for file to be 50% downloaded */ BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.progress_of_LinphoneFileTransfer, 50)); /* and simulate network error */ - belle_http_provider_set_recv_error(marie->lc->http_provider, -1); + belle_http_provider_set_recv_error(linphone_core_get_http_provider(marie->lc), -1); BC_ASSERT_TRUE(wait_for_until(marie->lc, pauline->lc, &marie->stat.number_of_LinphoneMessageNotDelivered,1, 10000)); - belle_http_provider_set_recv_error(marie->lc->http_provider, 0); + belle_http_provider_set_recv_error(linphone_core_get_http_provider(marie->lc), 0); } else { /* wait for a long time in case the DNS SRV resolution takes times - it should be immediate though */ if (BC_ASSERT_TRUE(wait_for_until(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneFileTransferDownloadSuccessful,1,55000))) { @@ -892,8 +893,8 @@ static int enable_lime_for_message_test(LinphoneCoreManager *marie, LinphoneCore linphone_core_enable_lime(pauline->lc, LinphoneLimeMandatory); /* make sure to not trigger the cache migration function */ - lp_config_set_int(marie->lc->config, "sip", "zrtp_cache_migration_done", TRUE); - lp_config_set_int(pauline->lc->config, "sip", "zrtp_cache_migration_done", TRUE); + lp_config_set_int(linphone_core_get_config(marie->lc), "sip", "zrtp_cache_migration_done", TRUE); + lp_config_set_int(linphone_core_get_config(pauline->lc), "sip", "zrtp_cache_migration_done", TRUE); /* create temporary cache files: setting the database_path will create and initialise the files */ tmp = bc_tester_file("tmpZIDCacheMarie.sqlite"); @@ -1157,8 +1158,8 @@ static void _im_error_delivery_notification(bool_t online) { BC_ASSERT_PTR_NOT_NULL(linphone_core_get_chat_room(marie->lc, pauline->identity)); /* Temporary disabling receiver cache and enable all IM notifications */ - zrtp_cache_db_holder = marie->lc->zrtp_cache_db; - marie->lc->zrtp_cache_db = NULL; + zrtp_cache_db_holder = linphone_core_get_zrtp_cache_db(marie->lc); + linphone_core_set_zrtp_cache_db(marie->lc, NULL); linphone_im_notif_policy_enable_all(linphone_core_get_im_notif_policy(marie->lc)); linphone_im_notif_policy_enable_all(linphone_core_get_im_notif_policy(pauline->lc)); @@ -1179,7 +1180,7 @@ static void _im_error_delivery_notification(bool_t online) { BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &pauline->stat.number_of_LinphoneMessageNotDelivered, 1)); /* Restore the ZID cache of the receiver and resend the chat message */ - marie->lc->zrtp_cache_db = zrtp_cache_db_holder; + linphone_core_set_zrtp_cache_db(marie->lc, zrtp_cache_db_holder); linphone_chat_message_ref(msg); linphone_chat_message_resend(msg); BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &marie->stat.number_of_LinphoneMessageReceived, 2)); /* Check the new message is now received */ @@ -1249,8 +1250,8 @@ static void lime_text_message_to_non_lime(bool_t sender_policy_mandatory, bool_t /* enable lime for both parts */ if (enable_lime_for_message_test(marie, pauline) < 0) goto end; /* but then disable marie */ - sqlite3_close(marie->lc->zrtp_cache_db); - marie->lc->zrtp_cache_db = NULL; + sqlite3_close(linphone_core_get_zrtp_cache_db(marie->lc)); + linphone_core_set_zrtp_cache_db(marie->lc, NULL); } chat_room = linphone_core_get_chat_room(pauline->lc, marie->identity); @@ -1479,7 +1480,7 @@ static void lime_cache_migration(void) { linphone_core_enable_lime(marie->lc, LinphoneLimeMandatory); /* make sure to trigger the cache migration function */ - lp_config_set_int(marie->lc->config, "sip", "zrtp_cache_migration_done", FALSE); + lp_config_set_int(linphone_core_get_config(marie->lc), "sip", "zrtp_cache_migration_done", FALSE); /* set the cache path, it will trigger the migration function */ linphone_core_set_zrtp_secrets_file(marie->lc, xmlCache_filepath); @@ -1490,7 +1491,7 @@ static void lime_cache_migration(void) { linphone_address_unref(new_identity); bctbx_str_to_uint8(associatedKey.peerZID, (const uint8_t *)"0987654321fedcba5a5a5a5a", (uint16_t)strlen("0987654321fedcba5a5a5a5a")); /* 0987654321fedcba5a5a5a5a is the only one with pvs=1*/ - BC_ASSERT_FALSE(lime_getCachedRcvKeyByZid(marie->lc->zrtp_cache_db, &associatedKey, selfURI, "sip:bob@sip.linphone.org")); + BC_ASSERT_FALSE(lime_getCachedRcvKeyByZid(linphone_core_get_zrtp_cache_db(marie->lc), &associatedKey, selfURI, "sip:bob@sip.linphone.org")); ms_free(selfURI); /* perform checks on the new cache, simple check is ok as deeper ones are performed in the bzrtp migration tester */ /* TODO */ @@ -1588,14 +1589,14 @@ static void database_migration(void) { // the messages.db has 10000 dummy messages with the very first DB scheme. // This will test the migration procedure linphone_core_set_chat_database_path(marie->lc, tmp_db); - BC_ASSERT_PTR_NOT_NULL(marie->lc->db); - if (!marie->lc->db) goto end; + BC_ASSERT_PTR_NOT_NULL(linphone_core_get_sqlite_database(marie->lc)); + if (!linphone_core_get_sqlite_database(marie->lc)) goto end; chatrooms = linphone_core_get_chat_rooms(marie->lc); BC_ASSERT(bctbx_list_size(chatrooms) > 0); // check that all messages have been migrated to the UTC time storage - BC_ASSERT(sqlite3_exec(marie->lc->db, "SELECT COUNT(*) FROM history WHERE time != '-1';", check_no_strange_time, NULL, NULL) == SQLITE_OK); + BC_ASSERT(sqlite3_exec(linphone_core_get_sqlite_database(marie->lc), "SELECT COUNT(*) FROM history WHERE time != '-1';", check_no_strange_time, NULL, NULL) == SQLITE_OK); // check that the read messages (field read=1) has been migrated to the LinphoneChatMessageStateDisplayed state cr = linphone_core_get_chat_room_from_uri(marie->lc, "sip:Marielle@sip.linphone.org"); @@ -1618,8 +1619,8 @@ static void history_range(void){ BC_ASSERT_EQUAL(message_tester_copy_file(src_db, tmp_db), 0, int, "%d"); linphone_core_set_chat_database_path(marie->lc, tmp_db); - BC_ASSERT_PTR_NOT_NULL(marie->lc->db); - if (!marie->lc->db) goto end; + BC_ASSERT_PTR_NOT_NULL(linphone_core_get_sqlite_database(marie->lc)); + if (!linphone_core_get_sqlite_database(marie->lc)) goto end; chatroom = linphone_core_get_chat_room(marie->lc, jehan_addr); BC_ASSERT_PTR_NOT_NULL(chatroom); @@ -1663,8 +1664,8 @@ static void history_count(void) { BC_ASSERT_EQUAL(message_tester_copy_file(src_db, tmp_db), 0, int, "%d"); linphone_core_set_chat_database_path(marie->lc, tmp_db); - BC_ASSERT_PTR_NOT_NULL(marie->lc->db); - if (!marie->lc->db) goto end; + BC_ASSERT_PTR_NOT_NULL(linphone_core_get_sqlite_database(marie->lc)); + if (!linphone_core_get_sqlite_database(marie->lc)) goto end; chatroom = linphone_core_get_chat_room(marie->lc, jehan_addr); BC_ASSERT_PTR_NOT_NULL(chatroom); @@ -1846,19 +1847,19 @@ static void real_time_text(bool_t audio_stream_enabled, bool_t srtp_enabled, boo linphone_core_set_chat_database_path(marie->lc, marie_db); linphone_core_set_chat_database_path(pauline->lc, pauline_db); #ifdef SQLITE_STORAGE_ENABLED - BC_ASSERT_PTR_NOT_NULL(marie->lc->db); - BC_ASSERT_PTR_NOT_NULL(pauline->lc->db); + BC_ASSERT_PTR_NOT_NULL(linphone_core_get_sqlite_database(marie->lc)); + BC_ASSERT_PTR_NOT_NULL(linphone_core_get_sqlite_database(pauline->lc)); #endif if (do_not_store_rtt_messages_in_sql_storage) { - lp_config_set_int(marie->lc->config, "misc", "store_rtt_messages", 0); - lp_config_set_int(pauline->lc->config, "misc", "store_rtt_messages", 0); + lp_config_set_int(linphone_core_get_config(marie->lc), "misc", "store_rtt_messages", 0); + lp_config_set_int(linphone_core_get_config(pauline->lc), "misc", "store_rtt_messages", 0); } } if (mess_with_marie_payload_number) { - bctbx_list_t *elem; - for (elem = marie->lc->codecs_conf.text_codecs; elem != NULL; elem = elem->next) { + const bctbx_list_t *elem; + for (elem = linphone_core_get_text_codecs(marie->lc); elem != NULL; elem = elem->next) { PayloadType *pt = (PayloadType*)elem->data; if (strcasecmp(pt->mime_type, payload_type_t140.mime_type) == 0) { payload_type_set_number(pt, 99); @@ -1866,8 +1867,8 @@ static void real_time_text(bool_t audio_stream_enabled, bool_t srtp_enabled, boo } } } else if (mess_with_pauline_payload_number) { - bctbx_list_t *elem; - for (elem = pauline->lc->codecs_conf.text_codecs; elem != NULL; elem = elem->next) { + const bctbx_list_t *elem; + for (elem = linphone_core_get_text_codecs(pauline->lc); elem != NULL; elem = elem->next) { PayloadType *pt = (PayloadType*)elem->data; if (strcasecmp(pt->mime_type, payload_type_t140.mime_type) == 0) { payload_type_set_number(pt, 99); diff --git a/tester/offeranswer_tester.c b/tester/offeranswer_tester.c index fb043f576..4d1c9f720 100644 --- a/tester/offeranswer_tester.c +++ b/tester/offeranswer_tester.c @@ -20,7 +20,6 @@ #include #include "linphone/core.h" #include "linphone/lpconfig.h" -#include "private.h" #include "liblinphone_tester.h" static int get_codec_position(const MSList *l, const char *mime_type, int rate){ diff --git a/tester/presence_server_tester.c b/tester/presence_server_tester.c index 4e8753a55..7e8cac7f6 100644 --- a/tester/presence_server_tester.c +++ b/tester/presence_server_tester.c @@ -18,8 +18,8 @@ #include "linphone/core.h" -#include "private.h" #include "liblinphone_tester.h" +#include "linphone/core_utils.h" static void enable_publish(LinphoneCoreManager *mgr, bool_t enable) { LinphoneProxyConfig *cfg = linphone_core_get_default_proxy_config(mgr->lc); @@ -37,9 +37,9 @@ const char * get_identity(LinphoneCoreManager *mgr) { static void enable_deflate_content_encoding(LinphoneCoreManager *mgr, bool_t enable) { LinphoneCore *lc = mgr->lc; if (enable == TRUE) - lp_config_set_string(lc->config, "sip", "handle_content_encoding", "deflate"); + lp_config_set_string(linphone_core_get_config(lc), "sip", "handle_content_encoding", "deflate"); else - lp_config_set_string(lc->config, "sip", "handle_content_encoding", "none"); + lp_config_set_string(linphone_core_get_config(lc), "sip", "handle_content_encoding", "none"); } static void simple(void) { @@ -54,7 +54,7 @@ static void simple(void) { _linphone_core_add_callbacks(pauline->lc, callbacks, TRUE); linphone_core_cbs_unref(callbacks); - lp_config_set_int(marie->lc->config, "sip", "subscribe_expires", 40); + lp_config_set_int(linphone_core_get_config(marie->lc), "sip", "subscribe_expires", 40); linphone_core_set_user_agent(pauline->lc, "full-presence-support-bypass", NULL); linphone_core_set_user_agent(marie->lc, "full-presence-support-bypass", NULL); enable_publish(pauline, TRUE); @@ -153,7 +153,7 @@ static void subscriber_no_longer_reachable(void){ lcs = bctbx_list_append(lcs, marie->lc); lcs = bctbx_list_append(lcs, pauline1->lc); - lp_config_set_int(marie->lc->config, "sip", "subscribe_expires", 80); + lp_config_set_int(linphone_core_get_config(marie->lc), "sip", "subscribe_expires", 80); linphone_core_set_user_agent(marie->lc, "full-presence-support-bypass", NULL); linphone_core_set_user_agent(pauline1->lc, "full-presence-support-bypass", NULL); @@ -425,16 +425,16 @@ static void test_presence_list_base(bool_t enable_compression) { wait_for_list(lcs, &laure->stat.number_of_NotifyPresenceReceived, 2, 4000); BC_ASSERT_EQUAL(laure->stat.number_of_NotifyPresenceReceived, 2, int, "%d"); - BC_ASSERT_EQUAL(linphone_core_get_default_friend_list(laure->lc)->expected_notification_version, 1, int, "%d"); + BC_ASSERT_EQUAL(linphone_friend_list_get_expected_notification_version(linphone_core_get_default_friend_list(laure->lc)), 1, int, "%d"); lf = linphone_friend_list_find_friend_by_uri(linphone_core_get_default_friend_list(laure->lc), marie_identity); BC_ASSERT_EQUAL(linphone_friend_get_status(lf), LinphoneStatusBusy, int, "%d"); - if (!BC_ASSERT_TRUE(lf->presence_received)) goto end; + if (!BC_ASSERT_TRUE(linphone_friend_is_presence_received(lf))) goto end; lf = linphone_friend_list_find_friend_by_uri(linphone_core_get_default_friend_list(laure->lc), pauline_identity); BC_ASSERT_EQUAL(linphone_friend_get_status(lf), LinphoneStatusVacation, int, "%d"); - if (!BC_ASSERT_TRUE(lf->presence_received)) goto end; + if (!BC_ASSERT_TRUE(linphone_friend_is_presence_received(lf))) goto end; lf = linphone_friend_list_find_friend_by_uri(linphone_core_get_default_friend_list(laure->lc), "sip:michelle@sip.inexistentdomain.com"); BC_ASSERT_EQUAL(linphone_friend_get_status(lf), LinphoneStatusOffline, int, "%d"); - BC_ASSERT_FALSE(lf->presence_received); + BC_ASSERT_FALSE(linphone_friend_is_presence_received(lf)); lfl = linphone_core_create_friend_list(marie->lc); linphone_friend_list_set_rls_uri(lfl, rls_uri); @@ -448,10 +448,10 @@ static void test_presence_list_base(bool_t enable_compression) { wait_for_list(lcs, &marie->stat.number_of_NotifyPresenceReceived, 1, 4000); BC_ASSERT_EQUAL(marie->stat.number_of_NotifyPresenceReceived, 1, int, "%d"); - BC_ASSERT_EQUAL(linphone_core_get_default_friend_list(marie->lc)->expected_notification_version, 1, int, "%d"); + BC_ASSERT_EQUAL(linphone_friend_list_get_expected_notification_version(linphone_core_get_default_friend_list(marie->lc)), 1, int, "%d"); lf = linphone_friend_list_find_friend_by_uri(linphone_core_get_default_friend_list(marie->lc), laure_identity); BC_ASSERT_EQUAL(linphone_friend_get_status(lf), LinphoneStatusOnline, int, "%d"); - if (!BC_ASSERT_TRUE(lf->presence_received)) goto end; + if (!BC_ASSERT_TRUE(linphone_friend_is_presence_received(lf))) goto end; lfl = linphone_core_create_friend_list(pauline->lc); linphone_friend_list_set_rls_uri(lfl, rls_uri); @@ -465,10 +465,10 @@ static void test_presence_list_base(bool_t enable_compression) { wait_for_list(lcs, &pauline->stat.number_of_NotifyPresenceReceived, 1, 4000); BC_ASSERT_EQUAL(pauline->stat.number_of_NotifyPresenceReceived, 1, int, "%d"); - BC_ASSERT_EQUAL(linphone_core_get_default_friend_list(pauline->lc)->expected_notification_version, 1, int, "%d"); + BC_ASSERT_EQUAL(linphone_friend_list_get_expected_notification_version(linphone_core_get_default_friend_list(pauline->lc)), 1, int, "%d"); lf = linphone_friend_list_find_friend_by_uri(linphone_core_get_default_friend_list(pauline->lc), marie_identity); BC_ASSERT_EQUAL(linphone_friend_get_status(lf), LinphoneStatusBusy, int, "%d"); - if (!BC_ASSERT_TRUE(lf->presence_received)) goto end; + if (!BC_ASSERT_TRUE(linphone_friend_is_presence_received(lf))) goto end; presence = linphone_core_create_presence_model_with_activity(marie->lc, LinphonePresenceActivityOnThePhone, NULL); linphone_core_set_presence_model(marie->lc, presence); @@ -478,13 +478,13 @@ static void test_presence_list_base(bool_t enable_compression) { /* The number of PresenceReceived events can be 3 or 4 here. TODO: ideally it should always be 3. */ BC_ASSERT_GREATER(laure->stat.number_of_NotifyPresenceReceived, 3, int, "%d"); BC_ASSERT_LOWER(laure->stat.number_of_NotifyPresenceReceived, 4, int, "%d"); - BC_ASSERT_EQUAL(linphone_core_get_default_friend_list(laure->lc)->expected_notification_version, 2, int, "%d"); + BC_ASSERT_EQUAL(linphone_friend_list_get_expected_notification_version(linphone_core_get_default_friend_list(laure->lc)), 2, int, "%d"); lf = linphone_friend_list_find_friend_by_uri(linphone_core_get_default_friend_list(laure->lc), marie_identity); BC_ASSERT_EQUAL(linphone_friend_get_status(lf), LinphoneStatusOnThePhone, int, "%d"); wait_for_list(lcs, &pauline->stat.number_of_NotifyPresenceReceived, 2, 4000); BC_ASSERT_EQUAL(pauline->stat.number_of_NotifyPresenceReceived, 2, int, "%d"); - BC_ASSERT_EQUAL(linphone_core_get_default_friend_list(pauline->lc)->expected_notification_version, 2, int, "%d"); + BC_ASSERT_EQUAL(linphone_friend_list_get_expected_notification_version(linphone_core_get_default_friend_list(pauline->lc)), 2, int, "%d"); lf = linphone_friend_list_find_friend_by_uri(linphone_core_get_default_friend_list(pauline->lc), marie_identity); BC_ASSERT_EQUAL(linphone_friend_get_status(lf), LinphoneStatusOnThePhone, int, "%d"); @@ -605,7 +605,7 @@ static void test_presence_list_subscription_expire_for_unknown(void) { const char *rls_uri = "sip:rls@sip.example.org"; LinphoneFriendList *lfl; LinphoneFriend *lf; - lp_config_set_int(laure->lc->config, "sip", "rls_presence_expires", 3); + lp_config_set_int(linphone_core_get_config(laure->lc), "sip", "rls_presence_expires", 3); lfl = linphone_core_create_friend_list(laure->lc); linphone_friend_list_set_rls_uri(lfl, rls_uri); @@ -636,7 +636,7 @@ static void test_presence_list_subscribe_with_error(bool_t io_error) { int dummy = 0; LinphonePresenceModel *presence; - lp_config_set_int(laure->lc->config, "sip", "rls_presence_expires", 5); + lp_config_set_int(linphone_core_get_config(laure->lc), "sip", "rls_presence_expires", 5); pauline_identity = get_identity(pauline); presence = linphone_core_create_presence_model_with_activity(pauline->lc, LinphonePresenceActivityVacation, NULL); @@ -667,28 +667,28 @@ static void test_presence_list_subscribe_with_error(bool_t io_error) { enable_publish(pauline, TRUE); BC_ASSERT_TRUE(wait_for_until(laure->lc, pauline->lc, &laure->stat.number_of_LinphonePresenceActivityVacation, 1, 6000)); BC_ASSERT_GREATER(laure->stat.number_of_NotifyPresenceReceived, 1, int, "%d"); - BC_ASSERT_GREATER(linphone_core_get_default_friend_list(laure->lc)->expected_notification_version, 1, int, "%d"); + BC_ASSERT_GREATER(linphone_friend_list_get_expected_notification_version(linphone_core_get_default_friend_list(laure->lc)), 1, int, "%d"); lf = linphone_friend_list_find_friend_by_uri(linphone_core_get_default_friend_list(laure->lc), pauline_identity); BC_ASSERT_EQUAL(linphone_friend_get_status(lf), LinphoneStatusVacation, int, "%d"); - BC_ASSERT_TRUE(lf->presence_received); + BC_ASSERT_TRUE(linphone_friend_is_presence_received(lf)); lf = linphone_friend_list_find_friend_by_uri(linphone_core_get_default_friend_list(laure->lc), "sip:michelle@sip.inexistentdomain.com"); BC_ASSERT_EQUAL(linphone_friend_get_status(lf), LinphoneStatusOffline, int, "%d"); - BC_ASSERT_FALSE(lf->presence_received); + BC_ASSERT_FALSE(linphone_friend_is_presence_received(lf)); BC_ASSERT_TRUE(wait_for_until(laure->lc, pauline->lc, &laure->stat.number_of_LinphonePresenceActivityVacation, 2, 6000)); if (io_error) { ms_message("Simulating socket error"); - sal_set_recv_error(laure->lc->sal, -1); + sal_set_recv_error(linphone_core_get_sal(laure->lc), -1); wait_for_list(lcs, &dummy, 1, 500); /* just time for socket to be closed */ } else { ms_message("Simulating in/out packets losses"); - sal_set_send_error(laure->lc->sal,1500); /*make sure no refresh is sent, trash the message without generating error*/ - sal_set_recv_error(laure->lc->sal, 1500); /*make sure server notify to close the dialog is also ignored*/ + sal_set_send_error(linphone_core_get_sal(laure->lc),1500); /*make sure no refresh is sent, trash the message without generating error*/ + sal_set_recv_error(linphone_core_get_sal(laure->lc), 1500); /*make sure server notify to close the dialog is also ignored*/ wait_for_list(lcs, &dummy, 1, 32000); /* Wait a little bit for the subscribe transaction to timeout */ } /*restart normal behavior*/ - sal_set_send_error(laure->lc->sal,0); - sal_set_recv_error(laure->lc->sal, 1); + sal_set_send_error(linphone_core_get_sal(laure->lc),0); + sal_set_recv_error(linphone_core_get_sal(laure->lc), 1); /*a new subscribe should be sent */ BC_ASSERT_TRUE(wait_for_until(laure->lc, pauline->lc, &laure->stat.number_of_LinphonePresenceActivityVacation, 3, 9000)); /* give time for subscription to recover to avoid to receive 491 Request pending*/ @@ -726,7 +726,7 @@ static void presence_list_subscribe_network_changes(void) { int dummy = 0; LinphonePresenceModel *presence; - lp_config_set_int(laure->lc->config, "sip", "rls_presence_expires", 5); + lp_config_set_int(linphone_core_get_config(laure->lc), "sip", "rls_presence_expires", 5); pauline_identity = get_identity(pauline); presence = linphone_core_create_presence_model_with_activity(pauline->lc, LinphonePresenceActivityVacation, NULL); @@ -757,13 +757,13 @@ static void presence_list_subscribe_network_changes(void) { enable_publish(pauline, TRUE); BC_ASSERT_TRUE(wait_for_until(laure->lc, pauline->lc, &laure->stat.number_of_LinphonePresenceActivityVacation, 1, 6000)); BC_ASSERT_GREATER(laure->stat.number_of_NotifyPresenceReceived, 1, int, "%d"); - BC_ASSERT_GREATER(linphone_core_get_default_friend_list(laure->lc)->expected_notification_version, 1, int, "%d"); + BC_ASSERT_GREATER(linphone_friend_list_get_expected_notification_version(linphone_core_get_default_friend_list(laure->lc)), 1, int, "%d"); lf = linphone_friend_list_find_friend_by_uri(linphone_core_get_default_friend_list(laure->lc), pauline_identity); BC_ASSERT_EQUAL(linphone_friend_get_status(lf), LinphoneStatusVacation, int, "%d"); - BC_ASSERT_TRUE(lf->presence_received); + BC_ASSERT_TRUE(linphone_friend_is_presence_received(lf)); lf = linphone_friend_list_find_friend_by_uri(linphone_core_get_default_friend_list(laure->lc), "sip:michelle@sip.inexistentdomain.com"); BC_ASSERT_EQUAL(linphone_friend_get_status(lf), LinphoneStatusOffline, int, "%d"); - BC_ASSERT_FALSE(lf->presence_received); + BC_ASSERT_FALSE(linphone_friend_is_presence_received(lf)); BC_ASSERT_TRUE(wait_for_until(laure->lc, pauline->lc, &laure->stat.number_of_LinphonePresenceActivityVacation, 2, 6000)); @@ -897,7 +897,7 @@ static void long_term_presence_list(void) { if (BC_ASSERT_PTR_NOT_NULL(presence)) { BC_ASSERT_STRING_EQUAL(linphone_presence_model_get_contact(presence), "sip:liblinphone_tester@sip.example.org"); } - BC_ASSERT_TRUE(f1->presence_received); + BC_ASSERT_TRUE(linphone_friend_is_presence_received(f1)); /*now try with nationnal version of phone numer*/ pauline_proxy_config = linphone_core_get_default_proxy_config(pauline->lc); @@ -910,7 +910,7 @@ static void long_term_presence_list(void) { f2 = linphone_friend_list_find_friend_by_uri(linphone_core_get_default_friend_list(pauline->lc), "sip:random_unknown@sip.example.org"); BC_ASSERT_EQUAL(linphone_presence_model_get_basic_status(linphone_friend_get_presence_model(f2)), LinphonePresenceBasicStatusClosed, int, "%d"); - BC_ASSERT_FALSE(f2->presence_received); + BC_ASSERT_FALSE(linphone_friend_is_presence_received(f2)); linphone_core_manager_destroy(pauline); }else ms_warning("Test skipped, no vcard support"); @@ -1144,7 +1144,7 @@ static void multiple_publish_aggregation(void) { _linphone_core_add_callbacks(pauline2->lc, callbacks, TRUE); linphone_core_cbs_unref(callbacks); - lp_config_set_int(marie->lc->config, "sip", "subscribe_expires", 40); + lp_config_set_int(linphone_core_get_config(marie->lc), "sip", "subscribe_expires", 40); linphone_core_set_user_agent(pauline->lc, "full-presence-support", NULL); linphone_core_set_user_agent(pauline2->lc, "full-presence-support", NULL); linphone_core_set_user_agent(marie->lc, "full-presence-support", NULL); @@ -1229,7 +1229,7 @@ static void extended_notify_only_both_side_subscribed(void) { _linphone_core_add_callbacks(pauline->lc, callbacks, TRUE); linphone_core_cbs_unref(callbacks); - lp_config_set_int(marie->lc->config, "sip", "subscribe_expires", 40); + lp_config_set_int(linphone_core_get_config(marie->lc), "sip", "subscribe_expires", 40); linphone_core_set_user_agent(pauline->lc, "full-presence-support", NULL); linphone_core_set_user_agent(marie->lc, "full-presence-support", NULL); enable_publish(pauline, TRUE); @@ -1303,7 +1303,7 @@ static void extended_notify_only_both_side_subscribed2(void) { _linphone_core_add_callbacks(pauline->lc, callbacks, TRUE); linphone_core_cbs_unref(callbacks); - lp_config_set_int(marie->lc->config, "sip", "subscribe_expires", 40); + lp_config_set_int(linphone_core_get_config(marie->lc), "sip", "subscribe_expires", 40); linphone_core_set_user_agent(pauline->lc, "full-presence-support", NULL); linphone_core_set_user_agent(marie->lc, "full-presence-support", NULL); enable_publish(pauline, TRUE); @@ -1380,7 +1380,7 @@ static void extended_notify_sub_unsub_sub(void) { _linphone_core_add_callbacks(pauline->lc, callbacks, TRUE); linphone_core_cbs_unref(callbacks); - lp_config_set_int(marie->lc->config, "sip", "subscribe_expires", 40); + lp_config_set_int(linphone_core_get_config(marie->lc), "sip", "subscribe_expires", 40); linphone_core_set_user_agent(pauline->lc, "full-presence-support", NULL); linphone_core_set_user_agent(marie->lc, "full-presence-support", NULL); @@ -1471,7 +1471,7 @@ static void extended_notify_sub_unsub_sub2(void) { _linphone_core_add_callbacks(pauline2->lc, callbacks, TRUE); linphone_core_cbs_unref(callbacks); - lp_config_set_int(marie->lc->config, "sip", "subscribe_expires", 40); + lp_config_set_int(linphone_core_get_config(marie->lc), "sip", "subscribe_expires", 40); linphone_core_set_user_agent(pauline->lc, "full-presence-support", NULL); linphone_core_set_user_agent(pauline2->lc, "full-presence-support", NULL); linphone_core_set_user_agent(marie->lc, "full-presence-support", NULL); diff --git a/tester/presence_tester.c b/tester/presence_tester.c index 7de76b692..176bba7d5 100644 --- a/tester/presence_tester.c +++ b/tester/presence_tester.c @@ -18,7 +18,6 @@ #include "linphone/core.h" -#include "private.h" #include "liblinphone_tester.h" static LinphoneCoreManager* presence_linphone_core_manager_new_with_rc_name(char* username, char * rc_name) { @@ -282,11 +281,11 @@ static void subscribe_failure_handle_by_app(void) { BC_ASSERT_TRUE(subscribe_to_callee_presence(marie,pauline)); wait_for(marie->lc,pauline->lc,&pauline->stat.number_of_NewSubscriptionRequest,1); /*just to wait for unsubscription even if not notified*/ - sal_set_recv_error(marie->lc->sal, 0); /*simulate an error*/ + sal_set_recv_error(linphone_core_get_sal(marie->lc), 0); /*simulate an error*/ BC_ASSERT_TRUE(wait_for(marie->lc,pauline->lc,&marie->stat.number_of_LinphoneRegistrationProgress,2)); BC_ASSERT_EQUAL(linphone_proxy_config_get_error(config),LinphoneReasonIOError, int, "%d"); - sal_set_recv_error(marie->lc->sal, 1); + sal_set_recv_error(linphone_core_get_sal(marie->lc), 1); lf = linphone_core_get_friend_by_address(marie->lc,lf_identity); ms_free(lf_identity); @@ -578,7 +577,7 @@ static void subscribe_presence_expired(void){ lcs = bctbx_list_append(lcs, marie->lc); lcs = bctbx_list_append(lcs, pauline1->lc); - lp_config_set_int(marie->lc->config, "sip", "subscribe_expires", 10); + lp_config_set_int(linphone_core_get_config(marie->lc), "sip", "subscribe_expires", 10); lf = linphone_core_create_friend(marie->lc); linphone_friend_set_address(lf, pauline1->identity); @@ -592,13 +591,13 @@ static void subscribe_presence_expired(void){ lf = linphone_core_find_friend(pauline1->lc, marie->identity); BC_ASSERT_PTR_NOT_NULL(lf); if (lf) { - BC_ASSERT_PTR_NOT_NULL(lf->insubs); + BC_ASSERT_PTR_NOT_NULL(linphone_friend_get_insubs(lf)); /*marie comes offline suddenly*/ linphone_core_set_network_reachable(marie->lc, FALSE); /*after a certain time, pauline shall see the incoming SUBSCRIBE expired*/ wait_for_list(lcs,NULL, 0, 11000); - BC_ASSERT_PTR_NULL(lf->insubs); + BC_ASSERT_PTR_NULL(linphone_friend_get_insubs(lf)); /*just make network reachable so that marie can unregister properly*/ linphone_core_set_network_reachable(marie->lc, TRUE); diff --git a/tester/quality_reporting_tester.c b/tester/quality_reporting_tester.c index d60068418..590ab6694 100644 --- a/tester/quality_reporting_tester.c +++ b/tester/quality_reporting_tester.c @@ -18,8 +18,8 @@ #include #include "linphone/core.h" -#include "private.h" #include "liblinphone_tester.h" +#include "quality_reporting.h" /*avoid crash if x is NULL on libc versions <4.5.26 */ #define __strstr(x, y) ((x==NULL)?NULL:strstr(x,y)) @@ -81,14 +81,14 @@ char * on_report_send_verify_metrics(const reporting_content_metrics_t *metrics, void on_report_send_with_rtcp_xr_local(const LinphoneCall *call, SalStreamType stream_type, const LinphoneContent *content){ char * body = (char*)linphone_content_get_buffer(content); char * remote_metrics_start = __strstr(body, "RemoteMetrics:"); - reporting_session_report_t * report = linphone_call_get_log(call)->reporting.reports[stream_type]; + reporting_session_report_t * report = linphone_quality_reporting_get_reports(linphone_call_log_get_quality_reporting(linphone_call_get_log(call)))[stream_type]; on_report_send_mandatory(call,stream_type,content); BC_ASSERT_PTR_NOT_NULL(body=__strstr(body, "LocalMetrics:")); BC_ASSERT_TRUE(!remote_metrics_start || on_report_send_verify_metrics(&report->local_metrics,body) < remote_metrics_start); } void on_report_send_with_rtcp_xr_remote(const LinphoneCall *call, SalStreamType stream_type, const LinphoneContent *content){ char * body = (char*)linphone_content_get_buffer(content); - reporting_session_report_t * report = linphone_call_get_log(call)->reporting.reports[stream_type]; + reporting_session_report_t * report = linphone_quality_reporting_get_reports(linphone_call_log_get_quality_reporting(linphone_call_get_log(call)))[stream_type]; on_report_send_mandatory(call,stream_type,content); if (report->remote_metrics.rtcp_sr_count+report->remote_metrics.rtcp_xr_count>0){ @@ -132,6 +132,8 @@ static void quality_reporting_not_used_without_config(void) { LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_tcp_rc"); LinphoneCall* call_marie = NULL; LinphoneCall* call_pauline = NULL; + reporting_session_report_t **quality_reports = NULL; + if (create_call_for_quality_reporting_tests(marie, pauline, &call_marie, &call_pauline, NULL, NULL)) { // marie has stats collection enabled but pauline has not @@ -139,10 +141,11 @@ static void quality_reporting_not_used_without_config(void) { BC_ASSERT_FALSE(linphone_proxy_config_quality_reporting_enabled(linphone_call_get_dest_proxy(call_pauline))); // this field should be already filled - BC_ASSERT_PTR_NOT_NULL(linphone_call_get_log(call_marie)->reporting.reports[0]->info.local_addr.ip); + quality_reports = linphone_quality_reporting_get_reports(linphone_call_log_get_quality_reporting(linphone_call_get_log(call_marie))); + BC_ASSERT_PTR_NOT_NULL(quality_reports[0]->info.local_addr.ip); // but not this one since it is updated at the end of call - BC_ASSERT_PTR_NULL(linphone_call_get_log(call_marie)->reporting.reports[0]->dialog_id); + BC_ASSERT_PTR_NULL(quality_reports[0]->dialog_id); end_call(marie, pauline); } @@ -233,6 +236,7 @@ static void quality_reporting_at_call_termination(void) { LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc_rtcp_xr"); LinphoneCall* call_marie = NULL; LinphoneCall* call_pauline = NULL; + reporting_session_report_t **quality_reports = NULL; if (create_call_for_quality_reporting_tests(marie, pauline, &call_marie, &call_pauline, NULL, NULL)) { linphone_reporting_set_on_report_send(call_marie, on_report_send_with_rtcp_xr_remote); @@ -240,7 +244,8 @@ static void quality_reporting_at_call_termination(void) { linphone_core_terminate_all_calls(marie->lc); // now dialog id should be filled - BC_ASSERT_PTR_NOT_NULL(linphone_call_get_log(call_marie)->reporting.reports[0]->dialog_id); + quality_reports = linphone_quality_reporting_get_reports(linphone_call_log_get_quality_reporting(linphone_call_get_log(call_marie))); + BC_ASSERT_PTR_NOT_NULL(quality_reports[0]->dialog_id); BC_ASSERT_TRUE(wait_for_until(marie->lc,pauline->lc,&marie->stat.number_of_LinphoneCallReleased,1, 10000)); BC_ASSERT_TRUE(wait_for_until(pauline->lc,NULL,&pauline->stat.number_of_LinphoneCallReleased,1, 10000)); diff --git a/tester/register_tester.c b/tester/register_tester.c index aa9b1f52e..e3b750480 100644 --- a/tester/register_tester.c +++ b/tester/register_tester.c @@ -18,7 +18,6 @@ #include "linphone/core.h" -#include "private.h" #include "liblinphone_tester.h" @@ -145,7 +144,7 @@ static void register_with_refresh_base_2(LinphoneCore* lc register_with_refresh_base_3(lc, refresh, domain, route, late_auth_info, transport,LinphoneRegistrationOk ); } static void register_with_refresh_base(LinphoneCore* lc, bool_t refresh,const char* domain,const char* route) { - LinphoneTransports *transport = linphone_transports_new(); + LinphoneTransports *transport = linphone_factory_create_transports(linphone_factory_get()); linphone_transports_set_udp_port(transport, 5070); linphone_transports_set_tcp_port(transport, 5070); linphone_transports_set_tls_port(transport, 5071); @@ -172,7 +171,7 @@ static void register_with_refresh_with_send_error(void) { linphone_auth_info_unref(info); register_with_refresh_base(lcm->lc,TRUE,auth_domain,route); /*simultate a network error*/ - sal_set_send_error(lcm->lc->sal, -1); + sal_set_send_error(linphone_core_get_sal(lcm->lc), -1); while (counters->number_of_LinphoneRegistrationProgress<2 && retry++ <200) { linphone_core_iterate(lcm->lc); ms_usleep(10000); @@ -289,7 +288,7 @@ static void simple_tcp_register_compatibility_mode(void){ LinphoneTransports *transport = NULL; sprintf(route,"sip:%s",test_route); lcm = create_lcm(); - transport = linphone_transports_new(); + transport = linphone_factory_create_transports(linphone_factory_get()); linphone_transports_set_tcp_port(transport, 5070); register_with_refresh_base_2(lcm->lc,FALSE,test_domain,route,FALSE,transport); linphone_transports_unref(transport); @@ -369,7 +368,7 @@ static void authenticated_register_with_late_credentials(void){ sprintf(route,"sip:%s",test_route); lcm = linphone_core_manager_new(NULL); - transport = linphone_transports_new(); + transport = linphone_factory_create_transports(linphone_factory_get()); linphone_transports_set_udp_port(transport, 5070); linphone_transports_set_tcp_port(transport, 5070); linphone_transports_set_dtls_port(transport, 5071); @@ -415,8 +414,8 @@ static void authenticated_register_with_provided_credentials(void){ BC_ASSERT_TRUE(wait_for(lcm->lc,lcm->lc,&counters->number_of_LinphoneRegistrationOk,1)); BC_ASSERT_EQUAL(counters->number_of_auth_info_requested,0, int, "%d"); - BC_ASSERT_PTR_NULL(lp_config_get_string(lcm->lc->config, "auth_info_0", "passwd", NULL)); - BC_ASSERT_PTR_NOT_NULL(lp_config_get_string(lcm->lc->config, "auth_info_0", "ha1", NULL)); + BC_ASSERT_PTR_NULL(lp_config_get_string(linphone_core_get_config(lcm->lc), "auth_info_0", "passwd", NULL)); + BC_ASSERT_PTR_NOT_NULL(lp_config_get_string(linphone_core_get_config(lcm->lc), "auth_info_0", "ha1", NULL)); linphone_proxy_config_destroy(cfg); linphone_core_manager_destroy(lcm); @@ -435,7 +434,7 @@ static void authenticated_register_with_wrong_late_credentials(void){ sprintf(route,"sip:%s",test_route); lcm = linphone_core_manager_new(NULL); - transport = linphone_transports_new(); + transport = linphone_factory_create_transports(linphone_factory_get()); linphone_transports_set_udp_port(transport, 5070); linphone_transports_set_tcp_port(transport, 5070); linphone_transports_set_tls_port(transport, 5071); @@ -454,7 +453,7 @@ static void authenticated_register_with_wrong_late_credentials(void){ static void authenticated_register_with_wrong_credentials_with_params_base(const char* user_agent,LinphoneCoreManager *lcm) { stats* counters; - LinphoneTransports *transport = linphone_transports_new(); + LinphoneTransports *transport = linphone_factory_create_transports(linphone_factory_get()); LinphoneAuthInfo *info=linphone_auth_info_new(test_username,NULL,"wrong passwd",NULL,auth_domain,NULL); /*create authentication structure from identity*/ char route[256]; @@ -464,7 +463,7 @@ static void authenticated_register_with_wrong_credentials_with_params_base(const linphone_transports_set_tls_port(transport, 5071); linphone_transports_set_dtls_port(transport, 0); - sal_set_refresher_retry_after(lcm->lc->sal,500); + sal_set_refresher_retry_after(linphone_core_get_sal(lcm->lc),500); if (user_agent) { linphone_core_set_user_agent(lcm->lc,user_agent,NULL); } @@ -585,7 +584,7 @@ static void transport_change(void){ lcm=configure_lcm(); if (lcm) { lc=lcm->lc; - sip_tr = linphone_transports_new(); + sip_tr = linphone_factory_create_transports(linphone_factory_get()); counters = get_stats(lc); register_ok=counters->number_of_LinphoneRegistrationOk; @@ -593,7 +592,7 @@ static void transport_change(void){ total_number_of_proxies=(int)bctbx_list_size(linphone_core_get_proxy_config_list(lc)); sip_tr_orig = linphone_core_get_transports(lc); - sip_tr->udp_port = sip_tr_orig->udp_port; + linphone_transports_set_udp_port(sip_tr, linphone_transports_get_udp_port(sip_tr_orig)); /*keep only udp*/ linphone_core_set_transports(lc, sip_tr); @@ -610,7 +609,7 @@ static void transport_change(void){ static void transport_dont_bind(void){ LinphoneCoreManager *pauline = linphone_core_manager_new("pauline_tcp_rc"); stats* counters = &pauline->stat; - LinphoneTransports *tr = linphone_transports_new(); + LinphoneTransports *tr = linphone_factory_create_transports(linphone_factory_get()); linphone_transports_set_tcp_port(tr, LC_SIP_TRANSPORT_DONTBIND); linphone_transports_set_tls_port(tr, LC_SIP_TRANSPORT_DONTBIND); @@ -618,9 +617,9 @@ static void transport_dont_bind(void){ BC_ASSERT_TRUE(wait_for_until(pauline->lc,pauline->lc,&counters->number_of_LinphoneRegistrationOk,2,15000)); linphone_transports_unref(tr); tr = linphone_core_get_transports_used(pauline->lc); - BC_ASSERT_EQUAL(tr->udp_port, 0, int, "%i"); - BC_ASSERT_EQUAL(tr->tcp_port, LC_SIP_TRANSPORT_DONTBIND, int, "%i"); - BC_ASSERT_EQUAL(tr->tls_port, LC_SIP_TRANSPORT_DONTBIND, int, "%i"); + BC_ASSERT_EQUAL(linphone_transports_get_udp_port(tr), 0, int, "%i"); + BC_ASSERT_EQUAL(linphone_transports_get_tcp_port(tr), LC_SIP_TRANSPORT_DONTBIND, int, "%i"); + BC_ASSERT_EQUAL(linphone_transports_get_tls_port(tr), LC_SIP_TRANSPORT_DONTBIND, int, "%i"); linphone_transports_unref(tr); linphone_core_manager_destroy(pauline); } @@ -696,7 +695,7 @@ static void proxy_transport_change_with_wrong_port(void) { LinphoneProxyConfig* proxy_config; LinphoneAuthInfo *info=linphone_auth_info_new(test_username,NULL,test_password,NULL,auth_domain,NULL); /*create authentication structure from identity*/ char route[256]; - LinphoneTransports *transport= linphone_transports_new(); + LinphoneTransports *transport= linphone_factory_create_transports(linphone_factory_get()); sprintf(route,"sip:%s",test_route); linphone_transports_set_udp_port(transport, LC_SIP_TRANSPORT_RANDOM); linphone_transports_set_tcp_port(transport, LC_SIP_TRANSPORT_RANDOM); @@ -732,7 +731,7 @@ static void proxy_transport_change_with_wrong_port_givin_up(void) { LinphoneProxyConfig* proxy_config; LinphoneAuthInfo *info=linphone_auth_info_new(test_username,NULL,test_password,NULL,auth_domain,NULL); /*create authentication structure from identity*/ char route[256]; - LinphoneTransports *transport = linphone_transports_new(); + LinphoneTransports *transport = linphone_factory_create_transports(linphone_factory_get()); sprintf(route,"sip:%s",test_route); linphone_transports_set_udp_port(transport, LC_SIP_TRANSPORT_RANDOM); linphone_transports_set_tcp_port(transport, LC_SIP_TRANSPORT_RANDOM); @@ -774,12 +773,12 @@ static void io_recv_error(void){ counters = get_stats(lc); register_ok=counters->number_of_LinphoneRegistrationOk; number_of_udp_proxy=get_number_of_udp_proxy(lc); - sal_set_recv_error(lc->sal, 0); + sal_set_recv_error(linphone_core_get_sal(lc), 0); BC_ASSERT_TRUE(wait_for(lc,lc,&counters->number_of_LinphoneRegistrationProgress,2*(register_ok-number_of_udp_proxy) /*because 1 udp*/)); BC_ASSERT_EQUAL(counters->number_of_LinphoneRegistrationFailed,0,int,"%d"); - sal_set_recv_error(lc->sal, 1); /*reset*/ + sal_set_recv_error(linphone_core_get_sal(lc), 1); /*reset*/ linphone_core_manager_destroy(lcm); } @@ -798,11 +797,11 @@ static void io_recv_error_retry_immediatly(void){ counters = get_stats(lc); register_ok=counters->number_of_LinphoneRegistrationOk; number_of_udp_proxy=get_number_of_udp_proxy(lc); - sal_set_recv_error(lc->sal, 0); + sal_set_recv_error(linphone_core_get_sal(lc), 0); BC_ASSERT_TRUE(wait_for(lc,NULL,&counters->number_of_LinphoneRegistrationProgress,(register_ok-number_of_udp_proxy)+register_ok /*because 1 udp*/)); BC_ASSERT_EQUAL(counters->number_of_LinphoneRegistrationFailed,0,int,"%d"); - sal_set_recv_error(lc->sal, 1); /*reset*/ + sal_set_recv_error(linphone_core_get_sal(lc), 1); /*reset*/ BC_ASSERT_TRUE(wait_for_until(lc,lc,&counters->number_of_LinphoneRegistrationOk,register_ok-number_of_udp_proxy+register_ok,30000)); @@ -820,7 +819,7 @@ static void io_recv_error_late_recovery(void){ bctbx_list_t* lcs; lcm=linphone_core_manager_new2( "multi_account_rc",FALSE); /*to make sure iterates are not call yet*/ lc=lcm->lc; - sal_set_refresher_retry_after(lc->sal,1000); + sal_set_refresher_retry_after(linphone_core_get_sal(lc),1000); counters=&lcm->stat; BC_ASSERT_TRUE(wait_for(lcm->lc,lcm->lc,&counters->number_of_LinphoneRegistrationOk,(int)bctbx_list_size(linphone_core_get_proxy_config_list(lcm->lc)))); @@ -829,18 +828,18 @@ static void io_recv_error_late_recovery(void){ register_ok=counters->number_of_LinphoneRegistrationOk; number_of_udp_proxy=get_number_of_udp_proxy(lc); /*simulate a general socket error*/ - sal_set_recv_error(lc->sal, 0); - sal_set_send_error(lc->sal, -1); + sal_set_recv_error(linphone_core_get_sal(lc), 0); + sal_set_send_error(linphone_core_get_sal(lc), -1); BC_ASSERT_TRUE(wait_for(lc,NULL,&counters->number_of_LinphoneRegistrationProgress,(register_ok-number_of_udp_proxy)+register_ok /*because 1 udp*/)); BC_ASSERT_EQUAL(counters->number_of_LinphoneRegistrationFailed,0,int,"%d"); - BC_ASSERT_TRUE(wait_for_list(lcs=bctbx_list_append(NULL,lc),&counters->number_of_LinphoneRegistrationFailed,(register_ok-number_of_udp_proxy),sal_get_refresher_retry_after(lc->sal)+3000)); + BC_ASSERT_TRUE(wait_for_list(lcs=bctbx_list_append(NULL,lc),&counters->number_of_LinphoneRegistrationFailed,(register_ok-number_of_udp_proxy),sal_get_refresher_retry_after(linphone_core_get_sal(lc))+3000)); - sal_set_recv_error(lc->sal, 1); /*reset*/ - sal_set_send_error(lc->sal, 0); + sal_set_recv_error(linphone_core_get_sal(lc), 1); /*reset*/ + sal_set_send_error(linphone_core_get_sal(lc), 0); - BC_ASSERT_TRUE(wait_for_list(lcs=bctbx_list_append(NULL,lc),&counters->number_of_LinphoneRegistrationOk,register_ok-number_of_udp_proxy +register_ok,sal_get_refresher_retry_after(lc->sal)+3000)); + BC_ASSERT_TRUE(wait_for_list(lcs=bctbx_list_append(NULL,lc),&counters->number_of_LinphoneRegistrationOk,register_ok-number_of_udp_proxy +register_ok,sal_get_refresher_retry_after(linphone_core_get_sal(lc))+3000)); linphone_core_manager_destroy(lcm); } } @@ -870,7 +869,7 @@ static void io_recv_error_without_active_register(void){ /*wait for unregistrations*/ BC_ASSERT_TRUE(wait_for(lc,lc,&counters->number_of_LinphoneRegistrationCleared,register_ok /*because 1 udp*/)); - sal_set_recv_error(lc->sal, 0); + sal_set_recv_error(linphone_core_get_sal(lc), 0); /*nothing should happen because no active registration*/ wait_for_until(lc,lc, &dummy, 1, 3000); @@ -878,7 +877,7 @@ static void io_recv_error_without_active_register(void){ BC_ASSERT_EQUAL(counters->number_of_LinphoneRegistrationFailed,0,int,"%d"); - sal_set_recv_error(lc->sal, 1); /*reset*/ + sal_set_recv_error(linphone_core_get_sal(lc), 1); /*reset*/ linphone_core_manager_destroy(lcm); } @@ -969,7 +968,7 @@ static void tls_with_non_tls_server(void){ lcm=linphone_core_manager_new2( "marie_rc", 0); lc=lcm->lc; - sal_set_transport_timeout(lc->sal,3000); + sal_set_transport_timeout(linphone_core_get_sal(lc),3000); proxy_cfg = linphone_core_get_default_proxy_config(lc); linphone_proxy_config_edit(proxy_cfg); addr=linphone_address_new(linphone_proxy_config_get_addr(proxy_cfg)); @@ -1024,7 +1023,7 @@ static void redirect(void){ sprintf(route,"sip:%s:5064",test_route); lcm = create_lcm(); if (lcm) { - transport = linphone_transports_new(); + transport = linphone_factory_create_transports(linphone_factory_get()); linphone_transports_set_udp_port(transport, -1); linphone_core_set_user_agent(lcm->lc,"redirect",NULL); register_with_refresh_base_2(lcm->lc,FALSE,test_domain,route,FALSE,transport); @@ -1040,7 +1039,7 @@ static void tls_auth_global_client_cert(void) { char *cert_path = bc_tester_res("certificates/client/cert.pem"); char *key_path = bc_tester_res("certificates/client/key.pem"); linphone_core_manager_init(manager, "pauline_tls_client_rc", NULL); - lpc = manager->lc->config; + lpc = linphone_core_get_config(manager->lc); lp_config_set_string(lpc, "sip", "client_cert_chain", cert_path); lp_config_set_string(lpc, "sip", "client_cert_key", key_path); linphone_core_manager_start(manager, TRUE); @@ -1092,7 +1091,7 @@ static void tls_auth_info_client_cert_api(void) { char *cert = read_file(cert_path); char *key = read_file(key_path); LinphoneCore *lc = pauline->lc; - LinphoneAuthInfo *authInfo = (LinphoneAuthInfo *)lc->auth_info->data; + LinphoneAuthInfo *authInfo = (LinphoneAuthInfo *)bctbx_list_get_data(linphone_core_get_auth_info_list(lc)); linphone_auth_info_set_tls_cert(authInfo, cert); linphone_auth_info_set_tls_key(authInfo, key); BC_ASSERT_TRUE(wait_for(lc, lc, &pauline->stat.number_of_LinphoneRegistrationOk, 1)); @@ -1110,7 +1109,7 @@ static void tls_auth_info_client_cert_api_path(void) { char *cert = bc_tester_res("certificates/client/cert.pem"); char *key = bc_tester_res("certificates/client/key.pem"); LinphoneCore *lc = pauline->lc; - LinphoneAuthInfo *authInfo = (LinphoneAuthInfo *)lc->auth_info->data; + LinphoneAuthInfo *authInfo = (LinphoneAuthInfo *)bctbx_list_get_data(linphone_core_get_auth_info_list(lc)); linphone_auth_info_set_tls_cert_path(authInfo, cert); linphone_auth_info_set_tls_key_path(authInfo, key); BC_ASSERT_TRUE(wait_for(lc, lc, &pauline->stat.number_of_LinphoneRegistrationOk, 1)); diff --git a/tester/remote_provisioning_tester.c b/tester/remote_provisioning_tester.c index 967533780..25fc22d17 100644 --- a/tester/remote_provisioning_tester.c +++ b/tester/remote_provisioning_tester.c @@ -18,7 +18,6 @@ #include "linphone/core.h" -#include "private.h" #include "liblinphone_tester.h" void linphone_configuration_status(LinphoneCore *lc, LinphoneConfiguringState status, const char *message) { @@ -89,11 +88,11 @@ static void remote_provisioning_default_values(void) { LinphoneCoreManager* marie = linphone_core_manager_new2("marie_remote_default_values_rc", FALSE); BC_ASSERT_TRUE(wait_for(marie->lc,NULL,&marie->stat.number_of_LinphoneConfiguringSuccessful,1)); lpc = linphone_core_create_proxy_config(marie->lc); - BC_ASSERT_TRUE(lpc->reg_sendregister); - BC_ASSERT_EQUAL(lpc->expires, 604800, int, "%d"); - BC_ASSERT_STRING_EQUAL(lpc->reg_proxy, ""); - BC_ASSERT_STRING_EQUAL(lpc->reg_route, ""); - BC_ASSERT_STRING_EQUAL(lpc->reg_identity, "sip:?@sip.linphone.org"); + BC_ASSERT_TRUE(linphone_proxy_config_register_enabled(lpc)); + BC_ASSERT_EQUAL(linphone_proxy_config_get_expires(lpc), 604800, int, "%d"); + BC_ASSERT_STRING_EQUAL(linphone_proxy_config_get_server_addr(lpc), ""); + BC_ASSERT_STRING_EQUAL(linphone_proxy_config_get_route(lpc), ""); + BC_ASSERT_STRING_EQUAL(linphone_proxy_config_get_identity(lpc), "sip:?@sip.linphone.org"); { LpConfig* lp = linphone_core_get_config(marie->lc); BC_ASSERT_STRING_EQUAL(lp_config_get_string(lp,"app","toto","empty"),"titi"); @@ -119,7 +118,7 @@ static void remote_provisioning_file(void) { { char* path = bc_tester_res("rcfiles/marie_remote_localfile2_rc"); char* abspath = ms_strdup_printf("file://%s", path); - lp_config_set_string(marie->lc->config, "misc", "config-uri", abspath); + lp_config_set_string(linphone_core_get_config(marie->lc), "misc", "config-uri", abspath); linphone_core_manager_start(marie, 1); ms_free(path); ms_free(abspath); diff --git a/tester/setup_tester.c b/tester/setup_tester.c index 5f4e24890..3e37b6965 100644 --- a/tester/setup_tester.c +++ b/tester/setup_tester.c @@ -20,7 +20,6 @@ #include "linphone/core.h" #include "liblinphone_tester.h" #include "linphone/lpconfig.h" -#include "private.h" static void linphone_version_test(void){ const char *version=linphone_core_get_version(); @@ -187,7 +186,7 @@ static void linphone_lpconfig_from_xml_zerolen_value(void){ BC_ASSERT_EQUAL(linphone_remote_provisioning_load_file(mgr->lc, xml_path), 0, int, "%d"); - conf = mgr->lc->config; + conf = linphone_core_get_config(mgr->lc); BC_ASSERT_STRING_EQUAL(lp_config_get_string(conf,"test","zero_len","LOL"),"LOL"); BC_ASSERT_STRING_EQUAL(lp_config_get_string(conf,"test","non_zero_len",""),"test"); diff --git a/tester/stun_tester.c b/tester/stun_tester.c index 6cad11fe8..3c6768c86 100644 --- a/tester/stun_tester.c +++ b/tester/stun_tester.c @@ -17,7 +17,6 @@ */ #include "linphone/core.h" -#include "private.h" #include "liblinphone_tester.h" #include "mediastreamer2/stun.h" #include "ortp/port.h" diff --git a/tester/tester.c b/tester/tester.c index 7f2d684bc..7829cb540 100644 --- a/tester/tester.c +++ b/tester/tester.c @@ -19,7 +19,6 @@ #include #include #include "linphone/core.h" -#include "private.h" #include "liblinphone_tester.h" #include @@ -164,8 +163,8 @@ LinphoneCore* configure_lc_from(LinphoneCoreVTable* v_table, const char* path, c linphone_core_enable_ipv6(lc, liblinphonetester_ipv6); linphone_core_set_sip_transport_timeout(lc, liblinphonetester_transport_timeout); - sal_enable_test_features(lc->sal,TRUE); - sal_set_dns_user_hosts_file(lc->sal, dnsuserhostspath); + sal_enable_test_features(linphone_core_get_sal(lc),TRUE); + sal_set_dns_user_hosts_file(linphone_core_get_sal(lc), dnsuserhostspath); #ifdef VIDEO_ENABLED linphone_core_set_static_picture(lc,nowebcampath); #endif @@ -343,13 +342,13 @@ void linphone_core_manager_init(LinphoneCoreManager *mgr, const char* rc_file, c { MSWebCam *cam; - cam = ms_web_cam_manager_get_cam(ms_factory_get_web_cam_manager(mgr->lc->factory), "Mire: Mire (synthetic moving picture)"); + cam = ms_web_cam_manager_get_cam(ms_factory_get_web_cam_manager(linphone_core_get_ms_factory(mgr->lc)), "Mire: Mire (synthetic moving picture)"); if (cam == NULL) { MSWebCamDesc *desc = ms_mire_webcam_desc_get(); if (desc){ cam=ms_web_cam_new(desc); - ms_web_cam_manager_add_cam(ms_factory_get_web_cam_manager(mgr->lc->factory), cam); + ms_web_cam_manager_add_cam(ms_factory_get_web_cam_manager(linphone_core_get_ms_factory(mgr->lc)), cam); } } } @@ -369,7 +368,7 @@ void linphone_core_manager_init(LinphoneCoreManager *mgr, const char* rc_file, c linphone_core_set_user_certificates_path(mgr->lc,bc_tester_get_writable_dir_prefix()); /*for now, we need the periodical updates facility to compute bandwidth measurements correctly during tests*/ - mgr->lc->send_call_stats_periodical_updates = TRUE; + linphone_core_enable_send_call_stats_periodical_updates(mgr->lc, TRUE); if (rc_path) ms_free(rc_path); } @@ -713,7 +712,7 @@ static void check_ice_from_rtp(LinphoneCall *c1, LinphoneCall *c2, LinphoneStrea const LinphoneCallParams *cp2 = linphone_call_get_current_params(c2); if (linphone_call_params_get_update_call_when_ice_completed(cp1) && linphone_call_params_get_update_call_when_ice_completed(cp2)) { memset(&remaddr, 0, remaddrlen); - result_desc = sal_call_get_final_media_description(linphone_call_get_op(c2)); + result_desc = sal_call_get_final_media_description(linphone_call_get_op_as_sal_op(c2)); expected_addr = result_desc->streams[0].rtp_addr; if (expected_addr[0] == '\0') expected_addr = result_desc->addr; astream = (AudioStream *)linphone_call_get_stream(c1, LinphoneStreamTypeAudio); diff --git a/tester/tunnel_tester.c b/tester/tunnel_tester.c index 37889b847..5e3d41e86 100644 --- a/tester/tunnel_tester.c +++ b/tester/tunnel_tester.c @@ -20,7 +20,6 @@ #include #include "linphone/core.h" #include "linphone/lpconfig.h" -#include "private.h" #include "liblinphone_tester.h" /* Retrieve the public IP from a given hostname */ diff --git a/tester/vcard_tester.c b/tester/vcard_tester.c index d4031715a..abad43f2d 100644 --- a/tester/vcard_tester.c +++ b/tester/vcard_tester.c @@ -17,13 +17,13 @@ */ #include "linphone/core.h" -#include "private.h" #ifdef VCARD_ENABLED #include "liblinphone_tester.h" #include "carddav.h" +#include #include #define CARDDAV_SERVER "http://dav.linphone.org/card.php/addressbooks/tester/default" @@ -145,7 +145,7 @@ static void linphone_vcard_update_existing_friends_test(void) { static void linphone_vcard_phone_numbers_and_sip_addresses(void) { LinphoneCoreManager* manager = linphone_core_manager_new2("empty_rc", FALSE); - LinphoneVcard *lvc = linphone_vcard_context_get_vcard_from_buffer(manager->lc->vcard_context, "BEGIN:VCARD\r\nVERSION:4.0\r\nFN:Sylvain Berfini\r\nIMPP:sip:sberfini@sip.linphone.org\r\nIMPP;TYPE=home:sip:sylvain@sip.linphone.org\r\nTEL;TYPE=work:0952636505\r\nEND:VCARD\r\n"); + LinphoneVcard *lvc = linphone_vcard_context_get_vcard_from_buffer(linphone_core_get_vcard_context(manager->lc), "BEGIN:VCARD\r\nVERSION:4.0\r\nFN:Sylvain Berfini\r\nIMPP:sip:sberfini@sip.linphone.org\r\nIMPP;TYPE=home:sip:sylvain@sip.linphone.org\r\nTEL;TYPE=work:0952636505\r\nEND:VCARD\r\n"); LinphoneFriend *lf = linphone_friend_new_from_vcard(lvc); linphone_vcard_unref(lvc); const bctbx_list_t *sip_addresses = linphone_friend_get_addresses(lf); @@ -157,10 +157,10 @@ static void linphone_vcard_phone_numbers_and_sip_addresses(void) { if (phone_numbers) bctbx_list_free(phone_numbers); linphone_friend_unref(lf); - lvc = linphone_vcard_context_get_vcard_from_buffer(manager->lc->vcard_context, "BEGIN:VCARD\r\nVERSION:4.0\r\nFN:Sylvain Berfini\r\nTEL;TYPE=work:0952636505\r\nTEL:0476010203\r\nEND:VCARD\r\n"); + lvc = linphone_vcard_context_get_vcard_from_buffer(linphone_core_get_vcard_context(manager->lc), "BEGIN:VCARD\r\nVERSION:4.0\r\nFN:Sylvain Berfini\r\nTEL;TYPE=work:0952636505\r\nTEL:0476010203\r\nEND:VCARD\r\n"); lf = linphone_friend_new_from_vcard(lvc); linphone_vcard_unref(lvc); - lf->lc = manager->lc; + linphone_friend_set_core(lf, manager->lc); sip_addresses = linphone_friend_get_addresses(lf); phone_numbers = linphone_friend_get_phone_numbers(lf); @@ -314,19 +314,19 @@ static void friends_sqlite_storage(void) { linphone_friend_list_set_display_name(lfl, "Test"); BC_ASSERT_EQUAL(linphone_friend_list_add_friend(lfl, lf), LinphoneFriendListOK, int, "%i"); linphone_friend_unref(lf); - BC_ASSERT_EQUAL(lfl->storage_id, 1, unsigned int, "%u"); - BC_ASSERT_EQUAL(lf->storage_id, 1, unsigned int, "%u"); + BC_ASSERT_EQUAL(linphone_friend_list_get_storage_id(lfl), 1, unsigned int, "%u"); + BC_ASSERT_EQUAL(linphone_friend_get_storage_id(lf), 1, unsigned int, "%u"); friends = linphone_friend_list_get_friends(linphone_core_get_default_friend_list(lc)); BC_ASSERT_EQUAL((unsigned int)bctbx_list_size(friends), 0, unsigned int, "%u"); friends_lists_from_db = linphone_core_fetch_friends_lists_from_db(lc); BC_ASSERT_EQUAL((unsigned int)bctbx_list_size(friends_lists_from_db), 1, unsigned int, "%u"); - friends_from_db = ((LinphoneFriendList *)friends_lists_from_db->data)->friends; + friends_from_db = *linphone_friend_list_get_friends_attribute((LinphoneFriendList *)bctbx_list_get_data(friends_lists_from_db)); BC_ASSERT_EQUAL((unsigned int)bctbx_list_size(friends_from_db), 1, unsigned int, "%u"); lf2 = (LinphoneFriend *)friends_from_db->data; - BC_ASSERT_PTR_NOT_NULL(lf2->lc); - BC_ASSERT_PTR_NOT_NULL(lf2->friend_list); + BC_ASSERT_PTR_NOT_NULL(linphone_friend_get_core(lf2)); + BC_ASSERT_PTR_NOT_NULL(linphone_friend_get_friend_list(lf2)); friends_lists_from_db = bctbx_list_free_with_data(friends_lists_from_db, (void (*)(void *))linphone_friend_list_unref); friends_from_db = linphone_core_fetch_friends_from_db(lc, lfl); @@ -336,7 +336,7 @@ static void friends_sqlite_storage(void) { } lf2 = (LinphoneFriend *)friends_from_db->data; BC_ASSERT_STRING_EQUAL(linphone_friend_get_name(lf2), linphone_friend_get_name(lf)); - BC_ASSERT_EQUAL(lf2->storage_id, lf->storage_id, unsigned int, "%u"); + BC_ASSERT_EQUAL(linphone_friend_get_storage_id(lf2), linphone_friend_get_storage_id(lf), unsigned int, "%u"); BC_ASSERT_STRING_EQUAL(linphone_vcard_get_etag(linphone_friend_get_vcard(lf2)), linphone_vcard_get_etag(linphone_friend_get_vcard(lf))); BC_ASSERT_STRING_EQUAL(linphone_vcard_get_url(linphone_friend_get_vcard(lf2)), linphone_vcard_get_url(linphone_friend_get_vcard(lf))); laddress = linphone_friend_get_address(lf); @@ -388,7 +388,7 @@ static void friends_sqlite_store_lot_of_friends(void) { int ret; char *buf; - ret = sqlite3_open(lc->friends_db_file, &db); + ret = sqlite3_open(linphone_core_get_friends_database_path(lc), &db); BC_ASSERT_TRUE(ret ==SQLITE_OK); ret = sqlite3_exec(db,"BEGIN",0,0,&errmsg); BC_ASSERT_TRUE(ret ==SQLITE_OK); @@ -456,7 +456,7 @@ static void friends_sqlite_find_friend_in_lot_of_friends(void) { bctoolboxTimeSpec t1; bctoolboxTimeSpec t2; - ret = sqlite3_open(lc->friends_db_file, &db); + ret = sqlite3_open(linphone_core_get_friends_database_path(lc), &db); BC_ASSERT_TRUE(ret ==SQLITE_OK); ret = sqlite3_exec(db,"BEGIN",0,0,&errmsg); BC_ASSERT_TRUE(ret ==SQLITE_OK); @@ -633,7 +633,7 @@ static void carddav_sync_2(void) { static void carddav_sync_3(void) { LinphoneCoreManager *manager = linphone_core_manager_new2("carddav_rc", FALSE); LinphoneCardDAVStats *stats = (LinphoneCardDAVStats *)ms_new0(LinphoneCardDAVStats, 1); - LinphoneVcard *lvc = linphone_vcard_context_get_vcard_from_buffer(manager->lc->vcard_context, "BEGIN:VCARD\r\nVERSION:4.0\r\nUID:1f08dd48-29ac-4097-8e48-8596d7776283\r\nFN:Sylvain Berfini\r\nIMPP;TYPE=work:sip:sylvain@sip.linphone.org\r\nEND:VCARD\r\n"); + LinphoneVcard *lvc = linphone_vcard_context_get_vcard_from_buffer(linphone_core_get_vcard_context(manager->lc), "BEGIN:VCARD\r\nVERSION:4.0\r\nUID:1f08dd48-29ac-4097-8e48-8596d7776283\r\nFN:Sylvain Berfini\r\nIMPP;TYPE=work:sip:sylvain@sip.linphone.org\r\nEND:VCARD\r\n"); LinphoneFriend *lf = linphone_friend_new_from_vcard(lvc); char *friends_db = bc_tester_file("friends.db"); LinphoneFriendList *lfl = linphone_core_create_friend_list(manager->lc); @@ -674,7 +674,7 @@ static void carddav_sync_3(void) { static void carddav_sync_4(void) { LinphoneCoreManager *manager = linphone_core_manager_new2("carddav_rc", FALSE); LinphoneCardDAVStats *stats = (LinphoneCardDAVStats *)ms_new0(LinphoneCardDAVStats, 1); - LinphoneVcard *lvc = linphone_vcard_context_get_vcard_from_buffer(manager->lc->vcard_context, "BEGIN:VCARD\r\nVERSION:4.0\r\nFN:Margaux Clerc\r\nIMPP;TYPE=work:sip:margaux@sip.linphone.org\r\nEND:VCARD\r\n"); + LinphoneVcard *lvc = linphone_vcard_context_get_vcard_from_buffer(linphone_core_get_vcard_context(manager->lc), "BEGIN:VCARD\r\nVERSION:4.0\r\nFN:Margaux Clerc\r\nIMPP;TYPE=work:sip:margaux@sip.linphone.org\r\nEND:VCARD\r\n"); LinphoneFriend *lf = linphone_friend_new_from_vcard(lvc); LinphoneFriendList *lfl = linphone_core_create_friend_list(manager->lc); LinphoneCardDavContext *c = NULL; @@ -709,23 +709,23 @@ static void carddav_sync_4(void) { } static void carddav_contact_created(LinphoneFriendList *list, LinphoneFriend *lf) { - LinphoneCardDAVStats *stats = (LinphoneCardDAVStats *)linphone_friend_list_cbs_get_user_data(list->cbs); + LinphoneCardDAVStats *stats = (LinphoneCardDAVStats *)linphone_friend_list_cbs_get_user_data(linphone_friend_list_get_callbacks(list)); stats->new_contact_count++; } static void carddav_contact_deleted(LinphoneFriendList *list, LinphoneFriend *lf) { - LinphoneCardDAVStats *stats = (LinphoneCardDAVStats *)linphone_friend_list_cbs_get_user_data(list->cbs); + LinphoneCardDAVStats *stats = (LinphoneCardDAVStats *)linphone_friend_list_cbs_get_user_data(linphone_friend_list_get_callbacks(list)); stats->removed_contact_count++; } static void carddav_contact_updated(LinphoneFriendList *list, LinphoneFriend *new_friend, LinphoneFriend *old_friend) { - LinphoneCardDAVStats *stats = (LinphoneCardDAVStats *)linphone_friend_list_cbs_get_user_data(list->cbs); + LinphoneCardDAVStats *stats = (LinphoneCardDAVStats *)linphone_friend_list_cbs_get_user_data(linphone_friend_list_get_callbacks(list)); BC_ASSERT_STRING_EQUAL(linphone_vcard_get_full_name(linphone_friend_get_vcard(new_friend)), linphone_vcard_get_full_name(linphone_friend_get_vcard(old_friend))); stats->updated_contact_count++; } static void carddav_sync_status_changed(LinphoneFriendList *list, LinphoneFriendListSyncStatus status, const char *msg) { - LinphoneCardDAVStats *stats = (LinphoneCardDAVStats *)linphone_friend_list_cbs_get_user_data(list->cbs); + LinphoneCardDAVStats *stats = (LinphoneCardDAVStats *)linphone_friend_list_cbs_get_user_data(linphone_friend_list_get_callbacks(list)); char *state = status == LinphoneFriendListSyncStarted ? "Sync started" : (status == LinphoneFriendListSyncFailure ? "Sync failure" : "Sync successful"); ms_message("[CardDAV] %s : %s", state, msg); if (status == LinphoneFriendListSyncFailure || status == LinphoneFriendListSyncSuccessful) { @@ -736,7 +736,7 @@ static void carddav_sync_status_changed(LinphoneFriendList *list, LinphoneFriend static void carddav_integration(void) { LinphoneCoreManager *manager = linphone_core_manager_new2("carddav_rc", FALSE); LinphoneFriendList *lfl = linphone_core_create_friend_list(manager->lc); - LinphoneVcard *lvc = linphone_vcard_context_get_vcard_from_buffer(manager->lc->vcard_context, "BEGIN:VCARD\r\nVERSION:4.0\r\nFN:Margaux Clerc\r\nIMPP;TYPE=work:sip:margaux@sip.linphone.org\r\nEND:VCARD\r\n"); + LinphoneVcard *lvc = linphone_vcard_context_get_vcard_from_buffer(linphone_core_get_vcard_context(manager->lc), "BEGIN:VCARD\r\nVERSION:4.0\r\nFN:Margaux Clerc\r\nIMPP;TYPE=work:sip:margaux@sip.linphone.org\r\nEND:VCARD\r\n"); LinphoneFriend *lf = linphone_friend_new_from_vcard(lvc); LinphoneVcard *lvc2 = NULL; LinphoneFriend *lf2 = NULL; @@ -757,34 +757,34 @@ static void carddav_integration(void) { linphone_core_add_friend_list(manager->lc, lfl); BC_ASSERT_PTR_NULL(linphone_vcard_get_uid(lvc)); - BC_ASSERT_EQUAL((unsigned int)bctbx_list_size(lfl->dirty_friends_to_update), 0, unsigned int, "%u"); + BC_ASSERT_EQUAL((unsigned int)bctbx_list_size(linphone_friend_list_get_dirty_friends_to_update(lfl)), 0, unsigned int, "%u"); BC_ASSERT_EQUAL(linphone_friend_list_add_friend(lfl, lf), LinphoneFriendListOK, int, "%d"); - BC_ASSERT_EQUAL((unsigned int)bctbx_list_size(lfl->dirty_friends_to_update), 1, unsigned int, "%u"); + BC_ASSERT_EQUAL((unsigned int)bctbx_list_size(linphone_friend_list_get_dirty_friends_to_update(lfl)), 1, unsigned int, "%u"); wait_for_until(manager->lc, NULL, &stats->sync_done_count, 1, CARDDAV_SYNC_TIMEOUT); BC_ASSERT_EQUAL(stats->sync_done_count, 1, int, "%i"); - BC_ASSERT_EQUAL((unsigned int)bctbx_list_size(lfl->dirty_friends_to_update), 0, unsigned int, "%u"); + BC_ASSERT_EQUAL((unsigned int)bctbx_list_size(linphone_friend_list_get_dirty_friends_to_update(lfl)), 0, unsigned int, "%u"); BC_ASSERT_PTR_NOT_NULL(linphone_vcard_get_uid(lvc)); linphone_friend_list_remove_friend(lfl, lf); - BC_ASSERT_EQUAL((unsigned int)bctbx_list_size(lfl->friends), 0, unsigned int, "%u"); + BC_ASSERT_EQUAL((unsigned int)bctbx_list_size(linphone_friend_list_get_friends(lfl)), 0, unsigned int, "%u"); wait_for_until(manager->lc, NULL, &stats->sync_done_count, 2, CARDDAV_SYNC_TIMEOUT); BC_ASSERT_EQUAL(stats->sync_done_count, 2, int, "%i"); linphone_friend_unref(lf); lf = NULL; - lvc = linphone_vcard_context_get_vcard_from_buffer(manager->lc->vcard_context, "BEGIN:VCARD\r\nVERSION:4.0\r\nFN:Ghislain Mary\r\nIMPP;TYPE=work:sip:ghislain@sip.linphone.org\r\nEND:VCARD\r\n"); + lvc = linphone_vcard_context_get_vcard_from_buffer(linphone_core_get_vcard_context(manager->lc), "BEGIN:VCARD\r\nVERSION:4.0\r\nFN:Ghislain Mary\r\nIMPP;TYPE=work:sip:ghislain@sip.linphone.org\r\nEND:VCARD\r\n"); lf = linphone_friend_new_from_vcard(lvc); linphone_vcard_unref(lvc); BC_ASSERT_EQUAL(linphone_friend_list_add_local_friend(lfl, lf), LinphoneFriendListOK, int, "%d"); linphone_friend_unref(lf); - lvc2 = linphone_vcard_context_get_vcard_from_buffer(manager->lc->vcard_context, "BEGIN:VCARD\r\nVERSION:4.0\r\nFN:Sylvain Berfini\r\nIMPP:sip:sberfini@sip.linphone.org\r\nUID:1f08dd48-29ac-4097-8e48-8596d7776283\r\nEND:VCARD\r\n"); + lvc2 = linphone_vcard_context_get_vcard_from_buffer(linphone_core_get_vcard_context(manager->lc), "BEGIN:VCARD\r\nVERSION:4.0\r\nFN:Sylvain Berfini\r\nIMPP:sip:sberfini@sip.linphone.org\r\nUID:1f08dd48-29ac-4097-8e48-8596d7776283\r\nEND:VCARD\r\n"); linphone_vcard_set_url(lvc2, "/card.php/addressbooks/tester/default/me.vcf"); lf2 = linphone_friend_new_from_vcard(lvc2); linphone_vcard_unref(lvc2); linphone_friend_set_ref_key(lf2, refkey); BC_ASSERT_EQUAL(linphone_friend_list_add_local_friend(lfl, lf2), LinphoneFriendListOK, int, "%d"); - BC_ASSERT_EQUAL(lfl->revision, 0, int, "%i"); + BC_ASSERT_EQUAL(linphone_friend_list_get_revision(lfl), 0, int, "%i"); linphone_friend_list_synchronize_friends_from_server(lfl); wait_for_until(manager->lc, NULL, &stats->new_contact_count, 0, CARDDAV_SYNC_TIMEOUT); BC_ASSERT_EQUAL(stats->new_contact_count, 0, int, "%i"); @@ -792,14 +792,14 @@ static void carddav_integration(void) { BC_ASSERT_EQUAL(stats->removed_contact_count, 1, int, "%i"); wait_for_until(manager->lc, NULL, &stats->updated_contact_count, 1, CARDDAV_SYNC_TIMEOUT); BC_ASSERT_EQUAL(stats->updated_contact_count, 1, int, "%i"); - BC_ASSERT_NOT_EQUAL(lfl->revision, 0, int, "%i"); + BC_ASSERT_NOT_EQUAL(linphone_friend_list_get_revision(lfl), 0, int, "%i"); wait_for_until(manager->lc, NULL, &stats->sync_done_count, 3, CARDDAV_SYNC_TIMEOUT); BC_ASSERT_EQUAL(stats->sync_done_count, 3, int, "%i"); - BC_ASSERT_EQUAL((unsigned int)bctbx_list_size(lfl->friends), 1, unsigned int, "%u"); - lf = (LinphoneFriend *)lfl->friends->data; - BC_ASSERT_STRING_EQUAL(lf->refkey, refkey); - BC_ASSERT_EQUAL(lf->storage_id, lf2->storage_id, unsigned int, "%u"); + BC_ASSERT_EQUAL((unsigned int)bctbx_list_size(linphone_friend_list_get_friends(lfl)), 1, unsigned int, "%u"); + lf = (LinphoneFriend *)bctbx_list_get_data((linphone_friend_list_get_friends(lfl))); + BC_ASSERT_STRING_EQUAL(linphone_friend_get_ref_key(lf), refkey); + BC_ASSERT_EQUAL(linphone_friend_get_storage_id(lf), linphone_friend_get_storage_id(lf2), unsigned int, "%u"); linphone_friend_unref(lf2); addr = linphone_friend_get_address(lf); BC_ASSERT_PTR_NOT_NULL(addr); @@ -810,13 +810,13 @@ static void carddav_integration(void) { linphone_friend_edit(lf); linphone_friend_done(lf); - BC_ASSERT_EQUAL((unsigned int)bctbx_list_size(lf->friend_list->dirty_friends_to_update), 0, unsigned int, "%u"); + BC_ASSERT_EQUAL((unsigned int)bctbx_list_size(linphone_friend_list_get_dirty_friends_to_update(linphone_friend_get_friend_list(lf))), 0, unsigned int, "%u"); linphone_core_set_network_reachable(manager->lc, FALSE); //To prevent the CardDAV update linphone_friend_edit(lf); linphone_friend_set_name(lf, "François Grisez"); linphone_friend_done(lf); - BC_ASSERT_EQUAL((unsigned int)bctbx_list_size(lf->friend_list->dirty_friends_to_update), 1, unsigned int, "%u"); + BC_ASSERT_EQUAL((unsigned int)bctbx_list_size(linphone_friend_list_get_dirty_friends_to_update(linphone_friend_get_friend_list(lf))), 1, unsigned int, "%u"); ms_free(stats); linphone_friend_list_unref(lfl); @@ -846,7 +846,7 @@ static void carddav_clean(void) { // This is to ensure the content of the test BC_ASSERT_EQUAL(stats->sync_done_count, 1, int, "%i"); stats->sync_done_count = 0; - friends = bctbx_list_copy(lfl->friends); + friends = bctbx_list_copy(linphone_friend_list_get_friends(lfl)); friends_iterator = friends; while (friends_iterator) { LinphoneFriend *lf = (LinphoneFriend *)friends_iterator->data; @@ -859,7 +859,7 @@ static void carddav_clean(void) { // This is to ensure the content of the test } bctbx_list_free(friends); - lvc = linphone_vcard_context_get_vcard_from_buffer(manager->lc->vcard_context, "BEGIN:VCARD\r\nVERSION:4.0\r\nFN:Sylvain Berfini\r\nIMPP:sip:sylvain@sip.linphone.org\r\nUID:1f08dd48-29ac-4097-8e48-8596d7776283\r\nEND:VCARD\r\n"); + lvc = linphone_vcard_context_get_vcard_from_buffer(linphone_core_get_vcard_context(manager->lc), "BEGIN:VCARD\r\nVERSION:4.0\r\nFN:Sylvain Berfini\r\nIMPP:sip:sylvain@sip.linphone.org\r\nUID:1f08dd48-29ac-4097-8e48-8596d7776283\r\nEND:VCARD\r\n"); linphone_vcard_set_url(lvc, "http://dav.linphone.org/card.php/addressbooks/tester/default/me.vcf"); lf = linphone_friend_new_from_vcard(lvc); linphone_vcard_unref(lvc); @@ -908,9 +908,9 @@ static void carddav_server_to_client_and_client_to_sever_sync(void) { LinphoneFriendList *lfl = linphone_core_create_friend_list(manager->lc); LinphoneFriendListCbs *cbs = linphone_friend_list_get_callbacks(lfl); LinphoneCardDAVStats *stats = (LinphoneCardDAVStats *)ms_new0(LinphoneCardDAVStats, 1); - LinphoneVcard *lvc1 = linphone_vcard_context_get_vcard_from_buffer(manager->lc->vcard_context, "BEGIN:VCARD\r\nVERSION:4.0\r\nFN:Margaux Clerc\r\nIMPP;TYPE=work:sip:margaux@sip.linphone.org\r\nEND:VCARD\r\n"); + LinphoneVcard *lvc1 = linphone_vcard_context_get_vcard_from_buffer(linphone_core_get_vcard_context(manager->lc), "BEGIN:VCARD\r\nVERSION:4.0\r\nFN:Margaux Clerc\r\nIMPP;TYPE=work:sip:margaux@sip.linphone.org\r\nEND:VCARD\r\n"); LinphoneFriend *lf1 = linphone_friend_new_from_vcard(lvc1); - LinphoneVcard *lvc2 = linphone_vcard_context_get_vcard_from_buffer(manager->lc->vcard_context, "BEGIN:VCARD\r\nVERSION:4.0\r\nFN:Ghislain Mary\r\nIMPP;TYPE=work:sip:ghislain@sip.linphone.org\r\nEND:VCARD\r\n"); + LinphoneVcard *lvc2 = linphone_vcard_context_get_vcard_from_buffer(linphone_core_get_vcard_context(manager->lc), "BEGIN:VCARD\r\nVERSION:4.0\r\nFN:Ghislain Mary\r\nIMPP;TYPE=work:sip:ghislain@sip.linphone.org\r\nEND:VCARD\r\n"); LinphoneFriend *lf2 = linphone_friend_new_from_vcard(lvc2); bctbx_list_t *friends = NULL, *friends_iterator = NULL; @@ -933,7 +933,7 @@ static void carddav_server_to_client_and_client_to_sever_sync(void) { BC_ASSERT_EQUAL(stats->sync_done_count, 3, int, "%i"); stats->sync_done_count = 0; - friends = bctbx_list_copy(lfl->friends); + friends = bctbx_list_copy(linphone_friend_list_get_friends(lfl)); friends_iterator = friends; while (friends_iterator) { LinphoneFriend *lf = (LinphoneFriend *)friends_iterator->data; diff --git a/tester/video_tester.c b/tester/video_tester.c index 9bd720870..95cc03ef0 100644 --- a/tester/video_tester.c +++ b/tester/video_tester.c @@ -15,7 +15,6 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -#include "private.h" #if defined(VIDEO_ENABLED)