diff --git a/CMakeLists.txt b/CMakeLists.txt index e4eba9c0c..ddf41d3ae 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,7 +21,7 @@ ############################################################################ cmake_minimum_required(VERSION 3.0) -project(linphone VERSION 3.11.1 LANGUAGES C CXX) +project(linphone VERSION 3.11.2 LANGUAGES C CXX) set(LINPHONE_MAJOR_VERSION ${PROJECT_VERSION_MAJOR}) @@ -45,8 +45,8 @@ option(ENABLE_DOC "Enable documentation generation with Doxygen." YES) option(ENABLE_JAVADOC "Add a target to generate documentation for Java API" NO) option(ENABLE_GTK_UI "Turn on or off compilation of gtk interface." YES) option(ENABLE_LDAP "Enable LDAP support." NO) -option(ENABLE_LIME "Enable Instant Messaging Encryption." YES) option(ENABLE_SQLITE_STORAGE "Turn on compilation sqlite storage, for messages, contacts, history" YES) +cmake_dependent_option(ENABLE_LIME "Enable Instant Messaging Encryption." YES "ENABLE_SQLITE_STORAGE" NO) cmake_dependent_option(ENABLE_NOTIFY "Enable libnotify support." YES "ENABLE_GTK_UI;NOT APPLE" NO) option(ENABLE_RELATIVE_PREFIX "Find resources relatively to the installation directory." NO) option(ENABLE_STRICT "Build with strict compile options." YES) @@ -172,11 +172,12 @@ if(ENABLE_NLS) find_package(Intl REQUIRED) endif() if(ENABLE_LIME) - if(LINPHONE_BUILDER_GROUP_EXTERNAL_SOURCE_PATH_BUILDERS) - include("${EP_bzrtp_CONFIG_DIR}/BZRTPConfig.cmake") - else() - find_package(BZRTP) - endif() + #bzrtp is only required for LIME + if(LINPHONE_BUILDER_GROUP_EXTERNAL_SOURCE_PATH_BUILDERS) + include("${EP_bzrtp_CONFIG_DIR}/BZRTPConfig.cmake") + else() + find_package(BZRTP REQUIRED) + endif() set(HAVE_LIME 1) endif() if(ENABLE_CXX_WRAPPER) @@ -204,9 +205,11 @@ include_directories( set(LINPHONE_INCLUDE_DIRS ${BELLESIP_INCLUDE_DIRS} ${MEDIASTREAMER2_INCLUDE_DIRS} - ${BZRTP_INCLUDE_DIRS} ${BCTOOLBOX_CORE_INCLUDE_DIRS} ) +if (BZRTP_FOUND) + list(APPEND LINPHONE_INCLUDE_DIRS ${BZRTP_INCLUDE_DIRS}) +endif() if(ANDROID) include_directories(${CMAKE_CURRENT_BINARY_DIR}/java) endif() diff --git a/cmake/LinphoneConfig.cmake.in b/cmake/LinphoneConfig.cmake.in index 25ab6cc6e..264b8331a 100644 --- a/cmake/LinphoneConfig.cmake.in +++ b/cmake/LinphoneConfig.cmake.in @@ -45,11 +45,7 @@ if(@ENABLE_SHARED@) set(LINPHONE_LIBRARIES ${LINPHONE_TARGETNAME}) else() set(LINPHONE_TARGETNAME linphone-static) - get_target_property(LINPHONE_LIBRARIES ${LINPHONE_TARGETNAME} LOCATION) - get_target_property(LINPHONE_LINK_LIBRARIES ${LINPHONE_TARGETNAME} INTERFACE_LINK_LIBRARIES) - if(LINPHONE_LINK_LIBRARIES) - list(APPEND LINPHONE_LIBRARIES ${LINPHONE_LINK_LIBRARIES}) - endif() + bc_set_libraries_from_static_target(LINPHONE_LIBRARIES ${LINPHONE_TARGETNAME}) endif() get_target_property(LINPHONE_INCLUDE_DIRS ${LINPHONE_TARGETNAME} INTERFACE_INCLUDE_DIRECTORIES) if(LINPHONE_BUILDER_GROUP_EXTERNAL_SOURCE_PATH_BUILDERS) diff --git a/configure.ac b/configure.ac index 0a61de025..f1180465b 100644 --- a/configure.ac +++ b/configure.ac @@ -1,6 +1,6 @@ dnl Process this file with autoconf to produce a configure script. -AC_INIT([linphone],[3.11.1],[linphone-developers@nongnu.org]) +AC_INIT([linphone],[3.11.2],[linphone-developers@nongnu.org]) AC_CANONICAL_SYSTEM AC_CONFIG_SRCDIR([coreapi/linphonecore.c]) @@ -630,7 +630,7 @@ AC_ARG_ENABLE(alsa, [alsa=true] ) -dnl this options are just for passing to mediastreamer2 subproject + AC_ARG_ENABLE(zrtp, [AS_HELP_STRING([--enable-zrtp], [Turn on zrtp support])], [case "${enableval}" in @@ -638,9 +638,22 @@ AC_ARG_ENABLE(zrtp, no) zrtp=false ;; *) AC_MSG_ERROR(bad value ${enableval} for --enable-zrtp) ;; esac], - [zrtp=false] + [zrtp=auto] ) +if test "$zrtp" != "false" ; then + PKG_CHECK_MODULES(LIBBZRTP, libbzrtp >= 1.0.0, found_zrtp=true, found_zrtp=false) + if test "$zrtp$found_zrtp" = "truefalse" ; then + AC_MSG_ERROR("Cound not find bZRTP library.") + fi + if test "$found_zrtp" = "true" ; then + zrtp=true + AC_DEFINE(HAVE_ZRTP, 1, [Defined if bzrtp is available]) + else + zrtp=false + fi +fi + dnl this options are just for passing to mediastreamer2 subproject AC_ARG_ENABLE(dtls, [AS_HELP_STRING([--enable-dtls], [Turn on srtp-dtls support - requires polarssl > 1.4])], @@ -701,18 +714,21 @@ AC_ARG_ENABLE(lime, no) lime=false ;; *) AC_MSG_ERROR(bad value ${enableval} for --enable-lime) ;; esac], - [lime=false] + [lime=auto] ) +if test "$lime" = "true" ; then + if test "$zrtp" = "false" ; then + AC_MSG_ERROR([LIME requires zrtp]) + fi +fi + if test "$lime" != "false" ; then - if test "x$found_polarssl" != "xyes" ; then - if test "$lime" = "true" ; then - AC_MSG_ERROR("LIME requires POLARSSL in version >= 1.3") - fi - lime=false - else + if test "$found_zrtp" = "true" ; then AC_DEFINE(HAVE_LIME, 1, [Defined when LIME support is compiled]) lime=true + else + lime = false fi fi @@ -1091,6 +1107,7 @@ printf "* %-30s %s\n" "Console interface" $console_ui printf "* %-30s %s\n" "Tools" $build_tools printf "* %-30s %s\n" "Sqlite storage" $enable_sqlite_storage printf "* %-30s %s\n" "VCard support" $enable_vcard +printf "* %-30s %s\n" "ZRTP" $zrtp printf "* %-30s %s\n" "IM encryption" $lime printf "* %-30s %s\n" "uPnP support" $build_upnp printf "* %-30s %s\n" "LDAP support" $enable_ldap diff --git a/coreapi/CMakeLists.txt b/coreapi/CMakeLists.txt index 1514fa93a..a0932c85e 100644 --- a/coreapi/CMakeLists.txt +++ b/coreapi/CMakeLists.txt @@ -113,6 +113,7 @@ set(LINPHONE_SOURCE_FILES_C siplogin.c sipsetup.c sqlite3_bctbx_vfs.c + video_definition.c xml2lpc.c xml.c xmlrpc.c diff --git a/coreapi/Makefile.am b/coreapi/Makefile.am index 023e26be0..58cfab40e 100644 --- a/coreapi/Makefile.am +++ b/coreapi/Makefile.am @@ -34,6 +34,7 @@ liblinphone_la_SOURCES=\ carddav.h \ call_log.c \ call_params.c \ + carddav.c \ chat.c \ chat_file_transfer.c \ conference.cc conference_private.h \ @@ -46,6 +47,7 @@ liblinphone_la_SOURCES=\ enum.c enum.h \ error_info.c \ event.c \ + factory.c \ friend.c \ friendlist.c \ im_notif_policy.c \ @@ -63,25 +65,24 @@ liblinphone_la_SOURCES=\ misc.c \ nat_policy.c \ offeranswer.c offeranswer.h\ + payload_type.c \ player.c \ presence.c \ private.h \ proxy.c \ quality_reporting.c quality_reporting.h\ remote_provisioning.c \ + ringtoneplayer.c \ sal.c \ siplogin.c \ sipsetup.c \ + sqlite3_bctbx_vfs.c sqlite3_bctbx_vfs.h\ vcard_private.h \ + vtables.c \ + video_definition.c \ xml2lpc.c xml2lpc.h \ xml.c \ xmlrpc.c \ - vtables.c \ - carddav.c \ - ringtoneplayer.c \ - sqlite3_bctbx_vfs.c sqlite3_bctbx_vfs.h\ - factory.c \ - payload_type.c \ $(GITVERSION_FILE) if BUILD_UPNP diff --git a/coreapi/account_creator.c b/coreapi/account_creator.c index 574baf34f..7c048b17b 100644 --- a/coreapi/account_creator.c +++ b/coreapi/account_creator.c @@ -19,6 +19,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "linphone/account_creator.h" #include "linphone/core.h" +#include "linphone/lpconfig.h" #include "private.h" #if !_WIN32 #include "regex.h" @@ -46,7 +47,7 @@ static unsigned int validate_uri(const char* username, const char* domain, const LinphoneAddress* addr; int status = 0; LinphoneProxyConfig* proxy = linphone_proxy_config_new(); - linphone_proxy_config_set_identity(proxy, "sip:userame@domain.com"); + linphone_proxy_config_set_identity(proxy, "sip:?@domain.com"); if (username) { addr = linphone_proxy_config_normalize_sip_uri(proxy, username); @@ -107,13 +108,14 @@ static bool_t is_matching_regex(const char *entry, const char* regex) { #endif } -LinphoneProxyConfig * linphone_account_creator_configure(const LinphoneAccountCreator *creator) { +LinphoneProxyConfig * linphone_account_creator_create_proxy_config(const LinphoneAccountCreator *creator) { LinphoneAuthInfo *info; - LinphoneProxyConfig *cfg = creator->proxy_cfg; + LinphoneProxyConfig *cfg = linphone_core_create_proxy_config(creator->core); char *identity_str = _get_identity(creator); LinphoneAddress *identity = linphone_address_new(identity_str); char *route = NULL; char *domain = NULL; + ms_free(identity_str); if (creator->display_name) { linphone_address_set_display_name(identity, creator->display_name); @@ -122,7 +124,7 @@ LinphoneProxyConfig * linphone_account_creator_configure(const LinphoneAccountCr route = ms_strdup_printf("%s", creator->route); } if (creator->domain) { - domain = ms_strdup_printf("%s", creator->domain); + domain = ms_strdup_printf("%s;transport=%s", creator->domain, linphone_transport_to_string(creator->transport)); } linphone_proxy_config_set_identity_address(cfg, identity); if (creator->phone_country_code) { @@ -141,24 +143,6 @@ LinphoneProxyConfig * linphone_account_creator_configure(const LinphoneAccountCr linphone_proxy_config_enable_publish(cfg, FALSE); linphone_proxy_config_enable_register(cfg, TRUE); - if (linphone_proxy_config_get_realm(cfg) != NULL - && strcmp(linphone_proxy_config_get_realm(cfg), "sip.linphone.org") == 0) { - linphone_proxy_config_enable_avpf(cfg, TRUE); - // If account created on sip.linphone.org, we configure linphone to use TLS by default - if (linphone_core_sip_transport_supported(creator->core, LinphoneTransportTls)) { - LinphoneAddress *addr = linphone_address_new(linphone_proxy_config_get_server_addr(cfg)); - char *tmp; - linphone_address_set_transport(addr, LinphoneTransportTls); - tmp = linphone_address_as_string(addr); - linphone_proxy_config_set_server_addr(cfg, tmp); - linphone_proxy_config_set_route(cfg, tmp); - ms_free(tmp); - linphone_address_unref(addr); - } - linphone_core_set_stun_server(creator->core, "stun.linphone.org"); - linphone_core_set_firewall_policy(creator->core, LinphonePolicyUseIce); - } - info = linphone_auth_info_new(linphone_address_get_username(identity), // username NULL, //user id creator->password, // passwd @@ -177,6 +161,10 @@ LinphoneProxyConfig * linphone_account_creator_configure(const LinphoneAccountCr linphone_core_remove_auth_info(creator->core, info); return NULL; } + +LinphoneProxyConfig * linphone_account_creator_configure(const LinphoneAccountCreator *creator) { + return linphone_account_creator_create_proxy_config(creator); +} /************************** End Misc **************************/ /************************** Start Account Creator Cbs **************************/ @@ -310,6 +298,7 @@ LinphoneAccountCreator * _linphone_account_creator_new(LinphoneCore *core, const creator->service = linphone_core_get_account_creator_service(core); creator->cbs = linphone_account_creator_cbs_new(); creator->core = core; + creator->transport = LinphoneTransportTcp; creator->xmlrpc_session = (xmlrpc_url) ? linphone_xml_rpc_session_new(core, xmlrpc_url) : NULL; if (domain) { linphone_account_creator_set_domain(creator, domain); @@ -518,19 +507,31 @@ const char * linphone_account_creator_get_email(const LinphoneAccountCreator *cr return creator->email; } -LinphoneAccountCreatorStatus linphone_account_creator_set_domain(LinphoneAccountCreator *creator, const char *domain) { +LinphoneAccountCreatorDomainStatus linphone_account_creator_set_domain(LinphoneAccountCreator *creator, const char *domain) { if (domain && validate_uri(NULL, domain, NULL) != 0) { - return LinphoneAccountCreatorStatusRequestFailed; + return LinphoneAccountCreatorDomainInvalid; } set_string(&creator->domain, domain, TRUE); - return LinphoneAccountCreatorStatusRequestOk; + return LinphoneAccountCreatorDomainOk; } const char * linphone_account_creator_get_domain(const LinphoneAccountCreator *creator) { return creator->domain; } +LinphoneAccountCreatorTransportStatus linphone_account_creator_set_transport(LinphoneAccountCreator *creator, LinphoneTransportType transport) { + if (!linphone_core_sip_transport_supported(creator->core, transport)) { + return LinphoneAccountCreatorTransportUnsupported; + } + creator->transport = transport; + return LinphoneAccountCreatorTransportOk; +} + +LinphoneTransportType linphone_account_creator_get_transport(const LinphoneAccountCreator *creator) { + return creator->transport; +} + LinphoneAccountCreatorStatus linphone_account_creator_set_route(LinphoneAccountCreator *creator, const char *route) { if (!route || linphone_proxy_config_set_route(creator->proxy_cfg, route) != 0) return LinphoneAccountCreatorStatusRequestFailed; @@ -799,11 +800,33 @@ LinphoneAccountCreatorStatus linphone_account_creator_activate_account_linphone( } request = linphone_xml_rpc_request_new_with_args(LinphoneXmlRpcArgString, "activate_phone_account", - LinphoneXmlRpcArgString, creator->phone_number, - LinphoneXmlRpcArgString, creator->username ? creator->username : creator->phone_number, - LinphoneXmlRpcArgString, creator->activation_code, - linphone_proxy_config_get_domain(creator->proxy_cfg), - LinphoneXmlRpcArgNone); + LinphoneXmlRpcArgString, creator->phone_number, + LinphoneXmlRpcArgString, creator->username ? creator->username : creator->phone_number, + LinphoneXmlRpcArgString, creator->activation_code, + linphone_proxy_config_get_domain(creator->proxy_cfg), + LinphoneXmlRpcArgNone); + + linphone_xml_rpc_request_set_user_data(request, creator); + linphone_xml_rpc_request_cbs_set_response(linphone_xml_rpc_request_get_callbacks(request), _activate_account_cb_custom); + linphone_xml_rpc_session_send_request(creator->xmlrpc_session, request); + linphone_xml_rpc_request_unref(request); + return LinphoneAccountCreatorStatusRequestOk; +} + +LinphoneAccountCreatorStatus linphone_account_creator_activate_email_account_linphone(LinphoneAccountCreator *creator) { + LinphoneXmlRpcRequest *request; + if (!creator->activation_code) { + if (creator->cbs->is_account_activated_response_cb != NULL) { + creator->cbs->is_account_activated_response_cb(creator, LinphoneAccountCreatorStatusMissingArguments, "Missing required parameters"); + } + return LinphoneAccountCreatorStatusMissingArguments; + } + + request = linphone_xml_rpc_request_new_with_args(LinphoneXmlRpcArgString, "activate_email_account", + LinphoneXmlRpcArgString, creator->username, + LinphoneXmlRpcArgString, creator->activation_code, + linphone_proxy_config_get_domain(creator->proxy_cfg), + LinphoneXmlRpcArgNone); linphone_xml_rpc_request_set_user_data(request, creator); linphone_xml_rpc_request_cbs_set_response(linphone_xml_rpc_request_get_callbacks(request), _activate_account_cb_custom); diff --git a/coreapi/bellesip_sal/sal_op_call.c b/coreapi/bellesip_sal/sal_op_call.c index 9676c9b73..df06c1e8e 100644 --- a/coreapi/bellesip_sal/sal_op_call.c +++ b/coreapi/bellesip_sal/sal_op_call.c @@ -510,6 +510,7 @@ static int is_media_description_acceptable(SalMediaDescription *md){ static SalReason process_sdp_for_invite(SalOp* op,belle_sip_request_t* invite) { belle_sdp_session_description_t* sdp; SalReason reason = SalReasonNone; + SalErrorInfo sei = {0}; if (extract_sdp(op,BELLE_SIP_MESSAGE(invite),&sdp,&reason)==0) { if (sdp){ @@ -525,7 +526,9 @@ static SalReason process_sdp_for_invite(SalOp* op,belle_sip_request_t* invite) { } if (reason != SalReasonNone){ - sal_call_decline(op,reason,NULL); + 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; } @@ -943,6 +946,17 @@ int sal_call_accept(SalOp*h){ 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; +} + int sal_call_decline(SalOp *op, SalReason reason, const char *redirection /*optional*/){ belle_sip_response_t* response; belle_sip_header_contact_t* contact=NULL; @@ -971,6 +985,41 @@ int sal_call_decline(SalOp *op, SalReason reason, const char *redirection /*opti 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; @@ -1040,7 +1089,17 @@ int sal_call_send_dtmf(SalOp *h, char dtmf){ return 0; } -int sal_call_terminate(SalOp *op){ + +int sal_call_terminate_with_error(SalOp *op, const SalErrorInfo *info){ + SalErrorInfo sei = { 0 }; + const SalErrorInfo *p_sei; + if (info == NULL){ + sal_error_info_set(&sei,SalReasonDeclined, "SIP", 0, NULL, NULL); + p_sei = &sei; + } else{ + p_sei = info; + + } belle_sip_dialog_state_t dialog_state=op->dialog?belle_sip_dialog_get_state(op->dialog):BELLE_SIP_DIALOG_NULL; if (op->state==SalOpStateTerminating || op->state==SalOpStateTerminated) { ms_error("Cannot terminate op [%p] in state [%s]",op,sal_op_state_to_string(op->state)); @@ -1048,13 +1107,19 @@ int sal_call_terminate(SalOp *op){ } switch(dialog_state) { case BELLE_SIP_DIALOG_CONFIRMED: { - sal_op_send_request(op,belle_sip_dialog_create_request(op->dialog,"BYE")); + 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(op, SalReasonDeclined,NULL); + 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){ @@ -1071,7 +1136,7 @@ int sal_call_terminate(SalOp *op){ } case BELLE_SIP_DIALOG_EARLY: { if (op->dir == SalOpDirIncoming) { - sal_call_decline(op, SalReasonDeclined,NULL); + sal_call_decline_with_error_info(op, p_sei,NULL); op->state=SalOpStateTerminated; } else { cancelling_invite(op); @@ -1086,6 +1151,12 @@ int sal_call_terminate(SalOp *op){ return 0; } + +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; } diff --git a/coreapi/bellesip_sal/sal_op_impl.c b/coreapi/bellesip_sal/sal_op_impl.c index d7ddaa959..2ee70a372 100644 --- a/coreapi/bellesip_sal/sal_op_impl.c +++ b/coreapi/bellesip_sal/sal_op_impl.c @@ -561,7 +561,8 @@ const SalErrorInfo *sal_error_info_none(void){ "Ok", 200, NULL, - NULL + NULL, + }; return &none; } @@ -586,12 +587,18 @@ void sal_error_info_reset(SalErrorInfo *ei){ } ei->protocol_code=0; ei->reason=SalReasonNone; + ei->sub_sei = NULL; } void sal_error_info_set(SalErrorInfo *ei, SalReason reason, const char *protocol, int code, const char *status_string, const char *warning){ sal_error_info_reset(ei); - if (reason==SalReasonUnknown && strcmp(protocol, "SIP") == 0) ei->reason=_sal_reason_from_sip_code(code); - else ei->reason=reason; + if (reason==SalReasonUnknown && strcmp(protocol, "SIP") == 0 && code != 0) ei->reason=_sal_reason_from_sip_code(code); + else{ + ei->reason=reason; + if (code == 0) { + code = sal_reason_to_sip_code(reason); + } + } ei->protocol_code=code; ei->status_string=status_string ? ms_strdup(status_string) : NULL; ei->warnings=warning ? ms_strdup(warning) : NULL; @@ -606,7 +613,7 @@ 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; + 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); @@ -623,6 +630,7 @@ void sal_op_set_error_info_from_response(SalOp *op, belle_sip_response_t *respon 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){ @@ -633,6 +641,9 @@ 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); diff --git a/coreapi/call_params.c b/coreapi/call_params.c index a4989670d..b1bbf7d20 100644 --- a/coreapi/call_params.c +++ b/coreapi/call_params.c @@ -193,6 +193,10 @@ MSVideoSize linphone_call_params_get_received_video_size(const LinphoneCallParam return cp->recv_vsize; } +const LinphoneVideoDefinition * linphone_call_params_get_received_video_definition(const LinphoneCallParams *cp) { + return cp->recv_vdef; +} + const char *linphone_call_params_get_record_file(const LinphoneCallParams *cp){ return cp->record_file; } @@ -209,6 +213,10 @@ MSVideoSize linphone_call_params_get_sent_video_size(const LinphoneCallParams *c return cp->sent_vsize; } +const LinphoneVideoDefinition * linphone_call_params_get_sent_video_definition(const LinphoneCallParams *cp) { + return cp->sent_vdef; +} + const char *linphone_call_params_get_session_name(const LinphoneCallParams *cp){ return cp->session_name; } @@ -348,6 +356,8 @@ static void _linphone_call_params_uninit(LinphoneCallParams *cp){ if (cp->custom_sdp_media_attributes[i]) sal_custom_sdp_attribute_free(cp->custom_sdp_media_attributes[i]); } if (cp->session_name) ms_free(cp->session_name); + if (cp->sent_vdef != NULL) linphone_video_definition_unref(cp->sent_vdef); + if (cp->recv_vdef != NULL) linphone_video_definition_unref(cp->recv_vdef); } static void _linphone_call_params_clone(LinphoneCallParams *dst, const LinphoneCallParams *src) { @@ -359,7 +369,9 @@ static void _linphone_call_params_clone(LinphoneCallParams *dst, const LinphoneC belle_sip_object_t tmp = dst->base; memcpy(dst, src, sizeof(LinphoneCallParams)); dst->base = tmp; - + + if (src->sent_vdef) dst->sent_vdef = linphone_video_definition_ref(src->sent_vdef); + if (src->recv_vdef) dst->recv_vdef = linphone_video_definition_ref(src->recv_vdef); if (src->record_file) dst->record_file=ms_strdup(src->record_file); if (src->session_name) dst->session_name=ms_strdup(src->session_name); /* diff --git a/coreapi/callbacks.c b/coreapi/callbacks.c index 867f493d5..ef1d4822d 100644 --- a/coreapi/callbacks.c +++ b/coreapi/callbacks.c @@ -306,12 +306,15 @@ static void call_received(SalOp *h){ case LinphonePresenceActivityPermanentAbsence: alt_contact = linphone_presence_model_get_contact(lc->presence_model); if (alt_contact != NULL) { - sal_call_decline(h,SalReasonRedirect,alt_contact); + SalErrorInfo sei = { 0 }; + sal_error_info_set(&sei,SalReasonRedirect, "SIP", 0, NULL, NULL); + sal_call_decline_with_error_info(h, &sei,alt_contact); ms_free(alt_contact); ei = linphone_error_info_new(); - linphone_error_info_set(ei, LinphoneReasonMovedPermanently, 302, "Moved permanently", NULL); + linphone_error_info_set(ei, NULL, LinphoneReasonMovedPermanently, 302, "Moved permanently", NULL); linphone_core_report_early_failed_call(lc, LinphoneCallIncoming, from_addr, to_addr, ei); sal_op_release(h); + sal_error_info_reset(&sei); return; } break; @@ -324,7 +327,7 @@ static void call_received(SalOp *h){ if (!linphone_core_can_we_add_call(lc)){/*busy*/ sal_call_decline(h,SalReasonBusy,NULL); ei = linphone_error_info_new(); - linphone_error_info_set(ei, LinphoneReasonBusy, 486, "Busy - too many calls", NULL); + linphone_error_info_set(ei, NULL, LinphoneReasonBusy, 486, "Busy - too many calls", NULL); linphone_core_report_early_failed_call(lc, LinphoneCallIncoming, from_addr, to_addr, ei); sal_op_release(h); return; @@ -344,7 +347,7 @@ static void call_received(SalOp *h){ 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,NULL); ei = linphone_error_info_new(); - linphone_error_info_set(ei, LinphoneReasonBusy, 486, "Busy - duplicated call", NULL); + linphone_error_info_set(ei, NULL, LinphoneReasonBusy, 486, "Busy - duplicated call", NULL); linphone_core_report_early_failed_call(lc, LinphoneCallIncoming, from_addr, to_addr, ei); sal_op_release(h); linphone_address_unref(from_address_to_search_if_me); @@ -362,7 +365,7 @@ static void call_received(SalOp *h){ if (md){ if (sal_media_description_empty(md) || linphone_core_incompatible_security(lc,md)){ ei = linphone_error_info_new(); - linphone_error_info_set(ei, LinphoneReasonNotAcceptable, 488, "Not acceptable here", NULL); + linphone_error_info_set(ei, NULL, LinphoneReasonNotAcceptable, 488, "Not acceptable here", NULL); linphone_core_report_early_failed_call(lc, LinphoneCallIncoming, linphone_address_ref(from_addr), linphone_address_ref(to_addr), ei); sal_call_decline(call->op,SalReasonNotAcceptable,NULL); linphone_call_unref(call); @@ -698,6 +701,7 @@ static void call_updated_by_remote(LinphoneCore *lc, LinphoneCall *call){ /* this callback is called when an incoming re-INVITE/ SIP UPDATE modifies the session*/ static void call_updated(LinphoneCore *lc, LinphoneCall *call, SalOp *op, bool_t is_update){ + SalErrorInfo sei = { 0 }; SalMediaDescription *rmd=sal_call_get_remote_media_description(op); call->defer_update = lp_config_get_int(lc->config, "sip", "defer_update_default", FALSE); @@ -735,7 +739,8 @@ static void call_updated(LinphoneCore *lc, LinphoneCall *call, SalOp *op, bool_t case LinphoneCallUpdating: case LinphoneCallPausing: case LinphoneCallResuming: - sal_call_decline(call->op,SalReasonInternalError,NULL); + sal_error_info_set(&sei,SalReasonInternalError, "SIP", 0, NULL, NULL); + sal_call_decline_with_error_info(call->op, &sei,NULL); /*no break*/ case LinphoneCallIdle: case LinphoneCallOutgoingInit: @@ -750,6 +755,7 @@ static void call_updated(LinphoneCore *lc, LinphoneCall *call, SalOp *op, bool_t ms_warning("Receiving reINVITE or UPDATE while in state [%s], should not happen.",linphone_call_state_to_string(call->state)); break; } + sal_error_info_reset(&sei); } /* this callback is called when an incoming re-INVITE/ SIP UPDATE modifies the session*/ @@ -757,7 +763,8 @@ static void call_updating(SalOp *op, bool_t is_update){ LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op)); LinphoneCall *call=(LinphoneCall*)sal_op_get_user_pointer(op); SalMediaDescription *rmd=sal_call_get_remote_media_description(op); - + SalErrorInfo sei = {0}; + if (!call) { ms_error("call_updating(): call doesn't exist anymore"); return ; @@ -768,7 +775,7 @@ static void call_updating(SalOp *op, bool_t is_update){ if (rmd == NULL && lp_config_get_int(call->core->config,"sip","sdp_200_ack_follow_video_policy",0)) { LinphoneCallParams *p=linphone_core_create_call_params(lc, NULL); ms_message("Applying default policy for offering SDP on call [%p]",call); - linphone_call_set_new_params(call, p); + _linphone_call_set_new_params(call, p); linphone_call_params_unref(p); } linphone_call_make_local_media_description(call); @@ -787,14 +794,18 @@ static void call_updating(SalOp *op, bool_t is_update){ md=sal_call_get_final_media_description(call->op); if (md && (sal_media_description_empty(md) || linphone_core_incompatible_security(lc,md))){ - sal_call_decline(call->op,SalReasonNotAcceptable,NULL); + sal_error_info_set(&sei,SalReasonNotAcceptable, "SIP", 0, NULL, NULL); + sal_call_decline_with_error_info(call->op, &sei,NULL); + sal_error_info_reset(&sei); return; } if (is_update && prev_result_desc && md){ int diff=sal_media_description_equals(prev_result_desc,md); if (diff & (SAL_MEDIA_DESCRIPTION_CRYPTO_POLICY_CHANGED|SAL_MEDIA_DESCRIPTION_STREAMS_CHANGED)){ ms_warning("Cannot accept this update, it is changing parameters that require user approval"); - sal_call_decline(call->op,SalReasonNotAcceptable,NULL); /*FIXME should send 504 Cannot change the session parameters without prompting the user"*/ + sal_error_info_set(&sei,SalReasonUnknown, "SIP", 504, "Cannot change the session parameters without prompting the user", NULL); + sal_call_decline_with_error_info(call->op, &sei,NULL); + sal_error_info_reset(&sei); return; } } @@ -838,7 +849,7 @@ static void call_terminated(SalOp *op, const char *from){ break; case LinphoneCallIncomingReceived: case LinphoneCallIncomingEarlyMedia: - linphone_error_info_set(call->ei, LinphoneReasonNotAnswered, 0, "Incoming call cancelled", NULL); + linphone_error_info_set(call->ei,NULL, LinphoneReasonNotAnswered, 0, "Incoming call cancelled", NULL); call->non_op_error = TRUE; break; default: diff --git a/coreapi/error_info.c b/coreapi/error_info.c index 4fc26252a..ffe29fed7 100644 --- a/coreapi/error_info.c +++ b/coreapi/error_info.c @@ -31,6 +31,7 @@ static void error_info_destroy(LinphoneErrorInfo *ei){ } static void error_info_clone(LinphoneErrorInfo *ei, const LinphoneErrorInfo *other){ + linphone_error_info_set_reason(ei, linphone_error_info_get_reason(other)); ei->protocol = bctbx_strdup(other->protocol); ei->phrase = bctbx_strdup(other->phrase); ei->warnings = bctbx_strdup(other->warnings); @@ -58,9 +59,6 @@ void linphone_error_info_unref ( LinphoneErrorInfo* ei ) { belle_sip_object_unref(ei); } -void linphone_error_info_set_reason ( LinphoneErrorInfo* ei, LinphoneReason reason ) { - ei->reason = reason; -} const char *linphone_reason_to_string(LinphoneReason err){ switch(err) { @@ -214,10 +212,30 @@ void linphone_error_info_from_sal_op(LinphoneErrorInfo *ei, const SalOp *op){ } } -void linphone_error_info_set(LinphoneErrorInfo *ei, LinphoneReason reason, int code, const char *status_string, const char *warning){ +void linphone_error_info_fields_to_sal(const LinphoneErrorInfo* ei, SalErrorInfo* sei){ + sei->reason = linphone_reason_to_sal(linphone_error_info_get_reason(ei)); + sei->status_string = bctbx_strdup(ei->phrase); + sei->full_string = bctbx_strdup(ei->full_string); + sei->warnings = bctbx_strdup(ei->warnings); + sei->protocol_code = ei->protocol_code; + sei->protocol = bctbx_strdup(ei->protocol); +} + +void linphone_error_info_to_sal(const LinphoneErrorInfo* ei, SalErrorInfo* sei){ + + linphone_error_info_fields_to_sal(ei, sei); + if (ei->sub_ei !=NULL) { + + linphone_error_info_to_sal(ei->sub_ei, sei->sub_sei); + } +} + + +void linphone_error_info_set(LinphoneErrorInfo *ei, const char *protocol, LinphoneReason reason, int code, const char *status_string, const char *warning){ linphone_error_info_reset(ei); ei->reason = reason; ei->protocol_code = code; + ei->protocol = bctbx_strdup(protocol ? protocol : "SIP"); ei->phrase = bctbx_strdup(status_string); ei->warnings = bctbx_strdup(warning); } @@ -248,6 +266,36 @@ int linphone_error_info_get_protocol_code(const LinphoneErrorInfo *ei) { return ei->protocol_code; } -const LinphoneErrorInfo * linphone_error_info_get_sub_error_info(const LinphoneErrorInfo *ei){ +LinphoneErrorInfo * linphone_error_info_get_sub_error_info(const LinphoneErrorInfo *ei){ return ei->sub_ei; } + +void linphone_error_info_set_reason(LinphoneErrorInfo *ei, LinphoneReason reason){ + ei->reason = reason; +} + +void linphone_error_info_set_protocol(LinphoneErrorInfo *ei, const char *proto){ + STRING_SET(ei->protocol, proto); +} + +void linphone_error_info_set_protocol_code(LinphoneErrorInfo *ei, int code){ + ei->protocol_code = code; +} + +void linphone_error_info_set_phrase(LinphoneErrorInfo *ei, const char *phrase){ + STRING_SET(ei->phrase, phrase); +} + +void linphone_error_info_set_warnings(LinphoneErrorInfo *ei, const char *warnings){ + STRING_SET(ei->warnings, warnings); +} + +void linphone_error_info_set_sub_error_info(LinphoneErrorInfo *ei, LinphoneErrorInfo *appended_ei){ + if (appended_ei != NULL){ + linphone_error_info_ref(appended_ei); + } + if (ei->sub_ei){ + linphone_error_info_unref(ei->sub_ei); + } + ei->sub_ei = appended_ei; +} diff --git a/coreapi/factory.c b/coreapi/factory.c index f5983291d..5601a620b 100644 --- a/coreapi/factory.c +++ b/coreapi/factory.c @@ -38,6 +38,9 @@ typedef belle_sip_object_t_vptr_t LinphoneFactory_vptr_t; struct _LinphoneFactory { belle_sip_object_t base; + + bctbx_list_t *supported_video_definitions; + /*these are the directories set by the application*/ char *top_resources_dir; char *data_resources_dir; @@ -52,9 +55,12 @@ struct _LinphoneFactory { char *cached_ring_resources_dir; char *cached_image_resources_dir; char *cached_msplugins_dir; + LinphoneErrorInfo* ei; }; static void linphone_factory_uninit(LinphoneFactory *obj){ + bctbx_list_free_with_data(obj->supported_video_definitions, (bctbx_list_free_func)linphone_video_definition_unref); + STRING_RESET(obj->top_resources_dir); STRING_RESET(obj->data_resources_dir); STRING_RESET(obj->sound_resources_dir); @@ -86,9 +92,41 @@ static void _linphone_factory_destroying_cb(void) { } } +#define ADD_SUPPORTED_VIDEO_DEFINITION(factory, width, height, name) \ + (factory)->supported_video_definitions = bctbx_list_append((factory)->supported_video_definitions, \ + linphone_video_definition_ref(linphone_video_definition_new(width, height, name))) + +static void initialize_supported_video_definitions(LinphoneFactory *factory) { +#if !defined(__ANDROID__) && !TARGET_OS_IPHONE + ADD_SUPPORTED_VIDEO_DEFINITION(factory, MS_VIDEO_SIZE_1080P_W, MS_VIDEO_SIZE_1080P_H, "1080p"); +#endif +#if !defined(__ANDROID__) && !TARGET_OS_MAC /*limit to most common sizes because mac video API cannot list supported resolutions*/ + ADD_SUPPORTED_VIDEO_DEFINITION(factory, MS_VIDEO_SIZE_UXGA_W, MS_VIDEO_SIZE_UXGA_H, "uxga"); + ADD_SUPPORTED_VIDEO_DEFINITION(factory, MS_VIDEO_SIZE_SXGA_MINUS_W, MS_VIDEO_SIZE_SXGA_MINUS_H, "sxga-"); +#endif + ADD_SUPPORTED_VIDEO_DEFINITION(factory, MS_VIDEO_SIZE_720P_W, MS_VIDEO_SIZE_720P_H, "720p"); +#if !defined(__ANDROID__) && !TARGET_OS_MAC + ADD_SUPPORTED_VIDEO_DEFINITION(factory, MS_VIDEO_SIZE_XGA_W, MS_VIDEO_SIZE_XGA_H, "xga"); +#endif +#if !defined(__ANDROID__) && !TARGET_OS_IPHONE + ADD_SUPPORTED_VIDEO_DEFINITION(factory, MS_VIDEO_SIZE_SVGA_W, MS_VIDEO_SIZE_SVGA_H, "svga"); + ADD_SUPPORTED_VIDEO_DEFINITION(factory, MS_VIDEO_SIZE_4CIF_W, MS_VIDEO_SIZE_4CIF_H, "4cif"); +#endif + ADD_SUPPORTED_VIDEO_DEFINITION(factory, MS_VIDEO_SIZE_VGA_W, MS_VIDEO_SIZE_VGA_H, "vga"); +#if TARGET_OS_IPHONE + ADD_SUPPORTED_VIDEO_DEFINITION(factory, MS_VIDEO_SIZE_IOS_MEDIUM_H, MS_VIDEO_SIZE_IOS_MEDIUM_W, "ios-medium"); +#endif + ADD_SUPPORTED_VIDEO_DEFINITION(factory, MS_VIDEO_SIZE_CIF_W, MS_VIDEO_SIZE_CIF_H, "cif"); +#if !TARGET_OS_MAC || TARGET_OS_IPHONE /* OS_MAC is 1 for iPhone, but we need QVGA */ + ADD_SUPPORTED_VIDEO_DEFINITION(factory, MS_VIDEO_SIZE_QVGA_W, MS_VIDEO_SIZE_QVGA_H, "qvga"); +#endif + ADD_SUPPORTED_VIDEO_DEFINITION(factory, MS_VIDEO_SIZE_QCIF_W, MS_VIDEO_SIZE_QCIF_H, "qcif"); +} + static LinphoneFactory *linphone_factory_new(void){ LinphoneFactory *factory = belle_sip_object_new(LinphoneFactory); factory->top_resources_dir = bctbx_strdup(PACKAGE_DATA_DIR); + initialize_supported_video_definitions(factory); return factory; } @@ -140,6 +178,54 @@ LinphoneVcard *linphone_factory_create_vcard(LinphoneFactory *factory) { return _linphone_vcard_new(); } +LinphoneVideoDefinition * linphone_factory_create_video_definition(const LinphoneFactory *factory, unsigned int width, unsigned int height) { + return linphone_video_definition_ref(linphone_video_definition_new(width, height, NULL)); +} + +LinphoneVideoDefinition * linphone_factory_create_video_definition_from_name(const LinphoneFactory *factory, const char *name) { + unsigned int width = 0; + unsigned int height = 0; + LinphoneVideoDefinition *vdef = linphone_factory_find_supported_video_definition_by_name(factory, name); + if (vdef != NULL) return vdef; + if (sscanf(name, "%ux%u", &width, &height) == 2) { + return linphone_video_definition_new(width, height, NULL); + } + return linphone_video_definition_new(0, 0, NULL); +} + +const bctbx_list_t * linphone_factory_get_supported_video_definitions(const LinphoneFactory *factory) { + return factory->supported_video_definitions; +} + +LinphoneVideoDefinition * linphone_factory_find_supported_video_definition(const LinphoneFactory *factory, unsigned int width, unsigned int height) { + const bctbx_list_t *item; + const bctbx_list_t *supported = linphone_factory_get_supported_video_definitions(factory); + LinphoneVideoDefinition *searched_vdef = linphone_video_definition_new(width, height, NULL); + + for (item = supported; item != NULL; item = bctbx_list_next(item)) { + LinphoneVideoDefinition *svdef = (LinphoneVideoDefinition *)bctbx_list_get_data(item); + if (linphone_video_definition_equals(svdef, searched_vdef)) { + linphone_video_definition_unref(searched_vdef); + return linphone_video_definition_clone(svdef); + } + } + + return searched_vdef; +} + +LinphoneVideoDefinition * linphone_factory_find_supported_video_definition_by_name(const LinphoneFactory *factory, const char *name) { + const bctbx_list_t *item; + const bctbx_list_t *supported = linphone_factory_get_supported_video_definitions(factory); + + for (item = supported; item != NULL; item = bctbx_list_next(item)) { + LinphoneVideoDefinition *svdef = (LinphoneVideoDefinition *)bctbx_list_get_data(item); + if (strcmp(linphone_video_definition_get_name(svdef), name) == 0) { + return linphone_video_definition_clone(svdef); + } + } + return NULL; +} + const char * linphone_factory_get_top_resources_dir(const LinphoneFactory *factory) { return factory->top_resources_dir; } @@ -209,3 +295,21 @@ const char * linphone_factory_get_msplugins_dir(LinphoneFactory *factory) { void linphone_factory_set_msplugins_dir(LinphoneFactory *factory, const char *path) { STRING_SET(factory->msplugins_dir, path); } + +LinphoneErrorInfo *linphone_factory_create_error_info(LinphoneFactory *factory){ + + return linphone_error_info_new(); + +} + +LinphoneRange *linphone_factory_create_range(LinphoneFactory *factory) { + return linphone_range_new(); +} + +LinphoneTransports *linphone_factory_create_transports(LinphoneFactory *factory) { + return linphone_transports_new(); +} + +LinphoneVideoActivationPolicy *linphone_factory_create_video_activation_policy(LinphoneFactory *factory) { + return linphone_video_activation_policy_new(); +} \ No newline at end of file diff --git a/coreapi/help/Doxyfile.in b/coreapi/help/Doxyfile.in index 169f6cf2a..40d2bf95a 100644 --- a/coreapi/help/Doxyfile.in +++ b/coreapi/help/Doxyfile.in @@ -177,7 +177,7 @@ SHORT_NAMES = NO # description.) # The default value is: NO. -JAVADOC_AUTOBRIEF = NO +JAVADOC_AUTOBRIEF = YES # If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first # line (until the first dot) of a Qt-style comment as the brief description. If diff --git a/coreapi/help/doxygen.dox b/coreapi/help/doxygen.dox index db7af3a0b..38002841c 100644 --- a/coreapi/help/doxygen.dox +++ b/coreapi/help/doxygen.dox @@ -30,11 +30,13 @@ */ /** - * @defgroup initializing Initializing liblinphone + * @defgroup initializing Initializing + * @brief Initializing liblinphone. **/ /** - * @defgroup call_control Placing and receiving calls + * @defgroup call_control Call control + * @brief Placing and receiving calls. * * The #LinphoneCall object represents an incoming or outgoing call managed by the #LinphoneCore. * Outgoing calls can be created using linphone_core_invite() or linphone_core_invite_address(), while incoming calls are notified to the application @@ -45,32 +47,40 @@ **/ /** - * @defgroup call_misc Obtaining information about a running call: sound volumes, quality indicators + * @defgroup call_misc Call misc + * @brief Obtaining information about a running call: sound volumes, quality indicators. * * When a call is running, it is possible to retrieve in real time current measured volumes and quality indicator. * **/ /** - * @defgroup media_parameters Controlling media parameters - * Multicast - *
Call using rtp multicast addresses are supported for both audio and video with some limitations. Limitations are, no stun, no ice, no encryption. - *
+ * @defgroup media_parameters Media parameters + * @brief Controlling media parameters. + * + * Multicast + * + * Call using rtp multicast addresses are supported for both audio and video with some limitations. Limitations are, no stun, no ice, no encryption. + * - Incoming call with multicast address are automatically accepted. The called party switches in a media receive only mode. + * - Outgoing call willing to send media to a multicast address can activate multicast using linphone_core_enable_video_multicast() + * or linphone_core_enable_audio_multicast(). The calling party switches in a media listen send only mode. **/ /** - * @defgroup proxies Managing proxies - *User registration is controled by #LinphoneProxyConfig settings.
Each #LinphoneProxyConfig object can be configured with registration informations - *like \link linphone_proxy_config_set_server_addr() proxy address \endlink , \link linphone_proxy_config_set_identity() user id \endlink, \link linphone_proxy_config_expires() refresh period \endlink, and so on. - *
A created proxy config using linphone_proxy_config_new(), once configured, must be added to #LinphoneCore using function linphone_core_add_proxy_config(). - *
It is recommended to set a default \link #LinphoneProxyConfig proxy config \endlink using function linphone_core_set_default_proxy(). Once done, if \link #LinphoneProxyConfig a proxy config \endlink has been configured with attribute \link linphone_proxy_config_enable_register() enable register \endlink , next call to linphone_core_iterate() triggers a SIP register. - *
Registration status is reported by LinphoneCoreRegistrationStateChangedCb. - *
- *
This pseudo code demonstrates basic registration operations: - *
\code + * @defgroup proxies Proxies + * @brief Managing proxies. + * + * User registration is controled by #LinphoneProxyConfig settings.
Each #LinphoneProxyConfig object can be configured with registration informations + * like \link linphone_proxy_config_set_server_addr() proxy address \endlink , \link linphone_proxy_config_set_identity() user id \endlink, \link linphone_proxy_config_expires() + * refresh period \endlink, and so on. + *
A created proxy config using linphone_proxy_config_new(), once configured, must be added to #LinphoneCore using function linphone_core_add_proxy_config(). + *
It is recommended to set a default \link #LinphoneProxyConfig proxy config \endlink using function linphone_core_set_default_proxy(). Once done, if \link #LinphoneProxyConfig + * a proxy config \endlink has been configured with attribute \link linphone_proxy_config_enable_register() enable register \endlink , next call to linphone_core_iterate() triggers + * a SIP register. + *
Registration status is reported by LinphoneCoreRegistrationStateChangedCb. + *
+ *
This pseudo code demonstrates basic registration operations: + *
\code * * LinphoneProxyConfig* proxy_cfg; * /*create proxy config*/ @@ -119,90 +129,102 @@ **/ /** - * @defgroup network_parameters Controlling network parameters (ports, mtu...) + * @defgroup network_parameters Network parameters + * @brief Controlling network parameters (ports, mtu...). **/ /** - * @defgroup authentication Managing authentication: userid and passwords + * @defgroup authentication Authentication + * @brief Managing authentication: userid and passwords. **/ /** -* @defgroup buddy_list Managing Buddies and buddy list and presence -Buddies and buddy list -
Each buddy is represented by a #LinphoneFriend object created by function linphone_friend_new(). -Buddy configuration parameters like \link linphone_friend_set_addr() sip uri \endlink or \link linphone_friend_set_inc_subscribe_policy() status publication \endlink policy for this \link #LinphoneFriend friend \endlink are configurable for each buddy. -
Here under a typical buddy creation: -
-\code -LinphoneFriend* my_friend=linphone_friend_new_with_addr("sip:joe@sip.linphone.org"); /*creates friend object for buddy joe*/ -linphone_friend_enable_subscribes(my_friend,TRUE); /*configure this friend to emit SUBSCRIBE message after being added to LinphoneCore*/ -linphone_friend_set_inc_subscribe_policy(my_friend,LinphoneSPAccept); /* accept Incoming subscription request for this friend*/ -\endcode -\link #LinphoneFriend friends \endlink status changes are reported by callback LinphoneCoreVTable.notify_presence_recv -\code -static void notify_presence_recv_updated (struct _LinphoneCore *lc, LinphoneFriend *friend) { - const LinphoneAddress* friend_address = linphone_friend_get_address(friend); - printf("New state state [%s] for user id [%s] \n" - ,linphone_online_status_to_string(linphone_friend_get_status(friend)) - ,linphone_address_as_string (friend_address)); -} -\endcode -
Once created a buddy can be added to the buddy list using function linphone_core_add_friend() . Added friends will be notified about \link linphone_core_set_presence_info() local status changes \endlink -
-Any subsequente modifications to #LinphoneFriend must be first started by a call to function linphone_friend_edit() and validated by function linphone_friend_done() -\code -linphone_friend_edit(my_friend); /* start editing friend */ -linphone_friend_enable_subscribes(my_friend,FALSE); /*disable subscription for this friend*/ -linphone_friend_done(my_friend); /*commit changes triggering an UNSUBSCRIBE message*/ -\endcode - - - Publishing presence status -
Local presence status can be changed using function linphone_core_set_presence_model() .New status is propagated to all friends \link linphone_core_add_friend() previously added \endlink to #LinphoneCore. - -Handling incoming subscription request -
New incoming subscription requests are process according to \link linphone_friend_set_inc_subscribe_policy() the incoming subscription policy state \endlink for subscription initiated by \link linphone_core_add_friend() members of the buddy list. \endlink -
For incoming request comming from an unknown buddy, the call back LinphoneCoreVTable.new_subscription_request is invoked. - -
A complete tutorial can be found at : \ref buddy_tutorials "Registration tutorial" - - + * @defgroup buddy_list Buddy list + * @brief Managing Buddies and buddy list and presence. + * + * Buddies and buddy list + *
Each buddy is represented by a #LinphoneFriend object created by function linphone_friend_new(). + * Buddy configuration parameters like \link linphone_friend_set_addr() sip uri \endlink or \link linphone_friend_set_inc_subscribe_policy() status publication \endlink policy for + * this * \link #LinphoneFriend friend \endlink are configurable for each buddy. + *
Here under a typical buddy creation: + *
+ * \code + * LinphoneFriend* my_friend=linphone_friend_new_with_addr("sip:joe@sip.linphone.org"); /*creates friend object for buddy joe*/ + * linphone_friend_enable_subscribes(my_friend,TRUE); /*configure this friend to emit SUBSCRIBE message after being added to LinphoneCore*/ + * linphone_friend_set_inc_subscribe_policy(my_friend,LinphoneSPAccept); /* accept Incoming subscription request for this friend*/ + * \endcode + * \link #LinphoneFriend friends \endlink status changes are reported by callback LinphoneCoreVTable.notify_presence_recv + * \code + * static void notify_presence_recv_updated (struct _LinphoneCore *lc, LinphoneFriend *friend) { + * const LinphoneAddress* friend_address = linphone_friend_get_address(friend); + * printf("New state state [%s] for user id [%s] \n" + * ,linphone_online_status_to_string(linphone_friend_get_status(friend)) + * ,linphone_address_as_string (friend_address)); + * } + * \endcode + *
Once created a buddy can be added to the buddy list using function linphone_core_add_friend() . Added friends will be notified about \link linphone_core_set_presence_info() local status changes \endlink + *
+ * Any subsequente modifications to #LinphoneFriend must be first started by a call to function linphone_friend_edit() and validated by function linphone_friend_done() + * \code + * linphone_friend_edit(my_friend); /* start editing friend */ + * linphone_friend_enable_subscribes(my_friend,FALSE); /*disable subscription for this friend*/ + * linphone_friend_done(my_friend); /*commit changes triggering an UNSUBSCRIBE message*/ + * \endcode + * + * + * Publishing presence status + *
Local presence status can be changed using function linphone_core_set_presence_model() .New status is propagated to all friends \link linphone_core_add_friend() previously added \endlink to #LinphoneCore. + * + * Handling incoming subscription request + *
New incoming subscription requests are process according to \link linphone_friend_set_inc_subscribe_policy() the incoming subscription policy state \endlink for subscription initiated by \link linphone_core_add_friend() members of the buddy list. \endlink + *
For incoming request comming from an unknown buddy, the call back LinphoneCoreVTable.new_subscription_request is invoked. + * + *
A complete tutorial can be found at : \ref buddy_tutorials "Registration tutorial" + * + * **/ /** -* @defgroup chatroom Chat room and Messaging - Exchanging text messages -
Messages are sent using #LinphoneChatRoom object. First step is to create a \link linphone_core_get_chat_room() chat room \endlink -from a peer sip uri. -\code -LinphoneChatRoom* chat_room = linphone_core_get_chat_room(lc,"sip:joe@sip.linphone.org"); -\endcode - -
Once created, messages are sent using function linphone_chat_room_send_message(). -\code -linphone_chat_room_send_message(chat_room,"Hello world"); /*sending message*/ -\endcode -
Incoming message are received from call back LinphoneCoreVTable.text_received -\code -void text_received(LinphoneCore *lc, LinphoneChatRoom *room, const LinphoneAddress *from, const char *message) { - printf(" Message [%s] received from [%s] \n",message,linphone_address_as_string (from)); -} -\endcode -
A complete tutorial can be found at : \ref chatroom_tuto "Chat room tutorial" + * @defgroup chatroom Chatroom + * @brief Chat room and Messaging. + * + * Exchanging text messages + *
Messages are sent using #LinphoneChatRoom object. First step is to create a \link linphone_core_get_chat_room() chat room \endlink + * from a peer sip uri. + * \code + * LinphoneChatRoom* chat_room = linphone_core_get_chat_room(lc,"sip:joe@sip.linphone.org"); + * \endcode + * + *
Once created, messages are sent using function linphone_chat_room_send_message(). + * \code + * linphone_chat_room_send_message(chat_room,"Hello world"); /*sending message*/ + * \endcode + *
Incoming message are received from call back LinphoneCoreVTable.text_received + * \code + * void text_received(LinphoneCore *lc, LinphoneChatRoom *room, const LinphoneAddress *from, const char *message) { + * printf(" Message [%s] received from [%s] \n",message,linphone_address_as_string (from)); + * } + * \endcode + *
A complete tutorial can be found at : \ref chatroom_tuto "Chat room tutorial" **/ /** - * @defgroup call_logs Managing call logs + * @defgroup call_logs Call logs + * @brief Managing call logs. **/ /** - * @defgroup linphone_address SIP address parser API. + * @defgroup linphone_address Linphone address + * @brief SIP address parser API. + * This api is useful for manipulating SIP addresses ('from' or 'to' headers). **/ /** - * @defgroup conferencing Making an audio conference. + * @defgroup conferencing Conferencing + * @brief Making an audio conference. + * * This API allows to create a conference entirely managed by the client. No server capabilities are required. * The way such conference is created is by doing the following:
* The application shall makes "normal" calls to several destinations (using linphone_core_invite() ), one after another. @@ -224,12 +246,15 @@ void text_received(LinphoneCore *lc, LinphoneChatRoom *room, const LinphoneAddre /** - * @defgroup event_api Managing generic subscriptions and publishes + * @defgroup event_api Event api + * @brief Managing generic subscriptions and publishes. + * * The LinphoneEvent api allows application to control subscriptions, receive notifications and make publish to peers, in a generic manner. */ /** - * @defgroup misc Miscenalleous: logs, version strings, config storage + * @defgroup misc Misc + * @brief Miscenalleous: logs, version strings, config storage. **/ /** @@ -244,6 +269,7 @@ void text_received(LinphoneCore *lc, LinphoneChatRoom *room, const LinphoneAddre /** * @defgroup IOS IOS * @ingroup port + * *
Multitasking
Liblinphone for IOS natively supports multitasking assuming application follows multitasking guides provided by Apple. First step is to declare application as multitasked. It means adding background mode for both audio and voip to Info.plist file. @@ -464,7 +490,9 @@ I/lib/Could not find decoder for SILK */ /** - * @defgroup wrapper Wrapper utilities + * @defgroup wrapper + * @brief Wrapper utilities. + * * These functions are used by automatic API wrapper generators and should not * be used by C API users. */ diff --git a/coreapi/linphone_tunnel.cc b/coreapi/linphone_tunnel.cc index 845cf9fcf..c82876105 100644 --- a/coreapi/linphone_tunnel.cc +++ b/coreapi/linphone_tunnel.cc @@ -34,7 +34,7 @@ LinphoneTunnel* linphone_core_get_tunnel(const LinphoneCore *lc){ } struct _LinphoneTunnel { - ::belle_sip_object_t *base; + ::belle_sip_object_t base; belledonnecomm::TunnelManager *manager; bctbx_list_t *config_list; }; diff --git a/coreapi/linphonecall.c b/coreapi/linphonecall.c index f48e5d94e..2d90b81e8 100644 --- a/coreapi/linphonecall.c +++ b/coreapi/linphonecall.c @@ -1106,9 +1106,9 @@ static void linphone_call_init_common(LinphoneCall *call, LinphoneAddress *from, linphone_core_get_text_port_range(call->core, &min_port, &max_port); port_config_set(call,call->main_text_stream_index,min_port,max_port); - linphone_call_init_stats(&call->stats[LINPHONE_CALL_STATS_AUDIO], LINPHONE_CALL_STATS_AUDIO); - linphone_call_init_stats(&call->stats[LINPHONE_CALL_STATS_VIDEO], LINPHONE_CALL_STATS_VIDEO); - linphone_call_init_stats(&call->stats[LINPHONE_CALL_STATS_TEXT], LINPHONE_CALL_STATS_TEXT); + linphone_call_init_stats(call->audio_stats, LINPHONE_CALL_STATS_AUDIO); + linphone_call_init_stats(call->video_stats, LINPHONE_CALL_STATS_VIDEO); + linphone_call_init_stats(call->text_stats, LINPHONE_CALL_STATS_TEXT); } void linphone_call_init_stats(LinphoneCallStats *stats, int type) { @@ -1307,6 +1307,9 @@ LinphoneCall * linphone_call_new_outgoing(struct _LinphoneCore *lc, LinphoneAddr call->dir=LinphoneCallOutgoing; call->core=lc; call->dest_proxy=cfg; + call->audio_stats = linphone_call_stats_ref(linphone_call_stats_new()); + call->video_stats = linphone_call_stats_ref(linphone_call_stats_new()); + call->text_stats = linphone_call_stats_ref(linphone_call_stats_new()); linphone_call_outgoing_select_ip_version(call,to,cfg); linphone_call_get_local_ip(call, to); call->params = linphone_call_params_copy(params); @@ -1489,6 +1492,9 @@ LinphoneCall * linphone_call_new_incoming(LinphoneCore *lc, LinphoneAddress *fro LinphoneNatPolicy *nat_policy = NULL; int i; call->dir=LinphoneCallIncoming; + call->audio_stats = linphone_call_stats_ref(linphone_call_stats_new()); + call->video_stats = linphone_call_stats_ref(linphone_call_stats_new()); + call->text_stats = linphone_call_stats_ref(linphone_call_stats_new()); sal_op_set_user_pointer(op,call); call->op=op; call->core=lc; @@ -1613,9 +1619,9 @@ static void linphone_call_free_media_resources(LinphoneCall *call){ for (i = 0; i < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; ++i){ ms_media_stream_sessions_uninit(&call->sessions[i]); } - linphone_call_stats_uninit(&call->stats[LINPHONE_CALL_STATS_AUDIO]); - linphone_call_stats_uninit(&call->stats[LINPHONE_CALL_STATS_VIDEO]); - linphone_call_stats_uninit(&call->stats[LINPHONE_CALL_STATS_TEXT]); + linphone_call_stats_uninit(call->audio_stats); + linphone_call_stats_uninit(call->video_stats); + linphone_call_stats_uninit(call->text_stats); } /* @@ -1872,6 +1878,18 @@ static void linphone_call_destroy(LinphoneCall *obj){ if (obj->audiostream || obj->videostream){ linphone_call_free_media_resources(obj); } + if (obj->audio_stats) { + linphone_call_stats_unref(obj->audio_stats); + obj->audio_stats = NULL; + } + if (obj->video_stats) { + linphone_call_stats_unref(obj->video_stats); + obj->video_stats = NULL; + } + if (obj->text_stats) { + linphone_call_stats_unref(obj->text_stats); + obj->text_stats = NULL; + } if (obj->op!=NULL) { sal_op_release(obj->op); obj->op=NULL; @@ -1967,10 +1985,18 @@ const LinphoneCallParams * linphone_call_get_current_params(LinphoneCall *call){ MS_VIDEO_SIZE_ASSIGN(call->current_params->sent_vsize, UNKNOWN); MS_VIDEO_SIZE_ASSIGN(call->current_params->recv_vsize, UNKNOWN); #ifdef VIDEO_ENABLED + if (call->current_params->sent_vdef != NULL) linphone_video_definition_unref(call->current_params->sent_vdef); + call->current_params->sent_vdef = NULL; + if (call->current_params->recv_vdef != NULL) linphone_video_definition_unref(call->current_params->recv_vdef); + call->current_params->recv_vdef = NULL; vstream = call->videostream; if (vstream != NULL) { call->current_params->sent_vsize = video_stream_get_sent_video_size(vstream); call->current_params->recv_vsize = video_stream_get_received_video_size(vstream); + call->current_params->sent_vdef = linphone_video_definition_ref(linphone_factory_find_supported_video_definition( + linphone_factory_get(), call->current_params->sent_vsize.width, call->current_params->sent_vsize.height)); + call->current_params->recv_vdef = linphone_video_definition_ref(linphone_factory_find_supported_video_definition( + linphone_factory_get(), call->current_params->recv_vsize.width, call->current_params->recv_vsize.height)); call->current_params->sent_fps = video_stream_get_sent_framerate(vstream); call->current_params->received_fps = video_stream_get_received_framerate(vstream); } @@ -3899,9 +3925,9 @@ void linphone_call_delete_ice_session(LinphoneCall *call){ if (call->audiostream != NULL) call->audiostream->ms.ice_check_list = NULL; if (call->videostream != NULL) call->videostream->ms.ice_check_list = NULL; if (call->textstream != NULL) call->textstream->ms.ice_check_list = NULL; - call->stats[LINPHONE_CALL_STATS_AUDIO].ice_state = LinphoneIceStateNotActivated; - call->stats[LINPHONE_CALL_STATS_VIDEO].ice_state = LinphoneIceStateNotActivated; - call->stats[LINPHONE_CALL_STATS_TEXT].ice_state = LinphoneIceStateNotActivated; + call->audio_stats->ice_state = LinphoneIceStateNotActivated; + call->video_stats->ice_state = LinphoneIceStateNotActivated; + call->text_stats->ice_state = LinphoneIceStateNotActivated; } } @@ -3926,7 +3952,15 @@ static void linphone_call_log_fill_stats(LinphoneCallLog *log, MediaStream *st){ static void update_rtp_stats(LinphoneCall *call, int stream_index) { if (call->sessions[stream_index].rtp_session) { const rtp_stats_t *stats = rtp_session_get_stats(call->sessions[stream_index].rtp_session); - memcpy(&call->stats[stream_index].rtp_stats, stats, sizeof(*stats)); + LinphoneCallStats *call_stats = NULL; + if (stream_index == call->main_audio_stream_index) { + call_stats = call->audio_stats; + } else if (stream_index == call->main_video_stream_index) { + call_stats = call->video_stats; + } else { + call_stats = call->text_stats; + } + if (call_stats) memcpy(&(call_stats->rtp_stats), stats, sizeof(*stats)); } } @@ -4194,26 +4228,47 @@ static MediaStream *linphone_call_get_stream(LinphoneCall *call, LinphoneStreamT return NULL; } -const LinphoneCallStats *linphone_call_get_stats(LinphoneCall *call, LinphoneStreamType type){ +static void _linphone_call_stats_clone(LinphoneCallStats *dst, const LinphoneCallStats *src) { + /* + * Save the belle_sip_object_t part, copy the entire structure and restore the belle_sip_object_t part + */ + belle_sip_object_t tmp = dst->base; + memcpy(dst, src, sizeof(LinphoneCallStats)); + dst->base = tmp; + + dst->received_rtcp = NULL; + dst->sent_rtcp = NULL; +} + +LinphoneCallStats *linphone_call_get_stats(LinphoneCall *call, LinphoneStreamType type){ if ((int)type >=0 && type<=LinphoneStreamTypeText){ - LinphoneCallStats *stats = &call->stats[type]; + LinphoneCallStats *stats = NULL; + LinphoneCallStats *stats_copy = linphone_call_stats_new(); + if (type == LinphoneStreamTypeAudio) { + stats = call->audio_stats; + } else if (type == LinphoneStreamTypeVideo) { + stats = call->video_stats; + } else if (type == LinphoneStreamTypeText) { + stats = call->text_stats; + } MediaStream *ms = linphone_call_get_stream(call, type); - if (ms) update_local_stats(stats, ms); - return stats; + if (ms && stats) update_local_stats(stats, ms); + _linphone_call_stats_clone(stats_copy, stats); + return stats_copy; } ms_error("Invalid stream type %i", (int)type); return NULL; } -const LinphoneCallStats *linphone_call_get_audio_stats(LinphoneCall *call) { +LinphoneCallStats *linphone_call_get_audio_stats(LinphoneCall *call) { return linphone_call_get_stats(call, LinphoneStreamTypeAudio); } -const LinphoneCallStats *linphone_call_get_video_stats(LinphoneCall *call) { +LinphoneCallStats *linphone_call_get_video_stats(LinphoneCall *call) { return linphone_call_get_stats(call, LinphoneStreamTypeVideo); } -const LinphoneCallStats *linphone_call_get_text_stats(LinphoneCall *call) { +LinphoneCallStats *linphone_call_get_text_stats(LinphoneCall *call) { return linphone_call_get_stats(call, LinphoneStreamTypeText); } @@ -4223,12 +4278,42 @@ static bool_t ice_in_progress(LinphoneCallStats *stats){ bool_t linphone_call_media_in_progress(LinphoneCall *call){ bool_t ret=FALSE; - if (ice_in_progress(&call->stats[LINPHONE_CALL_STATS_AUDIO]) || ice_in_progress(&call->stats[LINPHONE_CALL_STATS_VIDEO]) || ice_in_progress(&call->stats[LINPHONE_CALL_STATS_TEXT])) + if (ice_in_progress(call->audio_stats) || ice_in_progress(call->video_stats) || ice_in_progress(call->text_stats)) ret=TRUE; /*TODO: could check zrtp state, upnp state*/ return ret; } +BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(LinphoneCallStats); + +BELLE_SIP_INSTANCIATE_VPTR(LinphoneCallStats, belle_sip_object_t, + NULL, // destroy + _linphone_call_stats_clone, // clone + NULL, // marshal + TRUE +); + +LinphoneCallStats *linphone_call_stats_new() { + LinphoneCallStats *stats = belle_sip_object_new(LinphoneCallStats); + return stats; +} + +LinphoneCallStats* linphone_call_stats_ref(LinphoneCallStats* stats) { + return (LinphoneCallStats*) belle_sip_object_ref(stats); +} + +void linphone_call_stats_unref(LinphoneCallStats* stats) { + belle_sip_object_unref(stats); +} + +void *linphone_call_stats_get_user_data(const LinphoneCallStats *stats) { + return stats->user_data; +} + +void linphone_call_stats_set_user_data(LinphoneCallStats *stats, void *data) { + stats->user_data = data; +} + LinphoneStreamType linphone_call_stats_get_type(const LinphoneCallStats *stats) { return stats->type; } @@ -4241,7 +4326,7 @@ float linphone_call_stats_get_sender_loss_rate(const LinphoneCallStats *stats) { /* Perform msgpullup() to prevent crashes in rtcp_is_SR() or rtcp_is_RR() if the RTCP packet is composed of several mblk_t structure */ if (stats->sent_rtcp->b_cont != NULL) msgpullup(stats->sent_rtcp, -1); - + do{ if (rtcp_is_SR(stats->sent_rtcp)) srb = rtcp_SR_get_report_block(stats->sent_rtcp, 0); @@ -4263,7 +4348,7 @@ float linphone_call_stats_get_receiver_loss_rate(const LinphoneCallStats *stats) /* Perform msgpullup() to prevent crashes in rtcp_is_SR() or rtcp_is_RR() if the RTCP packet is composed of several mblk_t structure */ if (stats->received_rtcp->b_cont != NULL) msgpullup(stats->received_rtcp, -1); - + do{ if (rtcp_is_RR(stats->received_rtcp)) rrb = rtcp_RR_get_report_block(stats->received_rtcp, 0); @@ -4277,9 +4362,17 @@ float linphone_call_stats_get_receiver_loss_rate(const LinphoneCallStats *stats) return 100.0f * report_block_get_fraction_lost(rrb) / 256.0f; } +float linphone_call_stats_get_local_loss_rate(const LinphoneCallStats *stats) { + return stats->local_loss_rate; +} + +float linphone_call_stats_get_local_late_rate(const LinphoneCallStats *stats) { + return stats->local_late_rate; +} + float linphone_call_stats_get_sender_interarrival_jitter(const LinphoneCallStats *stats) { const report_block_t *srb = NULL; - + if (!stats || !stats->sent_rtcp) return 0.0; /* Perform msgpullup() to prevent crashes in rtcp_is_SR() or rtcp_is_RR() if the RTCP packet is composed of several mblk_t structure */ @@ -4347,6 +4440,10 @@ float linphone_call_stats_get_jitter_buffer_size_ms(const LinphoneCallStats *sta return stats->jitter_stats.jitter_buffer_size_ms; } +float linphone_call_stats_get_round_trip_delay(const LinphoneCallStats *stats) { + return stats->round_trip_delay; +} + void linphone_call_start_recording(LinphoneCall *call){ if (!call->params->record_file){ ms_error("linphone_call_start_recording(): no output file specified. Use linphone_call_params_set_record_file()."); @@ -4367,15 +4464,24 @@ void linphone_call_stop_recording(LinphoneCall *call){ static void report_bandwidth_for_stream(LinphoneCall *call, MediaStream *ms, LinphoneStreamType type){ bool_t active = ms ? (media_stream_get_state(ms) == MSStreamStarted) : FALSE; - LinphoneCallStats *stats = &call->stats[type]; - + LinphoneCallStats *stats = NULL; + if (type == LinphoneStreamTypeAudio) { + stats = call->audio_stats; + } else if (type == LinphoneStreamTypeVideo) { + stats = call->video_stats; + } else if (type == LinphoneStreamTypeText) { + stats = call->text_stats; + } else { + return; + } + stats->download_bandwidth=(active) ? (float)(media_stream_get_down_bw(ms)*1e-3) : 0.f; stats->upload_bandwidth=(active) ? (float)(media_stream_get_up_bw(ms)*1e-3) : 0.f; stats->rtcp_download_bandwidth=(active) ? (float)(media_stream_get_rtcp_down_bw(ms)*1e-3) : 0.f; stats->rtcp_upload_bandwidth=(active) ? (float)(media_stream_get_rtcp_up_bw(ms)*1e-3) : 0.f; stats->rtp_remote_family=(active) ? (ortp_stream_is_ipv6(&ms->sessions.rtp_session->rtp.gs) ? LinphoneAddressFamilyInet6 : LinphoneAddressFamilyInet) : LinphoneAddressFamilyUnspec; - + if (call->core->send_call_stats_periodical_updates){ if (active) update_local_stats(stats, ms); stats->updated |= LINPHONE_CALL_STATS_PERIODICAL_UPDATE; @@ -4393,18 +4499,18 @@ static void report_bandwidth(LinphoneCall *call, MediaStream *as, MediaStream *v "\tRTP audio=[d=%5.1f,u=%5.1f], video=[d=%5.1f,u=%5.1f], text=[d=%5.1f,u=%5.1f] kbits/sec\n" "\tRTCP audio=[d=%5.1f,u=%5.1f], video=[d=%5.1f,u=%5.1f], text=[d=%5.1f,u=%5.1f] kbits/sec", call, - call->stats[LINPHONE_CALL_STATS_AUDIO].download_bandwidth, - call->stats[LINPHONE_CALL_STATS_AUDIO].upload_bandwidth, - call->stats[LINPHONE_CALL_STATS_VIDEO].download_bandwidth, - call->stats[LINPHONE_CALL_STATS_VIDEO].upload_bandwidth, - call->stats[LINPHONE_CALL_STATS_TEXT].download_bandwidth, - call->stats[LINPHONE_CALL_STATS_TEXT].upload_bandwidth, - call->stats[LINPHONE_CALL_STATS_AUDIO].rtcp_download_bandwidth, - call->stats[LINPHONE_CALL_STATS_AUDIO].rtcp_upload_bandwidth, - call->stats[LINPHONE_CALL_STATS_VIDEO].rtcp_download_bandwidth, - call->stats[LINPHONE_CALL_STATS_VIDEO].rtcp_upload_bandwidth, - call->stats[LINPHONE_CALL_STATS_TEXT].rtcp_download_bandwidth, - call->stats[LINPHONE_CALL_STATS_TEXT].rtcp_upload_bandwidth + call->audio_stats->download_bandwidth, + call->audio_stats->upload_bandwidth, + call->video_stats->download_bandwidth, + call->video_stats->upload_bandwidth, + call->text_stats->download_bandwidth, + call->text_stats->upload_bandwidth, + call->audio_stats->rtcp_download_bandwidth, + call->audio_stats->rtcp_upload_bandwidth, + call->video_stats->rtcp_download_bandwidth, + call->video_stats->rtcp_upload_bandwidth, + call->text_stats->rtcp_download_bandwidth, + call->text_stats->rtcp_upload_bandwidth ); } @@ -4419,7 +4525,7 @@ static void linphone_call_lost(LinphoneCall *call){ ms_message("LinphoneCall [%p]: %s", call, temp); linphone_core_notify_display_warning(lc, temp); call->non_op_error = TRUE; - linphone_error_info_set(call->ei, LinphoneReasonIOError, 503, "Media lost", NULL); + linphone_error_info_set(call->ei,NULL, LinphoneReasonIOError, 503, "Media lost", NULL); linphone_call_terminate(call); linphone_core_play_named_tone(lc, LinphoneToneCallLost); ms_free(temp); @@ -4537,7 +4643,14 @@ void linphone_call_stats_uninit(LinphoneCallStats *stats){ } void linphone_call_notify_stats_updated_with_stream_index(LinphoneCall *call, int stream_index){ - LinphoneCallStats *stats = &call->stats[stream_index]; + LinphoneCallStats *stats = NULL; + if (stream_index == call->main_audio_stream_index) { + stats = call->audio_stats; + } else if (stream_index == call->main_video_stream_index) { + stats = call->video_stats; + } else { + stats = call->text_stats; + } if (stats->updated){ switch(stats->updated) { case LINPHONE_CALL_STATS_RECEIVED_RTCP_UPDATE: @@ -4607,13 +4720,25 @@ void linphone_call_handle_stream_events(LinphoneCall *call, int stream_index){ while((evq = linphone_call_get_event_queue(call, stream_index)) != NULL && NULL != (ev=ortp_ev_queue_get(evq))){ OrtpEventType evt=ortp_event_get_type(ev); OrtpEventData *evd=ortp_event_get_data(ev); - int stats_index = stream_index == call->main_audio_stream_index ? LINPHONE_CALL_STATS_AUDIO : (stream_index == call->main_video_stream_index ? LINPHONE_CALL_STATS_VIDEO : LINPHONE_CALL_STATS_TEXT); + int stats_index; + LinphoneCallStats *stats = NULL; + + if (stream_index == call->main_audio_stream_index) { + stats_index = LINPHONE_CALL_STATS_AUDIO; + stats = call->audio_stats; + } else if (stream_index == call->main_video_stream_index) { + stats_index = LINPHONE_CALL_STATS_VIDEO; + stats = call->video_stats; + } else { + stats_index = LINPHONE_CALL_STATS_TEXT; + stats = call->text_stats; + } /*and yes the MediaStream must be taken at each iteration, because it may have changed due to the handling of events * in this loop*/ ms = linphone_call_get_media_stream(call, stream_index); - if (ms) linphone_call_stats_fill(&call->stats[stats_index],ms,ev); + if (ms) linphone_call_stats_fill(stats,ms,ev); linphone_call_notify_stats_updated_with_stream_index(call,stats_index); if (evt == ORTP_EVENT_ZRTP_ENCRYPTION_CHANGED){ @@ -4624,7 +4749,7 @@ void linphone_call_handle_stream_events(LinphoneCall *call, int stream_index){ } } else if (evt == ORTP_EVENT_ZRTP_SAS_READY) { if (stream_index == call->main_audio_stream_index) - linphone_call_audiostream_auth_token_ready(call, evd->info.zrtp_sas.sas, evd->info.zrtp_sas.verified); + linphone_call_audiostream_auth_token_ready(call, evd->info.zrtp_info.sas, evd->info.zrtp_info.verified); } else if (evt == ORTP_EVENT_DTLS_ENCRYPTION_CHANGED) { if (stream_index == call->main_audio_stream_index) linphone_call_audiostream_encryption_changed(call, evd->info.dtls_stream_encrypted); @@ -4690,7 +4815,7 @@ void linphone_call_background_tasks(LinphoneCall *call, bool_t one_second_elapse void linphone_call_log_completed(LinphoneCall *call){ LinphoneCore *lc=call->core; - + call->log->duration= _linphone_call_compute_duration(call); /*store duration since connected*/ call->log->error_info = linphone_error_info_ref((LinphoneErrorInfo*)linphone_call_get_error_info(call)); @@ -4813,13 +4938,29 @@ LinphonePlayer *linphone_call_get_player(LinphoneCall *call){ return call->player; } -void linphone_call_set_new_params(LinphoneCall *call, const LinphoneCallParams *params){ + +void linphone_call_set_params(LinphoneCall *call, const LinphoneCallParams *params){ + if ( call->state == LinphoneCallOutgoingInit || call->state == LinphoneCallIncomingReceived){ + _linphone_call_set_new_params(call, params); + } + else { + ms_error("linphone_call_set_params() invalid state %s to call this function", linphone_call_state_to_string(call->state)); + } +} + + +void _linphone_call_set_new_params(LinphoneCall *call, const LinphoneCallParams *params){ LinphoneCallParams *cp=NULL; if (params) cp=linphone_call_params_copy(params); if (call->params) linphone_call_params_unref(call->params); call->params=cp; } +const LinphoneCallParams * linphone_call_get_params(LinphoneCall *call){ + return call->params; +} + + static int send_dtmf_handler(void *data, unsigned int revents){ LinphoneCall *call = (LinphoneCall*)data; /*By default we send DTMF RFC2833 if we do not have enabled SIP_INFO but we can also send RFC2833 and SIP_INFO*/ @@ -5118,6 +5259,14 @@ static void terminate_call(LinphoneCall *call) { } LinphoneStatus linphone_call_terminate(LinphoneCall *call) { + return linphone_call_terminate_with_error_info(call, NULL); +} + + +LinphoneStatus linphone_call_terminate_with_error_info(LinphoneCall *call , const LinphoneErrorInfo *ei){ + SalErrorInfo sei={0}; + LinphoneErrorInfo* p_ei = (LinphoneErrorInfo*) ei; + ms_message("Terminate call [%p] which is currently in state %s", call, linphone_call_state_to_string(call->state)); switch (call->state) { case LinphoneCallReleased: @@ -5127,24 +5276,35 @@ LinphoneStatus linphone_call_terminate(LinphoneCall *call) { return -1; case LinphoneCallIncomingReceived: case LinphoneCallIncomingEarlyMedia: - return linphone_call_decline(call, LinphoneReasonDeclined); + return linphone_call_decline_with_error_info(call, p_ei); case LinphoneCallOutgoingInit: /* In state OutgoingInit, op has to be destroyed */ sal_op_release(call->op); call->op = NULL; break; default: - sal_call_terminate(call->op); + + if (ei == NULL){ + sal_call_terminate(call->op); + } + else{ + linphone_error_info_to_sal(ei, &sei); + sal_call_terminate_with_error(call->op, &sei); + sal_error_info_reset(&sei); + } break; } + terminate_call(call); return 0; + } LinphoneStatus linphone_call_redirect(LinphoneCall *call, const char *redirect_uri) { char *real_url = NULL; LinphoneCore *lc; LinphoneAddress *real_parsed_url; + SalErrorInfo sei = {0}; if (call->state != LinphoneCallIncomingReceived) { ms_error("Bad state for call redirection."); @@ -5160,22 +5320,45 @@ LinphoneStatus linphone_call_redirect(LinphoneCall *call, const char *redirect_u } real_url = linphone_address_as_string(real_parsed_url); - sal_call_decline(call->op, SalReasonRedirect, real_url); + sal_error_info_set(&sei,SalReasonRedirect, "SIP", 0, NULL, NULL); + sal_call_decline_with_error_info(call->op, &sei, real_url); ms_free(real_url); - linphone_error_info_set(call->ei, LinphoneReasonMovedPermanently, 302, "Call redirected", NULL); + linphone_error_info_set(call->ei, NULL, LinphoneReasonMovedPermanently, 302, "Call redirected", NULL); call->non_op_error = TRUE; terminate_call(call); linphone_address_unref(real_parsed_url); + sal_error_info_reset(&sei); return 0; } LinphoneStatus linphone_call_decline(LinphoneCall * call, LinphoneReason reason) { + LinphoneStatus status; + LinphoneErrorInfo *ei = linphone_error_info_new(); + linphone_error_info_set(ei, "SIP", reason,linphone_reason_to_error_code(reason), NULL, NULL); + status = linphone_call_decline_with_error_info(call, ei); + linphone_error_info_unref(ei); + return status; +} + + +LinphoneStatus linphone_call_decline_with_error_info(LinphoneCall * call, const LinphoneErrorInfo *ei) { + SalErrorInfo sei = {0}; + SalErrorInfo sub_sei = {0}; + + sei.sub_sei = &sub_sei; + if ((call->state != LinphoneCallIncomingReceived) && (call->state != LinphoneCallIncomingEarlyMedia)) { ms_error("Cannot decline a call that is in state %s", linphone_call_state_to_string(call->state)); return -1; } - - sal_call_decline(call->op, linphone_reason_to_sal(reason), NULL); + if (ei) { + linphone_error_info_to_sal(ei, &sei); + sal_call_decline_with_error_info(call->op, &sei , NULL); + }else{ + sal_call_decline(call->op, SalReasonDeclined, NULL); + } + sal_error_info_reset(&sei); + sal_error_info_reset(&sub_sei); terminate_call(call); return 0; } @@ -5248,7 +5431,7 @@ LinphoneStatus linphone_call_accept_with_params(LinphoneCall *call, const Linpho /* Try to be best-effort in giving real local or routable contact address */ linphone_call_set_contact_op(call); if (params) { - linphone_call_set_new_params(call, params); + _linphone_call_set_new_params(call, params); linphone_call_prepare_ice(call, TRUE); linphone_call_make_local_media_description(call); sal_call_set_local_media_description(call->op, call->localdesc); @@ -5304,7 +5487,7 @@ LinphoneStatus linphone_call_accept_early_media_with_params(LinphoneCall *call, /* If parameters are passed, update the media description */ if (params) { - linphone_call_set_new_params(call, params); + _linphone_call_set_new_params(call, params); linphone_call_make_local_media_description(call); sal_call_set_local_media_description(call->op, call->localdesc); sal_op_set_sent_custom_header(call->op, params->custom_headers); @@ -5377,7 +5560,7 @@ LinphoneStatus linphone_call_update(LinphoneCall *call, const LinphoneCallParams } } #endif /* defined(VIDEO_ENABLED) && defined(BUILD_UPNP) */ - linphone_call_set_new_params(call, params); + _linphone_call_set_new_params(call, params); err = linphone_call_prepare_ice(call, FALSE); if (err == 1) { ms_message("Defer call update to gather ICE candidates"); @@ -5470,12 +5653,12 @@ LinphoneStatus linphone_call_defer_update(LinphoneCall *call) { ms_error("linphone_call_defer_update() not done in state LinphoneCallUpdatedByRemote"); return -1; } - + if (call->expect_media_in_ack) { ms_error("linphone_call_defer_update() is not possible during a late offer incoming reINVITE (INVITE without SDP)"); return -1; } - + call->defer_update=TRUE; return 0; } @@ -5525,7 +5708,7 @@ int _linphone_call_accept_update(LinphoneCall *call, const LinphoneCallParams *p linphone_call_params_enable_video_multicast(call->params, FALSE); } } else { - linphone_call_set_new_params(call, params); + _linphone_call_set_new_params(call, params); } if (call->params->has_video && !linphone_core_video_enabled(lc)) { @@ -5686,7 +5869,7 @@ int linphone_call_start_invite(LinphoneCall *call, const LinphoneAddress *destin linphone_call_ref(call); /* Take a ref because sal_call() may destroy the call if no SIP transport is available */ err = sal_call(call->op, from, real_url); - + if (err < 0) { if ((call->state != LinphoneCallError) && (call->state != LinphoneCallReleased)) { /* sal_call() may invoke call_failure() and call_released() SAL callbacks synchronously, @@ -5774,6 +5957,7 @@ void linphone_call_reinvite_to_recover_from_connection_loss(LinphoneCall *call) } void linphone_call_repair_if_broken(LinphoneCall *call){ + SalErrorInfo sei = {0}; if (!call->broken) return; if (!call->core->media_network_reachable) return; @@ -5803,7 +5987,8 @@ void linphone_call_repair_if_broken(LinphoneCall *call){ break; case LinphoneCallUpdatedByRemote: if (sal_call_dialog_request_pending(call->op)) { - sal_call_decline(call->op, SalReasonServiceUnavailable, NULL); + sal_error_info_set(&sei, SalReasonServiceUnavailable,"SIP", 0, NULL, NULL); + sal_call_decline_with_error_info(call->op, &sei,NULL); } linphone_call_reinvite_to_recover_from_connection_loss(call); break; @@ -5825,6 +6010,7 @@ void linphone_call_repair_if_broken(LinphoneCall *call){ call->broken = FALSE; break; } + sal_error_info_reset(&sei); } void linphone_call_refresh_sockets(LinphoneCall *call){ @@ -5878,20 +6064,14 @@ void linphone_call_replace_op(LinphoneCall *call, SalOp *op) { sal_op_release(oldop); } -void linphone_call_ogl_render(LinphoneCall *call, bool_t is_preview) { +void linphone_call_ogl_render(const LinphoneCall *call) { + #ifdef VIDEO_ENABLED + VideoStream *stream = call->videostream; - if (!stream) - return; + if (stream && stream->output && ms_filter_get_id(stream->output) == MS_OGL_ID) + ms_filter_call_method(stream->output, MS_OGL_RENDER, NULL); - if (!is_preview) { - if (stream->output && ms_filter_get_id(stream->output) == MS_OGL_ID) - ms_filter_call_method(stream->output, MS_OGL_RENDER, NULL); - - return; - } - - if (stream->output2 && ms_filter_get_id(stream->output2) == MS_OGL_ID) - ms_filter_call_method(stream->output2, MS_OGL_RENDER, NULL); + #endif } void linphone_call_add_callbacks(LinphoneCall *call, LinphoneCallCbs *cbs) { diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index 4f7149ed6..2d546440a 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -28,8 +28,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #ifdef SQLITE_STORAGE_ENABLED #include "sqlite3_bctbx_vfs.h" -/* we need bzrtp.h to setup the zrtp cache only when SQLITE is enabled */ -#include "bzrtp/bzrtp.h" #endif #include @@ -38,13 +36,14 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include #include #include -#include "mediastreamer2/mediastream.h" -#include "mediastreamer2/msfactory.h" -#include "mediastreamer2/mseventqueue.h" -#include "mediastreamer2/msvolume.h" -#include "mediastreamer2/msequalizer.h" #include "mediastreamer2/dtmfgen.h" +#include "mediastreamer2/mediastream.h" +#include "mediastreamer2/msequalizer.h" +#include "mediastreamer2/mseventqueue.h" +#include "mediastreamer2/msfactory.h" #include "mediastreamer2/msjpegwriter.h" +#include "mediastreamer2/msogl.h" +#include "mediastreamer2/msvolume.h" #ifdef INET6 #ifndef _WIN32 @@ -107,6 +106,7 @@ static void set_media_network_reachable(LinphoneCore* lc,bool_t isReachable); static void linphone_core_run_hooks(LinphoneCore *lc); static void linphone_core_uninit(LinphoneCore *lc); static void linphone_core_zrtp_cache_close(LinphoneCore *lc); +void linphone_core_zrtp_cache_db_init(LinphoneCore *lc, const char *fileName); #include "enum.h" #include "contact_providers_priv.h" @@ -2521,11 +2521,10 @@ void linphone_core_get_audio_port_range(const LinphoneCore *lc, int *min_port, i *max_port = lc->rtp_conf.audio_rtp_max_port; } -LinphoneIntRange linphone_core_get_audio_port_range_2(const LinphoneCore *lc) { - LinphoneIntRange range = { - .min = lc->rtp_conf.audio_rtp_min_port, - .max = lc->rtp_conf.audio_rtp_max_port - }; +LinphoneRange *linphone_core_get_audio_ports_range(const LinphoneCore *lc) { + LinphoneRange *range = linphone_range_new(); + range->min = lc->rtp_conf.audio_rtp_min_port; + range->max = lc->rtp_conf.audio_rtp_max_port; return range; } @@ -2538,11 +2537,10 @@ void linphone_core_get_video_port_range(const LinphoneCore *lc, int *min_port, i *max_port = lc->rtp_conf.video_rtp_max_port; } -LinphoneIntRange linphone_core_get_video_port_range_2(const LinphoneCore *lc) { - LinphoneIntRange range = { - .min = lc->rtp_conf.video_rtp_min_port, - .max = lc->rtp_conf.video_rtp_max_port - }; +LinphoneRange *linphone_core_get_video_ports_range(const LinphoneCore *lc) { + LinphoneRange *range = linphone_range_new(); + range->min = lc->rtp_conf.video_rtp_min_port; + range->max = lc->rtp_conf.video_rtp_max_port; return range; } @@ -2555,11 +2553,10 @@ void linphone_core_get_text_port_range(const LinphoneCore *lc, int *min_port, in *max_port = lc->rtp_conf.text_rtp_max_port; } -LinphoneIntRange linphone_core_get_text_port_range_2(const LinphoneCore *lc) { - LinphoneIntRange range = { - .min = lc->rtp_conf.text_rtp_min_port, - .max = lc->rtp_conf.text_rtp_max_port - }; +LinphoneRange *linphone_core_get_text_ports_range(const LinphoneCore *lc) { + LinphoneRange *range = linphone_range_new(); + range->min = lc->rtp_conf.text_rtp_min_port; + range->max = lc->rtp_conf.text_rtp_max_port; return range; } @@ -2764,6 +2761,72 @@ bool_t linphone_core_sip_transport_supported(const LinphoneCore *lc, LinphoneTra return sal_transport_available(lc->sal,(SalTransport)tp); } +BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(LinphoneTransports); + +BELLE_SIP_INSTANCIATE_VPTR(LinphoneTransports, belle_sip_object_t, + NULL, // destroy + NULL, // clone + NULL, // marshal + FALSE +); + +LinphoneTransports *linphone_transports_new() { + LinphoneTransports *transports = belle_sip_object_new(LinphoneTransports); + transports->udp_port = 0; + transports->tcp_port = 0; + transports->tls_port = 0; + transports->dtls_port = 0; + return transports; +} + +LinphoneTransports* linphone_transports_ref(LinphoneTransports* transports) { + return (LinphoneTransports*) belle_sip_object_ref(transports); +} + +void linphone_transports_unref (LinphoneTransports* transports) { + belle_sip_object_unref(transports); +} + +void *linphone_transports_get_user_data(const LinphoneTransports *transports) { + return transports->user_data; +} + +void linphone_transports_set_user_data(LinphoneTransports *transports, void *data) { + transports->user_data = data; +} + +int linphone_transports_get_udp_port(const LinphoneTransports* transports) { + return transports->udp_port; +} + +int linphone_transports_get_tcp_port(const LinphoneTransports* transports) { + return transports->tcp_port; +} + +int linphone_transports_get_tls_port(const LinphoneTransports* transports) { + return transports->tls_port; +} + +int linphone_transports_get_dtls_port(const LinphoneTransports* transports) { + return transports->dtls_port; +} + +void linphone_transports_set_udp_port(LinphoneTransports *transports, int port) { + transports->udp_port = port; +} + +void linphone_transports_set_tcp_port(LinphoneTransports *transports, int port) { + transports->tcp_port = port; +} + +void linphone_transports_set_tls_port(LinphoneTransports *transports, int port) { + transports->tls_port = port; +} + +void linphone_transports_set_dtls_port(LinphoneTransports *transports, int port) { + transports->dtls_port = port; +} + LinphoneStatus linphone_core_set_sip_transports(LinphoneCore *lc, const LinphoneSipTransports * tr_config /*config to be saved*/){ LinphoneSipTransports tr=*tr_config; @@ -2798,17 +2861,57 @@ LinphoneStatus linphone_core_set_sip_transports(LinphoneCore *lc, const Linphone return _linphone_core_apply_transports(lc); } +LinphoneStatus linphone_core_set_transports(LinphoneCore *lc, const LinphoneTransports * transports){ + if (transports->udp_port == lc->sip_conf.transports.udp_port && + transports->tcp_port == lc->sip_conf.transports.tcp_port && + transports->tls_port == lc->sip_conf.transports.tls_port && + transports->dtls_port == lc->sip_conf.transports.dtls_port) { + return 0; + } + lc->sip_conf.transports.udp_port = transports->udp_port; + lc->sip_conf.transports.tcp_port = transports->tcp_port; + lc->sip_conf.transports.tls_port = transports->tls_port; + lc->sip_conf.transports.dtls_port = transports->dtls_port; + + if (linphone_core_ready(lc)) { + lp_config_set_int(lc->config,"sip", "sip_port", transports->udp_port); + lp_config_set_int(lc->config,"sip", "sip_tcp_port", transports->tcp_port); + lp_config_set_int(lc->config,"sip", "sip_tls_port", transports->tls_port); + } + + if (lc->sal == NULL) return 0; + return _linphone_core_apply_transports(lc); +} + LinphoneStatus linphone_core_get_sip_transports(LinphoneCore *lc, LinphoneSipTransports *tr){ memcpy(tr,&lc->sip_conf.transports,sizeof(*tr)); return 0; } +LinphoneTransports *linphone_core_get_transports(LinphoneCore *lc){ + LinphoneTransports *transports = linphone_transports_new(); + transports->udp_port = lc->sip_conf.transports.udp_port; + transports->tcp_port = lc->sip_conf.transports.tcp_port; + transports->tls_port = lc->sip_conf.transports.tls_port; + transports->dtls_port = lc->sip_conf.transports.dtls_port; + return transports; +} + 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); } +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); + return transports; +} + void linphone_core_set_sip_port(LinphoneCore *lc,int port) { LinphoneSipTransports tr; memset(&tr,0,sizeof(tr)); @@ -3081,7 +3184,7 @@ void linphone_core_iterate(LinphoneCore *lc){ decline_reason = (lc->current_call != call) ? LinphoneReasonBusy : LinphoneReasonDeclined; call->log->status=LinphoneCallMissed; call->non_op_error = TRUE; - linphone_error_info_set(call->ei, decline_reason, linphone_reason_to_error_code(decline_reason), "Not answered", NULL); + linphone_error_info_set(call->ei, NULL, decline_reason, linphone_reason_to_error_code(decline_reason), "Not answered", NULL); linphone_call_decline(call, decline_reason); } } @@ -4595,8 +4698,8 @@ void linphone_core_remove_call_log(LinphoneCore *lc, LinphoneCallLog *cl) { linphone_core_delete_call_log(lc, cl); } #endif + lc->call_logs = bctbx_list_remove(lc->call_logs, cl); if (!call_logs_sqlite_db_found) { - lc->call_logs = bctbx_list_remove(lc->call_logs, cl); call_logs_write_to_config_file(lc); linphone_call_log_unref(cl); } @@ -4709,7 +4812,13 @@ static void toggle_video_preview(LinphoneCore *lc, bool_t val){ if (val){ if (lc->previewstream==NULL){ const char *display_filter=linphone_core_get_video_display_filter(lc); - MSVideoSize vsize=lc->video_conf.preview_vsize.width!=0 ? lc->video_conf.preview_vsize : lc->video_conf.vsize; + MSVideoSize vsize = { 0 }; + const LinphoneVideoDefinition *vdef = linphone_core_get_preview_video_definition(lc); + if (!vdef || linphone_video_definition_is_undefined(vdef)) { + vdef = linphone_core_get_preferred_video_definition(lc); + } + vsize.width = linphone_video_definition_get_width(vdef); + vsize.height = linphone_video_definition_get_height(vdef); lc->previewstream=video_preview_new(lc->factory); video_preview_set_size(lc->previewstream,vsize); if (display_filter) @@ -4818,6 +4927,70 @@ const LinphoneVideoPolicy *linphone_core_get_video_policy(const LinphoneCore *lc return &lc->video_policy; } +BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(LinphoneVideoActivationPolicy); + +BELLE_SIP_INSTANCIATE_VPTR(LinphoneVideoActivationPolicy, belle_sip_object_t, + NULL, // destroy + NULL, // clone + NULL, // marshal + FALSE +); + +LinphoneVideoActivationPolicy *linphone_video_activation_policy_new() { + LinphoneVideoActivationPolicy *policy = belle_sip_object_new(LinphoneVideoActivationPolicy); + policy->automatically_accept = FALSE; + policy->automatically_initiate = FALSE; + return policy; +} + +LinphoneVideoActivationPolicy* linphone_video_activation_policy_ref(LinphoneVideoActivationPolicy* policy) { + return (LinphoneVideoActivationPolicy*) belle_sip_object_ref(policy); +} + +void linphone_video_activation_policy_unref(LinphoneVideoActivationPolicy* policy) { + belle_sip_object_unref(policy); +} + +void *linphone_video_activation_policy_get_user_data(const LinphoneVideoActivationPolicy *policy) { + return policy->user_data; +} + +void linphone_video_activation_policy_set_user_data(LinphoneVideoActivationPolicy *policy, void *data) { + policy->user_data = data; +} + +bool_t linphone_video_activation_policy_get_automatically_accept(const LinphoneVideoActivationPolicy *policy) { + return policy->automatically_accept; +} + +bool_t linphone_video_activation_policy_get_automatically_initiate(const LinphoneVideoActivationPolicy *policy) { + return policy->automatically_initiate; +} + +void linphone_video_activation_policy_set_automatically_accept(LinphoneVideoActivationPolicy *policy, bool_t enable) { + policy->automatically_accept = enable; +} + +void linphone_video_activation_policy_set_automatically_initiate(LinphoneVideoActivationPolicy *policy, bool_t enable) { + policy->automatically_initiate = enable; +} + +void linphone_core_set_video_activation_policy(LinphoneCore *lc, const LinphoneVideoActivationPolicy *policy) { + lc->video_policy.automatically_accept = policy->automatically_accept; + lc->video_policy.automatically_initiate = policy->automatically_initiate; + if (linphone_core_ready(lc)) { + lp_config_set_int(lc->config, "video", "automatically_initiate", policy->automatically_initiate); + lp_config_set_int(lc->config, "video", "automatically_accept", policy->automatically_accept); + } +} + +LinphoneVideoActivationPolicy *linphone_core_get_video_activation_policy(const LinphoneCore *lc){ + LinphoneVideoActivationPolicy *policy = linphone_video_activation_policy_new(); + policy->automatically_accept = lc->video_policy.automatically_accept; + policy->automatically_initiate = lc->video_policy.automatically_initiate; + return policy; +} + void linphone_core_enable_video_preview(LinphoneCore *lc, bool_t val){ lc->video_conf.show_local=val; if (linphone_core_ready(lc)) @@ -5107,33 +5280,32 @@ int linphone_core_get_camera_sensor_rotation(LinphoneCore *lc) { return -1; } -static MSVideoSizeDef supported_resolutions[]={ +static MSVideoSizeDef supported_resolutions[] = { #if !defined(__ANDROID__) && !TARGET_OS_IPHONE - { { MS_VIDEO_SIZE_1080P_W, MS_VIDEO_SIZE_1080P_H } , "1080p" }, + { { MS_VIDEO_SIZE_1080P_W, MS_VIDEO_SIZE_1080P_H }, "1080p" }, #endif #if !defined(__ANDROID__) && !TARGET_OS_MAC /*limit to most common sizes because mac video API cannot list supported resolutions*/ - { { MS_VIDEO_SIZE_UXGA_W, MS_VIDEO_SIZE_UXGA_H } , "uxga" }, - { { MS_VIDEO_SIZE_SXGA_MINUS_W, MS_VIDEO_SIZE_SXGA_MINUS_H } , "sxga-" }, + { { MS_VIDEO_SIZE_UXGA_W, MS_VIDEO_SIZE_UXGA_H }, "uxga" }, + { { MS_VIDEO_SIZE_SXGA_MINUS_W, MS_VIDEO_SIZE_SXGA_MINUS_H }, "sxga-" }, #endif - { { MS_VIDEO_SIZE_720P_W, MS_VIDEO_SIZE_720P_H } , "720p" }, + { { MS_VIDEO_SIZE_720P_W, MS_VIDEO_SIZE_720P_H }, "720p" }, #if !defined(__ANDROID__) && !TARGET_OS_MAC - { { MS_VIDEO_SIZE_XGA_W, MS_VIDEO_SIZE_XGA_H } , "xga" }, + { { MS_VIDEO_SIZE_XGA_W, MS_VIDEO_SIZE_XGA_H }, "xga" }, #endif #if !defined(__ANDROID__) && !TARGET_OS_IPHONE - { { MS_VIDEO_SIZE_SVGA_W, MS_VIDEO_SIZE_SVGA_H } , "svga" }, - { { MS_VIDEO_SIZE_4CIF_W, MS_VIDEO_SIZE_4CIF_H } , "4cif" }, + { { MS_VIDEO_SIZE_SVGA_W, MS_VIDEO_SIZE_SVGA_H }, "svga" }, + { { MS_VIDEO_SIZE_4CIF_W, MS_VIDEO_SIZE_4CIF_H }, "4cif" }, #endif - - { { MS_VIDEO_SIZE_VGA_W, MS_VIDEO_SIZE_VGA_H } , "vga" }, + { { MS_VIDEO_SIZE_VGA_W, MS_VIDEO_SIZE_VGA_H }, "vga" }, #if TARGET_OS_IPHONE - { { MS_VIDEO_SIZE_IOS_MEDIUM_H, MS_VIDEO_SIZE_IOS_MEDIUM_W } , "ios-medium" }, + { { MS_VIDEO_SIZE_IOS_MEDIUM_H, MS_VIDEO_SIZE_IOS_MEDIUM_W }, "ios-medium" }, #endif - { { MS_VIDEO_SIZE_CIF_W, MS_VIDEO_SIZE_CIF_H } , "cif" }, + { { MS_VIDEO_SIZE_CIF_W, MS_VIDEO_SIZE_CIF_H }, "cif" }, #if !TARGET_OS_MAC || TARGET_OS_IPHONE /* OS_MAC is 1 for iPhone, but we need QVGA */ - { { MS_VIDEO_SIZE_QVGA_W, MS_VIDEO_SIZE_QVGA_H } , "qvga" }, + { { MS_VIDEO_SIZE_QVGA_W, MS_VIDEO_SIZE_QVGA_H } , "qvga" }, #endif - { { MS_VIDEO_SIZE_QCIF_W, MS_VIDEO_SIZE_QCIF_H } , "qcif" }, - { { 0,0 } , NULL } + { { MS_VIDEO_SIZE_QCIF_W, MS_VIDEO_SIZE_QCIF_H }, "qcif" }, + { { 0, 0 }, NULL } }; const MSVideoSizeDef *linphone_core_get_supported_video_sizes(LinphoneCore *lc){ @@ -5157,69 +5329,77 @@ static MSVideoSize video_size_get_by_name(const char *name){ return null_vsize; } -/* warning: function not reentrant*/ -static const char *video_size_get_name(MSVideoSize vsize){ - MSVideoSizeDef *pdef=supported_resolutions; - static char customsize[64]={0}; - for(;pdef->name!=NULL;pdef++){ - if (pdef->vsize.width==vsize.width && pdef->vsize.height==vsize.height){ - return pdef->name; - } +static bool_t video_definition_supported(const LinphoneVideoDefinition *vdef) { + const bctbx_list_t *item; + const bctbx_list_t *supported_definitions = linphone_factory_get_supported_video_definitions(linphone_factory_get()); + for (item = supported_definitions; item != NULL; item = bctbx_list_next(item)) { + LinphoneVideoDefinition *supported_vdef = (LinphoneVideoDefinition *)bctbx_list_get_data(item); + if (linphone_video_definition_equals(vdef, supported_vdef)) return TRUE; } - if (vsize.width && vsize.height){ - snprintf(customsize,sizeof(customsize)-1,"%ix%i",vsize.width,vsize.height); - return customsize; - } - return NULL; -} - -static bool_t video_size_supported(MSVideoSize vsize){ - if (video_size_get_name(vsize)) return TRUE; - ms_warning("Video resolution %ix%i is not supported in linphone.",vsize.width,vsize.height); + ms_warning("Video definition %ix%i is not supported", linphone_video_definition_get_width(vdef), linphone_video_definition_get_height(vdef)); return FALSE; } -static void update_preview_size(LinphoneCore *lc, MSVideoSize oldvsize, MSVideoSize vsize){ - if (!ms_video_size_equal(oldvsize,vsize) && lc->previewstream!=NULL){ - relaunch_video_preview(lc); - } -} +void linphone_core_set_preferred_video_definition(LinphoneCore *lc, LinphoneVideoDefinition *vdef) { + if (video_definition_supported(vdef)) { + LinphoneVideoDefinition *oldvdef = lc->video_conf.vdef; + lc->video_conf.vdef = linphone_video_definition_ref(vdef); -void linphone_core_set_preferred_video_size(LinphoneCore *lc, MSVideoSize vsize){ - if (video_size_supported(vsize)){ - MSVideoSize oldvsize=lc->video_conf.preview_vsize; - - if (oldvsize.width==0){ - oldvsize=lc->video_conf.vsize; + if ((lc->previewstream != NULL) && (lc->video_conf.preview_vdef == NULL) + && (oldvdef != NULL) && !linphone_video_definition_equals(oldvdef, vdef)) { + relaunch_video_preview(lc); } - lc->video_conf.vsize=vsize; - update_preview_size(lc,oldvsize,vsize); - if (linphone_core_ready(lc)) - lp_config_set_string(lc->config,"video","size",video_size_get_name(vsize)); + if (oldvdef != NULL) linphone_video_definition_unref(oldvdef); + if (linphone_core_ready(lc)) { + lp_config_set_string(lc->config, "video", "size", linphone_video_definition_get_name(vdef)); + } } } -void linphone_core_set_preview_video_size(LinphoneCore *lc, MSVideoSize vsize){ - MSVideoSize oldvsize; - if (vsize.width==0 && vsize.height==0){ - /*special case to reset the forced preview size mode*/ - lc->video_conf.preview_vsize=vsize; - if (linphone_core_ready(lc)) - lp_config_set_string(lc->config,"video","preview_size",NULL); +void linphone_core_set_preferred_video_size(LinphoneCore *lc, MSVideoSize vsize) { + linphone_core_set_preferred_video_definition(lc, + linphone_factory_find_supported_video_definition(linphone_factory_get(), vsize.width, vsize.height)); +} + +void linphone_core_set_preview_video_definition(LinphoneCore *lc, LinphoneVideoDefinition *vdef) { + if (!vdef || linphone_video_definition_is_undefined(vdef)) { + /* Reset the forced preview video definition mode */ + if (lc->video_conf.preview_vdef != NULL) linphone_video_definition_unref(lc->video_conf.preview_vdef); + lc->video_conf.preview_vdef = NULL; + if (linphone_core_ready(lc)) { + lp_config_set_string(lc->config, "video", "preview_size", NULL); + } return; } - oldvsize=lc->video_conf.preview_vsize; - lc->video_conf.preview_vsize=vsize; - if (!ms_video_size_equal(oldvsize,vsize) && lc->previewstream!=NULL){ - relaunch_video_preview(lc); + + if (!linphone_video_definition_equals(lc->video_conf.preview_vdef, vdef)) { + LinphoneVideoDefinition *oldvdef = lc->video_conf.preview_vdef; + lc->video_conf.preview_vdef = linphone_video_definition_ref(vdef); + if (oldvdef != NULL) linphone_video_definition_unref(oldvdef); + if (lc->previewstream != NULL) { + relaunch_video_preview(lc); + } + } + if (linphone_core_ready(lc)) { + lp_config_set_string(lc->config, "video", "preview_size", linphone_video_definition_get_name(vdef)); } - if (linphone_core_ready(lc)) - lp_config_set_string(lc->config,"video","preview_size",video_size_get_name(vsize)); } -MSVideoSize linphone_core_get_preview_video_size(const LinphoneCore *lc){ - return lc->video_conf.preview_vsize; +void linphone_core_set_preview_video_size(LinphoneCore *lc, MSVideoSize vsize) { + linphone_core_set_preview_video_definition(lc, + linphone_factory_find_supported_video_definition(linphone_factory_get(), vsize.width, vsize.height)); +} + +const LinphoneVideoDefinition * linphone_core_get_preview_video_definition(const LinphoneCore *lc) { + return lc->video_conf.preview_vdef; +} + +MSVideoSize linphone_core_get_preview_video_size(const LinphoneCore *lc) { + MSVideoSize vsize = { 0 }; + vsize.width = linphone_video_definition_get_width(lc->video_conf.preview_vdef); + vsize.height = linphone_video_definition_get_height(lc->video_conf.preview_vdef); + return vsize; } MSVideoSize linphone_core_get_current_preview_video_size(const LinphoneCore *lc){ @@ -5234,11 +5414,33 @@ MSVideoSize linphone_core_get_current_preview_video_size(const LinphoneCore *lc) return ret; } +LinphoneVideoDefinition * linphone_core_get_current_preview_video_definition(const LinphoneCore *lc) { +#ifdef VIDEO_ENABLED + MSVideoSize vsize; + if (lc->previewstream) { + vsize = video_preview_get_current_size(lc->previewstream); + } + return linphone_factory_find_supported_video_definition(linphone_factory_get(), vsize.width, vsize.height); +#else + ms_error("Video support is disabled"); + return NULL; +#endif +} + void linphone_core_set_preview_video_size_by_name(LinphoneCore *lc, const char *name){ MSVideoSize vsize=video_size_get_by_name(name); linphone_core_set_preview_video_size(lc,vsize); } +void linphone_core_set_preview_video_definition_by_name(LinphoneCore *lc, const char *name) { + LinphoneVideoDefinition *vdef = linphone_factory_find_supported_video_definition_by_name(linphone_factory_get(), name); + if (vdef == NULL) { + ms_error("Video definition '%s' is not supported", name); + } else { + linphone_core_set_preview_video_definition(lc, vdef); + } +} + void linphone_core_set_preferred_video_size_by_name(LinphoneCore *lc, const char *name){ MSVideoSize vsize=video_size_get_by_name(name); MSVideoSize default_vsize={MS_VIDEO_SIZE_CIF_W,MS_VIDEO_SIZE_CIF_H}; @@ -5246,12 +5448,28 @@ void linphone_core_set_preferred_video_size_by_name(LinphoneCore *lc, const char else linphone_core_set_preferred_video_size(lc,default_vsize); } -MSVideoSize linphone_core_get_preferred_video_size(const LinphoneCore *lc){ - return lc->video_conf.vsize; +void linphone_core_set_preferred_video_definition_by_name(LinphoneCore *lc, const char *name) { + LinphoneVideoDefinition *vdef = linphone_factory_find_supported_video_definition_by_name(linphone_factory_get(), name); + if (vdef == NULL) { + ms_error("Video definition '%s' is not supported", name); + } else { + linphone_core_set_preferred_video_definition(lc, vdef); + } +} + +const LinphoneVideoDefinition * linphone_core_get_preferred_video_definition(const LinphoneCore *lc) { + return lc->video_conf.vdef; +} + +MSVideoSize linphone_core_get_preferred_video_size(const LinphoneCore *lc) { + MSVideoSize vsize = { 0 }; + vsize.width = linphone_video_definition_get_width(lc->video_conf.vdef); + vsize.height = linphone_video_definition_get_height(lc->video_conf.vdef); + return vsize; } char * linphone_core_get_preferred_video_size_name(const LinphoneCore *lc) { - return ms_strdup(video_size_get_name(lc->video_conf.vsize)); + return ms_strdup(linphone_video_definition_get_name(lc->video_conf.vdef)); } void linphone_core_set_preferred_framerate(LinphoneCore *lc, float fps){ @@ -5264,6 +5482,17 @@ float linphone_core_get_preferred_framerate(LinphoneCore *lc){ return lc->video_conf.fps; } +void linphone_core_preview_ogl_render(const LinphoneCore *lc) { + #ifdef VIDEO_ENABLED + + LinphoneCall *call = linphone_core_get_current_call(lc); + VideoStream *stream = call ? call->videostream : lc->previewstream; + + if (stream && stream->output2 && ms_filter_get_id(stream->output2) == MS_OGL_ID) + ms_filter_call_method(stream->output2, MS_OGL_RENDER, NULL); + + #endif +} void linphone_core_set_use_files(LinphoneCore *lc, bool_t yesno){ lc->use_files=yesno; @@ -5582,7 +5811,7 @@ void sip_config_uninit(LinphoneCore *lc) /*now that we are unregisted, there is no more channel using tunnel socket we no longer need the tunnel.*/ #ifdef TUNNEL_ENABLED if (lc->tunnel) { - linphone_tunnel_ref(lc->tunnel); + linphone_tunnel_unref(lc->tunnel); lc->tunnel=NULL; ms_message("Tunnel destroyed."); } @@ -5646,11 +5875,14 @@ static void sound_config_uninit(LinphoneCore *lc) static void video_config_uninit(LinphoneCore *lc) { - lp_config_set_string(lc->config,"video","size",video_size_get_name(linphone_core_get_preferred_video_size(lc))); + const LinphoneVideoDefinition *vdef = linphone_core_get_preferred_video_definition(lc); + lp_config_set_string(lc->config,"video","size",vdef ? linphone_video_definition_get_name(vdef) : NULL); lp_config_set_int(lc->config,"video","display",lc->video_conf.display); lp_config_set_int(lc->config,"video","capture",lc->video_conf.capture); if (lc->video_conf.cams) ms_free((void *)lc->video_conf.cams); + if (lc->video_conf.vdef) linphone_video_definition_unref(lc->video_conf.vdef); + if (lc->video_conf.preview_vdef) linphone_video_definition_unref(lc->video_conf.preview_vdef); } void _linphone_core_codec_config_write(LinphoneCore *lc){ @@ -5791,10 +6023,6 @@ static void linphone_core_uninit(LinphoneCore *lc) ms_free(lc->zrtp_secrets_cache); } - if(lc->zrtp_cache_db_file != NULL) { - ms_free(lc->zrtp_cache_db_file); - } - if(lc->user_certificates_path != NULL) { ms_free(lc->user_certificates_path); } @@ -6061,15 +6289,15 @@ bool_t linphone_core_get_ring_during_incoming_early_media(const LinphoneCore *lc } static OrtpPayloadType* _linphone_core_find_payload_type(LinphoneCore* lc, const char* type, int rate, int channels) { - OrtpPayloadType* result = find_payload_type_from_list(type, rate, channels, linphone_core_get_audio_codecs(lc)); + OrtpPayloadType* result = find_payload_type_from_list(type, rate, channels, lc->codecs_conf.audio_codecs); if (result) { return result; } else { - result = find_payload_type_from_list(type, rate, 0, linphone_core_get_video_codecs(lc)); + result = find_payload_type_from_list(type, rate, 0, lc->codecs_conf.video_codecs); if (result) { return result; } else { - result = find_payload_type_from_list(type, rate, 0, linphone_core_get_text_codecs(lc)); + result = find_payload_type_from_list(type, rate, 0, lc->codecs_conf.text_codecs); if (result) { return result; } @@ -6218,7 +6446,62 @@ void linphone_core_set_zrtp_secrets_file(LinphoneCore *lc, const char* file){ if (lc->zrtp_secrets_cache != NULL) { ms_free(lc->zrtp_secrets_cache); } + lc->zrtp_secrets_cache=file ? ms_strdup(file) : NULL; + + /* shall we perform cache migration ? */ + if (!lp_config_get_int(lc->config,"sip","zrtp_cache_migration_done",FALSE)) { + char *tmpFile = bctbx_malloc(strlen(file)+6); + /* check we have a valid xml cache file given in path */ + FILE *CACHEFD = NULL; + /* load the xml cache */ + if (file != NULL) { + int ret=0; + CACHEFD = fopen(file, "rb+"); + xmlDocPtr cacheXml = NULL; + if (CACHEFD) { + size_t cacheSize; + char *cacheString = ms_load_file_content(CACHEFD, &cacheSize); + if (!cacheString) { + ms_warning("Unable to load content of ZRTP ZID cache"); + bctbx_free(tmpFile); + return; + } + cacheString[cacheSize] = '\0'; + cacheSize += 1; + fclose(CACHEFD); + cacheXml = xmlParseDoc((xmlChar*)cacheString); + ms_free(cacheString); + } + + /* create a temporary file for the sqlite base and initialise it */ + sprintf(tmpFile,"%s.tmp", file); + linphone_core_zrtp_cache_db_init(lc, tmpFile); + + /* migrate */ + char *bkpFile = bctbx_malloc(strlen(file)+6); + sprintf(bkpFile,"%s.bkp", file); + + if ((ret = ms_zrtp_cache_migration((void *)cacheXml, linphone_core_get_zrtp_cache_db(lc), linphone_core_get_identity(lc))) == 0) { + ms_message("LIME/ZRTP cache migration successfull, obsolete xml file kept as backup in %s", bkpFile); + } else { + ms_error("LIME/ZRTP cache migration failed(returned -%x), start with a fresh cache, old one kept as backup in %s", -ret, bkpFile); + } + + /* rename the newly created sqlite3 file in to the given file name */ + rename(file, bkpFile); + if (rename(tmpFile, file)==0) { /* set the flag if we were able to set the sqlite file in the correct place (even if migration failed) */ + lp_config_set_int(lc->config, "sip", "zrtp_cache_migration_done", TRUE); + } + + /* clean up */ + bctbx_free(bkpFile); + xmlFree(cacheXml); + } + bctbx_free(tmpFile); + } else { + linphone_core_zrtp_cache_db_init(lc, file); + } } const char *linphone_core_get_zrtp_secrets_file(LinphoneCore *lc){ @@ -6242,249 +6525,40 @@ static void linphone_core_zrtp_cache_close(LinphoneCore *lc) { #endif /* SQLITE_STORAGE_ENABLED */ } + +void linphone_core_zrtp_cache_db_init(LinphoneCore *lc, const char *fileName) { #ifdef SQLITE_STORAGE_ENABLED -/* this function is called only when the sqlite cache is newly created but still empty(contains tables structures but no data) - * and we have an xml cache - * SQL zid cache associate each local sip:uri its own ZID while XML version used one ZID for the whole device-> use the XML provided ZID - * for the default local sipUri retrieved using linphone_core_get_identity - */ -static void linphone_core_zrtp_cache_migration(LinphoneCore *lc) { - FILE *CACHEFD = NULL; - /* load the xml cache */ - if (lc->zrtp_secrets_cache != NULL) { - CACHEFD = fopen(lc->zrtp_secrets_cache, "rb+"); - if (CACHEFD) { - size_t cacheSize; - xmlDocPtr cacheXml; - char *cacheString = ms_load_file_content(CACHEFD, &cacheSize); - if (!cacheString) { - ms_warning("Unable to load content of ZRTP ZID cache"); - return; - } - cacheString[cacheSize] = '\0'; - cacheSize += 1; - fclose(CACHEFD); - cacheXml = xmlParseDoc((xmlChar*)cacheString); - ms_free(cacheString); - if (cacheXml) { - xmlNodePtr cur; - xmlChar *selfZidHex=NULL; - uint8_t selfZID[12]; - sqlite3 *db = (sqlite3 *)linphone_core_get_zrtp_cache_db(lc); - sqlite3_stmt *sqlStmt = NULL; - const char *selfURI = linphone_core_get_identity(lc); - int ret; - - /* parse the cache to get the selfZID and insert it in sqlcache */ - cur = xmlDocGetRootElement(cacheXml); - /* if we found a root element, parse its children node */ - if (cur!=NULL) - { - cur = cur->xmlChildrenNode; - } - selfZidHex = NULL; - while (cur!=NULL) { - if ((!xmlStrcmp(cur->name, (const xmlChar *)"selfZID"))){ /* self ZID found, extract it */ - selfZidHex = xmlNodeListGetString(cacheXml, cur->xmlChildrenNode, 1); - bctbx_str_to_uint8(selfZID, selfZidHex, 24); - break; - } - cur = cur->next; - } - /* did we found a self ZID? */ - if (selfZidHex == NULL) { - ms_warning("ZRTP/LIME cache migration: Failed to parse selfZID"); - return; - } - - /* insert the selfZID in cache, associate it to default local sip:uri in case we have more than one */ - ms_message("ZRTP/LIME cache migration: found selfZID %.24s link it to default URI %s in SQL cache", selfZidHex, selfURI); - xmlFree(selfZidHex); - - ret = sqlite3_prepare_v2(db, "INSERT INTO ziduri (zid,selfuri,peeruri) VALUES(?,?,?);", -1, &sqlStmt, NULL); - if (ret != SQLITE_OK) { - ms_warning("ZRTP/LIME cache migration: Failed to insert selfZID"); - return; - } - sqlite3_bind_blob(sqlStmt, 1, selfZID, 12, SQLITE_TRANSIENT); - sqlite3_bind_text(sqlStmt, 2, selfURI,-1,SQLITE_TRANSIENT); - sqlite3_bind_text(sqlStmt, 3, "self",-1,SQLITE_TRANSIENT); - - ret = sqlite3_step(sqlStmt); - if (ret!=SQLITE_DONE) { - ms_warning("ZRTP/LIME cache migration: Failed to insert selfZID"); - return; - } - sqlite3_finalize(sqlStmt); - - /* loop over all the peer node in the xml cache and get from them : uri(can be more than one), ZID, rs1, rs2, pvs, sndKey, rcvKey, sndSId, rcvSId, sndIndex, rcvIndex, valid */ - /* some of these may be missing(pvs, valid, rs2) but we'll consider them NULL */ - /* aux and pbx secrets were not used, so don't even bother looking for them */ - cur = xmlDocGetRootElement(cacheXml)->xmlChildrenNode; - - while (cur!=NULL) { /* loop on all peer nodes */ - if ((!xmlStrcmp(cur->name, (const xmlChar *)"peer"))) { /* found a peer node, check if there is a sipURI node in it (other nodes are just ignored) */ - int i; - xmlNodePtr peerNodeChildren = cur->xmlChildrenNode; - xmlChar *nodeContent = NULL; - xmlChar *peerZIDString = NULL; - uint8_t peerZID[12]; - uint8_t peerZIDFound=0; - xmlChar *peerUri[128]; /* array to contain all the peer uris found in one node */ - /* hopefully they won't be more than 128(it would mean some peer has more than 128 accounts and we called all of them...) */ - int peerUriIndex=0; /* index of previous array */ - char *zrtpColNames[] = {"rs1", "rs2", "pvs"}; - uint8_t *zrtpColValues[] = {NULL, NULL, NULL}; - size_t zrtpColExpectedLengths[] = {32,32,1}; - size_t zrtpColLengths[] = {0,0,0}; - - char *limeColNames[] = {"sndKey", "rcvKey", "sndSId", "rcvSId", "sndIndex", "rcvIndex", "valid"}; - uint8_t *limeColValues[] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL}; - size_t limeColExpectedLengths[] = {32,32,32,32,4,4,8}; - size_t limeColLengths[] = {0,0,0,0,0,0,0}; - - /* check all the children nodes to retrieve all information we may get */ - while (peerNodeChildren!=NULL && peerUriIndex<128) { - if (!xmlStrcmp(peerNodeChildren->name, (const xmlChar *)"uri")) { /* found a peer an URI node, get the content */ - peerUri[peerUriIndex] = xmlNodeListGetString(cacheXml, peerNodeChildren->xmlChildrenNode, 1); - peerUriIndex++; - } - - if (!xmlStrcmp(peerNodeChildren->name, (const xmlChar *)"ZID")) { - peerZIDString = xmlNodeListGetString(cacheXml, peerNodeChildren->xmlChildrenNode, 1); - bctbx_str_to_uint8(peerZID, peerZIDString, 24); - - peerZIDFound=1; - } - - for (i=0; i<3; i++) { - if (!xmlStrcmp(peerNodeChildren->name, (const xmlChar *)zrtpColNames[i])) { - nodeContent = xmlNodeListGetString(cacheXml, peerNodeChildren->xmlChildrenNode, 1); - zrtpColValues[i] = (uint8_t *)bctbx_malloc(zrtpColExpectedLengths[i]); - bctbx_str_to_uint8(zrtpColValues[i], nodeContent, 2*zrtpColExpectedLengths[i]); - zrtpColLengths[i]=zrtpColExpectedLengths[i]; - } - } - - for (i=0; i<7; i++) { - if (!xmlStrcmp(peerNodeChildren->name, (const xmlChar *)limeColNames[i])) { - nodeContent = xmlNodeListGetString(cacheXml, peerNodeChildren->xmlChildrenNode, 1); - limeColValues[i] = (uint8_t *)bctbx_malloc(limeColExpectedLengths[i]); - bctbx_str_to_uint8(limeColValues[i], nodeContent, 2*limeColExpectedLengths[i]); - limeColLengths[i]=limeColExpectedLengths[i]; - } - } - - peerNodeChildren = peerNodeChildren->next; - xmlFree(nodeContent); - nodeContent=NULL; - } - - if (peerUriIndex>0 && peerZIDFound==1) { /* we found at least an uri in this peer node, extract the keys all other informations */ - /* retrieve all the informations */ - - /* loop over all the uri founds */ - for (i=0; inext; - } - } - } - } -} - - -static void linphone_core_zrtp_cache_db_init(LinphoneCore *lc) { int ret; const char *errmsg; sqlite3 *db; linphone_core_zrtp_cache_close(lc); - ret = _linphone_sqlite3_open(lc->zrtp_cache_db_file, &db); + ret = _linphone_sqlite3_open(fileName, &db); if (ret != SQLITE_OK) { errmsg = sqlite3_errmsg(db); - ms_error("Error in the opening zrtp_cache_db_file(%s): %s.\n", lc->zrtp_cache_db_file, errmsg); + ms_error("Error in the opening zrtp_cache_db_file(%s): %s.\n", fileName, errmsg); sqlite3_close(db); lc->zrtp_cache_db=NULL; return; } - ret = bzrtp_initCache((void *)db); /* this may perform an update, check return value */ + ret = ms_zrtp_initCache((void *)db); /* this may perform an update, check return value */ - if (ret == BZRTP_CACHE_SETUP || ret == BZRTP_CACHE_UPDATE) { + if (ret == MSZRTP_CACHE_SETUP || ret == MSZRTP_CACHE_UPDATE) { /* After updating schema, database need to be closed/reopenned */ sqlite3_close(db); - _linphone_sqlite3_open(lc->zrtp_cache_db_file, &db); + _linphone_sqlite3_open(fileName, &db); + } else if(ret != 0) { /* something went wrong */ + ms_error("Zrtp cache failed to initialise(returned -%x), run cacheless", -ret); + sqlite3_close(db); + lc->zrtp_cache_db = NULL; + return; } + /* everything ok, set the db pointer into core */ lc->zrtp_cache_db = db; - - if (ret == BZRTP_CACHE_SETUP && lc->zrtp_secrets_cache != NULL) { - /* we just created the db and we have an old XML version of the cache : migrate */ - linphone_core_zrtp_cache_migration(lc); - } -} -#else /* SQLITE_STORAGE_ENABLED */ -static void linphone_core_zrtp_cache_db_init(LinphoneCore *lc) { - ms_warning("Tried to open %s as zrtp_cache_db_file, but SQLITE_STORAGE is not enabled", lc->zrtp_cache_db_file); -} #endif /* SQLITE_STORAGE_ENABLED */ - -void linphone_core_set_zrtp_cache_database_path(LinphoneCore *lc, const char *path) { - if (lc->zrtp_cache_db_file){ - ms_free(lc->zrtp_cache_db_file); - lc->zrtp_cache_db_file = NULL; - } - if (path) { - lc->zrtp_cache_db_file = ms_strdup(path); - linphone_core_zrtp_cache_db_init(lc); - } } void linphone_core_set_user_certificates_path(LinphoneCore *lc, const char* path){ diff --git a/coreapi/linphonecore_jni.cc b/coreapi/linphonecore_jni.cc index 99141e869..c3083289d 100644 --- a/coreapi/linphonecore_jni.cc +++ b/coreapi/linphonecore_jni.cc @@ -216,6 +216,10 @@ extern "C" void Java_org_linphone_core_LinphoneCoreFactoryImpl_setLogCollectionP ReleaseStringUTFChars(env, jpath, path); } +extern "C" jlong Java_org_linphone_core_LinphoneCoreFactoryImpl_createErrorInfoNative(JNIEnv* env, jobject thiz){ + return (jlong)linphone_factory_create_error_info(linphone_factory_get()); +} + extern "C" jobjectArray Java_org_linphone_core_LinphoneCoreFactoryImpl_getAllDialPlanNative(JNIEnv *env, jobject thiz) { LinphoneDialPlan *countries; jclass addr_class = env->FindClass("org/linphone/core/DialPlanImpl"); @@ -3419,23 +3423,27 @@ extern "C" jboolean Java_org_linphone_core_LinphoneCallLogImpl_wasConference(JNI /* CallStats */ extern "C" jint Java_org_linphone_core_LinphoneCallStatsImpl_getMediaType(JNIEnv *env, jobject thiz, jlong stats_ptr) { - return (jint)((LinphoneCallStats *)stats_ptr)->type; + LinphoneCallStats *stats = (LinphoneCallStats *)stats_ptr; + return (jint)linphone_call_stats_get_type(stats); } extern "C" jint Java_org_linphone_core_LinphoneCallStatsImpl_getIceState(JNIEnv *env, jobject thiz, jlong stats_ptr) { - return (jint)((LinphoneCallStats *)stats_ptr)->ice_state; + LinphoneCallStats *stats = (LinphoneCallStats *)stats_ptr; + return (jint)linphone_call_stats_get_ice_state(stats); } extern "C" jfloat Java_org_linphone_core_LinphoneCallStatsImpl_getDownloadBandwidth(JNIEnv *env, jobject thiz, jlong stats_ptr) { - return (jfloat)((LinphoneCallStats *)stats_ptr)->download_bandwidth; + LinphoneCallStats *stats = (LinphoneCallStats *)stats_ptr; + return (jfloat)linphone_call_stats_get_download_bandwidth(stats); } extern "C" jfloat Java_org_linphone_core_LinphoneCallStatsImpl_getUploadBandwidth(JNIEnv *env, jobject thiz, jlong stats_ptr) { - return (jfloat)((LinphoneCallStats *)stats_ptr)->upload_bandwidth; + LinphoneCallStats *stats = (LinphoneCallStats *)stats_ptr; + return (jfloat)linphone_call_stats_get_upload_bandwidth(stats); } extern "C" jfloat Java_org_linphone_core_LinphoneCallStatsImpl_getSenderLossRate(JNIEnv *env, jobject thiz, jlong stats_ptr) { - const LinphoneCallStats *stats = (LinphoneCallStats *)stats_ptr; + LinphoneCallStats *stats = (LinphoneCallStats *)stats_ptr; return (jfloat) linphone_call_stats_get_sender_loss_rate(stats); } extern "C" jfloat Java_org_linphone_core_LinphoneCallStatsImpl_getReceiverLossRate(JNIEnv *env, jobject thiz, jlong stats_ptr) { - const LinphoneCallStats *stats = (LinphoneCallStats *)stats_ptr; + LinphoneCallStats *stats = (LinphoneCallStats *)stats_ptr; return (jfloat) linphone_call_stats_get_receiver_loss_rate(stats); } extern "C" jfloat Java_org_linphone_core_LinphoneCallStatsImpl_getSenderInterarrivalJitter(JNIEnv *env, jobject thiz, jlong stats_ptr) { @@ -3447,28 +3455,31 @@ extern "C" jfloat Java_org_linphone_core_LinphoneCallStatsImpl_getReceiverIntera return (jfloat) linphone_call_stats_get_receiver_interarrival_jitter(stats); } extern "C" jfloat Java_org_linphone_core_LinphoneCallStatsImpl_getRoundTripDelay(JNIEnv *env, jobject thiz, jlong stats_ptr) { - return (jfloat)((LinphoneCallStats *)stats_ptr)->round_trip_delay; + LinphoneCallStats *stats = (LinphoneCallStats *)stats_ptr; + return (jfloat)linphone_call_stats_get_round_trip_delay(stats); } extern "C" jlong Java_org_linphone_core_LinphoneCallStatsImpl_getLatePacketsCumulativeNumber(JNIEnv *env, jobject thiz, jlong stats_ptr) { LinphoneCallStats *stats = (LinphoneCallStats *)stats_ptr; return (jlong) linphone_call_stats_get_late_packets_cumulative_number(stats); } extern "C" jfloat Java_org_linphone_core_LinphoneCallStatsImpl_getJitterBufferSize(JNIEnv *env, jobject thiz, jlong stats_ptr) { - return (jfloat)((LinphoneCallStats *)stats_ptr)->jitter_stats.jitter_buffer_size_ms; + LinphoneCallStats *stats = (LinphoneCallStats *)stats_ptr; + return (jfloat)linphone_call_stats_get_jitter_buffer_size_ms(stats); } extern "C" jfloat Java_org_linphone_core_LinphoneCallStatsImpl_getLocalLossRate(JNIEnv *env, jobject thiz,jlong stats_ptr) { - const LinphoneCallStats *stats = (LinphoneCallStats *)stats_ptr; - return stats->local_loss_rate; + LinphoneCallStats *stats = (LinphoneCallStats *)stats_ptr; + return linphone_call_stats_get_local_loss_rate(stats); } extern "C" jfloat Java_org_linphone_core_LinphoneCallStatsImpl_getLocalLateRate(JNIEnv *env, jobject thiz, jlong stats_ptr) { - const LinphoneCallStats *stats = (LinphoneCallStats *)stats_ptr; - return stats->local_late_rate; + LinphoneCallStats *stats = (LinphoneCallStats *)stats_ptr; + return linphone_call_stats_get_local_late_rate(stats); } extern "C" jint Java_org_linphone_core_LinphoneCallStatsImpl_getIpFamilyOfRemote(JNIEnv *env, jobject thiz, jlong stats_ptr) { - return (jint) ((LinphoneCallStats *)stats_ptr)->rtp_remote_family; + LinphoneCallStats *stats = (LinphoneCallStats *)stats_ptr; + return (jint) linphone_call_stats_get_ip_family_of_remote(stats); } /*payloadType*/ @@ -3505,7 +3516,7 @@ JNIEXPORT jobject JNICALL Java_org_linphone_core_LinphoneCallImpl_getStats(JNIEn ,jlong ptr, jint type) { LinphoneCall *call=(LinphoneCall*)ptr; LinphoneJavaBindings *ljb = (LinphoneJavaBindings *) linphone_core_get_user_data(linphone_call_get_core(call)); - const LinphoneCallStats *stats = linphone_call_get_stats(call, (LinphoneStreamType)type); + LinphoneCallStats *stats = linphone_call_get_stats(call, (LinphoneStreamType)type); return stats ? env->NewObject(ljb->callStatsClass, ljb->callStatsId, (jlong)stats) : NULL; } @@ -3691,6 +3702,18 @@ extern "C" jboolean Java_org_linphone_core_LinphoneCallImpl_mediaInProgress( JNI return (jboolean) linphone_call_media_in_progress((LinphoneCall*)ptr); } +extern "C" void Java_org_linphone_core_LinphoneCallImpl_declineWithErrorInfo( JNIEnv* env + ,jobject thiz + ,jlong callptr, jlong eiptr) { + linphone_call_decline_with_error_info((LinphoneCall*)callptr, (LinphoneErrorInfo*)eiptr); +} + +extern "C" void Java_org_linphone_core_LinphoneCallImpl_terminateWithErrorInfo( JNIEnv* env + ,jobject thiz + ,jlong callptr, jlong eiptr) { + linphone_call_terminate_with_error_info((LinphoneCall*)callptr, (LinphoneErrorInfo*)eiptr); +} + //LinphoneFriend extern "C" jlong Java_org_linphone_core_LinphoneFriendImpl_newLinphoneFriend(JNIEnv* env ,jobject thiz @@ -4175,7 +4198,11 @@ extern "C" void Java_org_linphone_core_LinphoneFriendImpl_finalize(JNIEnv* env ,jobject thiz ,jlong ptr) { LinphoneFriend *lfriend=(LinphoneFriend*)ptr; + jobject wref = (jobject)linphone_friend_get_user_data(lfriend); linphone_friend_set_user_data(lfriend,NULL); + if (wref){ + env->DeleteWeakGlobalRef(wref); + } linphone_friend_unref(lfriend); } @@ -4711,7 +4738,11 @@ extern "C" void Java_org_linphone_core_LinphoneChatMessageImpl_setListener(JNIEn extern "C" void Java_org_linphone_core_LinphoneChatMessageImpl_unref(JNIEnv* env ,jobject thiz ,jlong ptr) { + jobject wref = (jobject)linphone_chat_message_get_user_data((LinphoneChatMessage*)ptr); linphone_chat_message_set_user_data((LinphoneChatMessage*)ptr, NULL); + if (wref){ + env->DeleteWeakGlobalRef(wref); + } linphone_chat_message_unref((LinphoneChatMessage*)ptr); } @@ -5984,6 +6015,13 @@ extern "C" void Java_org_linphone_core_LpConfigImpl_sync(JNIEnv *env, jobject th lp_config_sync(lp); } +extern "C" void Java_org_linphone_core_LpConfigImpl_loadXmlFile(JNIEnv *env, jobject thiz, jlong lpc, jstring jfilename) { + const char *filename = GetStringUTFChars(env, jfilename); + LpConfig *lp = (LpConfig *)lpc; + linphone_config_load_from_xml_file(lp, filename, NULL, NULL); + ReleaseStringUTFChars(env, jfilename, filename); +} + extern "C" void Java_org_linphone_core_LpConfigImpl_delete(JNIEnv *env, jobject thiz, jlong lpc) { LpConfig *lp = (LpConfig *)lpc; lp_config_destroy(lp); @@ -7317,6 +7355,86 @@ JNIEXPORT jstring JNICALL Java_org_linphone_core_ErrorInfoImpl_getPhrase(JNIEnv return tmp ? env->NewStringUTF(tmp) : NULL; } +/* + * Class: org_linphone_core_ErrorInfoImpl + * Method: getProtocol + * Signature: (J)Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL Java_org_linphone_core_ErrorInfoImpl_getProtocol(JNIEnv *env, jobject jobj, jlong ei){ + const char *tmp=linphone_error_info_get_protocol((const LinphoneErrorInfo*)ei); + return tmp ? env->NewStringUTF(tmp) : NULL; +} + +/* + * Class: org_linphone_core_ErrorInfoImpl + * Method: getSubErrorInfo + * Signature: (J)J + */ +JNIEXPORT jlong JNICALL Java_org_linphone_core_ErrorInfoImpl_getSubErrorInfo(JNIEnv *env, jobject jobj, jlong ei){ + return (jlong)linphone_error_info_get_sub_error_info((LinphoneErrorInfo*)ei); +} + +/* + * Class: org_linphone_core_ErrorInfoImpl + * Method: setReason + * Signature: (JI) + */ +JNIEXPORT void JNICALL Java_org_linphone_core_ErrorInfoImpl_setReason(JNIEnv *env, jobject jobj, jlong ei, jint reason){ + linphone_error_info_set_reason((LinphoneErrorInfo*)ei, (LinphoneReason)reason); +} + +/* + * Class: org_linphone_core_ErrorInfoImpl + * Method: getProtocolCode + * Signature: (JI) + */ +JNIEXPORT void JNICALL Java_org_linphone_core_ErrorInfoImpl_setProtocolCode(JNIEnv *env, jobject jobj, jlong ei, jint code){ + return linphone_error_info_set_protocol_code((LinphoneErrorInfo*)ei, code); +} + +/* + * Class: org_linphone_core_ErrorInfoImpl + * Method: setPhrase + * Signature: (JLjava/lang/String;) + */ +JNIEXPORT void JNICALL Java_org_linphone_core_ErrorInfoImpl_setPhrase(JNIEnv *env, jobject jobj, jlong ei, jstring phrase){ + const char *tmp = GetStringUTFChars(env,phrase); + linphone_error_info_set_phrase((LinphoneErrorInfo*)ei, tmp); + if (phrase) ReleaseStringUTFChars(env, phrase, tmp); +} + +/* + * Class: org_linphone_core_ErrorInfoImpl + * Method: setProtocol + * Signature: (JLjava/lang/String;) + */ +JNIEXPORT void JNICALL Java_org_linphone_core_ErrorInfoImpl_setProtocol(JNIEnv *env, jobject jobj, jlong ei, jstring protocol){ + const char *tmp = GetStringUTFChars(env, protocol); + linphone_error_info_set_protocol((LinphoneErrorInfo*)ei, tmp); + if (protocol) ReleaseStringUTFChars(env, protocol, tmp); +} + + +/* + * Class: org_linphone_core_ErrorInfoImpl + * Method: setWarnings + * Signature: (JLjava/lang/String;) + */ +JNIEXPORT void JNICALL Java_org_linphone_core_ErrorInfoImpl_setWarnings(JNIEnv *env, jobject jobj, jlong ei, jstring warnings){ + const char *tmp = GetStringUTFChars(env, warnings); + linphone_error_info_set_warnings((LinphoneErrorInfo*)ei, tmp); + if (warnings) ReleaseStringUTFChars(env, warnings, tmp); +} + +/* + * Class: org_linphone_core_ErrorInfoImpl + * Method: setSubErrorInfo + * Signature: (JLjava/lang/String;) + */ +JNIEXPORT void JNICALL Java_org_linphone_core_ErrorInfoImpl_setSubErrorInfo(JNIEnv *env, jobject jobj, jlong ei, jlong sub_ei){ + linphone_error_info_set_sub_error_info((LinphoneErrorInfo*)ei, (LinphoneErrorInfo*)sub_ei); +} + /* * Class: org_linphone_core_ErrorInfoImpl * Method: getDetails diff --git a/coreapi/lpconfig.c b/coreapi/lpconfig.c index 1e55d02d9..12d14b65b 100644 --- a/coreapi/lpconfig.c +++ b/coreapi/lpconfig.c @@ -27,6 +27,7 @@ #include "private.h" #include "bctoolbox/vfs.h" #include "belle-sip/object.h" +#include "xml2lpc.h" #include #include @@ -402,7 +403,7 @@ LpConfig * linphone_config_new_from_buffer(const char *buffer){ static int _linphone_config_init_from_files(LinphoneConfig *lpconfig, const char *config_filename, const char *factory_config_filename) { lpconfig->g_bctbx_vfs = bctbx_vfs_get_default(); - + if (config_filename!=NULL){ if(ortp_file_exist(config_filename) == 0) { lpconfig->filename=lp_realpath(config_filename, NULL); @@ -480,6 +481,34 @@ LinphoneStatus linphone_config_read_file(LpConfig *lpconfig, const char *filenam return -1; } +char* linphone_config_load_from_xml_file(LpConfig *lpc, const char *filename, void* lc, void* ctx) { + xml2lpc_context *context = NULL; + char* path = lp_realpath(filename, NULL); + char* error_msg = NULL; + + if (path) { + int result = -1; + context = xml2lpc_context_new(ctx, lc); + result = xml2lpc_set_xml_file(context, path); + if (result == 0) { + result = xml2lpc_convert(context, lpc); + if (result == 0) { + // if the remote provisioning added a proxy config and none was set before, set it + if (lp_config_has_section(lpc, "proxy_0") && lp_config_get_int(lpc, "sip", "default_proxy", -1) == -1){ + lp_config_set_int(lpc, "sip", "default_proxy", 0); + } + lp_config_sync(lpc); + } else { + error_msg = "xml to lpc failed"; + } + } else { + error_msg = "invalid xml"; + } + } + if (context) xml2lpc_context_destroy(context); + return error_msg; +} + void lp_item_set_value(LpItem *item, const char *value){ if (item->value != value) { char *prev_value=item->value; @@ -758,14 +787,14 @@ void linphone_config_set_skip_flag_for_section(LpConfig *lpconfig, const char *s void lp_item_write(LpItem *item, LpConfig *lpconfig){ int ret =-1 ; - if (item->is_comment){ + if (item->is_comment){ ret =bctbx_file_fprintf(lpconfig->pFile, 0, "%s\n",item->value); } else if (item->value && item->value[0] != '\0' ){ ret =bctbx_file_fprintf(lpconfig->pFile, 0, "%s=%s\n",item->key,item->value); } - + else { ms_warning("Not writing item %s to file, it is empty", item->key); } @@ -792,7 +821,7 @@ void lp_section_write(LpSection *sec,LpConfig *lpconfig){ bctbx_list_for_each2(sec->items, (void (*)(void*, void*))lp_item_write, (void *)lpconfig); if (bctbx_file_fprintf(lpconfig->pFile, 0, "\n")< 0) ms_error("lp_section_write : write error"); - + } LinphoneStatus linphone_config_sync(LpConfig *lpconfig){ @@ -811,7 +840,7 @@ LinphoneStatus linphone_config_sync(LpConfig *lpconfig){ lpconfig->readonly = TRUE; return -1; } - + bctbx_list_for_each2(lpconfig->sections,(void (*)(void *,void*))lp_section_write,(void *)lpconfig); bctbx_file_close(pFile); @@ -1018,7 +1047,7 @@ LinphoneStatus linphone_config_read_relative_file(const LpConfig *lpconfig, cons if(bctbx_file_read(pFile, data, 1, (off_t)max_length) < 0){ ms_error("%s could not be loaded.", realfilepath); goto err; - + } bctbx_file_close(pFile); @@ -1109,7 +1138,7 @@ int linphone_config_has_entry(const LpConfig *lpconfig, const char *section, con return lp_section_find_item(sec,key) != NULL; } else return FALSE; - + } BELLE_SIP_INSTANCIATE_VPTR( diff --git a/coreapi/misc.c b/coreapi/misc.c index 1216559ef..9f5f216a3 100644 --- a/coreapi/misc.c +++ b/coreapi/misc.c @@ -548,19 +548,19 @@ static void linphone_core_add_local_ice_candidates(LinphoneCall *call, int famil if ((ice_check_list_state(audio_cl) != ICL_Completed) && (ice_check_list_candidates_gathered(audio_cl) == FALSE)) { ice_add_local_candidate(audio_cl, "host", family, addr, call->media_ports[call->main_audio_stream_index].rtp_port, 1, NULL); ice_add_local_candidate(audio_cl, "host", family, addr, call->media_ports[call->main_audio_stream_index].rtcp_port, 2, NULL); - call->stats[LINPHONE_CALL_STATS_AUDIO].ice_state = LinphoneIceStateInProgress; + call->audio_stats->ice_state = LinphoneIceStateInProgress; } if (linphone_core_video_enabled(call->core) && (video_cl != NULL) && (ice_check_list_state(video_cl) != ICL_Completed) && (ice_check_list_candidates_gathered(video_cl) == FALSE)) { ice_add_local_candidate(video_cl, "host", family, addr, call->media_ports[call->main_video_stream_index].rtp_port, 1, NULL); ice_add_local_candidate(video_cl, "host", family, addr, call->media_ports[call->main_video_stream_index].rtcp_port, 2, NULL); - call->stats[LINPHONE_CALL_STATS_VIDEO].ice_state = LinphoneIceStateInProgress; + call->video_stats->ice_state = LinphoneIceStateInProgress; } if (call->params->realtimetext_enabled && (text_cl != NULL) && (ice_check_list_state(text_cl) != ICL_Completed) && (ice_check_list_candidates_gathered(text_cl) == FALSE)) { ice_add_local_candidate(text_cl, "host", family, addr, call->media_ports[call->main_text_stream_index].rtp_port, 1, NULL); ice_add_local_candidate(text_cl, "host", family, addr, call->media_ports[call->main_text_stream_index].rtcp_port, 2, NULL); - call->stats[LINPHONE_CALL_STATS_TEXT].ice_state = LinphoneIceStateInProgress; + call->text_stats->ice_state = LinphoneIceStateInProgress; } } @@ -697,14 +697,14 @@ void linphone_call_update_ice_state_in_call_stats(LinphoneCall *call) { if (ice_check_list_state(audio_check_list) == ICL_Completed) { switch (ice_check_list_selected_valid_candidate_type(audio_check_list)) { case ICT_HostCandidate: - call->stats[LINPHONE_CALL_STATS_AUDIO].ice_state = LinphoneIceStateHostConnection; + call->audio_stats->ice_state = LinphoneIceStateHostConnection; break; case ICT_ServerReflexiveCandidate: case ICT_PeerReflexiveCandidate: - call->stats[LINPHONE_CALL_STATS_AUDIO].ice_state = LinphoneIceStateReflexiveConnection; + call->audio_stats->ice_state = LinphoneIceStateReflexiveConnection; break; case ICT_RelayedCandidate: - call->stats[LINPHONE_CALL_STATS_AUDIO].ice_state = LinphoneIceStateRelayConnection; + call->audio_stats->ice_state = LinphoneIceStateRelayConnection; break; case ICT_CandidateInvalid: case ICT_CandidateTypeMax: @@ -712,22 +712,22 @@ void linphone_call_update_ice_state_in_call_stats(LinphoneCall *call) { break; } } else { - call->stats[LINPHONE_CALL_STATS_AUDIO].ice_state = LinphoneIceStateFailed; + call->audio_stats->ice_state = LinphoneIceStateFailed; } - }else call->stats[LINPHONE_CALL_STATS_AUDIO].ice_state = LinphoneIceStateNotActivated; + }else call->audio_stats->ice_state = LinphoneIceStateNotActivated; if (call->params->has_video && (video_check_list != NULL)) { if (ice_check_list_state(video_check_list) == ICL_Completed) { switch (ice_check_list_selected_valid_candidate_type(video_check_list)) { case ICT_HostCandidate: - call->stats[LINPHONE_CALL_STATS_VIDEO].ice_state = LinphoneIceStateHostConnection; + call->video_stats->ice_state = LinphoneIceStateHostConnection; break; case ICT_ServerReflexiveCandidate: case ICT_PeerReflexiveCandidate: - call->stats[LINPHONE_CALL_STATS_VIDEO].ice_state = LinphoneIceStateReflexiveConnection; + call->video_stats->ice_state = LinphoneIceStateReflexiveConnection; break; case ICT_RelayedCandidate: - call->stats[LINPHONE_CALL_STATS_VIDEO].ice_state = LinphoneIceStateRelayConnection; + call->video_stats->ice_state = LinphoneIceStateRelayConnection; break; case ICT_CandidateInvalid: case ICT_CandidateTypeMax: @@ -735,22 +735,22 @@ void linphone_call_update_ice_state_in_call_stats(LinphoneCall *call) { break; } } else { - call->stats[LINPHONE_CALL_STATS_VIDEO].ice_state = LinphoneIceStateFailed; + call->video_stats->ice_state = LinphoneIceStateFailed; } - }else call->stats[LINPHONE_CALL_STATS_VIDEO].ice_state = LinphoneIceStateNotActivated; + }else call->video_stats->ice_state = LinphoneIceStateNotActivated; if (call->params->realtimetext_enabled && (text_check_list != NULL)) { if (ice_check_list_state(text_check_list) == ICL_Completed) { switch (ice_check_list_selected_valid_candidate_type(text_check_list)) { case ICT_HostCandidate: - call->stats[LINPHONE_CALL_STATS_TEXT].ice_state = LinphoneIceStateHostConnection; + call->text_stats->ice_state = LinphoneIceStateHostConnection; break; case ICT_ServerReflexiveCandidate: case ICT_PeerReflexiveCandidate: - call->stats[LINPHONE_CALL_STATS_TEXT].ice_state = LinphoneIceStateReflexiveConnection; + call->text_stats->ice_state = LinphoneIceStateReflexiveConnection; break; case ICT_RelayedCandidate: - call->stats[LINPHONE_CALL_STATS_TEXT].ice_state = LinphoneIceStateRelayConnection; + call->text_stats->ice_state = LinphoneIceStateRelayConnection; break; case ICT_CandidateInvalid: case ICT_CandidateTypeMax: @@ -758,28 +758,28 @@ void linphone_call_update_ice_state_in_call_stats(LinphoneCall *call) { break; } } else { - call->stats[LINPHONE_CALL_STATS_TEXT].ice_state = LinphoneIceStateFailed; + call->text_stats->ice_state = LinphoneIceStateFailed; } - }else call->stats[LINPHONE_CALL_STATS_TEXT].ice_state = LinphoneIceStateNotActivated; + }else call->text_stats->ice_state = LinphoneIceStateNotActivated; } else if (session_state == IS_Running) { - call->stats[LINPHONE_CALL_STATS_AUDIO].ice_state = LinphoneIceStateInProgress; + call->audio_stats->ice_state = LinphoneIceStateInProgress; if (call->params->has_video && (video_check_list != NULL)) { - call->stats[LINPHONE_CALL_STATS_VIDEO].ice_state = LinphoneIceStateInProgress; + call->video_stats->ice_state = LinphoneIceStateInProgress; } if (call->params->realtimetext_enabled && (text_check_list != NULL)) { - call->stats[LINPHONE_CALL_STATS_TEXT].ice_state = LinphoneIceStateInProgress; + call->text_stats->ice_state = LinphoneIceStateInProgress; } } else { - call->stats[LINPHONE_CALL_STATS_AUDIO].ice_state = LinphoneIceStateFailed; + call->audio_stats->ice_state = LinphoneIceStateFailed; if (call->params->has_video && (video_check_list != NULL)) { - call->stats[LINPHONE_CALL_STATS_VIDEO].ice_state = LinphoneIceStateFailed; + call->video_stats->ice_state = LinphoneIceStateFailed; } if (call->params->realtimetext_enabled && (text_check_list != NULL)) { - call->stats[LINPHONE_CALL_STATS_TEXT].ice_state = LinphoneIceStateFailed; + call->text_stats->ice_state = LinphoneIceStateFailed; } } ms_message("Call [%p] New ICE state: audio: [%s] video: [%s] text: [%s]", call, - linphone_ice_state_to_string(call->stats[LINPHONE_CALL_STATS_AUDIO].ice_state), linphone_ice_state_to_string(call->stats[LINPHONE_CALL_STATS_VIDEO].ice_state), linphone_ice_state_to_string(call->stats[LINPHONE_CALL_STATS_TEXT].ice_state)); + linphone_ice_state_to_string(call->audio_stats->ice_state), linphone_ice_state_to_string(call->video_stats->ice_state), linphone_ice_state_to_string(call->text_stats->ice_state)); } void linphone_call_stop_ice_for_inactive_streams(LinphoneCall *call, SalMediaDescription *desc) { @@ -1780,26 +1780,6 @@ void linphone_call_update_ice_from_remote_media_description(LinphoneCall *call, } } - - -/* Functions to mainpulate the LinphoneIntRange structure */ - -int linphone_int_range_get_min(const LinphoneIntRange *range) { - return range->min; -} - -int linphone_int_range_get_max(const LinphoneIntRange *range) { - return range->max; -} - -void linphone_int_range_set_min(LinphoneIntRange *range, int min) { - range->min = min; -} - -void linphone_int_range_set_max(LinphoneIntRange *range, int max) { - range->max = max; -} - void linphone_core_report_call_log(LinphoneCore *lc, LinphoneCallLog *call_log){ bool_t call_logs_sqlite_db_found = FALSE; @@ -1835,4 +1815,52 @@ void linphone_core_report_early_failed_call(LinphoneCore *lc, LinphoneCallDir di linphone_call_log_unref(l); } +/* Functions to mainpulate the LinphoneRange structure */ +BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(LinphoneRange); + +BELLE_SIP_INSTANCIATE_VPTR(LinphoneRange, belle_sip_object_t, + NULL, // destroy + NULL, // clone + NULL, // marshal + FALSE +); + +LinphoneRange *linphone_range_new() { + LinphoneRange *range = belle_sip_object_new(LinphoneRange); + range->min = 0; + range->max = 0; + return range; +} + +LinphoneRange* linphone_range_ref(LinphoneRange* range) { + return (LinphoneRange*) belle_sip_object_ref(range); +} + +void linphone_range_unref(LinphoneRange* range) { + belle_sip_object_unref(range); +} + +void *linphone_range_get_user_data(const LinphoneRange *range) { + return range->user_data; +} + +void linphone_range_set_user_data(LinphoneRange *range, void *data) { + range->user_data = data; +} + +int linphone_range_get_min(const LinphoneRange *range) { + return range->min; +} + +int linphone_range_get_max(const LinphoneRange *range) { + return range->max; +} + +void linphone_range_set_min(LinphoneRange *range, int min) { + range->min = min; +} + +void linphone_range_set_max(LinphoneRange *range, int max) { + range->max = max; +} \ No newline at end of file diff --git a/coreapi/private.h b/coreapi/private.h index b0c9d47e9..d6e83f35c 100644 --- a/coreapi/private.h +++ b/coreapi/private.h @@ -139,8 +139,10 @@ struct _LinphoneCallParams{ PayloadType *audio_codec; /*audio codec currently in use */ PayloadType *video_codec; /*video codec currently in use */ PayloadType *text_codec; /*text codec currently in use */ - MSVideoSize sent_vsize; /* Size of the video currently being sent */ - MSVideoSize recv_vsize; /* Size of the video currently being received */ + MSVideoSize sent_vsize; /* DEPRECATED: Size of the video currently being sent */ + MSVideoSize recv_vsize; /* DEPRECATED: Size of the video currently being received */ + LinphoneVideoDefinition *sent_vdef; /* Definition of the video currently being sent */ + LinphoneVideoDefinition *recv_vdef; /* Definition of the video currrently being received */ float received_fps,sent_fps; int down_bw; int up_bw; @@ -349,7 +351,9 @@ struct _LinphoneCall{ OrtpEvQueue *videostream_app_evq; OrtpEvQueue *textstream_app_evq; CallCallbackObj nextVideoFrameDecoded; - LinphoneCallStats stats[3]; /* audio, video, text */ + LinphoneCallStats *audio_stats; + LinphoneCallStats *video_stats; + LinphoneCallStats *text_stats; #ifdef BUILD_UPNP UpnpSession *upnp_session; #endif //BUILD_UPNP @@ -390,7 +394,7 @@ struct _LinphoneCall{ bool_t broken; /*set to TRUE when the call is in broken state due to network disconnection or transport */ bool_t defer_notify_incoming; bool_t need_localip_refresh; - + bool_t reinvite_on_cancel_response_requested; bool_t non_op_error; /*set when the LinphoneErrorInfo was set at higher level than sal*/ @@ -410,7 +414,9 @@ void linphone_call_notify_info_message_received(LinphoneCall *call, const Linpho LinphoneCall * linphone_call_new_outgoing(struct _LinphoneCore *lc, LinphoneAddress *from, LinphoneAddress *to, const LinphoneCallParams *params, LinphoneProxyConfig *cfg); LinphoneCall * linphone_call_new_incoming(struct _LinphoneCore *lc, LinphoneAddress *from, LinphoneAddress *to, SalOp *op); -void linphone_call_set_new_params(LinphoneCall *call, const LinphoneCallParams *params); +void _linphone_call_set_new_params(LinphoneCall *call, const LinphoneCallParams *params); +LINPHONE_PUBLIC void linphone_call_set_params(LinphoneCall *call, const LinphoneCallParams *params); +LINPHONE_PUBLIC const LinphoneCallParams * linphone_call_get_params(LinphoneCall *call); void linphone_call_set_state(LinphoneCall *call, LinphoneCallState cstate, const char *message); void linphone_call_set_contact_op(LinphoneCall* call); void linphone_call_set_compatible_incoming_call_parameters(LinphoneCall *call, SalMediaDescription *md); @@ -927,6 +933,8 @@ typedef struct video_config{ const char **cams; MSVideoSize vsize; MSVideoSize preview_vsize; /*is 0,0 if no forced preview size is set, in which case vsize field above is used.*/ + LinphoneVideoDefinition *vdef; + LinphoneVideoDefinition *preview_vdef; float fps; bool_t capture; bool_t show_local; @@ -1054,7 +1062,7 @@ struct _LinphoneCore struct _EchoTester *ect; LinphoneTaskList hooks; /*tasks periodically executed in linphone_core_iterate()*/ LinphoneConference *conf_ctx; - char* zrtp_secrets_cache; /**< zrtp xml filename cache : obsolete, use zrtp_cache_db now, kept to allow cache migration */ + char* zrtp_secrets_cache; /**< zrtp cache filename */ char* user_certificates_path; LinphoneVideoPolicy video_policy; time_t network_last_check; @@ -1089,7 +1097,6 @@ struct _LinphoneCore char *chat_db_file; char *logs_db_file; char *friends_db_file; - char *zrtp_cache_db_file; #ifdef SQLITE_STORAGE_ENABLED sqlite3 *zrtp_cache_db; /**< zrtp sqlite cache, used by both zrtp and lime */ sqlite3 *db; @@ -1294,6 +1301,7 @@ LinphoneContent * linphone_content_copy(const LinphoneContent *ref); SalBodyHandler *sal_body_handler_from_content(const LinphoneContent *content); 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); void linphone_event_unpublish(LinphoneEvent *lev); @@ -1487,9 +1495,10 @@ struct _LinphoneAccountCreator { /* Misc */ char *language; /**< User language */ char *activation_code; /**< Account validation code */ + char *domain; /**< Domain */ + LinphoneTransportType transport; /**< Transport used */ /* Deprecated */ - char *domain; char *route; }; @@ -1517,12 +1526,19 @@ LINPHONE_PUBLIC LinphoneAccountCreatorStatus linphone_account_creator_is_account LINPHONE_PUBLIC LinphoneAccountCreatorStatus linphone_account_creator_create_account_linphone(LinphoneAccountCreator *creator); /** - * Send an XML-RPC request to activate a Linphone account. + * 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 @@ -1720,6 +1736,76 @@ BELLE_SIP_DECLARE_VPTR_NO_EXPORT(LinphoneImEncryptionEngine); LINPHONE_PUBLIC LinphoneImEncryptionEngine *linphone_im_encryption_engine_new(LinphoneCore *lc); +struct _LinphoneRange { + belle_sip_object_t base; + void *user_data; + int min; + int max; +}; + +BELLE_SIP_DECLARE_VPTR_NO_EXPORT(LinphoneRange); + +LinphoneRange *linphone_range_new(void); + +struct _LinphoneTransports { + belle_sip_object_t base; + void *user_data; + int udp_port; /**< SIP/UDP port */ + int tcp_port; /**< SIP/TCP port */ + int dtls_port; /**< SIP/DTLS port */ + int tls_port; /**< SIP/TLS port */ +}; + +BELLE_SIP_DECLARE_VPTR_NO_EXPORT(LinphoneTransports); + +LINPHONE_PUBLIC LinphoneTransports *linphone_transports_new(void); + +struct _LinphoneVideoActivationPolicy { + belle_sip_object_t base; + void *user_data; + bool_t automatically_initiate; /**config, "proxy", "contact_parameters", NULL) : NULL; const char *contact_uri_params = lc ? lp_config_get_default_string(lc->config, "proxy", "contact_uri_parameters", NULL) : NULL; const char *refkey = lc ? lp_config_get_default_string(lc->config, "proxy", "refkey", NULL) : NULL; + cfg->lc = lc; cfg->expires = lc ? lp_config_get_default_int(lc->config, "proxy", "reg_expires", 3600) : 3600; cfg->reg_sendregister = lc ? lp_config_get_default_int(lc->config, "proxy", "reg_sendregister", 1) : 1; cfg->dial_prefix = dial_prefix ? ms_strdup(dial_prefix) : NULL; diff --git a/coreapi/quality_reporting.c b/coreapi/quality_reporting.c index dc3678689..acce0cacb 100644 --- a/coreapi/quality_reporting.c +++ b/coreapi/quality_reporting.c @@ -592,21 +592,29 @@ static float reporting_rand(float t){ void linphone_reporting_on_rtcp_update(LinphoneCall *call, SalStreamType stats_type) { reporting_session_report_t * report = call->log->reporting.reports[stats_type]; reporting_content_metrics_t * metrics = NULL; - LinphoneCallStats stats = call->stats[stats_type]; + LinphoneCallStats *stats = NULL; mblk_t *block = NULL; int report_interval; + if (stats_type == 0) { + stats = call->audio_stats; + } else if (stats_type == 1) { + stats = call->video_stats; + } else { + stats = call->text_stats; + } + if (! media_report_enabled(call,stats_type)) return; report_interval = linphone_proxy_config_get_quality_reporting_interval(call->dest_proxy); - if (stats.updated == LINPHONE_CALL_STATS_RECEIVED_RTCP_UPDATE) { + if (stats->updated == LINPHONE_CALL_STATS_RECEIVED_RTCP_UPDATE) { metrics = &report->remote_metrics; - block = stats.received_rtcp; - } else if (stats.updated == LINPHONE_CALL_STATS_SENT_RTCP_UPDATE) { + block = stats->received_rtcp; + } else if (stats->updated == LINPHONE_CALL_STATS_SENT_RTCP_UPDATE) { metrics = &report->local_metrics; - block = stats.sent_rtcp; + block = stats->sent_rtcp; } do{ if (rtcp_is_XR(block) && (rtcp_XR_get_block_type(block) == RTCP_XR_VOIP_METRICS)){ @@ -617,7 +625,7 @@ void linphone_reporting_on_rtcp_update(LinphoneCall *call, SalStreamType stats_t // for local mos rating, we'll use the quality indicator directly // because rtcp XR might not be enabled - if (stats.updated == LINPHONE_CALL_STATS_RECEIVED_RTCP_UPDATE){ + if (stats->updated == LINPHONE_CALL_STATS_RECEIVED_RTCP_UPDATE){ metrics->quality_estimates.moslq = (rtcp_XR_voip_metrics_get_mos_lq(block)==127) ? 127 : rtcp_XR_voip_metrics_get_mos_lq(block) / 10.f; metrics->quality_estimates.moscq = (rtcp_XR_voip_metrics_get_mos_cq(block)==127) ? diff --git a/coreapi/remote_provisioning.c b/coreapi/remote_provisioning.c index 0bb40595b..daadf4163 100644 --- a/coreapi/remote_provisioning.c +++ b/coreapi/remote_provisioning.c @@ -18,6 +18,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "private.h" #include "xml2lpc.h" +#include "linphone/lpconfig.h" #define XML2LPC_CALLBACK_BUFFER_SIZE 1024 @@ -34,27 +35,8 @@ static void xml2lpc_callback(void *ctx, xml2lpc_log_level level, const char *fmt } static void linphone_remote_provisioning_apply(LinphoneCore *lc, const char *xml) { - xml2lpc_context *context = xml2lpc_context_new(xml2lpc_callback, lc); - int result = xml2lpc_set_xml_string(context, xml); - char * error_msg = NULL; - if (result == 0) { - LpConfig * lpc = linphone_core_get_config(lc); - result = xml2lpc_convert(context, lpc); - if (result == 0) { - // if the remote provisioning added a proxy config and none was set before, set it - if (lp_config_has_section(lpc, "proxy_0") && lp_config_get_int(lpc, "sip", "default_proxy", -1) == -1){ - lp_config_set_int(lpc, "sip", "default_proxy", 0); - } - lp_config_sync(lpc); + char* error_msg = linphone_config_load_from_xml_file(linphone_core_get_config(lc), xml, lc, xml2lpc_callback); - } else { - error_msg = "xml to lpc failed"; - } - } else { - error_msg = "invalid xml"; - } - - xml2lpc_context_destroy(context); linphone_configuring_terminated(lc ,error_msg ? LinphoneConfiguringFailed : LinphoneConfiguringSuccessful , error_msg); diff --git a/coreapi/video_definition.c b/coreapi/video_definition.c new file mode 100644 index 000000000..57329d154 --- /dev/null +++ b/coreapi/video_definition.c @@ -0,0 +1,114 @@ +/* +linphone +Copyright (C) 2010-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 "linphone/factory.h" +#include "linphone/video_definition.h" + +#include "private.h" + + +static void linphone_video_definition_destroy(LinphoneVideoDefinition *vdef) { + if (vdef->name) bctbx_free(vdef->name); +} + +BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(LinphoneVideoDefinition); + +BELLE_SIP_INSTANCIATE_VPTR(LinphoneVideoDefinition, belle_sip_object_t, + (belle_sip_object_destroy_t)linphone_video_definition_destroy, + NULL, // clone + NULL, // marshal + TRUE +); + + +LinphoneVideoDefinition * linphone_video_definition_new(unsigned int width, unsigned int height, const char *name) { + LinphoneVideoDefinition *vdef = belle_sip_object_new(LinphoneVideoDefinition); + vdef->width = width; + vdef->height = height; + if (name == NULL) { + vdef->name = bctbx_strdup_printf("%ux%u", width, height); + } else { + vdef->name = bctbx_strdup(name); + } + return vdef; +} + +LinphoneVideoDefinition * linphone_video_definition_ref(LinphoneVideoDefinition *vdef) { + belle_sip_object_ref(vdef); + return vdef; +} + +void linphone_video_definition_unref(LinphoneVideoDefinition *vdef) { + belle_sip_object_unref(vdef); +} + +void *linphone_video_definition_get_user_data(const LinphoneVideoDefinition *vdef) { + return vdef->user_data; +} + +void linphone_video_definition_set_user_data(LinphoneVideoDefinition *vdef, void *ud) { + vdef->user_data = ud; +} + +LinphoneVideoDefinition * linphone_video_definition_clone(const LinphoneVideoDefinition *vdef) { + return linphone_video_definition_new(linphone_video_definition_get_width(vdef), linphone_video_definition_get_height(vdef), linphone_video_definition_get_name(vdef)); +} + +unsigned int linphone_video_definition_get_width(const LinphoneVideoDefinition *vdef) { + return vdef->width; +} + +void linphone_video_definition_set_width(LinphoneVideoDefinition *vdef, unsigned int width) { + vdef->width = width; +} + +unsigned int linphone_video_definition_get_height(const LinphoneVideoDefinition *vdef) { + return vdef->height; +} + +void linphone_video_definition_set_height(LinphoneVideoDefinition *vdef, unsigned int height) { + vdef->height = height; +} + +void linphone_video_definition_set_definition(LinphoneVideoDefinition *vdef, unsigned int width, unsigned int height) { + vdef->width = width; + vdef->height = height; +} + +const char * linphone_video_definition_get_name(const LinphoneVideoDefinition *vdef) { + return vdef->name; +} + +void linphone_video_definition_set_name(LinphoneVideoDefinition *vdef, const char *name) { + if (vdef->name != NULL) bctbx_free(vdef->name); + vdef->name = bctbx_strdup(name); +} + +bool_t linphone_video_definition_equals(const LinphoneVideoDefinition *vdef1, const LinphoneVideoDefinition *vdef2) { + return (((vdef1->width == vdef2->width) && (vdef1->height == vdef2->height)) + || ((vdef1->width == vdef2->height) && (vdef1->height == vdef2->width))); +} + +bool_t linphone_video_definition_strict_equals(const LinphoneVideoDefinition *vdef1, const LinphoneVideoDefinition *vdef2) { + return (vdef1->width == vdef2->width) && (vdef1->height == vdef2->height); +} + +bool_t linphone_video_definition_is_undefined(const LinphoneVideoDefinition *vdef) { + return (vdef->width == 0) || (vdef->height == 0); +} diff --git a/daemon/commands/audio-stream-stats.cc b/daemon/commands/audio-stream-stats.cc index 4845dbb7b..7393b2cdd 100644 --- a/daemon/commands/audio-stream-stats.cc +++ b/daemon/commands/audio-stream-stats.cc @@ -61,5 +61,5 @@ void AudioStreamStatsCommand::exec(Daemon *app, const string& args) { return; } - app->sendResponse(Response(AudioStreamStatsResponse(app, stream->stream, &stream->stats, false).getBody(), Response::Ok)); + app->sendResponse(Response(AudioStreamStatsResponse(app, stream->stream, stream->stats, false).getBody(), Response::Ok)); } diff --git a/daemon/daemon.cc b/daemon/daemon.cc index 01f44e7c4..907972976 100644 --- a/daemon/daemon.cc +++ b/daemon/daemon.cc @@ -141,13 +141,13 @@ DtmfResponse::DtmfResponse(Daemon *daemon, LinphoneCall *call, int dtmf) { } static ostream &printCallStatsHelper(ostream &ostr, const LinphoneCallStats *stats, const string &prefix) { - ostr << prefix << "ICE state: " << ice_state_str[stats->ice_state] << "\n"; - ostr << prefix << "RoundTripDelay: " << stats->round_trip_delay << "\n"; - ostr << prefix << "Jitter: " << stats->jitter_stats.jitter << "\n"; + ostr << prefix << "ICE state: " << ice_state_str[linphone_call_stats_get_ice_state(stats)] << "\n"; + ostr << prefix << "RoundTripDelay: " << linphone_call_stats_get_round_trip_delay(stats) << "\n"; +// ostr << prefix << "Jitter: " << stats->jitter_stats.jitter << "\n"; // ostr << prefix << "MaxJitter: " << stats->jitter_stats.max_jitter << "\n"; // ostr << prefix << "SumJitter: " << stats->jitter_stats.sum_jitter << "\n"; // ostr << prefix << "MaxJitterTs: " << stats->jitter_stats.max_jitter_ts << "\n"; - ostr << prefix << "JitterBufferSizeMs: " << stats->jitter_stats.jitter_buffer_size_ms << "\n"; + ostr << prefix << "JitterBufferSizeMs: " << linphone_call_stats_get_jitter_buffer_size_ms(stats) << "\n"; ostr << prefix << "Received-InterarrivalJitter: " << linphone_call_stats_get_receiver_interarrival_jitter(stats) << "\n"; ostr << prefix << "Received-FractionLost: " << linphone_call_stats_get_receiver_loss_rate(stats) << "\n"; @@ -199,14 +199,14 @@ AudioStreamStatsResponse::AudioStreamStatsResponse(Daemon* daemon, AudioStream* ostr << "Event-type: audio-stream-stats\n"; ostr << "Id: " << daemon->updateAudioStreamId(stream) << "\n"; ostr << "Type: "; - if (stats->type == LINPHONE_CALL_STATS_AUDIO) { + if (linphone_call_stats_get_type(stats) == LINPHONE_CALL_STATS_AUDIO) { ostr << "Audio"; } else { ostr << "Video"; } ostr << "\n"; } else { - prefix = ((stats->type == LINPHONE_CALL_STATS_AUDIO) ? "Audio-" : "Video-"); + prefix = ((linphone_call_stats_get_type(stats) == LINPHONE_CALL_STATS_AUDIO) ? "Audio-" : "Video-"); } printCallStatsHelper(ostr, stats, prefix); @@ -547,9 +547,9 @@ void Daemon::iterateStreamStats() { while (it->second->queue && (NULL != (ev=ortp_ev_queue_get(it->second->queue)))){ OrtpEventType evt=ortp_event_get_type(ev); if (evt == ORTP_EVENT_RTCP_PACKET_RECEIVED || evt == ORTP_EVENT_RTCP_PACKET_EMITTED) { - linphone_call_stats_fill(&it->second->stats, &it->second->stream->ms, ev); + linphone_call_stats_fill(it->second->stats, &it->second->stream->ms, ev); if (mUseStatsEvents) mEventQueue.push(new AudioStreamStatsResponse(this, - it->second->stream, &it->second->stats, true)); + it->second->stream, it->second->stats, true)); } ortp_event_destroy(ev); } diff --git a/daemon/daemon.h b/daemon/daemon.h index 7a23b5587..12a32c358 100644 --- a/daemon/daemon.h +++ b/daemon/daemon.h @@ -191,11 +191,10 @@ private: struct AudioStreamAndOther { AudioStream *stream; OrtpEvQueue *queue; - LinphoneCallStats stats; + LinphoneCallStats *stats; AudioStreamAndOther(AudioStream *as) : stream(as) { queue = ortp_ev_queue_new(); rtp_session_register_event_queue(as->ms.sessions.rtp_session, queue); - memset(&stats, 0, sizeof(stats)); } ~AudioStreamAndOther() { rtp_session_unregister_event_queue(stream->ms.sessions.rtp_session, queue); diff --git a/gtk/incall_view.c b/gtk/incall_view.c index b3055f238..6c7edd939 100644 --- a/gtk/incall_view.c +++ b/gtk/incall_view.c @@ -243,8 +243,10 @@ static const char *upnp_state_to_string(LinphoneUpnpState ice_state){ } static void _refresh_call_stats(GtkWidget *callstats, LinphoneCall *call){ - const LinphoneCallStats *as=linphone_call_get_audio_stats(call); - const LinphoneCallStats *vs=linphone_call_get_video_stats(call); + LinphoneUpnpState upnp_state; + LinphoneIceState ice_state; + LinphoneCallStats *as=linphone_call_get_audio_stats(call); + LinphoneCallStats *vs=linphone_call_get_video_stats(call); const char *audio_media_connectivity = _("Direct or through server"); const char *video_media_connectivity = _("Direct or through server"); const LinphoneCallParams *curparams=linphone_call_get_current_params(call); @@ -256,7 +258,7 @@ static void _refresh_call_stats(GtkWidget *callstats, LinphoneCall *call){ gtk_label_set_markup(GTK_LABEL(linphone_gtk_get_widget(callstats,"rtp_profile")),tmp); g_free(tmp); tmp=g_strdup_printf(_("download: %f\nupload: %f (kbit/s)"), - as->download_bandwidth,as->upload_bandwidth); + linphone_call_stats_get_download_bandwidth(as),linphone_call_stats_get_upload_bandwidth(as)); gtk_label_set_markup(GTK_LABEL(linphone_gtk_get_widget(callstats,"audio_bandwidth_usage")),tmp); g_free(tmp); if (has_video){ @@ -267,7 +269,7 @@ static void _refresh_call_stats(GtkWidget *callstats, LinphoneCall *call){ gtk_label_set_markup(GTK_LABEL(linphone_gtk_get_widget(callstats,"video_size_recv")),size_r); gtk_label_set_markup(GTK_LABEL(linphone_gtk_get_widget(callstats,"video_size_sent")),size_s); - tmp=g_strdup_printf(_("download: %f\nupload: %f (kbit/s)"),vs->download_bandwidth,vs->upload_bandwidth); + tmp=g_strdup_printf(_("download: %f\nupload: %f (kbit/s)"),linphone_call_stats_get_download_bandwidth(vs),linphone_call_stats_get_upload_bandwidth(vs)); g_free(size_r); g_free(size_s); } else { @@ -275,27 +277,33 @@ static void _refresh_call_stats(GtkWidget *callstats, LinphoneCall *call){ } gtk_label_set_markup(GTK_LABEL(linphone_gtk_get_widget(callstats,"video_bandwidth_usage")),tmp); if (tmp) g_free(tmp); - if(as->upnp_state != LinphoneUpnpStateNotAvailable && as->upnp_state != LinphoneUpnpStateIdle) { - audio_media_connectivity = upnp_state_to_string(as->upnp_state); - } else if(as->ice_state != LinphoneIceStateNotActivated) { - audio_media_connectivity = ice_state_to_string(as->ice_state); + upnp_state = linphone_call_stats_get_upnp_state(as); + ice_state = linphone_call_stats_get_ice_state(as); + if(upnp_state != LinphoneUpnpStateNotAvailable && upnp_state != LinphoneUpnpStateIdle) { + audio_media_connectivity = upnp_state_to_string(upnp_state); + } else if(ice_state != LinphoneIceStateNotActivated) { + audio_media_connectivity = ice_state_to_string(ice_state); } gtk_label_set_text(GTK_LABEL(linphone_gtk_get_widget(callstats,"audio_media_connectivity")),audio_media_connectivity); if (has_video){ - if(vs->upnp_state != LinphoneUpnpStateNotAvailable && vs->upnp_state != LinphoneUpnpStateIdle) { - video_media_connectivity = upnp_state_to_string(vs->upnp_state); - } else if(vs->ice_state != LinphoneIceStateNotActivated) { - video_media_connectivity = ice_state_to_string(vs->ice_state); + upnp_state = linphone_call_stats_get_upnp_state(vs); + ice_state = linphone_call_stats_get_ice_state(vs); + if(upnp_state != LinphoneUpnpStateNotAvailable && upnp_state != LinphoneUpnpStateIdle) { + video_media_connectivity = upnp_state_to_string(upnp_state); + } else if(ice_state != LinphoneIceStateNotActivated) { + video_media_connectivity = ice_state_to_string(ice_state); } }else video_media_connectivity=NULL; gtk_label_set_text(GTK_LABEL(linphone_gtk_get_widget(callstats,"video_media_connectivity")),video_media_connectivity); - if (as->round_trip_delay>0){ - tmp=g_strdup_printf(_("%.3f seconds"),as->round_trip_delay); + if (linphone_call_stats_get_round_trip_delay(as)>0){ + tmp=g_strdup_printf(_("%.3f seconds"),linphone_call_stats_get_round_trip_delay(as)); gtk_label_set_text(GTK_LABEL(linphone_gtk_get_widget(callstats,"round_trip_time")),tmp); g_free(tmp); } + linphone_call_stats_unref(as); + linphone_call_stats_unref(vs); } static gboolean refresh_call_stats(GtkWidget *callstats){ diff --git a/gtk/main.c b/gtk/main.c index 394657281..9367c8080 100644 --- a/gtk/main.c +++ b/gtk/main.c @@ -253,8 +253,7 @@ gboolean linphone_gtk_get_audio_assistant_option(void){ static void linphone_gtk_init_liblinphone(const char *config_file, const char *factory_config_file, const char *chat_messages_db_file, - const char *call_logs_db_file, const char *friends_db_file, - const char *zrtp_cache_db_file) { + const char *call_logs_db_file, const char *friends_db_file) { LinphoneCoreVTable vtable={0}; gchar *secrets_file=linphone_gtk_get_config_file(SECRETS_FILE); gchar *user_certificates_dir=linphone_gtk_get_config_file(CERTIFICATES_PATH); @@ -291,7 +290,6 @@ static void linphone_gtk_init_liblinphone(const char *config_file, linphone_core_set_user_agent(the_core,"Linphone", LINPHONE_VERSION); linphone_core_set_waiting_callback(the_core,linphone_gtk_wait,NULL); linphone_core_set_zrtp_secrets_file(the_core,secrets_file); /* XML cache is superseeded by the sqlite one, keep it for migration purpose but it shall be removed in future version */ - if (zrtp_cache_db_file) linphone_core_set_zrtp_cache_database_path(the_core, zrtp_cache_db_file); g_free(secrets_file); linphone_core_set_user_certificates_path(the_core,user_certificates_dir); g_free(user_certificates_dir); @@ -2157,31 +2155,6 @@ static void populate_xdg_data_dirs_envvar(void) { } #define ZRTP_CACHE_CONFIG_FILE ".linphone-zidcache.db" -static char *linphone_gtk_zrtp_cache_get_db_file(const char *filename){ - const int path_max=1024; - char *db_file=NULL; - - db_file=(char *)g_malloc(path_max*sizeof(char)); - if (filename==NULL) filename=ZRTP_CACHE_CONFIG_FILE; - /*try accessing a local file first if exists*/ - if (bctbx_file_exist(ZRTP_CACHE_CONFIG_FILE)==0){ - snprintf(db_file,path_max,"%s",filename); - }else{ -#ifdef _WIN32 - const char *appdata=getenv("APPDATA"); - if (appdata){ - snprintf(db_file,path_max,"%s\\%s",appdata,LINPHONE_CONFIG_DIR); - CreateDirectory(db_file,NULL); - snprintf(db_file,path_max,"%s\\%s\\%s",appdata,LINPHONE_CONFIG_DIR,filename); - } -#else - const char *home=getenv("HOME"); - if (home==NULL) home="."; - snprintf(db_file,path_max,"%s/%s",home,filename); -#endif - } - return db_file; -} int main(int argc, char *argv[]){ char *config_file; @@ -2191,7 +2164,7 @@ int main(int argc, char *argv[]){ const char *icon_name=LINPHONE_ICON_NAME; const char *app_name="Linphone"; LpConfig *factory_config; - char *chat_messages_db_file, *call_logs_db_file, *friends_db_file, *zrtp_cache_db_file; + char *chat_messages_db_file, *call_logs_db_file, *friends_db_file; GError *error=NULL; const char *tmp; const char *resources_dir; @@ -2339,8 +2312,7 @@ core_start: chat_messages_db_file=linphone_gtk_message_storage_get_db_file(NULL); call_logs_db_file = linphone_gtk_call_logs_storage_get_db_file(NULL); friends_db_file = linphone_gtk_friends_storage_get_db_file(NULL); - zrtp_cache_db_file = linphone_gtk_zrtp_cache_get_db_file(NULL); - linphone_gtk_init_liblinphone(config_file, factory_config_file, chat_messages_db_file, call_logs_db_file, friends_db_file, zrtp_cache_db_file); + linphone_gtk_init_liblinphone(config_file, factory_config_file, chat_messages_db_file, call_logs_db_file, friends_db_file); g_free(chat_messages_db_file); g_free(call_logs_db_file); g_free(friends_db_file); diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt index 0534b57b1..54094d903 100644 --- a/include/CMakeLists.txt +++ b/include/CMakeLists.txt @@ -60,6 +60,7 @@ set(HEADER_FILES tunnel.h types.h vcard.h + video_definition.h wrapper_utils.h xmlrpc.h diff --git a/include/linphone/Makefile.am b/include/linphone/Makefile.am index 2aaf58f40..316f9b5e5 100644 --- a/include/linphone/Makefile.am +++ b/include/linphone/Makefile.am @@ -40,6 +40,7 @@ linphone_include_HEADERS=\ tunnel.h \ types.h \ vcard.h \ + video_definition.h \ wrapper_utils.h \ xmlrpc.h \ linphonecore.h \ diff --git a/include/linphone/account_creator.h b/include/linphone/account_creator.h index a4bfca7c4..bf5e5fc5a 100644 --- a/include/linphone/account_creator.h +++ b/include/linphone/account_creator.h @@ -277,16 +277,31 @@ LINPHONE_PUBLIC const char * linphone_account_creator_get_email(const LinphoneAc * Set the domain. * @param[in] creator LinphoneAccountCreator object * @param[in] domain The domain to set - * @return LinphoneAccountCreatorStatusRequestOk if everything is OK, or a specific error otherwise. + * @return LinphoneAccountCreatorDomainOk if everything is OK, or a specific error otherwise. **/ -LINPHONE_DEPRECATED LINPHONE_PUBLIC LinphoneAccountCreatorStatus linphone_account_creator_set_domain(LinphoneAccountCreator *creator, const char *domain); +LINPHONE_PUBLIC LinphoneAccountCreatorDomainStatus linphone_account_creator_set_domain(LinphoneAccountCreator *creator, const char *domain); /** * Get the domain. * @param[in] creator LinphoneAccountCreator object * @return The domain of the LinphoneAccountCreator **/ -LINPHONE_DEPRECATED LINPHONE_PUBLIC const char * linphone_account_creator_get_domain(const LinphoneAccountCreator *creator); +LINPHONE_PUBLIC const char * linphone_account_creator_get_domain(const LinphoneAccountCreator *creator); + +/** + * Set Transport + * @param[in] creator LinphoneAccountCreator object + * @param[in] transport The transport to set + * @return LinphoneAccountCreatorTransportOk if everything is OK, or a specific error otherwise. +**/ +LINPHONE_PUBLIC LinphoneAccountCreatorTransportStatus linphone_account_creator_set_transport(LinphoneAccountCreator *creator, LinphoneTransportType transport); + +/** + * get Transport + * @param[in] creator LinphoneAccountCreator object + * @return The transport of LinphoneAccountCreator +**/ +LINPHONE_PUBLIC LinphoneTransportType linphone_account_creator_get_transport(const LinphoneAccountCreator *creator); /** * Set the route. @@ -491,12 +506,19 @@ LINPHONE_PUBLIC void linphone_account_creator_cbs_set_update_account(LinphoneAcc /************************** End Account Creator Cbs **************************/ +/** + * Create and configure a proxy config and a authentication info for an account creator + * @param[in] creator LinphoneAccountCreator object + * @return A LinphoneProxyConfig object if successful, NULL otherwise +**/ +LINPHONE_PUBLIC LinphoneProxyConfig * linphone_account_creator_create_proxy_config(const LinphoneAccountCreator *creator); + /** * Configure an account (create a proxy config and authentication info for it). * @param[in] creator LinphoneAccountCreator object * @return A LinphoneProxyConfig object if successful, NULL otherwise - **/ -LINPHONE_PUBLIC LinphoneProxyConfig * linphone_account_creator_configure(const LinphoneAccountCreator *creator); +**/ +LINPHONE_DEPRECATED LINPHONE_PUBLIC LinphoneProxyConfig * linphone_account_creator_configure(const LinphoneAccountCreator *creator); /** * @} diff --git a/include/linphone/call.h b/include/linphone/call.h index ca697b91c..bef02c5a1 100644 --- a/include/linphone/call.h +++ b/include/linphone/call.h @@ -203,9 +203,12 @@ LINPHONE_PUBLIC LinphoneStatus linphone_call_take_preview_snapshot(LinphoneCall **/ LINPHONE_PUBLIC LinphoneReason linphone_call_get_reason(const LinphoneCall *call); + /** * Returns full details about call errors or termination reasons. -**/ + * @param call LinphoneCall object on which we want the information error + * @return LinphoneErrorInfo object holding the reason error. + */ LINPHONE_PUBLIC const LinphoneErrorInfo *linphone_call_get_error_info(const LinphoneCall *call); /** @@ -376,8 +379,16 @@ LINPHONE_PUBLIC LinphoneStatus linphone_call_resume(LinphoneCall *call); * Terminates a call. * @param[in] call LinphoneCall object * @return 0 on success, -1 on failure +**/LINPHONE_PUBLIC LinphoneStatus linphone_call_terminate(LinphoneCall *call); + + +/** + * Terminates a call. + * @param[in] call LinphoneCall object + * @param[in] ei LinphoneErrorInfo + * @return 0 on success, -1 on failure **/ -LINPHONE_PUBLIC LinphoneStatus linphone_call_terminate(LinphoneCall *call); +LINPHONE_PUBLIC LinphoneStatus linphone_call_terminate_with_error_info(LinphoneCall *call, const LinphoneErrorInfo *ei); /** * Redirect the specified call to the given redirect URI. @@ -395,6 +406,14 @@ LINPHONE_PUBLIC LinphoneStatus linphone_call_redirect(LinphoneCall *call, const **/ LINPHONE_PUBLIC LinphoneStatus linphone_call_decline(LinphoneCall * call, LinphoneReason reason); +/** + * Decline a pending incoming call, with a LinphoneErrorInfo object. + * @param[in] call A LinphoneCall object that must be in the IncomingReceived state + * @param[in] ei LinphoneErrorInfo containing more information on the call rejection. + * @return 0 on success, -1 on failure + */ +LINPHONE_PUBLIC int linphone_call_decline_with_error_info(LinphoneCall * call, const LinphoneErrorInfo *ei); + /** * Accept an incoming call. * @@ -801,9 +820,8 @@ LINPHONE_PUBLIC bool_t linphone_call_media_in_progress(LinphoneCall *call); /** * Call generic OpenGL render for a given call. * @param call The call. - * @is_preview If true the preview is displayed otherwise it's the input stream. */ -LINPHONE_PUBLIC void linphone_call_ogl_render(LinphoneCall *call, bool_t is_preview); +LINPHONE_PUBLIC void linphone_call_ogl_render(const LinphoneCall *call); @@ -815,17 +833,17 @@ LINPHONE_PUBLIC void linphone_call_ogl_render(LinphoneCall *call, bool_t is_prev LINPHONE_PUBLIC LinphoneStatus linphone_call_send_info_message(LinphoneCall *call, const LinphoneInfoMessage *info); /** - * Return call statistics for a particular stream type. + * Return a copy of the call statistics for a particular stream type. * @param call the call * @param type the stream type **/ -LINPHONE_PUBLIC const LinphoneCallStats *linphone_call_get_stats(LinphoneCall *call, LinphoneStreamType type); +LINPHONE_PUBLIC LinphoneCallStats *linphone_call_get_stats(LinphoneCall *call, LinphoneStreamType type); -LINPHONE_PUBLIC const LinphoneCallStats *linphone_call_get_audio_stats(LinphoneCall *call); +LINPHONE_PUBLIC LinphoneCallStats *linphone_call_get_audio_stats(LinphoneCall *call); -LINPHONE_PUBLIC const LinphoneCallStats *linphone_call_get_video_stats(LinphoneCall *call); +LINPHONE_PUBLIC LinphoneCallStats *linphone_call_get_video_stats(LinphoneCall *call); -LINPHONE_PUBLIC const LinphoneCallStats *linphone_call_get_text_stats(LinphoneCall *call); +LINPHONE_PUBLIC LinphoneCallStats *linphone_call_get_text_stats(LinphoneCall *call); /** * Add a listener in order to be notified of LinphoneCall events. Once an event is received, registred LinphoneCallCbs are diff --git a/include/linphone/call_params.h b/include/linphone/call_params.h index 838292583..3299b2242 100644 --- a/include/linphone/call_params.h +++ b/include/linphone/call_params.h @@ -132,12 +132,20 @@ LINPHONE_PUBLIC LinphonePrivacyMask linphone_call_params_get_privacy(const Linph */ LINPHONE_PUBLIC float linphone_call_params_get_received_framerate(const LinphoneCallParams *cp); +/** + * Get the definition of the received video. + * @param[in] cp LinphoneCallParams object + * @return The received LinphoneVideoDefinition + */ +LINPHONE_PUBLIC const LinphoneVideoDefinition * linphone_call_params_get_received_video_definition(const LinphoneCallParams *cp); + /** * Get the size of the video that is received. * @param[in] cp LinphoneCallParams object * @return The received video size or MS_VIDEO_SIZE_UNKNOWN if not available. + * @deprecated Use linphone_call_params_get_received_video_definition() instead */ -LINPHONE_PUBLIC MSVideoSize linphone_call_params_get_received_video_size(const LinphoneCallParams *cp); +LINPHONE_PUBLIC LINPHONE_DEPRECATED MSVideoSize linphone_call_params_get_received_video_size(const LinphoneCallParams *cp); /** * Get the path for the audio recording of the call. @@ -160,12 +168,20 @@ LINPHONE_PUBLIC const char * linphone_call_params_get_rtp_profile(const Linphone */ LINPHONE_PUBLIC float linphone_call_params_get_sent_framerate(const LinphoneCallParams *cp); +/** + * Get the definition of the sent video. + * @param[in] cp LinphoneCallParams object + * @return The sent LinphoneVideoDefinition + */ +LINPHONE_PUBLIC const LinphoneVideoDefinition * linphone_call_params_get_sent_video_definition(const LinphoneCallParams *cp); + /** * Gets the size of the video that is sent. * @param[in] cp LinphoneCalParams object * @return The sent video size or MS_VIDEO_SIZE_UNKNOWN if not available. + * @deprecated Use linphone_call_params_get_sent_video_definition() instead */ -LINPHONE_PUBLIC MSVideoSize linphone_call_params_get_sent_video_size(const LinphoneCallParams *cp); +LINPHONE_PUBLIC LINPHONE_DEPRECATED MSVideoSize linphone_call_params_get_sent_video_size(const LinphoneCallParams *cp); /** * Get the session name of the media session (ie in SDP). diff --git a/include/linphone/call_stats.h b/include/linphone/call_stats.h index 11044c1c6..ff2074dba 100644 --- a/include/linphone/call_stats.h +++ b/include/linphone/call_stats.h @@ -40,33 +40,34 @@ extern "C" { #define LINPHONE_CALL_STATS_PERIODICAL_UPDATE (1 << 2) /**< Every seconds LinphoneCallStats object has been updated */ /** - * The LinphoneCallStats objects carries various statistic informations regarding quality of audio or video streams. - * - * To receive these informations periodically and as soon as they are computed, the application is invited to place a #LinphoneCoreCallStatsUpdatedCb callback in the LinphoneCoreVTable structure - * it passes for instantiating the LinphoneCore object (see linphone_core_new() ). - * - * At any time, the application can access last computed statistics using linphone_call_get_audio_stats() or linphone_call_get_video_stats(). + * Increment refcount. + * @param[in] stats LinphoneCallStats object + * @ingroup misc **/ -struct _LinphoneCallStats { - LinphoneStreamType type; /**< Type of the stream which the stats refer to */ - jitter_stats_t jitter_stats; /**sub_ei. + * @param[in] appended_ei LinphoneErrorInfo to append + */ +LINPHONE_PUBLIC void linphone_error_info_set_sub_error_info(LinphoneErrorInfo *ei, LinphoneErrorInfo *appended_ei); +/** + * Assign reason LinphoneReason to a LinphoneErrorInfo object. + * @param[in] ei ErrorInfo object + * @param[in] reason reason from LinphoneReason enum + */ LINPHONE_PUBLIC void linphone_error_info_set_reason(LinphoneErrorInfo *ei, LinphoneReason reason); +/** + * Assign protocol name to a LinphoneErrorInfo object. + * @param[in] ei ErrorInfo object + * @param[in] proto the protocol name + */ +LINPHONE_PUBLIC void linphone_error_info_set_protocol(LinphoneErrorInfo *ei, const char *proto); + +/** + * Assign protocol code to a LinphoneErrorInfo object. + * @param[in] ei ErrorInfo object + * @param[in] code the protocol code + */ +LINPHONE_PUBLIC void linphone_error_info_set_protocol_code(LinphoneErrorInfo *ei, int code); + +/** + * Assign phrase to a LinphoneErrorInfo object. + * @param[in] ei ErrorInfo object + * @param[in] phrase the phrase explaining the error + */ +LINPHONE_PUBLIC void linphone_error_info_set_phrase(LinphoneErrorInfo *ei, const char *phrase); + +/** + * Assign warnings to a LinphoneErrorInfo object. + * @param[in] ei ErrorInfo object + * @param[in] phrase the warnings + */ +LINPHONE_PUBLIC void linphone_error_info_set_warnings(LinphoneErrorInfo *ei, const char *warnings); + /** * @} */ diff --git a/include/linphone/factory.h b/include/linphone/factory.h index fae018c94..33a509e7c 100644 --- a/include/linphone/factory.h +++ b/include/linphone/factory.h @@ -125,6 +125,30 @@ LINPHONE_PUBLIC LinphoneCallCbs * linphone_factory_create_call_cbs(const Linphon */ LINPHONE_PUBLIC LinphoneVcard *linphone_factory_create_vcard(LinphoneFactory *factory); +/** + * Create a LinphoneVideoDefinition from a given width and height + * @param[in] factory LinphoneFactory singleton object + * @param[in] width The width of the created video definition + * @param[in] height The height of the created video definition + * @return A new LinphoneVideoDefinition object + */ +LINPHONE_PUBLIC LinphoneVideoDefinition * linphone_factory_create_video_definition(const LinphoneFactory *factory, unsigned int width, unsigned int height); + +/** + * Create a LinphoneVideoDefinition from a given standard definition name + * @param[in] factory LinphoneFactory singleton object + * @param[in] name The standard definition name of the video definition to create + * @return A new LinphoneVideoDefinition object + */ +LINPHONE_PUBLIC LinphoneVideoDefinition * linphone_factory_create_video_definition_from_name(const LinphoneFactory *factory, const char *name); + +/** + * Get the list of standard video definitions supported by Linphone. + * @param[in] factory LinphoneFactory singleton object + * @return \bctbx_list{LinphoneVideoDefinition} + */ +LINPHONE_PUBLIC const bctbx_list_t * linphone_factory_get_supported_video_definitions(const LinphoneFactory *factory); + /** * Get the top directory where the resources are located. * @param[in] factory LinphoneFactory object @@ -210,6 +234,33 @@ LINPHONE_PUBLIC const char * linphone_factory_get_msplugins_dir(LinphoneFactory */ LINPHONE_PUBLIC void linphone_factory_set_msplugins_dir(LinphoneFactory *factory, const char *path); +/** + * Creates an object LinphoneErrorInfo. + * @param[in] factory LinphoneFactory object + * @return LinphoneErrorInfo object. + */ +LINPHONE_PUBLIC LinphoneErrorInfo *linphone_factory_create_error_info(LinphoneFactory *factory); + +/** + * Creates an object LinphoneRange. + * @param[in] factory LinphoneFactory object + * @return LinphoneRange object. + */ +LINPHONE_PUBLIC LinphoneRange *linphone_factory_create_range(LinphoneFactory *factory); + +/** + * Creates an object LinphoneTransports. + * @param[in] factory LinphoneFactory object + * @return LinphoneTransports object. + */ +LINPHONE_PUBLIC LinphoneTransports *linphone_factory_create_transports(LinphoneFactory *factory); + +/** + * Creates an object LinphoneVideoActivationPolicy. + * @param[in] factory LinphoneFactory object + * @return LinphoneVideoActivationPolicy object. + */ +LINPHONE_PUBLIC LinphoneVideoActivationPolicy *linphone_factory_create_video_activation_policy(LinphoneFactory *factory); /** * @} */ diff --git a/include/linphone/lpconfig.h b/include/linphone/lpconfig.h index d178dab2d..72b06213d 100644 --- a/include/linphone/lpconfig.h +++ b/include/linphone/lpconfig.h @@ -82,6 +82,16 @@ LINPHONE_PUBLIC LinphoneConfig * linphone_config_new_with_factory(const char *co */ LINPHONE_PUBLIC LinphoneStatus linphone_config_read_file(LinphoneConfig *lpconfig, const char *filename); +/** + * Reads a xml config file and fill the LinphoneConfig with the read config dynamic values. + * @ingroup misc + * @param lpconfig The LinphoneConfig object to fill with the content of the file + * @param filename The filename of the config file to read to fill the LinphoneConfig + * @param lc LinphoneCore to share with xml2lpc + * @param ctx The context given to xml2lpc callback + */ +LINPHONE_PUBLIC char* linphone_config_load_from_xml_file(LpConfig *lpc, const char *filename, void* lc, void* ctx); + /** * Retrieves a configuration item as a string, given its section, key, and default value. * @@ -198,7 +208,7 @@ LINPHONE_PUBLIC int linphone_config_has_entry(const LinphoneConfig *lpconfig, co * @param[in] key **/ LINPHONE_PUBLIC void linphone_config_clean_entry(LinphoneConfig *lpconfig, const char *section, const char *key); - + /** * Returns the list of sections' names in the LinphoneConfig. * @param[in] lpconfig The LinphoneConfig object diff --git a/include/linphone/misc.h b/include/linphone/misc.h index cb27cbe54..1c05c2dc6 100644 --- a/include/linphone/misc.h +++ b/include/linphone/misc.h @@ -167,6 +167,68 @@ LINPHONE_PUBLIC LinphoneReason linphone_error_code_to_reason(int err); */ LINPHONE_PUBLIC int linphone_reason_to_error_code(LinphoneReason reason); +/** + * Increment refcount. + * @param[in] range LinphoneRange object + * @ingroup misc +**/ +LINPHONE_PUBLIC LinphoneRange *linphone_range_ref(LinphoneRange *range); + +/** + * Decrement refcount and possibly free the object. + * @param[in] range LinphoneRange object + * @ingroup misc +**/ +LINPHONE_PUBLIC void linphone_range_unref(LinphoneRange *range); + +/** + * Gets the user data in the LinphoneRange object + * @param[in] range the LinphoneRange + * @return the user data + * @ingroup misc +*/ +LINPHONE_PUBLIC void *linphone_range_get_user_data(const LinphoneRange *range); + +/** + * Sets the user data in the LinphoneRange object + * @param[in] range the LinphoneRange object + * @param[in] data the user data + * @ingroup misc +*/ +LINPHONE_PUBLIC void linphone_range_set_user_data(LinphoneRange *range, void *data); + +/** + * Gets the lower value of the range + * @param[in] range a LinphoneRange + * @return The lower value + * @ingroup misc + */ +LINPHONE_PUBLIC int linphone_range_get_min(const LinphoneRange *range); + +/** + * Gets the higher value of the range + * @param[in] range a LinphoneRange + * @return The higher value + * @ingroup misc + */ +LINPHONE_PUBLIC int linphone_range_get_max(const LinphoneRange *range); + +/** + * Sets the lower value of the range + * @param[in] range a LinphoneRange + * @param[in] min the value to set + * @ingroup misc + */ +LINPHONE_PUBLIC void linphone_range_set_min(LinphoneRange *range, int min); + +/** + * Sets the higher value of the range + * @param[in] range a LinphoneRange + * @param[in] max the value to set + * @ingroup misc + */ +LINPHONE_PUBLIC void linphone_range_set_max(LinphoneRange *range, int max); + #ifdef __cplusplus } diff --git a/include/linphone/types.h b/include/linphone/types.h index 70e80ae8b..2fd84800b 100644 --- a/include/linphone/types.h +++ b/include/linphone/types.h @@ -117,6 +117,24 @@ typedef enum _LinphoneAccountCreatorActivationCodeStatus { LinphoneAccountCreatorActivationCodeStatusInvalidCharacters /**< Contain invalid characters */ } LinphoneAccountCreatorActivationCodeStatus; +/** + * Enum describing Domain checking + * @ingroup account_creator +**/ +typedef enum _LinphoneAccountCreatorDomainStatus { + LinphoneAccountCreatorDomainOk, /**< Domain ok */ + LinphoneAccountCreatorDomainInvalid /**< Domain invalid */ +} LinphoneAccountCreatorDomainStatus; + +/** + * Enum describing Transport checking + * @ingroup account_creator +**/ +typedef enum _LinphoneAccountCreatorTransportStatus { + LinphoneAccountCreatorTransportOk, /**< Transport ok */ + LinphoneAccountCreatorTransportUnsupported /**< Transport invalid */ +} LinphoneAccountCreatorTransportStatus; + /** * Enum describing the status of server request. * @ingroup account_creator_request @@ -182,8 +200,8 @@ typedef enum _LinphoneAddressFamily { * @ingroup call_control **/ typedef enum _LinphoneAudioRoute { - LinphoneAudioRouteEarpiece = MSAudioRouteEarpiece, - LinphoneAudioRouteSpeaker = MSAudioRouteSpeaker + LinphoneAudioRouteEarpiece, + LinphoneAudioRouteSpeaker } LinphoneAudioRoute; /** @@ -972,7 +990,8 @@ typedef struct _LinphoneRingtonePlayer LinphoneRingtonePlayer; * Linphone core SIP transport ports. * Special values #LC_SIP_TRANSPORT_RANDOM, #LC_SIP_TRANSPORT_RANDOM, #LC_SIP_TRANSPORT_DONTBIND can be used. * Use with #linphone_core_set_sip_transports - * @ingroup initializing + * @deprecated + * @donotwrap */ typedef struct _LinphoneSipTransports { int udp_port; /**< SIP/UDP port */ @@ -981,6 +1000,14 @@ typedef struct _LinphoneSipTransports { int tls_port; /**< SIP/TLS port */ } LinphoneSipTransports; +/** + * Linphone core SIP transport ports. + * Special values #LC_SIP_TRANSPORT_RANDOM, #LC_SIP_TRANSPORT_RANDOM, #LC_SIP_TRANSPORT_DONTBIND can be used. + * Use with #linphone_core_set_sip_transports + * @ingroup initializing + */ +typedef struct _LinphoneTransports LinphoneTransports; + /** * Old name of LinphoneSipTransports * @deprecated @@ -1105,9 +1132,17 @@ typedef enum _LinphoneUpnpState { */ typedef struct _LinphoneVcard LinphoneVcard; +/** + * The LinphoneVideoDefinition object represents a video definition, eg. its width and its height. + * @ingroup media_parameters + */ +typedef struct _LinphoneVideoDefinition LinphoneVideoDefinition; + /** * Structure describing policy regarding video streams establishments. * @ingroup media_parameters + * @deprecated + * @donotwrap **/ typedef struct _LinphoneVideoPolicy { bool_t automatically_initiate; /** * The format of the configuration file is a .ini like format: * - sections are defined in [] * - each section contains a sequence of key=value pairs. - * + * * Example: * [sound] * echocanceler=1 @@ -47,7 +47,7 @@ public interface LpConfig { * @param value the value of the setting */ void setInt(String section, String key, int value); - + /** * Sets an float config item * @param section the section in the lpconfig @@ -80,7 +80,7 @@ public interface LpConfig { * @param max the max of the range */ void setIntRange(String section, String key, int min, int max); - + /** * Gets a int from the config * @param section the section in the lpconfig @@ -89,7 +89,7 @@ public interface LpConfig { * @return the value of the setting or the default value if not set */ int getInt(String section, String key, int defaultValue); - + /** * Gets a float from the config * @param section the section in the lpconfig @@ -98,7 +98,7 @@ public interface LpConfig { * @return the value of the setting or the default value if not set */ float getFloat(String section, String key, float defaultValue); - + /** * Gets a boolean from the config * @param section the section in the lpconfig @@ -107,7 +107,7 @@ public interface LpConfig { * @return the value of the setting or the default value if not set */ boolean getBool(String section, String key, boolean defaultValue); - + /** * Gets a string from the config * @param section the section in the lpconfig @@ -116,7 +116,7 @@ public interface LpConfig { * @return the value of the setting or the default value if not set */ String getString(String section, String key, String defaultValue); - + /** * Gets a int range from the config * @param section the section in the lpconfig @@ -129,4 +129,10 @@ public interface LpConfig { * Synchronize LpConfig with file */ void sync(); + + /** + * Load the value of the given xml file + * @param fileName the name of the xml file + */ + void loadXmlFile(String fileName); } diff --git a/java/impl/org/linphone/core/ErrorInfoImpl.java b/java/impl/org/linphone/core/ErrorInfoImpl.java index e9b6bd5f3..f49bfdcfb 100644 --- a/java/impl/org/linphone/core/ErrorInfoImpl.java +++ b/java/impl/org/linphone/core/ErrorInfoImpl.java @@ -1,41 +1,102 @@ package org.linphone.core; public class ErrorInfoImpl implements ErrorInfo { - private Reason mReason; - private int mCode; - private String mPhrase; - private String mDetails; + protected long mNativePtr; + + private native void ref(long nativePtr); + private native void unref(long nativePtr); private native int getReason(long nativePtr); + private native String getProtocol(long nativePtr); private native int getProtocolCode(long nativePtr); private native String getPhrase(long nativePtr); - private native String getDetails(long nativePtr); + private native String getWarnings(long nativePtr); + private native long getSubErrorInfo(long nativePtr); + + private native void setReason(long nativePtr, int reason); + private native void setProtocol(long nativePtr, String proto); + private native void setProtocolCode(long nativePtr, int code); + private native void setPhrase(long nativePtr, String phrase); + private native void setWarnings(long nativePtr, String warnings); + private native void setSubErrorInfo(long nativePtr, long other_nativePtr); + + public ErrorInfoImpl(long nativePtr, boolean ownsRef){ + if (!ownsRef) ref(nativePtr); + mNativePtr = nativePtr; + } public ErrorInfoImpl(long nativePtr){ - mReason=Reason.fromInt(getReason(nativePtr)); - mCode=getProtocolCode(nativePtr); - mPhrase=getPhrase(nativePtr); - mDetails=getDetails(nativePtr); + ref(nativePtr); + mNativePtr = nativePtr; } @Override public Reason getReason() { - return mReason; + return Reason.fromInt(getReason(mNativePtr)); + } + + @Override + public String getProtocol() { + return getProtocol(mNativePtr); } @Override public int getProtocolCode() { - return mCode; + return getProtocolCode(mNativePtr); } @Override public String getPhrase() { - return mPhrase; + return getPhrase(mNativePtr); + } + + @Override + public String getWarnings(){ + return getWarnings(mNativePtr); + } + + @Override + public ErrorInfo getSubErrorInfo(){ + long sub_ei = getSubErrorInfo(mNativePtr); + return sub_ei != 0 ? new ErrorInfoImpl(sub_ei, false) : null; + } + + + @Override + public void setReason(Reason reason) { + setReason(mNativePtr, reason.mValue); + } + + @Override + public void setProtocol(String proto) { + setProtocol(mNativePtr, proto); } @Override - public String getDetails() { - return mDetails; + public void setProtocolCode(int code) { + setProtocolCode(mNativePtr, code); } + @Override + public void setPhrase(String phrase) { + setPhrase(mNativePtr, phrase); + } + + @Override + public void setWarnings(String warnings){ + setWarnings(mNativePtr, warnings); + } + + @Override + public void setSubErrorInfo(ErrorInfo ei){ + setSubErrorInfo(mNativePtr, ei != null ? ((ErrorInfoImpl)ei).mNativePtr : 0); + } + + + @Override + public String getDetails() { + return getWarnings(); + } + + } diff --git a/java/impl/org/linphone/core/LinphoneCallImpl.java b/java/impl/org/linphone/core/LinphoneCallImpl.java index c276ce07d..f1338c423 100644 --- a/java/impl/org/linphone/core/LinphoneCallImpl.java +++ b/java/impl/org/linphone/core/LinphoneCallImpl.java @@ -93,20 +93,26 @@ class LinphoneCallImpl implements LinphoneCall { return LinphoneCall.State.fromInt(getState(nativePtr)); } public LinphoneCallParams getCurrentParams() { - return new LinphoneCallParamsImpl(getCurrentParams(nativePtr)); + synchronized(mCore){ + return new LinphoneCallParamsImpl(getCurrentParams(nativePtr)); + } } public LinphoneCallParams getCurrentParamsCopy(){ return getCurrentParams(); } public LinphoneCallParams getRemoteParams() { - long remoteParamsPtr = getRemoteParams(nativePtr); - if (remoteParamsPtr == 0) { - return null; + synchronized(mCore){ + long remoteParamsPtr = getRemoteParams(nativePtr); + if (remoteParamsPtr == 0) { + return null; + } + return new LinphoneCallParamsImpl(remoteParamsPtr); } - return new LinphoneCallParamsImpl(remoteParamsPtr); } public void enableCamera(boolean enabled) { - enableCamera(nativePtr, enabled); + synchronized(mCore){ + enableCamera(nativePtr, enabled); + } } public boolean cameraEnabled() { return cameraEnabled(nativePtr); @@ -200,7 +206,9 @@ class LinphoneCallImpl implements LinphoneCall { private native void takeSnapshot(long nativePtr, String path); public void takeSnapshot(String path) { - takeSnapshot(nativePtr, path); + synchronized(mCore){ + takeSnapshot(nativePtr, path); + } } private native void zoomVideo(long nativePtr, float factor, float cx, float cy); @@ -211,12 +219,16 @@ class LinphoneCallImpl implements LinphoneCall { private native void startRecording(long nativePtr); @Override public void startRecording() { - startRecording(nativePtr); + synchronized(mCore){ + startRecording(nativePtr); + } } private native void stopRecording(long nativePtr); @Override public void stopRecording() { - stopRecording(nativePtr); + synchronized(mCore){ + stopRecording(nativePtr); + } } private native int getTransferState(long nativePtr); @Override @@ -226,7 +238,9 @@ class LinphoneCallImpl implements LinphoneCall { private native int sendInfoMessage(long callPtr, long msgptr); @Override public void sendInfoMessage(LinphoneInfoMessage msg) { - sendInfoMessage(nativePtr,((LinphoneInfoMessageImpl)msg).nativePtr); + synchronized(mCore){ + sendInfoMessage(nativePtr,((LinphoneInfoMessageImpl)msg).nativePtr); + } } private native Object getTransfererCall(long callPtr); @Override @@ -246,7 +260,9 @@ class LinphoneCallImpl implements LinphoneCall { private native long getErrorInfo(long nativePtr); @Override public ErrorInfo getErrorInfo() { - return new ErrorInfoImpl(getErrorInfo(nativePtr)); + synchronized(mCore){ + return new ErrorInfoImpl(getErrorInfo(nativePtr)); + } } @Override public void setUserData(Object obj) { @@ -260,18 +276,24 @@ class LinphoneCallImpl implements LinphoneCall { private native long getPlayer(long callPtr); @Override public LinphonePlayer getPlayer() { - return new LinphonePlayerImpl(getPlayer(nativePtr)); + synchronized(mCore){ + return new LinphonePlayerImpl(getPlayer(nativePtr)); + } } private native Object getChatRoom(long nativePtr); @Override public LinphoneChatRoom getChatRoom() { - return (LinphoneChatRoom)(getChatRoom(nativePtr)); + synchronized(mCore){ + return (LinphoneChatRoom)(getChatRoom(nativePtr)); + } } @Override public void setListener(LinphoneCallListener listener) { - setListener(nativePtr, listener); + synchronized(mCore){ + setListener(nativePtr, listener); + } } public LinphoneAddress getDiversionAddress() { @@ -288,5 +310,20 @@ class LinphoneCallImpl implements LinphoneCall { public boolean askedToAutoAnswer(){ return askedToAutoAnswer(nativePtr); } + + private native void declineWithErrorInfo(long call, long ei); + @Override + public void declineWithErrorInfo(ErrorInfo ei){ + synchronized(mCore){ + declineWithErrorInfo(nativePtr, ((ErrorInfoImpl)ei).mNativePtr); + } + } + private native void terminateWithErrorInfo(long call, long ei); + @Override + public void terminateWithErrorInfo(ErrorInfo ei){ + synchronized(mCore){ + terminateWithErrorInfo(nativePtr, ((ErrorInfoImpl)ei).mNativePtr); + } + } } diff --git a/java/impl/org/linphone/core/LinphoneCoreFactoryImpl.java b/java/impl/org/linphone/core/LinphoneCoreFactoryImpl.java index d1f7f2952..1c817de3c 100644 --- a/java/impl/org/linphone/core/LinphoneCoreFactoryImpl.java +++ b/java/impl/org/linphone/core/LinphoneCoreFactoryImpl.java @@ -255,4 +255,10 @@ public class LinphoneCoreFactoryImpl extends LinphoneCoreFactory { public DialPlan[] getAllDialPlan(){ return getAllDialPlanNative(); } + + private native long createErrorInfoNative(); + @Override + public ErrorInfo createErrorInfo(){ + return new ErrorInfoImpl(createErrorInfoNative(), true); + } } diff --git a/java/impl/org/linphone/core/LpConfigImpl.java b/java/impl/org/linphone/core/LpConfigImpl.java index a8d6d6b04..285795f38 100644 --- a/java/impl/org/linphone/core/LpConfigImpl.java +++ b/java/impl/org/linphone/core/LpConfigImpl.java @@ -22,40 +22,40 @@ class LpConfigImpl implements LpConfig { private long nativePtr; boolean ownPtr = false; - + public LpConfigImpl(long ptr) { nativePtr = ptr; } - + private native long newLpConfigImpl(String file); private native long newLpConfigImplFromBuffer(String buffer); private native void delete(long ptr); - + @Deprecated public LpConfigImpl(String file) { nativePtr = newLpConfigImpl(file); ownPtr = true; } - + private LpConfigImpl() { nativePtr = -1; ownPtr = false; } - + public static LpConfigImpl fromFile(String file) { LpConfigImpl impl = new LpConfigImpl(); impl.nativePtr = impl.newLpConfigImpl(file); impl.ownPtr = true; return impl; } - + public static LpConfigImpl fromBuffer(String buffer) { LpConfigImpl impl = new LpConfigImpl(); impl.nativePtr = impl.newLpConfigImplFromBuffer(buffer); impl.ownPtr = true; return impl; } - + protected void finalize() throws Throwable { if(ownPtr) { delete(nativePtr); @@ -128,4 +128,8 @@ class LpConfigImpl implements LpConfig { return getIntRange(nativePtr, section, key, defaultMin, defaultMax); } + private native void loadXmlFile(long ptr, String fileName); + public void loadXmlFile(String fileName) { + loadXmlFile(nativePtr, fileName); + } } diff --git a/tester/CMakeLists.txt b/tester/CMakeLists.txt index e90af0224..dd24b205a 100644 --- a/tester/CMakeLists.txt +++ b/tester/CMakeLists.txt @@ -78,6 +78,7 @@ set(CERTIFICATE_FILES ${CERTIFICATE_ALT_FILES} ${CERTIFICATE_CN_FILES} ${CERTIFI set(RC_FILES rcfiles/account_creator_rc + rcfiles/assistant_create.rc rcfiles/carddav_rc rcfiles/conference_focus_rc rcfiles/empty_rc diff --git a/tester/Makefile.am b/tester/Makefile.am index efe2837ed..98634b009 100644 --- a/tester/Makefile.am +++ b/tester/Makefile.am @@ -35,6 +35,7 @@ CERTIFICATE_FILES = $(CERTIFICATE_ALT_FILES) $(CERTIFICATE_CN_FILES) $(CERTIFICA RCFILES = \ rcfiles/account_creator_rc\ + rcfiles/assistant_create.rc\ rcfiles/carddav_rc\ rcfiles/empty_rc\ rcfiles/friends_rc\ diff --git a/tester/account_creator_tester.c b/tester/account_creator_tester.c index 108b10521..118187e8d 100644 --- a/tester/account_creator_tester.c +++ b/tester/account_creator_tester.c @@ -493,6 +493,28 @@ static void server_delete_account_test(void) { wait_for_until(marie->lc, NULL, &stats->cb_done, 1, TIMEOUT_REQUEST); + linphone_account_creator_unref(creator); + + creator = _linphone_account_creator_new(marie->lc, XMLRPC_URL); + cbs = linphone_account_creator_get_callbacks(creator); + + linphone_account_creator_cbs_set_user_data(cbs, stats); + account_creator_reset_cb_done(cbs); + linphone_account_creator_service_set_user_data( + linphone_account_creator_get_service(creator), + (void*)LinphoneAccountCreatorStatusRequestOk); + linphone_account_creator_set_username(creator, "XXXTESTuser_3"); + linphone_account_creator_set_email(creator, "user_1@linphone.org"); + linphone_account_creator_set_password(creator, "password"); + + BC_ASSERT_EQUAL( + delete_account_cb(creator), + LinphoneAccountCreatorStatusRequestOk, + LinphoneAccountCreatorStatus, + "%i"); + + wait_for_until(marie->lc, NULL, &stats->cb_done, 1, TIMEOUT_REQUEST); + ms_free(stats); linphone_account_creator_unref(creator); linphone_core_manager_destroy(marie); @@ -996,6 +1018,10 @@ static void server_activate_account_not_activated(void) { (void*)LinphoneAccountCreatorStatusAccountActivated); linphone_account_creator_cbs_set_activate_account(cbs, account_creator_cb); + linphone_account_creator_service_set_activate_account_cb( + linphone_account_creator_get_service(creator), + linphone_account_creator_activate_email_account_linphone); + BC_ASSERT_EQUAL( linphone_account_creator_activate_account(creator), LinphoneAccountCreatorStatusRequestOk, @@ -1026,6 +1052,9 @@ static void server_activate_account_already_activated(void) { linphone_account_creator_get_service(creator), (void*)LinphoneAccountCreatorStatusAccountAlreadyActivated); linphone_account_creator_cbs_set_activate_account(cbs, account_creator_cb); + linphone_account_creator_service_set_activate_account_cb( + linphone_account_creator_get_service(creator), + linphone_account_creator_activate_email_account_linphone); BC_ASSERT_EQUAL( linphone_account_creator_activate_account(creator), @@ -1055,6 +1084,9 @@ static void server_activate_non_existent_account(void) { linphone_account_creator_get_service(creator), (void*)LinphoneAccountCreatorStatusAccountNotActivated); linphone_account_creator_cbs_set_activate_account(cbs, account_creator_cb); + linphone_account_creator_service_set_activate_account_cb( + linphone_account_creator_get_service(creator), + linphone_account_creator_activate_email_account_linphone); BC_ASSERT_EQUAL( linphone_account_creator_activate_account(creator), @@ -1099,6 +1131,9 @@ static void server_activate_account_with_email_activated_arg_username_missing(vo linphone_account_creator_get_service(creator), (void*)LinphoneAccountCreatorStatusMissingArguments); linphone_account_creator_cbs_set_activate_account(cbs, account_creator_cb); + linphone_account_creator_service_set_activate_account_cb( + linphone_account_creator_get_service(creator), + linphone_account_creator_activate_email_account_linphone); BC_ASSERT_EQUAL( linphone_account_creator_activate_account(creator), @@ -1125,6 +1160,9 @@ static void server_activate_account_with_email_activated_arg_activation_code_mis linphone_account_creator_get_service(creator), (void*)LinphoneAccountCreatorStatusMissingArguments); linphone_account_creator_cbs_set_activate_account(cbs, account_creator_cb); + linphone_account_creator_service_set_activate_account_cb( + linphone_account_creator_get_service(creator), + linphone_account_creator_activate_email_account_linphone); BC_ASSERT_EQUAL( linphone_account_creator_activate_account(creator), diff --git a/tester/call_multicast_tester.c b/tester/call_multicast_tester.c index 8850d565e..cf1758705 100644 --- a/tester/call_multicast_tester.c +++ b/tester/call_multicast_tester.c @@ -83,6 +83,7 @@ static void early_media_with_multicast_base(bool_t video) { LinphoneVideoPolicy marie_policy, pauline_policy; LpConfig *marie_lp; LinphoneCallParams *params; + LinphoneCallStats *stats = NULL; marie = linphone_core_manager_new("marie_rc"); pauline = linphone_core_manager_new("pauline_tcp_rc"); @@ -167,11 +168,15 @@ static void early_media_with_multicast_base(bool_t video) { wait_for_list(lcs, &dummy, 1, 3000); + stats = linphone_call_get_audio_stats(linphone_core_get_current_call(pauline->lc)); BC_ASSERT_GREATER(linphone_core_manager_get_max_audio_down_bw(pauline),70,int,"%i"); - BC_ASSERT_LOWER((int)linphone_call_get_audio_stats(linphone_core_get_current_call(pauline->lc))->download_bandwidth, 90, int, "%i"); + BC_ASSERT_LOWER((int)linphone_call_stats_get_download_bandwidth(stats), 90, int, "%i"); + linphone_call_stats_unref(stats); + stats = linphone_call_get_audio_stats(linphone_core_get_current_call(pauline2->lc)); BC_ASSERT_GREATER(linphone_core_manager_get_max_audio_down_bw(pauline2),70,int,"%i"); - BC_ASSERT_LOWER((int)linphone_call_get_audio_stats(linphone_core_get_current_call(pauline2->lc))->download_bandwidth,90, int, "%i"); + BC_ASSERT_LOWER((int)linphone_call_stats_get_download_bandwidth(stats),90, int, "%i"); + linphone_call_stats_unref(stats); BC_ASSERT_TRUE(linphone_call_params_audio_multicast_enabled(linphone_call_get_current_params(linphone_core_get_current_call(pauline->lc)))); BC_ASSERT_TRUE(linphone_call_params_audio_multicast_enabled(linphone_call_get_current_params(linphone_core_get_current_call(marie->lc)))); diff --git a/tester/call_single_tester.c b/tester/call_single_tester.c index 28a3be0cd..1e48d2d6d 100644 --- a/tester/call_single_tester.c +++ b/tester/call_single_tester.c @@ -112,13 +112,18 @@ void call_stats_updated(LinphoneCore *lc, LinphoneCall *call, const LinphoneCall if (lstats->updated & LINPHONE_CALL_STATS_PERIODICAL_UPDATE ) { int tab_size = sizeof (counters->audio_download_bandwidth)/sizeof(int); int index = (counters->current_bandwidth_index[lstats->type]++) % tab_size; + LinphoneCallStats *audio_stats, *video_stats; + audio_stats = linphone_call_get_audio_stats(call); + video_stats = linphone_call_get_video_stats(call); if (lstats->type == LINPHONE_CALL_STATS_AUDIO) { - counters->audio_download_bandwidth[index] = (int)linphone_call_get_audio_stats(call)->download_bandwidth; - counters->audio_upload_bandwidth[index] = (int)linphone_call_get_audio_stats(call)->upload_bandwidth; + counters->audio_download_bandwidth[index] = (int)audio_stats->download_bandwidth; + counters->audio_upload_bandwidth[index] = (int)audio_stats->upload_bandwidth; } else { - counters->video_download_bandwidth[index] = (int)linphone_call_get_video_stats(call)->download_bandwidth; - counters->video_upload_bandwidth[index] = (int)linphone_call_get_video_stats(call)->upload_bandwidth; + counters->video_download_bandwidth[index] = (int)video_stats->download_bandwidth; + counters->video_upload_bandwidth[index] = (int)video_stats->upload_bandwidth; } + linphone_call_stats_unref(audio_stats); + linphone_call_stats_unref(video_stats); } } @@ -179,6 +184,7 @@ void liblinphone_tester_check_rtcp(LinphoneCoreManager* caller, LinphoneCoreMana LinphoneCall *c1,*c2; MSTimeSpec ts; int max_time_to_wait; + LinphoneCallStats *audio_stats1, *video_stats1, *audio_stats2, *video_stats2; c1=linphone_core_get_current_call(caller->lc); c2=linphone_core_get_current_call(callee->lc); @@ -195,46 +201,58 @@ void liblinphone_tester_check_rtcp(LinphoneCoreManager* caller, LinphoneCoreMana max_time_to_wait = 5000; do { - if (linphone_call_get_audio_stats(c1)->round_trip_delay > 0.0 - && linphone_call_get_audio_stats(c2)->round_trip_delay > 0.0 - && (!linphone_call_log_video_enabled(linphone_call_get_call_log(c1)) || linphone_call_get_video_stats(c1)->round_trip_delay>0.0) - && (!linphone_call_log_video_enabled(linphone_call_get_call_log(c2)) || linphone_call_get_video_stats(c2)->round_trip_delay>0.0)) { + audio_stats1 = linphone_call_get_audio_stats(c1); + video_stats1 = linphone_call_get_video_stats(c1); + audio_stats2 = linphone_call_get_audio_stats(c2); + video_stats2 = linphone_call_get_video_stats(c2); + if (audio_stats1->round_trip_delay > 0.0 + && audio_stats2->round_trip_delay > 0.0 + && (!linphone_call_log_video_enabled(linphone_call_get_call_log(c1)) || video_stats1->round_trip_delay>0.0) + && (!linphone_call_log_video_enabled(linphone_call_get_call_log(c2)) || video_stats2->round_trip_delay>0.0)) { break; } + linphone_call_stats_unref(audio_stats1); + linphone_call_stats_unref(audio_stats2); + if (video_stats1) linphone_call_stats_unref(video_stats1); + if (video_stats2) linphone_call_stats_unref(video_stats2); wait_for_until(caller->lc,callee->lc,NULL,0,20); /*just to sleep while iterating*/ }while (!liblinphone_tester_clock_elapsed(&ts,max_time_to_wait)); + audio_stats1 = linphone_call_get_audio_stats(c1); + video_stats1 = linphone_call_get_video_stats(c1); + audio_stats2 = linphone_call_get_audio_stats(c2); + video_stats2 = linphone_call_get_video_stats(c2); if (linphone_core_rtcp_enabled(caller->lc) && linphone_core_rtcp_enabled(callee->lc)) { BC_ASSERT_GREATER(caller->stat.number_of_rtcp_received, 1, int, "%i"); BC_ASSERT_GREATER(callee->stat.number_of_rtcp_received, 1, int, "%i"); - BC_ASSERT_GREATER(linphone_call_get_audio_stats(c1)->round_trip_delay,0.0,float,"%f"); - BC_ASSERT_GREATER(linphone_call_get_audio_stats(c2)->round_trip_delay,0.0,float,"%f"); + BC_ASSERT_GREATER(audio_stats1->round_trip_delay,0.0,float,"%f"); + BC_ASSERT_GREATER(audio_stats2->round_trip_delay,0.0,float,"%f"); if (linphone_call_log_video_enabled(linphone_call_get_call_log(c1))) { - BC_ASSERT_GREATER(linphone_call_get_video_stats(c1)->round_trip_delay,0.0,float,"%f"); + BC_ASSERT_GREATER(video_stats1->round_trip_delay,0.0,float,"%f"); } if (linphone_call_log_video_enabled(linphone_call_get_call_log(c2))) { - BC_ASSERT_GREATER(linphone_call_get_video_stats(c2)->round_trip_delay,0.0,float,"%f"); + BC_ASSERT_GREATER(video_stats2->round_trip_delay,0.0,float,"%f"); } } else { if (linphone_core_rtcp_enabled(caller->lc)) { - BC_ASSERT_EQUAL(linphone_call_get_audio_stats(c1)->rtp_stats.sent_rtcp_packets, 0, unsigned long long, "%llu"); - BC_ASSERT_EQUAL(linphone_call_get_audio_stats(c2)->rtp_stats.recv_rtcp_packets, 0, unsigned long long, "%llu"); + BC_ASSERT_EQUAL(audio_stats1->rtp_stats.sent_rtcp_packets, 0, unsigned long long, "%llu"); + BC_ASSERT_EQUAL(audio_stats2->rtp_stats.recv_rtcp_packets, 0, unsigned long long, "%llu"); if (linphone_call_log_video_enabled(linphone_call_get_call_log(c1))) { - BC_ASSERT_EQUAL(linphone_call_get_video_stats(c1)->rtp_stats.sent_rtcp_packets, 0, unsigned long long, "%llu"); + BC_ASSERT_EQUAL(video_stats1->rtp_stats.sent_rtcp_packets, 0, unsigned long long, "%llu"); } if (linphone_call_log_video_enabled(linphone_call_get_call_log(c2))) { - BC_ASSERT_EQUAL(linphone_call_get_video_stats(c2)->rtp_stats.recv_rtcp_packets, 0, unsigned long long, "%llu"); + BC_ASSERT_EQUAL(video_stats2->rtp_stats.recv_rtcp_packets, 0, unsigned long long, "%llu"); } } if (linphone_core_rtcp_enabled(callee->lc)) { - BC_ASSERT_EQUAL(linphone_call_get_audio_stats(c2)->rtp_stats.sent_rtcp_packets, 0, unsigned long long, "%llu"); - BC_ASSERT_EQUAL(linphone_call_get_audio_stats(c1)->rtp_stats.recv_rtcp_packets, 0, unsigned long long, "%llu"); + BC_ASSERT_EQUAL(audio_stats2->rtp_stats.sent_rtcp_packets, 0, unsigned long long, "%llu"); + BC_ASSERT_EQUAL(audio_stats1->rtp_stats.recv_rtcp_packets, 0, unsigned long long, "%llu"); if (linphone_call_log_video_enabled(linphone_call_get_call_log(c1))) { - BC_ASSERT_EQUAL(linphone_call_get_video_stats(c1)->rtp_stats.recv_rtcp_packets, 0, unsigned long long, "%llu"); + BC_ASSERT_EQUAL(video_stats1->rtp_stats.recv_rtcp_packets, 0, unsigned long long, "%llu"); } if (linphone_call_log_video_enabled(linphone_call_get_call_log(c2))) { - BC_ASSERT_EQUAL(linphone_call_get_video_stats(c2)->rtp_stats.sent_rtcp_packets, 0, unsigned long long, "%llu"); + BC_ASSERT_EQUAL(video_stats2->rtp_stats.sent_rtcp_packets, 0, unsigned long long, "%llu"); } } @@ -980,6 +998,59 @@ static void simple_call_compatibility_mode(void) { linphone_core_manager_destroy(pauline); } +static void terminate_call_with_error(void) { + LinphoneCall* call_callee ; + LinphoneErrorInfo *ei ; + const LinphoneErrorInfo *rei ; + LinphoneCoreManager *callee_mgr = linphone_core_manager_new("marie_rc"); + LinphoneCoreManager *caller_mgr = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc"); + + LinphoneCall* out_call = linphone_core_invite_address(caller_mgr->lc,callee_mgr->identity); + + + linphone_call_ref(out_call); + ei = linphone_error_info_new(); + linphone_error_info_set(ei, NULL, LinphoneReasonNone, 200, "Call completed elsewhere", NULL); + + BC_ASSERT_TRUE(wait_for(caller_mgr->lc, callee_mgr->lc, &caller_mgr->stat.number_of_LinphoneCallOutgoingInit,1)); + BC_ASSERT_TRUE(wait_for(caller_mgr->lc, callee_mgr->lc, &callee_mgr->stat.number_of_LinphoneCallIncomingReceived, 1)); + BC_ASSERT_TRUE(wait_for(caller_mgr->lc, callee_mgr->lc, &caller_mgr->stat.number_of_LinphoneCallOutgoingProgress, 1)); + + call_callee = linphone_core_get_current_call(callee_mgr->lc); + BC_ASSERT_PTR_NOT_NULL(call_callee); + + BC_ASSERT_EQUAL( linphone_core_accept_call(callee_mgr->lc,call_callee), 0 , int, "%d"); + BC_ASSERT_TRUE(wait_for(caller_mgr->lc,callee_mgr->lc,&caller_mgr->stat.number_of_LinphoneCallConnected,1)); + + + + BC_ASSERT_TRUE(wait_for(caller_mgr->lc, callee_mgr->lc, &caller_mgr->stat.number_of_LinphoneCallStreamsRunning, 1)); + + + rei = ei; + + linphone_call_terminate_with_error_info(out_call,rei); + BC_ASSERT_TRUE(wait_for(caller_mgr->lc,callee_mgr->lc,&caller_mgr->stat.number_of_LinphoneCallEnd,1)); + + BC_ASSERT_PTR_NOT_NULL(rei); + if (rei){ + BC_ASSERT_EQUAL(linphone_error_info_get_protocol_code(rei),200, int, "%d"); + BC_ASSERT_PTR_NOT_NULL(linphone_error_info_get_phrase(rei)); + BC_ASSERT_STRING_EQUAL(linphone_error_info_get_phrase(rei), "Call completed elsewhere"); + BC_ASSERT_STRING_EQUAL(linphone_error_info_get_protocol(ei), "SIP"); + + } + + + BC_ASSERT_EQUAL(caller_mgr->stat.number_of_LinphoneCallEnd,1, int, "%d"); + BC_ASSERT_TRUE(wait_for(caller_mgr->lc,callee_mgr->lc,&caller_mgr->stat.number_of_LinphoneCallReleased,1)); + + linphone_error_info_unref(ei); + linphone_call_unref(out_call); + linphone_core_manager_destroy(callee_mgr); + linphone_core_manager_destroy(caller_mgr); +} + static void cancelled_call(void) { LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc"); @@ -1138,6 +1209,62 @@ static void call_busy_when_calling_self(void) { linphone_core_manager_destroy(marie); } +static void call_declined_with_error(void) { + LinphoneCoreManager* callee_mgr = linphone_core_manager_new("marie_rc"); + LinphoneCoreManager* caller_mgr = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc"); + + LinphoneCall* in_call = NULL; + LinphoneCall* out_call = linphone_core_invite_address(caller_mgr->lc,callee_mgr->identity); + LinphoneFactory* factory = linphone_factory_get(); + const LinphoneErrorInfo* rcvd_ei; + const LinphoneErrorInfo* sub_rcvd_ei; + + LinphoneErrorInfo *ei = linphone_factory_create_error_info(factory); + LinphoneErrorInfo *reason_ei = linphone_factory_create_error_info(factory); + + linphone_error_info_set(ei, "SIP", LinphoneReasonUnknown, 603, "Decline", NULL); //ordre des arguments à vérifier + linphone_error_info_set(reason_ei, "hardware", LinphoneReasonUnknown, 66, "J'ai plus de batterie", NULL); + + linphone_error_info_set_sub_error_info(ei, reason_ei); + + BC_ASSERT_TRUE(wait_for(caller_mgr->lc,callee_mgr->lc,&callee_mgr->stat.number_of_LinphoneCallIncomingReceived,1)); + BC_ASSERT_PTR_NOT_NULL(in_call=linphone_core_get_current_call(callee_mgr->lc)); + + linphone_call_ref(out_call); + BC_ASSERT_TRUE(wait_for(caller_mgr->lc,callee_mgr->lc,&callee_mgr->stat.number_of_LinphoneCallIncomingReceived,1)); + BC_ASSERT_PTR_NOT_NULL(in_call=linphone_core_get_current_call(callee_mgr->lc)); + if (in_call) { + linphone_call_ref(in_call); + linphone_call_decline_with_error_info(in_call, ei); + + BC_ASSERT_TRUE(wait_for(caller_mgr->lc,callee_mgr->lc,&callee_mgr->stat.number_of_LinphoneCallEnd,1)); + BC_ASSERT_TRUE(wait_for(callee_mgr->lc,caller_mgr->lc,&caller_mgr->stat.number_of_LinphoneCallEnd,1)); + + rcvd_ei = linphone_call_get_error_info(out_call); + sub_rcvd_ei = linphone_error_info_get_sub_error_info(rcvd_ei); + + BC_ASSERT_STRING_EQUAL(linphone_error_info_get_phrase(rcvd_ei), "Decline"); + BC_ASSERT_STRING_EQUAL(linphone_error_info_get_protocol(rcvd_ei), "SIP"); + BC_ASSERT_STRING_EQUAL(linphone_error_info_get_phrase(sub_rcvd_ei), "J'ai plus de batterie"); + BC_ASSERT_STRING_EQUAL(linphone_error_info_get_protocol(sub_rcvd_ei), "hardware"); + + BC_ASSERT_EQUAL(linphone_call_get_reason(in_call),LinphoneReasonDeclined, int, "%d"); + BC_ASSERT_EQUAL(linphone_call_log_get_status(linphone_call_get_call_log(in_call)),LinphoneCallDeclined, int, "%d"); + BC_ASSERT_EQUAL(linphone_call_get_reason(out_call),LinphoneReasonDeclined, int, "%d"); + BC_ASSERT_EQUAL(linphone_call_log_get_status(linphone_call_get_call_log(out_call)),LinphoneCallDeclined, int, "%d"); + + + BC_ASSERT_TRUE(wait_for(caller_mgr->lc,callee_mgr->lc,&callee_mgr->stat.number_of_LinphoneCallReleased,1)); + BC_ASSERT_TRUE(wait_for(caller_mgr->lc,callee_mgr->lc,&caller_mgr->stat.number_of_LinphoneCallReleased,1)); + linphone_call_unref(in_call); + } + linphone_call_unref(out_call); + linphone_error_info_unref(reason_ei); + linphone_error_info_unref(ei); + + linphone_core_manager_destroy(callee_mgr); + linphone_core_manager_destroy(caller_mgr); +} static void call_declined(void) { LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc"); @@ -1525,6 +1652,262 @@ static void call_with_custom_sdp_attributes(void) { linphone_core_manager_destroy(pauline); } + + + +static void call_with_custom_header_or_sdp_cb(LinphoneCore *lc, LinphoneCall *call, LinphoneCallState cstate, const char *message) { + + + const char *value; + if (cstate == LinphoneCallOutgoingInit){ + LinphoneCallParams *params = linphone_call_params_copy(linphone_call_get_params(call)); + linphone_call_params_add_custom_sdp_attribute(params, "working", "maybe"); + linphone_call_set_params(call, params); + linphone_call_params_unref(params); + + } + + else if (cstate == LinphoneCallIncomingReceived){ + const LinphoneCallParams *tparams = linphone_call_get_remote_params(call); + LinphoneCallParams *params = linphone_call_params_copy(tparams); + //Check received params + //SDP + value = linphone_call_params_get_custom_sdp_attribute(params, "working"); + BC_ASSERT_PTR_NOT_NULL(value); + if (value) BC_ASSERT_STRING_EQUAL(value, "maybe"); + //header + value = linphone_call_params_get_custom_header(params, "weather"); + BC_ASSERT_PTR_NOT_NULL(value); + if (value) BC_ASSERT_STRING_EQUAL(value, "thunderstorm"); + //modify SDP + linphone_call_params_add_custom_sdp_attribute(params, "working", "yes"); + linphone_call_set_params(call, params); + linphone_call_params_unref(params); + + } + + + +} + +static void call_caller_with_custom_header_or_sdp_attributes(void) { + LinphoneCoreManager *callee_mgr = linphone_core_manager_new("marie_rc"); + LinphoneCoreManager *caller_mgr = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc"); + LinphoneCall *call_caller = NULL, *call_callee = NULL; + LinphoneCallParams *caller_params; // *callee_params ; + + LinphoneCoreVTable *vtable; + + LinphoneCallTestParams caller_test_params = {0}; + LinphoneCallTestParams callee_test_params = {0}; + + stats initial_caller=caller_mgr->stat; + stats initial_callee=callee_mgr->stat; + bool_t result=FALSE; + bool_t did_receive_call; + + //Create caller params with custom header and custom SDP + caller_params = linphone_core_create_call_params(caller_mgr->lc, NULL); + linphone_call_params_add_custom_header(caller_params, "weather", "thunderstorm"); + linphone_call_params_add_custom_sdp_media_attribute(caller_params, LinphoneStreamTypeAudio, "sleeping", "almost"); + + caller_test_params.base = (LinphoneCallParams*)caller_params; + callee_test_params.base = NULL; + + /* TODO: This should be handled correctly inside the liblinphone library but meanwhile handle this here. */ + linphone_core_manager_wait_for_stun_resolution(caller_mgr); + linphone_core_manager_wait_for_stun_resolution(callee_mgr); + + setup_sdp_handling(&caller_test_params, caller_mgr); + setup_sdp_handling(&callee_test_params, callee_mgr); + + // Assign dedicated callback to vtable for caller and callee + vtable = linphone_core_v_table_new(); + vtable->call_state_changed = call_with_custom_header_or_sdp_cb; + linphone_core_add_listener(callee_mgr->lc, vtable); + linphone_core_add_listener(caller_mgr->lc, vtable); + + //Caller initates the call with INVITE + // caller params not null + BC_ASSERT_PTR_NOT_NULL((call_caller=linphone_core_invite_address_with_params(caller_mgr->lc,callee_mgr->identity,caller_params))); + + BC_ASSERT_PTR_NULL(linphone_call_get_remote_params(call_caller)); /*assert that remote params are NULL when no response is received yet*/ + + // Wait for Incoming received + did_receive_call = wait_for(callee_mgr->lc + ,caller_mgr->lc + ,&callee_mgr->stat.number_of_LinphoneCallIncomingReceived + ,initial_callee.number_of_LinphoneCallIncomingReceived+1); + BC_ASSERT_EQUAL(did_receive_call, !callee_test_params.sdp_simulate_error, int, "%d"); + + 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); + + // Wait for Outgoing Progress + if (linphone_core_get_calls_nb(callee_mgr->lc)<=1) + BC_ASSERT_TRUE(linphone_core_inc_invite_pending(callee_mgr->lc)); + BC_ASSERT_EQUAL(caller_mgr->stat.number_of_LinphoneCallOutgoingProgress,initial_caller.number_of_LinphoneCallOutgoingProgress+1, int, "%d"); + + + + + LinphoneCallParams *default_params=linphone_core_create_call_params(callee_mgr->lc,call_callee); + ms_message("Created default call params with video=%i", linphone_call_params_video_enabled(default_params)); + linphone_core_accept_call_with_params(callee_mgr->lc,call_callee,default_params); + linphone_call_params_unref(default_params); + + + BC_ASSERT_TRUE(wait_for(callee_mgr->lc,caller_mgr->lc,&callee_mgr->stat.number_of_LinphoneCallConnected,initial_callee.number_of_LinphoneCallConnected+1)); + BC_ASSERT_TRUE(wait_for(callee_mgr->lc,caller_mgr->lc,&caller_mgr->stat.number_of_LinphoneCallConnected,initial_caller.number_of_LinphoneCallConnected+1)); + + result = wait_for_until(callee_mgr->lc,caller_mgr->lc,&caller_mgr->stat.number_of_LinphoneCallStreamsRunning,initial_caller.number_of_LinphoneCallStreamsRunning+1, 2000) + && + wait_for_until(callee_mgr->lc,caller_mgr->lc,&callee_mgr->stat.number_of_LinphoneCallStreamsRunning,initial_callee.number_of_LinphoneCallStreamsRunning+1, 2000); + BC_ASSERT_TRUE(result); + + + caller_params = linphone_core_create_call_params(caller_mgr->lc, call_caller); + linphone_call_params_clear_custom_sdp_attributes(caller_params); + linphone_call_params_clear_custom_sdp_media_attributes(caller_params, LinphoneStreamTypeAudio); + linphone_call_params_add_custom_sdp_attribute(caller_params, "weather", "sunny"); + linphone_core_update_call(caller_mgr->lc, call_caller, caller_params); + linphone_call_params_unref(caller_params); + + + end_call(caller_mgr, callee_mgr); + + linphone_core_manager_destroy(callee_mgr); + linphone_core_manager_destroy(caller_mgr); +} + + + + +static void call_callee_with_custom_header_or_sdp_cb(LinphoneCore *lc, LinphoneCall *call, LinphoneCallState cstate, const char *message) { + + + const char *value; + if (cstate == LinphoneCallOutgoingInit){ + LinphoneCallParams *params = linphone_call_params_copy(linphone_call_get_params(call)); + linphone_call_params_add_custom_sdp_attribute(params, "working", "maybe"); + linphone_call_set_params(call, params); + linphone_call_params_unref(params); + + } + + else if (cstate == LinphoneCallIncomingReceived){ + const LinphoneCallParams *tparams = linphone_call_get_remote_params(call); + LinphoneCallParams *params = linphone_call_params_copy(tparams); + value = linphone_call_params_get_custom_sdp_attribute(params, "working"); + BC_ASSERT_PTR_NOT_NULL(value); + if (value) BC_ASSERT_STRING_EQUAL(value, "maybe"); + linphone_call_set_params(call, params); + linphone_call_params_unref(params); + + } + +} + + +static void call_callee_with_custom_header_or_sdp_attributes(void) { + int result; + LinphoneCoreManager *callee_mgr = linphone_core_manager_new("marie_rc"); + LinphoneCoreManager *caller_mgr = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc"); + LinphoneCall *call_caller = NULL, *call_callee = NULL; + LinphoneCallParams *callee_params, *caller_params ; + + LinphoneCoreVTable *vtable; + const char *value; + LinphoneCallTestParams caller_test_params = {0}; + LinphoneCallTestParams callee_test_params = {0}; + + stats initial_caller=caller_mgr->stat; + stats initial_callee=callee_mgr->stat; + bool_t did_receive_call; + const LinphoneCallParams *caller_remote_params; + + caller_params = linphone_core_create_call_params(caller_mgr->lc, NULL); + + + callee_test_params.base = NULL; + caller_test_params.base = NULL; + + /* TODO: This should be handled correctly inside the liblinphone library but meanwhile handle this here. */ + linphone_core_manager_wait_for_stun_resolution(caller_mgr); + linphone_core_manager_wait_for_stun_resolution(callee_mgr); + + setup_sdp_handling(&caller_test_params, caller_mgr); + setup_sdp_handling(&callee_test_params, callee_mgr); + + // Assign dedicated callback to vtable for caller and callee + vtable = linphone_core_v_table_new(); + vtable->call_state_changed = call_callee_with_custom_header_or_sdp_cb; + linphone_core_add_listener(callee_mgr->lc, vtable); + linphone_core_add_listener(caller_mgr->lc, vtable); + + //Caller initates the call with INVITE + // caller params not null + BC_ASSERT_PTR_NOT_NULL((call_caller=linphone_core_invite_address_with_params(caller_mgr->lc,callee_mgr->identity,caller_params))); + + BC_ASSERT_PTR_NULL(linphone_call_get_remote_params(call_caller)); /*assert that remote params are NULL when no response is received yet*/ + + // Wait for Incoming received + did_receive_call = wait_for(callee_mgr->lc + ,caller_mgr->lc + ,&callee_mgr->stat.number_of_LinphoneCallIncomingReceived + ,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); + + // Wait for Outgoing Progress + if (linphone_core_get_calls_nb(callee_mgr->lc)<=1) + BC_ASSERT_TRUE(linphone_core_inc_invite_pending(callee_mgr->lc)); + BC_ASSERT_EQUAL(caller_mgr->stat.number_of_LinphoneCallOutgoingProgress,initial_caller.number_of_LinphoneCallOutgoingProgress+1, int, "%d"); + + + //Create callee params with custom header and custom SDP + + + callee_params = linphone_core_create_call_params(callee_mgr->lc,call_callee); + linphone_call_params_add_custom_header(callee_params, "weather", "thunderstorm"); + linphone_call_params_add_custom_sdp_media_attribute(callee_params, LinphoneStreamTypeAudio, "sleeping", "almost"); + linphone_call_params_add_custom_sdp_attribute(callee_params, "working", "yes"); + ms_message("Created default call params with video=%i", linphone_call_params_video_enabled(callee_params)); + linphone_core_accept_call_with_params(callee_mgr->lc,call_callee,callee_params); + linphone_call_params_unref(callee_params); + + + BC_ASSERT_TRUE(wait_for(callee_mgr->lc,caller_mgr->lc,&callee_mgr->stat.number_of_LinphoneCallConnected,initial_callee.number_of_LinphoneCallConnected+1)); + BC_ASSERT_TRUE(wait_for(callee_mgr->lc,caller_mgr->lc,&caller_mgr->stat.number_of_LinphoneCallConnected,initial_caller.number_of_LinphoneCallConnected+1)); + + result = wait_for_until(callee_mgr->lc,caller_mgr->lc,&caller_mgr->stat.number_of_LinphoneCallStreamsRunning,initial_caller.number_of_LinphoneCallStreamsRunning+1, 2000) + && + wait_for_until(callee_mgr->lc,caller_mgr->lc,&callee_mgr->stat.number_of_LinphoneCallStreamsRunning,initial_callee.number_of_LinphoneCallStreamsRunning+1, 2000); + + BC_ASSERT_TRUE(result); + + caller_remote_params = linphone_call_get_remote_params(call_caller); + value = linphone_call_params_get_custom_sdp_attribute(caller_remote_params, "working"); + BC_ASSERT_PTR_NOT_NULL(value); + if (value) BC_ASSERT_STRING_EQUAL(value, "yes"); + //header + value = linphone_call_params_get_custom_header(caller_remote_params, "weather"); + BC_ASSERT_PTR_NOT_NULL(value); + if (value) BC_ASSERT_STRING_EQUAL(value, "thunderstorm"); + + linphone_call_params_unref(caller_params); + end_call(caller_mgr, callee_mgr); + + linphone_core_manager_destroy(callee_mgr); + linphone_core_manager_destroy(caller_mgr); +} + void call_paused_resumed_base(bool_t multicast, bool_t with_losses) { LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc"); LinphoneCoreManager* pauline = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc"); @@ -2339,6 +2722,8 @@ static void _call_base_with_configfile(LinphoneMediaEncryption mode, bool_t enab BC_ASSERT_PTR_NOT_NULL(marie_token); if (marie_token && pauline_token){ BC_ASSERT_STRING_EQUAL(pauline_token, marie_token); + BC_ASSERT_TRUE(strlen(pauline_token)>0); + BC_ASSERT_TRUE(strlen(marie_token)>0); } if (!plays_nothing) liblinphone_tester_check_rtcp(pauline,marie); } @@ -2988,6 +3373,7 @@ void check_media_direction(LinphoneCoreManager* mgr, LinphoneCall *call, bctbx_l if (video_dir != LinphoneMediaDirectionInvalid){ int current_recv_iframe = mgr->stat.number_of_IframeDecoded; int expected_recv_iframe=0; + LinphoneCallStats *stats = linphone_call_get_video_stats(call); if (video_dir != LinphoneMediaDirectionInactive){ BC_ASSERT_TRUE(linphone_call_params_video_enabled(params)); @@ -2995,24 +3381,23 @@ void check_media_direction(LinphoneCoreManager* mgr, LinphoneCall *call, bctbx_l linphone_call_set_next_video_frame_decoded_callback(call,linphone_call_iframe_decoded_cb,mgr->lc); linphone_call_send_vfu_request(call); } - switch (video_dir) { case LinphoneMediaDirectionInactive: - BC_ASSERT_LOWER((int)linphone_call_get_video_stats(call)->upload_bandwidth, 5, int, "%i"); + BC_ASSERT_LOWER((int)stats->upload_bandwidth, 5, int, "%i"); break; case LinphoneMediaDirectionSendOnly: expected_recv_iframe = 0; - BC_ASSERT_LOWER((int)linphone_call_get_video_stats(call)->download_bandwidth, 5, int, "%i"); + BC_ASSERT_LOWER((int)stats->download_bandwidth, 5, int, "%i"); break; case LinphoneMediaDirectionRecvOnly: - BC_ASSERT_LOWER((int)linphone_call_get_video_stats(call)->upload_bandwidth, 5, int, "%i"); + BC_ASSERT_LOWER((int)stats->upload_bandwidth, 5, int, "%i"); case LinphoneMediaDirectionSendRecv: expected_recv_iframe = 1; break; default: break; } - + linphone_call_stats_unref(stats); BC_ASSERT_TRUE(wait_for_list(lcs, &mgr->stat.number_of_IframeDecoded,current_recv_iframe + expected_recv_iframe,10000)); } #endif @@ -3354,6 +3739,7 @@ static void call_with_paused_no_sdp_on_resume(void) { LinphoneCoreManager* marie; LinphoneCoreManager* pauline; LinphoneCall* call_marie = NULL; + LinphoneCallStats *stats; bool_t call_ok; marie = linphone_core_manager_new( "marie_rc"); @@ -3391,7 +3777,9 @@ static void call_with_paused_no_sdp_on_resume(void) { wait_for_until(marie->lc, pauline->lc, &dummy, 1, 3000); BC_ASSERT_GREATER(linphone_core_manager_get_max_audio_down_bw(marie),70,int,"%i"); - BC_ASSERT_TRUE(linphone_call_get_audio_stats(linphone_core_get_current_call(pauline->lc))->download_bandwidth>70); + stats = linphone_call_get_audio_stats(linphone_core_get_current_call(pauline->lc)); + BC_ASSERT_TRUE(stats->download_bandwidth>70); + linphone_call_stats_unref(stats); end_call(marie,pauline); end: @@ -4204,8 +4592,8 @@ static void custom_rtp_modifier(bool_t pauseResumeTest, bool_t recordTest) { // Now we want to ensure that all sent RTP packets actually go through our RTP transport modifier and thus no packet leave without being processed (by any operation we might want to do on it) { - const LinphoneCallStats *marie_stats = linphone_call_get_audio_stats(call_marie); - const LinphoneCallStats *pauline_stats = linphone_call_get_audio_stats(call_pauline); + LinphoneCallStats *marie_stats = linphone_call_get_audio_stats(call_marie); + LinphoneCallStats *pauline_stats = linphone_call_get_audio_stats(call_pauline); rtp_stats_t marie_rtp_stats = *linphone_call_stats_get_rtp_stats(marie_stats); rtp_stats_t pauline_rtp_stats = *linphone_call_stats_get_rtp_stats(pauline_stats); ms_message("Marie sent %i RTP packets and received %i (for real)", (int)marie_rtp_stats.packet_sent, (int)marie_rtp_stats.packet_recv); @@ -4215,6 +4603,8 @@ static void custom_rtp_modifier(bool_t pauseResumeTest, bool_t recordTest) { // There can be a small difference between the number of packets received in the modifier and the number processed in reception because the processing is asynchronous BC_ASSERT_TRUE(data_pauline->packetReceivedCount - pauline_rtp_stats.packet_recv < 20); BC_ASSERT_TRUE(data_pauline->packetSentCount == pauline_rtp_stats.packet_sent); + linphone_call_stats_unref(marie_stats); + linphone_call_stats_unref(pauline_stats); } end: @@ -5284,7 +5674,7 @@ static bool_t quick_call(LinphoneCoreManager *m1, LinphoneCoreManager *m2){ static void call_with_encryption_mandatory(bool_t caller_has_encryption_mandatory){ LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc"); 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; @@ -5305,8 +5695,12 @@ static void call_with_encryption_mandatory(bool_t caller_has_encryption_mandator BC_ASSERT_EQUAL(linphone_call_get_audio_stats(linphone_core_get_current_call(pauline->lc))->rtp_stats.packet_sent, 0, int, "%i"); #endif /*however we can trust packet_recv from the other party instead */ - BC_ASSERT_EQUAL((int)linphone_call_get_audio_stats(linphone_core_get_current_call(marie->lc))->rtp_stats.packet_recv, 0, int, "%i"); - BC_ASSERT_EQUAL((int)linphone_call_get_audio_stats(linphone_core_get_current_call(pauline->lc))->rtp_stats.packet_recv, 0, int, "%i"); + marie_stats = linphone_call_get_audio_stats(linphone_core_get_current_call(marie->lc)); + pauline_stats = linphone_call_get_audio_stats(linphone_core_get_current_call(pauline->lc)); + BC_ASSERT_EQUAL((int)marie_stats->rtp_stats.packet_recv, 0, int, "%i"); + BC_ASSERT_EQUAL((int)pauline_stats->rtp_stats.packet_recv, 0, int, "%i"); + linphone_call_stats_unref(marie_stats); + linphone_call_stats_unref(pauline_stats); end_call(marie, pauline); end: @@ -5464,6 +5858,7 @@ static void call_with_network_reachable_down_in_callback(void){ test_t call_tests[] = { TEST_NO_TAG("Early declined call", early_declined_call), TEST_NO_TAG("Call declined", call_declined), + TEST_NO_TAG("Call declined with error", call_declined_with_error), TEST_NO_TAG("Cancelled call", cancelled_call), TEST_NO_TAG("Early cancelled call", early_cancelled_call), TEST_NO_TAG("Call with DNS timeout", call_with_dns_time_out), @@ -5537,6 +5932,8 @@ test_t call_tests[] = { TEST_ONE_TAG("Call with ICE added by reINVITE", ice_added_by_reinvite, "ICE"), TEST_NO_TAG("Call with custom headers", call_with_custom_headers), TEST_NO_TAG("Call with custom SDP attributes", call_with_custom_sdp_attributes), + TEST_NO_TAG("Call caller with custom header or sdp", call_caller_with_custom_header_or_sdp_attributes), + TEST_NO_TAG("Call callee with custom header or sdp", call_callee_with_custom_header_or_sdp_attributes), TEST_NO_TAG("Call established with rejected INFO", call_established_with_rejected_info), TEST_NO_TAG("Call established with rejected RE-INVITE", call_established_with_rejected_reinvite), TEST_NO_TAG("Call established with rejected incoming RE-INVITE", call_established_with_rejected_incoming_reinvite), @@ -5604,7 +6001,8 @@ test_t call_tests[] = { TEST_NO_TAG("Call with ZRTP configured receiver side only", call_with_zrtp_configured_callee_side), TEST_NO_TAG("Call from plain RTP to ZRTP mandatory should be silent", call_from_plain_rtp_to_zrtp), TEST_NO_TAG("Call ZRTP mandatory to plain RTP should be silent", call_from_zrtp_to_plain_rtp), - TEST_NO_TAG("Call with network reachable down in callback", call_with_network_reachable_down_in_callback) + TEST_NO_TAG("Call with network reachable down in callback", call_with_network_reachable_down_in_callback), + TEST_NO_TAG("Call terminated with reason", terminate_call_with_error) }; test_suite_t call_test_suite = {"Single Call", NULL, NULL, liblinphone_tester_before_each, liblinphone_tester_after_each, diff --git a/tester/call_video_tester.c b/tester/call_video_tester.c index 30b72a71e..b0de949c6 100644 --- a/tester/call_video_tester.c +++ b/tester/call_video_tester.c @@ -223,7 +223,7 @@ static LinphoneCall* _request_video(LinphoneCoreManager* caller,LinphoneCoreMana bool_t request_video(LinphoneCoreManager* caller,LinphoneCoreManager* callee, bool_t accept_with_params) { stats initial_caller_stat=caller->stat; stats initial_callee_stat=callee->stat; - const LinphoneVideoPolicy *video_policy; + LinphoneVideoActivationPolicy *video_policy; LinphoneCall *call_obj; bool_t video_added = FALSE; @@ -233,7 +233,7 @@ bool_t request_video(LinphoneCoreManager* caller,LinphoneCoreManager* callee, bo BC_ASSERT_TRUE(wait_for(caller->lc,callee->lc,&callee->stat.number_of_LinphoneCallStreamsRunning,initial_callee_stat.number_of_LinphoneCallStreamsRunning+1)); 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_policy(caller->lc); + video_policy = linphone_core_get_video_activation_policy(caller->lc); if (video_policy->automatically_accept || 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 = @@ -243,6 +243,7 @@ bool_t request_video(LinphoneCoreManager* caller,LinphoneCoreManager* callee, bo 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)))); } + linphone_video_activation_policy_unref(video_policy); if (linphone_core_get_media_encryption(caller->lc) != LinphoneMediaEncryptionNone && linphone_core_get_media_encryption(callee->lc) != LinphoneMediaEncryptionNone) { const LinphoneCallParams* call_param; diff --git a/tester/complex_sip_case_tester.c b/tester/complex_sip_case_tester.c index 3e2a566af..f50996b5a 100644 --- a/tester/complex_sip_case_tester.c +++ b/tester/complex_sip_case_tester.c @@ -26,21 +26,30 @@ #if HAVE_SIPP void check_rtcp(LinphoneCall *call) { MSTimeSpec ts; + LinphoneCallStats *audio_stats, *video_stats; linphone_call_ref(call); liblinphone_tester_clock_start(&ts); do { - if (linphone_call_get_audio_stats(call)->round_trip_delay > 0.0 && (!linphone_call_log_video_enabled(linphone_call_get_call_log(call)) || linphone_call_get_video_stats(call)->round_trip_delay > 0.0)) { + audio_stats = linphone_call_get_audio_stats(call); + video_stats = linphone_call_get_video_stats(call); + if (linphone_call_stats_get_round_trip_delay(audio_stats) > 0.0 && (!linphone_call_log_video_enabled(linphone_call_get_call_log(call)) || linphone_call_stats_get_round_trip_delay(video_stats) > 0.0)) { break; } + linphone_call_stats_unref(audio_stats); + if (video_stats) linphone_call_stats_unref(video_stats); wait_for_until(call->core, NULL, NULL, 0, 20); /*just to sleep while iterating*/ } while (!liblinphone_tester_clock_elapsed(&ts, 15000)); - BC_ASSERT_GREATER(linphone_call_get_audio_stats(call)->round_trip_delay, 0.0, float, "%f"); + audio_stats = linphone_call_get_audio_stats(call); + BC_ASSERT_GREATER(linphone_call_stats_get_round_trip_delay(audio_stats), 0.0, float, "%f"); if (linphone_call_log_video_enabled(linphone_call_get_call_log(call))) { - BC_ASSERT_GREATER(linphone_call_get_video_stats(call)->round_trip_delay, 0.0, float, "%f"); + video_stats = linphone_call_get_video_stats(call); + BC_ASSERT_GREATER(linphone_call_stats_get_round_trip_delay(video_stats), 0.0, float, "%f"); + linphone_call_stats_unref(video_stats); } + linphone_call_stats_unref(audio_stats); linphone_call_unref(call); } diff --git a/tester/message_tester.c b/tester/message_tester.c index 7540b266a..c5ee54ef4 100644 --- a/tester/message_tester.c +++ b/tester/message_tester.c @@ -42,6 +42,8 @@ static const char *marie_zid_sqlcache = "BEGIN TRANSACTION; CREATE TABLE IF NOT static const char *pauline_zid_sqlcache = "BEGIN TRANSACTION; CREATE TABLE IF NOT EXISTS ziduri (zuid INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,zid BLOB NOT NULL DEFAULT '000000000000',selfuri TEXT NOT NULL DEFAULT 'unset',peeruri TEXT NOT NULL DEFAULT 'unset'); INSERT INTO `ziduri` (zuid,zid,selfuri,peeruri) VALUES (1,X'bcb4028bf55e1b7ac4c4edee','%s','self'), (2,X'4ddc8042bee500ad0366bf93','%s','%s'); CREATE TABLE IF NOT EXISTS zrtp (zuid INTEGER NOT NULL DEFAULT 0 UNIQUE,rs1 BLOB DEFAULT NULL,rs2 BLOB DEFAULT NULL,aux BLOB DEFAULT NULL,pbx BLOB DEFAULT NULL,pvs BLOB DEFAULT NULL,FOREIGN KEY(zuid) REFERENCES ziduri(zuid) ON UPDATE CASCADE ON DELETE CASCADE); INSERT INTO `zrtp` (zuid,rs1,rs2,aux,pbx,pvs) VALUES (2,X'f0e0ad4d3d4217ba4048d1553e5ab26fae0b386cdac603f29a66d5f4258e14ef',NULL,NULL,NULL,X'01'); CREATE TABLE IF NOT EXISTS lime (zuid INTEGER NOT NULL DEFAULT 0 UNIQUE,sndKey BLOB DEFAULT NULL,rcvKey BLOB DEFAULT NULL,sndSId BLOB DEFAULT NULL,rcvSId BLOB DEFAULT NULL,sndIndex BLOB DEFAULT NULL,rcvIndex BLOB DEFAULT NULL,valid BLOB DEFAULT NULL,FOREIGN KEY(zuid) REFERENCES ziduri(zuid) ON UPDATE CASCADE ON DELETE CASCADE); INSERT INTO `lime` (zuid,rcvKey,sndKey,rcvSId,sndSId,rcvIndex,sndIndex,valid) VALUES (2,X'97c75a5a92a041b415296beec268efc3373ef4aa8b3d5f301ac7522a7fb4e332',x'3b74b709b961e5ebccb1db6b850ea8c1f490546d6adee2f66b5def7093cead3d',X'e2ebca22ad33071bc37631393bf25fc0a9badeea7bf6dcbcb5d480be7ff8c5ea',X'a2086d195344ec2997bf3de7441d261041cda5d90ed0a0411ab2032e5860ea48',X'33376935',X'7ce32d86',X'0000000000000000'); COMMIT;"; +static const char *xmlCacheMigration = "\n00112233445566778899aabb99887766554433221100ffeec4274f13a2b6fa05c15ec93158f930e7264b0a893393376dbc80c6eb1cccdc5asip:bob@sip.linphone.org219d9e445d10d4ed64083c7ccbb83a23bc17a97df0af5de4261f3fe026b05b0b747e72a5cc996413cb9fa6e3d18d8b370436e274cd6ba4efc1a4580340af57cadf2bf38e719fa89e17332cf8d5e774ee70d347baa74d16dee01f306c54789869928ce78b0bfc30427a02b1b668b2b3b0496d5664d7e89b75ed292ee97e3fc850496bcc8959337abe5dda11f388384b349d210612f30824268a3753a7afa52ef6df5866dca76315c4sip:bob2@sip.linphone.orgffeeddccbbaa987654321012858b495dfad483af3c088f26d68c4beebc638bd44feae45aea726a771727235esip:bob@sip.linphone.orgb6aac945057bc4466bfe9a23771c6a1b3b8d72ec3e7d8f30ed63cbc5a9479a25bea5ac3225edd0545b816f061a8190370e3ee5160e75404846a34d1580e0c26317ce70fdf12e500294bcb5f2ffef53096761bb1c912b21e972ae03a5a9f05c477e13a20e15a517700f0be0921f74b96d4b4a0c539d5e14d5cdd8706441874ac075e18caa2cfbbf061533dee20c8116dc2c282cae9adfea689b87bc4c6a4e18a846f12e3e7fea39590987654321fedcba5a5a5a5acb6ecc87d1dd87b23f225eec53a26fc541384917623e0c46abab8c0350c6929e92bb03988e8f0ccfefa37a55fd7c5893bea3bfbb27312f49dd9b10d0e3c15fc72315705a5830b98f68458fcd49623144cb34a667512c4d44686aee125bb8b62294c56eea0dd829379263b6da3f6ac0a95388090f168a3568736ca0bd9f8d595fc319ae0d41183fec90afc412d42253c5b456580f7a463c111c7293623b8631f4sip:bob@sip.linphone.org2c46ddcc15f5779e0000000058f095bf01"; + void text_message_received(LinphoneCore *lc, LinphoneChatRoom *room, const LinphoneAddress *from_address, const char *msg) { stats* counters = get_stats(lc); counters->number_of_LinphoneMessageReceivedLegacy++; @@ -883,14 +885,18 @@ static int enable_lime_for_message_test(LinphoneCoreManager *marie, LinphoneCore linphone_core_enable_lime(marie->lc, LinphoneLimeMandatory); 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); + /* create temporary cache files: setting the database_path will create and initialise the files */ remove(bc_tester_file("tmpZIDCacheMarie.sqlite")); remove(bc_tester_file("tmpZIDCachePauline.sqlite")); filepath = bc_tester_file("tmpZIDCacheMarie.sqlite"); - linphone_core_set_zrtp_cache_database_path(marie->lc, filepath); + linphone_core_set_zrtp_secrets_file(marie->lc, filepath); bc_free(filepath); filepath = bc_tester_file("tmpZIDCachePauline.sqlite"); - linphone_core_set_zrtp_cache_database_path(pauline->lc, filepath); + linphone_core_set_zrtp_secrets_file(pauline->lc, filepath); bc_free(filepath); /* caches are empty, populate them */ @@ -1397,6 +1403,44 @@ static void lime_transfer_message_without_encryption_2(void) { lime_transfer_message_base(FALSE, FALSE, TRUE, FALSE); } +static void lime_cache_migration(void) { + if (lime_is_available()) { + char *xmlCache_filepath = bc_tester_file("tmp_zidCacheMigration"); + FILE *xmlCacheFD = NULL; + /* create the temporary cache xml file, it will be turned to sqlite */ + if ((xmlCacheFD = fopen(xmlCache_filepath, "w") ) == NULL) { + BC_ASSERT_PTR_NOT_NULL(xmlCacheFD); + ms_error("Unable to create temporary XML ZID cache file to test cache migration"); + return; + } + fprintf(xmlCacheFD, "%s", xmlCacheMigration); + fclose(xmlCacheFD); + + LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc"); + + if (!linphone_core_lime_available(marie->lc)) { + ms_warning("Lime not available, skiping"); + return; + } + + /* make sure lime is enabled */ + 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); + + /* set the cache path, it will trigger the migration function */ + linphone_core_set_zrtp_secrets_file(marie->lc, xmlCache_filepath); + + /* perform checks on the new cache, simple check is ok as deeper ones are performed in the bzrtp migration tester */ + /* TODO */ + + /* free memory */ + linphone_core_manager_destroy(marie); + remove(xmlCache_filepath); + } +} + static void lime_unit(void) { if (lime_is_available()) { LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc"); @@ -2367,6 +2411,7 @@ test_t message_tests[] = { TEST_ONE_TAG("Lime transfer message from history", lime_transfer_message_from_history, "LIME"), TEST_ONE_TAG("Lime transfer message without encryption", lime_transfer_message_without_encryption, "LIME"), TEST_ONE_TAG("Lime transfer message without encryption 2", lime_transfer_message_without_encryption_2, "LIME"), + TEST_ONE_TAG("Lime cache migration", lime_cache_migration, "LIME"), TEST_ONE_TAG("Lime unitary", lime_unit, "LIME"), TEST_NO_TAG("Database migration", database_migration), TEST_NO_TAG("History range", history_range), diff --git a/tester/proxy_config_tester.c b/tester/proxy_config_tester.c index 6f38c30e6..fe71778c6 100644 --- a/tester/proxy_config_tester.c +++ b/tester/proxy_config_tester.c @@ -68,7 +68,7 @@ static void phone_normalization_with_proxy(void) { BC_ASSERT_STRING_EQUAL(phone_normalization(proxy, "+33 (0) 1 23 45 67 89"), "+33123456789"); BC_ASSERT_STRING_EQUAL(phone_normalization(proxy, "+90 (903) 1234567"), "+909031234567"); BC_ASSERT_STRING_EQUAL(phone_normalization(proxy, "0033123456789"), "0033123456789"); - + linphone_proxy_config_set_dial_prefix(proxy, "33"); BC_ASSERT_STRING_EQUAL(phone_normalization(proxy, "123456789"), "+33123456789"); BC_ASSERT_STRING_EQUAL(phone_normalization(proxy, " 0123456789"), "+33123456789"); @@ -179,11 +179,20 @@ static void sip_uri_normalization(void) { SIP_URI_CHECK("١", expected); //test that no more invalid memory writes are made (valgrind only) } +/*static void load_dynamic_proxy_config(void) { + LinphoneProxyConfig *proxy; + + //Load file + + proxy = linphone_proxy_config_new(); +}*/ + test_t proxy_config_tests[] = { TEST_NO_TAG("Phone normalization without proxy", phone_normalization_without_proxy), TEST_NO_TAG("Phone normalization with proxy", phone_normalization_with_proxy), TEST_NO_TAG("Phone normalization with dial escape plus", phone_normalization_with_dial_escape_plus), - TEST_NO_TAG("SIP URI normalization", sip_uri_normalization) + TEST_NO_TAG("SIP URI normalization", sip_uri_normalization), + //TEST_NO_TAG("Load new default value for proxy config", load_dynamic_proxy_config) }; test_suite_t proxy_config_test_suite = {"Proxy config", NULL, NULL, liblinphone_tester_before_each, liblinphone_tester_after_each, diff --git a/tester/rcfiles/assistant_create.rc b/tester/rcfiles/assistant_create.rc new file mode 100644 index 000000000..a4f42a809 --- /dev/null +++ b/tester/rcfiles/assistant_create.rc @@ -0,0 +1,32 @@ + + + +
+ 1 + 0 + 0 + sip:voip-metrics@sip.linphone.org;transport=tls + 1 + 180 + 31536000 + sip:?@sip.linphone.org + 1 + push_notification + sip.linphone.org +
+ +
+ sips:rls@sip.linphone.org +
+ +
+ sip.linphone.org + -1 + 1 + -1 + 64 + 1 + ^[a-z0-9+_.\-]*$ + https://sip3.linphone.org:444/wizard.php +
+
diff --git a/tester/register_tester.c b/tester/register_tester.c index 33819efb7..6989c8b1c 100644 --- a/tester/register_tester.c +++ b/tester/register_tester.c @@ -69,7 +69,7 @@ static void register_with_refresh_base_3(LinphoneCore* lc ,const char* domain ,const char* route ,bool_t late_auth_info - ,LCSipTransports transport + ,LinphoneTransports *transport ,LinphoneRegistrationState expected_final_state) { int retry=0; char* addr; @@ -84,7 +84,7 @@ static void register_with_refresh_base_3(LinphoneCore* lc counters = get_stats(lc); reset_counters(counters); - linphone_core_set_sip_transports(lc,&transport); + linphone_core_set_transports(lc, transport); proxy_cfg = linphone_proxy_config_new(); @@ -141,12 +141,17 @@ static void register_with_refresh_base_2(LinphoneCore* lc ,const char* domain ,const char* route ,bool_t late_auth_info - ,LCSipTransports transport) { + ,LinphoneTransports *transport) { 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) { - LCSipTransports transport = {5070,5070,0,5071}; + LinphoneTransports *transport = linphone_transports_new(); + linphone_transports_set_udp_port(transport, 5070); + linphone_transports_set_tcp_port(transport, 5070); + linphone_transports_set_tls_port(transport, 5071); + linphone_transports_set_dtls_port(transport, 0); register_with_refresh_base_2(lc,refresh,domain,route,FALSE,transport); + linphone_transports_unref(transport); } static void register_with_refresh(LinphoneCoreManager* lcm, bool_t refresh,const char* domain,const char* route) { @@ -281,10 +286,13 @@ static void simple_tcp_register(void){ static void simple_tcp_register_compatibility_mode(void){ char route[256]; LinphoneCoreManager* lcm; - LCSipTransports transport = {0,5070,0,0}; + LinphoneTransports *transport = NULL; sprintf(route,"sip:%s",test_route); lcm = create_lcm(); + transport = linphone_transports_new(); + linphone_transports_set_tcp_port(transport, 5070); register_with_refresh_base_2(lcm->lc,FALSE,test_domain,route,FALSE,transport); + linphone_transports_unref(transport); linphone_core_manager_destroy(lcm); } @@ -356,14 +364,19 @@ static void authenticated_register_with_late_credentials(void){ LinphoneCoreManager *lcm; stats* counters; char route[256]; - LCSipTransports transport = {5070,5070,0,5071}; + LinphoneTransports *transport = NULL; sprintf(route,"sip:%s",test_route); lcm = linphone_core_manager_new(NULL); + transport = linphone_transports_new(); + linphone_transports_set_udp_port(transport, 5070); + linphone_transports_set_tcp_port(transport, 5070); + linphone_transports_set_dtls_port(transport, 5071); counters = get_stats(lcm->lc); register_with_refresh_base_2(lcm->lc,FALSE,auth_domain,route,TRUE,transport); + linphone_transports_unref(transport); BC_ASSERT_EQUAL(counters->number_of_auth_info_requested,1, int, "%d"); linphone_core_manager_destroy(lcm); } @@ -412,7 +425,7 @@ static void authenticated_register_with_provided_credentials(void){ static void authenticated_register_with_wrong_late_credentials(void){ LinphoneCoreManager *lcm; stats* counters; - LCSipTransports transport = {5070,5070,0,5071}; + LinphoneTransports *transport = NULL; char route[256]; const char* saved_test_passwd=test_password; char* wrong_passwd="mot de pass tout pourri"; @@ -422,9 +435,15 @@ 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(); + linphone_transports_set_udp_port(transport, 5070); + linphone_transports_set_tcp_port(transport, 5070); + linphone_transports_set_tls_port(transport, 5071); + linphone_transports_set_dtls_port(transport, 0); counters = get_stats(lcm->lc); register_with_refresh_base_3(lcm->lc,FALSE,auth_domain,route,TRUE,transport,LinphoneRegistrationFailed); + linphone_transports_unref(transport); BC_ASSERT_EQUAL(counters->number_of_auth_info_requested,2, int, "%d"); BC_ASSERT_EQUAL(counters->number_of_LinphoneRegistrationFailed,2, int, "%d"); BC_ASSERT_EQUAL(counters->number_of_LinphoneRegistrationProgress,2, int, "%d"); @@ -435,11 +454,15 @@ 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; - LCSipTransports transport = {5070,5070,0,5071}; + LinphoneTransports *transport = linphone_transports_new(); LinphoneAuthInfo *info=linphone_auth_info_new(test_username,NULL,"wrong passwd",NULL,auth_domain,NULL); /*create authentication structure from identity*/ char route[256]; sprintf(route,"sip:%s",test_route); + linphone_transports_set_udp_port(transport, 5070); + linphone_transports_set_tcp_port(transport, 5070); + linphone_transports_set_tls_port(transport, 5071); + linphone_transports_set_dtls_port(transport, 0); sal_set_refresher_retry_after(lcm->lc->sal,500); if (user_agent) { @@ -449,6 +472,7 @@ static void authenticated_register_with_wrong_credentials_with_params_base(const linphone_auth_info_unref(info); counters = get_stats(lcm->lc); register_with_refresh_base_3(lcm->lc,TRUE,auth_domain,route,FALSE,transport,LinphoneRegistrationFailed); + linphone_transports_unref(transport); //BC_ASSERT_EQUAL(counters->number_of_auth_info_requested,3, int, "%d"); register_with_refresh_base_3 does not alow to precisely check number of number_of_auth_info_requested /*wait for retry*/ BC_ASSERT_TRUE(wait_for(lcm->lc,lcm->lc,&counters->number_of_auth_info_requested,4)); @@ -552,30 +576,32 @@ static void transport_change(void){ LinphoneCore* lc; int register_ok; stats* counters ; - LCSipTransports sip_tr; - LCSipTransports sip_tr_orig; + LinphoneTransports *sip_tr; + LinphoneTransports *sip_tr_orig; int number_of_udp_proxy=0; int total_number_of_proxies; lcm=configure_lcm(); if (lcm) { - memset(&sip_tr,0,sizeof(sip_tr)); lc=lcm->lc; + sip_tr = linphone_transports_new(); counters = get_stats(lc); register_ok=counters->number_of_LinphoneRegistrationOk; number_of_udp_proxy=get_number_of_udp_proxy(lc); total_number_of_proxies=(int)bctbx_list_size(linphone_core_get_proxy_config_list(lc)); - linphone_core_get_sip_transports(lc,&sip_tr_orig); + sip_tr_orig = linphone_core_get_transports(lc); - sip_tr.udp_port=sip_tr_orig.udp_port; + sip_tr->udp_port = sip_tr_orig->udp_port; /*keep only udp*/ - linphone_core_set_sip_transports(lc,&sip_tr); + linphone_core_set_transports(lc, sip_tr); BC_ASSERT_TRUE(wait_for(lc,lc,&counters->number_of_LinphoneRegistrationOk,register_ok+number_of_udp_proxy)); BC_ASSERT_TRUE(wait_for(lc,lc,&counters->number_of_LinphoneRegistrationFailed,total_number_of_proxies-number_of_udp_proxy)); + linphone_transports_unref(sip_tr); + linphone_transports_unref(sip_tr_orig); linphone_core_manager_destroy(lcm); } } @@ -583,20 +609,18 @@ static void transport_change(void){ static void transport_dont_bind(void){ LinphoneCoreManager *pauline = linphone_core_manager_new("pauline_tcp_rc"); stats* counters = &pauline->stat; - LCSipTransports tr; + LinphoneTransports *tr = linphone_transports_new(); + linphone_transports_set_tcp_port(tr, LC_SIP_TRANSPORT_DONTBIND); + linphone_transports_set_tls_port(tr, LC_SIP_TRANSPORT_DONTBIND); - memset(&tr, 0, sizeof(tr)); - tr.udp_port = 0; - tr.tcp_port = LC_SIP_TRANSPORT_DONTBIND; - tr.tls_port = LC_SIP_TRANSPORT_DONTBIND; - - linphone_core_set_sip_transports(pauline->lc, &tr); + linphone_core_set_transports(pauline->lc, tr); BC_ASSERT_TRUE(wait_for_until(pauline->lc,pauline->lc,&counters->number_of_LinphoneRegistrationOk,2,15000)); - memset(&tr, 0, sizeof(tr)); - linphone_core_get_sip_transports_used(pauline->lc, &tr); - 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"); + 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"); + linphone_transports_unref(tr); linphone_core_manager_destroy(pauline); } @@ -666,12 +690,17 @@ 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]; - LCSipTransports transport= {LC_SIP_TRANSPORT_RANDOM,LC_SIP_TRANSPORT_RANDOM,LC_SIP_TRANSPORT_RANDOM,LC_SIP_TRANSPORT_RANDOM}; + LinphoneTransports *transport= linphone_transports_new(); 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); + linphone_transports_set_tls_port(transport, LC_SIP_TRANSPORT_RANDOM); + linphone_transports_set_dtls_port(transport, LC_SIP_TRANSPORT_RANDOM); linphone_core_add_auth_info(lcm->lc,info); /*add authentication info to LinphoneCore*/ linphone_auth_info_unref(info); register_with_refresh_base_3(lcm->lc, FALSE, auth_domain, "sip2.linphone.org:5987", 0,transport,LinphoneRegistrationProgress); + linphone_transports_unref(transport); proxy_config = linphone_core_get_default_proxy_config(lcm->lc); linphone_proxy_config_edit(proxy_config); @@ -697,12 +726,17 @@ 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]; - LCSipTransports transport= {LC_SIP_TRANSPORT_RANDOM,LC_SIP_TRANSPORT_RANDOM,LC_SIP_TRANSPORT_RANDOM,LC_SIP_TRANSPORT_RANDOM}; + LinphoneTransports *transport = linphone_transports_new(); 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); + linphone_transports_set_tls_port(transport, LC_SIP_TRANSPORT_RANDOM); + linphone_transports_set_dtls_port(transport, LC_SIP_TRANSPORT_RANDOM); linphone_core_add_auth_info(lcm->lc,info); /*add authentication info to LinphoneCore*/ linphone_auth_info_unref(info); register_with_refresh_base_3(lcm->lc, FALSE, auth_domain, "sip2.linphone.org:5987", 0,transport,LinphoneRegistrationProgress); + linphone_transports_unref(transport); proxy_config = linphone_core_get_default_proxy_config(lcm->lc); linphone_proxy_config_edit(proxy_config); @@ -980,12 +1014,15 @@ static void tls_wildcard_register(void){ static void redirect(void){ char route[256]; LinphoneCoreManager* lcm; - LCSipTransports transport = {-1,0,0,0}; + LinphoneTransports *transport = NULL; sprintf(route,"sip:%s:5064",test_route); lcm = create_lcm(); if (lcm) { + transport = linphone_transports_new(); + 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); + linphone_transports_unref(transport); linphone_core_manager_destroy(lcm); } } diff --git a/tester/tester.c b/tester/tester.c index 363e84b4e..40f8b43b9 100644 --- a/tester/tester.c +++ b/tester/tester.c @@ -677,6 +677,7 @@ void liblinphone_tester_uninit(void) { static void check_ice_from_rtp(LinphoneCall *c1, LinphoneCall *c2, LinphoneStreamType stream_type) { MediaStream *ms; + LinphoneCallStats *stats; switch (stream_type) { case LinphoneStreamTypeAudio: ms=&c1->audiostream->ms; @@ -693,7 +694,8 @@ static void check_ice_from_rtp(LinphoneCall *c1, LinphoneCall *c2, LinphoneStrea return; } - if (linphone_call_get_audio_stats(c1)->ice_state == LinphoneIceStateHostConnection && media_stream_started(ms)) { + stats = linphone_call_get_audio_stats(c1); + if (stats->ice_state == LinphoneIceStateHostConnection && media_stream_started(ms)) { struct sockaddr_storage remaddr; socklen_t remaddrlen = sizeof(remaddr); char ip[NI_MAXHOST] = { 0 }; @@ -718,6 +720,7 @@ static void check_ice_from_rtp(LinphoneCall *c1, LinphoneCall *c2, LinphoneStrea BC_ASSERT_STRING_EQUAL(ip, expected_addr); } } + linphone_call_stats_unref(stats); } bool_t check_ice(LinphoneCoreManager* caller, LinphoneCoreManager* callee, LinphoneIceState state) { @@ -747,13 +750,17 @@ bool_t check_ice(LinphoneCoreManager* caller, LinphoneCoreManager* callee, Linph liblinphone_tester_clock_start(&ts); do{ if ((c1 != NULL) && (c2 != NULL)) { - if (linphone_call_get_audio_stats(c1)->ice_state==state && - linphone_call_get_audio_stats(c2)->ice_state==state ){ + LinphoneCallStats *stats1 = linphone_call_get_audio_stats(c1); + LinphoneCallStats *stats2 = linphone_call_get_audio_stats(c2); + if (stats1->ice_state==state && + stats2->ice_state==state){ audio_success=TRUE; check_ice_from_rtp(c1,c2,LinphoneStreamTypeAudio); check_ice_from_rtp(c2,c1,LinphoneStreamTypeAudio); break; } + linphone_call_stats_unref(stats1); + linphone_call_stats_unref(stats2); linphone_core_iterate(caller->lc); linphone_core_iterate(callee->lc); } @@ -765,13 +772,17 @@ bool_t check_ice(LinphoneCoreManager* caller, LinphoneCoreManager* callee, Linph liblinphone_tester_clock_start(&ts); do{ if ((c1 != NULL) && (c2 != NULL)) { - if (linphone_call_get_video_stats(c1)->ice_state==state && - linphone_call_get_video_stats(c2)->ice_state==state ){ + LinphoneCallStats *stats1 = linphone_call_get_video_stats(c1); + LinphoneCallStats *stats2 = linphone_call_get_video_stats(c2); + if (stats1->ice_state==state && + stats2->ice_state==state){ video_success=TRUE; check_ice_from_rtp(c1,c2,LinphoneStreamTypeVideo); check_ice_from_rtp(c2,c1,LinphoneStreamTypeVideo); break; } + linphone_call_stats_unref(stats1); + linphone_call_stats_unref(stats2); linphone_core_iterate(caller->lc); linphone_core_iterate(callee->lc); } @@ -783,13 +794,17 @@ bool_t check_ice(LinphoneCoreManager* caller, LinphoneCoreManager* callee, Linph liblinphone_tester_clock_start(&ts); do{ if ((c1 != NULL) && (c2 != NULL)) { - if (linphone_call_get_text_stats(c1)->ice_state==state && - linphone_call_get_text_stats(c2)->ice_state==state ){ + LinphoneCallStats *stats1 = linphone_call_get_text_stats(c1); + LinphoneCallStats *stats2 = linphone_call_get_text_stats(c2); + if (stats1->ice_state==state && + stats2->ice_state==state){ text_success=TRUE; check_ice_from_rtp(c1,c2,LinphoneStreamTypeText); check_ice_from_rtp(c2,c1,LinphoneStreamTypeText); break; } + linphone_call_stats_unref(stats1); + linphone_call_stats_unref(stats2); linphone_core_iterate(caller->lc); linphone_core_iterate(callee->lc); } diff --git a/tester/video_tester.c b/tester/video_tester.c index 0526441d7..54fccaea6 100644 --- a/tester/video_tester.c +++ b/tester/video_tester.c @@ -414,25 +414,35 @@ static void forked_outgoing_early_media_video_call_with_inactive_audio_test(void LinphoneCallParams *pauline_params; LinphoneCallParams *marie1_params; LinphoneCallParams *marie2_params; - LinphoneVideoPolicy pol; + LinphoneVideoActivationPolicy *pol = linphone_video_activation_policy_new(); LinphoneCall *marie1_call; LinphoneCall *marie2_call; LinphoneCall *pauline_call; LinphoneInfoMessage *info; int dummy = 0; - pol.automatically_accept = 1; - pol.automatically_initiate = 1; + pol->automatically_accept = TRUE; + pol->automatically_initiate = TRUE; + LinphoneRange *port_range = NULL; linphone_core_enable_video_capture(pauline->lc, TRUE); linphone_core_enable_video_display(pauline->lc, TRUE); linphone_core_enable_video_capture(marie1->lc, TRUE); linphone_core_enable_video_display(marie1->lc, TRUE); - linphone_core_set_video_policy(marie1->lc, &pol); + linphone_core_set_video_activation_policy(marie1->lc, pol); linphone_core_enable_video_capture(marie2->lc, TRUE); linphone_core_enable_video_display(marie2->lc, TRUE); - linphone_core_set_video_policy(marie2->lc, &pol); + linphone_core_set_video_activation_policy(marie2->lc, pol); + linphone_video_activation_policy_unref(pol); linphone_core_set_audio_port_range(marie2->lc, 40200, 40300); + port_range = linphone_core_get_audio_ports_range(marie2->lc); + BC_ASSERT_EQUAL(port_range->min, 40200, int, "%i"); + BC_ASSERT_EQUAL(port_range->max, 40300, int, "%i"); + linphone_range_unref(port_range); linphone_core_set_video_port_range(marie2->lc, 40400, 40500); + port_range = linphone_core_get_video_ports_range(marie2->lc); + BC_ASSERT_EQUAL(port_range->min, 40400, int, "%i"); + BC_ASSERT_EQUAL(port_range->max, 40500, int, "%i"); + linphone_range_unref(port_range); lcs = bctbx_list_append(lcs,marie1->lc); lcs = bctbx_list_append(lcs,marie2->lc); @@ -471,18 +481,32 @@ static void forked_outgoing_early_media_video_call_with_inactive_audio_test(void BC_ASSERT_PTR_NOT_NULL(marie2_call); if (pauline_call && marie1_call && marie2_call) { + LinphoneCallStats *pauline_audio_stats, *marie1_audio_stats, *marie2_audio_stats; + LinphoneCallStats *pauline_video_stats, *marie1_video_stats, *marie2_video_stats; linphone_call_set_next_video_frame_decoded_callback(pauline_call, linphone_call_iframe_decoded_cb, pauline->lc); /* wait a bit that streams are established */ wait_for_list(lcs, &dummy, 1, 3000); - BC_ASSERT_EQUAL(linphone_call_get_audio_stats(pauline_call)->download_bandwidth, 0, float, "%f"); - BC_ASSERT_EQUAL(linphone_call_get_audio_stats(marie1_call)->download_bandwidth, 0, float, "%f"); - BC_ASSERT_EQUAL(linphone_call_get_audio_stats(marie2_call)->download_bandwidth, 0, float, "%f"); - BC_ASSERT_LOWER(linphone_call_get_video_stats(pauline_call)->download_bandwidth, 11, float, "%f"); /* because of stun packets*/ - BC_ASSERT_GREATER(linphone_call_get_video_stats(marie1_call)->download_bandwidth, 0, float, "%f"); - BC_ASSERT_GREATER(linphone_call_get_video_stats(marie2_call)->download_bandwidth, 0, float, "%f"); + pauline_audio_stats = linphone_call_get_audio_stats(pauline_call); + marie1_audio_stats = linphone_call_get_audio_stats(marie1_call); + marie2_audio_stats = linphone_call_get_audio_stats(marie2_call); + pauline_video_stats = linphone_call_get_video_stats(pauline_call); + marie1_video_stats = linphone_call_get_video_stats(marie1_call); + marie2_video_stats = linphone_call_get_video_stats(marie2_call); + BC_ASSERT_EQUAL(pauline_audio_stats->download_bandwidth, 0, float, "%f"); + BC_ASSERT_EQUAL(marie1_audio_stats->download_bandwidth, 0, float, "%f"); + BC_ASSERT_EQUAL(marie2_audio_stats->download_bandwidth, 0, float, "%f"); + BC_ASSERT_LOWER(pauline_video_stats->download_bandwidth, 11, float, "%f"); /* because of stun packets*/ + BC_ASSERT_GREATER(marie1_video_stats->download_bandwidth, 0, float, "%f"); + BC_ASSERT_GREATER(marie2_video_stats->download_bandwidth, 0, float, "%f"); BC_ASSERT_GREATER(marie1->stat.number_of_IframeDecoded, 1, int, "%i"); BC_ASSERT_GREATER(marie2->stat.number_of_IframeDecoded, 1, int, "%i"); + linphone_call_stats_unref(pauline_audio_stats); + linphone_call_stats_unref(marie1_audio_stats); + linphone_call_stats_unref(marie2_audio_stats); + linphone_call_stats_unref(pauline_video_stats); + linphone_call_stats_unref(marie1_video_stats); + linphone_call_stats_unref(marie2_video_stats); linphone_call_params_set_audio_direction(marie1_params, LinphoneMediaDirectionSendRecv); linphone_call_accept_with_params(linphone_core_get_current_call(marie1->lc), marie1_params); @@ -494,11 +518,19 @@ static void forked_outgoing_early_media_video_call_with_inactive_audio_test(void /*wait a bit that streams are established*/ wait_for_list(lcs, &dummy, 1, 3000); - BC_ASSERT_GREATER(linphone_call_get_audio_stats(pauline_call)->download_bandwidth, 71, float, "%f"); - BC_ASSERT_GREATER(linphone_call_get_audio_stats(marie1_call)->download_bandwidth, 71, float, "%f"); - BC_ASSERT_GREATER(linphone_call_get_video_stats(pauline_call)->download_bandwidth, 0, float, "%f"); - BC_ASSERT_GREATER(linphone_call_get_video_stats(marie1_call)->download_bandwidth, 0, float, "%f"); + pauline_audio_stats = linphone_call_get_audio_stats(pauline_call); + marie1_audio_stats = linphone_call_get_audio_stats(marie1_call); + pauline_video_stats = linphone_call_get_video_stats(pauline_call); + marie1_video_stats = linphone_call_get_video_stats(marie1_call); + BC_ASSERT_GREATER(pauline_audio_stats->download_bandwidth, 71, float, "%f"); + BC_ASSERT_GREATER(marie1_audio_stats->download_bandwidth, 71, float, "%f"); + BC_ASSERT_GREATER(pauline_video_stats->download_bandwidth, 0, float, "%f"); + BC_ASSERT_GREATER(marie1_video_stats->download_bandwidth, 0, float, "%f"); BC_ASSERT_GREATER(pauline->stat.number_of_IframeDecoded, 1, int, "%i"); + linphone_call_stats_unref(pauline_audio_stats); + linphone_call_stats_unref(marie1_audio_stats); + linphone_call_stats_unref(pauline_video_stats); + linphone_call_stats_unref(marie1_video_stats); /* send an INFO in reverse side to check that dialogs are properly established */ info = linphone_core_create_info_message(marie1->lc); diff --git a/tools/genapixml.py b/tools/genapixml.py index 8549e8e25..f2c1fd555 100755 --- a/tools/genapixml.py +++ b/tools/genapixml.py @@ -23,6 +23,7 @@ import string import sys import xml.etree.ElementTree as ET import xml.dom.minidom as minidom +import metadoc class CObject: @@ -31,6 +32,7 @@ class CObject: self.briefDescription = '' self.detailedDescription = None self.deprecated = False + self.briefDoc = None class CEnumValue(CObject): @@ -381,6 +383,7 @@ class Project: if deprecatedNode is not None: ev.deprecated = True ev.briefDescription = ''.join(node.find('./briefdescription').itertext()).strip() + ev.briefDoc = metadoc.Description(node.find('./briefdescription')) ev.detailedDescription = self.__cleanDescription(node.find('./detaileddescription')) return ev @@ -392,6 +395,7 @@ class Project: if deprecatedNode is not None: e.deprecated = True e.briefDescription = ''.join(node.find('./briefdescription').itertext()).strip() + e.briefDoc = metadoc.Description(node.find('./briefdescription')) e.detailedDescription = self.__cleanDescription(node.find('./detaileddescription')) enumvalues = node.findall("enumvalue[@prot='public']") for enumvalue in enumvalues: @@ -414,6 +418,7 @@ class Project: if deprecatedNode is not None: sm.deprecated = True sm.briefDescription = ''.join(node.find('./briefdescription').itertext()).strip() + sm.briefDoc = metadoc.Description(node.find('./briefdescription')) sm.detailedDescription = self.__cleanDescription(node.find('./detaileddescription')) return sm @@ -423,6 +428,7 @@ class Project: if deprecatedNode is not None: s.deprecated = True s.briefDescription = ''.join(node.find('./briefdescription').itertext()).strip() + s.briefDoc = metadoc.Description(node.find('./briefdescription')) s.detailedDescription = self.__cleanDescription(node.find('./detaileddescription')) structmembers = node.findall("sectiondef/memberdef[@kind='variable'][@prot='public']") for structmember in structmembers: @@ -561,6 +567,7 @@ class Project: if deprecatedNode is not None: f.deprecated = True f.briefDescription = ''.join(node.find('./briefdescription').itertext()).strip() + f.briefDoc = metadoc.Description(node.find('./briefdescription')) f.detailedDescription = self.__cleanDescription(node.find('./detaileddescription')) if f.briefDescription == '' and ''.join(f.detailedDescription.itertext()).strip() == '': return None diff --git a/tools/metadoc.py b/tools/metadoc.py new file mode 100644 index 000000000..eb4b6e9d2 --- /dev/null +++ b/tools/metadoc.py @@ -0,0 +1,84 @@ +#!/usr/bin/python + +# 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. + + +class Nil: + pass + + +class Reference: + def __init__(self, name): + self.cObjectName = name + + +class Paragraph: + def __init__(self, node=None): + self.parts = [] + if node is not None: + self.parse_doxygen_node(node) + + def parse_doxygen_node(self, node): + for partNode in node.iter(): + text = partNode.text + if text is not None: + self.parts.append(text) + if partNode is not node: + tail = partNode.tail + if tail is not None: + self.parts.append(tail) + + +class Description: + def __init__(self, node=None): + self.paragraphs = [] + if node is not None: + self.parse_doxygen_node(node) + + def parse_doxygen_node(self, node): + for paraNode in node.findall('./para'): + self.paragraphs.append(Paragraph(paraNode)) + + +class Translator: + def translate(self, description): + lines = [] + for para in description.paragraphs: + if para is not description.paragraphs[0]: + lines.append('') + lines.append(''.join(para.parts)) + + self._tag_as_brief(lines) + + translatedDoc = {'lines': []} + for line in lines: + translatedDoc['lines'].append({'line': line}) + + return translatedDoc + + +class DoxygenCppTranslator(Translator): + def _tag_as_brief(self, lines): + if len(lines) > 0: + lines[0] = '@brief ' + lines[0] + + +class SandcastleCSharpTranslator(Translator): + def _tag_as_brief(self, lines): + if len(lines) > 0: + lines[0] = '' + lines[0] + lines[-1] = lines[-1] + '' diff --git a/wrappers/cpp/CMakeLists.txt b/wrappers/cpp/CMakeLists.txt index 2ff57dd1f..d397d96c0 100644 --- a/wrappers/cpp/CMakeLists.txt +++ b/wrappers/cpp/CMakeLists.txt @@ -23,6 +23,7 @@ add_custom_command(OUTPUT include/linphone++/linphone.hh src/linphone++.cc COMMAND ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/genwrapper.py" "${PROJECT_BINARY_DIR}/coreapi/help/doc/xml" DEPENDS ${PROJECT_SOURCE_DIR}/tools/genapixml.py + "${PROJECT_SOURCE_DIR}/tools/metadoc.py" abstractapi.py genwrapper.py class_header.mustache diff --git a/wrappers/cpp/abstractapi.py b/wrappers/cpp/abstractapi.py index 8f2bf6b44..868320285 100644 --- a/wrappers/cpp/abstractapi.py +++ b/wrappers/cpp/abstractapi.py @@ -586,6 +586,7 @@ class CParser(object): name = EnumName() name.from_camel_case(nameStr, namespace=self.namespace.name) enum = Enum(name) + enum.briefDescription = cenum.briefDoc self.namespace.add_child(enum) for cEnumValue in cenum.values: @@ -619,6 +620,7 @@ class CParser(object): name = ClassName() name.from_camel_case(cclass.name, namespace=self.namespace.name) _class = Class(name) + _class.briefDescription = cclass.briefDoc _class.refcountable = self._class_is_refcountable(cclass) for cproperty in cclass.properties.values(): @@ -686,6 +688,7 @@ class CParser(object): raise Error('{0} is not a listener'.format(cclass.name)) listener = Interface(name) + listener.briefDescription = cclass.briefDoc for property in cclass.properties.values(): if property.name != 'user_data': @@ -733,6 +736,7 @@ class CParser(object): raise BlacklistedException('{0} is blacklisted'.format(name.to_c())); method = Method(name, type=type) + method.briefDescription = cfunction.briefDoc method.deprecated = cfunction.deprecated method.returnType = self.parse_type(cfunction.returnArgument) diff --git a/wrappers/cpp/class_header.mustache b/wrappers/cpp/class_header.mustache index b228eb93f..e6c447914 100644 --- a/wrappers/cpp/class_header.mustache +++ b/wrappers/cpp/class_header.mustache @@ -84,10 +84,24 @@ namespace linphone { {{#methods}} + {{#doc}} + /** + {{#lines}} + * {{{line}}} + {{/lines}} + */ + {{/doc}} {{{prototype}}} {{/methods}} {{#staticMethods}} + {{#doc}} + /** + {{#lines}} + * {{{line}}} + {{/lines}} + */ + {{/doc}} {{{prototype}}} {{/staticMethods}} diff --git a/wrappers/cpp/genwrapper.py b/wrappers/cpp/genwrapper.py index f15046540..34ffd641d 100755 --- a/wrappers/cpp/genwrapper.py +++ b/wrappers/cpp/genwrapper.py @@ -26,6 +26,7 @@ import errno sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', '..', 'tools')) import genapixml as CApi import abstractapi as AbsApi +import metadoc class CppTranslator(object): @@ -240,6 +241,9 @@ class CppTranslator(object): methodDict['implPrototype'] = '{implReturn} {longname}({implParams}){const}'.format(**methodElems) methodDict['sourceCode' ] = self._generate_source_code(method, usedNamespace=namespace) + t = metadoc.DoxygenCppTranslator() + methodDict['doc'] = t.translate(method.briefDescription) if method.briefDescription is not None else None + return methodDict def _generate_source_code(self, method, usedNamespace=None): diff --git a/wrappers/cpp/tools.hh b/wrappers/cpp/tools.hh index f46e398eb..175af14cf 100644 --- a/wrappers/cpp/tools.hh +++ b/wrappers/cpp/tools.hh @@ -100,7 +100,7 @@ namespace linphone { static std::list bctbxListToCppList(const ::bctbx_list_t *bctbxList) { std::list cppList; for(const bctbx_list_t *it = bctbx_list_first_elem(bctbxList); it != NULL; it = bctbx_list_next(it)) { - cppList->push_back(T(it->data)); + cppList.push_back(T(it->data)); } return cppList; }