mirror of
https://gitlab.linphone.org/BC/public/linphone-iphone.git
synced 2026-01-29 17:29:20 +00:00
Merge remote-tracking branch 'origin' into dev_lime
Conflicts: build/android/Android.mk coreapi/Makefile.am
This commit is contained in:
commit
ed4d9c0d20
52 changed files with 2384 additions and 1009 deletions
10
README.mingw
10
README.mingw
|
|
@ -118,8 +118,8 @@ linphone-deps packages.
|
|||
|
||||
List of software included in linphone-deps:
|
||||
antlr3c (compiled)
|
||||
bzrtp (compiled)
|
||||
polarssl (compiled
|
||||
belle-sip (compiled)
|
||||
libsrtp (compiled)
|
||||
libavcodec, libavutil, libavformat, libavdevice, libswscale (compiled, all these from ffmpeg)
|
||||
libtheora (from the web)
|
||||
|
|
@ -167,6 +167,14 @@ When running "make install DESTDIR=<somepath>", somepath must be absolute and sh
|
|||
$ make install
|
||||
$ make install DESTDIR=/home/<myuser>/libsrtp-install
|
||||
|
||||
- building bzrtp
|
||||
* download the sources with msys-git shell using the following command:
|
||||
$ git clone git://git.linphone.org/bzrtp.git
|
||||
* compile and install
|
||||
$ ./autogen.sh
|
||||
$ ./configure --prefix=/usr --enable-shared --disable-static
|
||||
$ make && make install
|
||||
|
||||
- building sqlite3
|
||||
* download the sources on the following website:
|
||||
http://www.sqlite.org/download.html (choose the sqlite-autoconf-3XXX.tar.gz)
|
||||
|
|
|
|||
|
|
@ -65,7 +65,8 @@ LOCAL_SRC_FILES := \
|
|||
xml2lpc.c \
|
||||
lpc2xml.c \
|
||||
remote_provisioning.c \
|
||||
lime.c
|
||||
lime.c \
|
||||
quality_reporting.c
|
||||
|
||||
ifndef LINPHONE_VERSION
|
||||
LINPHONE_VERSION = "Devel"
|
||||
|
|
|
|||
|
|
@ -203,6 +203,7 @@
|
|||
<ClCompile Include="..\..\..\coreapi\offeranswer.c" />
|
||||
<ClCompile Include="..\..\..\coreapi\presence.c" />
|
||||
<ClCompile Include="..\..\..\coreapi\proxy.c" />
|
||||
<ClCompile Include="..\..\..\coreapi\quality_reporting.c" />
|
||||
<ClCompile Include="..\..\..\coreapi\sal.c" />
|
||||
<ClCompile Include="..\..\..\coreapi\siplogin.c" />
|
||||
<ClCompile Include="..\..\..\coreapi\sipsetup.c" />
|
||||
|
|
@ -275,4 +276,4 @@
|
|||
<Import Project="$(MSBuildExtensionsPath)\Microsoft\WindowsPhone\v$(TargetPlatformVersion)\Microsoft.Cpp.WindowsPhone.$(TargetPlatformVersion).targets" Condition="'$(Platform)'=='ARM'" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -1,3 +1,7 @@
|
|||
if(MSVC)
|
||||
find_library(LIBGCC NAMES gcc)
|
||||
find_library(LIBMINGWEX NAMES mingwex)
|
||||
endif()
|
||||
find_library(LIBORTP NAMES ortp)
|
||||
find_library(LIBMEDIASTREAMER_BASE NAMES mediastreamer_base)
|
||||
find_library(LIBMEDIASTREAMER_VOIP NAMES mediastreamer_voip)
|
||||
|
|
@ -74,6 +78,7 @@ set(SOURCE_FILES
|
|||
offeranswer.c
|
||||
presence.c
|
||||
proxy.c
|
||||
quality_reporting.c
|
||||
remote_provisioning.c
|
||||
sal.c
|
||||
siplogin.c
|
||||
|
|
@ -118,7 +123,7 @@ add_definitions(
|
|||
|
||||
set(LIBS ws2_32)
|
||||
endif(WIN32)
|
||||
set(LIBS ${LIBS} ${LIBORTP} ${LIBMEDIASTREAMER_BASE} ${LIBMEDIASTREAMER_VOIP} ${LIBBELLESIP} ${LIBXML2})
|
||||
set(LIBS ${LIBS} ${LIBGCC} ${LIBMINGWEX} ${LIBORTP} ${LIBMEDIASTREAMER_BASE} ${LIBMEDIASTREAMER_VOIP} ${LIBBELLESIP} ${LIBXML2})
|
||||
|
||||
add_library(linphone SHARED ${SOURCE_FILES})
|
||||
set_target_properties(linphone PROPERTIES VERSION 3.7.0 SOVERSION 5)
|
||||
|
|
|
|||
|
|
@ -18,11 +18,7 @@ CLEANFILES=$(GITVERSION_FILE)
|
|||
## Process this file with automake to produce Makefile.in
|
||||
linphone_includedir=$(includedir)/linphone
|
||||
|
||||
linphone_include_HEADERS=linphonecore.h linphonefriend.h linphonepresence.h linphonecore_utils.h lpconfig.h sipsetup.h event.h xml2lpc.h lpc2xml.h
|
||||
|
||||
if BUILD_TUNNEL
|
||||
linphone_include_HEADERS+=linphone_tunnel.h
|
||||
endif
|
||||
linphone_include_HEADERS=linphonecore.h linphonefriend.h linphonepresence.h linphonecore_utils.h lpconfig.h sipsetup.h event.h xml2lpc.h lpc2xml.h linphone_tunnel.h
|
||||
|
||||
lib_LTLIBRARIES=liblinphone.la
|
||||
|
||||
|
|
@ -57,6 +53,7 @@ liblinphone_la_SOURCES=\
|
|||
lpc2xml.c \
|
||||
remote_provisioning.c \
|
||||
lime.c \
|
||||
quality_reporting.c quality_reporting.h\
|
||||
$(GITVERSION_FILE)
|
||||
|
||||
if BUILD_UPNP
|
||||
|
|
@ -82,9 +79,9 @@ endif
|
|||
|
||||
liblinphone_la_SOURCES+=linphone_tunnel_config.c
|
||||
if BUILD_TUNNEL
|
||||
liblinphone_la_SOURCES+=linphone_tunnel.cc TunnelManager.cc TunnelManager.hh
|
||||
liblinphone_la_SOURCES+=linphone_tunnel.cc TunnelManager.cc TunnelManager.hh linphone_tunnel.h
|
||||
else
|
||||
liblinphone_la_SOURCES+=linphone_tunnel_stubs.c
|
||||
liblinphone_la_SOURCES+=linphone_tunnel_stubs.c linphone_tunnel.h
|
||||
endif
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -117,7 +117,7 @@ void sal_process_authentication(SalOp *op) {
|
|||
belle_sip_response_t *response=belle_sip_transaction_get_response((belle_sip_transaction_t*)op->pending_auth_transaction);
|
||||
belle_sip_header_from_t *from=belle_sip_message_get_header_by_type(initial_request,belle_sip_header_from_t);
|
||||
belle_sip_uri_t *from_uri=belle_sip_header_address_get_uri((belle_sip_header_address_t*)from);
|
||||
|
||||
|
||||
if (strcasecmp(belle_sip_uri_get_host(from_uri),"anonymous.invalid")==0){
|
||||
/*prefer using the from from the SalOp*/
|
||||
from_uri=belle_sip_header_address_get_uri((belle_sip_header_address_t*)sal_op_get_from_address(op));
|
||||
|
|
@ -137,7 +137,7 @@ void sal_process_authentication(SalOp *op) {
|
|||
ms_error("sal_process_authentication() op=[%p] cannot obtain new request from dialog.",op);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (belle_sip_provider_add_authorization(op->base.root->prov,new_request,response,from_uri,&auth_list)) {
|
||||
if (is_within_dialog) {
|
||||
sal_op_send_request(op,new_request);
|
||||
|
|
@ -308,7 +308,7 @@ static void process_response_event(void *user_ctx, const belle_sip_response_even
|
|||
belle_sip_client_transaction_t* client_transaction = belle_sip_response_event_get_client_transaction(event);
|
||||
belle_sip_response_t* response = belle_sip_response_event_get_response(event);
|
||||
int response_code = belle_sip_response_get_status_code(response);
|
||||
|
||||
|
||||
if (!client_transaction) {
|
||||
ms_warning("Discarding stateless response [%i]",response_code);
|
||||
return;
|
||||
|
|
@ -334,11 +334,11 @@ static void process_response_event(void *user_ctx, const belle_sip_response_even
|
|||
}
|
||||
|
||||
sal_op_assign_recv_headers(op,(belle_sip_message_t*)response);
|
||||
|
||||
|
||||
if (op->callbacks && op->callbacks->process_response_event) {
|
||||
/*handle authorization*/
|
||||
switch (response_code) {
|
||||
case 200:
|
||||
case 200:
|
||||
break;
|
||||
case 401:
|
||||
case 407:
|
||||
|
|
@ -424,14 +424,18 @@ Sal * sal_init(){
|
|||
belle_sip_listener_callbacks_t listener_callbacks;
|
||||
Sal * sal=ms_new0(Sal,1);
|
||||
sal->auto_contacts=TRUE;
|
||||
|
||||
/*first create the stack, which initializes the belle-sip object's pool for this thread*/
|
||||
belle_sip_set_log_handler(_belle_sip_log);
|
||||
sal->stack = belle_sip_stack_new(NULL);
|
||||
|
||||
sal->user_agent=belle_sip_header_user_agent_new();
|
||||
#if defined(PACKAGE_NAME) && defined(LINPHONE_VERSION)
|
||||
belle_sip_header_user_agent_add_product(sal->user_agent, PACKAGE_NAME "/" LINPHONE_VERSION);
|
||||
#endif
|
||||
sal_append_stack_string_to_user_agent(sal);
|
||||
belle_sip_object_ref(sal->user_agent);
|
||||
belle_sip_set_log_handler(_belle_sip_log);
|
||||
sal->stack = belle_sip_stack_new(NULL);
|
||||
|
||||
sal->prov = belle_sip_stack_create_provider(sal->stack,NULL);
|
||||
sal_nat_helper_enable(sal,TRUE);
|
||||
memset(&listener_callbacks,0,sizeof(listener_callbacks));
|
||||
|
|
@ -677,10 +681,10 @@ static void set_tls_properties(Sal *ctx){
|
|||
if (lp){
|
||||
belle_sip_tls_listening_point_t *tlp=BELLE_SIP_TLS_LISTENING_POINT(lp);
|
||||
int verify_exceptions=0;
|
||||
|
||||
|
||||
if (!ctx->tls_verify) verify_exceptions=BELLE_SIP_TLS_LISTENING_POINT_BADCERT_ANY_REASON;
|
||||
else if (!ctx->tls_verify_cn) verify_exceptions=BELLE_SIP_TLS_LISTENING_POINT_BADCERT_CN_MISMATCH;
|
||||
|
||||
|
||||
belle_sip_tls_listening_point_set_root_ca(tlp,ctx->root_ca); /*root_ca might be NULL */
|
||||
belle_sip_tls_listening_point_set_verify_exceptions(tlp,verify_exceptions);
|
||||
}
|
||||
|
|
@ -802,7 +806,7 @@ void sal_auth_info_set_mode(SalAuthInfo* auth_info, SalAuthMode mode) { auth_inf
|
|||
void sal_certificates_chain_delete(SalCertificatesChain *chain) {
|
||||
belle_sip_object_unref((belle_sip_object_t *)chain);
|
||||
}
|
||||
void sal_signing_key_delete(SalSigningKey *key) {
|
||||
void sal_signing_key_delete(SalSigningKey *key) {
|
||||
belle_sip_object_unref((belle_sip_object_t *)key);
|
||||
}
|
||||
|
||||
|
|
@ -829,7 +833,7 @@ int sal_auth_compute_ha1(const char* userid,const char* realm,const char* passwo
|
|||
SalCustomHeader *sal_custom_header_append(SalCustomHeader *ch, const char *name, const char *value){
|
||||
belle_sip_message_t *msg=(belle_sip_message_t*)ch;
|
||||
belle_sip_header_t *h;
|
||||
|
||||
|
||||
if (msg==NULL){
|
||||
msg=(belle_sip_message_t*)belle_sip_request_new();
|
||||
belle_sip_object_ref(msg);
|
||||
|
|
@ -846,7 +850,7 @@ SalCustomHeader *sal_custom_header_append(SalCustomHeader *ch, const char *name,
|
|||
const char *sal_custom_header_find(const SalCustomHeader *ch, const char *name){
|
||||
if (ch){
|
||||
belle_sip_header_t *h=belle_sip_message_get_header((belle_sip_message_t*)ch,name);
|
||||
|
||||
|
||||
if (h){
|
||||
return belle_sip_header_get_unparsed_value(h);
|
||||
}
|
||||
|
|
@ -879,12 +883,12 @@ void sal_set_uuid(Sal *sal, const char *uuid){
|
|||
}
|
||||
|
||||
typedef struct {
|
||||
unsigned int time_low;
|
||||
unsigned short time_mid;
|
||||
unsigned short time_hi_and_version;
|
||||
unsigned char clock_seq_hi_and_reserved;
|
||||
unsigned char clock_seq_low;
|
||||
unsigned char node[6];
|
||||
unsigned int time_low;
|
||||
unsigned short time_mid;
|
||||
unsigned short time_hi_and_version;
|
||||
unsigned char clock_seq_hi_and_reserved;
|
||||
unsigned char clock_seq_low;
|
||||
unsigned char node[6];
|
||||
} sal_uuid_t;
|
||||
|
||||
|
||||
|
|
@ -892,7 +896,7 @@ int sal_create_uuid(Sal*ctx, char *uuid, size_t len){
|
|||
sal_uuid_t uuid_struct;
|
||||
int i;
|
||||
int written;
|
||||
|
||||
|
||||
if (len==0) return -1;
|
||||
/*create an UUID as described in RFC4122, 4.4 */
|
||||
belle_sip_random_bytes((unsigned char*)&uuid_struct, sizeof(sal_uuid_t));
|
||||
|
|
@ -900,7 +904,7 @@ int sal_create_uuid(Sal*ctx, char *uuid, size_t len){
|
|||
uuid_struct.clock_seq_hi_and_reserved|=1<<7;
|
||||
uuid_struct.time_hi_and_version&=~(0xf<<12);
|
||||
uuid_struct.time_hi_and_version|=4<<12;
|
||||
|
||||
|
||||
written=snprintf(uuid,len,"%8.8x-%4.4x-%4.4x-%2.2x%2.2x-", uuid_struct.time_low, uuid_struct.time_mid,
|
||||
uuid_struct.time_hi_and_version, uuid_struct.clock_seq_hi_and_reserved,
|
||||
uuid_struct.clock_seq_low);
|
||||
|
|
@ -938,6 +942,10 @@ void sal_enable_test_features(Sal*ctx, bool_t enabled){
|
|||
ctx->enable_test_features=enabled;
|
||||
}
|
||||
|
||||
void sal_use_no_initial_route(Sal *ctx, bool_t enabled){
|
||||
ctx->no_initial_route=enabled;
|
||||
}
|
||||
|
||||
SalResolverContext * sal_resolve_a(Sal* sal, const char *name, int port, int family, SalResolverCallback cb, void *data){
|
||||
return (SalResolverContext*)belle_sip_stack_resolve_a(sal->stack,name,port,family,(belle_sip_resolver_callback_t)cb,data);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ struct Sal{
|
|||
bool_t use_dates;
|
||||
bool_t auto_contacts;
|
||||
bool_t enable_test_features;
|
||||
bool_t no_initial_route;
|
||||
};
|
||||
|
||||
typedef enum SalOpState {
|
||||
|
|
|
|||
|
|
@ -111,9 +111,9 @@ static int set_sdp_from_desc(belle_sip_message_t *msg, const SalMediaDescription
|
|||
}
|
||||
static void call_process_io_error(void *user_ctx, const belle_sip_io_error_event_t *event){
|
||||
SalOp* op=(SalOp*)user_ctx;
|
||||
|
||||
|
||||
if (op->state==SalOpStateTerminated) return;
|
||||
|
||||
|
||||
if (!op->dialog) {
|
||||
/*call terminated very early*/
|
||||
sal_error_info_set(&op->error_info,SalReasonIOError,503,"IO error",NULL);
|
||||
|
|
@ -129,7 +129,7 @@ static void process_dialog_terminated(void *ctx, const belle_sip_dialog_terminat
|
|||
if (op->dialog && op->dialog==belle_sip_dialog_terminated_event_get_dialog(event)) {
|
||||
/*belle_sip_transaction_t* trans=belle_sip_dialog_get_last_transaction(op->dialog);*/
|
||||
ms_message("Dialog [%p] terminated for op [%p]",belle_sip_dialog_terminated_event_get_dialog(event),op);
|
||||
|
||||
|
||||
switch(belle_sip_dialog_get_previous_state(op->dialog)) {
|
||||
case BELLE_SIP_DIALOG_CONFIRMED:
|
||||
if (op->state!=SalOpStateTerminated && op->state!=SalOpStateTerminating) {
|
||||
|
|
@ -192,7 +192,7 @@ static void call_process_response(void *op_base, const belle_sip_response_event_
|
|||
req=belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(client_transaction));
|
||||
set_or_update_dialog(op,belle_sip_response_event_get_dialog(event));
|
||||
dialog_state=op->dialog?belle_sip_dialog_get_state(op->dialog):BELLE_SIP_DIALOG_NULL;
|
||||
|
||||
|
||||
ms_message("Op [%p] receiving call response [%i], dialog is [%p] in state [%s]",op,code,op->dialog,belle_sip_dialog_state_to_string(dialog_state));
|
||||
|
||||
switch(dialog_state) {
|
||||
|
|
@ -290,9 +290,9 @@ static void call_process_response(void *op_base, const belle_sip_response_event_
|
|||
|
||||
static void call_process_timeout(void *user_ctx, const belle_sip_timeout_event_t *event) {
|
||||
SalOp* op=(SalOp*)user_ctx;
|
||||
|
||||
|
||||
if (op->state==SalOpStateTerminated) return;
|
||||
|
||||
|
||||
if (!op->dialog) {
|
||||
/*call terminated very early*/
|
||||
sal_error_info_set(&op->error_info,SalReasonRequestTimeout,408,"Request timeout",NULL);
|
||||
|
|
@ -342,7 +342,7 @@ static void unsupported_method(belle_sip_server_transaction_t* server_transactio
|
|||
* Extract the sdp from a sip message.
|
||||
* If there is no body in the message, the session_desc is set to null, 0 is returned.
|
||||
* If body was present is not a SDP or parsing of SDP failed, -1 is returned and SalReason is set appropriately.
|
||||
*
|
||||
*
|
||||
**/
|
||||
static int extract_sdp(belle_sip_message_t* message,belle_sdp_session_description_t** session_desc, SalReason *error) {
|
||||
belle_sip_header_content_type_t* content_type=belle_sip_message_get_header_by_type(message,belle_sip_header_content_type_t);
|
||||
|
|
@ -388,7 +388,7 @@ static int process_sdp_for_invite(SalOp* op,belle_sip_request_t* invite) {
|
|||
belle_sip_object_unref(sdp);
|
||||
}else op->sdp_offering=TRUE; /*INVITE without SDP*/
|
||||
}else err=-1;
|
||||
|
||||
|
||||
if (err==-1){
|
||||
sal_call_decline(op,reason,NULL);
|
||||
}
|
||||
|
|
@ -560,6 +560,18 @@ static void process_request_event(void *op_base, const belle_sip_request_event_t
|
|||
belle_sip_server_transaction_send_response(server_transaction,sal_op_create_response_from_request(op,req,481));
|
||||
} else if (strcmp("MESSAGE",method)==0){
|
||||
sal_process_incoming_message(op,event);
|
||||
} else if (strcmp("UPDATE",method)==0) {
|
||||
/*rfc 3311
|
||||
* 5.2 Receiving an UPDATE
|
||||
* ...
|
||||
* If the UAS cannot change the session parameters without prompting the user, it SHOULD reject
|
||||
* the request with a 504 response.
|
||||
*/
|
||||
resp=sal_op_create_response_from_request(op,req,504);
|
||||
belle_sip_message_add_header( BELLE_SIP_MESSAGE(resp)
|
||||
,belle_sip_header_create( "Warning", "Cannot change the session parameters without prompting the user"));
|
||||
belle_sip_server_transaction_send_response(server_transaction,resp);
|
||||
return;
|
||||
}else{
|
||||
ms_error("unexpected method [%s] for dialog [%p]",belle_sip_request_get_method(req),op->dialog);
|
||||
unsupported_method(server_transaction,req);
|
||||
|
|
@ -582,7 +594,7 @@ int sal_call_set_local_media_description(SalOp *op, SalMediaDescription *desc){
|
|||
if (op->base.local_media)
|
||||
sal_media_description_unref(op->base.local_media);
|
||||
op->base.local_media=desc;
|
||||
|
||||
|
||||
if (op->base.remote_media){
|
||||
/*case of an incoming call where we modify the local capabilities between the time
|
||||
* the call is ringing and it is accepted (for example if you want to accept without video*/
|
||||
|
|
@ -597,7 +609,7 @@ int sal_call_set_local_media_description(SalOp *op, SalMediaDescription *desc){
|
|||
|
||||
static belle_sip_header_allow_t *create_allow(){
|
||||
belle_sip_header_allow_t* header_allow;
|
||||
header_allow = belle_sip_header_allow_create("INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, NOTIFY, MESSAGE, SUBSCRIBE, INFO, UPDATE");
|
||||
header_allow = belle_sip_header_allow_create("INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, NOTIFY, MESSAGE, SUBSCRIBE, INFO, UPDATE");
|
||||
return header_allow;
|
||||
}
|
||||
|
||||
|
|
@ -609,8 +621,8 @@ static void sal_op_fill_invite(SalOp *op, belle_sip_request_t* invite) {
|
|||
belle_sip_message_add_header(BELLE_SIP_MESSAGE(invite),belle_sip_header_create( "Supported", "timer"));
|
||||
}
|
||||
if (op->base.local_media){
|
||||
op->sdp_offering=TRUE;
|
||||
set_sdp_from_desc(BELLE_SIP_MESSAGE(invite),op->base.local_media);
|
||||
op->sdp_offering=TRUE;
|
||||
set_sdp_from_desc(BELLE_SIP_MESSAGE(invite),op->base.local_media);
|
||||
}else op->sdp_offering=FALSE;
|
||||
return;
|
||||
}
|
||||
|
|
@ -633,7 +645,7 @@ int sal_call(SalOp *op, const char *from, const char *to){
|
|||
}
|
||||
if (op->referred_by)
|
||||
belle_sip_message_add_header(BELLE_SIP_MESSAGE(invite),BELLE_SIP_HEADER(op->referred_by));
|
||||
|
||||
|
||||
return sal_op_send_request(op,invite);
|
||||
}
|
||||
|
||||
|
|
@ -679,7 +691,7 @@ int sal_call_notify_ringing(SalOp *op, bool_t early_media){
|
|||
belle_sip_response_t* ringing_response = sal_op_create_response_from_request(op,req,status_code);
|
||||
belle_sip_header_t *require;
|
||||
const char *tags=NULL;
|
||||
|
||||
|
||||
if (early_media){
|
||||
handle_offer_answer_response(op,ringing_response);
|
||||
}
|
||||
|
|
@ -692,7 +704,7 @@ int sal_call_notify_ringing(SalOp *op, bool_t early_media){
|
|||
}
|
||||
|
||||
#ifndef SAL_OP_CALL_FORCE_CONTACT_IN_RINGING
|
||||
if (tags && strstr(tags,"100rel")!=0)
|
||||
if (tags && strstr(tags,"100rel")!=0)
|
||||
#endif
|
||||
{
|
||||
belle_sip_header_address_t* contact= (belle_sip_header_address_t*)sal_op_get_contact_address(op);
|
||||
|
|
@ -740,7 +752,7 @@ int sal_call_accept(SalOp*h){
|
|||
if ((contact_header=sal_op_create_contact(h))) {
|
||||
belle_sip_message_add_header(BELLE_SIP_MESSAGE(response),BELLE_SIP_HEADER(contact_header));
|
||||
}
|
||||
|
||||
|
||||
_sal_op_add_custom_headers(h, BELLE_SIP_MESSAGE(response));
|
||||
|
||||
handle_offer_answer_response(h,response);
|
||||
|
|
@ -757,7 +769,7 @@ int sal_call_decline(SalOp *op, SalReason reason, const char *redirection /*opti
|
|||
belle_sip_response_t* response;
|
||||
belle_sip_header_contact_t* contact=NULL;
|
||||
int status=sal_reason_to_sip_code(reason);
|
||||
|
||||
|
||||
if (reason==SalReasonRedirect){
|
||||
if (redirection!=NULL) {
|
||||
if (strstr(redirection,"sip:")!=0) status=302;
|
||||
|
|
@ -812,7 +824,7 @@ int sal_call_send_dtmf(SalOp *h, char dtmf){
|
|||
if (req){
|
||||
int bodylen;
|
||||
char dtmf_body[128]={0};
|
||||
|
||||
|
||||
snprintf(dtmf_body, sizeof(dtmf_body)-1, "Signal=%c\r\nDuration=250\r\n", dtmf);
|
||||
bodylen=strlen(dtmf_body);
|
||||
belle_sip_message_set_body((belle_sip_message_t*)req,dtmf_body,bodylen);
|
||||
|
|
|
|||
|
|
@ -90,19 +90,19 @@ SalAuthInfo * sal_op_get_auth_requested(SalOp *op){
|
|||
belle_sip_header_contact_t* sal_op_create_contact(SalOp *op){
|
||||
belle_sip_header_contact_t* contact_header;
|
||||
belle_sip_uri_t* contact_uri;
|
||||
|
||||
|
||||
if (sal_op_get_contact_address(op)) {
|
||||
contact_header = belle_sip_header_contact_create(BELLE_SIP_HEADER_ADDRESS(sal_op_get_contact_address(op)));
|
||||
} else {
|
||||
contact_header= belle_sip_header_contact_new();
|
||||
}
|
||||
|
||||
|
||||
if (!(contact_uri=belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(contact_header)))) {
|
||||
/*no uri, just creating a new one*/
|
||||
contact_uri=belle_sip_uri_new();
|
||||
belle_sip_header_address_set_uri(BELLE_SIP_HEADER_ADDRESS(contact_header),contact_uri);
|
||||
}
|
||||
|
||||
|
||||
belle_sip_uri_set_secure(contact_uri,sal_op_is_secure(op));
|
||||
if (op->privacy!=SalPrivacyNone){
|
||||
belle_sip_uri_set_user(contact_uri,NULL);
|
||||
|
|
@ -122,15 +122,38 @@ belle_sip_header_t * sal_make_supported_header(Sal *sal){
|
|||
return belle_sip_header_create("Supported","replaces, outbound");
|
||||
}
|
||||
|
||||
static void add_initial_route_set(belle_sip_request_t *request, const MSList *list){
|
||||
const MSList *elem;
|
||||
for (elem=list;elem!=NULL;elem=elem->next){
|
||||
SalAddress *addr=(SalAddress*)elem->data;
|
||||
belle_sip_header_route_t *route;
|
||||
belle_sip_uri_t *uri;
|
||||
/*Optimization: if the initial route set only contains one URI which is the same as the request URI, ommit it*/
|
||||
if (elem==list && list->next==NULL){
|
||||
belle_sip_uri_t *requri=belle_sip_request_get_uri(request);
|
||||
/*skip the first route it is the same as the request uri*/
|
||||
if (strcmp(sal_address_get_domain(addr),belle_sip_uri_get_host(requri))==0 ){
|
||||
ms_message("Skipping top route of initial route-set because same as request-uri.");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
route=belle_sip_header_route_create((belle_sip_header_address_t*)addr);
|
||||
uri=belle_sip_header_address_get_uri((belle_sip_header_address_t*)route);
|
||||
belle_sip_uri_set_lr_param(uri,1);
|
||||
belle_sip_message_add_header((belle_sip_message_t*)request,(belle_sip_header_t*)route);
|
||||
}
|
||||
}
|
||||
|
||||
belle_sip_request_t* sal_op_build_request(SalOp *op,const char* method) {
|
||||
belle_sip_header_from_t* from_header;
|
||||
belle_sip_header_to_t* to_header;
|
||||
belle_sip_provider_t* prov=op->base.root->prov;
|
||||
belle_sip_request_t *req;
|
||||
belle_sip_uri_t* req_uri;
|
||||
const MSList *elem=sal_op_get_route_addresses(op);
|
||||
char token[10];
|
||||
|
||||
|
||||
if (strcmp("REGISTER",method)==0 || op->privacy==SalPrivacyNone) {
|
||||
from_header = belle_sip_header_from_create(BELLE_SIP_HEADER_ADDRESS(sal_op_get_from_address(op))
|
||||
,belle_sip_random_token(token,sizeof(token)));
|
||||
|
|
@ -157,6 +180,11 @@ belle_sip_request_t* sal_op_build_request(SalOp *op,const char* method) {
|
|||
belle_sip_header_p_preferred_identity_t* p_preferred_identity=belle_sip_header_p_preferred_identity_create(BELLE_SIP_HEADER_ADDRESS(sal_op_get_from_address(op)));
|
||||
belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(p_preferred_identity));
|
||||
}
|
||||
|
||||
if (elem && strcmp(method,"REGISTER")!=0 && !op->base.root->no_initial_route){
|
||||
add_initial_route_set(req,elem);
|
||||
}
|
||||
|
||||
if (strcmp("REGISTER",method)!=0 && op->privacy!=SalPrivacyNone ){
|
||||
belle_sip_header_privacy_t* privacy_header=belle_sip_header_privacy_new();
|
||||
if (op->privacy&SalPrivacyCritical)
|
||||
|
|
@ -213,7 +241,7 @@ void sal_op_resend_request(SalOp* op, belle_sip_request_t* request) {
|
|||
}
|
||||
|
||||
static void add_headers(SalOp *op, belle_sip_header_t *h, belle_sip_message_t *msg){
|
||||
|
||||
|
||||
if (BELLE_SIP_OBJECT_IS_INSTANCE_OF(h,belle_sip_header_contact_t)){
|
||||
belle_sip_header_contact_t* newct;
|
||||
/*special case for contact, we want to keep everything from the custom contact but set automatic mode and add our own parameters as well*/
|
||||
|
|
@ -224,7 +252,7 @@ static void add_headers(SalOp *op, belle_sip_header_t *h, belle_sip_message_t *m
|
|||
}
|
||||
/*if a header already exists in the message, replace it*/
|
||||
belle_sip_message_set_header(msg,h);
|
||||
|
||||
|
||||
}
|
||||
|
||||
void _sal_op_add_custom_headers(SalOp *op, belle_sip_message_t *msg){
|
||||
|
|
@ -246,20 +274,20 @@ static int _sal_op_send_request_with_contact(SalOp* op, belle_sip_request_t* req
|
|||
belle_sip_header_contact_t* contact;
|
||||
int result =-1;
|
||||
belle_sip_uri_t *next_hop_uri=NULL;
|
||||
|
||||
|
||||
if (add_contact) {
|
||||
contact = sal_op_create_contact(op);
|
||||
belle_sip_message_set_header(BELLE_SIP_MESSAGE(request),BELLE_SIP_HEADER(contact));
|
||||
}
|
||||
|
||||
|
||||
_sal_op_add_custom_headers(op, (belle_sip_message_t*)request);
|
||||
|
||||
|
||||
if (!op->dialog || belle_sip_dialog_get_state(op->dialog) == BELLE_SIP_DIALOG_NULL) {
|
||||
/*don't put route header if dialog is in confirmed state*/
|
||||
const MSList *elem=sal_op_get_route_addresses(op);
|
||||
const char *transport;
|
||||
const char *method=belle_sip_request_get_method(request);
|
||||
|
||||
|
||||
if (elem) {
|
||||
outbound_proxy=belle_sip_header_address_get_uri((belle_sip_header_address_t*)elem->data);
|
||||
next_hop_uri=outbound_proxy;
|
||||
|
|
@ -284,7 +312,7 @@ static int _sal_op_send_request_with_contact(SalOp* op, belle_sip_request_t* req
|
|||
}
|
||||
}
|
||||
}
|
||||
if ((strcmp(method,"REGISTER")==0 || strcmp(method,"SUBSCRIBE")==0) && transport &&
|
||||
if ((strcmp(method,"REGISTER")==0 || strcmp(method,"SUBSCRIBE")==0) && transport &&
|
||||
(strcasecmp(transport,"TCP")==0 || strcasecmp(transport,"TLS")==0)){
|
||||
/*RFC 5923: add 'alias' parameter to tell the server that we want it to keep the connection for future requests*/
|
||||
belle_sip_header_via_t *via=belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(request),belle_sip_header_via_t);
|
||||
|
|
@ -307,12 +335,12 @@ static int _sal_op_send_request_with_contact(SalOp* op, belle_sip_request_t* req
|
|||
belle_sip_provider_add_authorization(op->base.root->prov,request,NULL,NULL,NULL);
|
||||
}
|
||||
result = belle_sip_client_transaction_send_request_to(client_transaction,next_hop_uri/*might be null*/);
|
||||
|
||||
|
||||
/*update call id if not set yet for this OP*/
|
||||
if (result == 0 && !op->base.call_id) {
|
||||
op->base.call_id=ms_strdup(belle_sip_header_call_id_get_call_id(BELLE_SIP_HEADER_CALL_ID(belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(request), belle_sip_header_call_id_t))));
|
||||
}
|
||||
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
|
@ -323,9 +351,9 @@ int sal_op_send_request(SalOp* op, belle_sip_request_t* request) {
|
|||
return -1; /*sanity check*/
|
||||
}
|
||||
/*
|
||||
Header field where proxy ACK BYE CAN INV OPT REG
|
||||
___________________________________________________________
|
||||
Contact R o - - m o o
|
||||
Header field where proxy ACK BYE CAN INV OPT REG
|
||||
___________________________________________________________
|
||||
Contact R o - - m o o
|
||||
*/
|
||||
if (strcmp(belle_sip_request_get_method(request),"INVITE")==0
|
||||
||strcmp(belle_sip_request_get_method(request),"REGISTER")==0
|
||||
|
|
@ -415,7 +443,7 @@ SalReason sal_reason_to_sip_code(SalReason r){
|
|||
|
||||
SalReason _sal_reason_from_sip_code(int code) {
|
||||
if (code>=100 && code<300) return SalReasonNone;
|
||||
|
||||
|
||||
switch(code) {
|
||||
case 0:
|
||||
return SalReasonIOError;
|
||||
|
|
@ -490,7 +518,7 @@ void sal_error_info_reset(SalErrorInfo *ei){
|
|||
if (ei->warnings){
|
||||
ms_free(ei->warnings);
|
||||
ei->warnings=NULL;
|
||||
|
||||
|
||||
}
|
||||
if (ei->full_string){
|
||||
ms_free(ei->full_string);
|
||||
|
|
@ -522,7 +550,7 @@ void sal_op_set_error_info_from_response(SalOp *op, belle_sip_response_t *respon
|
|||
belle_sip_header_t *warning=belle_sip_message_get_header(BELLE_SIP_MESSAGE(response),"Warning");
|
||||
SalErrorInfo *ei=&op->error_info;
|
||||
const char *warnings;
|
||||
|
||||
|
||||
warnings=warning ? belle_sip_header_get_unparsed_value(warning) : NULL;
|
||||
if (warnings==NULL) warnings=reason_header ? belle_sip_header_get_unparsed_value(reason_header) : NULL;
|
||||
sal_error_info_set(ei,SalReasonUnknown,code,reason_phrase,warnings);
|
||||
|
|
@ -618,7 +646,7 @@ void sal_op_assign_recv_headers(SalOp *op, belle_sip_message_t *incoming){
|
|||
}
|
||||
|
||||
const char *sal_op_get_remote_contact(const SalOp *op){
|
||||
/*
|
||||
/*
|
||||
* remote contact is filled in process_response
|
||||
* return sal_custom_header_find(op->base.recv_custom_headers,"Contact");
|
||||
*/
|
||||
|
|
@ -649,16 +677,16 @@ bool_t sal_op_get_body(SalOp *op, belle_sip_message_t *msg, SalBody *salbody){
|
|||
belle_sip_header_content_type_t *content_type;
|
||||
belle_sip_header_content_length_t *clen=NULL;
|
||||
belle_sip_header_t *content_encoding;
|
||||
|
||||
|
||||
content_type=belle_sip_message_get_header_by_type(msg,belle_sip_header_content_type_t);
|
||||
if (content_type){
|
||||
body=belle_sip_message_get_body(msg);
|
||||
clen=belle_sip_message_get_header_by_type(msg,belle_sip_header_content_length_t);
|
||||
}
|
||||
content_encoding=belle_sip_message_get_header(msg,"Content-encoding");
|
||||
|
||||
|
||||
memset(salbody,0,sizeof(SalBody));
|
||||
|
||||
|
||||
if (content_type && body && clen) {
|
||||
salbody->type=belle_sip_header_content_type_get_type(content_type);
|
||||
salbody->subtype=belle_sip_header_content_type_get_subtype(content_type);
|
||||
|
|
@ -693,7 +721,7 @@ bool_t sal_op_is_ipv6(SalOp *op){
|
|||
belle_sip_transaction_t *tr=NULL;
|
||||
belle_sip_header_address_t *contact;
|
||||
belle_sip_request_t *req;
|
||||
|
||||
|
||||
if (op->refresher)
|
||||
tr=(belle_sip_transaction_t *)belle_sip_refresher_get_transaction(op->refresher);
|
||||
|
||||
|
|
@ -701,7 +729,7 @@ bool_t sal_op_is_ipv6(SalOp *op){
|
|||
tr=(belle_sip_transaction_t *)op->pending_client_trans;
|
||||
if (tr==NULL)
|
||||
tr=(belle_sip_transaction_t *)op->pending_server_trans;
|
||||
|
||||
|
||||
if (tr==NULL){
|
||||
ms_error("Unable to determine IP version from signaling operation.");
|
||||
return FALSE;
|
||||
|
|
|
|||
|
|
@ -164,6 +164,8 @@ static SalPresenceModel * process_presence_notification(SalOp *op, belle_sip_req
|
|||
return NULL;
|
||||
if (belle_sip_header_content_length_get_content_length(content_length) == 0)
|
||||
return NULL;
|
||||
|
||||
if (body==NULL) return NULL;
|
||||
|
||||
op->base.root->callbacks.parse_presence_requested(op,
|
||||
belle_sip_header_content_type_get_type(content_type),
|
||||
|
|
@ -175,7 +177,7 @@ static SalPresenceModel * process_presence_notification(SalOp *op, belle_sip_req
|
|||
}
|
||||
|
||||
static void handle_notify(SalOp *op, belle_sip_request_t *req){
|
||||
belle_sip_response_t* resp;
|
||||
belle_sip_response_t* resp=NULL;
|
||||
belle_sip_server_transaction_t* server_transaction=op->pending_server_trans;
|
||||
belle_sip_header_subscription_state_t* subscription_state_header=belle_sip_message_get_header_by_type(req,belle_sip_header_subscription_state_t);
|
||||
SalSubscribeStatus sub_state;
|
||||
|
|
@ -183,30 +185,24 @@ static void handle_notify(SalOp *op, belle_sip_request_t *req){
|
|||
if (strcmp("NOTIFY",belle_sip_request_get_method(req))==0) {
|
||||
SalPresenceModel *presence_model = NULL;
|
||||
const char* body = belle_sip_message_get_body(BELLE_SIP_MESSAGE(req));
|
||||
if (body==NULL){
|
||||
ms_error("No body in NOTIFY received from [%s]",sal_op_get_from(op));
|
||||
resp = sal_op_create_response_from_request(op, req, 415);
|
||||
belle_sip_server_transaction_send_response(server_transaction,resp);
|
||||
return;
|
||||
if (!subscription_state_header || strcasecmp(BELLE_SIP_SUBSCRIPTION_STATE_TERMINATED,belle_sip_header_subscription_state_get_state(subscription_state_header)) ==0) {
|
||||
sub_state=SalSubscribeTerminated;
|
||||
ms_message("Outgoing subscription terminated by remote [%s]",sal_op_get_to(op));
|
||||
} else {
|
||||
sub_state=SalSubscribeActive;
|
||||
}
|
||||
presence_model = process_presence_notification(op, req);
|
||||
if (presence_model != NULL) {
|
||||
if (presence_model != NULL || body==NULL) {
|
||||
/* Presence notification body parsed successfully. */
|
||||
if (!subscription_state_header || strcasecmp(BELLE_SIP_SUBSCRIPTION_STATE_TERMINATED,belle_sip_header_subscription_state_get_state(subscription_state_header)) ==0) {
|
||||
sub_state=SalSubscribeTerminated;
|
||||
ms_message("Outgoing subscription terminated by remote [%s]",sal_op_get_to(op));
|
||||
} else {
|
||||
sub_state=SalSubscribeActive;
|
||||
}
|
||||
|
||||
resp = sal_op_create_response_from_request(op, req, 200); /*create first because the op may be destroyed by notify_presence */
|
||||
op->base.root->callbacks.notify_presence(op, sub_state, presence_model, NULL);
|
||||
|
||||
} else {
|
||||
} else if (body){
|
||||
/* Formatting error in presence notification body. */
|
||||
ms_error("Wrongly formatted presence notification received");
|
||||
resp = sal_op_create_response_from_request(op, req, 400);
|
||||
ms_warning("Wrongly formatted presence document.");
|
||||
resp = sal_op_create_response_from_request(op, req, 488);
|
||||
}
|
||||
belle_sip_server_transaction_send_response(server_transaction,resp);
|
||||
if (resp) belle_sip_server_transaction_send_response(server_transaction,resp);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ static void register_refresher_listener (belle_sip_refresher_t* refresher
|
|||
/*only take first one for now*/
|
||||
op->auth_info=sal_auth_info_create((belle_sip_auth_event_t*)(belle_sip_refresher_get_auth_events(refresher)->data));
|
||||
}
|
||||
sal_error_info_set(&op->error_info,SalReasonUnknown,status_code,reason_phrase,NULL);
|
||||
if(status_code == 200) {
|
||||
/*check service route rfc3608*/
|
||||
belle_sip_header_service_route_t* service_route;
|
||||
|
|
@ -41,7 +42,7 @@ static void register_refresher_listener (belle_sip_refresher_t* refresher
|
|||
}
|
||||
sal_op_set_service_route(op,(const SalAddress*)service_route_address);
|
||||
if (service_route_address) belle_sip_object_unref(service_route_address);
|
||||
|
||||
|
||||
sal_remove_pending_auth(op->base.root,op); /*just in case*/
|
||||
op->base.root->callbacks.register_success(op,belle_sip_refresher_get_expires(op->refresher)>0);
|
||||
} else if (status_code>=400) {
|
||||
|
|
@ -55,7 +56,6 @@ static void register_refresher_listener (belle_sip_refresher_t* refresher
|
|||
chooses not to re-register, the UA SHOULD discard any stored service
|
||||
route for that address-of-record. */
|
||||
sal_op_set_service_route(op,NULL);
|
||||
sal_error_info_set(&op->error_info,SalReasonUnknown,status_code,reason_phrase,NULL);
|
||||
op->base.root->callbacks.register_failure(op);
|
||||
if (op->auth_info) {
|
||||
/*add pending auth*/
|
||||
|
|
|
|||
|
|
@ -117,7 +117,7 @@ static void stream_description_to_sdp ( belle_sdp_session_description_t *session
|
|||
mime_param= belle_sdp_mime_parameter_create ( pt->mime_type
|
||||
, payload_type_get_number ( pt )
|
||||
, pt->clock_rate
|
||||
,stream->type==SalAudio?1:-1 );
|
||||
, pt->channels>0 ? pt->channels : -1 );
|
||||
belle_sdp_mime_parameter_set_parameters ( mime_param,pt->recv_fmtp );
|
||||
if ( stream->ptime>0 ) {
|
||||
belle_sdp_mime_parameter_set_ptime ( mime_param,stream->ptime );
|
||||
|
|
@ -149,22 +149,22 @@ static void stream_description_to_sdp ( belle_sdp_session_description_t *session
|
|||
const char *enc_name=NULL;
|
||||
|
||||
switch ( stream->crypto[j].algo ) {
|
||||
case AES_128_SHA1_80:
|
||||
case MS_AES_128_SHA1_80:
|
||||
enc_name="AES_CM_128_HMAC_SHA1_80";
|
||||
break;
|
||||
case AES_128_SHA1_32:
|
||||
case MS_AES_128_SHA1_32:
|
||||
enc_name="AES_CM_128_HMAC_SHA1_32";
|
||||
break;
|
||||
case AES_256_SHA1_32:
|
||||
case MS_AES_256_SHA1_32:
|
||||
enc_name="AES_CM_256_HMAC_SHA1_32";
|
||||
break;
|
||||
case AES_256_SHA1_80:
|
||||
case MS_AES_256_SHA1_80:
|
||||
enc_name="AES_CM_256_HMAC_SHA1_32";
|
||||
break;
|
||||
case AES_128_NO_AUTH:
|
||||
case MS_AES_128_NO_AUTH:
|
||||
ms_warning ( "Unsupported crypto suite: AES_128_NO_AUTH" );
|
||||
break;
|
||||
case NO_CIPHER_SHA1_80:
|
||||
case MS_NO_CIPHER_SHA1_80:
|
||||
ms_warning ( "Unsupported crypto suite: NO_CIPHER_SHA1_80" );
|
||||
break;
|
||||
default:
|
||||
|
|
@ -351,13 +351,13 @@ static void sdp_parse_media_crypto_parameters(belle_sdp_media_description_t *med
|
|||
tmp2 );
|
||||
if ( nb == 3 ) {
|
||||
if ( keywordcmp ( "AES_CM_128_HMAC_SHA1_80",tmp ) == 0 ){
|
||||
stream->crypto[valid_count].algo = AES_128_SHA1_80;
|
||||
stream->crypto[valid_count].algo = MS_AES_128_SHA1_80;
|
||||
}else if ( keywordcmp ( "AES_CM_128_HMAC_SHA1_32",tmp ) == 0 ){
|
||||
stream->crypto[valid_count].algo = AES_128_SHA1_32;
|
||||
stream->crypto[valid_count].algo = MS_AES_128_SHA1_32;
|
||||
}else if ( keywordcmp ( "AES_CM_256_HMAC_SHA1_32",tmp ) == 0 ){
|
||||
stream->crypto[valid_count].algo = AES_256_SHA1_32;
|
||||
stream->crypto[valid_count].algo = MS_AES_256_SHA1_32;
|
||||
}else if ( keywordcmp ( "AES_CM_256_HMAC_SHA1_80",tmp ) == 0 ){
|
||||
stream->crypto[valid_count].algo = AES_256_SHA1_80;
|
||||
stream->crypto[valid_count].algo = MS_AES_256_SHA1_80;
|
||||
}else {
|
||||
ms_warning ( "Failed to parse crypto-algo: '%s'", tmp );
|
||||
stream->crypto[valid_count].algo = 0;
|
||||
|
|
|
|||
|
|
@ -1075,7 +1075,7 @@ static void notify(SalOp *op, SalSubscribeStatus st, const char *eventname, cons
|
|||
|
||||
if (lev==NULL) {
|
||||
/*out of subscribe notify */
|
||||
lev=linphone_event_new_with_op(lc,op,LinphoneSubscriptionOutgoing,eventname);
|
||||
lev=linphone_event_new_with_out_of_dialog_op(lc,op,LinphoneSubscriptionOutgoing,eventname);
|
||||
}
|
||||
if (lc->vtable.notify_received){
|
||||
const LinphoneContent *ct=linphone_content_from_sal_body(&content,body);
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@
|
|||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
|
||||
#include "linphonecore.h"
|
||||
#include "private.h"
|
||||
#include "lpconfig.h"
|
||||
|
|
@ -114,7 +114,7 @@ bool_t linphone_chat_room_matches(LinphoneChatRoom *cr, const LinphoneAddress *f
|
|||
LinphoneChatRoom* linphone_core_get_or_create_chat_room(LinphoneCore* lc, const char* to) {
|
||||
LinphoneAddress *to_addr=linphone_core_interpret_url(lc,to);
|
||||
LinphoneChatRoom *ret;
|
||||
|
||||
|
||||
if (to_addr==NULL){
|
||||
ms_error("linphone_core_get_or_create_chat_room(): Cannot make a valid address with %s",to);
|
||||
return NULL;
|
||||
|
|
@ -174,7 +174,7 @@ static void _linphone_chat_room_send_message(LinphoneChatRoom *cr, LinphoneChatM
|
|||
char* content_type;
|
||||
const char *identity=NULL;
|
||||
time_t t=time(NULL);
|
||||
|
||||
|
||||
if (lp_config_get_int(cr->lc->config,"sip","chat_use_call_dialogs",0)){
|
||||
if((call = linphone_core_get_call_by_remote_address(cr->lc,cr->peer))!=NULL){
|
||||
if (call->state==LinphoneCallConnected ||
|
||||
|
|
@ -271,7 +271,7 @@ void linphone_core_message_received(LinphoneCore *lc, SalOp *op, const SalMessag
|
|||
char *cleanfrom;
|
||||
LinphoneChatMessage* msg;
|
||||
const SalCustomHeader *ch;
|
||||
|
||||
|
||||
addr=linphone_address_new(sal_msg->from);
|
||||
linphone_address_clean(addr);
|
||||
cr=linphone_core_get_chat_room(lc,addr);
|
||||
|
|
@ -284,20 +284,20 @@ void linphone_core_message_received(LinphoneCore *lc, SalOp *op, const SalMessag
|
|||
msg = linphone_chat_room_create_message(cr, sal_msg->text);
|
||||
|
||||
linphone_chat_message_set_from(msg, cr->peer_url);
|
||||
|
||||
|
||||
{
|
||||
LinphoneAddress *to;
|
||||
to=sal_op_get_to(op) ? linphone_address_new(sal_op_get_to(op)) : linphone_address_new(linphone_core_get_identity(lc));
|
||||
msg->to=to;
|
||||
}
|
||||
|
||||
|
||||
msg->time=sal_msg->time;
|
||||
msg->state=LinphoneChatMessageStateDelivered;
|
||||
msg->is_read=FALSE;
|
||||
msg->dir=LinphoneChatMessageIncoming;
|
||||
ch=sal_op_get_recv_custom_header(op);
|
||||
if (ch) msg->custom_headers=sal_custom_header_clone(ch);
|
||||
|
||||
|
||||
if (sal_msg->url) {
|
||||
linphone_chat_message_set_external_body_url(msg, sal_msg->url);
|
||||
}
|
||||
|
|
@ -442,8 +442,8 @@ LinphoneChatMessage* linphone_chat_room_create_message(LinphoneChatRoom *cr, con
|
|||
* @return a new #LinphoneChatMessage
|
||||
*/
|
||||
LinphoneChatMessage* linphone_chat_room_create_message_2(
|
||||
LinphoneChatRoom *cr, const char* message, const char* external_body_url,
|
||||
LinphoneChatMessageState state, time_t time, bool_t is_read, bool_t is_incoming) {
|
||||
LinphoneChatRoom *cr, const char* message, const char* external_body_url,
|
||||
LinphoneChatMessageState state, time_t time, bool_t is_read, bool_t is_incoming) {
|
||||
LinphoneCore *lc=linphone_chat_room_get_lc(cr);
|
||||
|
||||
LinphoneChatMessage* msg = belle_sip_object_new(LinphoneChatMessage);
|
||||
|
|
@ -610,13 +610,13 @@ void linphone_chat_room_compose(LinphoneChatRoom *cr) {
|
|||
*/
|
||||
const char* linphone_chat_message_state_to_string(const LinphoneChatMessageState state) {
|
||||
switch (state) {
|
||||
case LinphoneChatMessageStateIdle:return "LinphoneChatMessageStateIdle";
|
||||
case LinphoneChatMessageStateIdle:return "LinphoneChatMessageStateIdle";
|
||||
case LinphoneChatMessageStateInProgress:return "LinphoneChatMessageStateInProgress";
|
||||
case LinphoneChatMessageStateDelivered:return "LinphoneChatMessageStateDelivered";
|
||||
case LinphoneChatMessageStateNotDelivered:return "LinphoneChatMessageStateNotDelivered";
|
||||
default: return "Unknown state";
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -658,8 +658,8 @@ const char* linphone_chat_message_get_external_body_url(const LinphoneChatMessag
|
|||
|
||||
/**
|
||||
* Linphone message can carry external body as defined by rfc2017
|
||||
*
|
||||
* @param message a LinphoneChatMessage
|
||||
*
|
||||
* @param message a LinphoneChatMessage
|
||||
* @param url ex: access-type=URL; URL="http://www.foo.com/file"
|
||||
*/
|
||||
void linphone_chat_message_set_external_body_url(LinphoneChatMessage* message,const char* url) {
|
||||
|
|
@ -680,7 +680,7 @@ void linphone_chat_message_set_from(LinphoneChatMessage* message, const Linphone
|
|||
}
|
||||
|
||||
/**
|
||||
* Get origin of the message
|
||||
* Get origin of the message
|
||||
*@param message #LinphoneChatMessage obj
|
||||
*@return #LinphoneAddress
|
||||
*/
|
||||
|
|
@ -699,7 +699,7 @@ void linphone_chat_message_set_to(LinphoneChatMessage* message, const LinphoneAd
|
|||
}
|
||||
|
||||
/**
|
||||
* Get destination of the message
|
||||
* Get destination of the message
|
||||
*@param message #LinphoneChatMessage obj
|
||||
*@return #LinphoneAddress
|
||||
*/
|
||||
|
|
@ -785,7 +785,7 @@ bool_t linphone_chat_message_is_outgoing(LinphoneChatMessage* message) {
|
|||
* @return the id
|
||||
*/
|
||||
unsigned int linphone_chat_message_get_storage_id(LinphoneChatMessage* message) {
|
||||
return message->storage_id;
|
||||
return message->storage_id;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -74,17 +74,17 @@ LinphoneEvent *linphone_event_new(LinphoneCore *lc, LinphoneSubscriptionDir dir,
|
|||
return lev;
|
||||
}
|
||||
|
||||
LinphoneEvent *linphone_event_new_with_op(LinphoneCore *lc, SalOp *op, LinphoneSubscriptionDir dir, const char *name){
|
||||
static LinphoneEvent *linphone_event_new_with_op_base(LinphoneCore *lc, SalOp *op, LinphoneSubscriptionDir dir, const char *name, bool_t is_out_of_dialog){
|
||||
LinphoneEvent *lev=linphone_event_new_base(lc, dir, name, op);
|
||||
if (dir==LinphoneSubscriptionIncoming){
|
||||
lev->resource_addr=linphone_address_clone((LinphoneAddress*)sal_op_get_to_address(op));
|
||||
lev->from=linphone_address_clone((LinphoneAddress*)sal_op_get_from_address(lev->op));
|
||||
}else{
|
||||
lev->resource_addr=linphone_address_clone((LinphoneAddress*)sal_op_get_from_address(op));
|
||||
}
|
||||
lev->is_out_of_dialog_op=is_out_of_dialog;
|
||||
return lev;
|
||||
}
|
||||
|
||||
LinphoneEvent *linphone_event_new_with_op(LinphoneCore *lc, SalOp *op, LinphoneSubscriptionDir dir, const char *name) {
|
||||
return linphone_event_new_with_op_base(lc,op,dir,name,FALSE);
|
||||
}
|
||||
LinphoneEvent *linphone_event_new_with_out_of_dialog_op(LinphoneCore *lc, SalOp *op, LinphoneSubscriptionDir dir, const char *name) {
|
||||
return linphone_event_new_with_op_base(lc,op,dir,name,TRUE);
|
||||
}
|
||||
void linphone_event_set_state(LinphoneEvent *lev, LinphoneSubscriptionState state){
|
||||
LinphoneCore *lc=lev->lc;
|
||||
if (lev->subscription_state!=state){
|
||||
|
|
@ -129,8 +129,6 @@ LinphoneEvent *linphone_core_create_subscribe(LinphoneCore *lc, const LinphoneAd
|
|||
LinphoneEvent *lev=linphone_event_new(lc, LinphoneSubscriptionOutgoing, event, expires);
|
||||
linphone_configure_op(lc,lev->op,resource,NULL,TRUE);
|
||||
sal_op_set_manual_refresher_mode(lev->op,!lp_config_get_int(lc->config,"sip","refresh_generic_subscribe",1));
|
||||
lev->resource_addr=linphone_address_clone(resource);
|
||||
lev->from=linphone_address_clone((LinphoneAddress*)sal_op_get_from_address(lev->op));
|
||||
return lev;
|
||||
}
|
||||
|
||||
|
|
@ -318,8 +316,6 @@ static void linphone_event_destroy(LinphoneEvent *lev){
|
|||
if (lev->op)
|
||||
sal_op_release(lev->op);
|
||||
ms_free(lev->name);
|
||||
if (lev->resource_addr) linphone_address_destroy(lev->resource_addr);
|
||||
if (lev->from) linphone_address_destroy(lev->from);
|
||||
ms_free(lev);
|
||||
}
|
||||
|
||||
|
|
@ -341,11 +337,19 @@ const char *linphone_event_get_name(const LinphoneEvent *lev){
|
|||
}
|
||||
|
||||
const LinphoneAddress *linphone_event_get_from(const LinphoneEvent *lev){
|
||||
return lev->from;
|
||||
if (lev->is_out_of_dialog_op){
|
||||
return (LinphoneAddress*)sal_op_get_to_address(lev->op);
|
||||
}else{
|
||||
return (LinphoneAddress*)sal_op_get_from_address(lev->op);
|
||||
}
|
||||
}
|
||||
|
||||
const LinphoneAddress *linphone_event_get_resource(const LinphoneEvent *lev){
|
||||
return lev->resource_addr;
|
||||
if (lev->is_out_of_dialog_op){
|
||||
return (LinphoneAddress*)sal_op_get_from_address(lev->op);
|
||||
}else{
|
||||
return (LinphoneAddress*)sal_op_get_to_address(lev->op);
|
||||
}
|
||||
}
|
||||
|
||||
LinphoneCore *linphone_event_get_core(const LinphoneEvent *lev){
|
||||
|
|
|
|||
|
|
@ -62,8 +62,8 @@ const char *linphone_online_status_to_string(LinphoneOnlineStatus ss){
|
|||
case LinphoneStatusPending:
|
||||
str=_("Pending");
|
||||
break;
|
||||
case LinphoneStatusVacation:
|
||||
str=_("Vacation");
|
||||
case LinphoneStatusVacation:
|
||||
str=_("Vacation");
|
||||
default:
|
||||
str=_("Unknown-bug");
|
||||
}
|
||||
|
|
@ -109,7 +109,7 @@ LinphoneFriend *linphone_find_friend_by_out_subscribe(MSList *l, SalOp *op){
|
|||
|
||||
void __linphone_friend_do_subscribe(LinphoneFriend *fr){
|
||||
LinphoneCore *lc=fr->lc;
|
||||
|
||||
|
||||
if (fr->outsub==NULL){
|
||||
/* people for which we don't have yet an answer should appear as offline */
|
||||
fr->presence=NULL;
|
||||
|
|
@ -132,7 +132,7 @@ LinphoneFriend * linphone_friend_new(){
|
|||
obj->pol=LinphoneSPAccept;
|
||||
obj->presence=NULL;
|
||||
obj->subscribe=TRUE;
|
||||
return obj;
|
||||
return obj;
|
||||
}
|
||||
|
||||
LinphoneFriend *linphone_friend_new_with_address(const char *addr){
|
||||
|
|
@ -244,9 +244,17 @@ static void linphone_friend_unsubscribe(LinphoneFriend *lf){
|
|||
|
||||
static void linphone_friend_invalidate_subscription(LinphoneFriend *lf){
|
||||
if (lf->outsub!=NULL) {
|
||||
LinphoneCore *lc=lf->lc;
|
||||
sal_op_release(lf->outsub);
|
||||
lf->outsub=NULL;
|
||||
lf->subscribe_active=FALSE;
|
||||
/*notify application that we no longer know the presence activity */
|
||||
if (lf->presence != NULL) {
|
||||
linphone_presence_model_unref(lf->presence);
|
||||
}
|
||||
lf->presence = linphone_presence_model_new_with_activity(LinphonePresenceActivityOffline,"unknown activity");
|
||||
if (lc->vtable.notify_presence_received)
|
||||
lc->vtable.notify_presence_received(lc,lf);
|
||||
}
|
||||
lf->initial_subscribes_sent=FALSE;
|
||||
}
|
||||
|
|
@ -255,7 +263,7 @@ void linphone_friend_close_subscriptions(LinphoneFriend *lf){
|
|||
linphone_friend_unsubscribe(lf);
|
||||
if (lf->insub){
|
||||
sal_notify_presence_close(lf->insub);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -388,7 +396,7 @@ BuddyInfo * linphone_friend_get_info(const LinphoneFriend *lf){
|
|||
**/
|
||||
void linphone_friend_update_subscribes(LinphoneFriend *fr, LinphoneProxyConfig *proxy, bool_t only_when_registered){
|
||||
int can_subscribe=1;
|
||||
|
||||
|
||||
if (only_when_registered && (fr->subscribe || fr->subscribe_active)){
|
||||
LinphoneProxyConfig *cfg=linphone_core_lookup_known_proxy(fr->lc,fr->uri);
|
||||
if (proxy && proxy!=cfg) return;
|
||||
|
|
@ -592,13 +600,13 @@ LinphoneFriend * linphone_friend_new_from_config_file(LinphoneCore *lc, int inde
|
|||
int a;
|
||||
LinphoneFriend *lf;
|
||||
LpConfig *config=lc->config;
|
||||
|
||||
|
||||
sprintf(item,"friend_%i",index);
|
||||
|
||||
|
||||
if (!lp_config_has_section(config,item)){
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
tmp=lp_config_get_string(config,item,"url",NULL);
|
||||
if (tmp==NULL) {
|
||||
return NULL;
|
||||
|
|
@ -614,7 +622,7 @@ LinphoneFriend * linphone_friend_new_from_config_file(LinphoneCore *lc, int inde
|
|||
}
|
||||
a=lp_config_get_int(config,item,"subscribe",0);
|
||||
linphone_friend_send_subscribe(lf,a);
|
||||
|
||||
|
||||
linphone_friend_set_ref_key(lf,lp_config_get_string(config,item,"refkey",NULL));
|
||||
return lf;
|
||||
}
|
||||
|
|
@ -639,9 +647,9 @@ void linphone_friend_write_to_config_file(LpConfig *config, LinphoneFriend *lf,
|
|||
char key[50];
|
||||
char *tmp;
|
||||
const char *refkey;
|
||||
|
||||
|
||||
sprintf(key,"friend_%i",index);
|
||||
|
||||
|
||||
if (lf==NULL){
|
||||
lp_config_clean_section(config,key);
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ void linphone_tunnel_remove_server(LinphoneTunnel *tunnel, LinphoneTunnelConfig
|
|||
}
|
||||
|
||||
const MSList *linphone_tunnel_get_servers(LinphoneTunnel *tunnel){
|
||||
return NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void linphone_tunnel_clean_servers(LinphoneTunnel *tunnel){
|
||||
|
|
@ -56,7 +56,7 @@ void linphone_tunnel_enable(LinphoneTunnel *tunnel, bool_t enabled){
|
|||
}
|
||||
|
||||
bool_t linphone_tunnel_enabled(LinphoneTunnel *tunnel){
|
||||
return FALSE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
bool_t linphone_tunnel_connected(LinphoneTunnel *tunnel){
|
||||
|
|
|
|||
|
|
@ -95,25 +95,24 @@ bool_t linphone_call_get_authentication_token_verified(LinphoneCall *call){
|
|||
}
|
||||
|
||||
static bool_t linphone_call_are_all_streams_encrypted(LinphoneCall *call) {
|
||||
// Check ZRTP encryption in audiostream
|
||||
if (!call->audiostream_encrypted) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
#ifdef VIDEO_ENABLED
|
||||
// If video enabled, check ZRTP encryption in videostream
|
||||
{
|
||||
const LinphoneCallParams *params=linphone_call_get_current_params(call);
|
||||
if (params->has_video && !call->videostream_encrypted) {
|
||||
return FALSE;
|
||||
int number_of_encrypted_stream = 0;
|
||||
int number_of_active_stream = 0;
|
||||
if (call) {
|
||||
if (call->audiostream && media_stream_get_state((MediaStream *)call->audiostream) == MSStreamStarted) {
|
||||
number_of_active_stream++;
|
||||
if(media_stream_is_secured((MediaStream *)call->audiostream))
|
||||
number_of_encrypted_stream++;
|
||||
}
|
||||
if (call->videostream && media_stream_get_state((MediaStream *)call->videostream) == MSStreamStarted) {
|
||||
number_of_active_stream++;
|
||||
if (media_stream_is_secured((MediaStream *)call->videostream))
|
||||
number_of_encrypted_stream++;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return TRUE;
|
||||
return number_of_active_stream>0 && number_of_active_stream==number_of_encrypted_stream;
|
||||
}
|
||||
|
||||
void propagate_encryption_changed(LinphoneCall *call){
|
||||
static void propagate_encryption_changed(LinphoneCall *call){
|
||||
LinphoneCore *lc=call->core;
|
||||
if (!linphone_call_are_all_streams_encrypted(call)) {
|
||||
ms_message("Some streams are not encrypted");
|
||||
|
|
@ -128,23 +127,11 @@ void propagate_encryption_changed(LinphoneCall *call){
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef VIDEO_ENABLED
|
||||
static void linphone_call_videostream_encryption_changed(void *data, bool_t encrypted){
|
||||
LinphoneCall *call = (LinphoneCall *)data;
|
||||
|
||||
ms_message("Video stream is %s", encrypted ? "encrypted" : "not encrypted");
|
||||
call->videostream_encrypted=encrypted;
|
||||
propagate_encryption_changed(call);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void linphone_call_audiostream_encryption_changed(void *data, bool_t encrypted) {
|
||||
char status[255]={0};
|
||||
LinphoneCall *call;
|
||||
ms_message("Audio stream is %s ", encrypted ? "encrypted" : "not encrypted");
|
||||
|
||||
call = (LinphoneCall *)data;
|
||||
call->audiostream_encrypted=encrypted;
|
||||
|
||||
if (encrypted && call->core->vtable.display_status != NULL) {
|
||||
snprintf(status,sizeof(status)-1,_("Authentication token is %s"),call->auth_token);
|
||||
|
|
@ -248,7 +235,7 @@ static void setup_encryption_keys(LinphoneCall *call, SalMediaDescription *md){
|
|||
LinphoneCore *lc=call->core;
|
||||
int i;
|
||||
SalMediaDescription *old_md=call->localdesc;
|
||||
bool_t keep_srtp_keys=lp_config_get_int(lc->config,"sip","keep_srtp_keys",0);
|
||||
bool_t keep_srtp_keys=lp_config_get_int(lc->config,"sip","keep_srtp_keys",1);
|
||||
|
||||
for(i=0; i<md->n_active_streams; i++) {
|
||||
if (md->streams[i].proto == SalProtoRtpSavp) {
|
||||
|
|
@ -260,11 +247,11 @@ static void setup_encryption_keys(LinphoneCall *call, SalMediaDescription *md){
|
|||
}
|
||||
}else{
|
||||
md->streams[i].crypto[0].tag = 1;
|
||||
md->streams[i].crypto[0].algo = AES_128_SHA1_80;
|
||||
md->streams[i].crypto[0].algo = MS_AES_128_SHA1_80;
|
||||
if (!generate_b64_crypto_key(30, md->streams[i].crypto[0].master_key, SAL_SRTP_KEY_SIZE))
|
||||
md->streams[i].crypto[0].algo = 0;
|
||||
md->streams[i].crypto[1].tag = 2;
|
||||
md->streams[i].crypto[1].algo = AES_128_SHA1_32;
|
||||
md->streams[i].crypto[1].algo = MS_AES_128_SHA1_32;
|
||||
if (!generate_b64_crypto_key(30, md->streams[i].crypto[1].master_key, SAL_SRTP_KEY_SIZE))
|
||||
md->streams[i].crypto[1].algo = 0;
|
||||
md->streams[i].crypto[2].algo = 0;
|
||||
|
|
@ -399,7 +386,7 @@ static int find_port_offset(LinphoneCore *lc, int stream_index, int base_port){
|
|||
int tried_port;
|
||||
int existing_port;
|
||||
bool_t already_used=FALSE;
|
||||
|
||||
|
||||
for(offset=0;offset<100;offset+=2){
|
||||
tried_port=base_port+offset;
|
||||
already_used=FALSE;
|
||||
|
|
@ -482,13 +469,14 @@ static void linphone_call_init_common(LinphoneCall *call, LinphoneAddress *from,
|
|||
call->log=linphone_call_log_new(call, from, to);
|
||||
call->owns_call_log=TRUE;
|
||||
call->camera_enabled=TRUE;
|
||||
call->current_params.media_encryption=LinphoneMediaEncryptionNone;
|
||||
|
||||
linphone_core_get_audio_port_range(call->core, &min_port, &max_port);
|
||||
port_config_set(call,0,min_port,max_port);
|
||||
|
||||
|
||||
linphone_core_get_video_port_range(call->core, &min_port, &max_port);
|
||||
port_config_set(call,1,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);
|
||||
}
|
||||
|
|
@ -648,14 +636,7 @@ LinphoneCall * linphone_call_new_incoming(LinphoneCore *lc, LinphoneAddress *fro
|
|||
linphone_call_init_media_streams(call);
|
||||
switch (linphone_core_get_firewall_policy(call->core)) {
|
||||
case LinphonePolicyUseIce:
|
||||
/*start ICE gathering*/
|
||||
linphone_core_update_ice_from_remote_media_description(call, sal_call_get_remote_media_description(op));
|
||||
linphone_call_start_media_streams_for_ice_gathering(call);
|
||||
if (linphone_core_gather_ice_candidates(call->core,call)<0) {
|
||||
/* Ice candidates gathering failed, proceed with the call anyway. */
|
||||
linphone_call_delete_ice_session(call);
|
||||
linphone_call_stop_media_streams_for_ice_gathering(call);
|
||||
}
|
||||
linphone_call_prepare_ice(call,TRUE);
|
||||
break;
|
||||
case LinphonePolicyUseStun:
|
||||
call->ping_time=linphone_core_run_stun_tests(call->core,call);
|
||||
|
|
@ -780,7 +761,6 @@ void linphone_call_set_state(LinphoneCall *call, LinphoneCallState cstate, const
|
|||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ms_message("Call %p: moving from state %s to %s",call,linphone_call_state_to_string(call->state),
|
||||
linphone_call_state_to_string(cstate));
|
||||
|
||||
|
|
@ -789,6 +769,7 @@ void linphone_call_set_state(LinphoneCall *call, LinphoneCallState cstate, const
|
|||
Indeed it does not change the state of the call (still paused or running)*/
|
||||
call->state=cstate;
|
||||
}
|
||||
|
||||
if (cstate==LinphoneCallEnd || cstate==LinphoneCallError){
|
||||
switch(call->non_op_error.reason){
|
||||
case SalReasonDeclined:
|
||||
|
|
@ -807,8 +788,18 @@ void linphone_call_set_state(LinphoneCall *call, LinphoneCallState cstate, const
|
|||
call->media_start_time=time(NULL);
|
||||
}
|
||||
|
||||
if (cstate == LinphoneCallStreamsRunning) {
|
||||
linphone_reporting_update_ip(call);
|
||||
}
|
||||
|
||||
if (lc->vtable.call_state_changed)
|
||||
lc->vtable.call_state_changed(lc,call,cstate,message);
|
||||
|
||||
if (cstate==LinphoneCallEnd){
|
||||
if (call->log->status == LinphoneCallSuccess)
|
||||
linphone_reporting_publish(call);
|
||||
}
|
||||
|
||||
if (cstate==LinphoneCallReleased){
|
||||
if (call->op!=NULL) {
|
||||
/*transfer the last error so that it can be obtained even in Released state*/
|
||||
|
|
@ -923,6 +914,16 @@ const LinphoneCallParams * linphone_call_get_current_params(LinphoneCall *call){
|
|||
}
|
||||
#endif
|
||||
|
||||
if (linphone_call_are_all_streams_encrypted(call)) {
|
||||
if (linphone_call_get_authentication_token(call)) {
|
||||
call->current_params.media_encryption=LinphoneMediaEncryptionZRTP;
|
||||
} else {
|
||||
call->current_params.media_encryption=LinphoneMediaEncryptionSRTP;
|
||||
}
|
||||
} else {
|
||||
call->current_params.media_encryption=LinphoneMediaEncryptionNone;
|
||||
}
|
||||
|
||||
return &call->current_params;
|
||||
}
|
||||
|
||||
|
|
@ -1303,7 +1304,7 @@ const char *linphone_call_params_get_session_name(const LinphoneCallParams *cp){
|
|||
/**
|
||||
* Set the session name of the media session (ie in SDP). Subject from the SIP message (which is different) can be set using linphone_call_params_set_custom_header().
|
||||
* @param cp the call parameters.
|
||||
* @param name the session name
|
||||
* @param name the session name
|
||||
**/
|
||||
void linphone_call_params_set_session_name(LinphoneCallParams *cp, const char *name){
|
||||
if (cp->session_name){
|
||||
|
|
@ -1403,7 +1404,10 @@ static void video_stream_event_cb(void *user_pointer, const MSFilter *f, const u
|
|||
switch (event_id) {
|
||||
case MS_VIDEO_DECODER_DECODING_ERRORS:
|
||||
ms_warning("Case is MS_VIDEO_DECODER_DECODING_ERRORS");
|
||||
linphone_call_send_vfu_request(call);
|
||||
if (call->videostream && (video_stream_is_decoding_error_to_be_reported(call->videostream, 5000) == TRUE)) {
|
||||
video_stream_decoding_error_reported(call->videostream);
|
||||
linphone_call_send_vfu_request(call);
|
||||
}
|
||||
break;
|
||||
case MS_VIDEO_DECODER_FIRST_IMAGE_DECODED:
|
||||
ms_message("First video frame decoded successfully");
|
||||
|
|
@ -1431,6 +1435,60 @@ static void port_config_set_random_choosed(LinphoneCall *call, int stream_index,
|
|||
call->media_ports[stream_index].rtcp_port=rtp_session_get_local_rtcp_port(session);
|
||||
}
|
||||
|
||||
static void _linphone_call_prepare_ice_for_stream(LinphoneCall *call, int stream_index, bool_t create_checklist){
|
||||
MediaStream *ms=stream_index == 0 ? (MediaStream*)call->audiostream : (MediaStream*)call->videostream;
|
||||
if ((linphone_core_get_firewall_policy(call->core) == LinphonePolicyUseIce) && (call->ice_session != NULL)){
|
||||
IceCheckList *cl;
|
||||
rtp_session_set_pktinfo(ms->sessions.rtp_session, TRUE);
|
||||
rtp_session_set_symmetric_rtp(ms->sessions.rtp_session, FALSE);
|
||||
cl=ice_session_check_list(call->ice_session, stream_index);
|
||||
if (cl == NULL && create_checklist) {
|
||||
cl=ice_check_list_new();
|
||||
ice_session_add_check_list(call->ice_session, cl);
|
||||
ms_message("Created new ICE check list for stream [%i]",stream_index);
|
||||
}
|
||||
if (cl){
|
||||
ms->ice_check_list = cl;
|
||||
ice_check_list_set_rtp_session(ms->ice_check_list, ms->sessions.rtp_session);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int linphone_call_prepare_ice(LinphoneCall *call, bool_t incoming_offer){
|
||||
SalMediaDescription *remote = NULL;
|
||||
bool_t has_video=FALSE;
|
||||
|
||||
if ((linphone_core_get_firewall_policy(call->core) == LinphonePolicyUseIce) && (call->ice_session != NULL)){
|
||||
if (incoming_offer){
|
||||
remote=sal_call_get_remote_media_description(call->op);
|
||||
has_video=linphone_core_media_description_contains_video_stream(remote);
|
||||
}else has_video=call->params.has_video;
|
||||
|
||||
_linphone_call_prepare_ice_for_stream(call,0,TRUE);
|
||||
if (has_video) _linphone_call_prepare_ice_for_stream(call,1,TRUE);
|
||||
/*start ICE gathering*/
|
||||
if (incoming_offer)
|
||||
linphone_core_update_ice_from_remote_media_description(call,remote); /*this may delete the ice session*/
|
||||
if (call->ice_session && !ice_session_candidates_gathered(call->ice_session)){
|
||||
if (call->audiostream->ms.state==MSStreamInitialized)
|
||||
audio_stream_prepare_sound(call->audiostream, NULL, NULL);
|
||||
#ifdef VIDEO_ENABLED
|
||||
if (has_video && call->videostream && call->videostream->ms.state==MSStreamInitialized) {
|
||||
video_stream_prepare_video(call->videostream);
|
||||
}
|
||||
#endif
|
||||
if (linphone_core_gather_ice_candidates(call->core,call)<0) {
|
||||
/* Ice candidates gathering failed, proceed with the call anyway. */
|
||||
linphone_call_delete_ice_session(call);
|
||||
linphone_call_stop_media_streams_for_ice_gathering(call);
|
||||
return -1;
|
||||
}
|
||||
return 1;/*gathering in progress, wait*/
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void linphone_call_init_audio_stream(LinphoneCall *call){
|
||||
LinphoneCore *lc=call->core;
|
||||
AudioStream *audiostream;
|
||||
|
|
@ -1481,18 +1539,11 @@ void linphone_call_init_audio_stream(LinphoneCall *call){
|
|||
RtpTransport *artcp=lc->rtptf->audio_rtcp_func(lc->rtptf->audio_rtcp_func_data, call->media_ports[0].rtcp_port);
|
||||
rtp_session_set_transports(audiostream->ms.sessions.rtp_session,artp,artcp);
|
||||
}
|
||||
if ((linphone_core_get_firewall_policy(lc) == LinphonePolicyUseIce) && (call->ice_session != NULL)){
|
||||
rtp_session_set_pktinfo(audiostream->ms.sessions.rtp_session, TRUE);
|
||||
rtp_session_set_symmetric_rtp(audiostream->ms.sessions.rtp_session, FALSE);
|
||||
if (ice_session_check_list(call->ice_session, 0) == NULL) {
|
||||
ice_session_add_check_list(call->ice_session, ice_check_list_new());
|
||||
}
|
||||
audiostream->ms.ice_check_list = ice_session_check_list(call->ice_session, 0);
|
||||
ice_check_list_set_rtp_session(audiostream->ms.ice_check_list, audiostream->ms.sessions.rtp_session);
|
||||
}
|
||||
|
||||
call->audiostream_app_evq = ortp_ev_queue_new();
|
||||
rtp_session_register_event_queue(audiostream->ms.sessions.rtp_session,call->audiostream_app_evq);
|
||||
|
||||
_linphone_call_prepare_ice_for_stream(call,0,FALSE);
|
||||
}
|
||||
|
||||
void linphone_call_init_video_stream(LinphoneCall *call){
|
||||
|
|
@ -1503,7 +1554,7 @@ void linphone_call_init_video_stream(LinphoneCall *call){
|
|||
int video_recv_buf_size=lp_config_get_int(lc->config,"video","recv_buf_size",0);
|
||||
int dscp=linphone_core_get_video_dscp(lc);
|
||||
const char *display_filter=linphone_core_get_video_display_filter(lc);
|
||||
|
||||
|
||||
if (call->sessions[1].rtp_session==NULL){
|
||||
call->videostream=video_stream_new(call->media_ports[1].rtp_port,call->media_ports[1].rtcp_port, call->af==AF_INET6);
|
||||
}else{
|
||||
|
|
@ -1527,23 +1578,11 @@ void linphone_call_init_video_stream(LinphoneCall *call){
|
|||
}
|
||||
call->videostream_app_evq = ortp_ev_queue_new();
|
||||
rtp_session_register_event_queue(call->videostream->ms.sessions.rtp_session,call->videostream_app_evq);
|
||||
_linphone_call_prepare_ice_for_stream(call,1,FALSE);
|
||||
#ifdef TEST_EXT_RENDERER
|
||||
video_stream_set_render_callback(call->videostream,rendercb,NULL);
|
||||
#endif
|
||||
}
|
||||
/*eventually re-create the ICE check list that may have been destroyed if the stream wasn't used recently*/
|
||||
if ((linphone_core_get_firewall_policy(lc) == LinphonePolicyUseIce) && (call->ice_session != NULL)){
|
||||
rtp_session_set_pktinfo(call->videostream->ms.sessions.rtp_session, TRUE);
|
||||
rtp_session_set_symmetric_rtp(call->videostream->ms.sessions.rtp_session, FALSE);
|
||||
if (ice_session_check_list(call->ice_session, 1) == NULL) {
|
||||
ice_session_add_check_list(call->ice_session, ice_check_list_new());
|
||||
}
|
||||
call->videostream->ms.ice_check_list = ice_session_check_list(call->ice_session, 1);
|
||||
ice_check_list_set_rtp_session(call->videostream->ms.ice_check_list, call->videostream->ms.sessions.rtp_session);
|
||||
ms_message ("creating new ice video check list [%p] for session [%p]",call->videostream->ms.ice_check_list,call->videostream->ms.sessions.rtp_session);
|
||||
}
|
||||
|
||||
|
||||
#else
|
||||
call->videostream=NULL;
|
||||
#endif
|
||||
|
|
@ -1657,17 +1696,65 @@ static void post_configure_audio_streams(LinphoneCall*call){
|
|||
linphone_call_start_recording(call);
|
||||
}
|
||||
|
||||
static RtpProfile *make_profile(LinphoneCall *call, const SalMediaDescription *md, const SalStreamDescription *desc, int *used_pt){
|
||||
static int get_ideal_audio_bw(LinphoneCall *call, const SalMediaDescription *md, const SalStreamDescription *desc){
|
||||
int remote_bw=0;
|
||||
int upload_bw;
|
||||
int total_upload_bw=linphone_core_get_upload_bandwidth(call->core);
|
||||
const LinphoneCallParams *params=&call->params;
|
||||
bool_t will_use_video=linphone_core_media_description_contains_video_stream(md);
|
||||
bool_t forced=FALSE;
|
||||
|
||||
if (desc->bandwidth>0) remote_bw=desc->bandwidth;
|
||||
else if (md->bandwidth>0) {
|
||||
/*case where b=AS is given globally, not per stream*/
|
||||
remote_bw=md->bandwidth;
|
||||
}
|
||||
if (params->up_bw>0){
|
||||
forced=TRUE;
|
||||
upload_bw=params->up_bw;
|
||||
}else upload_bw=total_upload_bw;
|
||||
upload_bw=get_min_bandwidth(upload_bw,remote_bw);
|
||||
if (!will_use_video || forced) return upload_bw;
|
||||
|
||||
if (bandwidth_is_greater(upload_bw,512)){
|
||||
upload_bw=100;
|
||||
}else if (bandwidth_is_greater(upload_bw,256)){
|
||||
upload_bw=64;
|
||||
}else if (bandwidth_is_greater(upload_bw,128)){
|
||||
upload_bw=40;
|
||||
}else if (bandwidth_is_greater(upload_bw,0)){
|
||||
upload_bw=24;
|
||||
}
|
||||
return upload_bw;
|
||||
}
|
||||
|
||||
static int get_video_bw(LinphoneCall *call, const SalMediaDescription *md, const SalStreamDescription *desc){
|
||||
int remote_bw=0;
|
||||
int bw;
|
||||
if (desc->bandwidth>0) remote_bw=desc->bandwidth;
|
||||
else if (md->bandwidth>0) {
|
||||
/*case where b=AS is given globally, not per stream*/
|
||||
remote_bw=get_remaining_bandwidth_for_video(md->bandwidth,call->audio_bw);
|
||||
}
|
||||
bw=get_min_bandwidth(get_remaining_bandwidth_for_video(linphone_core_get_upload_bandwidth(call->core),call->audio_bw),remote_bw);
|
||||
return bw;
|
||||
}
|
||||
|
||||
static RtpProfile *make_profile(LinphoneCall *call, const SalMediaDescription *md, const SalStreamDescription *desc, int *used_pt){
|
||||
int bw=0;
|
||||
const MSList *elem;
|
||||
RtpProfile *prof=rtp_profile_new("Call profile");
|
||||
bool_t first=TRUE;
|
||||
int remote_bw=0;
|
||||
LinphoneCore *lc=call->core;
|
||||
int up_ptime=0;
|
||||
const LinphoneCallParams *params=&call->params;
|
||||
|
||||
*used_pt=-1;
|
||||
|
||||
if (desc->type==SalAudio)
|
||||
bw=get_ideal_audio_bw(call,md,desc);
|
||||
else if (desc->type==SalVideo)
|
||||
bw=get_video_bw(call,md,desc);
|
||||
|
||||
for(elem=desc->payloads;elem!=NULL;elem=elem->next){
|
||||
PayloadType *pt=(PayloadType*)elem->data;
|
||||
int number;
|
||||
|
|
@ -1676,8 +1763,11 @@ static RtpProfile *make_profile(LinphoneCall *call, const SalMediaDescription *m
|
|||
pt=payload_type_clone(pt);
|
||||
|
||||
if ((pt->flags & PAYLOAD_TYPE_FLAG_CAN_SEND) && first) {
|
||||
/*first codec in list is the selected one*/
|
||||
if (desc->type==SalAudio){
|
||||
linphone_core_update_allocated_audio_bandwidth_in_call(call,pt);
|
||||
/*this will update call->audio_bw*/
|
||||
linphone_core_update_allocated_audio_bandwidth_in_call(call,pt,bw);
|
||||
bw=call->audio_bw;
|
||||
if (params->up_ptime)
|
||||
up_ptime=params->up_ptime;
|
||||
else up_ptime=linphone_core_get_upload_ptime(lc);
|
||||
|
|
@ -1685,27 +1775,9 @@ static RtpProfile *make_profile(LinphoneCall *call, const SalMediaDescription *m
|
|||
*used_pt=payload_type_get_number(pt);
|
||||
first=FALSE;
|
||||
}
|
||||
if (desc->bandwidth>0) remote_bw=desc->bandwidth;
|
||||
else if (md->bandwidth>0) {
|
||||
/*case where b=AS is given globally, not per stream*/
|
||||
remote_bw=md->bandwidth;
|
||||
if (desc->type==SalVideo){
|
||||
remote_bw=get_video_bandwidth(remote_bw,call->audio_bw);
|
||||
}
|
||||
}
|
||||
|
||||
if (desc->type==SalAudio){
|
||||
int audio_bw=call->audio_bw;
|
||||
if (params->up_bw){
|
||||
if (params->up_bw< audio_bw)
|
||||
audio_bw=params->up_bw;
|
||||
}
|
||||
bw=get_min_bandwidth(audio_bw,remote_bw);
|
||||
}else bw=get_min_bandwidth(get_video_bandwidth(linphone_core_get_upload_bandwidth (lc),call->audio_bw),remote_bw);
|
||||
if (bw>0) pt->normal_bitrate=bw*1000;
|
||||
else if (desc->type==SalAudio){
|
||||
pt->normal_bitrate=-1;
|
||||
}
|
||||
if (pt->flags & PAYLOAD_TYPE_BITRATE_OVERRIDE){
|
||||
pt->normal_bitrate=get_min_bandwidth(pt->normal_bitrate,bw*1000);
|
||||
} else pt->normal_bitrate=bw*1000;
|
||||
if (desc->ptime>0){
|
||||
up_ptime=desc->ptime;
|
||||
}
|
||||
|
|
@ -1875,12 +1947,10 @@ static void linphone_call_start_audio_stream(LinphoneCall *call, const char *cna
|
|||
if (crypto_idx >= 0) {
|
||||
media_stream_set_srtp_recv_key(&call->audiostream->ms,stream->crypto[0].algo,stream->crypto[0].master_key);
|
||||
media_stream_set_srtp_send_key(&call->audiostream->ms,stream->crypto[0].algo,local_st_desc->crypto[crypto_idx].master_key);
|
||||
call->audiostream_encrypted=TRUE;
|
||||
} else {
|
||||
ms_warning("Failed to find local crypto algo with tag: %d", stream->crypto_local_tag);
|
||||
call->audiostream_encrypted=FALSE;
|
||||
}
|
||||
}else call->audiostream_encrypted=FALSE;
|
||||
}
|
||||
configure_rtp_session_for_rtcp_xr(lc, call, SalAudio);
|
||||
audio_stream_start_full(
|
||||
call->audiostream,
|
||||
|
|
@ -1925,7 +1995,7 @@ static void linphone_call_start_video_stream(LinphoneCall *call, const char *cna
|
|||
#ifdef VIDEO_ENABLED
|
||||
LinphoneCore *lc=call->core;
|
||||
int used_pt=-1;
|
||||
|
||||
|
||||
/* look for savp stream first */
|
||||
const SalStreamDescription *vstream=sal_media_description_find_stream(call->resultdesc,
|
||||
SalProtoRtpSavp,SalVideo);
|
||||
|
|
@ -1947,8 +2017,9 @@ static void linphone_call_start_video_stream(LinphoneCall *call, const char *cna
|
|||
const char *rtp_addr=vstream->rtp_addr[0]!='\0' ? vstream->rtp_addr : call->resultdesc->addr;
|
||||
const char *rtcp_addr=vstream->rtcp_addr[0]!='\0' ? vstream->rtcp_addr : call->resultdesc->addr;
|
||||
const SalStreamDescription *local_st_desc=sal_media_description_find_stream(call->localdesc,vstream->proto,SalVideo);
|
||||
|
||||
|
||||
call->video_profile=make_profile(call,call->resultdesc,vstream,&used_pt);
|
||||
|
||||
if (used_pt!=-1){
|
||||
VideoStreamDir dir=VideoStreamSendRecv;
|
||||
MSWebCam *cam=lc->video_conf.device;
|
||||
|
|
@ -1994,14 +2065,10 @@ static void linphone_call_start_video_stream(LinphoneCall *call, const char *cna
|
|||
if (!is_inactive){
|
||||
if (vstream->proto == SalProtoRtpSavp) {
|
||||
int crypto_idx = find_crypto_index_from_tag(local_st_desc->crypto, vstream->crypto_local_tag);
|
||||
|
||||
if (crypto_idx >= 0) {
|
||||
media_stream_set_srtp_recv_key(&call->videostream->ms,vstream->crypto[0].algo,vstream->crypto[0].master_key);
|
||||
media_stream_set_srtp_send_key(&call->videostream->ms,vstream->crypto[0].algo,local_st_desc->crypto[crypto_idx].master_key);
|
||||
call->videostream_encrypted=TRUE;
|
||||
}else call->videostream_encrypted=FALSE;
|
||||
}else{
|
||||
call->videostream_encrypted=FALSE;
|
||||
}
|
||||
}
|
||||
configure_rtp_session_for_rtcp_xr(lc, call, SalVideo);
|
||||
|
||||
|
|
@ -2062,13 +2129,19 @@ void linphone_call_start_media_streams(LinphoneCall *call, bool_t all_inputs_mut
|
|||
|
||||
if (call->params.media_encryption==LinphoneMediaEncryptionZRTP) {
|
||||
OrtpZrtpParams params;
|
||||
/*will be set later when zrtp is activated*/
|
||||
call->current_params.media_encryption=LinphoneMediaEncryptionNone;
|
||||
|
||||
memset(¶ms,0,sizeof(OrtpZrtpParams));
|
||||
/*call->current_params.media_encryption will be set later when zrtp is activated*/
|
||||
params.zid_file=lc->zrtp_secrets_cache;
|
||||
|
||||
params.uri= linphone_address_as_string_uri_only((call->dir==LinphoneCallIncoming) ? call->log->from : call->log->to);
|
||||
audio_stream_enable_zrtp(call->audiostream,¶ms);
|
||||
#if VIDEO_ENABLED
|
||||
if (media_stream_is_secured((MediaStream *)call->audiostream) && media_stream_get_state((MediaStream *)call->videostream) == MSStreamStarted) {
|
||||
/*audio stream is already encrypted and video stream is active*/
|
||||
memset(¶ms,0,sizeof(OrtpZrtpParams));
|
||||
video_stream_enable_zrtp(call->videostream,call->audiostream,¶ms);
|
||||
}
|
||||
#endif
|
||||
}else{
|
||||
call->current_params.media_encryption=linphone_call_are_all_streams_encrypted(call) ?
|
||||
LinphoneMediaEncryptionSRTP : LinphoneMediaEncryptionNone;
|
||||
|
|
@ -2084,19 +2157,10 @@ void linphone_call_start_media_streams(LinphoneCall *call, bool_t all_inputs_mut
|
|||
linphone_address_destroy(me);
|
||||
}
|
||||
|
||||
void linphone_call_start_media_streams_for_ice_gathering(LinphoneCall *call){
|
||||
audio_stream_prepare_sound(call->audiostream, NULL, NULL);
|
||||
#ifdef VIDEO_ENABLED
|
||||
if (call->videostream) {
|
||||
video_stream_prepare_video(call->videostream);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void linphone_call_stop_media_streams_for_ice_gathering(LinphoneCall *call){
|
||||
audio_stream_unprepare_sound(call->audiostream);
|
||||
if(call->audiostream && call->audiostream->ms.state==MSStreamPreparing) audio_stream_unprepare_sound(call->audiostream);
|
||||
#ifdef VIDEO_ENABLED
|
||||
if (call->videostream) {
|
||||
if (call->videostream && call->videostream->ms.state==MSStreamPreparing) {
|
||||
video_stream_unprepare_video(call->videostream);
|
||||
}
|
||||
#endif
|
||||
|
|
@ -2121,14 +2185,13 @@ void linphone_call_update_crypto_parameters(LinphoneCall *call, SalMediaDescript
|
|||
SalStreamDescription *old_stream;
|
||||
SalStreamDescription *new_stream;
|
||||
const SalStreamDescription *local_st_desc;
|
||||
|
||||
|
||||
local_st_desc = sal_media_description_find_stream(call->localdesc, SalProtoRtpSavp, SalAudio);
|
||||
old_stream = sal_media_description_find_stream(old_md, SalProtoRtpSavp, SalAudio);
|
||||
new_stream = sal_media_description_find_stream(new_md, SalProtoRtpSavp, SalAudio);
|
||||
if (call->audiostream && local_st_desc && old_stream && new_stream &&
|
||||
update_stream_crypto_params(call,local_st_desc,old_stream,new_stream,&call->audiostream->ms)){
|
||||
call->audiostream_encrypted = TRUE;
|
||||
}else call->audiostream_encrypted = FALSE;
|
||||
}
|
||||
|
||||
#ifdef VIDEO_ENABLED
|
||||
local_st_desc = sal_media_description_find_stream(call->localdesc, SalProtoRtpSavp, SalVideo);
|
||||
|
|
@ -2136,9 +2199,7 @@ void linphone_call_update_crypto_parameters(LinphoneCall *call, SalMediaDescript
|
|||
new_stream = sal_media_description_find_stream(new_md, SalProtoRtpSavp, SalVideo);
|
||||
if (call->videostream && local_st_desc && old_stream && new_stream &&
|
||||
update_stream_crypto_params(call,local_st_desc,old_stream,new_stream,&call->videostream->ms)){
|
||||
call->videostream_encrypted = TRUE;
|
||||
}
|
||||
call->videostream_encrypted = FALSE;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
@ -2183,6 +2244,7 @@ static void linphone_call_log_fill_stats(LinphoneCallLog *log, MediaStream *st){
|
|||
|
||||
void linphone_call_stop_audio_stream(LinphoneCall *call) {
|
||||
if (call->audiostream!=NULL) {
|
||||
linphone_reporting_update(call, LINPHONE_CALL_STATS_AUDIO);
|
||||
media_stream_reclaim_sessions(&call->audiostream->ms,&call->sessions[0]);
|
||||
rtp_session_unregister_event_queue(call->audiostream->ms.sessions.rtp_session,call->audiostream_app_evq);
|
||||
ortp_ev_queue_flush(call->audiostream_app_evq);
|
||||
|
|
@ -2211,6 +2273,7 @@ void linphone_call_stop_audio_stream(LinphoneCall *call) {
|
|||
void linphone_call_stop_video_stream(LinphoneCall *call) {
|
||||
#ifdef VIDEO_ENABLED
|
||||
if (call->videostream!=NULL){
|
||||
linphone_reporting_update(call, LINPHONE_CALL_STATS_VIDEO);
|
||||
media_stream_reclaim_sessions(&call->videostream->ms,&call->sessions[1]);
|
||||
rtp_session_unregister_event_queue(call->videostream->ms.sessions.rtp_session,call->videostream_app_evq);
|
||||
ortp_ev_queue_flush(call->videostream_app_evq);
|
||||
|
|
@ -2620,11 +2683,17 @@ static void handle_ice_events(LinphoneCall *call, OrtpEvent *ev){
|
|||
int ping_time;
|
||||
|
||||
if (evt == ORTP_EVENT_ICE_SESSION_PROCESSING_FINISHED) {
|
||||
LinphoneCallParams params;
|
||||
_linphone_call_params_copy(¶ms,&call->current_params);
|
||||
if (call->params.media_encryption == LinphoneMediaEncryptionZRTP) {
|
||||
/* preserve media encryption param because at that time ZRTP negociation may still be ongoing*/
|
||||
params.media_encryption=call->params.media_encryption;
|
||||
}
|
||||
switch (ice_session_state(call->ice_session)) {
|
||||
case IS_Completed:
|
||||
ice_session_select_candidates(call->ice_session);
|
||||
if (ice_session_role(call->ice_session) == IR_Controlling) {
|
||||
linphone_core_update_call(call->core, call, &call->current_params);
|
||||
linphone_core_update_call(call->core, call, ¶ms);
|
||||
}
|
||||
break;
|
||||
case IS_Failed:
|
||||
|
|
@ -2632,7 +2701,7 @@ static void handle_ice_events(LinphoneCall *call, OrtpEvent *ev){
|
|||
ice_session_select_candidates(call->ice_session);
|
||||
if (ice_session_role(call->ice_session) == IR_Controlling) {
|
||||
/* At least one ICE session has succeeded, so perform a call update. */
|
||||
linphone_core_update_call(call->core, call, &call->current_params);
|
||||
linphone_core_update_call(call->core, call, ¶ms);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
|
@ -2673,8 +2742,10 @@ static void handle_ice_events(LinphoneCall *call, OrtpEvent *ev){
|
|||
break;
|
||||
}
|
||||
} else if (evt == ORTP_EVENT_ICE_LOSING_PAIRS_COMPLETED) {
|
||||
linphone_core_start_accept_call_update(call->core, call);
|
||||
linphone_core_update_ice_state_in_call_stats(call);
|
||||
if (call->state==LinphoneCallUpdatedByRemote){
|
||||
linphone_core_start_accept_call_update(call->core, call);
|
||||
linphone_core_update_ice_state_in_call_stats(call);
|
||||
}
|
||||
} else if (evt == ORTP_EVENT_ICE_RESTART_NEEDED) {
|
||||
ice_session_restart(call->ice_session);
|
||||
ice_session_set_role(call->ice_session, IR_Controlling);
|
||||
|
|
@ -2682,8 +2753,92 @@ static void handle_ice_events(LinphoneCall *call, OrtpEvent *ev){
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/*do not change the prototype of this function, it is also used internally in linphone-daemon.*/
|
||||
void linphone_call_stats_fill(LinphoneCallStats *stats, MediaStream *ms, OrtpEvent *ev){
|
||||
OrtpEventType evt=ortp_event_get_type(ev);
|
||||
OrtpEventData *evd=ortp_event_get_data(ev);
|
||||
|
||||
if (evt == ORTP_EVENT_RTCP_PACKET_RECEIVED) {
|
||||
stats->round_trip_delay = rtp_session_get_round_trip_propagation(ms->sessions.rtp_session);
|
||||
if(stats->received_rtcp != NULL)
|
||||
freemsg(stats->received_rtcp);
|
||||
stats->received_rtcp = evd->packet;
|
||||
evd->packet = NULL;
|
||||
stats->updated = LINPHONE_CALL_STATS_RECEIVED_RTCP_UPDATE;
|
||||
update_local_stats(stats,ms);
|
||||
} else if (evt == ORTP_EVENT_RTCP_PACKET_EMITTED) {
|
||||
memcpy(&stats->jitter_stats, rtp_session_get_jitter_stats(ms->sessions.rtp_session), sizeof(jitter_stats_t));
|
||||
if (stats->sent_rtcp != NULL)
|
||||
freemsg(stats->sent_rtcp);
|
||||
stats->sent_rtcp = evd->packet;
|
||||
evd->packet = NULL;
|
||||
stats->updated = LINPHONE_CALL_STATS_SENT_RTCP_UPDATE;
|
||||
update_local_stats(stats,ms);
|
||||
}
|
||||
}
|
||||
|
||||
void linphone_call_notify_stats_updated(LinphoneCall *call, int stream_index){
|
||||
LinphoneCallStats *stats=&call->stats[stream_index];
|
||||
LinphoneCore *lc=call->core;
|
||||
if (stats->updated){
|
||||
linphone_reporting_call_stats_updated(call, stream_index);
|
||||
if (lc->vtable.call_stats_updated)
|
||||
lc->vtable.call_stats_updated(lc, call, stats);
|
||||
stats->updated = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void linphone_call_handle_stream_events(LinphoneCall *call, int stream_index){
|
||||
MediaStream *ms=stream_index==0 ? (MediaStream *)call->audiostream : (MediaStream *)call->videostream; /*assumption to remove*/
|
||||
OrtpEvQueue *evq;
|
||||
OrtpEvent *ev;
|
||||
|
||||
if (ms==NULL) return;
|
||||
/* Ensure there is no dangling ICE check list. */
|
||||
if (call->ice_session == NULL) ms->ice_check_list = NULL;
|
||||
|
||||
switch(ms->type){
|
||||
case AudioStreamType:
|
||||
audio_stream_iterate((AudioStream*)ms);
|
||||
break;
|
||||
case VideoStreamType:
|
||||
#ifdef VIDEO_ENABLED
|
||||
video_stream_iterate((VideoStream*)ms);
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
ms_error("linphone_call_handle_stream_events(): unsupported stream type.");
|
||||
return;
|
||||
break;
|
||||
}
|
||||
/*yes the event queue has to be taken at each iteration, because ice events may perform operations re-creating the streams*/
|
||||
while ((evq=stream_index==0 ? call->audiostream_app_evq : call->videostream_app_evq) && (NULL != (ev=ortp_ev_queue_get(evq)))){
|
||||
OrtpEventType evt=ortp_event_get_type(ev);
|
||||
OrtpEventData *evd=ortp_event_get_data(ev);
|
||||
|
||||
linphone_call_stats_fill(&call->stats[stream_index],ms,ev);
|
||||
linphone_call_notify_stats_updated(call,stream_index);
|
||||
|
||||
if (evt == ORTP_EVENT_ZRTP_ENCRYPTION_CHANGED){
|
||||
if (ms->type==AudioStreamType)
|
||||
linphone_call_audiostream_encryption_changed(call, evd->info.zrtp_stream_encrypted);
|
||||
else if (ms->type==VideoStreamType)
|
||||
propagate_encryption_changed(call);
|
||||
} else if (evt == ORTP_EVENT_ZRTP_SAS_READY) {
|
||||
if (ms->type==AudioStreamType)
|
||||
linphone_call_audiostream_auth_token_ready(call, evd->info.zrtp_sas.sas, evd->info.zrtp_sas.verified);
|
||||
} else if ((evt == ORTP_EVENT_ICE_SESSION_PROCESSING_FINISHED) || (evt == ORTP_EVENT_ICE_GATHERING_FINISHED)
|
||||
|| (evt == ORTP_EVENT_ICE_LOSING_PAIRS_COMPLETED) || (evt == ORTP_EVENT_ICE_RESTART_NEEDED)) {
|
||||
handle_ice_events(call, ev);
|
||||
} else if (evt==ORTP_EVENT_TELEPHONE_EVENT){
|
||||
linphone_core_dtmf_received(call->core,evd->info.telephone_event);
|
||||
}
|
||||
ortp_event_destroy(ev);
|
||||
}
|
||||
}
|
||||
|
||||
void linphone_call_background_tasks(LinphoneCall *call, bool_t one_second_elapsed){
|
||||
LinphoneCore* lc = call->core;
|
||||
int disconnect_timeout = linphone_core_get_nortp_timeout(call->core);
|
||||
bool_t disconnected=FALSE;
|
||||
|
||||
|
|
@ -2705,96 +2860,8 @@ void linphone_call_background_tasks(LinphoneCall *call, bool_t one_second_elapse
|
|||
linphone_upnp_call_process(call);
|
||||
#endif //BUILD_UPNP
|
||||
|
||||
#ifdef VIDEO_ENABLED
|
||||
if (call->videostream!=NULL) {
|
||||
OrtpEvent *ev;
|
||||
|
||||
/* Ensure there is no dangling ICE check list. */
|
||||
if (call->ice_session == NULL) call->videostream->ms.ice_check_list = NULL;
|
||||
|
||||
// Beware that the application queue should not depend on treatments fron the
|
||||
// mediastreamer queue.
|
||||
video_stream_iterate(call->videostream);
|
||||
|
||||
while (call->videostream_app_evq && (NULL != (ev=ortp_ev_queue_get(call->videostream_app_evq)))){
|
||||
OrtpEventType evt=ortp_event_get_type(ev);
|
||||
OrtpEventData *evd=ortp_event_get_data(ev);
|
||||
if (evt == ORTP_EVENT_ZRTP_ENCRYPTION_CHANGED){
|
||||
linphone_call_videostream_encryption_changed(call, evd->info.zrtp_stream_encrypted);
|
||||
} else if (evt == ORTP_EVENT_RTCP_PACKET_RECEIVED) {
|
||||
call->stats[LINPHONE_CALL_STATS_VIDEO].round_trip_delay = rtp_session_get_round_trip_propagation(call->videostream->ms.sessions.rtp_session);
|
||||
if(call->stats[LINPHONE_CALL_STATS_VIDEO].received_rtcp != NULL)
|
||||
freemsg(call->stats[LINPHONE_CALL_STATS_VIDEO].received_rtcp);
|
||||
call->stats[LINPHONE_CALL_STATS_VIDEO].received_rtcp = evd->packet;
|
||||
evd->packet = NULL;
|
||||
call->stats[LINPHONE_CALL_STATS_VIDEO].updated = LINPHONE_CALL_STATS_RECEIVED_RTCP_UPDATE;
|
||||
update_local_stats(&call->stats[LINPHONE_CALL_STATS_VIDEO],(MediaStream*)call->videostream);
|
||||
if (lc->vtable.call_stats_updated)
|
||||
lc->vtable.call_stats_updated(lc, call, &call->stats[LINPHONE_CALL_STATS_VIDEO]);
|
||||
} else if (evt == ORTP_EVENT_RTCP_PACKET_EMITTED) {
|
||||
memcpy(&call->stats[LINPHONE_CALL_STATS_VIDEO].jitter_stats, rtp_session_get_jitter_stats(call->videostream->ms.sessions.rtp_session), sizeof(jitter_stats_t));
|
||||
if(call->stats[LINPHONE_CALL_STATS_VIDEO].sent_rtcp != NULL)
|
||||
freemsg(call->stats[LINPHONE_CALL_STATS_VIDEO].sent_rtcp);
|
||||
call->stats[LINPHONE_CALL_STATS_VIDEO].sent_rtcp = evd->packet;
|
||||
evd->packet = NULL;
|
||||
call->stats[LINPHONE_CALL_STATS_VIDEO].updated = LINPHONE_CALL_STATS_SENT_RTCP_UPDATE;
|
||||
update_local_stats(&call->stats[LINPHONE_CALL_STATS_VIDEO],(MediaStream*)call->videostream);
|
||||
if (lc->vtable.call_stats_updated)
|
||||
lc->vtable.call_stats_updated(lc, call, &call->stats[LINPHONE_CALL_STATS_VIDEO]);
|
||||
} else if ((evt == ORTP_EVENT_ICE_SESSION_PROCESSING_FINISHED) || (evt == ORTP_EVENT_ICE_GATHERING_FINISHED)
|
||||
|| (evt == ORTP_EVENT_ICE_LOSING_PAIRS_COMPLETED) || (evt == ORTP_EVENT_ICE_RESTART_NEEDED)) {
|
||||
handle_ice_events(call, ev);
|
||||
}
|
||||
ortp_event_destroy(ev);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (call->audiostream!=NULL) {
|
||||
OrtpEvent *ev;
|
||||
|
||||
/* Ensure there is no dangling ICE check list. */
|
||||
if (call->ice_session == NULL) call->audiostream->ms.ice_check_list = NULL;
|
||||
|
||||
// Beware that the application queue should not depend on treatments fron the
|
||||
// mediastreamer queue.
|
||||
audio_stream_iterate(call->audiostream);
|
||||
|
||||
while (call->audiostream_app_evq && (NULL != (ev=ortp_ev_queue_get(call->audiostream_app_evq)))){
|
||||
OrtpEventType evt=ortp_event_get_type(ev);
|
||||
OrtpEventData *evd=ortp_event_get_data(ev);
|
||||
if (evt == ORTP_EVENT_ZRTP_ENCRYPTION_CHANGED){
|
||||
linphone_call_audiostream_encryption_changed(call, evd->info.zrtp_stream_encrypted);
|
||||
} else if (evt == ORTP_EVENT_ZRTP_SAS_READY) {
|
||||
linphone_call_audiostream_auth_token_ready(call, evd->info.zrtp_sas.sas, evd->info.zrtp_sas.verified);
|
||||
} else if (evt == ORTP_EVENT_RTCP_PACKET_RECEIVED) {
|
||||
call->stats[LINPHONE_CALL_STATS_AUDIO].round_trip_delay = rtp_session_get_round_trip_propagation(call->audiostream->ms.sessions.rtp_session);
|
||||
if(call->stats[LINPHONE_CALL_STATS_AUDIO].received_rtcp != NULL)
|
||||
freemsg(call->stats[LINPHONE_CALL_STATS_AUDIO].received_rtcp);
|
||||
call->stats[LINPHONE_CALL_STATS_AUDIO].received_rtcp = evd->packet;
|
||||
evd->packet = NULL;
|
||||
call->stats[LINPHONE_CALL_STATS_AUDIO].updated = LINPHONE_CALL_STATS_RECEIVED_RTCP_UPDATE;
|
||||
update_local_stats(&call->stats[LINPHONE_CALL_STATS_AUDIO],(MediaStream*)call->audiostream);
|
||||
if (lc->vtable.call_stats_updated)
|
||||
lc->vtable.call_stats_updated(lc, call, &call->stats[LINPHONE_CALL_STATS_AUDIO]);
|
||||
} else if (evt == ORTP_EVENT_RTCP_PACKET_EMITTED) {
|
||||
memcpy(&call->stats[LINPHONE_CALL_STATS_AUDIO].jitter_stats, rtp_session_get_jitter_stats(call->audiostream->ms.sessions.rtp_session), sizeof(jitter_stats_t));
|
||||
if(call->stats[LINPHONE_CALL_STATS_AUDIO].sent_rtcp != NULL)
|
||||
freemsg(call->stats[LINPHONE_CALL_STATS_AUDIO].sent_rtcp);
|
||||
call->stats[LINPHONE_CALL_STATS_AUDIO].sent_rtcp = evd->packet;
|
||||
evd->packet = NULL;
|
||||
call->stats[LINPHONE_CALL_STATS_AUDIO].updated = LINPHONE_CALL_STATS_SENT_RTCP_UPDATE;
|
||||
update_local_stats(&call->stats[LINPHONE_CALL_STATS_AUDIO],(MediaStream*)call->audiostream);
|
||||
if (lc->vtable.call_stats_updated)
|
||||
lc->vtable.call_stats_updated(lc, call, &call->stats[LINPHONE_CALL_STATS_AUDIO]);
|
||||
} else if ((evt == ORTP_EVENT_ICE_SESSION_PROCESSING_FINISHED) || (evt == ORTP_EVENT_ICE_GATHERING_FINISHED)
|
||||
|| (evt == ORTP_EVENT_ICE_LOSING_PAIRS_COMPLETED) || (evt == ORTP_EVENT_ICE_RESTART_NEEDED)) {
|
||||
handle_ice_events(call, ev);
|
||||
} else if (evt==ORTP_EVENT_TELEPHONE_EVENT){
|
||||
linphone_core_dtmf_received(lc,evd->info.telephone_event);
|
||||
}
|
||||
ortp_event_destroy(ev);
|
||||
}
|
||||
}
|
||||
linphone_call_handle_stream_events(call,0);
|
||||
linphone_call_handle_stream_events(call,1);
|
||||
if (call->state==LinphoneCallStreamsRunning && one_second_elapsed && call->audiostream!=NULL && disconnect_timeout>0 )
|
||||
disconnected=!audio_stream_alive(call->audiostream,disconnect_timeout);
|
||||
if (disconnected)
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
#include "sipsetup.h"
|
||||
#include "lpconfig.h"
|
||||
#include "private.h"
|
||||
#include "quality_reporting.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <ortp/telephonyevents.h>
|
||||
|
|
@ -127,6 +128,9 @@ LinphoneCallLog * linphone_call_log_new(LinphoneCall *call, LinphoneAddress *fro
|
|||
cl->to=to;
|
||||
cl->status=LinphoneCallAborted; /*default status*/
|
||||
cl->quality=-1;
|
||||
|
||||
cl->reports[LINPHONE_CALL_STATS_AUDIO]=linphone_reporting_new();
|
||||
cl->reports[LINPHONE_CALL_STATS_VIDEO]=linphone_reporting_new();
|
||||
return cl;
|
||||
}
|
||||
|
||||
|
|
@ -390,6 +394,9 @@ void linphone_call_log_destroy(LinphoneCallLog *cl){
|
|||
if (cl->to!=NULL) linphone_address_destroy(cl->to);
|
||||
if (cl->refkey!=NULL) ms_free(cl->refkey);
|
||||
if (cl->call_id) ms_free(cl->call_id);
|
||||
if (cl->reports[LINPHONE_CALL_STATS_AUDIO]!=NULL) linphone_reporting_destroy(cl->reports[LINPHONE_CALL_STATS_AUDIO]);
|
||||
if (cl->reports[LINPHONE_CALL_STATS_VIDEO]!=NULL) linphone_reporting_destroy(cl->reports[LINPHONE_CALL_STATS_VIDEO]);
|
||||
|
||||
ms_free(cl);
|
||||
}
|
||||
|
||||
|
|
@ -607,7 +614,7 @@ static void sound_config_read(LinphoneCore *lc)
|
|||
|
||||
linphone_core_set_play_file(lc,lp_config_get_string(lc->config,"sound","hold_music",PACKAGE_SOUND_DIR "/" HOLD_MUSIC));
|
||||
lc->sound_conf.latency=0;
|
||||
#ifndef __ios
|
||||
#ifndef __ios
|
||||
tmp=TRUE;
|
||||
#else
|
||||
tmp=FALSE; /* on iOS we have builtin echo cancellation.*/
|
||||
|
|
@ -626,7 +633,7 @@ static void sound_config_read(LinphoneCore *lc)
|
|||
|
||||
/*just parse requested stream feature once at start to print out eventual errors*/
|
||||
linphone_core_get_audio_features(lc);
|
||||
|
||||
|
||||
_linphone_core_set_tone(lc,LinphoneReasonBusy,LinphoneToneBusy,NULL);
|
||||
}
|
||||
|
||||
|
|
@ -640,7 +647,7 @@ static void certificates_config_read(LinphoneCore *lc)
|
|||
#endif
|
||||
linphone_core_set_root_ca(lc,rootca);
|
||||
linphone_core_verify_server_certificates(lc,lp_config_get_int(lc->config,"sip","verify_server_certs",TRUE));
|
||||
linphone_core_verify_server_cn(lc,lp_config_get_int(lc->config,"sip","verify_server_cn",TRUE));
|
||||
linphone_core_verify_server_cn(lc,lp_config_get_int(lc->config,"sip","verify_server_cn",TRUE));
|
||||
}
|
||||
|
||||
static void sip_config_read(LinphoneCore *lc)
|
||||
|
|
@ -655,6 +662,7 @@ static void sip_config_read(LinphoneCore *lc)
|
|||
sal_use_session_timers(lc->sal,200);
|
||||
}
|
||||
|
||||
sal_use_no_initial_route(lc->sal,lp_config_get_int(lc->config,"sip","use_no_initial_route",0));
|
||||
sal_use_rport(lc->sal,lp_config_get_int(lc->config,"sip","use_rport",1));
|
||||
|
||||
ipv6=lp_config_get_int(lc->config,"sip","use_ipv6",-1);
|
||||
|
|
@ -663,17 +671,17 @@ static void sip_config_read(LinphoneCore *lc)
|
|||
}
|
||||
linphone_core_enable_ipv6(lc,ipv6);
|
||||
memset(&tr,0,sizeof(tr));
|
||||
|
||||
|
||||
tr.udp_port=lp_config_get_int(lc->config,"sip","sip_port",5060);
|
||||
tr.tcp_port=lp_config_get_int(lc->config,"sip","sip_tcp_port",5060);
|
||||
/*we are not listening inbound connection for tls, port has no meaning*/
|
||||
tr.tls_port=lp_config_get_int(lc->config,"sip","sip_tls_port",LC_SIP_TRANSPORT_RANDOM);
|
||||
|
||||
|
||||
certificates_config_read(lc);
|
||||
/*setting the dscp must be done before starting the transports, otherwise it is not taken into effect*/
|
||||
sal_set_dscp(lc->sal,linphone_core_get_sip_dscp(lc));
|
||||
/*start listening on ports*/
|
||||
linphone_core_set_sip_transports(lc,&tr);
|
||||
linphone_core_set_sip_transports(lc,&tr);
|
||||
|
||||
tmpstr=lp_config_get_string(lc->config,"sip","contact",NULL);
|
||||
if (tmpstr==NULL || linphone_core_set_primary_contact(lc,tmpstr)==-1) {
|
||||
|
|
@ -705,7 +713,7 @@ static void sip_config_read(LinphoneCore *lc)
|
|||
|
||||
tmp=lp_config_get_int(lc->config,"sip","in_call_timeout",0);
|
||||
linphone_core_set_in_call_timeout(lc,tmp);
|
||||
|
||||
|
||||
tmp=lp_config_get_int(lc->config,"sip","delayed_timeout",4);
|
||||
linphone_core_set_delayed_timeout(lc,tmp);
|
||||
|
||||
|
|
@ -839,7 +847,7 @@ static bool_t get_codec(LinphoneCore *lc, const char* type, int index, PayloadTy
|
|||
if (pt && enabled ) pt->flags|=PAYLOAD_TYPE_ENABLED;
|
||||
//ms_message("Found codec %s/%i",pt->mime_type,pt->clock_rate);
|
||||
if (pt==NULL) ms_warning("Ignoring codec config %s/%i with fmtp=%s because unsupported",
|
||||
mime,rate,fmtp ? fmtp : "");
|
||||
mime,rate,fmtp ? fmtp : "");
|
||||
*ret=pt;
|
||||
return TRUE;
|
||||
}
|
||||
|
|
@ -897,7 +905,7 @@ static MSList *add_missing_codecs(LinphoneCore *lc, SalStreamType mtype, MSList
|
|||
if (mtype==SalVideo && pt->type!=PAYLOAD_VIDEO)
|
||||
pt=NULL;
|
||||
else if (mtype==SalAudio && (pt->type!=PAYLOAD_AUDIO_PACKETIZED
|
||||
&& pt->type!=PAYLOAD_AUDIO_CONTINUOUS)){
|
||||
&& pt->type!=PAYLOAD_AUDIO_CONTINUOUS)){
|
||||
pt=NULL;
|
||||
}
|
||||
if (pt && ms_filter_codec_supported(pt->mime_type)){
|
||||
|
|
@ -907,7 +915,7 @@ static MSList *add_missing_codecs(LinphoneCore *lc, SalStreamType mtype, MSList
|
|||
payload_type_set_flag(pt,PAYLOAD_TYPE_ENABLED);
|
||||
}
|
||||
ms_message("Adding new codec %s/%i with fmtp %s",
|
||||
pt->mime_type,pt->clock_rate,pt->recv_fmtp ? pt->recv_fmtp : "");
|
||||
pt->mime_type,pt->clock_rate,pt->recv_fmtp ? pt->recv_fmtp : "");
|
||||
l=ms_list_insert_sorted(l,pt,(int (*)(const void *, const void *))codec_compare);
|
||||
}
|
||||
}
|
||||
|
|
@ -977,8 +985,8 @@ static void video_config_read(LinphoneCore *lc){
|
|||
int capture, display, self_view;
|
||||
int automatic_video=1;
|
||||
#endif
|
||||
const char *str;
|
||||
#ifdef VIDEO_ENABLED
|
||||
const char *str;
|
||||
#ifdef VIDEO_ENABLED
|
||||
LinphoneVideoPolicy vpol;
|
||||
memset(&vpol, 0, sizeof(LinphoneVideoPolicy));
|
||||
#endif
|
||||
|
|
@ -1041,7 +1049,7 @@ bool_t linphone_core_tunnel_available(void){
|
|||
|
||||
/**
|
||||
* Enable adaptive rate control.
|
||||
*
|
||||
*
|
||||
* @ingroup media_parameters
|
||||
*
|
||||
* Adaptive rate control consists in using RTCP feedback provided information to dynamically
|
||||
|
|
@ -1055,7 +1063,7 @@ void linphone_core_enable_adaptive_rate_control(LinphoneCore *lc, bool_t enabled
|
|||
|
||||
/**
|
||||
* Returns whether adaptive rate control is enabled.
|
||||
*
|
||||
*
|
||||
* @ingroup media_parameters
|
||||
*
|
||||
* See linphone_core_enable_adaptive_rate_control().
|
||||
|
|
@ -1075,7 +1083,7 @@ bool_t linphone_core_rtcp_enabled(const LinphoneCore *lc){
|
|||
* calls (within SDP messages) so that the remote end can have
|
||||
* sufficient knowledge to properly configure its audio & video
|
||||
* codec output bitrate to not overflow available bandwidth.
|
||||
*
|
||||
*
|
||||
* @ingroup media_parameters
|
||||
*
|
||||
* @param lc the LinphoneCore object
|
||||
|
|
@ -1161,7 +1169,7 @@ void linphone_core_set_upload_ptime(LinphoneCore *lc, int ptime){
|
|||
* Set audio packetization time linphone will send (in absence of requirement from peer)
|
||||
* A value of 0 stands for the current codec default packetization time.
|
||||
*
|
||||
*
|
||||
*
|
||||
* @ingroup media_parameters
|
||||
**/
|
||||
int linphone_core_get_upload_ptime(LinphoneCore *lc){
|
||||
|
|
@ -1182,14 +1190,7 @@ const char * linphone_core_get_version(void){
|
|||
|
||||
static void linphone_core_assign_payload_type(LinphoneCore *lc, PayloadType *const_pt, int number, const char *recv_fmtp){
|
||||
PayloadType *pt;
|
||||
|
||||
#ifdef ANDROID
|
||||
if (const_pt->channels==2){
|
||||
ms_message("Stereo %s codec not supported on this platform.",const_pt->mime_type);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
pt=payload_type_clone(const_pt);
|
||||
if (number==-1){
|
||||
/*look for a free number */
|
||||
|
|
@ -1253,10 +1254,10 @@ void linphone_core_set_state(LinphoneCore *lc, LinphoneGlobalState gstate, const
|
|||
static void misc_config_read(LinphoneCore *lc) {
|
||||
LpConfig *config=lc->config;
|
||||
const char *uuid;
|
||||
|
||||
|
||||
lc->max_call_logs=lp_config_get_int(config,"misc","history_max_size",15);
|
||||
lc->max_calls=lp_config_get_int(config,"misc","max_calls",NB_MAX_CALLS);
|
||||
|
||||
|
||||
uuid=lp_config_get_string(config,"misc","uuid",NULL);
|
||||
if (!uuid){
|
||||
char tmp[64];
|
||||
|
|
@ -1292,12 +1293,12 @@ static void linphone_core_start(LinphoneCore * lc) {
|
|||
void linphone_configuring_terminated(LinphoneCore *lc, LinphoneConfiguringState state, const char *message) {
|
||||
if (lc->vtable.configuring_status)
|
||||
lc->vtable.configuring_status(lc, state, message);
|
||||
|
||||
|
||||
if (state == LinphoneConfiguringSuccessful) {
|
||||
if (linphone_core_is_provisioning_transient(lc) == TRUE)
|
||||
linphone_core_set_provisioning_uri(lc, NULL);
|
||||
}
|
||||
|
||||
|
||||
linphone_core_start(lc);
|
||||
}
|
||||
|
||||
|
|
@ -1306,7 +1307,7 @@ static void linphone_core_init(LinphoneCore * lc, const LinphoneCoreVTable *vtab
|
|||
const char *remote_provisioning_uri = NULL;
|
||||
ms_message("Initializing LinphoneCore %s", linphone_core_get_version());
|
||||
memset (lc, 0, sizeof (LinphoneCore));
|
||||
lc->config=config;
|
||||
lc->config=lp_config_ref(config);
|
||||
lc->data=userdata;
|
||||
lc->ringstream_autorelease=TRUE;
|
||||
|
||||
|
|
@ -1344,7 +1345,7 @@ static void linphone_core_init(LinphoneCore * lc, const LinphoneCoreVTable *vtab
|
|||
linphone_core_assign_payload_type(lc,&payload_type_mp4v,99,"profile-level-id=3");
|
||||
linphone_core_assign_payload_type(lc,&payload_type_h264,102,"profile-level-id=42801F");
|
||||
linphone_core_assign_payload_type(lc,&payload_type_vp8,103,NULL);
|
||||
|
||||
|
||||
linphone_core_assign_payload_type(lc,&payload_type_theora,97,NULL);
|
||||
linphone_core_assign_payload_type(lc,&payload_type_x_snow,-1,NULL);
|
||||
/* due to limited space in SDP, we have to disable this h264 line which is normally no more necessary */
|
||||
|
|
@ -1371,10 +1372,10 @@ static void linphone_core_init(LinphoneCore * lc, const LinphoneCoreVTable *vtab
|
|||
linphone_core_assign_payload_type(lc,&payload_type_g729,18,"annexb=no");
|
||||
linphone_core_assign_payload_type(lc,&payload_type_aaceld_22k,-1,"config=F8EE2000; constantDuration=512; indexDeltaLength=3; indexLength=3; mode=AAC-hbr; profile-level-id=76; sizeLength=13; streamType=5");
|
||||
linphone_core_assign_payload_type(lc,&payload_type_aaceld_44k,-1,"config=F8E82000; constantDuration=512; indexDeltaLength=3; indexLength=3; mode=AAC-hbr; profile-level-id=76; sizeLength=13; streamType=5");
|
||||
linphone_core_assign_payload_type(lc,&payload_type_opus,-1,"useinbandfec=1; usedtx=0; cbr=1");
|
||||
linphone_core_assign_payload_type(lc,&payload_type_opus,-1,"useinbandfec=1; stereo=0; sprop-stereo=0");
|
||||
linphone_core_assign_payload_type(lc,&payload_type_isac,-1,NULL);
|
||||
linphone_core_handle_static_payloads(lc);
|
||||
|
||||
|
||||
ms_init();
|
||||
/* create a mediastreamer2 event queue and set it as global */
|
||||
/* This allows to run event's callback in linphone_core_iterate() */
|
||||
|
|
@ -1386,15 +1387,15 @@ static void linphone_core_init(LinphoneCore * lc, const LinphoneCoreVTable *vtab
|
|||
sal_set_user_pointer(lc->sal,lc);
|
||||
sal_set_callbacks(lc->sal,&linphone_sal_callbacks);
|
||||
|
||||
lc->network_last_check = 0;
|
||||
lc->network_last_status = FALSE;
|
||||
|
||||
lc->network_last_check = 0;
|
||||
lc->network_last_status = FALSE;
|
||||
|
||||
lc->http_provider = belle_sip_stack_create_http_provider(sal_get_belle_sip_stack(lc->sal), "0.0.0.0");
|
||||
lc->http_verify_policy = belle_tls_verify_policy_new();
|
||||
belle_http_provider_set_tls_verify_policy(lc->http_provider,lc->http_verify_policy);
|
||||
|
||||
|
||||
certificates_config_read(lc);
|
||||
|
||||
|
||||
remote_provisioning_uri = linphone_core_get_provisioning_uri(lc);
|
||||
if (remote_provisioning_uri == NULL) {
|
||||
linphone_configuring_terminated(lc, LinphoneConfiguringSkipped, NULL);
|
||||
|
|
@ -1423,8 +1424,11 @@ static void linphone_core_init(LinphoneCore * lc, const LinphoneCoreVTable *vtab
|
|||
LinphoneCore *linphone_core_new(const LinphoneCoreVTable *vtable,
|
||||
const char *config_path, const char *factory_config_path, void * userdata)
|
||||
{
|
||||
LinphoneCore *lc;
|
||||
LpConfig *config = lp_config_new_with_factory(config_path, factory_config_path);
|
||||
return linphone_core_new_with_config(vtable, config, userdata);
|
||||
lc=linphone_core_new_with_config(vtable, config, userdata);
|
||||
lp_config_unref(config);
|
||||
return lc;
|
||||
}
|
||||
|
||||
LinphoneCore *linphone_core_new_with_config(const LinphoneCoreVTable *vtable, struct _LpConfig *config, void *userdata)
|
||||
|
|
@ -1493,7 +1497,7 @@ int linphone_core_set_primary_contact(LinphoneCore *lc, const char *contact)
|
|||
void linphone_core_get_local_ip(LinphoneCore *lc, int af, char *result){
|
||||
const char *ip;
|
||||
if (linphone_core_get_firewall_policy(lc)==LinphonePolicyUseNatAddress
|
||||
&& (ip=linphone_core_get_nat_address_resolved(lc))!=NULL){
|
||||
&& (ip=linphone_core_get_nat_address_resolved(lc))!=NULL){
|
||||
strncpy(result,ip,LINPHONE_IPADDR_SIZE);
|
||||
return;
|
||||
}
|
||||
|
|
@ -1518,7 +1522,9 @@ void linphone_core_get_local_ip(LinphoneCore *lc, int af, char *result){
|
|||
strncpy(result,"::1",LINPHONE_IPADDR_SIZE);
|
||||
return;
|
||||
}
|
||||
}else af=AF_INET;
|
||||
}
|
||||
/*in all other cases use IPv4*/
|
||||
af=AF_INET;
|
||||
}
|
||||
if (linphone_core_get_local_ip_for(af,NULL,result)==0)
|
||||
return;
|
||||
|
|
@ -1948,7 +1954,7 @@ static int apply_transports(LinphoneCore *lc){
|
|||
|
||||
/*first of all invalidate all current registrations so that we can register again with new transports*/
|
||||
__linphone_core_invalidate_registers(lc);
|
||||
|
||||
|
||||
if (lc->sip_conf.ipv6_enabled)
|
||||
anyaddr="::0";
|
||||
else
|
||||
|
|
@ -1958,7 +1964,6 @@ static int apply_transports(LinphoneCore *lc){
|
|||
if (tr->udp_port!=0){
|
||||
if (sal_listen_port (sal,anyaddr,tr->udp_port,SalTransportUDP,FALSE)!=0){
|
||||
transport_error(lc,"udp",tr->udp_port);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (tr->tcp_port!=0){
|
||||
|
|
@ -1966,9 +1971,11 @@ static int apply_transports(LinphoneCore *lc){
|
|||
transport_error(lc,"tcp",tr->tcp_port);
|
||||
}
|
||||
}
|
||||
if (tr->tls_port!=0){
|
||||
if (sal_listen_port (sal,anyaddr,tr->tls_port,SalTransportTLS,TRUE)!=0){
|
||||
transport_error(lc,"tls",tr->tls_port);
|
||||
if (linphone_core_sip_transport_supported(lc,LinphoneTransportTls)){
|
||||
if (tr->tls_port!=0){
|
||||
if (sal_listen_port (sal,anyaddr,tr->tls_port,SalTransportTLS,TRUE)!=0){
|
||||
transport_error(lc,"tls",tr->tls_port);
|
||||
}
|
||||
}
|
||||
}
|
||||
apply_user_agent(lc);
|
||||
|
|
@ -2092,23 +2099,32 @@ void linphone_core_enable_ipv6(LinphoneCore *lc, bool_t val){
|
|||
|
||||
|
||||
static void monitor_network_state(LinphoneCore *lc, time_t curtime){
|
||||
char result[LINPHONE_IPADDR_SIZE];
|
||||
bool_t new_status=lc->network_last_status;
|
||||
char newip[LINPHONE_IPADDR_SIZE];
|
||||
|
||||
/* only do the network up checking every five seconds */
|
||||
if (lc->network_last_check==0 || (curtime-lc->network_last_check)>=5){
|
||||
linphone_core_get_local_ip(lc,AF_UNSPEC,result);
|
||||
if (strcmp(result,"::1")!=0 && strcmp(result,"127.0.0.1")!=0){
|
||||
linphone_core_get_local_ip(lc,AF_UNSPEC,newip);
|
||||
if (strcmp(newip,"::1")!=0 && strcmp(newip,"127.0.0.1")!=0){
|
||||
new_status=TRUE;
|
||||
}else new_status=FALSE;
|
||||
lc->network_last_check=curtime;
|
||||
}else new_status=FALSE; /*no network*/
|
||||
|
||||
if (new_status==lc->network_last_status && new_status==TRUE && strcmp(newip,lc->localip)!=0){
|
||||
/*IP address change detected*/
|
||||
ms_message("IP address change detected.");
|
||||
set_network_reachable(lc,FALSE,curtime);
|
||||
lc->network_last_status=FALSE;
|
||||
}
|
||||
strncpy(lc->localip,newip,sizeof(lc->localip));
|
||||
|
||||
if (new_status!=lc->network_last_status) {
|
||||
if (new_status){
|
||||
ms_message("New local ip address is %s",result);
|
||||
ms_message("New local ip address is %s",lc->localip);
|
||||
}
|
||||
set_network_reachable(lc,new_status, curtime);
|
||||
lc->network_last_status=new_status;
|
||||
}
|
||||
lc->network_last_check=curtime;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2218,7 +2234,7 @@ void linphone_core_iterate(LinphoneCore *lc){
|
|||
int elapsed;
|
||||
bool_t one_second_elapsed=FALSE;
|
||||
const char *remote_provisioning_uri = NULL;
|
||||
|
||||
|
||||
if (linphone_core_get_global_state(lc) == LinphoneGlobalStartup) {
|
||||
if (sal_get_root_ca(lc->sal)) {
|
||||
belle_tls_verify_policy_t *tls_policy = belle_tls_verify_policy_new();
|
||||
|
|
@ -2229,7 +2245,7 @@ void linphone_core_iterate(LinphoneCore *lc){
|
|||
if (lc->vtable.display_status)
|
||||
lc->vtable.display_status(lc, _("Configuring"));
|
||||
linphone_core_set_state(lc, LinphoneGlobalConfiguring, "Configuring");
|
||||
|
||||
|
||||
remote_provisioning_uri = linphone_core_get_provisioning_uri(lc);
|
||||
if (remote_provisioning_uri) {
|
||||
int err = linphone_remote_provisioning_download_and_apply(lc, remote_provisioning_uri);
|
||||
|
|
@ -2252,7 +2268,7 @@ void linphone_core_iterate(LinphoneCore *lc){
|
|||
if (ecs==LinphoneEcCalibratorDone){
|
||||
int len=lp_config_get_int(lc->config,"sound","ec_tail_len",0);
|
||||
int margin=len/2;
|
||||
|
||||
|
||||
lp_config_set_int(lc->config, "sound", "ec_delay",MAX(lc->ecc->delay-margin,0));
|
||||
} else if (ecs == LinphoneEcCalibratorFailed) {
|
||||
lp_config_set_int(lc->config, "sound", "ec_delay", -1);/*use default value from soundcard*/
|
||||
|
|
@ -2272,7 +2288,7 @@ void linphone_core_iterate(LinphoneCore *lc){
|
|||
}
|
||||
|
||||
if (lc->ringstream && lc->ringstream_autorelease && lc->dmfs_playing_start_time!=0
|
||||
&& (curtime-lc->dmfs_playing_start_time)>5){
|
||||
&& (curtime-lc->dmfs_playing_start_time)>5){
|
||||
MSPlayerState state;
|
||||
bool_t stop=TRUE;
|
||||
if (lc->ringstream->source && ms_filter_call_method(lc->ringstream->source,MS_PLAYER_GET_STATE,&state)==0){
|
||||
|
|
@ -2365,7 +2381,7 @@ void linphone_core_iterate(LinphoneCore *lc){
|
|||
/**
|
||||
* Interpret a call destination as supplied by the user, and returns a fully qualified
|
||||
* LinphoneAddress.
|
||||
*
|
||||
*
|
||||
* @ingroup call_control
|
||||
*
|
||||
* A sip address should look like DisplayName <sip:username@domain:port> .
|
||||
|
|
@ -2384,7 +2400,7 @@ LinphoneAddress * linphone_core_interpret_url(LinphoneCore *lc, const char *url)
|
|||
LinphoneProxyConfig *proxy=lc->default_proxy;
|
||||
char *tmpurl;
|
||||
LinphoneAddress *uri;
|
||||
|
||||
|
||||
if (*url=='\0') return NULL;
|
||||
|
||||
if (is_enum(url,&enum_domain)){
|
||||
|
|
@ -2425,7 +2441,7 @@ LinphoneAddress * linphone_core_interpret_url(LinphoneCore *lc, const char *url)
|
|||
}
|
||||
linphone_address_set_display_name(uri,NULL);
|
||||
linphone_proxy_config_normalize_number(proxy,url,normalized_username,
|
||||
sizeof(normalized_username));
|
||||
sizeof(normalized_username));
|
||||
linphone_address_set_username(uri,normalized_username);
|
||||
return uri;
|
||||
}else return NULL;
|
||||
|
|
@ -2434,7 +2450,7 @@ LinphoneAddress * linphone_core_interpret_url(LinphoneCore *lc, const char *url)
|
|||
if (uri!=NULL){
|
||||
return uri;
|
||||
}
|
||||
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
@ -2472,7 +2488,7 @@ const char * linphone_core_get_route(LinphoneCore *lc){
|
|||
* Start a new call as a consequence of a transfer request received from a call.
|
||||
* This function is for advanced usage: the execution of transfers is automatically managed by the LinphoneCore. However if an application
|
||||
* wants to have control over the call parameters for the new call, it should call this function immediately during the LinphoneCallRefered notification.
|
||||
* @see LinphoneCoreVTable::call_state_changed
|
||||
* @see LinphoneCoreVTable::call_state_changed
|
||||
* @param lc the LinphoneCore
|
||||
* @param call a call that has just been notified about LinphoneCallRefered state event.
|
||||
* @param params the call parameters to be applied to the new call.
|
||||
|
|
@ -2481,13 +2497,13 @@ const char * linphone_core_get_route(LinphoneCore *lc){
|
|||
LinphoneCall * linphone_core_start_refered_call(LinphoneCore *lc, LinphoneCall *call, const LinphoneCallParams *params){
|
||||
LinphoneCallParams *cp=params ? linphone_call_params_copy(params) : linphone_core_create_default_call_parameters(lc);
|
||||
LinphoneCall *newcall;
|
||||
|
||||
|
||||
if (call->state!=LinphoneCallPaused){
|
||||
ms_message("Automatically pausing current call to accept transfer.");
|
||||
_linphone_core_pause_call(lc,call);
|
||||
call->was_automatically_paused=TRUE;
|
||||
}
|
||||
|
||||
|
||||
if (!params){
|
||||
cp->has_video = call->current_params.has_video; /*start the call to refer-target with video enabled if original call had video*/
|
||||
}
|
||||
|
|
@ -2527,7 +2543,7 @@ void linphone_core_notify_refer_state(LinphoneCore *lc, LinphoneCall *referer, L
|
|||
nodes with the basic SIP routing policy in order to get a workable
|
||||
system.
|
||||
*/
|
||||
|
||||
|
||||
static MSList *make_routes_for_proxy(LinphoneProxyConfig *proxy, const LinphoneAddress *dest){
|
||||
MSList *ret=NULL;
|
||||
const char *local_route=linphone_proxy_config_get_route(proxy);
|
||||
|
|
@ -2822,7 +2838,7 @@ LinphoneCall * linphone_core_invite_address_with_params(LinphoneCore *lc, const
|
|||
bool_t defer = FALSE;
|
||||
|
||||
linphone_core_preempt_sound_resources(lc);
|
||||
|
||||
|
||||
if(!linphone_core_can_we_add_call(lc)){
|
||||
if (lc->vtable.display_warning)
|
||||
lc->vtable.display_warning(lc,_("Sorry, we have reached the maximum number of simultaneous calls"));
|
||||
|
|
@ -2852,22 +2868,16 @@ LinphoneCall * linphone_core_invite_address_with_params(LinphoneCore *lc, const
|
|||
/* this call becomes now the current one*/
|
||||
lc->current_call=call;
|
||||
linphone_call_set_state (call,LinphoneCallOutgoingInit,"Starting outgoing call");
|
||||
call->log->start_date_time=time(NULL);
|
||||
linphone_call_init_media_streams(call);
|
||||
|
||||
if (linphone_core_get_firewall_policy(call->core) == LinphonePolicyUseIce) {
|
||||
/* Defer the start of the call after the ICE gathering process. */
|
||||
linphone_call_start_media_streams_for_ice_gathering(call);
|
||||
call->log->start_date_time=time(NULL);
|
||||
if (linphone_core_gather_ice_candidates(lc,call)<0) {
|
||||
/* Ice candidates gathering failed, proceed with the call anyway. */
|
||||
linphone_call_delete_ice_session(call);
|
||||
linphone_call_stop_media_streams_for_ice_gathering(call);
|
||||
} else {
|
||||
defer = TRUE;
|
||||
}
|
||||
if (linphone_call_prepare_ice(call,FALSE)==1)
|
||||
defer=TRUE;
|
||||
}
|
||||
else if (linphone_core_get_firewall_policy(call->core) == LinphonePolicyUseUpnp) {
|
||||
#ifdef BUILD_UPNP
|
||||
call->log->start_date_time=time(NULL);
|
||||
if (linphone_core_update_upnp(lc,call)<0) {
|
||||
/* uPnP port mappings failed, proceed with the call anyway. */
|
||||
linphone_call_delete_upnp_session(call);
|
||||
|
|
@ -2889,11 +2899,10 @@ LinphoneCall * linphone_core_invite_address_with_params(LinphoneCore *lc, const
|
|||
call->ping_op=sal_op_new(lc->sal);
|
||||
sal_ping(call->ping_op,from,real_url);
|
||||
sal_op_set_user_pointer(call->ping_op,call);
|
||||
call->log->start_date_time=time(NULL);
|
||||
defer = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (defer==FALSE) linphone_core_start_invite(lc,call,NULL);
|
||||
|
||||
if (real_url!=NULL) ms_free(real_url);
|
||||
|
|
@ -2906,7 +2915,7 @@ LinphoneCall * linphone_core_invite_address_with_params(LinphoneCore *lc, const
|
|||
* @ingroup call_control
|
||||
* The remote endpoint is expected to issue a new call to the specified destination.
|
||||
* The current call remains active and thus can be later paused or terminated.
|
||||
*
|
||||
*
|
||||
* It is possible to follow the progress of the transfer provided that transferee sends notification about it.
|
||||
* In this case, the transfer_state_changed callback of the #LinphoneCoreVTable is invoked to notify of the state of the new call at the other party.
|
||||
* The notified states are #LinphoneCallOutgoingInit , #LinphoneCallOutgoingProgress, #LinphoneCallOutgoingRinging and #LinphoneCallOutgoingConnected.
|
||||
|
|
@ -2938,7 +2947,7 @@ int linphone_core_transfer_call(LinphoneCore *lc, LinphoneCall *call, const char
|
|||
* @param lc linphone core object
|
||||
* @param call a running call you want to transfer
|
||||
* @param dest a running call whose remote person will receive the transfer
|
||||
*
|
||||
*
|
||||
* @ingroup call_control
|
||||
*
|
||||
* The transfered call is supposed to be in paused state, so that it is able to accept the transfer immediately.
|
||||
|
|
@ -2946,7 +2955,7 @@ int linphone_core_transfer_call(LinphoneCore *lc, LinphoneCall *call, const char
|
|||
* This method will send a transfer request to the transfered person. The phone of the transfered is then
|
||||
* expected to automatically call to the destination of the transfer. The receiver of the transfer will then automatically
|
||||
* close the call with us (the 'dest' call).
|
||||
*
|
||||
*
|
||||
* It is possible to follow the progress of the transfer provided that transferee sends notification about it.
|
||||
* In this case, the transfer_state_changed callback of the #LinphoneCoreVTable is invoked to notify of the state of the new call at the other party.
|
||||
* The notified states are #LinphoneCallOutgoingInit , #LinphoneCallOutgoingProgress, #LinphoneCallOutgoingRinging and #LinphoneCallOutgoingConnected.
|
||||
|
|
@ -2971,7 +2980,7 @@ bool_t linphone_core_inc_invite_pending(LinphoneCore*lc){
|
|||
bool_t linphone_core_media_description_has_srtp(const SalMediaDescription *md){
|
||||
int i;
|
||||
if (md->n_active_streams==0) return FALSE;
|
||||
|
||||
|
||||
for(i=0;i<md->n_active_streams;i++){
|
||||
const SalStreamDescription *sd=&md->streams[i];
|
||||
if (sd->proto!=SalProtoRtpSavp){
|
||||
|
|
@ -3011,10 +3020,10 @@ void linphone_core_notify_incoming_call(LinphoneCore *lc, LinphoneCall *call){
|
|||
tmp=linphone_address_as_string(from_parsed);
|
||||
linphone_address_destroy(from_parsed);
|
||||
barmesg=ortp_strdup_printf("%s %s%s",tmp,_("is contacting you"),
|
||||
(sal_call_autoanswer_asked(call->op)) ?_(" and asked autoanswer."):_("."));
|
||||
(sal_call_autoanswer_asked(call->op)) ?_(" and asked autoanswer."):_("."));
|
||||
if (lc->vtable.show) lc->vtable.show(lc);
|
||||
if (lc->vtable.display_status)
|
||||
lc->vtable.display_status(lc,barmesg);
|
||||
lc->vtable.display_status(lc,barmesg);
|
||||
|
||||
/* play the ring if this is the only call*/
|
||||
if (ms_list_size(lc->calls)==1){
|
||||
|
|
@ -3044,11 +3053,11 @@ void linphone_core_notify_incoming_call(LinphoneCore *lc, LinphoneCall *call){
|
|||
if (call->state==LinphoneCallIncomingReceived){
|
||||
/*try to be best-effort in giving real local or routable contact address for 100Rel case*/
|
||||
linphone_call_set_contact_op(call);
|
||||
|
||||
|
||||
if (propose_early_media || ringback_tone!=NULL){
|
||||
linphone_core_accept_early_media(lc,call);
|
||||
}else sal_call_notify_ringing(call->op,FALSE);
|
||||
|
||||
|
||||
if (sal_call_get_replaces(call->op)!=NULL && lp_config_get_int(lc->config,"sip","auto_answer_replacing_calls",1)){
|
||||
linphone_core_accept_call(lc,call);
|
||||
}
|
||||
|
|
@ -3074,7 +3083,7 @@ void linphone_core_notify_incoming_call(LinphoneCore *lc, LinphoneCall *call){
|
|||
int linphone_core_accept_early_media_with_params(LinphoneCore* lc, LinphoneCall* call, const LinphoneCallParams* params) {
|
||||
if (call->state==LinphoneCallIncomingReceived){
|
||||
SalMediaDescription* md;
|
||||
|
||||
|
||||
/*try to be best-effort in giving real local or routable contact address for 100Rel case*/
|
||||
linphone_call_set_contact_op(call);
|
||||
|
||||
|
|
@ -3085,7 +3094,7 @@ int linphone_core_accept_early_media_with_params(LinphoneCore* lc, LinphoneCall*
|
|||
sal_call_set_local_media_description ( call->op,call->localdesc );
|
||||
sal_op_set_sent_custom_header ( call->op,params->custom_headers );
|
||||
}
|
||||
|
||||
|
||||
sal_call_notify_ringing(call->op,TRUE);
|
||||
|
||||
linphone_call_set_state(call,LinphoneCallIncomingEarlyMedia,"Incoming call early media");
|
||||
|
|
@ -3115,9 +3124,7 @@ int linphone_core_accept_early_media(LinphoneCore* lc, LinphoneCall* call){
|
|||
int linphone_core_start_update_call(LinphoneCore *lc, LinphoneCall *call){
|
||||
const char *subject;
|
||||
|
||||
if (call->ice_session != NULL) {
|
||||
linphone_core_update_local_media_description_from_ice(call->localdesc, call->ice_session);
|
||||
}
|
||||
linphone_call_make_local_media_description(lc,call);
|
||||
#ifdef BUILD_UPNP
|
||||
if(call->upnp_session != NULL) {
|
||||
linphone_core_update_local_media_description_from_upnp(call->localdesc, call->upnp_session);
|
||||
|
|
@ -3164,10 +3171,6 @@ int linphone_core_update_call(LinphoneCore *lc, LinphoneCall *call, const Linpho
|
|||
|
||||
// Video removing
|
||||
if((call->videostream != NULL) && !params->has_video) {
|
||||
if (call->ice_session != NULL) {
|
||||
ice_session_remove_check_list(call->ice_session, call->videostream->ms.ice_check_list);
|
||||
call->videostream->ms.ice_check_list = NULL;
|
||||
}
|
||||
#ifdef BUILD_UPNP
|
||||
if(call->upnp_session != NULL) {
|
||||
if (linphone_core_update_upnp(lc, call)<0) {
|
||||
|
|
@ -3180,27 +3183,18 @@ int linphone_core_update_call(LinphoneCore *lc, LinphoneCall *call, const Linpho
|
|||
#endif /* VIDEO_ENABLED */
|
||||
|
||||
_linphone_call_params_copy(&call->params,params);
|
||||
linphone_call_make_local_media_description(lc, call);
|
||||
err=linphone_call_prepare_ice(call,FALSE);
|
||||
if (err==1) {
|
||||
ms_message("Defer call update to gather ICE candidates");
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef VIDEO_ENABLED
|
||||
// Video adding
|
||||
if (!has_video && call->params.has_video) {
|
||||
if (call->ice_session != NULL) {
|
||||
/* Defer call update until the ICE candidates gathering process has finished. */
|
||||
ms_message("Defer call update to gather ICE candidates");
|
||||
linphone_call_init_video_stream(call);
|
||||
video_stream_prepare_video(call->videostream);
|
||||
if (linphone_core_gather_ice_candidates(lc,call)<0) {
|
||||
/* Ice candidates gathering failed, proceed with the call anyway. */
|
||||
linphone_call_delete_ice_session(call);
|
||||
} else {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
#ifdef BUILD_UPNP
|
||||
if(call->upnp_session != NULL) {
|
||||
ms_message("Defer call update to add uPnP port mappings");
|
||||
linphone_call_init_video_stream(call);
|
||||
video_stream_prepare_video(call->videostream);
|
||||
if (linphone_core_update_upnp(lc, call)<0) {
|
||||
/* uPnP port mappings failed, proceed with the call anyway. */
|
||||
|
|
@ -3211,7 +3205,7 @@ int linphone_core_update_call(LinphoneCore *lc, LinphoneCall *call, const Linpho
|
|||
}
|
||||
#endif //BUILD_UPNP
|
||||
}
|
||||
#endif
|
||||
#endif //VIDEO_ENABLED
|
||||
err = linphone_core_start_update_call(lc, call);
|
||||
}else{
|
||||
#ifdef VIDEO_ENABLED
|
||||
|
|
@ -3230,15 +3224,15 @@ int linphone_core_update_call(LinphoneCore *lc, LinphoneCall *call, const Linpho
|
|||
/**
|
||||
* @ingroup call_control
|
||||
* When receiving a #LinphoneCallUpdatedByRemote state notification, prevent LinphoneCore from performing an automatic answer.
|
||||
*
|
||||
*
|
||||
* When receiving a #LinphoneCallUpdatedByRemote state notification (ie an incoming reINVITE), the default behaviour of
|
||||
* LinphoneCore is to automatically answer the reINIVTE with call parameters unchanged.
|
||||
* However when for example when the remote party updated the call to propose a video stream, it can be useful
|
||||
* to prompt the user before answering. This can be achieved by calling linphone_core_defer_call_update() during
|
||||
* to prompt the user before answering. This can be achieved by calling linphone_core_defer_call_update() during
|
||||
* the call state notifiacation, to deactivate the automatic answer that would just confirm the audio but reject the video.
|
||||
* Then, when the user responds to dialog prompt, it becomes possible to call linphone_core_accept_call_update() to answer
|
||||
* the reINVITE, with eventually video enabled in the LinphoneCallParams argument.
|
||||
*
|
||||
*
|
||||
* @return 0 if successful, -1 if the linphone_core_defer_call_update() was done outside a #LinphoneCallUpdatedByRemote notification, which is illegal.
|
||||
**/
|
||||
int linphone_core_defer_call_update(LinphoneCore *lc, LinphoneCall *call){
|
||||
|
|
@ -3257,13 +3251,9 @@ int linphone_core_start_accept_call_update(LinphoneCore *lc, LinphoneCall *call)
|
|||
/* Defer the sending of the answer until there are no losing pairs left. */
|
||||
return 0;
|
||||
}
|
||||
linphone_core_update_local_media_description_from_ice(call->localdesc, call->ice_session);
|
||||
}
|
||||
#ifdef BUILD_UPNP
|
||||
if(call->upnp_session != NULL) {
|
||||
linphone_core_update_local_media_description_from_upnp(call->localdesc, call->upnp_session);
|
||||
}
|
||||
#endif //BUILD_UPNP
|
||||
linphone_call_make_local_media_description(lc,call);
|
||||
|
||||
linphone_call_update_remote_session_id_and_ver(call);
|
||||
sal_call_set_local_media_description(call->op,call->localdesc);
|
||||
sal_call_accept(call->op);
|
||||
|
|
@ -3300,7 +3290,7 @@ int linphone_core_start_accept_call_update(LinphoneCore *lc, LinphoneCall *call)
|
|||
int linphone_core_accept_call_update(LinphoneCore *lc, LinphoneCall *call, const LinphoneCallParams *params){
|
||||
if (call->state!=LinphoneCallUpdatedByRemote){
|
||||
ms_error("linphone_core_accept_update(): invalid state %s to call this function.",
|
||||
linphone_call_state_to_string(call->state));
|
||||
linphone_call_state_to_string(call->state));
|
||||
return -1;
|
||||
}
|
||||
return _linphone_core_accept_call_update(lc, call, params);
|
||||
|
|
@ -3309,7 +3299,7 @@ int linphone_core_accept_call_update(LinphoneCore *lc, LinphoneCall *call, const
|
|||
int _linphone_core_accept_call_update(LinphoneCore *lc, LinphoneCall *call, const LinphoneCallParams *params){
|
||||
SalMediaDescription *remote_desc;
|
||||
bool_t keep_sdp_version;
|
||||
#ifdef VIDEO_ENABLED
|
||||
#if defined(VIDEO_ENABLED) && defined(BUILD_UPNP)
|
||||
bool_t old_has_video = call->params.has_video;
|
||||
#endif
|
||||
|
||||
|
|
@ -3337,20 +3327,9 @@ int _linphone_core_accept_call_update(LinphoneCore *lc, LinphoneCall *call, cons
|
|||
}
|
||||
call->params.has_video &= linphone_core_media_description_contains_video_stream(remote_desc);
|
||||
linphone_call_init_media_streams(call); /*so that video stream is initialized if necessary*/
|
||||
linphone_call_make_local_media_description(lc,call);
|
||||
if (call->ice_session != NULL) {
|
||||
linphone_core_update_ice_from_remote_media_description(call, remote_desc);
|
||||
#ifdef VIDEO_ENABLED
|
||||
if ((call->ice_session != NULL) && !ice_session_candidates_gathered(call->ice_session)) {
|
||||
if ((call->params.has_video) && (call->params.has_video != old_has_video)) {
|
||||
video_stream_prepare_video(call->videostream);
|
||||
if (linphone_core_gather_ice_candidates(lc,call)<0) {
|
||||
/* Ice candidates gathering failed, proceed with the call anyway. */
|
||||
linphone_call_delete_ice_session(call);
|
||||
} else return 0;
|
||||
}
|
||||
}
|
||||
#endif //VIDEO_ENABLED
|
||||
if (linphone_call_prepare_ice(call,TRUE)==1)
|
||||
return 0;/*deferred to completion of ICE gathering*/
|
||||
}
|
||||
|
||||
#ifdef BUILD_UPNP
|
||||
|
|
@ -3427,7 +3406,7 @@ int linphone_core_accept_call_with_params(LinphoneCore *lc, LinphoneCall *call,
|
|||
LinphoneCall *rc=(LinphoneCall*)sal_op_get_user_pointer (replaced);
|
||||
if (rc){
|
||||
ms_message("Call %p replaces call %p. This last one is going to be terminated automatically.",
|
||||
call,rc);
|
||||
call,rc);
|
||||
linphone_core_terminate_call(lc,rc);
|
||||
}
|
||||
}
|
||||
|
|
@ -3459,7 +3438,7 @@ int linphone_core_accept_call_with_params(LinphoneCore *lc, LinphoneCall *call,
|
|||
sal_call_set_local_media_description(call->op,call->localdesc);
|
||||
sal_op_set_sent_custom_header(call->op,params->custom_headers);
|
||||
}
|
||||
|
||||
|
||||
/*give a chance a set card prefered sampling frequency*/
|
||||
if (call->localdesc->streams[0].max_rate>0) {
|
||||
ms_message ("configuring prefered card sampling rate to [%i]",call->localdesc->streams[0].max_rate);
|
||||
|
|
@ -3468,7 +3447,7 @@ int linphone_core_accept_call_with_params(LinphoneCore *lc, LinphoneCall *call,
|
|||
if (lc->sound_conf.capt_sndcard)
|
||||
ms_snd_card_set_preferred_sample_rate(lc->sound_conf.capt_sndcard, call->localdesc->streams[0].max_rate);
|
||||
}
|
||||
|
||||
|
||||
if (!was_ringing && call->audiostream->ms.state==MSStreamInitialized){
|
||||
audio_stream_prepare_sound(call->audiostream,lc->sound_conf.play_sndcard,lc->sound_conf.capt_sndcard);
|
||||
}
|
||||
|
|
@ -3586,9 +3565,9 @@ int linphone_core_terminate_call(LinphoneCore *lc, LinphoneCall *the_call)
|
|||
|
||||
/**
|
||||
* Decline a pending incoming call, with a reason.
|
||||
*
|
||||
*
|
||||
* @ingroup call_control
|
||||
*
|
||||
*
|
||||
* @param lc the linphone core
|
||||
* @param call the LinphoneCall, must be in the IncomingReceived state.
|
||||
* @param reason the reason for rejecting the call: LinphoneReasonDeclined or LinphoneReasonBusy
|
||||
|
|
@ -3674,9 +3653,6 @@ int _linphone_core_pause_call(LinphoneCore *lc, LinphoneCall *call)
|
|||
return -1;
|
||||
}
|
||||
linphone_call_make_local_media_description(lc,call);
|
||||
if (call->ice_session != NULL) {
|
||||
linphone_core_update_local_media_description_from_ice(call->localdesc, call->ice_session);
|
||||
}
|
||||
#ifdef BUILD_UPNP
|
||||
if(call->upnp_session != NULL) {
|
||||
linphone_core_update_local_media_description_from_upnp(call->localdesc, call->upnp_session);
|
||||
|
|
@ -3725,12 +3701,12 @@ int linphone_core_pause_all_calls(LinphoneCore *lc){
|
|||
|
||||
void linphone_core_preempt_sound_resources(LinphoneCore *lc){
|
||||
LinphoneCall *current_call;
|
||||
|
||||
|
||||
if (linphone_core_is_in_conference(lc)){
|
||||
linphone_core_leave_conference(lc);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
current_call=linphone_core_get_current_call(lc);
|
||||
if(current_call != NULL){
|
||||
ms_message("Pausing automatically the current call.");
|
||||
|
|
@ -3749,7 +3725,7 @@ void linphone_core_preempt_sound_resources(LinphoneCore *lc){
|
|||
int linphone_core_resume_call(LinphoneCore *lc, LinphoneCall *call){
|
||||
char temp[255]={0};
|
||||
const char *subject="Call resuming";
|
||||
|
||||
|
||||
if(call->state!=LinphoneCallPaused ){
|
||||
ms_warning("we cannot resume a call that has not been established and paused before");
|
||||
return -1;
|
||||
|
|
@ -3764,15 +3740,12 @@ int linphone_core_resume_call(LinphoneCore *lc, LinphoneCall *call){
|
|||
}
|
||||
|
||||
call->was_automatically_paused=FALSE;
|
||||
|
||||
|
||||
/* Stop playing music immediately. If remote side is a conference it
|
||||
prevents the participants to hear it while the 200OK comes back.*/
|
||||
if (call->audiostream) audio_stream_play(call->audiostream, NULL);
|
||||
|
||||
linphone_call_make_local_media_description(lc,call);
|
||||
if (call->ice_session != NULL) {
|
||||
linphone_core_update_local_media_description_from_ice(call->localdesc, call->ice_session);
|
||||
}
|
||||
#ifdef BUILD_UPNP
|
||||
if(call->upnp_session != NULL) {
|
||||
linphone_core_update_local_media_description_from_upnp(call->localdesc, call->upnp_session);
|
||||
|
|
@ -3803,7 +3776,7 @@ static int remote_address_compare(LinphoneCall *call, const LinphoneAddress *rad
|
|||
* @param lc
|
||||
* @param remote_address
|
||||
* @return the LinphoneCall of the call if found
|
||||
*
|
||||
*
|
||||
* @ingroup call_control
|
||||
*/
|
||||
LinphoneCall *linphone_core_get_call_by_remote_address(LinphoneCore *lc, const char *remote_address){
|
||||
|
|
@ -3814,7 +3787,7 @@ LinphoneCall *linphone_core_get_call_by_remote_address(LinphoneCore *lc, const c
|
|||
}
|
||||
|
||||
int linphone_core_send_publish(LinphoneCore *lc,
|
||||
LinphonePresenceModel *presence)
|
||||
LinphonePresenceModel *presence)
|
||||
{
|
||||
const MSList *elem;
|
||||
for (elem=linphone_core_get_proxy_config_list(lc);elem!=NULL;elem=ms_list_next(elem)){
|
||||
|
|
@ -4171,7 +4144,7 @@ static MSSndCard *get_card_from_string_id(const char *devid, unsigned int cap){
|
|||
if (sndcard==NULL){/*looks like a bug! take the first one !*/
|
||||
const MSList *elem=ms_snd_card_manager_get_list(ms_snd_card_manager_get());
|
||||
if (elem) sndcard=(MSSndCard*)elem->data;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (sndcard==NULL) ms_error("Could not find a suitable soundcard !");
|
||||
return sndcard;
|
||||
|
|
@ -4406,7 +4379,7 @@ const char *linphone_core_get_root_ca(LinphoneCore *lc){
|
|||
|
||||
/**
|
||||
* Specify whether the tls server certificate must be verified when connecting to a SIP/TLS server.
|
||||
*
|
||||
*
|
||||
* @ingroup initializing
|
||||
**/
|
||||
void linphone_core_verify_server_certificates(LinphoneCore *lc, bool_t yesno){
|
||||
|
|
@ -4523,7 +4496,7 @@ void linphone_core_mute_mic(LinphoneCore *lc, bool_t val){
|
|||
if ( linphone_core_get_rtp_no_xmit_on_audio_mute(lc) ){
|
||||
audio_stream_mute_rtp(st,val);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -4609,7 +4582,7 @@ void linphone_core_set_stun_server(LinphoneCore *lc, const char *server){
|
|||
if (server)
|
||||
lc->net_conf.stun_server=ms_strdup(server);
|
||||
else lc->net_conf.stun_server=NULL;
|
||||
|
||||
|
||||
/* each time the stun server is changed, we must clean the resolved cached addrinfo*/
|
||||
if (lc->net_conf.stun_addrinfo){
|
||||
freeaddrinfo(lc->net_conf.stun_addrinfo);
|
||||
|
|
@ -4619,7 +4592,7 @@ void linphone_core_set_stun_server(LinphoneCore *lc, const char *server){
|
|||
if (lc->net_conf.stun_server){
|
||||
linphone_core_resolve_stun_server(lc);
|
||||
}
|
||||
|
||||
|
||||
if (linphone_core_ready(lc))
|
||||
lp_config_set_string(lc->config,"net","stun_server",lc->net_conf.stun_server);
|
||||
}
|
||||
|
|
@ -4676,7 +4649,7 @@ const char *linphone_core_get_nat_address_resolved(LinphoneCore *lc)
|
|||
char ipstring [INET6_ADDRSTRLEN];
|
||||
|
||||
if (lc->net_conf.nat_address==NULL) return NULL;
|
||||
|
||||
|
||||
if (parse_hostname_to_addr (lc->net_conf.nat_address, &ss, &ss_len, 5060)<0) {
|
||||
return lc->net_conf.nat_address;
|
||||
}
|
||||
|
|
@ -5045,7 +5018,7 @@ int linphone_core_set_static_picture(LinphoneCore *lc, const char *path) {
|
|||
const char *linphone_core_get_static_picture(LinphoneCore *lc) {
|
||||
const char *path=NULL;
|
||||
#ifdef VIDEO_ENABLED
|
||||
path=ms_static_image_get_default_image();
|
||||
path=ms_static_image_get_default_image();
|
||||
#else
|
||||
ms_warning("Video support not compiled.");
|
||||
#endif
|
||||
|
|
@ -5082,7 +5055,7 @@ float linphone_core_get_static_picture_fps(LinphoneCore *lc) {
|
|||
if (vs && vs->source) {
|
||||
if (ms_filter_get_id(vs->source) == MS_STATIC_IMAGE_ID) {
|
||||
|
||||
float fps;
|
||||
float fps;
|
||||
|
||||
ms_filter_call_method(vs->source, MS_FILTER_GET_FPS,(void *)&fps);
|
||||
return fps;
|
||||
|
|
@ -5120,7 +5093,7 @@ static void unset_video_window_id(LinphoneCore *lc, bool_t preview, unsigned lon
|
|||
LinphoneCall *call;
|
||||
MSList *elem;
|
||||
#endif
|
||||
|
||||
|
||||
if (id!=0 && id!=-1) {
|
||||
ms_error("Invalid use of unset_video_window_id()");
|
||||
return;
|
||||
|
|
@ -5284,7 +5257,7 @@ static MSVideoSizeDef supported_resolutions[]={
|
|||
#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" },
|
||||
#endif
|
||||
{ { MS_VIDEO_SIZE_QCIF_W, MS_VIDEO_SIZE_QCIF_H } , "qcif" },
|
||||
{ { MS_VIDEO_SIZE_QCIF_W, MS_VIDEO_SIZE_QCIF_H } , "qcif" },
|
||||
{ { 0,0 } , NULL }
|
||||
};
|
||||
|
||||
|
|
@ -5529,7 +5502,7 @@ void linphone_core_play_named_tone(LinphoneCore *lc, LinphoneToneID toneid){
|
|||
def.frequencies[0]=620;
|
||||
def.interval=250;
|
||||
def.repeat_count=3;
|
||||
|
||||
|
||||
break;
|
||||
default:
|
||||
ms_warning("Unhandled tone id.");
|
||||
|
|
@ -5595,7 +5568,7 @@ int linphone_core_get_mtu(const LinphoneCore *lc){
|
|||
* Sets the maximum transmission unit size in bytes.
|
||||
* This information is useful for sending RTP packets.
|
||||
* Default value is 1500.
|
||||
*
|
||||
*
|
||||
* @ingroup media_parameters
|
||||
**/
|
||||
void linphone_core_set_mtu(LinphoneCore *lc, int mtu){
|
||||
|
|
@ -5689,7 +5662,7 @@ void sip_config_uninit(LinphoneCore *lc)
|
|||
int i;
|
||||
sip_config_t *config=&lc->sip_conf;
|
||||
bool_t still_registered=TRUE;
|
||||
|
||||
|
||||
lp_config_set_int(lc->config,"sip","guess_hostname",config->guess_hostname);
|
||||
lp_config_set_string(lc->config,"sip","contact",config->contact);
|
||||
lp_config_set_int(lc->config,"sip","inc_timeout",config->inc_timeout);
|
||||
|
|
@ -5704,7 +5677,7 @@ void sip_config_uninit(LinphoneCore *lc)
|
|||
LinphoneProxyConfig *cfg=(LinphoneProxyConfig*)(elem->data);
|
||||
linphone_proxy_config_edit(cfg); /* to unregister */
|
||||
}
|
||||
|
||||
|
||||
ms_message("Unregistration started.");
|
||||
|
||||
for (i=0;i<20&&still_registered;i++){
|
||||
|
|
@ -5736,7 +5709,7 @@ void sip_config_uninit(LinphoneCore *lc)
|
|||
ms_message("Tunnel destroyed.");
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
sal_reset_transports(lc->sal);
|
||||
sal_unlisten_ports(lc->sal); /*to make sure no new messages are received*/
|
||||
if (lc->http_provider) {
|
||||
|
|
@ -5942,7 +5915,7 @@ static void linphone_core_uninit(LinphoneCore *lc)
|
|||
linphone_presence_model_unref(lc->presence_model);
|
||||
}
|
||||
linphone_core_free_payload_types(lc);
|
||||
|
||||
|
||||
linphone_core_message_storage_close(lc);
|
||||
ms_exit();
|
||||
linphone_core_set_state(lc,LinphoneGlobalOff,"Off");
|
||||
|
|
@ -5951,7 +5924,7 @@ static void linphone_core_uninit(LinphoneCore *lc)
|
|||
static void set_network_reachable(LinphoneCore* lc,bool_t isReachable, time_t curtime){
|
||||
// second get the list of available proxies
|
||||
const MSList *elem=linphone_core_get_proxy_config_list(lc);
|
||||
|
||||
|
||||
if (lc->network_reachable==isReachable) return; // no change, ignore.
|
||||
|
||||
ms_message("Network state is now [%s]",isReachable?"UP":"DOWN");
|
||||
|
|
@ -5968,7 +5941,7 @@ static void set_network_reachable(LinphoneCore* lc,bool_t isReachable, time_t cu
|
|||
}
|
||||
lc->netup_time=curtime;
|
||||
lc->network_reachable=isReachable;
|
||||
|
||||
|
||||
if (!lc->network_reachable){
|
||||
linphone_core_invalidate_friend_subscriptions(lc);
|
||||
sal_reset_transports(lc->sal);
|
||||
|
|
@ -6442,7 +6415,7 @@ int linphone_core_set_media_encryption(LinphoneCore *lc, LinphoneMediaEncryption
|
|||
|
||||
LinphoneMediaEncryption linphone_core_get_media_encryption(LinphoneCore *lc) {
|
||||
const char* menc = lp_config_get_string(lc->config, "sip", "media_encryption", NULL);
|
||||
|
||||
|
||||
if (menc == NULL)
|
||||
return LinphoneMediaEncryptionNone;
|
||||
else if (strcmp(menc, "srtp")==0)
|
||||
|
|
@ -6478,10 +6451,10 @@ const char* linphone_core_get_device_identifier(const LinphoneCore *lc) {
|
|||
|
||||
/**
|
||||
* Set the DSCP field for SIP signaling channel.
|
||||
*
|
||||
*
|
||||
* @ingroup network_parameters
|
||||
* * The DSCP defines the quality of service in IP packets.
|
||||
*
|
||||
*
|
||||
**/
|
||||
void linphone_core_set_sip_dscp(LinphoneCore *lc, int dscp){
|
||||
sal_set_dscp(lc->sal,dscp);
|
||||
|
|
@ -6493,10 +6466,10 @@ void linphone_core_set_sip_dscp(LinphoneCore *lc, int dscp){
|
|||
|
||||
/**
|
||||
* Get the DSCP field for SIP signaling channel.
|
||||
*
|
||||
*
|
||||
* @ingroup network_parameters
|
||||
* * The DSCP defines the quality of service in IP packets.
|
||||
*
|
||||
*
|
||||
**/
|
||||
int linphone_core_get_sip_dscp(const LinphoneCore *lc){
|
||||
return lp_config_get_int(lc->config,"sip","dscp",0x1a);
|
||||
|
|
@ -6507,7 +6480,7 @@ int linphone_core_get_sip_dscp(const LinphoneCore *lc){
|
|||
*
|
||||
* @ingroup network_parameters
|
||||
* The DSCP defines the quality of service in IP packets.
|
||||
*
|
||||
*
|
||||
**/
|
||||
void linphone_core_set_audio_dscp(LinphoneCore *lc, int dscp){
|
||||
if (linphone_core_ready(lc))
|
||||
|
|
@ -6519,7 +6492,7 @@ void linphone_core_set_audio_dscp(LinphoneCore *lc, int dscp){
|
|||
*
|
||||
* @ingroup network_parameters
|
||||
* The DSCP defines the quality of service in IP packets.
|
||||
*
|
||||
*
|
||||
**/
|
||||
int linphone_core_get_audio_dscp(const LinphoneCore *lc){
|
||||
return lp_config_get_int(lc->config,"rtp","audio_dscp",0x2e);
|
||||
|
|
@ -6530,12 +6503,12 @@ int linphone_core_get_audio_dscp(const LinphoneCore *lc){
|
|||
*
|
||||
* @ingroup network_parameters
|
||||
* The DSCP defines the quality of service in IP packets.
|
||||
*
|
||||
*
|
||||
**/
|
||||
void linphone_core_set_video_dscp(LinphoneCore *lc, int dscp){
|
||||
if (linphone_core_ready(lc))
|
||||
lp_config_set_int_hex(lc->config,"rtp","video_dscp",dscp);
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -6543,7 +6516,7 @@ void linphone_core_set_video_dscp(LinphoneCore *lc, int dscp){
|
|||
*
|
||||
* @ingroup network_parameters
|
||||
* The DSCP defines the quality of service in IP packets.
|
||||
*
|
||||
*
|
||||
**/
|
||||
int linphone_core_get_video_dscp(const LinphoneCore *lc){
|
||||
return lp_config_get_int(lc->config,"rtp","video_dscp",0);
|
||||
|
|
|
|||
|
|
@ -177,7 +177,7 @@ enum _LinphoneReason{
|
|||
LinphoneReasonNotAcceptable, /**<Operation like call update rejected by peer*/
|
||||
LinphoneReasonNoMatch, /**<Operation could not be executed by server or remote client because it didn't have any context for it*/
|
||||
LinphoneReasonMovedPermanently, /**<Resource moved permanently*/
|
||||
LinphoneReasonGone, /**<Resource no longer exists*/
|
||||
LinphoneReasonGone, /**<Resource no longer exists*/
|
||||
LinphoneReasonTemporarilyUnavailable, /**<Temporarily unavailable*/
|
||||
LinphoneReasonAddressIncomplete, /**<Address incomplete*/
|
||||
LinphoneReasonNotImplemented, /**<Not implemented*/
|
||||
|
|
@ -684,7 +684,6 @@ LINPHONE_PUBLIC LinphoneReason linphone_call_get_reason(const LinphoneCall *call
|
|||
LINPHONE_PUBLIC const LinphoneErrorInfo *linphone_call_get_error_info(const LinphoneCall *call);
|
||||
LINPHONE_PUBLIC const char *linphone_call_get_remote_user_agent(LinphoneCall *call);
|
||||
LINPHONE_PUBLIC const char *linphone_call_get_remote_contact(LinphoneCall *call);
|
||||
LINPHONE_PUBLIC LinphoneAddress *linphone_call_get_remote_contact_address(LinphoneCall *call);
|
||||
LINPHONE_PUBLIC float linphone_call_get_play_volume(LinphoneCall *call);
|
||||
LINPHONE_PUBLIC float linphone_call_get_record_volume(LinphoneCall *call);
|
||||
LINPHONE_PUBLIC float linphone_call_get_current_quality(LinphoneCall *call);
|
||||
|
|
@ -790,6 +789,7 @@ LINPHONE_PUBLIC int linphone_proxy_config_set_server_addr(LinphoneProxyConfig *o
|
|||
LINPHONE_PUBLIC int linphone_proxy_config_set_identity(LinphoneProxyConfig *obj, const char *identity);
|
||||
LINPHONE_PUBLIC int linphone_proxy_config_set_route(LinphoneProxyConfig *obj, const char *route);
|
||||
LINPHONE_PUBLIC void linphone_proxy_config_set_expires(LinphoneProxyConfig *obj, int expires);
|
||||
|
||||
#define linphone_proxy_config_expires linphone_proxy_config_set_expires
|
||||
/**
|
||||
* Indicates either or not, REGISTRATION must be issued for this #LinphoneProxyConfig .
|
||||
|
|
@ -809,9 +809,35 @@ LINPHONE_PUBLIC int linphone_proxy_config_done(LinphoneProxyConfig *obj);
|
|||
*
|
||||
*/
|
||||
LINPHONE_PUBLIC void linphone_proxy_config_enable_publish(LinphoneProxyConfig *obj, bool_t val);
|
||||
/**
|
||||
* Set the publish expiration time in second.
|
||||
* @param obj proxy config
|
||||
* @param exires in second
|
||||
* */
|
||||
|
||||
LINPHONE_PUBLIC void linphone_proxy_config_set_publish_expires(LinphoneProxyConfig *obj, int expires);
|
||||
/**
|
||||
* get the publish expiration time in second. Default value is the registration expiration value.
|
||||
* @param obj proxy config
|
||||
* @return expires in second
|
||||
* */
|
||||
|
||||
LINPHONE_PUBLIC int linphone_proxy_config_get_publish_expires(const LinphoneProxyConfig *obj);
|
||||
|
||||
LINPHONE_PUBLIC void linphone_proxy_config_set_dial_escape_plus(LinphoneProxyConfig *cfg, bool_t val);
|
||||
LINPHONE_PUBLIC void linphone_proxy_config_set_dial_prefix(LinphoneProxyConfig *cfg, const char *prefix);
|
||||
|
||||
/**
|
||||
* Indicates either or not, quality statistics during call should be stored and sent to a collector at termination.
|
||||
* @param cfg #LinphoneProxyConfig object
|
||||
* @param val if true, quality statistics publish will be stored and sent to the collector
|
||||
*
|
||||
*/
|
||||
LINPHONE_PUBLIC void linphone_proxy_config_enable_statistics(LinphoneProxyConfig *cfg, bool_t val);
|
||||
LINPHONE_PUBLIC bool_t linphone_proxy_config_send_statistics_enabled(LinphoneProxyConfig *cfg);
|
||||
LINPHONE_PUBLIC void linphone_proxy_config_set_statistics_collector(LinphoneProxyConfig *cfg, const char *collector);
|
||||
LINPHONE_PUBLIC const char *linphone_proxy_config_get_statistics_collector(const LinphoneProxyConfig *obj);
|
||||
|
||||
/**
|
||||
* Get the registration state of the given proxy config.
|
||||
* @param[in] obj #LinphoneProxyConfig object.
|
||||
|
|
@ -1556,6 +1582,33 @@ LINPHONE_PUBLIC int linphone_core_set_video_codecs(LinphoneCore *lc, MSList *cod
|
|||
*/
|
||||
LINPHONE_PUBLIC bool_t linphone_core_payload_type_enabled(LinphoneCore *lc, const PayloadType *pt);
|
||||
|
||||
/**
|
||||
* Tells whether the specified payload type represents a variable bitrate codec.
|
||||
* @param[in] lc #LinphoneCore object.
|
||||
* @param[in] pt The #PayloadType we want to know
|
||||
* @returns TRUE if the payload type represents a VBR codec, FALSE if disabled.
|
||||
* @ingroup media_parameters
|
||||
*/
|
||||
LINPHONE_PUBLIC bool_t linphone_core_payload_type_is_vbr(LinphoneCore *lc, const PayloadType *pt);
|
||||
|
||||
/**
|
||||
* Set an explicit bitrate (IP bitrate, not codec bitrate) for a given codec, in kbit/s.
|
||||
* @param[in] lc the #LinphoneCore object
|
||||
* @param[in] pt the #PayloadType to modify.
|
||||
* @param[in] bitrate the IP bitrate in kbit/s.
|
||||
* @ingroup media_parameters
|
||||
**/
|
||||
LINPHONE_PUBLIC void linphone_core_set_payload_type_bitrate(LinphoneCore *lc, PayloadType *pt, int bitrate);
|
||||
|
||||
/**
|
||||
* Get the bitrate explicitely set with linphone_core_set_payload_type_bitrate().
|
||||
* @param[in] lc the #LinphoneCore object
|
||||
* @param[in] pt the #PayloadType to modify.
|
||||
* @return bitrate the IP bitrate in kbit/s, or -1 if an error occured.
|
||||
* @ingroup media_parameters
|
||||
**/
|
||||
LINPHONE_PUBLIC int linphone_core_get_payload_type_bitrate(LinphoneCore *lc, const PayloadType *pt);
|
||||
|
||||
/**
|
||||
* Enable or disable the use of the specified payload type.
|
||||
* @param[in] lc #LinphoneCore object.
|
||||
|
|
@ -1592,7 +1645,7 @@ LINPHONE_PUBLIC int linphone_core_get_payload_type_number(LinphoneCore *lc, cons
|
|||
|
||||
LINPHONE_PUBLIC const char *linphone_core_get_payload_type_description(LinphoneCore *lc, PayloadType *pt);
|
||||
|
||||
LINPHONE_PUBLIC bool_t linphone_core_check_payload_type_usability(LinphoneCore *lc, PayloadType *pt);
|
||||
LINPHONE_PUBLIC bool_t linphone_core_check_payload_type_usability(LinphoneCore *lc, const PayloadType *pt);
|
||||
|
||||
/**
|
||||
* Create a proxy config with default values from Linphone core.
|
||||
|
|
|
|||
|
|
@ -1240,6 +1240,22 @@ extern "C" jboolean Java_org_linphone_core_LinphoneCoreImpl_isPayloadTypeEnabled
|
|||
,jlong pt) {
|
||||
return (jboolean) linphone_core_payload_type_enabled((LinphoneCore*)lc, (PayloadType*)pt);
|
||||
}
|
||||
|
||||
extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setPayloadTypeBitrate(JNIEnv* env
|
||||
,jobject thiz
|
||||
,jlong lc
|
||||
,jlong pt
|
||||
,jint bitrate) {
|
||||
linphone_core_set_payload_type_bitrate((LinphoneCore*)lc,(PayloadType*)pt,bitrate);
|
||||
}
|
||||
|
||||
extern "C" jint Java_org_linphone_core_LinphoneCoreImpl_getPayloadTypeBitrate(JNIEnv* env
|
||||
,jobject thiz
|
||||
,jlong lc
|
||||
,jlong pt) {
|
||||
return (jint)linphone_core_get_payload_type_bitrate((LinphoneCore*)lc,(PayloadType*)pt);
|
||||
}
|
||||
|
||||
extern "C" void Java_org_linphone_core_LinphoneCoreImpl_enableEchoCancellation(JNIEnv* env
|
||||
,jobject thiz
|
||||
,jlong lc
|
||||
|
|
|
|||
|
|
@ -63,6 +63,7 @@ typedef struct _LpSection{
|
|||
} LpSection;
|
||||
|
||||
struct _LpConfig{
|
||||
int refcnt;
|
||||
FILE *file;
|
||||
char *filename;
|
||||
MSList *sections;
|
||||
|
|
@ -293,6 +294,8 @@ LpConfig * lp_config_new_from_buffer(const char *buffer){
|
|||
char* strtok_storage = NULL;
|
||||
char* line = strtok_r(ptr, "\n", &strtok_storage);
|
||||
|
||||
conf->refcnt=1;
|
||||
|
||||
while( line != NULL ){
|
||||
current_section = lp_config_parse_line(conf,line,current_section);
|
||||
line = strtok_r(NULL, "\n", &strtok_storage);
|
||||
|
|
@ -305,7 +308,7 @@ LpConfig * lp_config_new_from_buffer(const char *buffer){
|
|||
|
||||
LpConfig *lp_config_new_with_factory(const char *config_filename, const char *factory_config_filename) {
|
||||
LpConfig *lpconfig=lp_new0(LpConfig,1);
|
||||
|
||||
lpconfig->refcnt=1;
|
||||
if (config_filename!=NULL){
|
||||
ms_message("Using (r/w) config information from %s", config_filename);
|
||||
lpconfig->filename=ortp_strdup(config_filename);
|
||||
|
|
@ -354,13 +357,28 @@ void lp_item_set_value(LpItem *item, const char *value){
|
|||
}
|
||||
|
||||
|
||||
void lp_config_destroy(LpConfig *lpconfig){
|
||||
static void _lp_config_destroy(LpConfig *lpconfig){
|
||||
if (lpconfig->filename!=NULL) ortp_free(lpconfig->filename);
|
||||
ms_list_for_each(lpconfig->sections,(void (*)(void*))lp_section_destroy);
|
||||
ms_list_free(lpconfig->sections);
|
||||
free(lpconfig);
|
||||
}
|
||||
|
||||
LpConfig *lp_config_ref(LpConfig *lpconfig){
|
||||
lpconfig->refcnt++;
|
||||
return lpconfig;
|
||||
}
|
||||
|
||||
void lp_config_unref(LpConfig *lpconfig){
|
||||
lpconfig->refcnt--;
|
||||
if (lpconfig->refcnt==0)
|
||||
_lp_config_destroy(lpconfig);
|
||||
}
|
||||
|
||||
void lp_config_destroy(LpConfig *lpconfig){
|
||||
lp_config_unref(lpconfig);
|
||||
}
|
||||
|
||||
void lp_section_remove_item(LpSection *sec, LpItem *item){
|
||||
sec->items=ms_list_remove(sec->items,(void *)item);
|
||||
lp_item_destroy(item);
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ extern "C" {
|
|||
|
||||
/**
|
||||
* Instantiates a LpConfig object from a user config file.
|
||||
*
|
||||
* The caller of this constructor owns a reference. lp_config_unref() must be called when this object is no longer needed.
|
||||
* @ingroup misc
|
||||
* @param filename the filename of the config file to read to fill the instantiated LpConfig
|
||||
* @see lp_config_new_with_factory
|
||||
|
|
@ -66,7 +66,7 @@ LINPHONE_PUBLIC LpConfig * lp_config_new(const char *filename);
|
|||
|
||||
/**
|
||||
* Instantiates a LpConfig object from a user provided buffer.
|
||||
*
|
||||
* The caller of this constructor owns a reference. lp_config_unref() must be called when this object is no longer needed.
|
||||
* @ingroup misc
|
||||
* @param buffer the buffer from which the lpconfig will be retrieved. We expect the buffer to be null-terminated.
|
||||
* @see lp_config_new_with_factory
|
||||
|
|
@ -76,7 +76,7 @@ LINPHONE_PUBLIC LpConfig * lp_config_new_from_buffer(const char *buffer);
|
|||
|
||||
/**
|
||||
* Instantiates a LpConfig object from a user config file and a factory config file.
|
||||
*
|
||||
* The caller of this constructor owns a reference. lp_config_unref() must be called when this object is no longer needed.
|
||||
* @ingroup misc
|
||||
* @param config_filename the filename of the user config file to read to fill the instantiated LpConfig
|
||||
* @param factory_config_filename the filename of the factory config file to read to fill the instantiated LpConfig
|
||||
|
|
@ -259,6 +259,19 @@ LINPHONE_PUBLIC const char* lp_config_get_default_string(const LpConfig *lpconfi
|
|||
**/
|
||||
LINPHONE_PUBLIC const char* lp_config_get_section_param_string(const LpConfig *lpconfig, const char *section, const char *key, const char *default_value);
|
||||
|
||||
|
||||
/**
|
||||
* increment reference count
|
||||
* @ingroup misc
|
||||
**/
|
||||
LINPHONE_PUBLIC LpConfig *lp_config_ref(LpConfig *lpconfig);
|
||||
|
||||
/**
|
||||
* Decrement reference count, which will eventually free the object.
|
||||
* @ingroup misc
|
||||
**/
|
||||
LINPHONE_PUBLIC void lp_config_unref(LpConfig *lpconfig);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
228
coreapi/misc.c
228
coreapi/misc.c
|
|
@ -77,6 +77,11 @@ bool_t linphone_core_payload_type_enabled(LinphoneCore *lc, const PayloadType *p
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
bool_t linphone_core_payload_type_is_vbr(LinphoneCore *lc, const PayloadType *pt){
|
||||
if (pt->type==PAYLOAD_VIDEO) return TRUE;
|
||||
return !!(pt->flags & PAYLOAD_TYPE_IS_VBR);
|
||||
}
|
||||
|
||||
int linphone_core_enable_payload_type(LinphoneCore *lc, PayloadType *pt, bool_t enabled){
|
||||
if (ms_list_find(lc->codecs_conf.audio_codecs,pt) || ms_list_find(lc->codecs_conf.video_codecs,pt)){
|
||||
payload_type_set_enable(pt,enabled);
|
||||
|
|
@ -88,7 +93,7 @@ int linphone_core_enable_payload_type(LinphoneCore *lc, PayloadType *pt, bool_t
|
|||
}
|
||||
|
||||
int linphone_core_get_payload_type_number(LinphoneCore *lc, const PayloadType *pt){
|
||||
return payload_type_get_number(pt);
|
||||
return payload_type_get_number(pt);
|
||||
}
|
||||
|
||||
const char *linphone_core_get_payload_type_description(LinphoneCore *lc, PayloadType *pt){
|
||||
|
|
@ -103,77 +108,134 @@ const char *linphone_core_get_payload_type_description(LinphoneCore *lc, Payload
|
|||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/*this function makes a special case for speex/8000.
|
||||
This codec is variable bitrate. The 8kbit/s mode is interesting when having a low upload bandwidth, but its quality
|
||||
is not very good. We 'd better use its 15kbt/s mode when we have enough bandwidth*/
|
||||
static int get_codec_bitrate(LinphoneCore *lc, const PayloadType *pt){
|
||||
int upload_bw=linphone_core_get_upload_bandwidth(lc);
|
||||
if (bandwidth_is_greater(upload_bw,129) || (bandwidth_is_greater(upload_bw,33) && !linphone_core_video_enabled(lc)) ) {
|
||||
if (strcmp(pt->mime_type,"speex")==0 && pt->clock_rate==8000){
|
||||
return 15000;
|
||||
void linphone_core_set_payload_type_bitrate(LinphoneCore *lc, PayloadType *pt, int bitrate){
|
||||
if (ms_list_find(lc->codecs_conf.audio_codecs, (PayloadType*) pt) || ms_list_find(lc->codecs_conf.video_codecs, (PayloadType*)pt)){
|
||||
if (pt->type==PAYLOAD_VIDEO || pt->flags & PAYLOAD_TYPE_IS_VBR){
|
||||
pt->normal_bitrate=bitrate*1000;
|
||||
pt->flags|=PAYLOAD_TYPE_BITRATE_OVERRIDE;
|
||||
}else{
|
||||
ms_error("Cannot set an explicit bitrate for codec %s/%i, because it is not VBR.",pt->mime_type,pt->clock_rate);
|
||||
return;
|
||||
}
|
||||
}
|
||||
return pt->normal_bitrate;
|
||||
ms_error("linphone_core_set_payload_type_bitrate() payload type not in audio or video list !");
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*((codec-birate*ptime/8) + RTP header + UDP header + IP header)*8/ptime;
|
||||
*ptime=1/npacket
|
||||
*/
|
||||
static double get_audio_payload_bandwidth(LinphoneCore *lc, const PayloadType *pt){
|
||||
|
||||
static double get_audio_payload_bandwidth_from_codec_bitrate(const PayloadType *pt){
|
||||
double npacket=50;
|
||||
double packet_size;
|
||||
int bitrate;
|
||||
|
||||
if (strcmp(payload_type_get_mime(&payload_type_aaceld_44k), payload_type_get_mime(pt))==0) {
|
||||
/*special case of aac 44K because ptime= 10ms*/
|
||||
npacket=100;
|
||||
}else if (strcmp(payload_type_get_mime(&payload_type_ilbc), payload_type_get_mime(pt))==0) {
|
||||
npacket=1000/30.0;
|
||||
}
|
||||
|
||||
bitrate=get_codec_bitrate(lc,pt);
|
||||
|
||||
bitrate=pt->normal_bitrate;
|
||||
packet_size= (((double)bitrate)/(npacket*8))+UDP_HDR_SZ+RTP_HDR_SZ+IP4_HDR_SZ;
|
||||
return packet_size*8.0*npacket;
|
||||
}
|
||||
|
||||
void linphone_core_update_allocated_audio_bandwidth_in_call(LinphoneCall *call, const PayloadType *pt){
|
||||
call->audio_bw=(int)(ceil(get_audio_payload_bandwidth(call->core,pt)/1000.0)); /*rounding codec bandwidth should be avoid, specially for AMR*/
|
||||
typedef struct vbr_codec_bitrate{
|
||||
int max_avail_bitrate;
|
||||
int min_rate;
|
||||
int recomended_bitrate;
|
||||
}vbr_codec_bitrate_t;
|
||||
|
||||
static vbr_codec_bitrate_t defauls_vbr[]={
|
||||
//{ 100, 44100, 100 },
|
||||
{ 64, 44100, 50 },
|
||||
{ 64, 16000, 40 },
|
||||
{ 32, 16000, 32 },
|
||||
{ 32, 8000, 32 },
|
||||
{ 0 , 8000, 24 },
|
||||
{ 0 , 0, 0 }
|
||||
};
|
||||
|
||||
static int lookup_vbr_typical_bitrate(int maxbw, int clock_rate){
|
||||
vbr_codec_bitrate_t *it;
|
||||
if (maxbw<=0) maxbw=defauls_vbr[0].max_avail_bitrate;
|
||||
for(it=defauls_vbr;it->min_rate!=0;it++){
|
||||
if (maxbw>=it->max_avail_bitrate && clock_rate>=it->min_rate)
|
||||
return it->recomended_bitrate;
|
||||
}
|
||||
ms_error("lookup_vbr_typical_bitrate(): should not happen.");
|
||||
return 32;
|
||||
}
|
||||
|
||||
static int get_audio_payload_bandwidth(LinphoneCore *lc, const PayloadType *pt, int maxbw){
|
||||
if (linphone_core_payload_type_is_vbr(lc,pt)){
|
||||
if (pt->flags & PAYLOAD_TYPE_BITRATE_OVERRIDE){
|
||||
ms_message("PayloadType %s/%i has bitrate override",pt->mime_type,pt->clock_rate);
|
||||
return pt->normal_bitrate/1000;
|
||||
}
|
||||
return lookup_vbr_typical_bitrate(maxbw,pt->clock_rate);
|
||||
}else return (int)ceil(get_audio_payload_bandwidth_from_codec_bitrate(pt)/1000.0);/*rounding codec bandwidth should be avoid, specially for AMR*/
|
||||
}
|
||||
|
||||
int linphone_core_get_payload_type_bitrate(LinphoneCore *lc, const PayloadType *pt){
|
||||
int maxbw=get_min_bandwidth(linphone_core_get_download_bandwidth(lc),
|
||||
linphone_core_get_upload_bandwidth(lc));
|
||||
if (pt->type==PAYLOAD_AUDIO_CONTINUOUS || pt->type==PAYLOAD_AUDIO_PACKETIZED){
|
||||
return get_audio_payload_bandwidth(lc,pt,maxbw);
|
||||
}else if (pt->type==PAYLOAD_VIDEO){
|
||||
int video_bw;
|
||||
linphone_core_update_allocated_audio_bandwidth(lc);
|
||||
if (maxbw<=0) {
|
||||
video_bw=1500; /*default bitrate for video stream when no bandwidth limit is set, around 1.5 Mbit/s*/
|
||||
}else{
|
||||
video_bw=get_remaining_bandwidth_for_video(maxbw,lc->audio_bw);
|
||||
}
|
||||
return video_bw;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void linphone_core_update_allocated_audio_bandwidth_in_call(LinphoneCall *call, const PayloadType *pt, int maxbw){
|
||||
call->audio_bw=get_audio_payload_bandwidth(call->core,pt,maxbw);
|
||||
ms_message("Audio bandwidth for this call is %i",call->audio_bw);
|
||||
}
|
||||
|
||||
void linphone_core_update_allocated_audio_bandwidth(LinphoneCore *lc){
|
||||
const MSList *elem;
|
||||
PayloadType *max=NULL;
|
||||
int maxbw=get_min_bandwidth(linphone_core_get_download_bandwidth(lc),
|
||||
linphone_core_get_upload_bandwidth(lc));
|
||||
int max_codec_bitrate=0;
|
||||
|
||||
for(elem=linphone_core_get_audio_codecs(lc);elem!=NULL;elem=elem->next){
|
||||
PayloadType *pt=(PayloadType*)elem->data;
|
||||
if (payload_type_enabled(pt)){
|
||||
int pt_bitrate=get_codec_bitrate(lc,pt);
|
||||
if (max==NULL) max=pt;
|
||||
else if (max->normal_bitrate<pt_bitrate){
|
||||
max=pt;
|
||||
int pt_bitrate=get_audio_payload_bandwidth(lc,pt,maxbw);
|
||||
if (max_codec_bitrate==0) {
|
||||
max_codec_bitrate=pt_bitrate;
|
||||
}else if (max_codec_bitrate<pt_bitrate){
|
||||
max_codec_bitrate=pt_bitrate;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (max) {
|
||||
lc->audio_bw=(int)(get_audio_payload_bandwidth(lc,max)/1000.0);
|
||||
if (max_codec_bitrate) {
|
||||
lc->audio_bw=max_codec_bitrate;
|
||||
}
|
||||
}
|
||||
|
||||
bool_t linphone_core_is_payload_type_usable_for_bandwidth(LinphoneCore *lc, PayloadType *pt, int bandwidth_limit)
|
||||
bool_t linphone_core_is_payload_type_usable_for_bandwidth(LinphoneCore *lc, const PayloadType *pt, int bandwidth_limit)
|
||||
{
|
||||
double codec_band;
|
||||
bool_t ret=FALSE;
|
||||
|
||||
|
||||
switch (pt->type){
|
||||
case PAYLOAD_AUDIO_CONTINUOUS:
|
||||
case PAYLOAD_AUDIO_PACKETIZED:
|
||||
codec_band=get_audio_payload_bandwidth(lc,pt);
|
||||
codec_band=get_audio_payload_bandwidth(lc,pt,bandwidth_limit);
|
||||
ret=bandwidth_is_greater(bandwidth_limit*1000,codec_band);
|
||||
/*hack to avoid using uwb codecs when having low bitrate and video*/
|
||||
if (bandwidth_is_greater(199,bandwidth_limit)){
|
||||
if (linphone_core_video_enabled(lc) && pt->clock_rate>16000){
|
||||
ret=FALSE;
|
||||
}
|
||||
}
|
||||
//ms_message("Payload %s: %g",pt->mime_type,codec_band);
|
||||
break;
|
||||
case PAYLOAD_VIDEO:
|
||||
|
|
@ -187,43 +249,8 @@ bool_t linphone_core_is_payload_type_usable_for_bandwidth(LinphoneCore *lc, Payl
|
|||
}
|
||||
|
||||
/* return TRUE if codec can be used with bandwidth, FALSE else*/
|
||||
bool_t linphone_core_check_payload_type_usability(LinphoneCore *lc, PayloadType *pt)
|
||||
{
|
||||
double codec_band;
|
||||
int allowed_bw,video_bw;
|
||||
bool_t ret=FALSE;
|
||||
|
||||
linphone_core_update_allocated_audio_bandwidth(lc);
|
||||
allowed_bw=get_min_bandwidth(linphone_core_get_download_bandwidth(lc),
|
||||
linphone_core_get_upload_bandwidth(lc));
|
||||
if (allowed_bw==0) {
|
||||
allowed_bw=-1;
|
||||
video_bw=1500; /*around 1.5 Mbit/s*/
|
||||
}else
|
||||
video_bw=get_video_bandwidth(allowed_bw,lc->audio_bw);
|
||||
|
||||
switch (pt->type){
|
||||
case PAYLOAD_AUDIO_CONTINUOUS:
|
||||
case PAYLOAD_AUDIO_PACKETIZED:
|
||||
codec_band=get_audio_payload_bandwidth(lc,pt);
|
||||
ret=bandwidth_is_greater(allowed_bw*1000,codec_band);
|
||||
/*hack to avoid using uwb codecs when having low bitrate and video*/
|
||||
if (bandwidth_is_greater(199,allowed_bw)){
|
||||
if (linphone_core_video_enabled(lc) && pt->clock_rate>16000){
|
||||
ret=FALSE;
|
||||
}
|
||||
}
|
||||
//ms_message("Payload %s: %g",pt->mime_type,codec_band);
|
||||
break;
|
||||
case PAYLOAD_VIDEO:
|
||||
if (video_bw>0){
|
||||
pt->normal_bitrate=video_bw*1000;
|
||||
ret=TRUE;
|
||||
}
|
||||
else ret=FALSE;
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
bool_t linphone_core_check_payload_type_usability(LinphoneCore *lc, const PayloadType *pt){
|
||||
return linphone_core_is_payload_type_usable_for_bandwidth(lc, pt, linphone_core_get_payload_type_bitrate(lc,pt));
|
||||
}
|
||||
|
||||
bool_t lp_spawn_command_line_sync(const char *command, char **result,int *command_ret){
|
||||
|
|
@ -278,7 +305,7 @@ static int sendStunRequest(int sock, const struct sockaddr *server, socklen_t ad
|
|||
char buf[STUN_MAX_MESSAGE_SIZE];
|
||||
int len = STUN_MAX_MESSAGE_SIZE;
|
||||
StunAtrString username;
|
||||
StunAtrString password;
|
||||
StunAtrString password;
|
||||
StunMessage req;
|
||||
int err;
|
||||
memset(&req, 0, sizeof(StunMessage));
|
||||
|
|
@ -301,9 +328,9 @@ static int sendStunRequest(int sock, const struct sockaddr *server, socklen_t ad
|
|||
int linphone_parse_host_port(const char *input, char *host, size_t hostlen, int *port){
|
||||
char tmphost[NI_MAXHOST]={0};
|
||||
char *p1, *p2;
|
||||
|
||||
|
||||
if ((sscanf(input, "[%64[^]]]:%d", tmphost, port) == 2) || (sscanf(input, "[%64[^]]]", tmphost) == 1)) {
|
||||
|
||||
|
||||
} else {
|
||||
p1 = strchr(input, ':');
|
||||
p2 = strrchr(input, ':');
|
||||
|
|
@ -324,9 +351,9 @@ int parse_hostname_to_addr(const char *server, struct sockaddr_storage *ss, sock
|
|||
char host[NI_MAXHOST];
|
||||
int port_int=default_port;
|
||||
int ret;
|
||||
|
||||
|
||||
linphone_parse_host_port(server,host,sizeof(host),&port_int);
|
||||
|
||||
|
||||
snprintf(port, sizeof(port), "%d", port_int);
|
||||
memset(&hints,0,sizeof(hints));
|
||||
hints.ai_family=AF_UNSPEC;
|
||||
|
|
@ -346,7 +373,7 @@ int parse_hostname_to_addr(const char *server, struct sockaddr_storage *ss, sock
|
|||
|
||||
static int recvStunResponse(ortp_socket_t sock, char *ipaddr, int *port, int *id){
|
||||
char buf[STUN_MAX_MESSAGE_SIZE];
|
||||
int len = STUN_MAX_MESSAGE_SIZE;
|
||||
int len = STUN_MAX_MESSAGE_SIZE;
|
||||
StunMessage resp;
|
||||
len=recv(sock,buf,len,0);
|
||||
if (len>0){
|
||||
|
|
@ -370,7 +397,7 @@ int linphone_core_run_stun_tests(LinphoneCore *lc, LinphoneCall *call){
|
|||
const char *server=linphone_core_get_stun_server(lc);
|
||||
StunCandidate *ac=&call->ac;
|
||||
StunCandidate *vc=&call->vc;
|
||||
|
||||
|
||||
if (lc->sip_conf.ipv6_enabled){
|
||||
ms_warning("stun support is not implemented for ipv6");
|
||||
return -1;
|
||||
|
|
@ -389,7 +416,7 @@ int linphone_core_run_stun_tests(LinphoneCore *lc, LinphoneCall *call){
|
|||
struct timeval init,cur;
|
||||
double elapsed;
|
||||
int ret=0;
|
||||
|
||||
|
||||
if (ai==NULL){
|
||||
ms_error("Could not obtain stun server addrinfo.");
|
||||
return -1;
|
||||
|
|
@ -408,7 +435,7 @@ int linphone_core_run_stun_tests(LinphoneCore *lc, LinphoneCall *call){
|
|||
got_video=FALSE;
|
||||
ortp_gettimeofday(&init,NULL);
|
||||
do{
|
||||
|
||||
|
||||
int id;
|
||||
if (loops%20==0){
|
||||
ms_message("Sending stun requests...");
|
||||
|
|
@ -487,7 +514,7 @@ void linphone_core_adapt_to_network(LinphoneCore *lc, int ping_time_ms, Linphone
|
|||
if (ping_time_ms>0 && lp_config_get_int(lc->config,"net","activate_edge_workarounds",0)==1){
|
||||
ms_message("Stun server ping time is %i ms",ping_time_ms);
|
||||
threshold=lp_config_get_int(lc->config,"net","edge_ping_time",500);
|
||||
|
||||
|
||||
if (ping_time_ms>threshold){
|
||||
/* we might be in a 2G network*/
|
||||
params->low_bandwidth=TRUE;
|
||||
|
|
@ -536,7 +563,7 @@ void linphone_core_resolve_stun_server(LinphoneCore *lc){
|
|||
* - have a cache of the stun server addrinfo
|
||||
* - this cached value is returned when it is non-null
|
||||
* - an asynchronous resolution is asked each time this function is called to ensure frequent refreshes of the cached value.
|
||||
* - if no cached value exists, block for a short time; this case must be unprobable because the resolution will be asked each time the stun server value is
|
||||
* - if no cached value exists, block for a short time; this case must be unprobable because the resolution will be asked each time the stun server value is
|
||||
* changed.
|
||||
**/
|
||||
const struct addrinfo *linphone_core_get_stun_server_addrinfo(LinphoneCore *lc){
|
||||
|
|
@ -957,7 +984,7 @@ unsigned int linphone_core_get_audio_features(LinphoneCore *lc){
|
|||
p=n;
|
||||
}
|
||||
}else ret=AUDIO_STREAM_FEATURE_ALL;
|
||||
|
||||
|
||||
if (ret==AUDIO_STREAM_FEATURE_ALL){
|
||||
/*since call recording is specified before creation of the stream in linphonecore,
|
||||
* it will be requested on demand. It is not necessary to include it all the time*/
|
||||
|
|
@ -973,12 +1000,12 @@ bool_t linphone_core_tone_indications_enabled(LinphoneCore*lc){
|
|||
#ifdef HAVE_GETIFADDRS
|
||||
|
||||
#include <ifaddrs.h>
|
||||
static int get_local_ip_with_getifaddrs(int type, char *address, int size)
|
||||
{
|
||||
static int get_local_ip_with_getifaddrs(int type, char *address, int size){
|
||||
struct ifaddrs *ifp;
|
||||
struct ifaddrs *ifpstart;
|
||||
int ret = 0;
|
||||
|
||||
char retaddr[LINPHONE_IPADDR_SIZE]={0};
|
||||
bool_t found=FALSE;
|
||||
|
||||
if (getifaddrs(&ifpstart) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
|
@ -987,7 +1014,7 @@ static int get_local_ip_with_getifaddrs(int type, char *address, int size)
|
|||
#else
|
||||
#define UP_FLAG IFF_RUNNING /* resources allocated */
|
||||
#endif
|
||||
|
||||
|
||||
for (ifp = ifpstart; ifp != NULL; ifp = ifp->ifa_next) {
|
||||
if (ifp->ifa_addr && ifp->ifa_addr->sa_family == type
|
||||
&& (ifp->ifa_flags & UP_FLAG) && !(ifp->ifa_flags & IFF_LOOPBACK))
|
||||
|
|
@ -995,17 +1022,18 @@ static int get_local_ip_with_getifaddrs(int type, char *address, int size)
|
|||
if(getnameinfo(ifp->ifa_addr,
|
||||
(type == AF_INET6) ?
|
||||
sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in),
|
||||
address, size, NULL, 0, NI_NUMERICHOST) == 0) {
|
||||
if (strchr(address, '%') == NULL) { /*avoid ipv6 link-local addresses */
|
||||
retaddr, size, NULL, 0, NI_NUMERICHOST) == 0) {
|
||||
if (strchr(retaddr, '%') == NULL) { /*avoid ipv6 link-local addresses */
|
||||
/*ms_message("getifaddrs() found %s",address);*/
|
||||
ret++;
|
||||
found=TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
freeifaddrs(ifpstart);
|
||||
return ret;
|
||||
if (found) strncpy(address,retaddr,size);
|
||||
return found;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -1042,8 +1070,8 @@ static int get_local_ip_for_with_connect(int type, const char *dest, char *resul
|
|||
if (err<0) {
|
||||
/*the network isn't reachable*/
|
||||
if (getSocketErrorCode()!=ENETUNREACH) ms_error("Error in connect: %s",strerror(errno));
|
||||
freeaddrinfo(res);
|
||||
close_socket(sock);
|
||||
freeaddrinfo(res);
|
||||
close_socket(sock);
|
||||
return -1;
|
||||
}
|
||||
freeaddrinfo(res);
|
||||
|
|
@ -1067,7 +1095,7 @@ static int get_local_ip_for_with_connect(int type, const char *dest, char *resul
|
|||
ms_error("getnameinfo error: %s",strerror(errno));
|
||||
}
|
||||
/*avoid ipv6 link-local addresses*/
|
||||
if (type==AF_INET6 && strchr(result,'%')!=NULL){
|
||||
if (p_addr->sa_family==AF_INET6 && strchr(result,'%')!=NULL){
|
||||
strcpy(result,"::1");
|
||||
close_socket(sock);
|
||||
return -1;
|
||||
|
|
@ -1078,19 +1106,19 @@ static int get_local_ip_for_with_connect(int type, const char *dest, char *resul
|
|||
|
||||
int linphone_core_get_local_ip_for(int type, const char *dest, char *result){
|
||||
int err;
|
||||
strcpy(result,type==AF_INET ? "127.0.0.1" : "::1");
|
||||
|
||||
strcpy(result,type==AF_INET ? "127.0.0.1" : "::1");
|
||||
|
||||
if (dest==NULL){
|
||||
if (type==AF_INET)
|
||||
dest="87.98.157.38"; /*a public IP address*/
|
||||
else dest="2a00:1450:8002::68";
|
||||
}
|
||||
err=get_local_ip_for_with_connect(type,dest,result);
|
||||
err=get_local_ip_for_with_connect(type,dest,result);
|
||||
if (err==0) return 0;
|
||||
|
||||
/* if the connect method failed, which happens when no default route is set,
|
||||
|
||||
/* if the connect method failed, which happens when no default route is set,
|
||||
* try to find 'the' running interface with getifaddrs*/
|
||||
|
||||
|
||||
#ifdef HAVE_GETIFADDRS
|
||||
/*we use getifaddrs for lookup of default interface */
|
||||
int found_ifs;
|
||||
|
|
@ -1103,7 +1131,7 @@ int linphone_core_get_local_ip_for(int type, const char *dest, char *result){
|
|||
return -1;
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
SalReason linphone_reason_to_sal(LinphoneReason reason){
|
||||
|
|
|
|||
|
|
@ -39,11 +39,20 @@ static PayloadType * find_payload_type_best_match(const MSList *l, const Payload
|
|||
|
||||
for (elem=l;elem!=NULL;elem=elem->next){
|
||||
pt=(PayloadType*)elem->data;
|
||||
|
||||
/*workaround a bug in earlier versions of linphone where opus/48000/1 is offered, which is uncompliant with opus rtp draft*/
|
||||
if (refpt->mime_type && strcasecmp(refpt->mime_type,"opus")==0 && refpt->channels==1
|
||||
&& strcasecmp(pt->mime_type,refpt->mime_type)==0){
|
||||
pt->channels=1; /*so that we respond with same number of channels */
|
||||
candidate=pt;
|
||||
break;
|
||||
}
|
||||
|
||||
/* the compare between G729 and G729A is for some stupid uncompliant phone*/
|
||||
if ( pt->mime_type && refpt->mime_type &&
|
||||
(strcasecmp(pt->mime_type,refpt->mime_type)==0 ||
|
||||
(strcasecmp(pt->mime_type, "G729") == 0 && strcasecmp(refpt->mime_type, "G729A") == 0 ))
|
||||
&& pt->clock_rate==refpt->clock_rate){
|
||||
(strcasecmp(pt->mime_type, "G729") == 0 && strcasecmp(refpt->mime_type, "G729A") == 0 ))
|
||||
&& pt->clock_rate==refpt->clock_rate && pt->channels==refpt->channels){
|
||||
candidate=pt;
|
||||
/*good candidate, check fmtp for H264 */
|
||||
if (strcasecmp(pt->mime_type,"H264")==0){
|
||||
|
|
@ -56,7 +65,7 @@ static PayloadType * find_payload_type_best_match(const MSList *l, const Payload
|
|||
mode2=atoi(value);
|
||||
}
|
||||
if (mode1==mode2)
|
||||
break; /*exact match */
|
||||
break; /*exact match */
|
||||
}
|
||||
}else break;
|
||||
}
|
||||
|
|
@ -69,7 +78,7 @@ static MSList *match_payloads(const MSList *local, const MSList *remote, bool_t
|
|||
MSList *res=NULL;
|
||||
PayloadType *matched;
|
||||
bool_t found_codec=FALSE;
|
||||
|
||||
|
||||
for(e2=remote;e2!=NULL;e2=e2->next){
|
||||
PayloadType *p2=(PayloadType*)e2->data;
|
||||
matched=find_payload_type_best_match(local,p2);
|
||||
|
|
@ -85,7 +94,7 @@ static MSList *match_payloads(const MSList *local, const MSList *remote, bool_t
|
|||
}else found_codec=TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
newp=payload_type_clone(matched);
|
||||
if (p2->send_fmtp)
|
||||
payload_type_set_send_fmtp(newp,p2->send_fmtp);
|
||||
|
|
@ -95,7 +104,7 @@ static MSList *match_payloads(const MSList *local, const MSList *remote, bool_t
|
|||
payload_type_set_number(newp,remote_number);
|
||||
if (reading_response && remote_number!=local_number){
|
||||
ms_warning("For payload type %s, proposed number was %i but the remote phone answered %i",
|
||||
newp->mime_type, local_number, remote_number);
|
||||
newp->mime_type, local_number, remote_number);
|
||||
/*
|
||||
We must add this payload type with our local numbering in order to be able to receive it.
|
||||
Indeed despite we must sent with the remote numbering, we must be able to receive with
|
||||
|
|
@ -106,7 +115,9 @@ static MSList *match_payloads(const MSList *local, const MSList *remote, bool_t
|
|||
res=ms_list_append(res,newp);
|
||||
}
|
||||
}else{
|
||||
ms_message("No match for %s/%i",p2->mime_type,p2->clock_rate);
|
||||
if (p2->channels>0)
|
||||
ms_message("No match for %s/%i/%i",p2->mime_type,p2->clock_rate,p2->channels);
|
||||
else ms_message("No match for %s/%i",p2->mime_type,p2->clock_rate);
|
||||
}
|
||||
}
|
||||
if (reading_response){
|
||||
|
|
@ -132,28 +143,28 @@ static MSList *match_payloads(const MSList *local, const MSList *remote, bool_t
|
|||
return res;
|
||||
}
|
||||
|
||||
static bool_t match_crypto_algo(const SalSrtpCryptoAlgo* local, const SalSrtpCryptoAlgo* remote,
|
||||
static bool_t match_crypto_algo(const SalSrtpCryptoAlgo* local, const SalSrtpCryptoAlgo* remote,
|
||||
SalSrtpCryptoAlgo* result, unsigned int* choosen_local_tag, bool_t use_local_key) {
|
||||
int i,j;
|
||||
for(i=0; i<SAL_CRYPTO_ALGO_MAX; i++) {
|
||||
if (remote[i].algo == 0)
|
||||
break;
|
||||
|
||||
/* Look for a local enabled crypto algo that matches one of the proposed by remote */
|
||||
/* Look for a local enabled crypto algo that matches one of the proposed by remote */
|
||||
for(j=0; j<SAL_CRYPTO_ALGO_MAX; j++) {
|
||||
if (remote[i].algo == local[j].algo) {
|
||||
result->algo = remote[i].algo;
|
||||
/* We're answering an SDP offer. Supply our master key, associated with the remote supplied tag */
|
||||
/* We're answering an SDP offer. Supply our master key, associated with the remote supplied tag */
|
||||
if (use_local_key) {
|
||||
strncpy(result->master_key, local[j].master_key, 41);
|
||||
result->tag = remote[i].tag;
|
||||
*choosen_local_tag = local[j].tag;
|
||||
*choosen_local_tag = local[j].tag;
|
||||
}
|
||||
/* We received an answer to our SDP crypto proposal. Copy matching algo remote master key to result, and memorize local tag */
|
||||
else {
|
||||
else {
|
||||
strncpy(result->master_key, remote[i].master_key, 41);
|
||||
result->tag = local[j].tag;
|
||||
*choosen_local_tag = local[j].tag;
|
||||
*choosen_local_tag = local[j].tag;
|
||||
}
|
||||
result->master_key[40] = '\0';
|
||||
return TRUE;
|
||||
|
|
@ -205,8 +216,8 @@ static SalStreamDir compute_dir_incoming(SalStreamDir local, SalStreamDir offere
|
|||
}
|
||||
|
||||
static void initiate_outgoing(const SalStreamDescription *local_offer,
|
||||
const SalStreamDescription *remote_answer,
|
||||
SalStreamDescription *result){
|
||||
const SalStreamDescription *remote_answer,
|
||||
SalStreamDescription *result){
|
||||
if (remote_answer->rtp_port!=0)
|
||||
result->payloads=match_payloads(local_offer->payloads,remote_answer->payloads,TRUE,FALSE);
|
||||
result->proto=remote_answer->proto;
|
||||
|
|
@ -233,8 +244,8 @@ static void initiate_outgoing(const SalStreamDescription *local_offer,
|
|||
|
||||
|
||||
static void initiate_incoming(const SalStreamDescription *local_cap,
|
||||
const SalStreamDescription *remote_offer,
|
||||
SalStreamDescription *result, bool_t one_matching_codec){
|
||||
const SalStreamDescription *remote_offer,
|
||||
SalStreamDescription *result, bool_t one_matching_codec){
|
||||
result->payloads=match_payloads(local_cap->payloads,remote_offer->payloads, FALSE, one_matching_codec);
|
||||
result->proto=remote_offer->proto;
|
||||
result->type=local_cap->type;
|
||||
|
|
@ -254,7 +265,7 @@ static void initiate_incoming(const SalStreamDescription *local_cap,
|
|||
memset(result->crypto, 0, sizeof(result->crypto));
|
||||
if (!match_crypto_algo(local_cap->crypto, remote_offer->crypto, &result->crypto[0], &result->crypto_local_tag, TRUE))
|
||||
result->rtp_port = 0;
|
||||
|
||||
|
||||
}
|
||||
strcpy(result->ice_pwd, local_cap->ice_pwd);
|
||||
strcpy(result->ice_ufrag, local_cap->ice_ufrag);
|
||||
|
|
@ -388,7 +399,7 @@ int offer_answer_initiate_incoming(const SalMediaDescription *local_capabilities
|
|||
strcpy(result->ice_ufrag, local_capabilities->ice_ufrag);
|
||||
result->ice_lite = local_capabilities->ice_lite;
|
||||
result->ice_completed = local_capabilities->ice_completed;
|
||||
|
||||
|
||||
strcpy(result->name,local_capabilities->name);
|
||||
|
||||
// Handle session RTCP XR attribute
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
#ifndef offeranswer_h
|
||||
#define offeranswer_h
|
||||
|
||||
/**
|
||||
/**
|
||||
This header files defines the SDP offer answer API.
|
||||
It can be used by implementations of SAL directly.
|
||||
**/
|
||||
|
|
@ -32,7 +32,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
**/
|
||||
int offer_answer_initiate_outgoing(const SalMediaDescription *local_offer,
|
||||
const SalMediaDescription *remote_answer,
|
||||
SalMediaDescription *result);
|
||||
SalMediaDescription *result);
|
||||
|
||||
/**
|
||||
* Returns a media description to run the streams with, based on the local capabilities and
|
||||
|
|
@ -41,7 +41,7 @@ int offer_answer_initiate_outgoing(const SalMediaDescription *local_offer,
|
|||
**/
|
||||
int offer_answer_initiate_incoming(const SalMediaDescription *local_capabilities,
|
||||
const SalMediaDescription *remote_offer,
|
||||
SalMediaDescription *result, bool_t one_matching_codec);
|
||||
|
||||
SalMediaDescription *result, bool_t one_matching_codec);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -170,7 +170,7 @@ static time_t parse_timestamp(const char *timestamp) {
|
|||
return seconds - timezone;
|
||||
}
|
||||
|
||||
static char * timestamp_to_string(time_t timestamp) {
|
||||
char * linphone_timestamp_to_rfc3339_string(time_t timestamp) {
|
||||
char timestamp_str[22];
|
||||
struct tm *ret;
|
||||
#ifndef WIN32
|
||||
|
|
@ -1467,7 +1467,7 @@ void linphone_subscription_new(LinphoneCore *lc, SalOp *op, const char *from){
|
|||
char *tmp;
|
||||
LinphoneAddress *uri;
|
||||
LinphoneProxyConfig *cfg;
|
||||
|
||||
|
||||
uri=linphone_address_new(from);
|
||||
linphone_address_clean(uri);
|
||||
tmp=linphone_address_as_string(uri);
|
||||
|
|
@ -1482,7 +1482,7 @@ void linphone_subscription_new(LinphoneCore *lc, SalOp *op, const char *from){
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* check if we answer to this subscription */
|
||||
if (linphone_find_friend_by_address(lc->friends,uri,&lf)!=NULL){
|
||||
lf->insub=op;
|
||||
|
|
@ -1604,7 +1604,7 @@ static void write_xml_presence_note_obj(LinphonePresenceNote *note, struct _pres
|
|||
|
||||
static int write_xml_presence_timestamp(xmlTextWriterPtr writer, time_t timestamp) {
|
||||
int err;
|
||||
char *timestamp_str = timestamp_to_string(timestamp);
|
||||
char *timestamp_str = linphone_timestamp_to_rfc3339_string(timestamp);
|
||||
err = xmlTextWriterWriteElement(writer, (const xmlChar *)"timestamp", (const xmlChar *)timestamp_str);
|
||||
if (timestamp_str) ms_free(timestamp_str);
|
||||
return err;
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ extern "C" {
|
|||
#include "linphonecore_utils.h"
|
||||
#include "sal/sal.h"
|
||||
#include "sipsetup.h"
|
||||
#include "quality_reporting.h"
|
||||
|
||||
#include <belle-sip/object.h>
|
||||
#include <belle-sip/dict.h>
|
||||
|
|
@ -115,6 +116,8 @@ struct _LinphoneCallLog{
|
|||
float quality;
|
||||
time_t start_date_time; /**Start date of the call in seconds as expressed in a time_t */
|
||||
char* call_id; /**unique id of a call*/
|
||||
|
||||
reporting_session_report_t * reports[2]; /**<Quality statistics of the call (rfc6035) */
|
||||
bool_t video_enabled;
|
||||
};
|
||||
|
||||
|
|
@ -191,6 +194,7 @@ struct _LinphoneCall
|
|||
StunCandidate ac,vc; /*audio video ip/port discovered by STUN*/
|
||||
struct _AudioStream *audiostream; /**/
|
||||
struct _VideoStream *videostream;
|
||||
|
||||
MSAudioEndpoint *endpoint; /*used for conferencing*/
|
||||
char *refer_to;
|
||||
LinphoneCallParams params;
|
||||
|
|
@ -224,8 +228,6 @@ struct _LinphoneCall
|
|||
bool_t owns_call_log;
|
||||
bool_t ringing_beep; /* whether this call is ringing through an already existent current call*/
|
||||
|
||||
bool_t videostream_encrypted;
|
||||
bool_t audiostream_encrypted;
|
||||
bool_t auth_token_verified;
|
||||
bool_t defer_update;
|
||||
|
||||
|
|
@ -290,7 +292,7 @@ static inline bool_t bandwidth_is_greater(int bw1, int bw2){
|
|||
else return bw1>=bw2;
|
||||
}
|
||||
|
||||
static inline int get_video_bandwidth(int total, int audio){
|
||||
static inline int get_remaining_bandwidth_for_video(int total, int audio){
|
||||
if (total<=0) return 0;
|
||||
return total-audio-10;
|
||||
}
|
||||
|
|
@ -305,6 +307,7 @@ static inline void set_string(char **dest, const char *src){
|
|||
}
|
||||
|
||||
#define PAYLOAD_TYPE_ENABLED PAYLOAD_TYPE_USER_FLAG_0
|
||||
#define PAYLOAD_TYPE_BITRATE_OVERRIDE PAYLOAD_TYPE_USER_FLAG_3
|
||||
|
||||
void linphone_process_authentication(LinphoneCore* lc, SalOp *op);
|
||||
void linphone_authentication_ok(LinphoneCore *lc, SalOp *op);
|
||||
|
|
@ -319,7 +322,7 @@ void linphone_subscription_answered(LinphoneCore *lc, SalOp *op);
|
|||
void linphone_subscription_closed(LinphoneCore *lc, SalOp *op);
|
||||
|
||||
void linphone_core_update_allocated_audio_bandwidth(LinphoneCore *lc);
|
||||
void linphone_core_update_allocated_audio_bandwidth_in_call(LinphoneCall *call, const PayloadType *pt);
|
||||
void linphone_core_update_allocated_audio_bandwidth_in_call(LinphoneCall *call, const PayloadType *pt, int maxbw);
|
||||
|
||||
int linphone_core_run_stun_tests(LinphoneCore *lc, LinphoneCall *call);
|
||||
void linphone_core_resolve_stun_server(LinphoneCore *lc);
|
||||
|
|
@ -327,6 +330,7 @@ const struct addrinfo *linphone_core_get_stun_server_addrinfo(LinphoneCore *lc);
|
|||
void linphone_core_adapt_to_network(LinphoneCore *lc, int ping_time_ms, LinphoneCallParams *params);
|
||||
int linphone_core_gather_ice_candidates(LinphoneCore *lc, LinphoneCall *call);
|
||||
void linphone_core_update_ice_state_in_call_stats(LinphoneCall *call);
|
||||
void linphone_call_stats_fill(LinphoneCallStats *stats, MediaStream *ms, OrtpEvent *ev);
|
||||
void linphone_core_update_local_media_description_from_ice(SalMediaDescription *desc, IceSession *session);
|
||||
void linphone_core_update_ice_from_remote_media_description(LinphoneCall *call, const SalMediaDescription *md);
|
||||
bool_t linphone_core_media_description_contains_video_stream(const SalMediaDescription *md);
|
||||
|
|
@ -401,10 +405,12 @@ struct _LinphoneProxyConfig
|
|||
char *reg_proxy;
|
||||
char *reg_identity;
|
||||
char *reg_route;
|
||||
char *statistics_collector;
|
||||
char *realm;
|
||||
char *contact_params;
|
||||
char *contact_uri_params;
|
||||
int expires;
|
||||
int publish_expires;
|
||||
SalOp *op;
|
||||
char *type;
|
||||
struct _SipSetupContext *ssctx;
|
||||
|
|
@ -417,6 +423,7 @@ struct _LinphoneProxyConfig
|
|||
bool_t publish;
|
||||
bool_t dial_escape_plus;
|
||||
bool_t send_publish;
|
||||
bool_t send_statistics;
|
||||
bool_t pad[3];
|
||||
void* user_data;
|
||||
time_t deletion_date;
|
||||
|
|
@ -649,7 +656,7 @@ struct _LinphoneCore
|
|||
char *play_file;
|
||||
char *rec_file;
|
||||
time_t prevtime;
|
||||
int audio_bw;
|
||||
int audio_bw; /*IP bw consumed by audio codec, set as soon as used codec is known, its purpose is to know the remaining bw for video*/
|
||||
LinphoneCoreWaitingCallback wait_cb;
|
||||
void *wait_ctx;
|
||||
unsigned long video_window_id;
|
||||
|
|
@ -671,10 +678,11 @@ struct _LinphoneCore
|
|||
bool_t use_preview_window;
|
||||
|
||||
time_t network_last_check;
|
||||
|
||||
|
||||
bool_t network_last_status;
|
||||
bool_t ringstream_autorelease;
|
||||
bool_t pad[2];
|
||||
char localip[LINPHONE_IPADDR_SIZE];
|
||||
int device_rotation;
|
||||
int max_calls;
|
||||
LinphoneTunnel *tunnel;
|
||||
|
|
@ -705,10 +713,9 @@ struct _LinphoneEvent{
|
|||
void *userdata;
|
||||
int refcnt;
|
||||
char *name;
|
||||
LinphoneAddress *from;
|
||||
LinphoneAddress *resource_addr;
|
||||
int expires;
|
||||
bool_t terminating;
|
||||
bool_t is_out_of_dialog_op; /*used for out of dialog notify*/
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -727,7 +734,7 @@ void linphone_core_set_state(LinphoneCore *lc, LinphoneGlobalState gstate, const
|
|||
void linphone_call_make_local_media_description(LinphoneCore *lc, LinphoneCall *call);
|
||||
void linphone_core_update_streams(LinphoneCore *lc, LinphoneCall *call, SalMediaDescription *new_md);
|
||||
|
||||
bool_t linphone_core_is_payload_type_usable_for_bandwidth(LinphoneCore *lc, PayloadType *pt, int bandwidth_limit);
|
||||
bool_t linphone_core_is_payload_type_usable_for_bandwidth(LinphoneCore *lc, const PayloadType *pt, int bandwidth_limit);
|
||||
|
||||
#define linphone_core_ready(lc) ((lc)->state==LinphoneGlobalOn || (lc)->state==LinphoneGlobalShutdown)
|
||||
void _linphone_core_configure_resolver();
|
||||
|
|
@ -805,13 +812,19 @@ bool_t linphone_core_tone_indications_enabled(LinphoneCore*lc);
|
|||
const char *linphone_core_create_uuid(LinphoneCore *lc);
|
||||
void linphone_configure_op(LinphoneCore *lc, SalOp *op, const LinphoneAddress *dest, SalCustomHeader *headers, bool_t with_contact);
|
||||
void linphone_call_create_op(LinphoneCall *call);
|
||||
int linphone_call_prepare_ice(LinphoneCall *call, bool_t incoming_offer);
|
||||
void linphone_core_notify_info_message(LinphoneCore* lc,SalOp *op, const SalBody *body);
|
||||
void linphone_content_uninit(LinphoneContent * obj);
|
||||
LinphoneContent *linphone_content_copy_from_sal_body(LinphoneContent *obj, const SalBody *ref);
|
||||
SalBody *sal_body_from_content(SalBody *body, const LinphoneContent *lc);
|
||||
SalReason linphone_reason_to_sal(LinphoneReason reason);
|
||||
LinphoneReason linphone_reason_from_sal(SalReason reason);
|
||||
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);
|
||||
/**
|
||||
* Useful for out of dialog notify
|
||||
* */
|
||||
LinphoneEvent *linphone_event_new_with_out_of_dialog_op(LinphoneCore *lc, SalOp *op, LinphoneSubscriptionDir dir, const char *name);
|
||||
void linphone_event_set_state(LinphoneEvent *lev, LinphoneSubscriptionState state);
|
||||
void linphone_event_set_publish_state(LinphoneEvent *lev, LinphonePublishState state);
|
||||
LinphoneSubscriptionState linphone_subscription_state_from_sal(SalSubscribeStatus ss);
|
||||
|
|
@ -854,11 +867,18 @@ char * linphone_get_xml_text_content(xmlparsing_context_t *xml_ctx, const char *
|
|||
void linphone_free_xml_text_content(const char *text);
|
||||
xmlXPathObjectPtr linphone_get_xml_xpath_object_for_node_list(xmlparsing_context_t *xml_ctx, const char *xpath_expression);
|
||||
|
||||
/*****************************************************************************
|
||||
* OTHER UTILITY FUNCTIONS *
|
||||
****************************************************************************/
|
||||
char * linphone_timestamp_to_rfc3339_string(time_t timestamp);
|
||||
|
||||
|
||||
static inline const LinphoneErrorInfo *linphone_error_info_from_sal_op(const SalOp *op){
|
||||
if (op==NULL) return (LinphoneErrorInfo*)sal_error_info_none();
|
||||
return (const LinphoneErrorInfo*)sal_op_get_error_info(op);
|
||||
}
|
||||
|
||||
|
||||
/** Belle Sip-based objects need unique ids
|
||||
*/
|
||||
|
||||
|
|
|
|||
123
coreapi/proxy.c
123
coreapi/proxy.c
|
|
@ -17,7 +17,7 @@ Copyright (C) 2000 Simon MORLAT (simon.morlat@linphone.org)
|
|||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
|
||||
#include "linphonecore.h"
|
||||
#include "sipsetup.h"
|
||||
#include "lpconfig.h"
|
||||
|
|
@ -31,7 +31,7 @@ void linphone_proxy_config_write_all_to_config_file(LinphoneCore *lc){
|
|||
MSList *elem;
|
||||
int i;
|
||||
if (!linphone_core_ready(lc)) return;
|
||||
|
||||
|
||||
for(elem=lc->sip_conf.proxies,i=0;elem!=NULL;elem=ms_list_next(elem),i++){
|
||||
LinphoneProxyConfig *cfg=(LinphoneProxyConfig*)elem->data;
|
||||
linphone_proxy_config_write_to_config_file(lc->config,cfg,i);
|
||||
|
|
@ -46,9 +46,10 @@ static void linphone_proxy_config_init(LinphoneCore* lc, LinphoneProxyConfig *ob
|
|||
const char *identity = lc ? lp_config_get_default_string(lc->config, "proxy", "reg_identity", NULL) : NULL;
|
||||
const char *proxy = lc ? lp_config_get_default_string(lc->config, "proxy", "reg_proxy", NULL) : NULL;
|
||||
const char *route = lc ? lp_config_get_default_string(lc->config, "proxy", "reg_route", NULL) : NULL;
|
||||
const char *statistics_collector = lc ? lp_config_get_default_string(lc->config, "proxy", "statistics_collector", NULL) : NULL;
|
||||
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;
|
||||
|
||||
|
||||
memset(obj, 0, sizeof(LinphoneProxyConfig));
|
||||
obj->magic = linphone_proxy_config_magic;
|
||||
obj->expires = lc ? lp_config_get_default_int(lc->config, "proxy", "reg_expires", 3600) : 3600;
|
||||
|
|
@ -59,8 +60,11 @@ static void linphone_proxy_config_init(LinphoneCore* lc, LinphoneProxyConfig *ob
|
|||
obj->reg_identity = identity ? ms_strdup(identity) : NULL;
|
||||
obj->reg_proxy = proxy ? ms_strdup(proxy) : NULL;
|
||||
obj->reg_route = route ? ms_strdup(route) : NULL;
|
||||
obj->statistics_collector = statistics_collector ? ms_strdup(statistics_collector) : NULL;
|
||||
obj->send_statistics = lc ? lp_config_get_default_int(lc->config, "proxy", "send_statistics", 0) : 0;
|
||||
obj->contact_params = contact_params ? ms_strdup(contact_params) : NULL;
|
||||
obj->contact_uri_params = contact_uri_params ? ms_strdup(contact_uri_params) : NULL;
|
||||
obj->publish_expires=-1;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -85,7 +89,7 @@ LinphoneProxyConfig * linphone_core_create_proxy_config(LinphoneCore *lc) {
|
|||
|
||||
/**
|
||||
* Destroys a proxy config.
|
||||
*
|
||||
*
|
||||
* @note: LinphoneProxyConfig that have been removed from LinphoneCore with
|
||||
* linphone_core_remove_proxy_config() must not be freed.
|
||||
**/
|
||||
|
|
@ -93,6 +97,7 @@ void linphone_proxy_config_destroy(LinphoneProxyConfig *obj){
|
|||
if (obj->reg_proxy!=NULL) ms_free(obj->reg_proxy);
|
||||
if (obj->reg_identity!=NULL) ms_free(obj->reg_identity);
|
||||
if (obj->reg_route!=NULL) ms_free(obj->reg_route);
|
||||
if (obj->statistics_collector!=NULL) ms_free(obj->statistics_collector);
|
||||
if (obj->ssctx!=NULL) sip_setup_context_free(obj->ssctx);
|
||||
if (obj->realm!=NULL) ms_free(obj->realm);
|
||||
if (obj->type!=NULL) ms_free(obj->type);
|
||||
|
|
@ -123,10 +128,10 @@ bool_t linphone_proxy_config_is_registered(const LinphoneProxyConfig *obj){
|
|||
int linphone_proxy_config_set_server_addr(LinphoneProxyConfig *obj, const char *server_addr){
|
||||
LinphoneAddress *addr=NULL;
|
||||
char *modified=NULL;
|
||||
|
||||
|
||||
if (obj->reg_proxy!=NULL) ms_free(obj->reg_proxy);
|
||||
obj->reg_proxy=NULL;
|
||||
|
||||
|
||||
if (server_addr!=NULL && strlen(server_addr)>0){
|
||||
if (strstr(server_addr,"sip:")==NULL && strstr(server_addr,"sips:")==NULL){
|
||||
modified=ms_strdup_printf("sip:%s",server_addr);
|
||||
|
|
@ -149,7 +154,7 @@ int linphone_proxy_config_set_server_addr(LinphoneProxyConfig *obj, const char *
|
|||
/**
|
||||
* Sets the user identity as a SIP address.
|
||||
*
|
||||
* This identity is normally formed with display name, username and domain, such
|
||||
* This identity is normally formed with display name, username and domain, such
|
||||
* as:
|
||||
* Alice <sip:alice@example.net>
|
||||
* The REGISTER messages will have from and to set to this identity.
|
||||
|
|
@ -297,14 +302,14 @@ LinphoneAddress *guess_contact_for_register(LinphoneProxyConfig *obj){
|
|||
LinphoneAddress *ret=NULL;
|
||||
LinphoneAddress *proxy=linphone_address_new(obj->reg_proxy);
|
||||
const char *host;
|
||||
|
||||
|
||||
if (proxy==NULL) return NULL;
|
||||
host=linphone_address_get_domain(proxy);
|
||||
if (host!=NULL){
|
||||
int localport = -1;
|
||||
const char *localip = NULL;
|
||||
LinphoneAddress *contact=linphone_address_new(obj->reg_identity);
|
||||
|
||||
|
||||
linphone_address_clean(contact);
|
||||
|
||||
if (obj->contact_params) {
|
||||
|
|
@ -374,7 +379,7 @@ void linphone_proxy_config_refresh_register(LinphoneProxyConfig *obj){
|
|||
|
||||
|
||||
/**
|
||||
* Sets a dialing prefix to be automatically prepended when inviting a number with
|
||||
* Sets a dialing prefix to be automatically prepended when inviting a number with
|
||||
* linphone_core_invite();
|
||||
* This dialing prefix shall usually be the country code of the country where the user is living.
|
||||
*
|
||||
|
|
@ -390,7 +395,7 @@ void linphone_proxy_config_set_dial_prefix(LinphoneProxyConfig *cfg, const char
|
|||
/**
|
||||
* Returns dialing prefix.
|
||||
*
|
||||
*
|
||||
*
|
||||
**/
|
||||
const char *linphone_proxy_config_get_dial_prefix(const LinphoneProxyConfig *cfg){
|
||||
return cfg->dial_prefix;
|
||||
|
|
@ -413,6 +418,37 @@ void linphone_proxy_config_set_dial_escape_plus(LinphoneProxyConfig *cfg, bool_t
|
|||
bool_t linphone_proxy_config_get_dial_escape_plus(const LinphoneProxyConfig *cfg){
|
||||
return cfg->dial_escape_plus;
|
||||
}
|
||||
|
||||
void linphone_proxy_config_enable_statistics(LinphoneProxyConfig *cfg, bool_t val){
|
||||
cfg->send_statistics = val;
|
||||
}
|
||||
|
||||
bool_t linphone_proxy_config_send_statistics_enabled(LinphoneProxyConfig *cfg){
|
||||
// ensure that collector address is set too!
|
||||
return cfg->send_statistics && cfg->statistics_collector != NULL;
|
||||
}
|
||||
|
||||
void linphone_proxy_config_set_statistics_collector(LinphoneProxyConfig *cfg, const char *collector){
|
||||
if (collector!=NULL && strlen(collector)>0){
|
||||
LinphoneAddress *addr=linphone_address_new(collector);
|
||||
if (!addr || linphone_address_get_username(addr)==NULL){
|
||||
ms_warning("Invalid sip collector identity: %s",collector);
|
||||
if (addr)
|
||||
linphone_address_destroy(addr);
|
||||
} else {
|
||||
if (cfg->statistics_collector != NULL)
|
||||
ms_free(cfg->statistics_collector);
|
||||
cfg->statistics_collector = ms_strdup(collector);
|
||||
linphone_address_destroy(addr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const char *linphone_proxy_config_get_statistics_collector(const LinphoneProxyConfig *cfg){
|
||||
return cfg->statistics_collector;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* http://en.wikipedia.org/wiki/Telephone_numbering_plan
|
||||
* http://en.wikipedia.org/wiki/Telephone_numbers_in_Europe
|
||||
|
|
@ -423,7 +459,7 @@ typedef struct dial_plan{
|
|||
char ccc[8]; /*country calling code*/
|
||||
int nnl; /*maximum national number length*/
|
||||
const char * icp; /*international call prefix, ex: 00 in europe*/
|
||||
|
||||
|
||||
}dial_plan_t;
|
||||
|
||||
/* TODO: fill with information for all countries over the world*/
|
||||
|
|
@ -708,7 +744,7 @@ static void lookup_dial_plan(const char *ccc, dial_plan_t *plan){
|
|||
static bool_t is_a_phone_number(const char *username){
|
||||
const char *p;
|
||||
for(p=username;*p!='\0';++p){
|
||||
if (isdigit(*p) ||
|
||||
if (isdigit(*p) ||
|
||||
*p==' ' ||
|
||||
*p=='.' ||
|
||||
*p=='-' ||
|
||||
|
|
@ -736,12 +772,12 @@ static char *flatten_number(const char *number){
|
|||
|
||||
static void replace_plus(const char *src, char *dest, size_t destlen, const char *icp){
|
||||
int i=0;
|
||||
|
||||
|
||||
if (icp && src[0]=='+' && (destlen>(i=strlen(icp))) ){
|
||||
src++;
|
||||
strcpy(dest,icp);
|
||||
}
|
||||
|
||||
|
||||
for(;(i<destlen-1) && *src!='\0';++i){
|
||||
dest[i]=*src;
|
||||
src++;
|
||||
|
|
@ -756,7 +792,7 @@ int linphone_proxy_config_normalize_number(LinphoneProxyConfig *proxy, const cha
|
|||
char *flatten;
|
||||
flatten=flatten_number(username);
|
||||
ms_message("Flattened number is '%s'",flatten);
|
||||
|
||||
|
||||
if (proxy->dial_prefix==NULL || proxy->dial_prefix[0]=='\0'){
|
||||
/*no prefix configured, nothing else to do*/
|
||||
strncpy(result,flatten,result_len);
|
||||
|
|
@ -824,7 +860,7 @@ void linphone_proxy_config_set_realm(LinphoneProxyConfig *cfg, const char *realm
|
|||
|
||||
int linphone_proxy_config_send_publish(LinphoneProxyConfig *proxy, LinphonePresenceModel *presence){
|
||||
int err=0;
|
||||
|
||||
|
||||
if (proxy->state==LinphoneRegistrationOk || proxy->state==LinphoneRegistrationCleared){
|
||||
if (proxy->publish_op==NULL){
|
||||
proxy->publish_op=sal_op_new(proxy->lc->sal);
|
||||
|
|
@ -837,7 +873,11 @@ int linphone_proxy_config_send_publish(LinphoneProxyConfig *proxy, LinphonePrese
|
|||
sal_address_unref(addr);
|
||||
}
|
||||
}
|
||||
err=sal_publish_presence(proxy->publish_op,NULL,NULL,proxy->expires,(SalPresenceModel *)presence);
|
||||
err=sal_publish_presence(proxy->publish_op
|
||||
,NULL
|
||||
,NULL
|
||||
,linphone_proxy_config_get_publish_expires(proxy)
|
||||
,(SalPresenceModel *)presence);
|
||||
}else proxy->send_publish=TRUE; /*otherwise do not send publish if registration is in progress, this will be done later*/
|
||||
return err;
|
||||
}
|
||||
|
|
@ -1015,7 +1055,7 @@ void linphone_core_set_default_proxy(LinphoneCore *lc, LinphoneProxyConfig *conf
|
|||
lc->default_proxy=config;
|
||||
if (linphone_core_ready(lc))
|
||||
lp_config_set_int(lc->config,"sip","default_proxy",linphone_core_get_default_proxy(lc,NULL));
|
||||
}
|
||||
}
|
||||
|
||||
void linphone_core_set_default_proxy_index(LinphoneCore *lc, int index){
|
||||
if (index<0) linphone_core_set_default_proxy(lc,NULL);
|
||||
|
|
@ -1059,6 +1099,9 @@ void linphone_proxy_config_write_to_config_file(LpConfig *config, LinphoneProxyC
|
|||
if (obj->reg_route!=NULL){
|
||||
lp_config_set_string(config,key,"reg_route",obj->reg_route);
|
||||
}
|
||||
if (obj->statistics_collector!=NULL){
|
||||
lp_config_set_string(config,key,"statistics_collector",obj->statistics_collector);
|
||||
}
|
||||
if (obj->reg_identity!=NULL){
|
||||
lp_config_set_string(config,key,"reg_identity",obj->reg_identity);
|
||||
}
|
||||
|
|
@ -1072,6 +1115,7 @@ void linphone_proxy_config_write_to_config_file(LpConfig *config, LinphoneProxyC
|
|||
lp_config_set_int(config,key,"reg_sendregister",obj->reg_sendregister);
|
||||
lp_config_set_int(config,key,"publish",obj->publish);
|
||||
lp_config_set_int(config,key,"dial_escape_plus",obj->dial_escape_plus);
|
||||
lp_config_set_int(config,key,"send_statistics",obj->send_statistics);
|
||||
lp_config_set_string(config,key,"dial_prefix",obj->dial_prefix);
|
||||
lp_config_set_int(config,key,"privacy",obj->privacy);
|
||||
}
|
||||
|
|
@ -1085,7 +1129,7 @@ LinphoneProxyConfig *linphone_proxy_config_new_from_config_file(LpConfig *config
|
|||
const char *proxy;
|
||||
LinphoneProxyConfig *cfg;
|
||||
char key[50];
|
||||
|
||||
|
||||
sprintf(key,"proxy_%i",index);
|
||||
|
||||
if (!lp_config_has_section(config,key)){
|
||||
|
|
@ -1094,29 +1138,33 @@ LinphoneProxyConfig *linphone_proxy_config_new_from_config_file(LpConfig *config
|
|||
|
||||
cfg=linphone_proxy_config_new();
|
||||
|
||||
identity=lp_config_get_string(config,key,"reg_identity",NULL);
|
||||
identity=lp_config_get_string(config,key,"reg_identity",NULL);
|
||||
proxy=lp_config_get_string(config,key,"reg_proxy",NULL);
|
||||
|
||||
|
||||
linphone_proxy_config_set_identity(cfg,identity);
|
||||
linphone_proxy_config_set_server_addr(cfg,proxy);
|
||||
|
||||
|
||||
tmp=lp_config_get_string(config,key,"reg_route",NULL);
|
||||
if (tmp!=NULL) linphone_proxy_config_set_route(cfg,tmp);
|
||||
|
||||
tmp=lp_config_get_string(config,key,"statistics_collector",NULL);
|
||||
if (tmp!=NULL) linphone_proxy_config_set_statistics_collector(cfg,tmp);
|
||||
linphone_proxy_config_enable_statistics(cfg,lp_config_get_int(config,key,"send_statistics",0));
|
||||
|
||||
linphone_proxy_config_set_contact_parameters(cfg,lp_config_get_string(config,key,"contact_parameters",NULL));
|
||||
|
||||
|
||||
linphone_proxy_config_set_contact_uri_parameters(cfg,lp_config_get_string(config,key,"contact_uri_parameters",NULL));
|
||||
|
||||
|
||||
linphone_proxy_config_expires(cfg,lp_config_get_int(config,key,"reg_expires",lp_config_get_default_int(config,"proxy","reg_expires",600)));
|
||||
linphone_proxy_config_enableregister(cfg,lp_config_get_int(config,key,"reg_sendregister",0));
|
||||
|
||||
|
||||
linphone_proxy_config_enable_publish(cfg,lp_config_get_int(config,key,"publish",0));
|
||||
|
||||
linphone_proxy_config_set_dial_escape_plus(cfg,lp_config_get_int(config,key,"dial_escape_plus",lp_config_get_default_int(config,"proxy","dial_escape_plus",0)));
|
||||
linphone_proxy_config_set_dial_prefix(cfg,lp_config_get_string(config,key,"dial_prefix",lp_config_get_default_string(config,"proxy","dial_prefix",NULL)));
|
||||
|
||||
|
||||
tmp=lp_config_get_string(config,key,"type",NULL);
|
||||
if (tmp!=NULL && strlen(tmp)>0)
|
||||
if (tmp!=NULL && strlen(tmp)>0)
|
||||
linphone_proxy_config_set_sip_setup(cfg,tmp);
|
||||
|
||||
linphone_proxy_config_set_privacy(cfg,lp_config_get_int(config,key,"privacy",lp_config_get_default_int(config,"proxy","privacy",LinphonePrivacyDefault)));
|
||||
|
|
@ -1155,7 +1203,7 @@ static void linphone_proxy_config_activate_sip_setup(LinphoneProxyConfig *cfg){
|
|||
ms_error("Could not retrieve proxy uri !");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
SipSetup *linphone_proxy_config_get_sip_setup(LinphoneProxyConfig *cfg){
|
||||
|
|
@ -1170,7 +1218,7 @@ static bool_t can_register(LinphoneProxyConfig *cfg){
|
|||
LinphoneCore *lc=cfg->lc;
|
||||
#ifdef BUILD_UPNP
|
||||
if (linphone_core_get_firewall_policy(lc)==LinphonePolicyUseUpnp){
|
||||
if(lc->sip_conf.register_only_when_upnp_is_ok &&
|
||||
if(lc->sip_conf.register_only_when_upnp_is_ok &&
|
||||
(lc->upnp == NULL || !linphone_upnp_context_is_ready_for_register(lc->upnp))) {
|
||||
return FALSE;
|
||||
}
|
||||
|
|
@ -1326,7 +1374,7 @@ void * linphone_proxy_config_get_user_data(LinphoneProxyConfig *cr) {
|
|||
void linphone_proxy_config_set_state(LinphoneProxyConfig *cfg, LinphoneRegistrationState state, const char *message){
|
||||
LinphoneCore *lc=cfg->lc;
|
||||
bool_t update_friends=FALSE;
|
||||
|
||||
|
||||
if (cfg->state!=state || state==LinphoneRegistrationOk) { /*allow multiple notification of LinphoneRegistrationOk for refreshing*/
|
||||
ms_message("Proxy config [%p] for identity [%s] moving from state [%s] to [%s]" , cfg,
|
||||
linphone_proxy_config_get_identity(cfg),
|
||||
|
|
@ -1337,7 +1385,7 @@ void linphone_proxy_config_set_state(LinphoneProxyConfig *cfg, LinphoneRegistrat
|
|||
|| (state!=LinphoneRegistrationOk && cfg->state==LinphoneRegistrationOk);
|
||||
}
|
||||
cfg->state=state;
|
||||
|
||||
|
||||
if (update_friends){
|
||||
linphone_core_update_friends_subscriptions(lc,cfg,TRUE);
|
||||
}
|
||||
|
|
@ -1413,3 +1461,14 @@ void linphone_proxy_config_set_privacy(LinphoneProxyConfig *params, LinphonePriv
|
|||
LinphonePrivacyMask linphone_proxy_config_get_privacy(const LinphoneProxyConfig *params) {
|
||||
return params->privacy;
|
||||
}
|
||||
void linphone_proxy_config_set_publish_expires(LinphoneProxyConfig *obj, int expires) {
|
||||
obj->publish_expires=expires;
|
||||
}
|
||||
int linphone_proxy_config_get_publish_expires(const LinphoneProxyConfig *obj) {
|
||||
if (obj->publish_expires<0) {
|
||||
return obj->expires; /*default value is same as register*/
|
||||
} else {
|
||||
return obj->publish_expires;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
527
coreapi/quality_reporting.c
Normal file
527
coreapi/quality_reporting.c
Normal file
|
|
@ -0,0 +1,527 @@
|
|||
/*
|
||||
linphone
|
||||
Copyright (C) 2014 - Belledonne Communications, Grenoble, France
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "../config.h"
|
||||
#endif
|
||||
|
||||
#include "linphonecore.h"
|
||||
#include "private.h"
|
||||
#include "sal/sal.h"
|
||||
#include "ortp/rtpsession.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
/***************************************************************************
|
||||
* TODO / REMINDER LIST
|
||||
****************************************************************************/
|
||||
/*For codecs that are able to change sample rates, the lowest and highest sample rates MUST be reported (e.g., 8000;16000).
|
||||
moslq == moscq
|
||||
video: what happens if doing stop/resume?
|
||||
one time value: average? worst value?
|
||||
rlq value: need algo to compute it*/
|
||||
/***************************************************************************
|
||||
* END OF TODO / REMINDER LIST
|
||||
****************************************************************************/
|
||||
|
||||
#define STR_REASSIGN(dest, src) {\
|
||||
if (dest != NULL) \
|
||||
ms_free(dest); \
|
||||
dest = src; \
|
||||
}
|
||||
|
||||
/*since printf family functions are LOCALE dependent, float separator may differ
|
||||
depending on the user's locale (LC_NUMERIC environment var).*/
|
||||
static char * float_to_one_decimal_string(float f) {
|
||||
float rounded_f = floorf(f * 10 + .5f) / 10;
|
||||
|
||||
int floor_part = (int) rounded_f;
|
||||
int one_decimal_part = floorf (10 * (rounded_f - floor_part) + .5f);
|
||||
|
||||
return ms_strdup_printf("%d.%d", floor_part, one_decimal_part);
|
||||
}
|
||||
|
||||
static void append_to_buffer_valist(char **buff, size_t *buff_size, size_t *offset, const char *fmt, va_list args) {
|
||||
belle_sip_error_code ret;
|
||||
size_t prevoffset = *offset;
|
||||
|
||||
#ifndef WIN32
|
||||
va_list cap;/*copy of our argument list: a va_list cannot be re-used (SIGSEGV on linux 64 bits)*/
|
||||
va_copy(cap,args);
|
||||
ret = belle_sip_snprintf_valist(*buff, *buff_size, offset, fmt, cap);
|
||||
va_end(cap);
|
||||
#else
|
||||
ret = belle_sip_snprintf_valist(*buff, *buff_size, offset, fmt, args);
|
||||
#endif
|
||||
|
||||
/*if we are out of memory, we add some size to buffer*/
|
||||
if (ret == BELLE_SIP_BUFFER_OVERFLOW) {
|
||||
/*some compilers complain that size_t cannot be formatted as unsigned long, hence forcing cast*/
|
||||
ms_warning("Buffer was too small to contain the whole report - doubling its size from %lu to %lu",
|
||||
(unsigned long)*buff_size, (unsigned long)2 * *buff_size);
|
||||
*buff_size += 2048;
|
||||
*buff = (char *) ms_realloc(*buff, *buff_size);
|
||||
|
||||
*offset = prevoffset;
|
||||
/*recall myself since we did not write all things into the buffer but
|
||||
only a part of it*/
|
||||
append_to_buffer_valist(buff, buff_size, offset, fmt, args);
|
||||
}
|
||||
}
|
||||
|
||||
static void append_to_buffer(char **buff, size_t *buff_size, size_t *offset, const char *fmt, ...) {
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
append_to_buffer_valist(buff, buff_size, offset, fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
|
||||
#define APPEND_IF_NOT_NULL_STR(buffer, size, offset, fmt, arg) if (arg != NULL) append_to_buffer(buffer, size, offset, fmt, arg)
|
||||
#define APPEND_IF_NUM_IN_RANGE(buffer, size, offset, fmt, arg, inf, sup) if (inf <= arg && arg <= sup) append_to_buffer(buffer, size, offset, fmt, arg)
|
||||
#define APPEND_IF(buffer, size, offset, fmt, arg, cond) if (cond) append_to_buffer(buffer, size, offset, fmt, arg)
|
||||
#define IF_NUM_IN_RANGE(num, inf, sup, statement) if (inf <= num && num <= sup) statement
|
||||
|
||||
static bool_t are_metrics_filled(const reporting_content_metrics_t rm) {
|
||||
IF_NUM_IN_RANGE(rm.packet_loss.network_packet_loss_rate, 0, 255, return TRUE);
|
||||
IF_NUM_IN_RANGE(rm.packet_loss.jitter_buffer_discard_rate, 0, 255, return TRUE);
|
||||
IF_NUM_IN_RANGE(rm.quality_estimates.moslq, 1, 5, return TRUE);
|
||||
IF_NUM_IN_RANGE(rm.quality_estimates.moscq, 1, 5, return TRUE);
|
||||
|
||||
/*since these are same values than local ones, do not check them*/
|
||||
/*if (rm.session_description.payload_type != -1) return TRUE;*/
|
||||
/*if (rm.session_description.payload_desc != NULL) return TRUE;*/
|
||||
/*if (rm.session_description.sample_rate != -1) return TRUE;*/
|
||||
if (rm.session_description.frame_duration != -1) return TRUE;
|
||||
/*if (rm.session_description.fmtp != NULL) return TRUE;*/
|
||||
if (rm.session_description.packet_loss_concealment != -1) return TRUE;
|
||||
|
||||
IF_NUM_IN_RANGE(rm.jitter_buffer.adaptive, 0, 3, return TRUE);
|
||||
IF_NUM_IN_RANGE(rm.jitter_buffer.nominal, 0, 65535, return TRUE);
|
||||
IF_NUM_IN_RANGE(rm.jitter_buffer.max, 0, 65535, return TRUE);
|
||||
IF_NUM_IN_RANGE(rm.jitter_buffer.abs_max, 0, 65535, return TRUE);
|
||||
|
||||
IF_NUM_IN_RANGE(rm.delay.round_trip_delay, 0, 65535, return TRUE);
|
||||
IF_NUM_IN_RANGE(rm.delay.end_system_delay, 0, 65535, return TRUE);
|
||||
IF_NUM_IN_RANGE(rm.delay.symm_one_way_delay, 0, 65535, return TRUE);
|
||||
IF_NUM_IN_RANGE(rm.delay.interarrival_jitter, 0, 65535, return TRUE);
|
||||
IF_NUM_IN_RANGE(rm.delay.mean_abs_jitter, 0, 65535, return TRUE);
|
||||
|
||||
if (rm.signal.level != 127) return TRUE;
|
||||
if (rm.signal.noise_level != 127) return TRUE;
|
||||
|
||||
IF_NUM_IN_RANGE(rm.quality_estimates.rlq, 1, 120, return TRUE);
|
||||
IF_NUM_IN_RANGE(rm.quality_estimates.rcq, 1, 120, return TRUE);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void append_metrics_to_buffer(char ** buffer, size_t * size, size_t * offset, const reporting_content_metrics_t rm) {
|
||||
char * timestamps_start_str = NULL;
|
||||
char * timestamps_stop_str = NULL;
|
||||
char * network_packet_loss_rate_str = NULL;
|
||||
char * jitter_buffer_discard_rate_str = NULL;
|
||||
/*char * gap_loss_density_str = NULL;*/
|
||||
char * moslq_str = NULL;
|
||||
char * moscq_str = NULL;
|
||||
|
||||
if (rm.timestamps.start > 0)
|
||||
timestamps_start_str = linphone_timestamp_to_rfc3339_string(rm.timestamps.start);
|
||||
if (rm.timestamps.stop > 0)
|
||||
timestamps_stop_str = linphone_timestamp_to_rfc3339_string(rm.timestamps.stop);
|
||||
|
||||
IF_NUM_IN_RANGE(rm.packet_loss.network_packet_loss_rate, 0, 255, network_packet_loss_rate_str = float_to_one_decimal_string(rm.packet_loss.network_packet_loss_rate / 256));
|
||||
IF_NUM_IN_RANGE(rm.packet_loss.jitter_buffer_discard_rate, 0, 255, jitter_buffer_discard_rate_str = float_to_one_decimal_string(rm.packet_loss.jitter_buffer_discard_rate / 256));
|
||||
/*IF_NUM_IN_RANGE(rm.burst_gap_loss.gap_loss_density, 0, 10, gap_loss_density_str = float_to_one_decimal_string(rm.burst_gap_loss.gap_loss_density));*/
|
||||
IF_NUM_IN_RANGE(rm.quality_estimates.moslq, 1, 5, moslq_str = float_to_one_decimal_string(rm.quality_estimates.moslq));
|
||||
IF_NUM_IN_RANGE(rm.quality_estimates.moscq, 1, 5, moscq_str = float_to_one_decimal_string(rm.quality_estimates.moscq));
|
||||
|
||||
append_to_buffer(buffer, size, offset, "Timestamps:");
|
||||
APPEND_IF_NOT_NULL_STR(buffer, size, offset, " START=%s", timestamps_start_str);
|
||||
APPEND_IF_NOT_NULL_STR(buffer, size, offset, " STOP=%s", timestamps_stop_str);
|
||||
|
||||
append_to_buffer(buffer, size, offset, "\r\nSessionDesc:");
|
||||
APPEND_IF(buffer, size, offset, " PT=%d", rm.session_description.payload_type, rm.session_description.payload_type != -1);
|
||||
APPEND_IF_NOT_NULL_STR(buffer, size, offset, " PD=%s", rm.session_description.payload_desc);
|
||||
APPEND_IF(buffer, size, offset, " SR=%d", rm.session_description.sample_rate, rm.session_description.sample_rate != -1);
|
||||
APPEND_IF(buffer, size, offset, " FD=%d", rm.session_description.frame_duration, rm.session_description.frame_duration != -1);
|
||||
/*append_to_buffer(buffer, size, offset, " FO=%d", rm.session_description.frame_ocets);*/
|
||||
/*append_to_buffer(buffer, size, offset, " FPP=%d", rm.session_description.frames_per_sec);*/
|
||||
/*append_to_buffer(buffer, size, offset, " PPS=%d", rm.session_description.packets_per_sec);*/
|
||||
APPEND_IF_NOT_NULL_STR(buffer, size, offset, " FMTP=\"%s\"", rm.session_description.fmtp);
|
||||
APPEND_IF(buffer, size, offset, " PLC=%d", rm.session_description.packet_loss_concealment, rm.session_description.packet_loss_concealment != -1);
|
||||
/*APPEND_IF_NOT_NULL_STR(buffer, size, offset, " SSUP=%s", rm.session_description.silence_suppression_state);*/
|
||||
|
||||
append_to_buffer(buffer, size, offset, "\r\nJitterBuffer:");
|
||||
APPEND_IF_NUM_IN_RANGE(buffer, size, offset, " JBA=%d", rm.jitter_buffer.adaptive, 0, 3);
|
||||
/*APPEND_IF_NUM_IN_RANGE(buffer, size, offset, " JBR=%d", rm.jitter_buffer.rate, 0, 15);*/
|
||||
APPEND_IF_NUM_IN_RANGE(buffer, size, offset, " JBN=%d", rm.jitter_buffer.nominal, 0, 65535);
|
||||
APPEND_IF_NUM_IN_RANGE(buffer, size, offset, " JBM=%d", rm.jitter_buffer.max, 0, 65535);
|
||||
APPEND_IF_NUM_IN_RANGE(buffer, size, offset, " JBX=%d", rm.jitter_buffer.abs_max, 0, 65535);
|
||||
|
||||
append_to_buffer(buffer, size, offset, "\r\nPacketLoss:");
|
||||
APPEND_IF_NOT_NULL_STR(buffer, size, offset, " NLR=%s", network_packet_loss_rate_str);
|
||||
APPEND_IF_NOT_NULL_STR(buffer, size, offset, " JDR=%s", jitter_buffer_discard_rate_str);
|
||||
|
||||
/*append_to_buffer(buffer, size, offset, "\r\nBurstGapLoss:");*/
|
||||
/* append_to_buffer(buffer, size, offset, " BLD=%d", rm.burst_gap_loss.burst_loss_density);*/
|
||||
/* append_to_buffer(buffer, size, offset, " BD=%d", rm.burst_gap_loss.burst_duration);*/
|
||||
/* APPEND_IF_NOT_NULL_STR(buffer, size, offset, " GLD=%s", gap_loss_density_str);*/
|
||||
/* append_to_buffer(buffer, size, offset, " GD=%d", rm.burst_gap_loss.gap_duration);*/
|
||||
/* append_to_buffer(buffer, size, offset, " GMIN=%d", rm.burst_gap_loss.min_gap_threshold);*/
|
||||
|
||||
append_to_buffer(buffer, size, offset, "\r\nDelay:");
|
||||
APPEND_IF_NUM_IN_RANGE(buffer, size, offset, " RTD=%d", rm.delay.round_trip_delay, 0, 65535);
|
||||
APPEND_IF_NUM_IN_RANGE(buffer, size, offset, " ESD=%d", rm.delay.end_system_delay, 0, 65535);
|
||||
/*APPEND_IF_NUM_IN_RANGE(buffer, size, offset, " OWD=%d", rm.delay.one_way_delay, 0, 65535);*/
|
||||
APPEND_IF_NUM_IN_RANGE(buffer, size, offset, " SOWD=%d", rm.delay.symm_one_way_delay, 0, 65535);
|
||||
APPEND_IF_NUM_IN_RANGE(buffer, size, offset, " IAJ=%d", rm.delay.interarrival_jitter, 0, 65535);
|
||||
APPEND_IF_NUM_IN_RANGE(buffer, size, offset, " MAJ=%d", rm.delay.mean_abs_jitter, 0, 65535);
|
||||
|
||||
append_to_buffer(buffer, size, offset, "\r\nSignal:");
|
||||
APPEND_IF(buffer, size, offset, " SL=%d", rm.signal.level, rm.signal.level != 127);
|
||||
APPEND_IF(buffer, size, offset, " NL=%d", rm.signal.noise_level, rm.signal.noise_level != 127);
|
||||
/*append_to_buffer(buffer, size, offset, " RERL=%d", rm.signal.residual_echo_return_loss);*/
|
||||
|
||||
append_to_buffer(buffer, size, offset, "\r\nQualityEst:");
|
||||
APPEND_IF_NUM_IN_RANGE(buffer, size, offset, " RLQ=%d", rm.quality_estimates.rlq, 1, 120);
|
||||
/*APPEND_IF_NOT_NULL_STR(buffer, size, offset, " RLQEstAlg=%s", rm.quality_estimates.rlqestalg);*/
|
||||
APPEND_IF_NUM_IN_RANGE(buffer, size, offset, " RCQ=%d", rm.quality_estimates.rcq, 1, 120);
|
||||
/*APPEND_IF_NOT_NULL_STR(buffer, size, offset, " RCQEstAlgo=%s", rm.quality_estimates.rcqestalg);*/
|
||||
/*append_to_buffer(buffer, size, offset, " EXTRI=%d", rm.quality_estimates.extri);*/
|
||||
/*APPEND_IF_NOT_NULL_STR(buffer, size, offset, " ExtRIEstAlg=%s", rm.quality_estimates.extriestalg);*/
|
||||
/*append_to_buffer(buffer, size, offset, " EXTRO=%d", rm.quality_estimates.extro);*/
|
||||
/*APPEND_IF_NOT_NULL_STR(buffer, size, offset, " ExtROEstAlg=%s", rm.quality_estimates.extroutestalg);*/
|
||||
APPEND_IF_NOT_NULL_STR(buffer, size, offset, " MOSLQ=%s", moslq_str);
|
||||
/*APPEND_IF_NOT_NULL_STR(buffer, size, offset, " MOSLQEstAlgo=%s", rm.quality_estimates.moslqestalg);*/
|
||||
APPEND_IF_NOT_NULL_STR(buffer, size, offset, " MOSCQ=%s", moscq_str);
|
||||
/*APPEND_IF_NOT_NULL_STR(buffer, size, offset, " MOSCQEstAlgo=%s", rm.quality_estimates.moscqestalg);*/
|
||||
/*APPEND_IF_NOT_NULL_STR(buffer, size, offset, " QoEEstAlg=%s", rm.quality_estimates.qoestalg);*/
|
||||
append_to_buffer(buffer, size, offset, "\r\n");
|
||||
|
||||
ms_free(timestamps_start_str);
|
||||
ms_free(timestamps_stop_str);
|
||||
ms_free(network_packet_loss_rate_str);
|
||||
ms_free(jitter_buffer_discard_rate_str);
|
||||
/*ms_free(gap_loss_density_str);*/
|
||||
ms_free(moslq_str);
|
||||
ms_free(moscq_str);
|
||||
}
|
||||
|
||||
static void reporting_publish(const LinphoneCall* call, const reporting_session_report_t * report) {
|
||||
LinphoneContent content = {0};
|
||||
LinphoneAddress *addr;
|
||||
int expires = -1;
|
||||
size_t offset = 0;
|
||||
size_t size = 2048;
|
||||
char * buffer;
|
||||
|
||||
/*if the call was hung up too early, we might have invalid IPs information
|
||||
in that case, we abort the report since it's not useful data*/
|
||||
if (report->info.local_addr.ip == NULL || strlen(report->info.local_addr.ip) == 0
|
||||
|| report->info.remote_addr.ip == NULL || strlen(report->info.remote_addr.ip) == 0) {
|
||||
ms_warning("The call was hang up too early (duration: %d sec) and IP could "
|
||||
"not be retrieved so dropping this report", linphone_call_get_duration(call));
|
||||
return;
|
||||
}
|
||||
|
||||
buffer = (char *) ms_malloc(size);
|
||||
content.type = ms_strdup("application");
|
||||
content.subtype = ms_strdup("vq-rtcpxr");
|
||||
|
||||
append_to_buffer(&buffer, &size, &offset, "VQSessionReport: CallTerm\r\n");
|
||||
append_to_buffer(&buffer, &size, &offset, "CallID: %s\r\n", report->info.call_id);
|
||||
append_to_buffer(&buffer, &size, &offset, "LocalID: %s\r\n", report->info.local_id);
|
||||
append_to_buffer(&buffer, &size, &offset, "RemoteID: %s\r\n", report->info.remote_id);
|
||||
append_to_buffer(&buffer, &size, &offset, "OrigID: %s\r\n", report->info.orig_id);
|
||||
|
||||
APPEND_IF_NOT_NULL_STR(&buffer, &size, &offset, "LocalGroup: %s\r\n", report->info.local_group);
|
||||
APPEND_IF_NOT_NULL_STR(&buffer, &size, &offset, "RemoteGroup: %s\r\n", report->info.remote_group);
|
||||
append_to_buffer(&buffer, &size, &offset, "LocalAddr: IP=%s PORT=%d SSRC=%d\r\n", report->info.local_addr.ip, report->info.local_addr.port, report->info.local_addr.ssrc);
|
||||
APPEND_IF_NOT_NULL_STR(&buffer, &size, &offset, "LocalMAC: %s\r\n", report->info.local_mac_addr);
|
||||
append_to_buffer(&buffer, &size, &offset, "RemoteAddr: IP=%s PORT=%d SSRC=%d\r\n", report->info.remote_addr.ip, report->info.remote_addr.port, report->info.remote_addr.ssrc);
|
||||
APPEND_IF_NOT_NULL_STR(&buffer, &size, &offset, "RemoteMAC: %s\r\n", report->info.remote_mac_addr);
|
||||
|
||||
append_to_buffer(&buffer, &size, &offset, "LocalMetrics:\r\n");
|
||||
append_metrics_to_buffer(&buffer, &size, &offset, report->local_metrics);
|
||||
|
||||
if (are_metrics_filled(report->remote_metrics)) {
|
||||
append_to_buffer(&buffer, &size, &offset, "RemoteMetrics:\r\n");
|
||||
append_metrics_to_buffer(&buffer, &size, &offset, report->remote_metrics);
|
||||
}
|
||||
APPEND_IF_NOT_NULL_STR(&buffer, &size, &offset, "DialogID: %s\r\n", report->dialog_id);
|
||||
|
||||
content.data = buffer;
|
||||
content.size = strlen((char*)content.data);
|
||||
|
||||
|
||||
addr = linphone_address_new(call->dest_proxy->statistics_collector);
|
||||
if (addr != NULL) {
|
||||
linphone_core_publish(call->core, addr, "vq-rtcpxr", expires, &content);
|
||||
linphone_address_destroy(addr);
|
||||
} else {
|
||||
ms_warning("Asked to submit reporting statistics but no collector address found");
|
||||
}
|
||||
|
||||
linphone_content_uninit(&content);
|
||||
}
|
||||
|
||||
static const SalStreamDescription * get_media_stream_for_desc(const SalMediaDescription * smd, SalStreamType sal_stream_type) {
|
||||
int count;
|
||||
if (smd != NULL) {
|
||||
for (count = 0; count < smd->n_total_streams; ++count) {
|
||||
if (smd->streams[count].type == sal_stream_type) {
|
||||
return &smd->streams[count];
|
||||
}
|
||||
}
|
||||
}
|
||||
if (smd == NULL || count == smd->n_total_streams) {
|
||||
ms_warning("Could not find the associated stream of type %d", sal_stream_type);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void reporting_update_ip(LinphoneCall * call, int stats_type) {
|
||||
SalStreamType sal_stream_type = (stats_type == LINPHONE_CALL_STATS_AUDIO) ? SalAudio : SalVideo;
|
||||
if (call->log->reports[stats_type] != NULL) {
|
||||
const SalStreamDescription * local_desc = get_media_stream_for_desc(call->localdesc, sal_stream_type);
|
||||
const SalStreamDescription * remote_desc = get_media_stream_for_desc(sal_call_get_remote_media_description(call->op), sal_stream_type);
|
||||
|
||||
/*local info are always up-to-date and correct*/
|
||||
if (local_desc != NULL) {
|
||||
call->log->reports[stats_type]->info.local_addr.port = local_desc->rtp_port;
|
||||
STR_REASSIGN(call->log->reports[stats_type]->info.local_addr.ip, ms_strdup(local_desc->rtp_addr));
|
||||
}
|
||||
|
||||
if (remote_desc != NULL) {
|
||||
/*port is always stored in stream description struct*/
|
||||
call->log->reports[stats_type]->info.remote_addr.port = remote_desc->rtp_port;
|
||||
|
||||
/*for IP it can be not set if we are using a direct route*/
|
||||
if (remote_desc->rtp_addr != NULL && strlen(remote_desc->rtp_addr) > 0) {
|
||||
STR_REASSIGN(call->log->reports[stats_type]->info.remote_addr.ip, ms_strdup(remote_desc->rtp_addr));
|
||||
} else {
|
||||
STR_REASSIGN(call->log->reports[stats_type]->info.remote_addr.ip, ms_strdup(sal_call_get_remote_media_description(call->op)->addr));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool_t reporting_enabled(const LinphoneCall * call) {
|
||||
return (call->dest_proxy != NULL && linphone_proxy_config_send_statistics_enabled(call->dest_proxy));
|
||||
}
|
||||
|
||||
void linphone_reporting_update_ip(LinphoneCall * call) {
|
||||
/*This function can be called in two different cases:
|
||||
- 1) at start when call is starting, remote ip/port info might be the proxy ones to which callee is registered
|
||||
- 2) later, if we found a direct route between caller and callee with ICE/Stun, ip/port are updated for the direct route access*/
|
||||
if (! reporting_enabled(call))
|
||||
return;
|
||||
|
||||
reporting_update_ip(call, LINPHONE_CALL_STATS_AUDIO);
|
||||
|
||||
if (linphone_call_params_video_enabled(linphone_call_get_current_params(call))) {
|
||||
reporting_update_ip(call, LINPHONE_CALL_STATS_VIDEO);
|
||||
}
|
||||
}
|
||||
|
||||
void linphone_reporting_update(LinphoneCall * call, int stats_type) {
|
||||
reporting_session_report_t * report = call->log->reports[stats_type];
|
||||
MediaStream * stream = NULL;
|
||||
const PayloadType * local_payload = NULL;
|
||||
const PayloadType * remote_payload = NULL;
|
||||
const LinphoneCallParams * current_params = linphone_call_get_current_params(call);
|
||||
|
||||
if (! reporting_enabled(call))
|
||||
return;
|
||||
|
||||
STR_REASSIGN(report->info.call_id, ms_strdup(call->log->call_id));
|
||||
STR_REASSIGN(report->info.local_group, ms_strdup_printf("linphone-%s-%s-%s", (stats_type == LINPHONE_CALL_STATS_AUDIO ? "audio" : "video"),
|
||||
linphone_core_get_user_agent_name(), report->info.call_id));
|
||||
STR_REASSIGN(report->info.remote_group, ms_strdup_printf("linphone-%s-%s-%s", (stats_type == LINPHONE_CALL_STATS_AUDIO ? "audio" : "video"),
|
||||
linphone_call_get_remote_user_agent(call), report->info.call_id));
|
||||
|
||||
if (call->dir == LinphoneCallIncoming) {
|
||||
STR_REASSIGN(report->info.remote_id, linphone_address_as_string(call->log->from));
|
||||
STR_REASSIGN(report->info.local_id, linphone_address_as_string(call->log->to));
|
||||
STR_REASSIGN(report->info.orig_id, ms_strdup(report->info.remote_id));
|
||||
} else {
|
||||
STR_REASSIGN(report->info.remote_id, linphone_address_as_string(call->log->to));
|
||||
STR_REASSIGN(report->info.local_id, linphone_address_as_string(call->log->from));
|
||||
STR_REASSIGN(report->info.orig_id, ms_strdup(report->info.local_id));
|
||||
}
|
||||
|
||||
STR_REASSIGN(report->dialog_id, sal_op_get_dialog_id(call->op));
|
||||
|
||||
report->local_metrics.timestamps.start = call->log->start_date_time;
|
||||
report->local_metrics.timestamps.stop = call->log->start_date_time + linphone_call_get_duration(call);
|
||||
|
||||
/*we use same timestamps for remote too*/
|
||||
report->remote_metrics.timestamps.start = call->log->start_date_time;
|
||||
report->remote_metrics.timestamps.stop = call->log->start_date_time + linphone_call_get_duration(call);
|
||||
|
||||
/*yet we use the same payload config for local and remote, since this is the largest use case*/
|
||||
if (stats_type == LINPHONE_CALL_STATS_AUDIO && call->audiostream != NULL) {
|
||||
stream = &call->audiostream->ms;
|
||||
local_payload = linphone_call_params_get_used_audio_codec(current_params);
|
||||
remote_payload = local_payload;
|
||||
} else if (stats_type == LINPHONE_CALL_STATS_VIDEO && call->videostream != NULL) {
|
||||
stream = &call->videostream->ms;
|
||||
local_payload = linphone_call_params_get_used_video_codec(current_params);
|
||||
remote_payload = local_payload;
|
||||
}
|
||||
|
||||
if (stream != NULL) {
|
||||
RtpSession * session = stream->sessions.rtp_session;
|
||||
|
||||
report->info.local_addr.ssrc = rtp_session_get_send_ssrc(session);
|
||||
report->info.remote_addr.ssrc = rtp_session_get_recv_ssrc(session);
|
||||
}
|
||||
|
||||
if (local_payload != NULL) {
|
||||
report->local_metrics.session_description.payload_type = local_payload->type;
|
||||
STR_REASSIGN(report->local_metrics.session_description.payload_desc, ms_strdup(local_payload->mime_type));
|
||||
report->local_metrics.session_description.sample_rate = local_payload->clock_rate;
|
||||
STR_REASSIGN(report->local_metrics.session_description.fmtp, ms_strdup(local_payload->recv_fmtp));
|
||||
}
|
||||
|
||||
if (remote_payload != NULL) {
|
||||
report->remote_metrics.session_description.payload_type = remote_payload->type;
|
||||
STR_REASSIGN(report->remote_metrics.session_description.payload_desc, ms_strdup(remote_payload->mime_type));
|
||||
report->remote_metrics.session_description.sample_rate = remote_payload->clock_rate;
|
||||
STR_REASSIGN(report->remote_metrics.session_description.fmtp, ms_strdup(remote_payload->recv_fmtp));
|
||||
}
|
||||
}
|
||||
|
||||
void linphone_reporting_call_stats_updated(LinphoneCall *call, int stats_type) {
|
||||
reporting_session_report_t * report = call->log->reports[stats_type];
|
||||
reporting_content_metrics_t * metrics = NULL;
|
||||
|
||||
LinphoneCallStats stats = call->stats[stats_type];
|
||||
mblk_t *block = NULL;
|
||||
|
||||
if (! reporting_enabled(call))
|
||||
return;
|
||||
|
||||
if (stats.updated == LINPHONE_CALL_STATS_RECEIVED_RTCP_UPDATE) {
|
||||
metrics = &report->remote_metrics;
|
||||
if (rtcp_is_XR(stats.received_rtcp) == TRUE) {
|
||||
block = stats.received_rtcp;
|
||||
}
|
||||
} else if (stats.updated == LINPHONE_CALL_STATS_SENT_RTCP_UPDATE) {
|
||||
metrics = &report->local_metrics;
|
||||
if (rtcp_is_XR(stats.sent_rtcp) == TRUE) {
|
||||
block = stats.sent_rtcp;
|
||||
}
|
||||
}
|
||||
if (block != NULL) {
|
||||
switch (rtcp_XR_get_block_type(block)) {
|
||||
case RTCP_XR_VOIP_METRICS: {
|
||||
uint8_t config;
|
||||
|
||||
metrics->quality_estimates.rcq = rtcp_XR_voip_metrics_get_r_factor(block);
|
||||
metrics->quality_estimates.moslq = rtcp_XR_voip_metrics_get_mos_lq(block) / 10.f;
|
||||
metrics->quality_estimates.moscq = rtcp_XR_voip_metrics_get_mos_cq(block) / 10.f;
|
||||
|
||||
metrics->jitter_buffer.nominal = rtcp_XR_voip_metrics_get_jb_nominal(block);
|
||||
metrics->jitter_buffer.max = rtcp_XR_voip_metrics_get_jb_maximum(block);
|
||||
metrics->jitter_buffer.abs_max = rtcp_XR_voip_metrics_get_jb_abs_max(block);
|
||||
metrics->packet_loss.network_packet_loss_rate = rtcp_XR_voip_metrics_get_loss_rate(block);
|
||||
metrics->packet_loss.jitter_buffer_discard_rate = rtcp_XR_voip_metrics_get_discard_rate(block);
|
||||
|
||||
config = rtcp_XR_voip_metrics_get_rx_config(block);
|
||||
metrics->session_description.packet_loss_concealment = (config >> 6) & 0x3;
|
||||
metrics->jitter_buffer.adaptive = (config >> 4) & 0x3;
|
||||
break;
|
||||
} default: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void linphone_reporting_publish(LinphoneCall* call) {
|
||||
if (! reporting_enabled(call))
|
||||
return;
|
||||
|
||||
|
||||
if (call->log->reports[LINPHONE_CALL_STATS_AUDIO] != NULL) {
|
||||
reporting_publish(call, call->log->reports[LINPHONE_CALL_STATS_AUDIO]);
|
||||
}
|
||||
|
||||
if (call->log->reports[LINPHONE_CALL_STATS_VIDEO] != NULL
|
||||
&& linphone_call_params_video_enabled(linphone_call_get_current_params(call))) {
|
||||
reporting_publish(call, call->log->reports[LINPHONE_CALL_STATS_VIDEO]);
|
||||
}
|
||||
}
|
||||
|
||||
reporting_session_report_t * linphone_reporting_new() {
|
||||
int i;
|
||||
reporting_session_report_t * rm = ms_new0(reporting_session_report_t,1);
|
||||
|
||||
reporting_content_metrics_t * metrics[2] = {&rm->local_metrics, &rm->remote_metrics};
|
||||
for (i = 0; i < 2; i++) {
|
||||
metrics[i]->session_description.payload_type = -1;
|
||||
metrics[i]->session_description.sample_rate = -1;
|
||||
metrics[i]->session_description.frame_duration = -1;
|
||||
|
||||
metrics[i]->packet_loss.network_packet_loss_rate = -1;
|
||||
metrics[i]->packet_loss.jitter_buffer_discard_rate = -1;
|
||||
|
||||
metrics[i]->session_description.packet_loss_concealment = -1;
|
||||
|
||||
metrics[i]->jitter_buffer.adaptive = -1;
|
||||
/*metrics[i]->jitter_buffer.rate = -1;*/
|
||||
metrics[i]->jitter_buffer.nominal = -1;
|
||||
metrics[i]->jitter_buffer.max = -1;
|
||||
metrics[i]->jitter_buffer.abs_max = -1;
|
||||
|
||||
metrics[i]->delay.round_trip_delay = -1;
|
||||
metrics[i]->delay.end_system_delay = -1;
|
||||
/*metrics[i]->delay.one_way_delay = -1;*/
|
||||
metrics[i]->delay.symm_one_way_delay = -1;
|
||||
metrics[i]->delay.interarrival_jitter = -1;
|
||||
metrics[i]->delay.mean_abs_jitter = -1;
|
||||
|
||||
metrics[i]->signal.level = 127;
|
||||
metrics[i]->signal.noise_level = 127;
|
||||
}
|
||||
return rm;
|
||||
}
|
||||
|
||||
void linphone_reporting_destroy(reporting_session_report_t * report) {
|
||||
if (report->info.call_id != NULL) ms_free(report->info.call_id);
|
||||
if (report->info.local_id != NULL) ms_free(report->info.local_id);
|
||||
if (report->info.remote_id != NULL) ms_free(report->info.remote_id);
|
||||
if (report->info.orig_id != NULL) ms_free(report->info.orig_id);
|
||||
if (report->info.local_addr.ip != NULL) ms_free(report->info.local_addr.ip);
|
||||
if (report->info.remote_addr.ip != NULL) ms_free(report->info.remote_addr.ip);
|
||||
if (report->info.local_group != NULL) ms_free(report->info.local_group);
|
||||
if (report->info.remote_group != NULL) ms_free(report->info.remote_group);
|
||||
if (report->info.local_mac_addr != NULL) ms_free(report->info.local_mac_addr);
|
||||
if (report->info.remote_mac_addr != NULL) ms_free(report->info.remote_mac_addr);
|
||||
if (report->dialog_id != NULL) ms_free(report->dialog_id);
|
||||
if (report->local_metrics.session_description.fmtp != NULL) ms_free(report->local_metrics.session_description.fmtp);
|
||||
if (report->local_metrics.session_description.payload_desc != NULL) ms_free(report->local_metrics.session_description.payload_desc);
|
||||
if (report->remote_metrics.session_description.fmtp != NULL) ms_free(report->remote_metrics.session_description.fmtp);
|
||||
if (report->remote_metrics.session_description.payload_desc != NULL) ms_free(report->remote_metrics.session_description.payload_desc);
|
||||
|
||||
ms_free(report);
|
||||
}
|
||||
164
coreapi/quality_reporting.h
Normal file
164
coreapi/quality_reporting.h
Normal file
|
|
@ -0,0 +1,164 @@
|
|||
/*
|
||||
linphone
|
||||
Copyright (C) 2014 - Belledonne Communications, Grenoble, France
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef quality_reporting_h
|
||||
#define quality_reporting_h
|
||||
|
||||
#include "linphonecore.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"{
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* Linphone quality report sub object storing address related information (ip / port / MAC).
|
||||
*/
|
||||
typedef struct reporting_addr {
|
||||
char * ip;
|
||||
int port;
|
||||
uint32_t ssrc;
|
||||
} reporting_addr_t;
|
||||
|
||||
/**
|
||||
* Linphone quality report sub object storing media metrics information as required by RFC035.
|
||||
*/
|
||||
|
||||
typedef struct reporting_content_metrics {
|
||||
// timestamps - mandatory
|
||||
struct {
|
||||
time_t start;
|
||||
time_t stop;
|
||||
} timestamps;
|
||||
|
||||
// session description - optional
|
||||
struct {
|
||||
int payload_type;
|
||||
char * payload_desc; // mime type
|
||||
int sample_rate; // clock rate
|
||||
int frame_duration; // to check (ptime?) - audio only
|
||||
char * fmtp;
|
||||
int packet_loss_concealment; // in voip metrics - audio only
|
||||
} session_description;
|
||||
|
||||
// jitter buffet - optional
|
||||
struct {
|
||||
int adaptive; // constant
|
||||
int nominal; // no may vary during the call <- average? worst score?
|
||||
int max; // no may vary during the call <- average?
|
||||
int abs_max; // constant
|
||||
} jitter_buffer;
|
||||
|
||||
// packet loss - optional
|
||||
struct {
|
||||
float network_packet_loss_rate;
|
||||
float jitter_buffer_discard_rate;
|
||||
} packet_loss;
|
||||
|
||||
// delay - optional
|
||||
struct {
|
||||
int round_trip_delay; // no - vary
|
||||
int end_system_delay; // no - not implemented yet
|
||||
int symm_one_way_delay; // no - vary (depends on round_trip_delay) + not implemented (depends on end_system_delay)
|
||||
int interarrival_jitter; // no - not implemented yet
|
||||
int mean_abs_jitter; // to check
|
||||
} delay;
|
||||
|
||||
// signal - optional
|
||||
struct {
|
||||
int level; // no - vary
|
||||
int noise_level; // no - vary
|
||||
} signal;
|
||||
|
||||
// quality estimates - optional
|
||||
struct {
|
||||
int rlq; // linked to moslq - in [0..120]
|
||||
int rcq; //voip metrics R factor - no - vary or avg in [0..120]
|
||||
float moslq; // no - vary or avg - voip metrics - in [0..4.9]
|
||||
float moscq; // no - vary or avg - voip metrics - in [0..4.9]
|
||||
} quality_estimates;
|
||||
} reporting_content_metrics_t;
|
||||
|
||||
|
||||
/**
|
||||
* Linphone quality report main object created by function linphone_reporting_new().
|
||||
* It contains all fields required by RFC6035
|
||||
*/
|
||||
typedef struct reporting_session_report {
|
||||
struct {
|
||||
char * call_id;
|
||||
char * local_id;
|
||||
char * remote_id;
|
||||
char * orig_id;
|
||||
reporting_addr_t local_addr;
|
||||
reporting_addr_t remote_addr;
|
||||
char * local_group;
|
||||
char * remote_group;
|
||||
|
||||
char * local_mac_addr; // optional
|
||||
char * remote_mac_addr; // optional
|
||||
} info;
|
||||
|
||||
reporting_content_metrics_t local_metrics;
|
||||
reporting_content_metrics_t remote_metrics; // optional
|
||||
|
||||
char * dialog_id; // optional
|
||||
} reporting_session_report_t;
|
||||
|
||||
reporting_session_report_t * linphone_reporting_new();
|
||||
void linphone_reporting_destroy(reporting_session_report_t * report);
|
||||
|
||||
/**
|
||||
* Fill media information about a given call. This function must be called before
|
||||
* stopping the media stream.
|
||||
* @param call #LinphoneCall object to consider
|
||||
* @param stats_type the media type (LINPHONE_CALL_STATS_AUDIO or LINPHONE_CALL_STATS_VIDEO)
|
||||
*
|
||||
*/
|
||||
void linphone_reporting_update(LinphoneCall * call, int stats_type);
|
||||
|
||||
/**
|
||||
* Fill IP information about a given call. This function must be called each
|
||||
* time state is 'LinphoneCallStreamsRunning' since IP might be updated (if we
|
||||
* found a direct route between caller and callee for example).
|
||||
* @param call #LinphoneCall object to consider
|
||||
*
|
||||
*/
|
||||
void linphone_reporting_update_ip(LinphoneCall * call);
|
||||
|
||||
/**
|
||||
* Publish the report on the call end.
|
||||
* @param call #LinphoneCall object to consider
|
||||
*
|
||||
*/
|
||||
void linphone_reporting_publish(LinphoneCall* call);
|
||||
|
||||
/**
|
||||
* Update publish report data with fresh RTCP stats, if needed.
|
||||
* @param call #LinphoneCall object to consider
|
||||
* @param stats_type the media type (LINPHONE_CALL_STATS_AUDIO or LINPHONE_CALL_STATS_VIDEO)
|
||||
*
|
||||
*/
|
||||
void linphone_reporting_call_stats_updated(LinphoneCall *call, int stats_type);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
@ -57,11 +57,15 @@ static int linphone_remote_provisioning_load_file( LinphoneCore* lc, const char*
|
|||
FILE* f = fopen(file_path, "r");
|
||||
|
||||
if( f ){
|
||||
long fsize;
|
||||
char* provisioning;
|
||||
|
||||
fseek(f, 0, SEEK_END);
|
||||
long fsize = ftell(f);
|
||||
fsize = ftell(f);
|
||||
fseek(f, 0, SEEK_SET);
|
||||
|
||||
char* provisioning = ms_malloc(fsize + 1);
|
||||
provisioning = ms_malloc(fsize + 1);
|
||||
provisioning[fsize]='\0';
|
||||
if (fread(provisioning, fsize, 1, f)==0){
|
||||
ms_error("Could not read xml provisioning file from %s",file_path);
|
||||
status=-1;
|
||||
|
|
|
|||
|
|
@ -17,9 +17,9 @@ along with this program; if not, write to the Free Software
|
|||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
/**
|
||||
This header files defines the Signaling Abstraction Layer.
|
||||
The purpose of this layer is too allow experiment different call signaling
|
||||
The purpose of this layer is too allow experiment different call signaling
|
||||
protocols and implementations under linphone, for example SIP, JINGLE...
|
||||
**/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
|
|
@ -39,7 +39,7 @@ const char* sal_transport_to_string(SalTransport transport) {
|
|||
default: {
|
||||
ms_fatal("Unexpected transport [%i]",transport);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -82,7 +82,7 @@ void sal_media_description_unref(SalMediaDescription *md){
|
|||
}
|
||||
|
||||
SalStreamDescription *sal_media_description_find_stream(SalMediaDescription *md,
|
||||
SalMediaProto proto, SalStreamType type){
|
||||
SalMediaProto proto, SalStreamType type){
|
||||
int i;
|
||||
for(i=0;i<md->n_active_streams;++i){
|
||||
SalStreamDescription *ss=&md->streams[i];
|
||||
|
|
@ -161,7 +161,7 @@ static bool_t payload_type_equals(const PayloadType *p1, const PayloadType *p2){
|
|||
*/
|
||||
/*
|
||||
if (!fmtp_equals(p1->recv_fmtp,p2->recv_fmtp) ||
|
||||
!fmtp_equals(p1->send_fmtp,p2->send_fmtp))
|
||||
!fmtp_equals(p1->send_fmtp,p2->send_fmtp))
|
||||
return FALSE;
|
||||
*/
|
||||
return TRUE;
|
||||
|
|
@ -372,6 +372,14 @@ const char *sal_op_get_network_origin(const SalOp *op){
|
|||
const char* sal_op_get_call_id(const SalOp *op) {
|
||||
return ((SalOpBase*)op)->call_id;
|
||||
}
|
||||
char* sal_op_get_dialog_id(const SalOp *op) {
|
||||
if (op->dialog != NULL) {
|
||||
return ms_strdup_printf("%s;to-tag=%s;from-tag=%s", ((SalOpBase*)op)->call_id,
|
||||
belle_sip_dialog_get_remote_tag(op->dialog), belle_sip_dialog_get_local_tag(op->dialog));
|
||||
}
|
||||
return NULL;
|
||||
|
||||
}
|
||||
void __sal_op_init(SalOp *b, Sal *sal){
|
||||
memset(b,0,sizeof(SalOpBase));
|
||||
((SalOpBase*)b)->root=sal;
|
||||
|
|
@ -401,17 +409,17 @@ void __sal_op_free(SalOp *op){
|
|||
sal_address_destroy(b->to_address);
|
||||
b->to_address=NULL;
|
||||
}
|
||||
|
||||
|
||||
if (b->service_route){
|
||||
sal_address_destroy(b->service_route);
|
||||
b->service_route=NULL;
|
||||
}
|
||||
|
||||
|
||||
if (b->origin_address){
|
||||
sal_address_destroy(b->origin_address);
|
||||
b->origin_address=NULL;
|
||||
}
|
||||
|
||||
|
||||
if (b->from) {
|
||||
ms_free(b->from);
|
||||
b->from=NULL;
|
||||
|
|
@ -616,7 +624,7 @@ static int line_get_value(const char *input, const char *key, char *value, size_
|
|||
|
||||
int sal_lines_get_value(const char *data, const char *key, char *value, size_t value_size){
|
||||
int read=0;
|
||||
|
||||
|
||||
do{
|
||||
if (line_get_value(data,key,value,value_size,&read))
|
||||
return TRUE;
|
||||
|
|
@ -626,7 +634,7 @@ int sal_lines_get_value(const char *data, const char *key, char *value, size_t v
|
|||
}
|
||||
|
||||
int sal_body_has_type(const SalBody *body, const char *type, const char *subtype){
|
||||
return body->type && body->subtype
|
||||
return body->type && body->subtype
|
||||
&& strcmp(body->type,type)==0
|
||||
&& strcmp(body->subtype,subtype)==0;
|
||||
}
|
||||
|
|
|
|||
110
coreapi/upnp.c
110
coreapi/upnp.c
|
|
@ -28,7 +28,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
#define UPNP_ADD_MAX_RETRY 4
|
||||
#define UPNP_REMOVE_MAX_RETRY 4
|
||||
#define UPNP_SECTION_NAME "uPnP"
|
||||
#define UPNP_CORE_READY_CHECK 1
|
||||
#define UPNP_CORE_READY_CHECK 1
|
||||
#define UPNP_CORE_RETRY_DELAY 10
|
||||
#define UPNP_CALL_RETRY_DELAY 3
|
||||
#define UPNP_UUID_LEN 128
|
||||
|
|
@ -79,7 +79,7 @@ struct _UpnpContext {
|
|||
|
||||
ms_mutex_t mutex;
|
||||
ms_cond_t empty_cond;
|
||||
|
||||
|
||||
time_t last_ready_check;
|
||||
LinphoneUpnpState last_ready_state;
|
||||
};
|
||||
|
|
@ -91,13 +91,13 @@ bool_t linphone_upnp_is_blacklisted(UpnpContext *ctx);
|
|||
|
||||
UpnpPortBinding *linphone_upnp_port_binding_new();
|
||||
UpnpPortBinding *linphone_upnp_port_binding_new_with_parameters(upnp_igd_ip_protocol protocol, int local_port, int external_port);
|
||||
UpnpPortBinding *linphone_upnp_port_binding_new_or_collect(MSList *list, upnp_igd_ip_protocol protocol, int local_port, int external_port);
|
||||
UpnpPortBinding *linphone_upnp_port_binding_new_or_collect(MSList *list, upnp_igd_ip_protocol protocol, int local_port, int external_port);
|
||||
UpnpPortBinding *linphone_upnp_port_binding_copy(const UpnpPortBinding *port);
|
||||
void linphone_upnp_port_binding_set_device_id(UpnpPortBinding *port, const char * device_id);
|
||||
bool_t linphone_upnp_port_binding_equal(const UpnpPortBinding *port1, const UpnpPortBinding *port2);
|
||||
UpnpPortBinding *linphone_upnp_port_binding_equivalent_in_list(MSList *list, const UpnpPortBinding *port);
|
||||
UpnpPortBinding *linphone_upnp_port_binding_retain(UpnpPortBinding *port);
|
||||
void linphone_upnp_update_port_binding(UpnpContext *lupnp, UpnpPortBinding **port_mapping, upnp_igd_ip_protocol protocol, int port, int retry_delay);
|
||||
void linphone_upnp_update_port_binding(UpnpContext *lupnp, UpnpPortBinding **port_mapping, upnp_igd_ip_protocol protocol, int port, int retry_delay);
|
||||
void linphone_upnp_port_binding_log(int level, const char *msg, const UpnpPortBinding *port);
|
||||
void linphone_upnp_port_binding_release(UpnpPortBinding *port);
|
||||
void linphone_upnp_update_config(UpnpContext *lupnp);
|
||||
|
|
@ -108,7 +108,7 @@ MSList *linphone_upnp_config_list_port_bindings(struct _LpConfig *lpc, const cha
|
|||
void linphone_upnp_config_add_port_binding(UpnpContext *lupnp, const UpnpPortBinding *port);
|
||||
void linphone_upnp_config_remove_port_binding(UpnpContext *lupnp, const UpnpPortBinding *port);
|
||||
|
||||
// uPnP
|
||||
// uPnP
|
||||
int linphone_upnp_context_send_remove_port_binding(UpnpContext *lupnp, UpnpPortBinding *port, bool_t retry);
|
||||
int linphone_upnp_context_send_add_port_binding(UpnpContext *lupnp, UpnpPortBinding *port, bool_t retry);
|
||||
|
||||
|
|
@ -141,7 +141,7 @@ char * linphone_upnp_format_device_id(const char *device_id) {
|
|||
char *ret = NULL;
|
||||
char *tmp;
|
||||
char tchar;
|
||||
bool_t copy;
|
||||
bool_t copy;
|
||||
if(device_id == NULL) {
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -366,7 +366,7 @@ void linphone_upnp_context_destroy(UpnpContext *lupnp) {
|
|||
linphone_core_remove_iterate_hook(lupnp->lc, linphone_core_upnp_hook, lupnp);
|
||||
|
||||
ms_mutex_lock(&lupnp->mutex);
|
||||
|
||||
|
||||
if(lupnp->lc->network_reachable) {
|
||||
/* Send port binding removes */
|
||||
if(lupnp->sip_udp != NULL) {
|
||||
|
|
@ -391,7 +391,7 @@ void linphone_upnp_context_destroy(UpnpContext *lupnp) {
|
|||
upnp_igd_destroy(lupnp->upnp_igd_ctxt);
|
||||
lupnp->upnp_igd_ctxt = NULL;
|
||||
}
|
||||
|
||||
|
||||
/* No more multi threading here */
|
||||
|
||||
/* Run one more time configuration update and proxy */
|
||||
|
|
@ -419,7 +419,7 @@ void linphone_upnp_context_destroy(UpnpContext *lupnp) {
|
|||
lupnp->removing_configs = ms_list_free(lupnp->removing_configs);
|
||||
ms_list_for_each(lupnp->pending_bindings,(void (*)(void*))linphone_upnp_port_binding_release);
|
||||
lupnp->pending_bindings = ms_list_free(lupnp->pending_bindings);
|
||||
|
||||
|
||||
ms_mutex_destroy(&lupnp->mutex);
|
||||
ms_cond_destroy(&lupnp->empty_cond);
|
||||
|
||||
|
|
@ -439,17 +439,17 @@ LinphoneUpnpState linphone_upnp_context_get_state(UpnpContext *lupnp) {
|
|||
|
||||
bool_t _linphone_upnp_context_is_ready_for_register(UpnpContext *lupnp) {
|
||||
bool_t ready = TRUE;
|
||||
|
||||
|
||||
// 1 Check global uPnP state
|
||||
ready = (lupnp->state == LinphoneUpnpStateOk);
|
||||
|
||||
|
||||
// 2 Check external ip address
|
||||
if(ready) {
|
||||
if (upnp_igd_get_external_ipaddress(lupnp->upnp_igd_ctxt) == NULL) {
|
||||
ready = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 3 Check sip ports bindings
|
||||
if(ready) {
|
||||
if(lupnp->sip_udp != NULL) {
|
||||
|
|
@ -468,7 +468,7 @@ bool_t _linphone_upnp_context_is_ready_for_register(UpnpContext *lupnp) {
|
|||
ready = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return ready;
|
||||
}
|
||||
|
||||
|
|
@ -486,7 +486,7 @@ int linphone_upnp_context_get_external_port(UpnpContext *lupnp) {
|
|||
int port = -1;
|
||||
if(lupnp != NULL) {
|
||||
ms_mutex_lock(&lupnp->mutex);
|
||||
|
||||
|
||||
if(lupnp->sip_udp != NULL) {
|
||||
if(lupnp->sip_udp->state == LinphoneUpnpStateOk) {
|
||||
port = lupnp->sip_udp->external_port;
|
||||
|
|
@ -500,7 +500,7 @@ int linphone_upnp_context_get_external_port(UpnpContext *lupnp) {
|
|||
port = lupnp->sip_tls->external_port;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ms_mutex_unlock(&lupnp->mutex);
|
||||
}
|
||||
return port;
|
||||
|
|
@ -508,7 +508,7 @@ int linphone_upnp_context_get_external_port(UpnpContext *lupnp) {
|
|||
|
||||
bool_t linphone_upnp_is_blacklisted(UpnpContext *lupnp) {
|
||||
const char * device_model_name = upnp_igd_get_device_model_name(lupnp->upnp_igd_ctxt);
|
||||
const char * device_model_number = upnp_igd_get_device_model_number(lupnp->upnp_igd_ctxt);
|
||||
const char * device_model_number = upnp_igd_get_device_model_number(lupnp->upnp_igd_ctxt);
|
||||
const char * blacklist = lp_config_get_string(lupnp->lc->config, "net", "upnp_blacklist", NULL);
|
||||
bool_t blacklisted = FALSE;
|
||||
char *str;
|
||||
|
|
@ -521,7 +521,7 @@ bool_t linphone_upnp_is_blacklisted(UpnpContext *lupnp) {
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
// Find in the list
|
||||
// Find in the list
|
||||
str = strdup(blacklist);
|
||||
pch = strtok(str, ";");
|
||||
while (pch != NULL && !blacklisted) {
|
||||
|
|
@ -537,7 +537,7 @@ bool_t linphone_upnp_is_blacklisted(UpnpContext *lupnp) {
|
|||
if(model_number == NULL || strcmp(model_number, device_model_number) == 0) {
|
||||
blacklisted = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
pch = strtok(NULL, ";");
|
||||
}
|
||||
free(str);
|
||||
|
|
@ -563,7 +563,7 @@ int linphone_upnp_context_send_add_port_binding(UpnpContext *lupnp, UpnpPortBind
|
|||
upnp_igd_port_mapping mapping;
|
||||
char description[128];
|
||||
int ret;
|
||||
|
||||
|
||||
if(lupnp->state != LinphoneUpnpStateOk) {
|
||||
return -2;
|
||||
}
|
||||
|
|
@ -587,7 +587,7 @@ int linphone_upnp_context_send_add_port_binding(UpnpContext *lupnp, UpnpPortBind
|
|||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// No retry if specified
|
||||
if(port->retry != 0 && !retry) {
|
||||
return -1;
|
||||
|
|
@ -626,7 +626,7 @@ int linphone_upnp_context_send_add_port_binding(UpnpContext *lupnp, UpnpPortBind
|
|||
int linphone_upnp_context_send_remove_port_binding(UpnpContext *lupnp, UpnpPortBinding *port, bool_t retry) {
|
||||
upnp_igd_port_mapping mapping;
|
||||
int ret;
|
||||
|
||||
|
||||
if(lupnp->state != LinphoneUpnpStateOk) {
|
||||
return -2;
|
||||
}
|
||||
|
|
@ -649,7 +649,7 @@ int linphone_upnp_context_send_remove_port_binding(UpnpContext *lupnp, UpnpPortB
|
|||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// No retry if specified
|
||||
if(port->retry != 0 && !retry) {
|
||||
return 1;
|
||||
|
|
@ -697,19 +697,19 @@ int linphone_core_update_upnp_audio_video(LinphoneCall *call, bool_t audio, bool
|
|||
/*
|
||||
* Audio part
|
||||
*/
|
||||
linphone_upnp_update_port_binding(lupnp, &call->upnp_session->audio->rtp,
|
||||
linphone_upnp_update_port_binding(lupnp, &call->upnp_session->audio->rtp,
|
||||
UPNP_IGD_IP_PROTOCOL_UDP, (audio)? call->media_ports[0].rtp_port:0, UPNP_CALL_RETRY_DELAY);
|
||||
|
||||
linphone_upnp_update_port_binding(lupnp, &call->upnp_session->audio->rtcp,
|
||||
linphone_upnp_update_port_binding(lupnp, &call->upnp_session->audio->rtcp,
|
||||
UPNP_IGD_IP_PROTOCOL_UDP, (audio)? call->media_ports[0].rtcp_port:0, UPNP_CALL_RETRY_DELAY);
|
||||
|
||||
|
||||
/*
|
||||
* Video part
|
||||
*/
|
||||
linphone_upnp_update_port_binding(lupnp, &call->upnp_session->video->rtp,
|
||||
linphone_upnp_update_port_binding(lupnp, &call->upnp_session->video->rtp,
|
||||
UPNP_IGD_IP_PROTOCOL_UDP, (video)? call->media_ports[1].rtp_port:0, UPNP_CALL_RETRY_DELAY);
|
||||
|
||||
linphone_upnp_update_port_binding(lupnp, &call->upnp_session->video->rtcp,
|
||||
linphone_upnp_update_port_binding(lupnp, &call->upnp_session->video->rtcp,
|
||||
UPNP_IGD_IP_PROTOCOL_UDP, (video)? call->media_ports[1].rtcp_port:0, UPNP_CALL_RETRY_DELAY);
|
||||
}
|
||||
|
||||
|
|
@ -756,16 +756,16 @@ void linphone_upnp_update_stream_state(UpnpStream *stream) {
|
|||
if((stream->rtp == NULL || stream->rtp->state == LinphoneUpnpStateOk || stream->rtp->state == LinphoneUpnpStateIdle) &&
|
||||
(stream->rtcp == NULL || stream->rtcp->state == LinphoneUpnpStateOk || stream->rtcp->state == LinphoneUpnpStateIdle)) {
|
||||
stream->state = LinphoneUpnpStateOk;
|
||||
} else if((stream->rtp != NULL &&
|
||||
(stream->rtp->state == LinphoneUpnpStateAdding || stream->rtp->state == LinphoneUpnpStateRemoving)) ||
|
||||
(stream->rtcp != NULL &&
|
||||
(stream->rtcp->state == LinphoneUpnpStateAdding || stream->rtcp->state == LinphoneUpnpStateRemoving))) {
|
||||
} else if((stream->rtp != NULL &&
|
||||
(stream->rtp->state == LinphoneUpnpStateAdding || stream->rtp->state == LinphoneUpnpStateRemoving)) ||
|
||||
(stream->rtcp != NULL &&
|
||||
(stream->rtcp->state == LinphoneUpnpStateAdding || stream->rtcp->state == LinphoneUpnpStateRemoving))) {
|
||||
stream->state = LinphoneUpnpStatePending;
|
||||
} else if((stream->rtp != NULL && stream->rtp->state == LinphoneUpnpStateKo) ||
|
||||
(stream->rtcp != NULL && stream->rtcp->state == LinphoneUpnpStateKo)) {
|
||||
stream->state = LinphoneUpnpStateKo;
|
||||
} else {
|
||||
ms_error("Invalid stream %p state", stream);
|
||||
ms_error("Invalid stream %p state", stream);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -799,7 +799,7 @@ int linphone_upnp_call_process(LinphoneCall *call) {
|
|||
* Update stat
|
||||
*/
|
||||
linphone_core_update_upnp_state_in_call_stats(call);
|
||||
|
||||
|
||||
/*
|
||||
* Update session state
|
||||
*/
|
||||
|
|
@ -820,7 +820,7 @@ int linphone_upnp_call_process(LinphoneCall *call) {
|
|||
}
|
||||
|
||||
ms_mutex_unlock(&lupnp->mutex);
|
||||
|
||||
|
||||
/* When change is done proceed update */
|
||||
if(oldState != LinphoneUpnpStateOk && oldState != LinphoneUpnpStateKo &&
|
||||
(newState == LinphoneUpnpStateOk || newState == LinphoneUpnpStateKo)) {
|
||||
|
|
@ -865,9 +865,9 @@ void linphone_upnp_update(UpnpContext *lupnp) {
|
|||
UpnpPortBinding *port_mapping, *port_mapping2;
|
||||
|
||||
ms_message("uPnP IGD: Name:%s", linphone_core_upnp_get_charptr_null(upnp_igd_get_device_name(lupnp->upnp_igd_ctxt)));
|
||||
ms_message("uPnP IGD: Device:%s %s",
|
||||
linphone_core_upnp_get_charptr_null(upnp_igd_get_device_model_name(lupnp->upnp_igd_ctxt)),
|
||||
linphone_core_upnp_get_charptr_null(upnp_igd_get_device_model_number(lupnp->upnp_igd_ctxt)));
|
||||
ms_message("uPnP IGD: Device:%s %s",
|
||||
linphone_core_upnp_get_charptr_null(upnp_igd_get_device_model_name(lupnp->upnp_igd_ctxt)),
|
||||
linphone_core_upnp_get_charptr_null(upnp_igd_get_device_model_number(lupnp->upnp_igd_ctxt)));
|
||||
ms_message("uPnP IGD: Refresh mappings");
|
||||
|
||||
if(lupnp->sip_udp != NULL) {
|
||||
|
|
@ -939,7 +939,7 @@ void linphone_upnp_update_port_binding(UpnpContext *lupnp, UpnpPortBinding **por
|
|||
if(*port_mapping == NULL) {
|
||||
*port_mapping = linphone_upnp_port_binding_new_or_collect(lupnp->pending_bindings, protocol, port, port);
|
||||
}
|
||||
|
||||
|
||||
// Get addresses
|
||||
local_addr = upnp_igd_get_local_ipaddress(lupnp->upnp_igd_ctxt);
|
||||
external_addr = upnp_igd_get_external_ipaddress(lupnp->upnp_igd_ctxt);
|
||||
|
|
@ -972,7 +972,7 @@ void linphone_upnp_update_config(UpnpContext* lupnp) {
|
|||
char key[64];
|
||||
const MSList *item;
|
||||
UpnpPortBinding *port_mapping;
|
||||
|
||||
|
||||
/* Add configs */
|
||||
for(item = lupnp->adding_configs;item!=NULL;item=item->next) {
|
||||
port_mapping = (UpnpPortBinding *)item->data;
|
||||
|
|
@ -1006,7 +1006,7 @@ void linphone_upnp_update_proxy(UpnpContext* lupnp, bool_t force) {
|
|||
LinphoneUpnpState ready_state;
|
||||
const MSList *item;
|
||||
time_t now = (force)? (lupnp->last_ready_check + UPNP_CORE_READY_CHECK) : time(NULL);
|
||||
|
||||
|
||||
/* Refresh registers if we are ready */
|
||||
if(now - lupnp->last_ready_check >= UPNP_CORE_READY_CHECK) {
|
||||
lupnp->last_ready_check = now;
|
||||
|
|
@ -1046,7 +1046,7 @@ bool_t linphone_core_upnp_hook(void *data) {
|
|||
linphone_upnp_update_port_binding(lupnp, &lupnp->sip_tls, UPNP_IGD_IP_PROTOCOL_TCP, transport.tls_port, UPNP_CORE_RETRY_DELAY);
|
||||
}
|
||||
|
||||
linphone_upnp_update_proxy(lupnp, FALSE);
|
||||
linphone_upnp_update_proxy(lupnp, FALSE);
|
||||
linphone_upnp_update_config(lupnp);
|
||||
|
||||
ms_mutex_unlock(&lupnp->mutex);
|
||||
|
|
@ -1090,7 +1090,7 @@ UpnpPortBinding *linphone_upnp_port_binding_new() {
|
|||
port = ms_new0(UpnpPortBinding,1);
|
||||
ms_mutex_init(&port->mutex, NULL);
|
||||
port->state = LinphoneUpnpStateIdle;
|
||||
port->protocol = UPNP_IGD_IP_PROTOCOL_UDP;
|
||||
port->protocol = UPNP_IGD_IP_PROTOCOL_UDP;
|
||||
port->device_id = NULL;
|
||||
port->local_addr[0] = '\0';
|
||||
port->local_port = -1;
|
||||
|
|
@ -1114,20 +1114,20 @@ UpnpPortBinding *linphone_upnp_port_binding_new_with_parameters(upnp_igd_ip_prot
|
|||
UpnpPortBinding *linphone_upnp_port_binding_new_or_collect(MSList *list, upnp_igd_ip_protocol protocol, int local_port, int external_port) {
|
||||
UpnpPortBinding *tmp_binding;
|
||||
UpnpPortBinding *end_binding;
|
||||
|
||||
|
||||
// Seek an binding with same protocol and local port
|
||||
end_binding = linphone_upnp_port_binding_new_with_parameters(protocol, local_port, -1);
|
||||
tmp_binding = linphone_upnp_port_binding_equivalent_in_list(list, end_binding);
|
||||
|
||||
// Must be not attached to any struct
|
||||
|
||||
// Must be not attached to any struct
|
||||
if(tmp_binding != NULL && tmp_binding->ref == 1) {
|
||||
linphone_upnp_port_binding_release(end_binding);
|
||||
end_binding = linphone_upnp_port_binding_retain(tmp_binding);
|
||||
} else {
|
||||
end_binding->external_port = external_port;
|
||||
}
|
||||
return end_binding;
|
||||
}
|
||||
return end_binding;
|
||||
}
|
||||
|
||||
UpnpPortBinding *linphone_upnp_port_binding_copy(const UpnpPortBinding *port) {
|
||||
UpnpPortBinding *new_port = NULL;
|
||||
|
|
@ -1174,8 +1174,8 @@ void linphone_upnp_port_binding_log(int level, const char *msg, const UpnpPortBi
|
|||
// Return true if the binding are equivalent. (Note external_port == -1 means "don't care")
|
||||
bool_t linphone_upnp_port_binding_equal(const UpnpPortBinding *port1, const UpnpPortBinding *port2) {
|
||||
return port1->protocol == port2->protocol &&
|
||||
port1->local_port == port2->local_port &&
|
||||
(port1->external_port == -1 || port2->external_port == -1 || port1->external_port == port2->external_port);
|
||||
port1->local_port == port2->local_port &&
|
||||
(port1->external_port == -1 || port2->external_port == -1 || port1->external_port == port2->external_port);
|
||||
}
|
||||
|
||||
UpnpPortBinding *linphone_upnp_port_binding_equivalent_in_list(MSList *list, const UpnpPortBinding *port) {
|
||||
|
|
@ -1220,7 +1220,7 @@ void linphone_upnp_port_binding_release(UpnpPortBinding *port) {
|
|||
UpnpStream* linphone_upnp_stream_new() {
|
||||
UpnpStream *stream = ms_new0(UpnpStream,1);
|
||||
stream->state = LinphoneUpnpStateIdle;
|
||||
stream->rtp = NULL;
|
||||
stream->rtp = NULL;
|
||||
stream->rtcp = NULL;
|
||||
return stream;
|
||||
}
|
||||
|
|
@ -1269,10 +1269,10 @@ void linphone_upnp_session_destroy(UpnpSession *session) {
|
|||
linphone_upnp_context_send_remove_port_binding(lc->upnp, session->video->rtcp, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
session->call->stats[LINPHONE_CALL_STATS_AUDIO].upnp_state = LinphoneUpnpStateKo;
|
||||
session->call->stats[LINPHONE_CALL_STATS_VIDEO].upnp_state = LinphoneUpnpStateKo;
|
||||
|
||||
|
||||
linphone_upnp_stream_destroy(session->audio);
|
||||
linphone_upnp_stream_destroy(session->video);
|
||||
ms_free(session);
|
||||
|
|
@ -1302,12 +1302,12 @@ static void linphone_upnp_config_list_port_bindings_cb(const char *entry, struct
|
|||
int ret;
|
||||
bool_t valid = TRUE;
|
||||
UpnpPortBinding *port;
|
||||
|
||||
|
||||
ret = sscanf(entry, "%"UPNP_UUID_LEN_STR"[^-]-%3s-%i-%i", device_id, protocol_str, &external_port, &local_port);
|
||||
if(ret == 4) {
|
||||
// Handle only wanted device bindings
|
||||
if(device_id != NULL && strcmp(cookie->device_id, device_id) != 0) {
|
||||
return;
|
||||
return;
|
||||
}
|
||||
if(linphone_upnp_strncmpi(protocol_str, "TCP", 3) == 0) {
|
||||
protocol = UPNP_IGD_IP_PROTOCOL_TCP;
|
||||
|
|
@ -1344,7 +1344,7 @@ MSList *linphone_upnp_config_list_port_bindings(struct _LpConfig *lpc, const cha
|
|||
void linphone_upnp_config_add_port_binding(UpnpContext *lupnp, const UpnpPortBinding *port) {
|
||||
MSList *list;
|
||||
UpnpPortBinding *list_port;
|
||||
|
||||
|
||||
if(port->device_id == NULL) {
|
||||
ms_error("Can't remove port binding without device_id");
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ struct _xml2lpc_context {
|
|||
LpConfig *lpc;
|
||||
xml2lpc_function cbf;
|
||||
void *ctx;
|
||||
|
||||
|
||||
xmlDoc *doc;
|
||||
xmlDoc *xsd;
|
||||
char errorBuffer[XML2LPC_BZ];
|
||||
|
|
@ -43,7 +43,7 @@ xml2lpc_context* xml2lpc_context_new(xml2lpc_function cbf, void *ctx) {
|
|||
xmlCtx->lpc = NULL;
|
||||
xmlCtx->cbf = cbf;
|
||||
xmlCtx->ctx = ctx;
|
||||
|
||||
|
||||
xmlCtx->doc = NULL;
|
||||
xmlCtx->xsd = NULL;
|
||||
xmlCtx->errorBuffer[0]='\0';
|
||||
|
|
@ -70,19 +70,19 @@ static void xml2lpc_context_clear_logs(xml2lpc_context *ctx) {
|
|||
}
|
||||
|
||||
static void xml2lpc_log(xml2lpc_context *xmlCtx, int level, const char *fmt, ...) {
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
if(xmlCtx->cbf != NULL) {
|
||||
xmlCtx->cbf((xmlCtx)->ctx, level, fmt, args);
|
||||
}
|
||||
va_end(args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
static void xml2lpc_genericxml_error(void *ctx, const char *fmt, ...) {
|
||||
xml2lpc_context *xmlCtx = (xml2lpc_context *)ctx;
|
||||
int sl = strlen(xmlCtx->errorBuffer);
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
vsnprintf(xmlCtx->errorBuffer + sl, XML2LPC_BZ-sl, fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
|
@ -90,25 +90,25 @@ static void xml2lpc_genericxml_error(void *ctx, const char *fmt, ...) {
|
|||
static void xml2lpc_genericxml_warning(void *ctx, const char *fmt, ...) {
|
||||
xml2lpc_context *xmlCtx = (xml2lpc_context *)ctx;
|
||||
int sl = strlen(xmlCtx->warningBuffer);
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
vsnprintf(xmlCtx->warningBuffer + sl, XML2LPC_BZ-sl, fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void dumpNodes(int level, xmlNode * a_node, xml2lpc_context *ctx) {
|
||||
xmlNode *cur_node = NULL;
|
||||
xmlNode *cur_node = NULL;
|
||||
|
||||
for (cur_node = a_node; cur_node; cur_node = cur_node->next) {
|
||||
if (cur_node->type == XML_ELEMENT_NODE) {
|
||||
xml2lpc_log(ctx, XML2LPC_DEBUG, "node level: %d type: Element, name: %s", level, cur_node->name);
|
||||
} else {
|
||||
xml2lpc_log(ctx, XML2LPC_DEBUG, "node level: %d type: %d, name: %s", level, cur_node->type, cur_node->name);
|
||||
}
|
||||
for (cur_node = a_node; cur_node; cur_node = cur_node->next) {
|
||||
if (cur_node->type == XML_ELEMENT_NODE) {
|
||||
xml2lpc_log(ctx, XML2LPC_DEBUG, "node level: %d type: Element, name: %s", level, cur_node->name);
|
||||
} else {
|
||||
xml2lpc_log(ctx, XML2LPC_DEBUG, "node level: %d type: %d, name: %s", level, cur_node->type, cur_node->name);
|
||||
}
|
||||
|
||||
dumpNodes(level + 1, cur_node->children, ctx);
|
||||
}
|
||||
dumpNodes(level + 1, cur_node->children, ctx);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -162,7 +162,7 @@ static int processEntry(xmlElement *element, const char *sectionName, xml2lpc_co
|
|||
} else {
|
||||
xml2lpc_log(ctx, XML2LPC_WARNING, "ignored entry with no \"name\" attribute line:%d",xmlGetLineNo((xmlNode*)element));
|
||||
}
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int processSection(xmlElement *element, xml2lpc_context *ctx) {
|
||||
|
|
@ -185,13 +185,13 @@ static int processSection(xmlElement *element, xml2lpc_context *ctx) {
|
|||
processEntry((xmlElement*)cur_node, name, ctx);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
} else {
|
||||
xml2lpc_log(ctx, XML2LPC_WARNING, "ignored section with no \"name\" attribute, line:%d", xmlGetLineNo((xmlNode*)element));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
xml2lpc_log(ctx, XML2LPC_WARNING, "ignored section with no \"name\" attribute, line:%d", xmlGetLineNo((xmlNode*)element));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int processConfig(xmlElement *element, xml2lpc_context *ctx) {
|
||||
|
|
@ -199,19 +199,19 @@ static int processConfig(xmlElement *element, xml2lpc_context *ctx) {
|
|||
|
||||
for (cur_node = element->children; cur_node; cur_node = cur_node->next) {
|
||||
dumpNode(cur_node, ctx);
|
||||
if (cur_node->type == XML_ELEMENT_NODE &&
|
||||
if (cur_node->type == XML_ELEMENT_NODE &&
|
||||
strcmp((const char*)cur_node->name, "section") == 0 ) {
|
||||
processSection((xmlElement*)cur_node, ctx);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int processDoc(xmlNode *node, xml2lpc_context *ctx) {
|
||||
dumpNode(node, ctx);
|
||||
|
||||
if (node->type == XML_ELEMENT_NODE &&
|
||||
|
||||
if (node->type == XML_ELEMENT_NODE &&
|
||||
strcmp((const char*)node->name, "config") == 0 ) {
|
||||
processConfig((xmlElement*)node, ctx);
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -268,6 +268,49 @@ void linphone_gtk_start_play_record_sound(GtkWidget *w,gpointer data){
|
|||
}
|
||||
}
|
||||
|
||||
void display_popup(GtkMessageType type,const gchar *message){
|
||||
GtkWidget *dialog = gtk_message_dialog_new (GTK_WINDOW(audio_assistant),
|
||||
GTK_DIALOG_DESTROY_WITH_PARENT,
|
||||
type,
|
||||
GTK_BUTTONS_CLOSE,
|
||||
"%s",
|
||||
(const gchar*)message);
|
||||
/* Destroy the dialog when the user responds to it (e.g. clicks a button) */
|
||||
g_signal_connect_swapped (G_OBJECT (dialog), "response",
|
||||
G_CALLBACK (gtk_widget_destroy),
|
||||
G_OBJECT (dialog));
|
||||
gtk_widget_show(dialog);
|
||||
}
|
||||
|
||||
static void open_mixer(){
|
||||
GError *error = NULL;
|
||||
|
||||
#ifdef WIN32
|
||||
if(!g_spawn_command_line_async("control mmsys.cpl",&error)){
|
||||
display_popup(GTK_MESSAGE_WARNING,"Sound preferences not found ");
|
||||
g_error_free(error);
|
||||
}
|
||||
#elif __APPLE__
|
||||
if(!g_spawn_command_line_async("open /System/Library/PreferencePanes/Sound.prefPane",&error)){
|
||||
display_popup(GTK_MESSAGE_WARNING,"Sound preferences not found ");
|
||||
g_error_free(error);
|
||||
}
|
||||
#else
|
||||
if(!g_spawn_command_line_async("gnome-volume-control",&error)){
|
||||
if(!g_spawn_command_line_async("gnome-control-center sound",&error)){
|
||||
if(!g_spawn_command_line_async("kmix",&error)){
|
||||
if(!g_spawn_command_line_async("mate-volume-control",&error)){
|
||||
if(!g_spawn_command_line_async("xterm alsamixer",&error)){
|
||||
display_popup(GTK_MESSAGE_WARNING,"Cannot launch system sound control ");
|
||||
g_error_free(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static GtkWidget *create_intro(){
|
||||
GtkWidget *vbox=gtk_vbox_new(FALSE,2);
|
||||
GtkWidget *label=gtk_label_new(_("Welcome !\nThis assistant will help you to configure audio settings for Linphone"));
|
||||
|
|
@ -286,6 +329,11 @@ static GtkWidget *create_mic_page(){
|
|||
GtkWidget *capture_device=gtk_combo_box_new();
|
||||
GtkWidget *box = gtk_vbox_new(FALSE,0);
|
||||
GtkWidget *label_audiolevel=gtk_label_new(_("No voice"));
|
||||
GtkWidget *mixer_button=gtk_button_new_with_label("System sound preferences");
|
||||
GtkWidget *image;
|
||||
|
||||
image=gtk_image_new_from_stock(GTK_STOCK_PREFERENCES,GTK_ICON_SIZE_MENU);
|
||||
gtk_button_set_image(GTK_BUTTON(mixer_button),image);
|
||||
|
||||
gtk_box_pack_start(GTK_BOX(box),mic_audiolevel,TRUE,TRUE,1);
|
||||
gtk_box_pack_start(GTK_BOX(box),label_audiolevel,FALSE,FALSE,1);
|
||||
|
|
@ -294,6 +342,7 @@ static GtkWidget *create_mic_page(){
|
|||
gtk_table_attach_defaults(GTK_TABLE(vbox), capture_device, 1, 2, 0, 1);
|
||||
gtk_table_attach_defaults(GTK_TABLE(vbox), labelMicLevel, 0, 1, 1, 2);
|
||||
gtk_table_attach_defaults(GTK_TABLE(vbox), box, 1, 2, 1, 2);
|
||||
gtk_table_attach(GTK_TABLE(vbox), mixer_button, 0, 2, 2, 3, GTK_SHRINK, GTK_SHRINK, 0,0);
|
||||
|
||||
gtk_table_set_row_spacings(GTK_TABLE(vbox),10);
|
||||
|
||||
|
|
@ -306,23 +355,30 @@ static GtkWidget *create_mic_page(){
|
|||
gtk_widget_show_all(vbox);
|
||||
|
||||
g_signal_connect(G_OBJECT(capture_device),"changed",(GCallback)capture_device_changed,capture_device);
|
||||
g_signal_connect(G_OBJECT(mixer_button),"clicked",(GCallback)open_mixer,vbox);
|
||||
|
||||
return vbox;
|
||||
}
|
||||
|
||||
static GtkWidget *create_speaker_page(){
|
||||
GtkWidget *vbox=gtk_table_new(2,2,FALSE);
|
||||
GtkWidget *vbox=gtk_table_new(3,2,FALSE);
|
||||
LinphoneCore *lc=linphone_gtk_get_core();
|
||||
|
||||
GtkWidget *labelSpeakerChoice=gtk_label_new(_("Playback device"));
|
||||
GtkWidget *labelSpeakerLevel=gtk_label_new(_("Play three beeps"));
|
||||
GtkWidget *spk_button=gtk_button_new_from_stock(GTK_STOCK_MEDIA_PLAY);
|
||||
GtkWidget *playback_device=gtk_combo_box_new();
|
||||
GtkWidget *mixer_button=gtk_button_new_with_label("System sound preferences");
|
||||
GtkWidget *image;
|
||||
|
||||
image=gtk_image_new_from_stock(GTK_STOCK_PREFERENCES,GTK_ICON_SIZE_MENU);
|
||||
gtk_button_set_image(GTK_BUTTON(mixer_button),image);
|
||||
|
||||
gtk_table_attach_defaults(GTK_TABLE(vbox), labelSpeakerChoice, 0, 1, 0, 1);
|
||||
gtk_table_attach_defaults(GTK_TABLE(vbox), playback_device, 1, 2, 0, 1);
|
||||
gtk_table_attach(GTK_TABLE(vbox), playback_device, 1, 2, 0, 1, GTK_SHRINK, GTK_SHRINK, 0,0);
|
||||
gtk_table_attach_defaults(GTK_TABLE(vbox), labelSpeakerLevel, 0, 1, 1, 2);
|
||||
gtk_table_attach(GTK_TABLE(vbox), spk_button, 1, 2, 1, 2, GTK_SHRINK, GTK_SHRINK, 0,0);
|
||||
gtk_table_attach(GTK_TABLE(vbox), mixer_button, 0, 2, 2, 3, GTK_SHRINK, GTK_SHRINK, 0,0);
|
||||
|
||||
gtk_table_set_row_spacings(GTK_TABLE(vbox),10);
|
||||
|
||||
|
|
@ -334,6 +390,7 @@ static GtkWidget *create_speaker_page(){
|
|||
set_widget_to_assistant("speaker_page",vbox);
|
||||
g_signal_connect(G_OBJECT(playback_device),"changed",(GCallback)playback_device_changed,playback_device);
|
||||
g_signal_connect(G_OBJECT(spk_button),"clicked",(GCallback)linphone_gtk_start_sound,vbox);
|
||||
g_signal_connect(G_OBJECT(mixer_button),"clicked",(GCallback)open_mixer,vbox);
|
||||
|
||||
return vbox;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -565,7 +565,7 @@ static void linphone_gtk_init_codec_list(GtkTreeView *listview){
|
|||
"foreground",CODEC_COLOR,
|
||||
NULL);
|
||||
gtk_tree_view_append_column (listview, column);
|
||||
column = gtk_tree_view_column_new_with_attributes (_("Bitrate (kbit/s)"),
|
||||
column = gtk_tree_view_column_new_with_attributes (_("IP Bitrate (kbit/s)"),
|
||||
renderer,
|
||||
"text", CODEC_BITRATE,
|
||||
"foreground",CODEC_COLOR,
|
||||
|
|
@ -621,7 +621,7 @@ static void linphone_gtk_show_codecs(GtkTreeView *listview, const MSList *codecl
|
|||
}
|
||||
/* get an iterator */
|
||||
gtk_list_store_append(store,&iter);
|
||||
bitrate=payload_type_get_bitrate(pt)/1000.0;
|
||||
bitrate=linphone_core_get_payload_type_bitrate(linphone_gtk_get_core(),pt);
|
||||
rate=payload_type_get_rate(pt);
|
||||
if (pt->recv_fmtp!=NULL) params=pt->recv_fmtp;
|
||||
gtk_list_store_set(store,&iter, CODEC_NAME,payload_type_get_mime(pt),
|
||||
|
|
@ -657,7 +657,7 @@ static void linphone_gtk_check_codec_bandwidth(GtkTreeView *v){
|
|||
gfloat bitrate;
|
||||
gtk_tree_model_get(model,&iter,CODEC_PRIVDATA,&pt,-1);
|
||||
|
||||
bitrate=payload_type_get_bitrate(pt)/1000.0;
|
||||
bitrate=linphone_core_get_payload_type_bitrate(linphone_gtk_get_core(),pt);
|
||||
gtk_list_store_set(GTK_LIST_STORE(model),&iter,CODEC_COLOR, (gpointer)get_codec_color(linphone_gtk_get_core(),pt),
|
||||
CODEC_BITRATE, bitrate,-1);
|
||||
}while(gtk_tree_model_iter_next(model,&iter));
|
||||
|
|
|
|||
|
|
@ -17,9 +17,9 @@ along with this program; if not, write to the Free Software
|
|||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
/**
|
||||
This header files defines the Signaling Abstraction Layer.
|
||||
The purpose of this layer is too allow experiment different call signaling
|
||||
The purpose of this layer is too allow experiment different call signaling
|
||||
protocols and implementations under linphone, for example SIP, JINGLE...
|
||||
**/
|
||||
|
||||
|
|
@ -30,9 +30,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "mediastreamer2/mscommon.h"
|
||||
#include "mediastreamer2/mediastream.h"
|
||||
#include "ortp/rtpsession.h"
|
||||
#include "ortp/ortp_srtp.h"
|
||||
#include "belle-sip/belle-sip.h"
|
||||
|
||||
#ifndef LINPHONE_PUBLIC
|
||||
|
|
@ -171,7 +170,7 @@ typedef struct SalIceRemoteCandidate {
|
|||
|
||||
typedef struct SalSrtpCryptoAlgo {
|
||||
unsigned int tag;
|
||||
enum ortp_srtp_crypto_suite_t algo;
|
||||
MSCryptoSuite algo;
|
||||
char master_key[SAL_SRTP_KEY_SIZE];
|
||||
} SalSrtpCryptoAlgo;
|
||||
|
||||
|
|
@ -531,6 +530,7 @@ void sal_verify_server_cn(Sal *ctx, bool_t verify);
|
|||
void sal_set_uuid(Sal*ctx, const char *uuid);
|
||||
int sal_create_uuid(Sal*ctx, char *uuid, size_t len);
|
||||
void sal_enable_test_features(Sal*ctx, bool_t enabled);
|
||||
void sal_use_no_initial_route(Sal *ctx, bool_t enabled);
|
||||
|
||||
int sal_iterate(Sal *sal);
|
||||
MSList * sal_get_pending_auths(Sal *sal);
|
||||
|
|
@ -572,6 +572,7 @@ const SalAddress *sal_op_get_network_origin_address(const SalOp *op);
|
|||
const char *sal_op_get_remote_ua(const SalOp *op);
|
||||
void *sal_op_get_user_pointer(const SalOp *op);
|
||||
const char* sal_op_get_call_id(const SalOp *op);
|
||||
char* sal_op_get_dialog_id(const SalOp *op);
|
||||
|
||||
const SalAddress* sal_op_get_service_route(const SalOp *op);
|
||||
void sal_op_set_service_route(SalOp *op,const SalAddress* service_route);
|
||||
|
|
|
|||
|
|
@ -693,6 +693,20 @@ public interface LinphoneCore {
|
|||
*/
|
||||
boolean isPayloadTypeEnabled(PayloadType pt);
|
||||
|
||||
/**
|
||||
* Set an explicit bitrate (IP bitrate, not codec bitrate) for a given codec, in kbit/s.
|
||||
* @param pt the payload type
|
||||
* @param bitrate target IP bitrate in kbit/s
|
||||
*/
|
||||
void setPayloadTypeBitrate(PayloadType pt, int bitrate);
|
||||
|
||||
/**
|
||||
* Get target bitrate previously set by setPayloadTypeBitrate().
|
||||
* @param pt
|
||||
* @return IP bitrate in kbit/s
|
||||
*/
|
||||
int getPayloadTypeBitrate(PayloadType pt);
|
||||
|
||||
/**
|
||||
* Enables or disable echo cancellation.
|
||||
* @param enable
|
||||
|
|
|
|||
|
|
@ -1188,5 +1188,15 @@ class LinphoneCoreImpl implements LinphoneCore {
|
|||
public void stopRinging() {
|
||||
stopRinging(nativePtr);
|
||||
}
|
||||
private native void setPayloadTypeBitrate(long coreptr, long payload_ptr, int bitrate);
|
||||
@Override
|
||||
public void setPayloadTypeBitrate(PayloadType pt, int bitrate) {
|
||||
setPayloadTypeBitrate(nativePtr, ((PayloadTypeImpl)pt).nativePtr, bitrate);
|
||||
}
|
||||
private native int getPayloadTypeBitrate(long coreptr, long payload_ptr);
|
||||
@Override
|
||||
public int getPayloadTypeBitrate(PayloadType pt) {
|
||||
return getPayloadTypeBitrate(nativePtr, ((PayloadTypeImpl)pt).nativePtr);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Subproject commit 13d0cee33672690daca1a7252c9f3a7022da95bd
|
||||
Subproject commit d51333b63b6f61c96bb861ad07e8165321c50f59
|
||||
2
oRTP
2
oRTP
|
|
@ -1 +1 @@
|
|||
Subproject commit ebd87c21d3d5c8b4775ef08af18e27c4bf4fa3ac
|
||||
Subproject commit c93363ac023c2122bfdfb8b0d99b811dffbad827
|
||||
|
|
@ -22,6 +22,8 @@ liblinphonetester_la_SOURCES = tester.c \
|
|||
stun_tester.c \
|
||||
remote_provisioning_tester.c
|
||||
|
||||
liblinphonetester_la_LDFLAGS= -no-undefined
|
||||
liblinphonetester_la_LIBADD= ../coreapi/liblinphone.la $(CUNIT_LIBS)
|
||||
|
||||
AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/coreapi
|
||||
AM_CFLAGS = $(STRICT_OPTIONS) -DIN_LINPHONE $(ORTP_CFLAGS) $(MEDIASTREAMER_CFLAGS) $(CUNIT_CFLAGS) $(BELLESIP_CFLAGS) $(LIBXML2_CFLAGS)
|
||||
|
|
@ -31,7 +33,7 @@ if !BUILD_IOS
|
|||
noinst_PROGRAMS = liblinphone_tester
|
||||
|
||||
liblinphone_tester_SOURCES = liblinphone_tester.c
|
||||
liblinphone_tester_LDADD = $(top_builddir)/coreapi/liblinphone.la liblinphonetester.la $(SIPSTACK_LIBS) $(LIBXML2_LIBS) $(CUNIT_LIBS)
|
||||
liblinphone_tester_LDADD = $(top_builddir)/coreapi/liblinphone.la liblinphonetester.la
|
||||
|
||||
endif
|
||||
|
||||
|
|
|
|||
|
|
@ -24,6 +24,8 @@
|
|||
#include "private.h"
|
||||
#include "liblinphone_tester.h"
|
||||
|
||||
static void call_base(LinphoneMediaEncryption mode, bool_t enable_video,bool_t enable_relay,LinphoneFirewallPolicy policy);
|
||||
static void disable_all_codecs_except_one(LinphoneCore *lc, const char *mime);
|
||||
|
||||
void call_state_changed(LinphoneCore *lc, LinphoneCall *call, LinphoneCallState cstate, const char *msg){
|
||||
char* to=linphone_address_as_string(linphone_call_get_call_log(call)->to);
|
||||
|
|
@ -59,7 +61,22 @@ void call_state_changed(LinphoneCore *lc, LinphoneCall *call, LinphoneCallState
|
|||
CU_FAIL("unexpected event");break;
|
||||
}
|
||||
}
|
||||
|
||||
void linphone_call_encryption_changed(LinphoneCore *lc, LinphoneCall *call, bool_t on, const char *authentication_token) {
|
||||
char* to=linphone_address_as_string(linphone_call_get_call_log(call)->to);
|
||||
char* from=linphone_address_as_string(linphone_call_get_call_log(call)->from);
|
||||
stats* counters;
|
||||
ms_message(" %s call from [%s] to [%s], is now [%s]",linphone_call_get_call_log(call)->dir==LinphoneCallIncoming?"Incoming":"Outgoing"
|
||||
,from
|
||||
,to
|
||||
,(on?"encrypted":"unencrypted"));
|
||||
ms_free(to);
|
||||
ms_free(from);
|
||||
counters = get_stats(lc);
|
||||
if (on)
|
||||
counters->number_of_LinphoneCallEncryptedOn++;
|
||||
else
|
||||
counters->number_of_LinphoneCallEncryptedOff++;
|
||||
}
|
||||
void linphone_transfer_state_changed(LinphoneCore *lc, LinphoneCall *transfered, LinphoneCallState new_call_state) {
|
||||
char* to=linphone_address_as_string(linphone_call_get_call_log(transfered)->to);
|
||||
char* from=linphone_address_as_string(linphone_call_get_call_log(transfered)->from);
|
||||
|
|
@ -103,10 +120,10 @@ void liblinphone_tester_check_rtcp(LinphoneCoreManager* caller, LinphoneCoreMana
|
|||
|
||||
c1=linphone_core_get_current_call(caller->lc);
|
||||
c2=linphone_core_get_current_call(callee->lc);
|
||||
|
||||
|
||||
CU_ASSERT_PTR_NOT_NULL(c1);
|
||||
CU_ASSERT_PTR_NOT_NULL(c2);
|
||||
|
||||
|
||||
if (!c1 || !c2) return;
|
||||
|
||||
for (i=0; i<24 /*=12s need at least one exchange of SR to maybe 10s*/; i++) {
|
||||
|
|
@ -198,12 +215,19 @@ bool_t call_with_params(LinphoneCoreManager* caller_mgr
|
|||
&&
|
||||
wait_for(callee_mgr->lc,caller_mgr->lc,&callee_mgr->stat.number_of_LinphoneCallStreamsRunning,initial_callee.number_of_LinphoneCallStreamsRunning+1);
|
||||
|
||||
if (linphone_core_get_media_encryption(caller_mgr->lc)
|
||||
&& linphone_core_get_media_encryption(callee_mgr->lc)) {
|
||||
if (linphone_core_get_media_encryption(caller_mgr->lc) != LinphoneMediaEncryptionNone
|
||||
&& linphone_core_get_media_encryption(callee_mgr->lc) != LinphoneMediaEncryptionNone) {
|
||||
/*wait for encryption to be on, in case of zrtp, it can take a few seconds*/
|
||||
if (linphone_core_get_media_encryption(caller_mgr->lc) == LinphoneMediaEncryptionZRTP)
|
||||
wait_for(callee_mgr->lc,caller_mgr->lc,&caller_mgr->stat.number_of_LinphoneCallEncryptedOn,initial_caller.number_of_LinphoneCallEncryptedOn+1);
|
||||
if (linphone_core_get_media_encryption(callee_mgr->lc) == LinphoneMediaEncryptionZRTP)
|
||||
wait_for(callee_mgr->lc,caller_mgr->lc,&callee_mgr->stat.number_of_LinphoneCallEncryptedOn,initial_callee.number_of_LinphoneCallEncryptedOn+1);
|
||||
{
|
||||
const LinphoneCallParams* call_param = linphone_call_get_current_params(linphone_core_get_current_call(callee_mgr->lc));
|
||||
CU_ASSERT_EQUAL(linphone_call_params_get_media_encryption(call_param),linphone_core_get_media_encryption(caller_mgr->lc));
|
||||
call_param = linphone_call_get_current_params(linphone_core_get_current_call(caller_mgr->lc));
|
||||
CU_ASSERT_EQUAL(linphone_call_params_get_media_encryption(call_param),linphone_core_get_media_encryption(caller_mgr->lc));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
|
@ -226,6 +250,39 @@ static void simple_call(void) {
|
|||
linphone_core_manager_destroy(pauline);
|
||||
}
|
||||
|
||||
static void call_with_specified_codec_bitrate(void) {
|
||||
LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc");
|
||||
LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc");
|
||||
const LinphoneCallStats *pauline_stats,*marie_stats;
|
||||
bool_t call_ok;
|
||||
if (linphone_core_find_payload_type(marie->lc,"opus",48000,-1)==NULL){
|
||||
ms_warning("opus codec not supported, test skipped.");
|
||||
goto end;
|
||||
}
|
||||
|
||||
disable_all_codecs_except_one(marie->lc,"opus");
|
||||
disable_all_codecs_except_one(pauline->lc,"opus");
|
||||
|
||||
linphone_core_set_payload_type_bitrate(marie->lc,
|
||||
linphone_core_find_payload_type(marie->lc,"opus",48000,-1),
|
||||
50);
|
||||
linphone_core_set_payload_type_bitrate(pauline->lc,
|
||||
linphone_core_find_payload_type(pauline->lc,"opus",48000,-1),
|
||||
24);
|
||||
|
||||
CU_ASSERT_TRUE((call_ok=call(pauline,marie)));
|
||||
if (!call_ok) goto end;
|
||||
liblinphone_tester_check_rtcp(marie,pauline);
|
||||
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));
|
||||
CU_ASSERT_TRUE(marie_stats->download_bandwidth<30);
|
||||
CU_ASSERT_TRUE(pauline_stats->download_bandwidth>45);
|
||||
|
||||
end:
|
||||
linphone_core_manager_destroy(marie);
|
||||
linphone_core_manager_destroy(pauline);
|
||||
}
|
||||
|
||||
static void simple_call_compatibility_mode(void) {
|
||||
char route[256];
|
||||
LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc");
|
||||
|
|
@ -316,7 +373,7 @@ static void cancelled_call(void) {
|
|||
static void disable_all_codecs_except_one(LinphoneCore *lc, const char *mime){
|
||||
const MSList *elem=linphone_core_get_audio_codecs(lc);
|
||||
PayloadType *pt;
|
||||
|
||||
|
||||
for(;elem!=NULL;elem=elem->next){
|
||||
pt=(PayloadType*)elem->data;
|
||||
linphone_core_enable_payload_type(lc,pt,FALSE);
|
||||
|
|
@ -351,7 +408,7 @@ static void call_with_dns_time_out(void) {
|
|||
LinphoneCoreManager* marie = linphone_core_manager_new2( "empty_rc", FALSE);
|
||||
LCSipTransports transport = {9773,0,0,0};
|
||||
int i;
|
||||
|
||||
|
||||
linphone_core_set_sip_transports(marie->lc,&transport);
|
||||
linphone_core_iterate(marie->lc);
|
||||
sal_set_dns_timeout(marie->lc->sal,0);
|
||||
|
|
@ -359,7 +416,7 @@ static void call_with_dns_time_out(void) {
|
|||
for(i=0;i<10;i++){
|
||||
ms_usleep(200000);
|
||||
linphone_core_iterate(marie->lc);
|
||||
}
|
||||
}
|
||||
CU_ASSERT_EQUAL(marie->stat.number_of_LinphoneCallOutgoingInit,1);
|
||||
CU_ASSERT_EQUAL(marie->stat.number_of_LinphoneCallOutgoingProgress,1);
|
||||
CU_ASSERT_EQUAL(marie->stat.number_of_LinphoneCallError,1);
|
||||
|
|
@ -372,21 +429,21 @@ static void early_cancelled_call(void) {
|
|||
LinphoneCoreManager* pauline = linphone_core_manager_new2( "empty_rc",FALSE);
|
||||
|
||||
LinphoneCall* out_call = linphone_core_invite_address(pauline->lc,marie->identity);
|
||||
|
||||
|
||||
CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallOutgoingInit,1));
|
||||
linphone_core_terminate_call(pauline->lc,out_call);
|
||||
|
||||
|
||||
/*since everything is executed in a row, no response can be received from the server, thus the CANCEL cannot be sent.
|
||||
It will ring at Marie's side.*/
|
||||
|
||||
|
||||
CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallEnd,1));
|
||||
|
||||
|
||||
CU_ASSERT_EQUAL(pauline->stat.number_of_LinphoneCallEnd,1);
|
||||
|
||||
|
||||
CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneCallIncomingReceived,1));
|
||||
/* now the CANCEL should have been sent and the the call at marie's side should terminate*/
|
||||
CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneCallEnd,1));
|
||||
|
||||
|
||||
CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallReleased,1));
|
||||
|
||||
linphone_core_manager_destroy(marie);
|
||||
|
|
@ -426,7 +483,7 @@ static void early_declined_call(void) {
|
|||
CU_ASSERT_TRUE(wait_for_until(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallError,1,33000));
|
||||
CU_ASSERT_EQUAL(pauline->stat.number_of_LinphoneCallError,1);
|
||||
/* FIXME http://git.linphone.org/mantis/view.php?id=757
|
||||
|
||||
|
||||
CU_ASSERT_EQUAL(linphone_call_get_reason(out_call),LinphoneReasonBusy);
|
||||
*/
|
||||
if (ms_list_size(linphone_core_get_call_logs(pauline->lc))>0) {
|
||||
|
|
@ -466,7 +523,7 @@ static void call_declined(void) {
|
|||
static void call_terminated_by_caller(void) {
|
||||
LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc");
|
||||
LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc");
|
||||
|
||||
|
||||
CU_ASSERT_TRUE(call(pauline,marie));
|
||||
/*just to sleep*/
|
||||
linphone_core_terminate_all_calls(pauline->lc);
|
||||
|
|
@ -480,7 +537,7 @@ static void call_terminated_by_caller(void) {
|
|||
static void call_with_no_sdp(void) {
|
||||
LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc");
|
||||
LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc");
|
||||
|
||||
|
||||
linphone_core_enable_sdp_200_ack(marie->lc,TRUE);
|
||||
|
||||
CU_ASSERT_TRUE(call(marie,pauline));
|
||||
|
|
@ -500,7 +557,7 @@ static bool_t check_ice(LinphoneCoreManager* caller, LinphoneCoreManager* callee
|
|||
|
||||
c1=linphone_core_get_current_call(caller->lc);
|
||||
c2=linphone_core_get_current_call(callee->lc);
|
||||
|
||||
|
||||
CU_ASSERT_PTR_NOT_NULL(c1);
|
||||
CU_ASSERT_PTR_NOT_NULL(c2);
|
||||
|
||||
|
|
@ -516,18 +573,33 @@ static bool_t check_ice(LinphoneCoreManager* caller, LinphoneCoreManager* callee
|
|||
}
|
||||
ms_usleep(50000);
|
||||
}
|
||||
|
||||
/*make sure encryption mode are preserved*/
|
||||
if (c1) {
|
||||
const LinphoneCallParams* call_param = linphone_call_get_current_params(c1);
|
||||
CU_ASSERT_EQUAL(linphone_call_params_get_media_encryption(call_param),linphone_core_get_media_encryption(caller->lc));
|
||||
}
|
||||
if (c2) {
|
||||
const LinphoneCallParams* call_param = linphone_call_get_current_params(c2);
|
||||
CU_ASSERT_EQUAL(linphone_call_params_get_media_encryption(call_param),linphone_core_get_media_encryption(callee->lc));
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
static void _call_with_ice(bool_t random_ports) {
|
||||
static void _call_with_ice(bool_t caller_with_ice, bool_t callee_with_ice, bool_t random_ports) {
|
||||
LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc");
|
||||
LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc");
|
||||
|
||||
linphone_core_set_firewall_policy(marie->lc,LinphonePolicyUseIce);
|
||||
linphone_core_set_stun_server(marie->lc,"stun.linphone.org");
|
||||
linphone_core_set_firewall_policy(pauline->lc,LinphonePolicyUseIce);
|
||||
linphone_core_set_stun_server(pauline->lc,"stun.linphone.org");
|
||||
|
||||
|
||||
if (callee_with_ice){
|
||||
linphone_core_set_firewall_policy(marie->lc,LinphonePolicyUseIce);
|
||||
linphone_core_set_stun_server(marie->lc,"stun.linphone.org");
|
||||
}
|
||||
if (caller_with_ice){
|
||||
linphone_core_set_firewall_policy(pauline->lc,LinphonePolicyUseIce);
|
||||
linphone_core_set_stun_server(pauline->lc,"stun.linphone.org");
|
||||
}
|
||||
|
||||
if (random_ports){
|
||||
linphone_core_set_audio_port(marie->lc,-1);
|
||||
linphone_core_set_video_port(marie->lc,-1);
|
||||
|
|
@ -537,11 +609,15 @@ static void _call_with_ice(bool_t random_ports) {
|
|||
|
||||
CU_ASSERT_TRUE(call(pauline,marie));
|
||||
|
||||
CU_ASSERT_TRUE(check_ice(pauline,marie,LinphoneIceStateHostConnection));
|
||||
/*wait for the ICE reINVITE to complete*/
|
||||
CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallStreamsRunning,2));
|
||||
CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneCallStreamsRunning,2));
|
||||
|
||||
if (callee_with_ice && caller_with_ice) {
|
||||
check_ice(pauline,marie,LinphoneIceStateHostConnection);
|
||||
/*wait for the ICE reINVITE to complete*/
|
||||
CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallStreamsRunning,2));
|
||||
CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneCallStreamsRunning,2));
|
||||
|
||||
CU_ASSERT_TRUE(check_ice(pauline,marie,LinphoneIceStateHostConnection));
|
||||
}
|
||||
|
||||
liblinphone_tester_check_rtcp(marie,pauline);
|
||||
/*then close the call*/
|
||||
linphone_core_terminate_all_calls(pauline->lc);
|
||||
|
|
@ -553,11 +629,19 @@ static void _call_with_ice(bool_t random_ports) {
|
|||
}
|
||||
|
||||
static void call_with_ice(void){
|
||||
_call_with_ice(FALSE);
|
||||
_call_with_ice(TRUE,TRUE,FALSE);
|
||||
}
|
||||
|
||||
static void call_with_ice_random_ports(void){
|
||||
_call_with_ice(TRUE);
|
||||
_call_with_ice(TRUE,TRUE,TRUE);
|
||||
}
|
||||
|
||||
static void ice_to_not_ice(void){
|
||||
_call_with_ice(TRUE,FALSE,FALSE);
|
||||
}
|
||||
|
||||
static void not_ice_to_ice(void){
|
||||
_call_with_ice(FALSE,TRUE,FALSE);
|
||||
}
|
||||
|
||||
static void call_with_custom_headers(void) {
|
||||
|
|
@ -579,17 +663,17 @@ static void call_with_custom_headers(void) {
|
|||
ms_free(tmp);
|
||||
linphone_address_destroy(marie->identity);
|
||||
marie->identity=marie_identity;
|
||||
|
||||
|
||||
params=linphone_core_create_default_call_parameters(marie->lc);
|
||||
linphone_call_params_add_custom_header(params,"Weather","bad");
|
||||
linphone_call_params_add_custom_header(params,"Working","yes");
|
||||
|
||||
|
||||
CU_ASSERT_TRUE(call_with_caller_params(pauline,marie,params));
|
||||
linphone_call_params_destroy(params);
|
||||
|
||||
|
||||
call_marie=linphone_core_get_current_call(marie->lc);
|
||||
call_pauline=linphone_core_get_current_call(pauline->lc);
|
||||
|
||||
|
||||
CU_ASSERT_PTR_NOT_NULL(call_marie);
|
||||
CU_ASSERT_PTR_NOT_NULL(call_pauline);
|
||||
|
||||
|
|
@ -701,6 +785,15 @@ static bool_t add_video(LinphoneCoreManager* caller,LinphoneCoreManager* callee)
|
|||
LinphoneVideoPolicy caller_policy;
|
||||
LinphoneCallParams* callee_params;
|
||||
LinphoneCall* call_obj;
|
||||
stats initial_caller_stat=caller->stat;
|
||||
stats initial_callee_stat=callee->stat;
|
||||
|
||||
if (linphone_call_get_state(linphone_core_get_current_call(callee->lc)) != LinphoneCallStreamsRunning
|
||||
|| linphone_call_get_state(linphone_core_get_current_call(caller->lc)) != LinphoneCallStreamsRunning ) {
|
||||
ms_warning("bad state for adding video");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
caller_policy.automatically_accept=TRUE;
|
||||
caller_policy.automatically_initiate=TRUE;
|
||||
linphone_core_enable_video_capture(callee->lc, TRUE);
|
||||
|
|
@ -708,8 +801,8 @@ static bool_t add_video(LinphoneCoreManager* caller,LinphoneCoreManager* callee)
|
|||
linphone_core_enable_video_capture(caller->lc, TRUE);
|
||||
linphone_core_enable_video_display(caller->lc, FALSE);
|
||||
linphone_core_set_video_policy(caller->lc,&caller_policy);
|
||||
stats initial_caller_stat=caller->stat;
|
||||
stats initial_callee_stat=callee->stat;
|
||||
|
||||
|
||||
|
||||
if ((call_obj = linphone_core_get_current_call(callee->lc))) {
|
||||
callee_params = linphone_call_params_copy(linphone_call_get_current_params(call_obj));
|
||||
|
|
@ -724,6 +817,21 @@ static bool_t add_video(LinphoneCoreManager* caller,LinphoneCoreManager* callee)
|
|||
|
||||
CU_ASSERT_TRUE(linphone_call_params_video_enabled(linphone_call_get_current_params(linphone_core_get_current_call(callee->lc))));
|
||||
CU_ASSERT_TRUE(linphone_call_params_video_enabled(linphone_call_get_current_params(linphone_core_get_current_call(caller->lc))));
|
||||
if (linphone_core_get_media_encryption(caller->lc) != LinphoneMediaEncryptionNone
|
||||
&& linphone_core_get_media_encryption(callee->lc) != LinphoneMediaEncryptionNone) {
|
||||
/*wait for encryption to be on, in case of zrtp, it can take a few seconds*/
|
||||
if (linphone_core_get_media_encryption(caller->lc) == LinphoneMediaEncryptionZRTP)
|
||||
wait_for(callee->lc,caller->lc,&caller->stat.number_of_LinphoneCallEncryptedOn,initial_caller_stat.number_of_LinphoneCallEncryptedOn+1);
|
||||
if (linphone_core_get_media_encryption(callee->lc) == LinphoneMediaEncryptionZRTP)
|
||||
wait_for(callee->lc,caller->lc,&callee->stat.number_of_LinphoneCallEncryptedOn,initial_callee_stat.number_of_LinphoneCallEncryptedOn+1);
|
||||
|
||||
{
|
||||
const LinphoneCallParams* call_param = linphone_call_get_current_params(linphone_core_get_current_call(callee->lc));
|
||||
CU_ASSERT_EQUAL(linphone_call_params_get_media_encryption(call_param),linphone_core_get_media_encryption(caller->lc));
|
||||
call_param = linphone_call_get_current_params(linphone_core_get_current_call(caller->lc));
|
||||
CU_ASSERT_EQUAL(linphone_call_params_get_media_encryption(call_param),linphone_core_get_media_encryption(caller->lc));
|
||||
}
|
||||
}
|
||||
|
||||
linphone_call_set_next_video_frame_decoded_callback(call_obj,linphone_call_cb,callee->lc);
|
||||
/*send vfu*/
|
||||
|
|
@ -750,12 +858,12 @@ static void call_with_video_added(void) {
|
|||
static void call_with_video_added_random_ports(void) {
|
||||
LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc");
|
||||
LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc");
|
||||
|
||||
|
||||
linphone_core_set_audio_port(marie->lc,-1);
|
||||
linphone_core_set_video_port(marie->lc,-1);
|
||||
linphone_core_set_audio_port(pauline->lc,-1);
|
||||
linphone_core_set_video_port(pauline->lc,-1);
|
||||
|
||||
|
||||
CU_ASSERT_TRUE(call(pauline,marie));
|
||||
|
||||
CU_ASSERT_TRUE(add_video(pauline,marie));
|
||||
|
|
@ -822,19 +930,21 @@ static void video_call(void) {
|
|||
marie_call=linphone_core_get_current_call(marie->lc);
|
||||
pauline_call=linphone_core_get_current_call(pauline->lc);
|
||||
|
||||
CU_ASSERT_TRUE(linphone_call_log_video_enabled(linphone_call_get_call_log(marie_call)));
|
||||
CU_ASSERT_TRUE(linphone_call_log_video_enabled(linphone_call_get_call_log(pauline_call)));
|
||||
if (marie_call && pauline_call ) {
|
||||
CU_ASSERT_TRUE(linphone_call_log_video_enabled(linphone_call_get_call_log(marie_call)));
|
||||
CU_ASSERT_TRUE(linphone_call_log_video_enabled(linphone_call_get_call_log(pauline_call)));
|
||||
|
||||
/*check video path*/
|
||||
linphone_call_set_next_video_frame_decoded_callback(marie_call,linphone_call_cb,marie->lc);
|
||||
linphone_call_send_vfu_request(marie_call);
|
||||
CU_ASSERT_TRUE( wait_for(marie->lc,pauline->lc,&marie->stat.number_of_IframeDecoded,1));
|
||||
/*check video path*/
|
||||
linphone_call_set_next_video_frame_decoded_callback(marie_call,linphone_call_cb,marie->lc);
|
||||
linphone_call_send_vfu_request(marie_call);
|
||||
CU_ASSERT_TRUE( wait_for(marie->lc,pauline->lc,&marie->stat.number_of_IframeDecoded,1));
|
||||
|
||||
liblinphone_tester_check_rtcp(marie,pauline);
|
||||
liblinphone_tester_check_rtcp(marie,pauline);
|
||||
|
||||
linphone_core_terminate_all_calls(pauline->lc);
|
||||
CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallEnd,1));
|
||||
CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneCallEnd,1));
|
||||
linphone_core_terminate_all_calls(pauline->lc);
|
||||
CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallEnd,1));
|
||||
CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneCallEnd,1));
|
||||
}
|
||||
|
||||
linphone_core_manager_destroy(marie);
|
||||
linphone_core_manager_destroy(pauline);
|
||||
|
|
@ -846,17 +956,17 @@ static void _call_with_media_relay(bool_t random_ports) {
|
|||
LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc");
|
||||
linphone_core_set_user_agent(marie->lc,"Natted Linphone",NULL);
|
||||
linphone_core_set_user_agent(pauline->lc,"Natted Linphone",NULL);
|
||||
|
||||
|
||||
if (random_ports){
|
||||
linphone_core_set_audio_port(marie->lc,-1);
|
||||
linphone_core_set_video_port(marie->lc,-1);
|
||||
linphone_core_set_audio_port(pauline->lc,-1);
|
||||
linphone_core_set_video_port(pauline->lc,-1);
|
||||
}
|
||||
|
||||
|
||||
CU_ASSERT_TRUE(call(pauline,marie));
|
||||
liblinphone_tester_check_rtcp(pauline,marie);
|
||||
|
||||
|
||||
#ifdef VIDEO_ENABLED
|
||||
CU_ASSERT_TRUE(add_video(pauline,marie));
|
||||
liblinphone_tester_check_rtcp(pauline,marie);
|
||||
|
|
@ -942,7 +1052,7 @@ static void call_with_privacy2(void) {
|
|||
LinphoneProxyConfig* pauline_proxy;
|
||||
params=linphone_core_create_default_call_parameters(pauline->lc);
|
||||
linphone_call_params_set_privacy(params,LinphonePrivacyId);
|
||||
|
||||
|
||||
linphone_core_get_default_proxy(pauline->lc,&pauline_proxy);
|
||||
linphone_proxy_config_edit(pauline_proxy);
|
||||
linphone_proxy_config_enable_register(pauline_proxy,FALSE);
|
||||
|
|
@ -1136,46 +1246,16 @@ static void simple_conference(void) {
|
|||
ms_list_free(lcs);
|
||||
}
|
||||
|
||||
|
||||
static void encrypted_call(LinphoneMediaEncryption mode) {
|
||||
LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc");
|
||||
LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc");
|
||||
|
||||
if (linphone_core_media_encryption_supported(marie->lc,mode)) {
|
||||
linphone_core_set_media_encryption(marie->lc,mode);
|
||||
linphone_core_set_media_encryption(pauline->lc,mode);
|
||||
|
||||
CU_ASSERT_TRUE(call(pauline,marie));
|
||||
|
||||
CU_ASSERT_EQUAL(linphone_core_get_media_encryption(marie->lc),mode);
|
||||
CU_ASSERT_EQUAL(linphone_core_get_media_encryption(pauline->lc),mode);
|
||||
if (linphone_core_get_media_encryption(pauline->lc) == LinphoneMediaEncryptionZRTP
|
||||
&& linphone_core_get_media_encryption(pauline->lc) == LinphoneMediaEncryptionZRTP) {
|
||||
/*check SAS*/
|
||||
CU_ASSERT_STRING_EQUAL(linphone_call_get_authentication_token(linphone_core_get_current_call(pauline->lc))
|
||||
,linphone_call_get_authentication_token(linphone_core_get_current_call(marie->lc)));
|
||||
}
|
||||
liblinphone_tester_check_rtcp(pauline,marie);
|
||||
/*just to sleep*/
|
||||
linphone_core_terminate_all_calls(marie->lc);
|
||||
CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallEnd,1));
|
||||
CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneCallEnd,1));
|
||||
} else {
|
||||
ms_warning ("Not tested because %s not available", linphone_media_encryption_to_string(mode));
|
||||
}
|
||||
linphone_core_manager_destroy(marie);
|
||||
linphone_core_manager_destroy(pauline);
|
||||
}
|
||||
|
||||
static void srtp_call() {
|
||||
encrypted_call(LinphoneMediaEncryptionSRTP);
|
||||
call_base(LinphoneMediaEncryptionSRTP,FALSE,FALSE,LinphonePolicyNoFirewall);
|
||||
}
|
||||
|
||||
/*
|
||||
* future work
|
||||
static void zrtp_call() {
|
||||
encrypted_call(LinphoneMediaEncryptionZRTP);
|
||||
}*/
|
||||
call_base(LinphoneMediaEncryptionZRTP,FALSE,FALSE,LinphonePolicyNoFirewall);
|
||||
}
|
||||
static void zrtp_video_call() {
|
||||
call_base(LinphoneMediaEncryptionZRTP,TRUE,FALSE,LinphonePolicyNoFirewall);
|
||||
}
|
||||
|
||||
static void call_with_declined_srtp(void) {
|
||||
LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc");
|
||||
|
|
@ -1195,58 +1275,103 @@ static void call_with_declined_srtp(void) {
|
|||
linphone_core_manager_destroy(marie);
|
||||
linphone_core_manager_destroy(pauline);
|
||||
}
|
||||
#ifdef VIDEO_ENABLED
|
||||
static void srtp_video_ice_call(void) {
|
||||
int i=0;
|
||||
#else
|
||||
static void srtp_ice_call(void) {
|
||||
#endif
|
||||
|
||||
static void call_base(LinphoneMediaEncryption mode, bool_t enable_video,bool_t enable_relay,LinphoneFirewallPolicy policy) {
|
||||
LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc");
|
||||
LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc");
|
||||
if (enable_relay) {
|
||||
linphone_core_set_user_agent(marie->lc,"Natted Linphone",NULL);
|
||||
linphone_core_set_user_agent(pauline->lc,"Natted Linphone",NULL);
|
||||
}
|
||||
if (linphone_core_media_encryption_supported(marie->lc,mode)) {
|
||||
linphone_core_set_media_encryption(marie->lc,mode);
|
||||
linphone_core_set_media_encryption(pauline->lc,mode);
|
||||
|
||||
if (linphone_core_media_encryption_supported(marie->lc,LinphoneMediaEncryptionSRTP)) {
|
||||
linphone_core_set_media_encryption(marie->lc,LinphoneMediaEncryptionSRTP);
|
||||
linphone_core_set_media_encryption(pauline->lc,LinphoneMediaEncryptionSRTP);
|
||||
|
||||
linphone_core_set_firewall_policy(marie->lc,LinphonePolicyUseIce);
|
||||
linphone_core_set_firewall_policy(marie->lc,policy);
|
||||
linphone_core_set_stun_server(marie->lc,"stun.linphone.org");
|
||||
linphone_core_set_firewall_policy(pauline->lc,LinphonePolicyUseIce);
|
||||
linphone_core_set_firewall_policy(pauline->lc,policy);
|
||||
linphone_core_set_stun_server(pauline->lc,"stun.linphone.org");
|
||||
|
||||
|
||||
CU_ASSERT_TRUE(call(pauline,marie));
|
||||
if (linphone_core_get_media_encryption(pauline->lc) == LinphoneMediaEncryptionZRTP
|
||||
&& linphone_core_get_media_encryption(pauline->lc) == LinphoneMediaEncryptionZRTP) {
|
||||
/*wait for SAS*/
|
||||
int i;
|
||||
for (i=0;i<10;i++) {
|
||||
if (linphone_call_get_authentication_token(linphone_core_get_current_call(pauline->lc))
|
||||
&&
|
||||
linphone_call_get_authentication_token(linphone_core_get_current_call(marie->lc))) {
|
||||
/*check SAS*/
|
||||
CU_ASSERT_STRING_EQUAL(linphone_call_get_authentication_token(linphone_core_get_current_call(pauline->lc))
|
||||
,linphone_call_get_authentication_token(linphone_core_get_current_call(marie->lc)));
|
||||
liblinphone_tester_check_rtcp(pauline,marie);
|
||||
break;
|
||||
}
|
||||
linphone_core_iterate(marie->lc);
|
||||
linphone_core_iterate(pauline->lc);
|
||||
ms_usleep(200000);
|
||||
}
|
||||
|
||||
CU_ASSERT_TRUE(check_ice(pauline,marie,LinphoneIceStateHostConnection));
|
||||
#ifdef VIDEO_ENABLED
|
||||
for (i=0;i<100;i++) { /*fixme to workaround a crash*/
|
||||
ms_usleep(20000);
|
||||
linphone_core_iterate(marie->lc);
|
||||
linphone_core_iterate(pauline->lc);
|
||||
}
|
||||
|
||||
add_video(pauline,marie);
|
||||
if (policy == LinphonePolicyUseIce)
|
||||
CU_ASSERT_TRUE(check_ice(pauline,marie,LinphoneIceStateHostConnection));
|
||||
#ifdef VIDEO_ENABLED
|
||||
if (enable_video) {
|
||||
int i=0;
|
||||
if (linphone_core_video_supported(marie->lc)) {
|
||||
for (i=0;i<100;i++) { /*fixme to workaround a crash*/
|
||||
ms_usleep(20000);
|
||||
linphone_core_iterate(marie->lc);
|
||||
linphone_core_iterate(pauline->lc);
|
||||
}
|
||||
|
||||
CU_ASSERT_TRUE(check_ice(pauline,marie,LinphoneIceStateHostConnection));
|
||||
liblinphone_tester_check_rtcp(marie,pauline);
|
||||
/*wait for ice to found the direct path*/
|
||||
CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_IframeDecoded,1));
|
||||
add_video(pauline,marie);
|
||||
if (policy == LinphonePolicyUseIce)
|
||||
CU_ASSERT_TRUE(check_ice(pauline,marie,LinphoneIceStateHostConnection));
|
||||
|
||||
liblinphone_tester_check_rtcp(marie,pauline);
|
||||
/*wait for ice to found the direct path*/
|
||||
CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_IframeDecoded,1));
|
||||
} else {
|
||||
ms_warning ("not tested because video not available");
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/*just to sleep*/
|
||||
linphone_core_terminate_all_calls(marie->lc);
|
||||
CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallEnd,1));
|
||||
CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneCallEnd,1));
|
||||
} else {
|
||||
ms_warning ("not tested because srtp not available");
|
||||
ms_warning ("not tested because %s not available", linphone_media_encryption_to_string(mode));
|
||||
}
|
||||
linphone_core_manager_destroy(marie);
|
||||
linphone_core_manager_destroy(pauline);
|
||||
}
|
||||
|
||||
#ifdef VIDEO_ENABLED
|
||||
static void srtp_video_ice_call(void) {
|
||||
call_base(LinphoneMediaEncryptionSRTP,TRUE,FALSE,LinphonePolicyUseIce);
|
||||
}
|
||||
static void zrtp_video_ice_call(void) {
|
||||
call_base(LinphoneMediaEncryptionZRTP,TRUE,FALSE,LinphonePolicyUseIce);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void srtp_ice_call(void) {
|
||||
call_base(LinphoneMediaEncryptionSRTP,FALSE,FALSE,LinphonePolicyUseIce);
|
||||
}
|
||||
|
||||
|
||||
static void zrtp_ice_call(void) {
|
||||
call_base(LinphoneMediaEncryptionZRTP,FALSE,FALSE,LinphonePolicyUseIce);
|
||||
}
|
||||
static void zrtp_ice_call_with_relay(void) {
|
||||
call_base(LinphoneMediaEncryptionZRTP,FALSE,TRUE,LinphonePolicyUseIce);
|
||||
}
|
||||
|
||||
static void early_media_call(void) {
|
||||
LinphoneCoreManager* marie = linphone_core_manager_new( "marie_early_rc");
|
||||
|
|
@ -1256,19 +1381,19 @@ static void early_media_call(void) {
|
|||
|
||||
CU_ASSERT_EQUAL(marie->stat.number_of_LinphoneCallIncomingEarlyMedia,1);
|
||||
CU_ASSERT_EQUAL(pauline->stat.number_of_LinphoneCallOutgoingEarlyMedia,1);
|
||||
|
||||
|
||||
wait_for_until(pauline->lc,marie->lc,NULL,0,1000);
|
||||
|
||||
|
||||
/*added because a bug related to early-media caused the Connected state to be reached two times*/
|
||||
CU_ASSERT_EQUAL(marie->stat.number_of_LinphoneCallConnected,1);
|
||||
|
||||
|
||||
/*just to sleep*/
|
||||
linphone_core_terminate_all_calls(marie->lc);
|
||||
CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallEnd,1));
|
||||
CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneCallEnd,1));
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
linphone_core_manager_destroy(marie);
|
||||
linphone_core_manager_destroy(pauline);
|
||||
}
|
||||
|
|
@ -1285,7 +1410,7 @@ static void early_media_call_with_ringing(void){
|
|||
/*
|
||||
Marie calls Pauline, and after the call has rung, transitions to an early_media session
|
||||
*/
|
||||
|
||||
|
||||
/*use playfile for callee to avoid locking on capture card*/
|
||||
linphone_core_use_files (pauline->lc,TRUE);
|
||||
snprintf(hellopath,sizeof(hellopath), "%s/sounds/hello8000.wav", liblinphone_tester_file_prefix);
|
||||
|
|
@ -1297,31 +1422,32 @@ static void early_media_call_with_ringing(void){
|
|||
CU_ASSERT_TRUE(wait_for_list(lcs, &marie->stat.number_of_LinphoneCallOutgoingRinging,1,1000));
|
||||
|
||||
|
||||
/* send a 183 to initiate the early media */
|
||||
if (linphone_core_inc_invite_pending(pauline->lc)) {
|
||||
/* send a 183 to initiate the early media */
|
||||
|
||||
linphone_core_accept_early_media(pauline->lc, linphone_core_get_current_call(pauline->lc));
|
||||
linphone_core_accept_early_media(pauline->lc, linphone_core_get_current_call(pauline->lc));
|
||||
|
||||
CU_ASSERT_TRUE( wait_for_list(lcs, &pauline->stat.number_of_LinphoneCallIncomingEarlyMedia,1,2000) );
|
||||
CU_ASSERT_TRUE( wait_for_list(lcs, &marie->stat.number_of_LinphoneCallOutgoingEarlyMedia,1,2000) );
|
||||
CU_ASSERT_TRUE( wait_for_list(lcs, &pauline->stat.number_of_LinphoneCallIncomingEarlyMedia,1,2000) );
|
||||
CU_ASSERT_TRUE( wait_for_list(lcs, &marie->stat.number_of_LinphoneCallOutgoingEarlyMedia,1,2000) );
|
||||
|
||||
liblinphone_tester_check_rtcp(marie, pauline);
|
||||
liblinphone_tester_check_rtcp(marie, pauline);
|
||||
|
||||
linphone_core_accept_call(pauline->lc, linphone_core_get_current_call(pauline->lc));
|
||||
linphone_core_accept_call(pauline->lc, linphone_core_get_current_call(pauline->lc));
|
||||
|
||||
CU_ASSERT_TRUE(wait_for_list(lcs, &marie->stat.number_of_LinphoneCallStreamsRunning, 1,1000));
|
||||
CU_ASSERT_TRUE(wait_for_list(lcs, &marie->stat.number_of_LinphoneCallStreamsRunning, 1,1000));
|
||||
|
||||
CU_ASSERT_EQUAL(marie_call, linphone_core_get_current_call(marie->lc));
|
||||
CU_ASSERT_EQUAL(marie_call, linphone_core_get_current_call(marie->lc));
|
||||
|
||||
liblinphone_tester_check_rtcp(marie, pauline);
|
||||
liblinphone_tester_check_rtcp(marie, pauline);
|
||||
|
||||
linphone_core_terminate_all_calls(pauline->lc);
|
||||
linphone_core_terminate_all_calls(pauline->lc);
|
||||
|
||||
CU_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneCallEnd,1,1000));
|
||||
CU_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneCallEnd,1,1000));
|
||||
CU_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneCallEnd,1,1000));
|
||||
CU_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneCallEnd,1,1000));
|
||||
|
||||
|
||||
ms_list_free(lcs);
|
||||
|
||||
ms_list_free(lcs);
|
||||
}
|
||||
linphone_core_manager_destroy(marie);
|
||||
linphone_core_manager_destroy(pauline);
|
||||
}
|
||||
|
|
@ -1444,9 +1570,9 @@ static void simple_call_transfer(void) {
|
|||
CU_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneCallPaused,1,2000));
|
||||
/*marie calling laure*/
|
||||
CU_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneCallOutgoingProgress,1,2000));
|
||||
|
||||
|
||||
CU_ASSERT_PTR_NOT_NULL(linphone_call_get_transfer_target_call(marie_calling_pauline));
|
||||
|
||||
|
||||
CU_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneTransferCallOutgoingInit,1,2000));
|
||||
CU_ASSERT_TRUE(wait_for_list(lcs,&laure->stat.number_of_LinphoneCallIncomingReceived,1,2000));
|
||||
CU_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneCallOutgoingRinging,1,2000));
|
||||
|
|
@ -1456,11 +1582,11 @@ static void simple_call_transfer(void) {
|
|||
CU_ASSERT_TRUE(wait_for_list(lcs,&laure->stat.number_of_LinphoneCallStreamsRunning,1,2000));
|
||||
CU_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneCallConnected,1,2000));
|
||||
CU_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneCallStreamsRunning,1,2000));
|
||||
|
||||
|
||||
marie_calling_laure=linphone_core_get_current_call(marie->lc);
|
||||
CU_ASSERT_PTR_NOT_NULL_FATAL(marie_calling_laure);
|
||||
CU_ASSERT_TRUE(linphone_call_get_transferer_call(marie_calling_laure)==marie_calling_pauline);
|
||||
|
||||
|
||||
CU_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneTransferCallConnected,1,2000));
|
||||
|
||||
/*terminate marie to pauline call*/
|
||||
|
|
@ -1494,11 +1620,11 @@ static void unattended_call_transfer(void) {
|
|||
|
||||
linphone_core_transfer_call(marie->lc,pauline_called_by_marie,laure_identity);
|
||||
CU_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneCallRefered,1,2000));
|
||||
|
||||
|
||||
/*marie ends the call */
|
||||
linphone_core_terminate_call(marie->lc,pauline_called_by_marie);
|
||||
CU_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneCallEnd,1,2000));
|
||||
|
||||
|
||||
/*Pauline starts the transfer*/
|
||||
CU_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneCallOutgoingInit,1,2000));
|
||||
CU_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneCallOutgoingProgress,1,2000));
|
||||
|
|
@ -1535,21 +1661,21 @@ static void unattended_call_transfer_with_error(void) {
|
|||
|
||||
linphone_core_transfer_call(marie->lc,pauline_called_by_marie,"unknown_user");
|
||||
CU_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneCallRefered,1,2000));
|
||||
|
||||
|
||||
/*Pauline starts the transfer*/
|
||||
CU_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneCallOutgoingInit,1,2000));
|
||||
/* and immediately get an error*/
|
||||
CU_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneCallError,1,2000));
|
||||
|
||||
|
||||
/*the error must be reported back to marie*/
|
||||
CU_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneTransferCallError,1,2000));
|
||||
|
||||
/*and pauline should resume the call automatically*/
|
||||
CU_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneCallResuming,1,2000));
|
||||
|
||||
|
||||
/*and call should be resumed*/
|
||||
CU_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneCallStreamsRunning,1,2000));
|
||||
|
||||
|
||||
linphone_core_manager_destroy(marie);
|
||||
linphone_core_manager_destroy(pauline);
|
||||
ms_list_free(lcs);
|
||||
|
|
@ -1703,7 +1829,7 @@ static void call_established_with_rejected_incoming_reinvite(void) {
|
|||
LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc");
|
||||
|
||||
CU_ASSERT_TRUE(call(pauline,marie));
|
||||
|
||||
|
||||
/*wait for ACK to be transmitted before going to reINVITE*/
|
||||
wait_for_until(marie->lc,pauline->lc,NULL,0,1000);
|
||||
|
||||
|
|
@ -1748,7 +1874,7 @@ static void call_redirect(void){
|
|||
/*
|
||||
Marie calls Pauline, which will redirect the call to Laure via a 302
|
||||
*/
|
||||
|
||||
|
||||
/*use playfile for callee to avoid locking on capture card*/
|
||||
linphone_core_use_files (pauline->lc,TRUE);
|
||||
linphone_core_use_files (laure->lc,TRUE);
|
||||
|
|
@ -1786,7 +1912,7 @@ static void call_redirect(void){
|
|||
CU_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneCallEnd,1,1000));
|
||||
|
||||
ms_list_free(lcs);
|
||||
|
||||
|
||||
linphone_core_manager_destroy(marie);
|
||||
linphone_core_manager_destroy(pauline);
|
||||
linphone_core_manager_destroy(laure);
|
||||
|
|
@ -1875,6 +2001,98 @@ static void call_rejected_without_403_because_wrong_credentials_no_auth_req_cb()
|
|||
call_rejected_because_wrong_credentials_with_params("tester-no-403",FALSE);
|
||||
}
|
||||
|
||||
void create_call_for_statistics_tests(
|
||||
LinphoneCoreManager* marie,
|
||||
LinphoneCoreManager* pauline,
|
||||
LinphoneCall** call_marie,
|
||||
LinphoneCall** call_pauline) {
|
||||
CU_ASSERT_TRUE(call(pauline,marie));
|
||||
*call_marie = linphone_core_get_current_call(marie->lc);
|
||||
*call_pauline = linphone_core_get_current_call(pauline->lc);
|
||||
CU_ASSERT_PTR_NOT_NULL(*call_marie);
|
||||
CU_ASSERT_PTR_NOT_NULL(*call_pauline);
|
||||
}
|
||||
|
||||
static void statistics_not_used_without_config() {
|
||||
LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc");
|
||||
LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc");
|
||||
LinphoneCall* call_marie = NULL;
|
||||
LinphoneCall* call_pauline = NULL;
|
||||
|
||||
create_call_for_statistics_tests(marie, pauline, &call_marie, &call_pauline);
|
||||
|
||||
// marie has stats collection enabled since pauline has not
|
||||
CU_ASSERT_TRUE(linphone_proxy_config_send_statistics_enabled(call_marie->dest_proxy));
|
||||
CU_ASSERT_FALSE(linphone_proxy_config_send_statistics_enabled(call_pauline->dest_proxy));
|
||||
|
||||
CU_ASSERT_EQUAL(strcmp("sip:collector@sip.example.org",
|
||||
linphone_proxy_config_get_statistics_collector(call_marie->dest_proxy)), 0);
|
||||
|
||||
// this field should be already filled
|
||||
CU_ASSERT_PTR_NOT_NULL(call_marie->log->reports[0]->info.local_addr.ip);
|
||||
CU_ASSERT_PTR_NULL(call_pauline->log->reports[0]->info.local_addr.ip);
|
||||
|
||||
// but not this one since it is updated at the end of call
|
||||
CU_ASSERT_PTR_NULL(call_marie->log->reports[0]->dialog_id);
|
||||
|
||||
linphone_core_manager_destroy(marie);
|
||||
linphone_core_manager_destroy(pauline);
|
||||
}
|
||||
static void statistics_not_sent_if_call_not_started() {
|
||||
LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc");
|
||||
LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc");
|
||||
LinphoneCallLog* out_call_log;
|
||||
LinphoneCall* out_call;
|
||||
|
||||
linphone_core_set_max_calls(pauline->lc,0);
|
||||
out_call = linphone_core_invite(marie->lc,"pauline");
|
||||
linphone_call_ref(out_call);
|
||||
|
||||
CU_ASSERT_TRUE(wait_for_until(marie->lc,pauline->lc,&marie->stat.number_of_LinphoneCallError,1, 10000));
|
||||
CU_ASSERT_EQUAL(marie->stat.number_of_LinphoneCallError,1);
|
||||
|
||||
if (ms_list_size(linphone_core_get_call_logs(marie->lc))>0) {
|
||||
CU_ASSERT_PTR_NOT_NULL(out_call_log=(LinphoneCallLog*)(linphone_core_get_call_logs(marie->lc)->data));
|
||||
CU_ASSERT_EQUAL(linphone_call_log_get_status(out_call_log),LinphoneCallAborted);
|
||||
}
|
||||
linphone_call_unref(out_call);
|
||||
|
||||
// wait a few time...
|
||||
wait_for(marie->lc,NULL,NULL,0);
|
||||
// since the callee was busy, there should be no publish to do
|
||||
CU_ASSERT_EQUAL(marie->stat.number_of_LinphonePublishProgress,0);
|
||||
CU_ASSERT_EQUAL(marie->stat.number_of_LinphonePublishOk,0);
|
||||
|
||||
linphone_core_manager_destroy(marie);
|
||||
linphone_core_manager_destroy(pauline);
|
||||
}
|
||||
static void statistics_sent_at_call_termination() {
|
||||
// int return_code = -1;
|
||||
LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc");
|
||||
LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc");
|
||||
LinphoneCall* call_marie = NULL;
|
||||
LinphoneCall* call_pauline = NULL;
|
||||
|
||||
create_call_for_statistics_tests(marie, pauline, &call_marie, &call_pauline);
|
||||
|
||||
linphone_core_terminate_all_calls(marie->lc);
|
||||
CU_ASSERT_TRUE(wait_for_until(marie->lc,pauline->lc,&marie->stat.number_of_LinphoneCallReleased,1, 10000));
|
||||
CU_ASSERT_TRUE(wait_for_until(pauline->lc,NULL,&pauline->stat.number_of_LinphoneCallReleased,1, 10000));
|
||||
|
||||
CU_ASSERT_PTR_NULL(linphone_core_get_current_call(marie->lc));
|
||||
CU_ASSERT_PTR_NULL(linphone_core_get_current_call(pauline->lc));
|
||||
|
||||
// now dialog id should be filled
|
||||
CU_ASSERT_PTR_NOT_NULL(call_marie->log->reports[0]->dialog_id);
|
||||
|
||||
// PUBLISH submission to the collector should be ok
|
||||
CU_ASSERT_TRUE(wait_for(marie->lc,NULL,&marie->stat.number_of_LinphonePublishProgress,1));
|
||||
CU_ASSERT_TRUE(wait_for(marie->lc,NULL,&marie->stat.number_of_LinphonePublishOk,1));
|
||||
|
||||
linphone_core_manager_destroy(marie);
|
||||
linphone_core_manager_destroy(pauline);
|
||||
}
|
||||
|
||||
#ifdef VIDEO_ENABLED
|
||||
#endif
|
||||
|
||||
|
|
@ -1899,17 +2117,20 @@ test_t call_tests[] = {
|
|||
{ "Call paused resumed", call_paused_resumed },
|
||||
{ "Call paused resumed from callee", call_paused_resumed_from_callee },
|
||||
{ "SRTP call", srtp_call },
|
||||
/*{ "ZRTP call",zrtp_call}, futur work*/
|
||||
{ "ZRTP call",zrtp_call},
|
||||
{ "ZRTP video call",zrtp_video_call},
|
||||
{ "SRTP call with declined srtp", call_with_declined_srtp },
|
||||
#ifdef VIDEO_ENABLED
|
||||
{ "Simple video call",video_call},
|
||||
{ "SRTP ice video call", srtp_video_ice_call },
|
||||
{ "ZRTP ice video call", zrtp_video_ice_call },
|
||||
{ "Call with video added", call_with_video_added },
|
||||
{ "Call with video added (random ports)", call_with_video_added_random_ports },
|
||||
{ "Call with video declined",call_with_declined_video},
|
||||
#else
|
||||
{ "SRTP ice call", srtp_ice_call },
|
||||
#endif
|
||||
{ "SRTP ice call", srtp_ice_call },
|
||||
{ "ZRTP ice call", zrtp_ice_call },
|
||||
{ "ZRTP ice call with relay", zrtp_ice_call_with_relay},
|
||||
{ "Call with privacy", call_with_privacy },
|
||||
{ "Call with privacy 2", call_with_privacy2 },
|
||||
{ "Call rejected because of wrong credential", call_rejected_because_wrong_credentials},
|
||||
|
|
@ -1924,12 +2145,18 @@ test_t call_tests[] = {
|
|||
{ "Call transfer existing call outgoing call", call_transfer_existing_call_outgoing_call },
|
||||
{ "Call with ICE", call_with_ice },
|
||||
{ "Call with ICE (random ports)", call_with_ice_random_ports },
|
||||
{ "Call from ICE to not ICE",ice_to_not_ice},
|
||||
{ "Call from not ICE to ICE",not_ice_to_ice},
|
||||
{ "Call with custom headers",call_with_custom_headers},
|
||||
{ "Call established with rejected INFO",call_established_with_rejected_info},
|
||||
{ "Call established with rejected RE-INVITE",call_established_with_rejected_reinvite},
|
||||
{ "Call established with rejected incoming RE-INVITE", call_established_with_rejected_incoming_reinvite },
|
||||
{ "Call established with rejected RE-INVITE in error", call_established_with_rejected_reinvite_with_error},
|
||||
{ "Call redirected by callee", call_redirect}
|
||||
{ "Call redirected by callee", call_redirect},
|
||||
{ "Call statistics not used if no config", statistics_not_used_without_config},
|
||||
{ "Call statistics not sent if call did not start", statistics_not_sent_if_call_not_started},
|
||||
{ "Call statistics sent if call ended normally", statistics_sent_at_call_termination},
|
||||
{ "Call with specified codec bitrate", call_with_specified_codec_bitrate}
|
||||
};
|
||||
|
||||
test_suite_t call_test_suite = {
|
||||
|
|
@ -1939,4 +2166,3 @@ test_suite_t call_test_suite = {
|
|||
sizeof(call_tests) / sizeof(call_tests[0]),
|
||||
call_tests
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -48,12 +48,16 @@ void linphone_subscription_state_change(LinphoneCore *lc, LinphoneEvent *lev, Li
|
|||
stats* counters = get_stats(lc);
|
||||
LinphoneCoreManager *mgr=get_manager(lc);
|
||||
LinphoneContent content={0};
|
||||
|
||||
const LinphoneAddress* from_addr = linphone_event_get_from(lev);
|
||||
char* from = linphone_address_as_string(from_addr);
|
||||
content.type="application";
|
||||
content.subtype="somexml2";
|
||||
content.data=(void*)notify_content;
|
||||
content.size=strlen(notify_content);
|
||||
|
||||
ms_message("Subscription state [%s] from [%s]",linphone_subscription_state_to_string(state),from);
|
||||
ms_free(from);
|
||||
|
||||
switch(state){
|
||||
case LinphoneSubscriptionNone:
|
||||
break;
|
||||
|
|
@ -95,6 +99,10 @@ void linphone_subscription_state_change(LinphoneCore *lc, LinphoneEvent *lev, Li
|
|||
|
||||
void linphone_publish_state_changed(LinphoneCore *lc, LinphoneEvent *ev, LinphonePublishState state){
|
||||
stats* counters = get_stats(lc);
|
||||
const LinphoneAddress* from_addr = linphone_event_get_from(ev);
|
||||
char* from = linphone_address_as_string(from_addr);
|
||||
ms_message("Publish state [%s] from [%s]",linphone_publish_state_to_string(state),from);
|
||||
ms_free(from);
|
||||
switch(state){
|
||||
case LinphonePublishProgress: counters->number_of_LinphonePublishProgress++; break;
|
||||
case LinphonePublishOk:
|
||||
|
|
@ -132,7 +140,7 @@ static void subscribe_test_declined(void) {
|
|||
linphone_event_ref(lev);
|
||||
|
||||
CU_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneSubscriptionOutgoingInit,1,1000));
|
||||
CU_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneSubscriptionIncomingReceived,1,1000));
|
||||
CU_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneSubscriptionIncomingReceived,1,3000));
|
||||
CU_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneSubscriptionError,1,21000));/*yes flexisip may wait 20 secs in case of forking*/
|
||||
ei=linphone_event_get_error_info(lev);
|
||||
CU_ASSERT_PTR_NOT_NULL(ei);
|
||||
|
|
@ -175,8 +183,8 @@ static void subscribe_test_with_args(bool_t terminated_by_subscriber, RefreshTes
|
|||
lev=linphone_core_subscribe(marie->lc,pauline->identity,"dodo",expires,&content);
|
||||
|
||||
CU_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneSubscriptionOutgoingInit,1,1000));
|
||||
CU_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneSubscriptionIncomingReceived,1,1000));
|
||||
CU_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneSubscriptionActive,1,1000));
|
||||
CU_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneSubscriptionIncomingReceived,1,3000));
|
||||
CU_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneSubscriptionActive,1,3000));
|
||||
CU_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneSubscriptionActive,1,1000));
|
||||
|
||||
/*make sure marie receives first notification before terminating*/
|
||||
|
|
@ -230,7 +238,7 @@ static void subscribe_test_with_args2(bool_t terminated_by_subscriber, RefreshTe
|
|||
linphone_event_send_subscribe(lev,&content);
|
||||
|
||||
CU_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneSubscriptionOutgoingInit,1,1000));
|
||||
CU_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneSubscriptionIncomingReceived,1,1000));
|
||||
CU_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneSubscriptionIncomingReceived,1,3000));
|
||||
|
||||
/*check good receipt of custom headers*/
|
||||
CU_ASSERT_STRING_EQUAL(linphone_event_get_custom_header(pauline->lev,"My-Header"),"pouet");
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ static void subscribe_forking(void) {
|
|||
lev=linphone_core_subscribe(marie->lc,pauline->identity,"dodo",expires,&content);
|
||||
|
||||
CU_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneSubscriptionOutgoingInit,1,1000));
|
||||
CU_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneSubscriptionIncomingReceived,1,1000));
|
||||
CU_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneSubscriptionIncomingReceived,1,3000));
|
||||
CU_ASSERT_TRUE(wait_for_list(lcs,&pauline2->stat.number_of_LinphoneSubscriptionIncomingReceived,1,1000));
|
||||
CU_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneSubscriptionActive,1,1000));
|
||||
|
||||
|
|
@ -71,7 +71,7 @@ static void message_forking(void) {
|
|||
lcs=ms_list_append(lcs,marie2->lc);
|
||||
|
||||
linphone_chat_room_send_message2(chat_room,message,liblinphone_tester_chat_message_state_change,pauline->lc);
|
||||
CU_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneMessageReceived,1,1000));
|
||||
CU_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneMessageReceived,1,3000));
|
||||
CU_ASSERT_TRUE(wait_for_list(lcs,&marie2->stat.number_of_LinphoneMessageReceived,1,1000));
|
||||
CU_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneMessageDelivered,1,1000));
|
||||
CU_ASSERT_EQUAL(pauline->stat.number_of_LinphoneMessageInProgress,1);
|
||||
|
|
@ -101,7 +101,7 @@ static void message_forking_with_unreachable_recipients(void) {
|
|||
linphone_core_set_network_reachable(marie3->lc,FALSE);
|
||||
|
||||
linphone_chat_room_send_message2(chat_room,message,liblinphone_tester_chat_message_state_change,pauline->lc);
|
||||
CU_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneMessageReceived,1,1000));
|
||||
CU_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneMessageReceived,1,3000));
|
||||
CU_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneMessageDelivered,1,1000));
|
||||
CU_ASSERT_EQUAL(pauline->stat.number_of_LinphoneMessageInProgress,1);
|
||||
CU_ASSERT_TRUE( marie2->stat.number_of_LinphoneMessageReceived==0);
|
||||
|
|
@ -192,7 +192,7 @@ static void call_forking(void){
|
|||
|
||||
linphone_core_invite_address(pauline->lc,marie->identity);
|
||||
/*pauline should hear ringback*/
|
||||
CU_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneCallOutgoingRinging,1,1000));
|
||||
CU_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneCallOutgoingRinging,1,3000));
|
||||
/*all devices from Marie should be ringing*/
|
||||
CU_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneCallIncomingReceived,1,1000));
|
||||
CU_ASSERT_TRUE(wait_for_list(lcs,&marie2->stat.number_of_LinphoneCallIncomingReceived,1,1000));
|
||||
|
|
@ -352,11 +352,11 @@ static void call_forking_declined(bool_t declined_globaly){
|
|||
CU_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneCallStreamsRunning,1,2000));
|
||||
CU_ASSERT_TRUE(wait_for_list(lcs,&marie2->stat.number_of_LinphoneCallStreamsRunning,1,2000));
|
||||
liblinphone_tester_check_rtcp(pauline,marie2);
|
||||
CU_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneCallEnd,1,1000));
|
||||
CU_ASSERT_TRUE(wait_for_list(lcs,&marie3->stat.number_of_LinphoneCallEnd,1,1000));
|
||||
CU_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneCallEnd,1,3000));
|
||||
CU_ASSERT_TRUE(wait_for_list(lcs,&marie3->stat.number_of_LinphoneCallEnd,1,3000));
|
||||
linphone_core_terminate_call(marie2->lc,linphone_core_get_current_call(marie2->lc));
|
||||
CU_ASSERT_TRUE(wait_for_list(lcs,&marie2->stat.number_of_LinphoneCallEnd,1,1000));
|
||||
CU_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneCallEnd,1,1000));
|
||||
CU_ASSERT_TRUE(wait_for_list(lcs,&marie2->stat.number_of_LinphoneCallEnd,1,3000));
|
||||
CU_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneCallEnd,1,3000));
|
||||
}
|
||||
|
||||
linphone_core_manager_destroy(pauline);
|
||||
|
|
@ -400,7 +400,7 @@ static void call_forking_with_push_notification_single(void){
|
|||
linphone_core_set_network_reachable(marie->lc,TRUE);
|
||||
|
||||
/*Marie shall receive the call immediately*/
|
||||
CU_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneCallIncomingReceived,1,1000));
|
||||
CU_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneCallIncomingReceived,1,5000));
|
||||
/*pauline should hear ringback as well*/
|
||||
CU_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneCallOutgoingRinging,1,1000));
|
||||
|
||||
|
|
@ -450,7 +450,7 @@ static void call_forking_with_push_notification_multiple(void){
|
|||
linphone_core_invite_address(pauline->lc,marie->identity);
|
||||
|
||||
/*marie1 will ring*/
|
||||
CU_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneCallIncomingReceived,1,1000));
|
||||
CU_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneCallIncomingReceived,1,5000));
|
||||
/*pauline should hear ringback as well*/
|
||||
CU_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneCallOutgoingRinging,1,1000));
|
||||
|
||||
|
|
@ -458,7 +458,7 @@ static void call_forking_with_push_notification_multiple(void){
|
|||
linphone_core_set_network_reachable(marie2->lc,TRUE);
|
||||
|
||||
/*Marie shall receive the call immediately*/
|
||||
CU_ASSERT_TRUE(wait_for_list(lcs,&marie2->stat.number_of_LinphoneCallIncomingReceived,1,1000));
|
||||
CU_ASSERT_TRUE(wait_for_list(lcs,&marie2->stat.number_of_LinphoneCallIncomingReceived,1,5000));
|
||||
|
||||
/*marie2 accepts the call*/
|
||||
linphone_core_accept_call(marie2->lc,linphone_core_get_current_call(marie2->lc));
|
||||
|
|
@ -500,7 +500,7 @@ void call_forking_not_responded(void){
|
|||
|
||||
linphone_core_invite_address(pauline->lc,marie->identity);
|
||||
/*pauline should hear ringback*/
|
||||
CU_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneCallOutgoingRinging,1,1000));
|
||||
CU_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneCallOutgoingRinging,1,3000));
|
||||
/*all devices from Marie should be ringing*/
|
||||
CU_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneCallIncomingReceived,1,1000));
|
||||
CU_ASSERT_TRUE(wait_for_list(lcs,&marie2->stat.number_of_LinphoneCallIncomingReceived,1,1000));
|
||||
|
|
@ -568,9 +568,9 @@ static void early_media_call_forking(void) {
|
|||
linphone_core_invite_address_with_params(pauline->lc,marie1->identity,params);
|
||||
linphone_call_params_destroy(params);
|
||||
|
||||
CU_ASSERT_TRUE(wait_for_list(lcs, &marie1->stat.number_of_LinphoneCallIncomingEarlyMedia,1,1000));
|
||||
CU_ASSERT_TRUE(wait_for_list(lcs, &marie2->stat.number_of_LinphoneCallIncomingEarlyMedia,1,1000));
|
||||
CU_ASSERT_TRUE(wait_for_list(lcs, &pauline->stat.number_of_LinphoneCallOutgoingEarlyMedia,1,1000));
|
||||
CU_ASSERT_TRUE(wait_for_list(lcs, &marie1->stat.number_of_LinphoneCallIncomingEarlyMedia,1,3000));
|
||||
CU_ASSERT_TRUE(wait_for_list(lcs, &marie2->stat.number_of_LinphoneCallIncomingEarlyMedia,1,3000));
|
||||
CU_ASSERT_TRUE(wait_for_list(lcs, &pauline->stat.number_of_LinphoneCallOutgoingEarlyMedia,1,3000));
|
||||
|
||||
pauline_call=linphone_core_get_current_call(pauline->lc);
|
||||
marie1_call=linphone_core_get_current_call(marie1->lc);
|
||||
|
|
@ -583,8 +583,8 @@ static void early_media_call_forking(void) {
|
|||
CU_ASSERT_TRUE(linphone_call_get_audio_stats(marie2_call)->download_bandwidth>70);
|
||||
|
||||
linphone_core_accept_call(marie1->lc,linphone_core_get_current_call(marie1->lc));
|
||||
CU_ASSERT_TRUE(wait_for_list(lcs,&marie1->stat.number_of_LinphoneCallStreamsRunning,1,1000));
|
||||
CU_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneCallStreamsRunning,1,1000));
|
||||
CU_ASSERT_TRUE(wait_for_list(lcs,&marie1->stat.number_of_LinphoneCallStreamsRunning,1,3000));
|
||||
CU_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneCallStreamsRunning,1,3000));
|
||||
|
||||
/*marie2 should get her call terminated*/
|
||||
CU_ASSERT_TRUE(wait_for_list(lcs,&marie2->stat.number_of_LinphoneCallEnd,1,1000));
|
||||
|
|
|
|||
|
|
@ -181,6 +181,9 @@ typedef struct _stats {
|
|||
int number_of_LinphoneConfiguringSkipped;
|
||||
int number_of_LinphoneConfiguringFailed;
|
||||
int number_of_LinphoneConfiguringSuccessful;
|
||||
|
||||
int number_of_LinphoneCallEncryptedOn;
|
||||
int number_of_LinphoneCallEncryptedOff;
|
||||
}stats;
|
||||
|
||||
typedef struct _LinphoneCoreManager {
|
||||
|
|
@ -212,6 +215,7 @@ void linphone_subscription_state_change(LinphoneCore *lc, LinphoneEvent *ev, Lin
|
|||
void linphone_publish_state_changed(LinphoneCore *lc, LinphoneEvent *ev, LinphonePublishState state);
|
||||
void linphone_notify_received(LinphoneCore *lc, LinphoneEvent *lev, const char *eventname, const LinphoneContent *content);
|
||||
void linphone_configuration_status(LinphoneCore *lc, LinphoneConfiguringState status, const char *message);
|
||||
void linphone_call_encryption_changed(LinphoneCore *lc, LinphoneCall *call, bool_t on, const char *authentication_token);
|
||||
|
||||
LinphoneAddress * create_linphone_address(const char * domain);
|
||||
bool_t wait_for(LinphoneCore* lc_1, LinphoneCore* lc_2,int* counter,int value);
|
||||
|
|
|
|||
|
|
@ -123,13 +123,16 @@ static void wait_core(LinphoneCore *core) {
|
|||
}
|
||||
}
|
||||
|
||||
static void simple_publish(void) {
|
||||
static void simple_publish_with_expire(int expires) {
|
||||
LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc");
|
||||
LinphoneProxyConfig* proxy;
|
||||
LinphonePresenceModel* presence;
|
||||
|
||||
linphone_core_get_default_proxy(marie->lc,&proxy);
|
||||
linphone_proxy_config_edit(proxy);
|
||||
if (expires >0) {
|
||||
linphone_proxy_config_set_publish_expires(proxy,expires);
|
||||
}
|
||||
linphone_proxy_config_enable_publish(proxy,TRUE);
|
||||
linphone_proxy_config_done(proxy);
|
||||
wait_core(marie->lc);
|
||||
|
|
@ -139,6 +142,14 @@ static void simple_publish(void) {
|
|||
linphone_core_manager_destroy(marie);
|
||||
}
|
||||
|
||||
static void simple_publish() {
|
||||
simple_publish_with_expire(-1);
|
||||
}
|
||||
|
||||
static void publish_with_expires() {
|
||||
simple_publish_with_expire(1);
|
||||
}
|
||||
|
||||
static bool_t subscribe_to_callee_presence(LinphoneCoreManager* caller_mgr,LinphoneCoreManager* callee_mgr) {
|
||||
stats initial_caller=caller_mgr->stat;
|
||||
stats initial_callee=callee_mgr->stat;
|
||||
|
|
@ -340,6 +351,7 @@ static void presence_information(void) {
|
|||
test_t presence_tests[] = {
|
||||
{ "Simple Subscribe", simple_subscribe },
|
||||
{ "Simple Publish", simple_publish },
|
||||
{ "Simple Publish with expires", publish_with_expires },
|
||||
/*{ "Call with presence", call_with_presence },*/
|
||||
{ "Unsubscribe while subscribing", unsubscribe_while_subscribing },
|
||||
{ "Presence information", presence_information },
|
||||
|
|
|
|||
|
|
@ -22,6 +22,8 @@ reg_expires=3600
|
|||
reg_sendregister=1
|
||||
publish=0
|
||||
dial_escape_plus=0
|
||||
statistics_collector=sip:collector@sip.example.org
|
||||
send_statistics=1
|
||||
|
||||
[friend_0]
|
||||
url="Paupoche" <sip:pauline@sip.example.org>
|
||||
|
|
|
|||
3
tester/rcfiles/marie_remote_localfile_android_rc
Normal file
3
tester/rcfiles/marie_remote_localfile_android_rc
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
[misc]
|
||||
config-uri=file:///data/data/org.linphone.tester/files/config_files/rcfiles/marie_remote_localfile2_rc
|
||||
|
||||
|
|
@ -90,8 +90,13 @@ static void remote_provisioning_default_values(void) {
|
|||
}
|
||||
|
||||
static void remote_provisioning_file(void) {
|
||||
LinphoneCoreManager* marie = linphone_core_manager_new2("marie_remote_localfile_rc", FALSE);
|
||||
LinphoneCoreManager* marie;
|
||||
const LpConfig* conf;
|
||||
#if ANDROID
|
||||
marie = linphone_core_manager_new2("marie_remote_localfile_android_rc", FALSE);
|
||||
#else
|
||||
marie = linphone_core_manager_new2("marie_remote_localfile_rc", FALSE);
|
||||
#endif
|
||||
CU_ASSERT_TRUE(wait_for(marie->lc,NULL,&marie->stat.number_of_LinphoneConfiguringSuccessful,1));
|
||||
|
||||
conf = linphone_core_get_config( marie->lc );
|
||||
|
|
|
|||
|
|
@ -141,7 +141,7 @@ bool_t wait_for_until(LinphoneCore* lc_1, LinphoneCore* lc_2,int* counter,int va
|
|||
}
|
||||
|
||||
bool_t wait_for(LinphoneCore* lc_1, LinphoneCore* lc_2,int* counter,int value) {
|
||||
return wait_for_until(lc_1, lc_2,counter,value,3000);
|
||||
return wait_for_until(lc_1, lc_2,counter,value,10000);
|
||||
}
|
||||
|
||||
bool_t wait_for_list(MSList* lcs,int* counter,int value,int timeout_ms) {
|
||||
|
|
@ -205,6 +205,7 @@ LinphoneCoreManager* linphone_core_manager_new2(const char* rc_file, int check_f
|
|||
mgr->v_table.notify_received=linphone_notify_received;
|
||||
mgr->v_table.publish_state_changed=linphone_publish_state_changed;
|
||||
mgr->v_table.configuring_status=linphone_configuration_status;
|
||||
mgr->v_table.call_encryption_changed=linphone_call_encryption_changed;
|
||||
|
||||
reset_counters(&mgr->stat);
|
||||
if (rc_file) rc_path = ms_strdup_printf("rcfiles/%s", rc_file);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue