Merge remote-tracking branch 'linphone/master'

This commit is contained in:
Sylvain Berfini 2017-04-21 14:47:44 +02:00
commit 4f3129d810
73 changed files with 3549 additions and 971 deletions

View file

@ -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()

View file

@ -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)

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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);

View file

@ -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;
}

View file

@ -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);

View file

@ -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);
/*

View file

@ -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:

View file

@ -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;
}

View file

@ -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();
}

View file

@ -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

View file

@ -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
*<b> Multicast </b>
*<br> Call using rtp multicast addresses are supported for both audio and video with some limitations. Limitations are, no stun, no ice, no encryption.
*<br><ul><li> Incoming call with multicast address are automatically accepted. The called party switches in a media receive only mode.</li>
*<br><li> Outgoing call willing to send media to a multicast address can activate multicast using \link linphone_core_enable_video_multicast\endlink or
*\link linphone_core_enable_audio_multicast\endlink . The calling party switches in a media listen send only mode.</li>
*</ul>
* @defgroup media_parameters Media parameters
* @brief Controlling media parameters.
*
* <b>Multicast</b>
*
* 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.<br> 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.
*<br> A created proxy config using linphone_proxy_config_new(), once configured, must be added to #LinphoneCore using function linphone_core_add_proxy_config().
*<br> 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.
*<br> Registration status is reported by LinphoneCoreRegistrationStateChangedCb.
*<br>
*<br> This pseudo code demonstrates basic registration operations:
*<br> \code
* @defgroup proxies Proxies
* @brief Managing proxies.
*
* User registration is controled by #LinphoneProxyConfig settings.<br> 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.
* <br> A created proxy config using linphone_proxy_config_new(), once configured, must be added to #LinphoneCore using function linphone_core_add_proxy_config().
* <br> 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.
* <br> Registration status is reported by LinphoneCoreRegistrationStateChangedCb.
* <br>
* <br> This pseudo code demonstrates basic registration operations:
* <br> \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
<b>Buddies and buddy list</b>
<br>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.
<br>Here under a typical buddy creation:
<br>
\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
<br>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
<br>
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
<b> Publishing presence status </b>
<br>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.
<b>Handling incoming subscription request</b>
<br> 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
<br> For incoming request comming from an unknown buddy, the call back LinphoneCoreVTable.new_subscription_request is invoked.
<br> 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.
*
* <b>Buddies and buddy list</b>
* <br>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.
* <br>Here under a typical buddy creation:
* <br>
* \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
* <br>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
* <br>
* 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
*
*
* <b> Publishing presence status </b>
* <br>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.
*
* <b>Handling incoming subscription request</b>
* <br> 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
* <br> For incoming request comming from an unknown buddy, the call back LinphoneCoreVTable.new_subscription_request is invoked.
*
* <br> A complete tutorial can be found at : \ref buddy_tutorials "Registration tutorial"
*
*
**/
/**
* @defgroup chatroom Chat room and Messaging
<b> Exchanging text messages</b>
<br> 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
<br>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
<br>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
<br> A complete tutorial can be found at : \ref chatroom_tuto "Chat room tutorial"
* @defgroup chatroom Chatroom
* @brief Chat room and Messaging.
*
* <b> Exchanging text messages</b>
* <br> 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
*
* <br>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
* <br>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
* <br> 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:<br>
* 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
*
*<br>
<b>Multitasking</b>
<br> 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.
*/

View file

@ -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;
};

View file

@ -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) {

View file

@ -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 <math.h>
@ -38,13 +36,14 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include <ortp/telephonyevents.h>
#include <mediastreamer2/zrtp.h>
#include <mediastreamer2/dtls_srtp.h>
#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; i<peerUriIndex; i++) {
char *stmt = NULL;
int zuid;
/* create the entry in the ziduri table (it will give us the zuid to be used to insert infos in lime and zrtp tables) */
/* we could use directly the bzrtp_cache_getZuid function, but avoid useless query by directly inserting the data */
stmt = sqlite3_mprintf("INSERT INTO ziduri (zid,selfuri,peeruri) VALUES(?,?,?);");
ret = sqlite3_prepare_v2(db, stmt, -1, &sqlStmt, NULL);
if (ret != SQLITE_OK) {
ms_warning("ZRTP/LIME cache migration: Failed to insert peer ZID %s", peerUri[i]);
return;
}
sqlite3_free(stmt);
sqlite3_bind_blob(sqlStmt, 1, peerZID, 12, SQLITE_TRANSIENT);
sqlite3_bind_text(sqlStmt, 2, selfURI, -1, SQLITE_TRANSIENT);
sqlite3_bind_text(sqlStmt, 3, (const char *)(peerUri[i]), -1, SQLITE_TRANSIENT);
ret = sqlite3_step(sqlStmt);
if (ret!=SQLITE_DONE) {
ms_warning("ZRTP/LIME cache migration: Failed to insert peer ZID %s", peerUri[i]);
return;
}
sqlite3_finalize(sqlStmt);
/* get the zuid created */
zuid = (int)sqlite3_last_insert_rowid(db);
ms_message("ZRTP/LIME cache migration: Inserted self %s peer %s ZID %s sucessfully with zuid %d\n", selfURI, peerUri[i], peerZIDString, zuid);
xmlFree(peerUri[i]);
peerUri[i]=NULL;
/* now insert data in the zrtp and lime table, keep going even if it fails */
if ((ret=bzrtp_cache_write(db, zuid, "zrtp", zrtpColNames, zrtpColValues, zrtpColLengths, 3)) != 0) {
ms_error("ZRTP/LIME cache migration: could not insert data in zrtp table, return value %x", ret);
}
if ((ret=bzrtp_cache_write(db, zuid, "lime", limeColNames, limeColValues, limeColLengths, 7)) != 0) {
ms_error("ZRTP/LIME cache migration: could not insert data in lime table, return value %x", ret);
}
}
}
bctbx_free(zrtpColValues[0]);
bctbx_free(zrtpColValues[1]);
bctbx_free(zrtpColValues[2]);
for (i=0; i<7; i++) {
bctbx_free(limeColValues[i]);
}
xmlFree(peerZIDString);
}
cur = cur->next;
}
}
}
}
}
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){

View file

@ -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

View file

@ -27,6 +27,7 @@
#include "private.h"
#include "bctoolbox/vfs.h"
#include "belle-sip/object.h"
#include "xml2lpc.h"
#include <stdio.h>
#include <stdlib.h>
@ -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(

View file

@ -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;
}

View file

@ -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; /**<Whether video shall be automatically proposed for outgoing calls.*/
bool_t automatically_accept; /**<Whether video shall be automatically accepted for incoming calls*/
};
BELLE_SIP_DECLARE_VPTR_NO_EXPORT(LinphoneVideoActivationPolicy);
LinphoneVideoActivationPolicy *linphone_video_activation_policy_new(void);
/**
* 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().
**/
struct _LinphoneCallStats {
belle_sip_object_t base;
void *user_data;
LinphoneStreamType type; /**< Type of the stream which the stats refer to */
jitter_stats_t jitter_stats; /**<jitter buffer statistics, see oRTP documentation for details */
mblk_t *received_rtcp; /**<Last RTCP packet received, as a mblk_t structure. See oRTP documentation for details how to extract information from it*/
mblk_t *sent_rtcp;/**<Last RTCP packet sent, as a mblk_t structure. See oRTP documentation for details how to extract information from it*/
float round_trip_delay; /**<Round trip propagation time in seconds if known, -1 if unknown.*/
LinphoneIceState ice_state; /**< State of ICE processing. */
LinphoneUpnpState upnp_state; /**< State of uPnP processing. */
float download_bandwidth; /**<Download bandwidth measurement of received stream, expressed in kbit/s, including IP/UDP/RTP headers*/
float upload_bandwidth; /**<Download bandwidth measurement of sent stream, expressed in kbit/s, including IP/UDP/RTP headers*/
float local_late_rate; /**<percentage of packet received too late over last second*/
float local_loss_rate; /**<percentage of lost packet over last second*/
int updated; /**< Tell which RTCP packet has been updated (received_rtcp or sent_rtcp). Can be either LINPHONE_CALL_STATS_RECEIVED_RTCP_UPDATE or LINPHONE_CALL_STATS_SENT_RTCP_UPDATE */
float rtcp_download_bandwidth; /**<RTCP download bandwidth measurement of received stream, expressed in kbit/s, including IP/UDP/RTP headers*/
float rtcp_upload_bandwidth; /**<RTCP download bandwidth measurement of sent stream, expressed in kbit/s, including IP/UDP/RTP headers*/
rtp_stats_t rtp_stats; /**< RTP stats */
int rtp_remote_family; /**< Ip adress family of the remote destination */
int clockrate; /*RTP clockrate of the stream, provided here for easily converting timestamp units expressed in RTCP packets in milliseconds*/
bool_t rtcp_received_via_mux; /*private flag, for non-regression test only*/
};
BELLE_SIP_DECLARE_VPTR_NO_EXPORT(LinphoneCallStats);
LinphoneCallStats *linphone_call_stats_new(void);
/** Belle Sip-based objects need unique ids
*/
@ -1769,7 +1855,12 @@ BELLE_SIP_TYPE_ID(LinphoneErrorInfo),
BELLE_SIP_TYPE_ID(LinphoneConferenceParams),
BELLE_SIP_TYPE_ID(LinphoneConference),
BELLE_SIP_TYPE_ID(LinphoneInfoMessage),
BELLE_SIP_TYPE_ID(LinphonePayloadType)
BELLE_SIP_TYPE_ID(LinphonePayloadType),
BELLE_SIP_TYPE_ID(LinphoneRange),
BELLE_SIP_TYPE_ID(LinphoneVideoDefinition),
BELLE_SIP_TYPE_ID(LinphoneTransports),
BELLE_SIP_TYPE_ID(LinphoneVideoActivationPolicy),
BELLE_SIP_TYPE_ID(LinphoneCallStats)
BELLE_SIP_DECLARE_TYPES_END
@ -1783,8 +1874,6 @@ void linphone_core_notify_display_status(LinphoneCore *lc, const char *message);
void linphone_core_notify_display_message(LinphoneCore *lc, const char *message);
void linphone_core_notify_display_warning(LinphoneCore *lc, const char *message);
void linphone_core_notify_display_url(LinphoneCore *lc, const char *message, const char *url);
void linphone_core_notify_notify_presence_received(LinphoneCore *lc, LinphoneFriend * lf);
void linphone_core_notify_notify_presence_received_for_uri_or_tel(LinphoneCore *lc, LinphoneFriend *lf, const char *uri_or_tel, const LinphonePresenceModel *presence_model);
void linphone_core_notify_new_subscription_requested(LinphoneCore *lc, LinphoneFriend *lf, const char *url);
void linphone_core_notify_auth_info_requested(LinphoneCore *lc, const char *realm, const char *username, const char *domain);
void linphone_core_notify_authentication_requested(LinphoneCore *lc, LinphoneAuthInfo *auth_info, LinphoneAuthMethod method);
@ -1909,6 +1998,21 @@ BELLE_SIP_DECLARE_VPTR_NO_EXPORT(LinphoneErrorInfo);
void linphone_core_report_call_log(LinphoneCore *lc, LinphoneCallLog *call_log);
void linphone_core_report_early_failed_call(LinphoneCore *lc, LinphoneCallDir dir, LinphoneAddress *from, LinphoneAddress *to, LinphoneErrorInfo *ei);
struct _LinphoneVideoDefinition {
belle_sip_object_t base;
void *user_data;
unsigned int width; /**< The width of the video */
unsigned int height; /**< The height of the video */
char *name; /** The name of the video definition */
};
BELLE_SIP_DECLARE_VPTR_NO_EXPORT(LinphoneVideoDefinition);
LinphoneVideoDefinition * linphone_video_definition_new(unsigned int width, unsigned int height, const char *name);
LinphoneVideoDefinition * linphone_factory_find_supported_video_definition(const LinphoneFactory *factory, unsigned int width, unsigned int height);
LinphoneVideoDefinition * linphone_factory_find_supported_video_definition_by_name(const LinphoneFactory *factory, const char *name);
#ifdef __cplusplus
}
#endif

View file

@ -107,6 +107,7 @@ static void linphone_proxy_config_init(LinphoneCore* lc, LinphoneProxyConfig *cf
const char *contact_params = lc ? lp_config_get_default_string(lc->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;

View file

@ -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) ?

View file

@ -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);

114
coreapi/video_definition.c Normal file
View file

@ -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);
}

View file

@ -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));
}

View file

@ -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);
}

View file

@ -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);

View file

@ -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){

View file

@ -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);

View file

@ -60,6 +60,7 @@ set(HEADER_FILES
tunnel.h
types.h
vcard.h
video_definition.h
wrapper_utils.h
xmlrpc.h

View file

@ -40,6 +40,7 @@ linphone_include_HEADERS=\
tunnel.h \
types.h \
vcard.h \
video_definition.h \
wrapper_utils.h \
xmlrpc.h \
linphonecore.h \

View file

@ -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);
/**
* @}

View file

@ -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

View file

@ -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).

View file

@ -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; /**<jitter buffer statistics, see oRTP documentation for details */
mblk_t *received_rtcp; /**<Last RTCP packet received, as a mblk_t structure. See oRTP documentation for details how to extract information from it*/
mblk_t *sent_rtcp;/**<Last RTCP packet sent, as a mblk_t structure. See oRTP documentation for details how to extract information from it*/
float round_trip_delay; /**<Round trip propagation time in seconds if known, -1 if unknown.*/
LinphoneIceState ice_state; /**< State of ICE processing. */
LinphoneUpnpState upnp_state; /**< State of uPnP processing. */
float download_bandwidth; /**<Download bandwidth measurement of received stream, expressed in kbit/s, including IP/UDP/RTP headers*/
float upload_bandwidth; /**<Download bandwidth measurement of sent stream, expressed in kbit/s, including IP/UDP/RTP headers*/
float local_late_rate; /**<percentage of packet received too late over last second*/
float local_loss_rate; /**<percentage of lost packet over last second*/
int updated; /**< Tell which RTCP packet has been updated (received_rtcp or sent_rtcp). Can be either LINPHONE_CALL_STATS_RECEIVED_RTCP_UPDATE or LINPHONE_CALL_STATS_SENT_RTCP_UPDATE */
float rtcp_download_bandwidth; /**<RTCP download bandwidth measurement of received stream, expressed in kbit/s, including IP/UDP/RTP headers*/
float rtcp_upload_bandwidth; /**<RTCP download bandwidth measurement of sent stream, expressed in kbit/s, including IP/UDP/RTP headers*/
rtp_stats_t rtp_stats; /**< RTP stats */
int rtp_remote_family; /**< Ip adress family of the remote destination */
int clockrate; /*RTP clockrate of the stream, provided here for easily converting timestamp units expressed in RTCP packets in milliseconds*/
bool_t rtcp_received_via_mux; /*private flag, for non-regression test only*/
};
LINPHONE_PUBLIC LinphoneCallStats *linphone_call_stats_ref(LinphoneCallStats *stats);
/**
* Decrement refcount and possibly free the object.
* @param[in] stats LinphoneCallStats object
* @ingroup misc
**/
LINPHONE_PUBLIC void linphone_call_stats_unref(LinphoneCallStats *stats);
/**
* Gets the user data in the LinphoneCallStats object
* @param[in] stats the LinphoneCallStats
* @return the user data
* @ingroup misc
*/
LINPHONE_PUBLIC void *linphone_call_stats_get_user_data(const LinphoneCallStats *stats);
/**
* Sets the user data in the LinphoneCallStats object
* @param[in] stats the LinphoneCallStats object
* @param[in] data the user data
* @ingroup misc
*/
LINPHONE_PUBLIC void linphone_call_stats_set_user_data(LinphoneCallStats *stats, void *data);
/**
* Get the type of the stream the stats refer to.
@ -87,6 +88,18 @@ LINPHONE_PUBLIC float linphone_call_stats_get_sender_loss_rate(const LinphoneCal
**/
LINPHONE_PUBLIC float linphone_call_stats_get_receiver_loss_rate(const LinphoneCallStats *stats);
/**
* Get the local loss rate since last report
* @return The local loss rate
**/
LINPHONE_PUBLIC float linphone_call_stats_get_local_loss_rate(const LinphoneCallStats *stats);
/**
* Gets the local late rate since last report
* @return The local late rate
**/
LINPHONE_PUBLIC float linphone_call_stats_get_local_late_rate(const LinphoneCallStats *stats);
/**
* Gets the local interarrival jitter
* @param[in] stats LinphoneCallStats object
@ -152,6 +165,13 @@ LINPHONE_PUBLIC LinphoneAddressFamily linphone_call_stats_get_ip_family_of_remot
*/
LINPHONE_PUBLIC float linphone_call_stats_get_jitter_buffer_size_ms(const LinphoneCallStats *stats);
/**
* Get the round trip delay in s.
* @param[in] stats LinphoneCallStats object
* @return The round trip delay in s.
*/
LINPHONE_PUBLIC float linphone_call_stats_get_round_trip_delay(const LinphoneCallStats *stats);
/**
* @}
*/

View file

@ -62,6 +62,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "linphone/proxy_config.h"
#include "linphone/ringtoneplayer.h"
#include "linphone/vcard.h"
#include "linphone/video_definition.h"
#include "linphone/xmlrpc.h"
@ -2104,10 +2105,12 @@ LINPHONE_PUBLIC int linphone_core_get_audio_port(const LinphoneCore *lc);
LINPHONE_PUBLIC void linphone_core_get_audio_port_range(const LinphoneCore *lc, int *min_port, int *max_port);
/**
* Overload of linphone_core_get_audio_port_range().
* Get the audio port range from which is randomly chosen the UDP port used for audio streaming.
* @param[in] lc LinphoneCore object
* @return a LinphoneRange object
* @ingroup network_parameters
*/
LINPHONE_PUBLIC LinphoneIntRange linphone_core_get_audio_port_range_2(const LinphoneCore *lc);
LINPHONE_PUBLIC LinphoneRange *linphone_core_get_audio_ports_range(const LinphoneCore *lc);
/**
* Gets the UDP port used for video streaming.
@ -2128,10 +2131,12 @@ LINPHONE_PUBLIC int linphone_core_get_video_port(const LinphoneCore *lc);
LINPHONE_PUBLIC void linphone_core_get_video_port_range(const LinphoneCore *lc, int *min_port, int *max_port);
/**
* Overload of linphone_core_get_video_port_range().
* Get the video port range from which is randomly chosen the UDP port used for video streaming.
* @param[in] lc LinphoneCore object
* @return a LinphoneRange object
* @ingroup network_parameters
*/
LINPHONE_PUBLIC LinphoneIntRange linphone_core_get_video_port_range_2(const LinphoneCore *lc);
LINPHONE_PUBLIC LinphoneRange *linphone_core_get_video_ports_range(const LinphoneCore *lc);
/**
* Gets the UDP port used for text streaming.
@ -2152,10 +2157,12 @@ LINPHONE_PUBLIC int linphone_core_get_text_port(const LinphoneCore *lc);
LINPHONE_PUBLIC void linphone_core_get_text_port_range(const LinphoneCore *lc, int *min_port, int *max_port);
/**
* Overload of linphone_core_get_text_port_range().
* Get the text port range from which is randomly chosen the UDP port used for text streaming.
* @param[in] lc LinphoneCore object
* @return a LinphoneRange object
* @ingroup network_parameters
*/
LINPHONE_PUBLIC LinphoneIntRange linphone_core_get_text_port_range_2(const LinphoneCore *lc);
LINPHONE_PUBLIC LinphoneRange *linphone_core_get_text_ports_range(const LinphoneCore *lc);
/**
* Gets the value of the no-rtp timeout.
@ -2296,6 +2303,8 @@ LINPHONE_PUBLIC LINPHONE_DEPRECATED int linphone_core_get_sip_port(LinphoneCore
* @param[in] transports A LinphoneSipTransports structure giving the ports to use
* @return 0
* @ingroup network_parameters
* @deprecated Use linphone_core_set_transports instead
* @donotwrap
**/
LINPHONE_PUBLIC LinphoneStatus linphone_core_set_sip_transports(LinphoneCore *lc, const LinphoneSipTransports *transports);
@ -2307,6 +2316,7 @@ LINPHONE_PUBLIC LinphoneStatus linphone_core_set_sip_transports(LinphoneCore *lc
* @param[out] transports A #LinphoneSipTransports structure that will receive the configured ports
* @return 0
* @ingroup network_parameters
* @deprecated
* @donotwrap
**/
LINPHONE_PUBLIC LinphoneStatus linphone_core_get_sip_transports(LinphoneCore *lc, LinphoneSipTransports *transports);
@ -2318,10 +2328,136 @@ LINPHONE_PUBLIC LinphoneStatus linphone_core_get_sip_transports(LinphoneCore *lc
* @param[in] lc LinphoneCore object
* @param[out] tr A #LinphoneSipTransports structure that will receive the ports being used
* @ingroup network_parameters
* @deprecated Use linphone_core_get_transports_used instead
* @donotwrap
**/
LINPHONE_PUBLIC void linphone_core_get_sip_transports_used(LinphoneCore *lc, LinphoneSipTransports *tr);
/**
* Sets the ports to be used for each of transport (UDP or TCP)
* A zero value port for a given transport means the transport
* is not used. A value of LC_SIP_TRANSPORT_RANDOM (-1) means the port is to be choosen randomly by the system.
* @param[in] lc LinphoneCore object
* @param[in] transports A LinphoneSipTransports structure giving the ports to use
* @return 0
* @ingroup network_parameters
**/
LINPHONE_PUBLIC LinphoneStatus linphone_core_set_transports(LinphoneCore *lc, const LinphoneTransports *transports);
/**
* Retrieves the port configuration used for each transport (udp, tcp, tls).
* A zero value port for a given transport means the transport
* is not used. A value of LC_SIP_TRANSPORT_RANDOM (-1) means the port is to be chosen randomly by the system.
* @param[in] lc LinphoneCore object
* @return A #LinphoneTransports structure with the configured ports
* @ingroup network_parameters
**/
LINPHONE_PUBLIC LinphoneTransports *linphone_core_get_transports(LinphoneCore *lc);
/**
* Retrieves the real port number assigned for each sip transport (udp, tcp, tls).
* A zero value means that the transport is not activated.
* If LC_SIP_TRANSPORT_RANDOM was passed to linphone_core_set_sip_transports(), the random port choosed by the system is returned.
* @param[in] lc LinphoneCore object
* @return A #LinphoneTransports structure with the ports being used
* @ingroup network_parameters
**/
LINPHONE_PUBLIC LinphoneTransports *linphone_core_get_transports_used(LinphoneCore *lc);
/**
* Increment refcount.
* @param[in] transports LinphoneTransports object
* @ingroup network_parameters
**/
LINPHONE_PUBLIC LinphoneTransports *linphone_transports_ref(LinphoneTransports *transports);
/**
* Decrement refcount and possibly free the object.
* @param[in] transports LinphoneTransports object
* @ingroup network_parameters
**/
LINPHONE_PUBLIC void linphone_transports_unref(LinphoneTransports *transports);
/**
* Gets the user data in the LinphoneTransports object
* @param[in] transports the LinphoneTransports
* @return the user data
* @ingroup network_parameters
*/
LINPHONE_PUBLIC void *linphone_transports_get_user_data(const LinphoneTransports *transports);
/**
* Sets the user data in the LinphoneTransports object
* @param[in] transports the LinphoneTransports object
* @param[in] data the user data
* @ingroup network_parameters
*/
LINPHONE_PUBLIC void linphone_transports_set_user_data(LinphoneTransports *transports, void *data);
/**
* Gets the UDP port in the LinphoneTransports object
* @param[in] transports the LinphoneTransports object
* @return the UDP port
* @ingroup network_parameters
*/
LINPHONE_PUBLIC int linphone_transports_get_udp_port(const LinphoneTransports* transports);
/**
* Gets the TCP port in the LinphoneTransports object
* @param[in] transports the LinphoneTransports object
* @return the TCP port
* @ingroup network_parameters
*/
LINPHONE_PUBLIC int linphone_transports_get_tcp_port(const LinphoneTransports* transports);
/**
* Gets the TLS port in the LinphoneTransports object
* @param[in] transports the LinphoneTransports object
* @return the TLS port
* @ingroup network_parameters
*/
LINPHONE_PUBLIC int linphone_transports_get_tls_port(const LinphoneTransports* transports);
/**
* Gets the DTLS port in the LinphoneTransports object
* @param[in] transports the LinphoneTransports object
* @return the DTLS port
* @ingroup network_parameters
*/
LINPHONE_PUBLIC int linphone_transports_get_dtls_port(const LinphoneTransports* transports);
/**
* Sets the UDP port in the LinphoneTransports object
* @param[in] transports the LinphoneTransports object
* @param[in] port the UDP port
* @ingroup network_parameters
*/
LINPHONE_PUBLIC void linphone_transports_set_udp_port(LinphoneTransports *transports, int port);
/**
* Sets the TCP port in the LinphoneTransports object
* @param[in] transports the LinphoneTransports object
* @param[in] port the TCP port
* @ingroup network_parameters
*/
LINPHONE_PUBLIC void linphone_transports_set_tcp_port(LinphoneTransports *transports, int port);
/**
* Sets the TLS port in the LinphoneTransports object
* @param[in] transports the LinphoneTransports object
* @param[in] port the TLS port
* @ingroup network_parameters
*/
LINPHONE_PUBLIC void linphone_transports_set_tls_port(LinphoneTransports *transports, int port);
/**
* Sets the DTLS port in the LinphoneTransports object
* @param[in] transports the LinphoneTransports object
* @param[in] port the DTLS port
* @ingroup network_parameters
*/
LINPHONE_PUBLIC void linphone_transports_set_dtls_port(LinphoneTransports *transports, int port);
/**
* Tells whether the given transport type is supported by the library.
* @param[in] lc LinphoneCore object
@ -2789,7 +2925,7 @@ LINPHONE_PUBLIC void linphone_core_set_ring_during_incoming_early_media(Linphone
/**
* Tells whether the ring play is enabled during an incoming early media call.
* @param[in] lc #LinphoneCore object
* @ingroup media_paramaters
* @ingroup media_parameters
*/
LINPHONE_PUBLIC bool_t linphone_core_get_ring_during_incoming_early_media(const LinphoneCore *lc);
@ -3073,11 +3209,13 @@ LINPHONE_PUBLIC bool_t linphone_core_video_display_enabled(LinphoneCore *lc);
* This policy defines whether:
* - video shall be initiated by default for outgoing calls
* - video shall be accepter by default for incoming calls
*
* @param[in] lc LinphoneCore object
* @param[in] policy The video policy to use
* @ingroup media_parameters
* @deprecated
**/
LINPHONE_PUBLIC void linphone_core_set_video_policy(LinphoneCore *lc, const LinphoneVideoPolicy *policy);
LINPHONE_PUBLIC LINPHONE_DEPRECATED void linphone_core_set_video_policy(LinphoneCore *lc, const LinphoneVideoPolicy *policy);
/**
* Get the default policy for video.
@ -3085,14 +3223,107 @@ LINPHONE_PUBLIC void linphone_core_set_video_policy(LinphoneCore *lc, const Linp
* @param[in] lc LinphoneCore object
* @return The video policy being used
* @ingroup media_parameters
* @deprecated
**/
LINPHONE_PUBLIC const LinphoneVideoPolicy *linphone_core_get_video_policy(const LinphoneCore *lc);
LINPHONE_PUBLIC LINPHONE_DEPRECATED const LinphoneVideoPolicy *linphone_core_get_video_policy(const LinphoneCore *lc);
/**
* Increment refcount.
* @param[in] policy LinphoneVideoActivationPolicy object
* @ingroup media_parameters
**/
LINPHONE_PUBLIC LinphoneVideoActivationPolicy *linphone_video_activation_policy_ref(LinphoneVideoActivationPolicy *policy);
/**
* Decrement refcount and possibly free the object.
* @param[in] policy LinphoneVideoActivationPolicy object
* @ingroup media_parameters
**/
LINPHONE_PUBLIC void linphone_video_activation_policy_unref(LinphoneVideoActivationPolicy *policy);
/**
* Gets the user data in the LinphoneVideoActivationPolicy object
* @param[in] policy the LinphoneVideoActivationPolicy
* @return the user data
* @ingroup media_parameters
*/
LINPHONE_PUBLIC void *linphone_video_activation_policy_get_user_data(const LinphoneVideoActivationPolicy *policy);
/**
* Sets the user data in the LinphoneVideoActivationPolicy object
* @param[in] policy the LinphoneVideoActivationPolicy object
* @param[in] data the user data
* @ingroup media_parameters
*/
LINPHONE_PUBLIC void linphone_video_activation_policy_set_user_data(LinphoneVideoActivationPolicy *policy, void *data);
/**
* Gets the value for the automatically accept video policy
* @param[in] policy the LinphoneVideoActivationPolicy object
* @return whether or not to automatically accept video requests is enabled
* @ingroup media_parameters
*/
LINPHONE_PUBLIC bool_t linphone_video_activation_policy_get_automatically_accept(const LinphoneVideoActivationPolicy *policy);
/**
* Gets the value for the automatically initiate video policy
* @param[in] policy the LinphoneVideoActivationPolicy object
* @return whether or not to automatically initiate video calls is enabled
* @ingroup media_parameters
*/
LINPHONE_PUBLIC bool_t linphone_video_activation_policy_get_automatically_initiate(const LinphoneVideoActivationPolicy *policy);
/**
* Sets the value for the automatically accept video policy
* @param[in] policy the LinphoneVideoActivationPolicy object
* @param[in] enable whether or not to enable automatically accept video requests
* @ingroup media_parameters
*/
LINPHONE_PUBLIC void linphone_video_activation_policy_set_automatically_accept(LinphoneVideoActivationPolicy *policy, bool_t enable);
/**
* Sets the value for the automatically initiate video policy
* @param[in] policy the LinphoneVideoActivationPolicy object
* @param[in] enable whether or not to enable automatically initiate video calls
* @ingroup media_parameters
*/
LINPHONE_PUBLIC void linphone_video_activation_policy_set_automatically_initiate(LinphoneVideoActivationPolicy *policy, bool_t enable);
/**
* Sets the default policy for video.
* This policy defines whether:
* - video shall be initiated by default for outgoing calls
* - video shall be accepted by default for incoming calls
* @param[in] lc LinphoneCore object
* @param[in] policy The video policy to use
* @ingroup media_parameters
**/
LINPHONE_PUBLIC void linphone_core_set_video_activation_policy(LinphoneCore *lc, const LinphoneVideoActivationPolicy *policy);
/**
* Get the default policy for video.
* See linphone_core_set_video_activation_policy() for more details.
* @param[in] lc LinphoneCore object
* @return The video policy being used
* @ingroup media_parameters
**/
LINPHONE_PUBLIC LinphoneVideoActivationPolicy *linphone_core_get_video_activation_policy(const LinphoneCore *lc);
/**
* Returns the zero terminated table of supported video resolutions.
* @ingroup media_parameters
* @deprecated Use linphone_factory_get_supported_video_definitions() instead
**/
LINPHONE_PUBLIC const MSVideoSizeDef *linphone_core_get_supported_video_sizes(LinphoneCore *lc);
LINPHONE_PUBLIC LINPHONE_DEPRECATED const MSVideoSizeDef *linphone_core_get_supported_video_sizes(LinphoneCore *lc);
/**
* Set the preferred video definition for the stream that is captured and sent to the remote party.
* All standard video definitions are accepted on the receive path.
* @param[in] lc LinphoneCore object
* @param[in] vdef LinphoneVideoDefinition object
* @ingroup media_parameters
*/
LINPHONE_PUBLIC void linphone_core_set_preferred_video_definition(LinphoneCore *lc, LinphoneVideoDefinition *vdef);
/**
* Sets the preferred video size.
@ -3100,8 +3331,20 @@ LINPHONE_PUBLIC const MSVideoSizeDef *linphone_core_get_supported_video_sizes(Li
* This applies only to the stream that is captured and sent to the remote party,
* since we accept all standard video size on the receive path.
* @ingroup media_parameters
* @deprecated Use linphone_core_set_preferred_video_definition() instead
**/
LINPHONE_PUBLIC void linphone_core_set_preferred_video_size(LinphoneCore *lc, MSVideoSize vsize);
LINPHONE_PUBLIC LINPHONE_DEPRECATED void linphone_core_set_preferred_video_size(LinphoneCore *lc, MSVideoSize vsize);
/**
* Set the video definition for the captured (preview) video.
* This method is for advanced usage where a video capture must be set independently of the definition of the stream actually sent through the call.
* This allows for example to have the preview window in High Definition even if due to bandwidth constraint the sent video definition is small.
* Using this feature increases the CPU consumption, since a rescaling will be done internally.
* @param[in] lc LinphoneCore object
* @param[in] vdef LinphoneVideoDefinition object
* @ingroup media_parameters
*/
LINPHONE_PUBLIC void linphone_core_set_preview_video_definition(LinphoneCore *lc, LinphoneVideoDefinition *vdef);
/**
* Sets the video size for the captured (preview) video.
@ -3111,25 +3354,47 @@ LINPHONE_PUBLIC void linphone_core_set_preferred_video_size(LinphoneCore *lc, MS
* @ingroup media_parameters
* @param lc the linphone core
* @param vsize the video resolution choosed for capuring and previewing. It can be (0,0) to not request any specific preview size and let the core optimize the processing.
* @deprecated Use linphone_core_set_preview_video_definition() instead
**/
LINPHONE_PUBLIC void linphone_core_set_preview_video_size(LinphoneCore *lc, MSVideoSize vsize);
LINPHONE_PUBLIC LINPHONE_DEPRECATED void linphone_core_set_preview_video_size(LinphoneCore *lc, MSVideoSize vsize);
/**
* Sets the preview video size by its name. See linphone_core_set_preview_video_size() for more information about this feature.
*
* Video resolution names are: qcif, svga, cif, vga, 4cif, svga ...
* @ingroup media_parameters
* @deprecated Use linphone_factory_create_video_definition_from_name() and linphone_core_set_preview_video_definition() instead
**/
LINPHONE_PUBLIC void linphone_core_set_preview_video_size_by_name(LinphoneCore *lc, const char *name);
/**
* Get the definition of the captured video.
* @param[in] lc LinphoneCore object
* @return The captured LinphoneVideoDefinition if it was previously set by linphone_core_set_preview_video_definition(), otherwise a 0x0 LinphoneVideoDefinition.
* @see linphone_core_set_preview_video_definition()
* @ingroup media_parameters
*/
LINPHONE_PUBLIC const LinphoneVideoDefinition * linphone_core_get_preview_video_definition(const LinphoneCore *lc);
/**
* Returns video size for the captured video if it was previously set by linphone_core_set_preview_video_size(), otherwise returns a 0,0 size.
* @see linphone_core_set_preview_video_size()
* @ingroup media_parameters
* @param lc the core
* @return a MSVideoSize
* @deprecated Use linphone_core_get_preview_video_definition() instead
**/
LINPHONE_PUBLIC MSVideoSize linphone_core_get_preview_video_size(const LinphoneCore *lc);
LINPHONE_PUBLIC LINPHONE_DEPRECATED MSVideoSize linphone_core_get_preview_video_size(const LinphoneCore *lc);
/**
* Get the effective video definition provided by the camera for the captured video.
* When preview is disabled or not yet started this function returns a 0x0 video definition.
* @param[in] lc LinphoneCore object
* @return The captured LinphoneVideoDefinition
* @ingroup media_parameters
* @see linphone_core_set_preview_video_definition()
*/
LINPHONE_PUBLIC LinphoneVideoDefinition * linphone_core_get_current_preview_video_definition(const LinphoneCore *lc);
/**
* Returns the effective video size for the captured video as provided by the camera.
@ -3138,20 +3403,30 @@ LINPHONE_PUBLIC MSVideoSize linphone_core_get_preview_video_size(const LinphoneC
* @ingroup media_parameters
* @param lc the core
* @return a MSVideoSize
* @deprecated Use linphone_core_get_current_preview_video_definition() instead
**/
LINPHONE_PUBLIC MSVideoSize linphone_core_get_current_preview_video_size(const LinphoneCore *lc);
LINPHONE_PUBLIC LINPHONE_DEPRECATED MSVideoSize linphone_core_get_current_preview_video_size(const LinphoneCore *lc);
/**
* Get the preferred video definition for the stream that is captured and sent to the remote party.
* @param[in] lc LinphoneCore object
* @return The preferred LinphoneVideoDefinition
* @ingroup media_parameters
*/
LINPHONE_PUBLIC const LinphoneVideoDefinition * linphone_core_get_preferred_video_definition(const LinphoneCore *lc);
/**
* Returns the current preferred video size for sending.
*
* @ingroup media_parameters
* @deprecated Use linphone_core_get_preferred_video_definition() instead
**/
LINPHONE_PUBLIC MSVideoSize linphone_core_get_preferred_video_size(const LinphoneCore *lc);
LINPHONE_PUBLIC LINPHONE_DEPRECATED MSVideoSize linphone_core_get_preferred_video_size(const LinphoneCore *lc);
/**
* Get the name of the current preferred video size for sending.
* @param[in] lc #LinphoneCore object.
* @return A string containing the name of the current preferred video size (to be freed with ms_free()).
* @deprecated Use linphone_core_get_preferred_video_defintion() and linphone_video_definition_get_name() instead
*/
LINPHONE_PUBLIC char * linphone_core_get_preferred_video_size_name(const LinphoneCore *lc);
@ -3162,6 +3437,7 @@ LINPHONE_PUBLIC char * linphone_core_get_preferred_video_size_name(const Linphon
* that it takes the name of the video resolution as input.
* Video resolution names are: qcif, svga, cif, vga, 4cif, svga ...
* @ingroup media_parameters
* @deprecated Use linphone_factory_create_video_definition_from_name() and linphone_core_set_preferred_video_definition() instead
**/
LINPHONE_PUBLIC void linphone_core_set_preferred_video_size_by_name(LinphoneCore *lc, const char *name);
@ -3184,6 +3460,13 @@ LINPHONE_PUBLIC void linphone_core_set_preferred_framerate(LinphoneCore *lc, flo
**/
LINPHONE_PUBLIC float linphone_core_get_preferred_framerate(LinphoneCore *lc);
/**
* Call generic OpenGL render for a given core.
* @param lc The core.
* @ingroup media_parameters
*/
LINPHONE_PUBLIC void linphone_core_preview_ogl_render(const LinphoneCore *lc);
/**
* Controls video preview enablement.
* @param[in] lc LinphoneCore object
@ -3655,18 +3938,16 @@ LINPHONE_PUBLIC void linphone_core_refresh_registers(LinphoneCore* lc);
* @param[in] lc #LinphoneCore object
* @param[in] file The path to the file to use to store the zrtp secrets cache.
* @ingroup initializing
* @deprecated cache is now hold as sqlite db, use linphone_core_set_zrtp_cache_database_path to set path to the db and open it
*/
LINPHONE_PUBLIC LINPHONE_DEPRECATED void linphone_core_set_zrtp_secrets_file(LinphoneCore *lc, const char* file);
LINPHONE_PUBLIC void linphone_core_set_zrtp_secrets_file(LinphoneCore *lc, const char* file);
/**
* Get the path to the file storing the zrtp secrets cache.
* @param[in] lc #LinphoneCore object.
* @return The path to the file storing the zrtp secrets cache.
* @ingroup initializing
* @deprecated cache is now hold as sqlite db, use linphone_core_get_zrtp_cache_db to get a pointer to it
*/
LINPHONE_PUBLIC LINPHONE_DEPRECATED const char *linphone_core_get_zrtp_secrets_file(LinphoneCore *lc);
LINPHONE_PUBLIC const char *linphone_core_get_zrtp_secrets_file(LinphoneCore *lc);
/**
* Get a pointer to the sqlite db holding zrtp/lime cache
@ -3676,15 +3957,6 @@ LINPHONE_PUBLIC LINPHONE_DEPRECATED const char *linphone_core_get_zrtp_secrets_f
*/
LINPHONE_PUBLIC void *linphone_core_get_zrtp_cache_db(LinphoneCore *lc);
/**
* Sets the database filename where zrtp cache will be stored.
* If the file does not exist, it will be created.
* @ingroup initializing
* @param lc the linphone core
* @param path filesystem path
**/
LINPHONE_PUBLIC void linphone_core_set_zrtp_cache_database_path(LinphoneCore *lc, const char *path);
/**
* Set the path to the directory storing the user's x509 certificates (used by dtls)
* @param[in] lc #LinphoneCore object
@ -4124,7 +4396,7 @@ LINPHONE_PUBLIC const char ** linphone_core_get_supported_file_formats(LinphoneC
* @see linphone_core_get_supported_file_formats
* @param lc A #LinphoneCore object
* @param fmt The format extension (wav, mkv).
* @ingroup media_paramaters
* @ingroup media_parameters
**/
LINPHONE_PUBLIC bool_t linphone_core_file_format_supported(LinphoneCore *lc, const char *fmt);
@ -4887,6 +5159,28 @@ LINPHONE_PUBLIC LinphonePresencePerson * linphone_core_create_presence_person(Li
*/
LINPHONE_PUBLIC LinphonePresenceService * linphone_core_create_presence_service(LinphoneCore *lc, const char *id, LinphonePresenceBasicStatus basic_status, const char *contact);
/**
* Notifies the upper layer that a presence status has been received by calling the appropriate
* callback if one has been set.
* @param[in] lc the #LinphoneCore object.
* @param[in] lf the #LinphoneFriend whose presence information has been received.
*/
LINPHONE_PUBLIC void linphone_core_notify_notify_presence_received(LinphoneCore *lc, LinphoneFriend *lf);
/**
* Notifies the upper layer that a presence model change has been received for the uri or
* telephone number given as a parameter, by calling the appropriate callback if one has been set.
* @param[in] lc the #LinphoneCore object.
* @param[in] lf the #LinphoneFriend whose presence information has been received.
* @param[in] uri_or_tel telephone number or sip uri
* @param[in] presence_model the #LinphonePresenceModel that has been modified
*/
LINPHONE_PUBLIC void linphone_core_notify_notify_presence_received_for_uri_or_tel(LinphoneCore *lc, LinphoneFriend *lf, const char *uri_or_tel, const LinphonePresenceModel *presence_model);
/**
* @}
*/

View file

@ -62,6 +62,14 @@ LINPHONE_PUBLIC void linphone_error_info_unref(LinphoneErrorInfo *ei);
**/
LINPHONE_PUBLIC LinphoneReason linphone_error_info_get_reason(const LinphoneErrorInfo *ei);
/**
* Get pointer to chained LinphoneErrorInfo set in sub_ei.
* It corresponds to a Reason header in a received SIP response.
* @param ei ErrorInfo object
* @return LinphoneErrorInfo pointer defined in the ei object.
*/
LINPHONE_PUBLIC LinphoneErrorInfo* linphone_error_info_get_sub_error_info(const LinphoneErrorInfo *ei);
/**
* Get textual phrase from the error info.
* This is the text that is provided by the peer in the protocol (SIP).
@ -69,6 +77,13 @@ LINPHONE_PUBLIC LinphoneReason linphone_error_info_get_reason(const LinphoneErro
* @return The error phrase
**/
LINPHONE_PUBLIC const char * linphone_error_info_get_phrase(const LinphoneErrorInfo *ei);
/**
* Get protocol from the error info.
* @param[in] ei ErrorInfo object
* @return The protocol
*/
LINPHONE_PUBLIC const char *linphone_error_info_get_protocol(const LinphoneErrorInfo *ei);
/**
* Provides additional information regarding the failure.
@ -88,12 +103,59 @@ LINPHONE_PUBLIC int linphone_error_info_get_protocol_code(const LinphoneErrorInf
/**
* Assign information to a LinphoneErrorInfo object.
* @param[in] ei ErrorInfo object
* @param[in] ei ErrorInfo object
* @param[in] protocol protocol name
* @param[in] reason reason from LinphoneReason enum
* @param[in] code protocol code
* @param[in] status_string description of the reason
* @param[in] warning warning message
*/
LINPHONE_PUBLIC void linphone_error_info_set(LinphoneErrorInfo *ei, LinphoneReason reason, int code, const char *status_string, const char *warning);
LINPHONE_PUBLIC void linphone_error_info_set(LinphoneErrorInfo *ei, const char *protocol, LinphoneReason reason, int code, const char *status_string, const char *warning);
/**
* Set the sub_ei in LinphoneErrorInfo to another LinphoneErrorInfo.
* Used when a reason header is to be added in a SIP response. The first level LinphoneErrorInfo defines the SIP response code and phrase,
* the second (sub) LinphoneErroInfo defining the content of the Reason header.
* @param[in] ei LinphoneErrorInfo object to which the other LinphoneErrorInfo will be appended as ei->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);
/**
* @}
*/

View file

@ -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);
/**
* @}
*/

View file

@ -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

View file

@ -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
}

View file

@ -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; /**<Whether video shall be automatically proposed for outgoing calls.*/
@ -1115,6 +1150,12 @@ typedef struct _LinphoneVideoPolicy {
bool_t unused[2];
} LinphoneVideoPolicy;
/**
* Structure describing policy regarding video streams establishments.
* @ingroup media_parameters
**/
typedef struct _LinphoneVideoActivationPolicy LinphoneVideoActivationPolicy;
typedef struct LinphoneVideoSizeDef {
MSVideoSize vsize;
const char *name;
@ -1178,15 +1219,11 @@ typedef struct _LsdPlayer LsdPlayer;
*/
typedef struct _LinphonePayloadType LinphonePayloadType;
/**
* Structure describing a range of integers
* @ingroup misc
*/
typedef struct _LinphoneIntRange {
int min; /**< Minimum value */
int max; /**< Maximum value */
} LinphoneIntRange;
typedef struct _LinphoneRange LinphoneRange;
/**
* Status code returned by some functions to

View file

@ -0,0 +1,153 @@
/*
video_definition.h
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.
*/
#ifndef LINPHONE_VIDEO_DEFINITION_H_
#define LINPHONE_VIDEO_DEFINITION_H_
#include "linphone/types.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @addtogroup media_parameters
* @{
*/
/**
* Acquire a reference to the video definition.
* @param[in] vdef LinphoneVideoDefinition object.
* @return The same LinphoneVideoDefinition object.
**/
LINPHONE_PUBLIC LinphoneVideoDefinition * linphone_video_definition_ref(LinphoneVideoDefinition *vdef);
/**
* Release reference to the video definition.
* @param[in] vdef LinphoneVideoDefinition object.
**/
LINPHONE_PUBLIC void linphone_video_definition_unref(LinphoneVideoDefinition *vdef);
/**
* Retrieve the user pointer associated with the video definition.
* @param[in] vdef LinphoneVideoDefinition object.
* @return The user pointer associated with the video definition.
**/
LINPHONE_PUBLIC void *linphone_video_definition_get_user_data(const LinphoneVideoDefinition *vdef);
/**
* Assign a user pointer to the video definition.
* @param[in] vdef LinphoneVideoDefinition object.
* @param[in] ud The user pointer to associate with the video definition.
**/
LINPHONE_PUBLIC void linphone_video_definition_set_user_data(LinphoneVideoDefinition *vdef, void *ud);
/**
* Clone a video definition.
* @param[in] vdef LinphoneVideoDefinition object to be cloned
* @return The new clone of the video definition
*/
LINPHONE_PUBLIC LinphoneVideoDefinition * linphone_video_definition_clone(const LinphoneVideoDefinition *vdef);
/**
* Get the width of the video definition.
* @param[in] vdef LinphoneVideoDefinition object
* @return The width of the video definition
*/
LINPHONE_PUBLIC unsigned int linphone_video_definition_get_width(const LinphoneVideoDefinition *vdef);
/**
* Set the width of the video definition.
* @param[in] vdef LinphoneVideoDefinition object
* @param[in] width The width of the video definition
*/
LINPHONE_PUBLIC void linphone_video_definition_set_width(LinphoneVideoDefinition *vdef, unsigned int width);
/**
* Get the height of the video definition.
* @param[in] vdef LinphoneVideoDefinition object
* @return The height of the video definition
*/
LINPHONE_PUBLIC unsigned int linphone_video_definition_get_height(const LinphoneVideoDefinition *vdef);
/**
* Set the height of the video definition.
* @param[in] vdef LinphoneVideoDefinition object
* @param[in] height The height of the video definition
*/
LINPHONE_PUBLIC void linphone_video_definition_set_height(LinphoneVideoDefinition *vdef, unsigned int height);
/**
* Set the width and the height of the video definition.
* @param[in] vdef LinphoneVideoDefinition object
* @param[in] width The width of the video definition
* @param[in] height The height of the video definition
*/
LINPHONE_PUBLIC void linphone_video_definition_set_definition(LinphoneVideoDefinition *vdef, unsigned int width, unsigned int height);
/**
* Get the name of the video definition.
* @param[in] vdef LinphoneVideoDefinition object
* @return The name of the video definition
*/
LINPHONE_PUBLIC const char * linphone_video_definition_get_name(const LinphoneVideoDefinition *vdef);
/**
* Set the name of the video definition.
* @param[in] vdef LinphoneVideoDefinition object
* @param[in] name The name of the video definition
*/
LINPHONE_PUBLIC void linphone_video_definition_set_name(LinphoneVideoDefinition *vdef, const char *name);
/**
* Tells whether two LinphoneVideoDefinition objects are equal (the widths and the heights are the same but can be switched).
* @param[in] vdef1 LinphoneVideoDefinition object
* @param[in] vdef2 LinphoneVideoDefinition object
* @return A boolean value telling whether the two LinphoneVideoDefinition objects are equal.
*/
LINPHONE_PUBLIC bool_t linphone_video_definition_equals(const LinphoneVideoDefinition *vdef1, const LinphoneVideoDefinition *vdef2);
/**
* Tells whether two LinphoneVideoDefinition objects are strictly equal (the widths are the same and the heights are the same).
* @param[in] vdef1 LinphoneVideoDefinition object
* @param[in] vdef2 LinphoneVideoDefinition object
* @return A boolean value telling whether the two LinphoneVideoDefinition objects are strictly equal.
*/
LINPHONE_PUBLIC bool_t linphone_video_definition_strict_equals(const LinphoneVideoDefinition *vdef1, const LinphoneVideoDefinition *vdef2);
/**
* Tells whether a LinphoneVideoDefinition is undefined.
* @param[in] vdef LinphoneVideoDefinition object
* @return A boolean value telling whether the LinphoneVideoDefinition is undefined.
*/
LINPHONE_PUBLIC bool_t linphone_video_definition_is_undefined(const LinphoneVideoDefinition *vdef);
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* LINPHONE_VIDEO_DEFINITION_H_ */

View file

@ -65,30 +65,6 @@ LINPHONE_PUBLIC void linphone_chat_message_resend(LinphoneChatMessage *msg);
*/
LINPHONE_PUBLIC void *linphone_vcard_get_belcard(LinphoneVcard *vcard);
/* Functions to mainpulate the LinphoneIntRange structure */
/**
* Get the minimum value of a #LinphoneIntRange.
*/
LINPHONE_PUBLIC int linphone_int_range_get_min(const LinphoneIntRange *range);
/**
* Get the maximum value of a #LinphoneIntRange.
*/
LINPHONE_PUBLIC int linphone_int_range_get_max(const LinphoneIntRange *range);
/**
* Set the minimum value of a #LinphoneIntRange.
*/
LINPHONE_PUBLIC void linphone_int_range_set_min(LinphoneIntRange *range, int min);
/**
* Set the maximum value of a #LinphoneIntRange.
*/
LINPHONE_PUBLIC void linphone_int_range_set_max(LinphoneIntRange *range, int max);
/**
* @}
*/

View file

@ -412,6 +412,7 @@ typedef struct SalErrorInfo{
char *warnings;
char *protocol;
char *full_string; /*concatenation of status_string + warnings*/
struct SalErrorInfo *sub_sei;
}SalErrorInfo;
typedef enum SalPresenceStatus{
@ -730,6 +731,7 @@ const SalErrorInfo *sal_error_info_none(void);
LINPHONE_PUBLIC const SalErrorInfo *sal_op_get_error_info(const SalOp *op);
const SalErrorInfo *sal_op_get_reason_error_info(const SalOp *op);
void sal_error_info_reset(SalErrorInfo *ei);
void sal_error_info_init_to_null(SalErrorInfo *sei);
void sal_error_info_set(SalErrorInfo *ei, SalReason reason, const char *protocol, int code, const char *status_string, const char *warning);
/*entity tag used for publish (see RFC 3903)*/
@ -745,6 +747,7 @@ int sal_call_notify_ringing(SalOp *h, bool_t early_media);
/*accept an incoming call or, during a call accept a reINVITE*/
int sal_call_accept(SalOp*h);
int sal_call_decline(SalOp *h, SalReason reason, const char *redirection /*optional*/);
int sal_call_decline_with_error_info(SalOp *h, const SalErrorInfo* info, const char *redirection /*optional*/);
int sal_call_update(SalOp *h, const char *subject, bool_t no_user_consent);
void sal_call_cancel_invite(SalOp *op);
SalMediaDescription * sal_call_get_remote_media_description(SalOp *h);
@ -758,6 +761,7 @@ int sal_call_set_referer(SalOp *h, SalOp *refered_call);
SalOp *sal_call_get_replaces(SalOp *h);
int sal_call_send_dtmf(SalOp *h, char dtmf);
int sal_call_terminate(SalOp *h);
int sal_call_terminate_with_error(SalOp *op, const SalErrorInfo *info);
bool_t sal_call_autoanswer_asked(SalOp *op);
void sal_call_send_vfu_request(SalOp *h);
int sal_call_is_offerer(const SalOp *h);

View file

@ -6,6 +6,10 @@ public interface ErrorInfo {
* @return the reason.
*/
Reason getReason();
/**
* Get the protocol name for which the error code (returned by getProtocolCode()) is meaningful.
**/
String getProtocol();
/**
* Get the protocol code corresponding to the error (typically a SIP status code).
* @return the code.
@ -16,9 +20,46 @@ public interface ErrorInfo {
* @return the reason phrase.
*/
String getPhrase();
/**
* Get content of warning header, if any.
**/
String getWarnings();
/**
* Get additional error information, which is provided as a Reason header in SIP response.
**/
ErrorInfo getSubErrorInfo();
/**
* Set Reason enum.
*/
void setReason(Reason r);
/**
* Set the protocol name for which the error code (set by setProtocolCode()) is meaningful.
**/
void setProtocol(String protocol);
/**
* Set the protocol code corresponding to the error (typically a SIP status code).
* @return the code.
*/
void setProtocolCode(int code);
/**
* Set the reason-phrase provided by the protocol (typically a SIP reason-phrase).
* @return the reason phrase.
*/
void setPhrase(String phrase);
/**
* Set warnings.
**/
void setWarnings(String warnings);
/**
* Set additional error information, which is provided as a Reason header in SIP response.
**/
void setSubErrorInfo(ErrorInfo sub_ei);
/**
* Get details about the error, if provided by the protocol. For SIP it consists of the content of a Warning or Reason header.
* @return details about the error.
* @deprecated
*/
String getDetails();
}

View file

@ -391,13 +391,13 @@ public interface LinphoneCall {
* Call player enable to stream a media file through a call
* @return A player
*/
public LinphonePlayer getPlayer();
LinphonePlayer getPlayer();
/**
* Create a new chat room for messaging from a call if not already existing, else return existing one
* @return LinphoneChatRoom where messaging can take place.
*/
public LinphoneChatRoom getChatRoom() ;
LinphoneChatRoom getChatRoom() ;
/**
* Set the callbacks associated with the LinphoneCall.
@ -409,4 +409,15 @@ public interface LinphoneCall {
* This is an indication - the application remains responsible for answering the call.
**/
boolean askedToAutoAnswer();
/**
* Decline a pending incoming call providing an ErrorInfo object.
**/
void declineWithErrorInfo(ErrorInfo ei);
/**
* Terminate a call providing an ErrorInfo object.
**/
void terminateWithErrorInfo(ErrorInfo ei);
}

View file

@ -188,6 +188,11 @@ abstract public class LinphoneCoreFactory {
* Create LinphoneAccountCreator object
*/
abstract public LinphoneAccountCreator createAccountCreator(LinphoneCore lc, String url);
/**
* Create ErrorInfo object
*/
abstract public ErrorInfo createErrorInfo();
/**
* Array of countries list

View file

@ -21,12 +21,12 @@ package org.linphone.core;
/**
* The LpConfig object is used to manipulate a configuration file.
*
*
* <pre>
* 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);
}

View file

@ -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();
}
}

View file

@ -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);
}
}
}

View file

@ -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);
}
}

View file

@ -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);
}
}

View file

@ -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

View file

@ -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\

View file

@ -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),

View file

@ -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))));

View file

@ -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,

View file

@ -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;

View file

@ -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);
}

View file

@ -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 = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<cache><selfZID>00112233445566778899aabb</selfZID><peer><ZID>99887766554433221100ffee</ZID><rs1>c4274f13a2b6fa05c15ec93158f930e7264b0a893393376dbc80c6eb1cccdc5a</rs1><uri>sip:bob@sip.linphone.org</uri><sndKey>219d9e445d10d4ed64083c7ccbb83a23bc17a97df0af5de4261f3fe026b05b0b</sndKey><rcvKey>747e72a5cc996413cb9fa6e3d18d8b370436e274cd6ba4efc1a4580340af57ca</rcvKey><sndSId>df2bf38e719fa89e17332cf8d5e774ee70d347baa74d16dee01f306c54789869</sndSId><rcvSId>928ce78b0bfc30427a02b1b668b2b3b0496d5664d7e89b75ed292ee97e3fc850</rcvSId><sndIndex>496bcc89</sndIndex><rcvIndex>59337abe</rcvIndex><rs2>5dda11f388384b349d210612f30824268a3753a7afa52ef6df5866dca76315c4</rs2><uri>sip:bob2@sip.linphone.org</uri></peer><peer><ZID>ffeeddccbbaa987654321012</ZID><rs1>858b495dfad483af3c088f26d68c4beebc638bd44feae45aea726a771727235e</rs1><uri>sip:bob@sip.linphone.org</uri><sndKey>b6aac945057bc4466bfe9a23771c6a1b3b8d72ec3e7d8f30ed63cbc5a9479a25</sndKey><rcvKey>bea5ac3225edd0545b816f061a8190370e3ee5160e75404846a34d1580e0c263</rcvKey><sndSId>17ce70fdf12e500294bcb5f2ffef53096761bb1c912b21e972ae03a5a9f05c47</sndSId><rcvSId>7e13a20e15a517700f0be0921f74b96d4b4a0c539d5e14d5cdd8706441874ac0</rcvSId><sndIndex>75e18caa</sndIndex><rcvIndex>2cfbbf06</rcvIndex><rs2>1533dee20c8116dc2c282cae9adfea689b87bc4c6a4e18a846f12e3e7fea3959</rs2></peer><peer><ZID>0987654321fedcba5a5a5a5a</ZID><rs1>cb6ecc87d1dd87b23f225eec53a26fc541384917623e0c46abab8c0350c6929e</rs1><sndKey>92bb03988e8f0ccfefa37a55fd7c5893bea3bfbb27312f49dd9b10d0e3c15fc7</sndKey><rcvKey>2315705a5830b98f68458fcd49623144cb34a667512c4d44686aee125bb8b622</rcvKey><sndSId>94c56eea0dd829379263b6da3f6ac0a95388090f168a3568736ca0bd9f8d595f</sndSId><rcvSId>c319ae0d41183fec90afc412d42253c5b456580f7a463c111c7293623b8631f4</rcvSId><uri>sip:bob@sip.linphone.org</uri><sndIndex>2c46ddcc</sndIndex><rcvIndex>15f5779e</rcvIndex><valid>0000000058f095bf</valid><pvs>01</pvs></peer></cache>";
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),

View file

@ -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,

View file

@ -0,0 +1,32 @@
<?xml version="1.0" encoding="UTF-8"?>
<config xmlns="http://www.linphone.org/xsds/lpconfig.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.linphone.org/xsds/lpconfig.xsd lpconfig.xsd">
<section name="proxy_default_values">
<entry name="avpf" overwrite="true">1</entry>
<entry name="dial_escape_plus" overwrite="true">0</entry>
<entry name="publish" overwrite="true">0</entry>
<entry name="quality_reporting_collector" overwrite="true">sip:voip-metrics@sip.linphone.org;transport=tls</entry>
<entry name="quality_reporting_enabled" overwrite="true">1</entry>
<entry name="quality_reporting_interval" overwrite="true">180</entry>
<entry name="reg_expires" overwrite="true">31536000</entry>
<entry name="reg_identity" overwrite="true">sip:?@sip.linphone.org</entry>
<entry name="reg_sendregister" overwrite="true">1</entry>
<entry name="refkey" overwrite="true">push_notification</entry>
<entry name="realm" overwrite="true">sip.linphone.org</entry>
</section>
<section name="sip">
<entry name="rls_uri" overwrite="true">sips:rls@sip.linphone.org</entry>
</section>
<section name="assistant">
<entry name="domain" overwrite="true">sip.linphone.org</entry>
<entry name="password_max_length" overwrite="true">-1</entry>
<entry name="password_min_length" overwrite="true">1</entry>
<entry name="username_length" overwrite="true">-1</entry>
<entry name="username_max_length" overwrite="true">64</entry>
<entry name="username_min_length" overwrite="true">1</entry>
<entry name="username_regex" overwrite="true">^[a-z0-9+_.\-]*$</entry>
<entry name="xmlrpc_url" overwrite="true">https://sip3.linphone.org:444/wizard.php</entry>
</section>
</config>

View file

@ -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);
}
}

View file

@ -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);
}

View file

@ -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);

View file

@ -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

84
tools/metadoc.py Normal file
View file

@ -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] = '<summary>' + lines[0]
lines[-1] = lines[-1] + '</summary>'

View file

@ -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

View file

@ -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)

View file

@ -84,10 +84,24 @@ namespace linphone {
{{#methods}}
{{#doc}}
/**
{{#lines}}
* {{{line}}}
{{/lines}}
*/
{{/doc}}
{{{prototype}}}
{{/methods}}
{{#staticMethods}}
{{#doc}}
/**
{{#lines}}
* {{{line}}}
{{/lines}}
*/
{{/doc}}
{{{prototype}}}
{{/staticMethods}}

View file

@ -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):

View file

@ -100,7 +100,7 @@ namespace linphone {
static std::list<T> bctbxListToCppList(const ::bctbx_list_t *bctbxList) {
std::list<T> 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;
}