mirror of
https://gitlab.linphone.org/BC/public/linphone-iphone.git
synced 2026-05-03 20:46:28 +00:00
Merge remote-tracking branch 'linphone/master'
This commit is contained in:
commit
86b769e366
35 changed files with 1520 additions and 548 deletions
|
|
@ -64,7 +64,8 @@ LOCAL_SRC_FILES := \
|
|||
xml.c \
|
||||
xml2lpc.c \
|
||||
lpc2xml.c \
|
||||
remote_provisioning.c
|
||||
remote_provisioning.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)
|
||||
|
|
|
|||
|
|
@ -56,6 +56,7 @@ liblinphone_la_SOURCES=\
|
|||
xml2lpc.c \
|
||||
lpc2xml.c \
|
||||
remote_provisioning.c \
|
||||
quality_reporting.c quality_reporting.h\
|
||||
$(GITVERSION_FILE)
|
||||
|
||||
if BUILD_UPNP
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
@ -677,10 +677,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 +802,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 +829,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 +846,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 +879,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 +892,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 +900,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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -582,7 +582,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 +597,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;
|
||||
}
|
||||
|
||||
|
|
@ -633,7 +633,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 +679,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 +692,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 +740,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 +757,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 +812,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);
|
||||
|
|
@ -213,7 +213,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 +224,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 +246,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 +284,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 +307,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 +323,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 +415,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 +490,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 +522,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 +618,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 +649,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 +693,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 +701,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;
|
||||
|
|
|
|||
|
|
@ -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*/
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
@ -116,7 +116,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;
|
||||
|
|
@ -176,7 +176,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 ||
|
||||
|
|
@ -266,7 +266,7 @@ void linphone_core_message_received(LinphoneCore *lc, SalOp *op, const SalMessag
|
|||
char *from;
|
||||
LinphoneChatMessage* msg;
|
||||
const SalCustomHeader *ch;
|
||||
|
||||
|
||||
addr=linphone_address_new(sal_msg->from);
|
||||
linphone_address_clean(addr);
|
||||
cr=linphone_core_get_chat_room(lc,addr);
|
||||
|
|
@ -278,20 +278,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);
|
||||
}
|
||||
|
|
@ -437,8 +437,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);
|
||||
|
|
@ -605,13 +605,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";
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -653,8 +653,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) {
|
||||
|
|
@ -675,7 +675,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
|
||||
*/
|
||||
|
|
@ -694,7 +694,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
|
||||
*/
|
||||
|
|
@ -780,7 +780,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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -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){
|
||||
|
|
@ -255,7 +255,7 @@ void linphone_friend_close_subscriptions(LinphoneFriend *lf){
|
|||
linphone_friend_unsubscribe(lf);
|
||||
if (lf->insub){
|
||||
sal_notify_presence_close(lf->insub);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -388,7 +388,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 +592,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 +614,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 +639,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){
|
||||
|
|
|
|||
|
|
@ -127,13 +127,6 @@ static 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;
|
||||
propagate_encryption_changed(call);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void linphone_call_audiostream_encryption_changed(void *data, bool_t encrypted) {
|
||||
char status[255]={0};
|
||||
LinphoneCall *call;
|
||||
|
|
@ -393,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;
|
||||
|
|
@ -480,10 +473,10 @@ static void linphone_call_init_common(LinphoneCall *call, LinphoneAddress *from,
|
|||
|
||||
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);
|
||||
}
|
||||
|
|
@ -768,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));
|
||||
|
||||
|
|
@ -777,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:
|
||||
|
|
@ -795,9 +788,17 @@ 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==LinphoneCallReleased){
|
||||
|
||||
if (call->log->status == LinphoneCallSuccess)
|
||||
linphone_reporting_publish(call);
|
||||
|
||||
if (call->op!=NULL) {
|
||||
/*transfer the last error so that it can be obtained even in Released state*/
|
||||
if (call->non_op_error.reason==SalReasonNone){
|
||||
|
|
@ -1301,7 +1302,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){
|
||||
|
|
@ -1449,19 +1450,19 @@ static void _linphone_call_prepare_ice_for_stream(LinphoneCall *call, int stream
|
|||
}
|
||||
|
||||
int linphone_call_prepare_ice(LinphoneCall *call, bool_t incoming_offer){
|
||||
SalMediaDescription *remote;
|
||||
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)
|
||||
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)
|
||||
|
|
@ -1536,7 +1537,7 @@ void linphone_call_init_audio_stream(LinphoneCall *call){
|
|||
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
@ -1548,7 +1549,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{
|
||||
|
|
@ -1956,7 +1957,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);
|
||||
|
|
@ -1978,8 +1979,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;
|
||||
|
|
@ -2143,7 +2145,7 @@ 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);
|
||||
|
|
@ -2202,6 +2204,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);
|
||||
|
|
@ -2230,6 +2233,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);
|
||||
|
|
@ -2709,8 +2713,90 @@ static void handle_ice_events(LinphoneCall *call, OrtpEvent *ev){
|
|||
}
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
|
|
@ -2732,96 +2818,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)
|
||||
|
|
@ -663,17 +670,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) {
|
||||
|
|
@ -703,7 +710,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);
|
||||
|
||||
|
|
@ -837,7 +844,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;
|
||||
}
|
||||
|
|
@ -895,7 +902,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)){
|
||||
|
|
@ -905,7 +912,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);
|
||||
}
|
||||
}
|
||||
|
|
@ -975,8 +982,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
|
||||
|
|
@ -1039,7 +1046,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
|
||||
|
|
@ -1053,7 +1060,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().
|
||||
|
|
@ -1073,7 +1080,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
|
||||
|
|
@ -1159,7 +1166,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){
|
||||
|
|
@ -1180,14 +1187,14 @@ 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 */
|
||||
|
|
@ -1251,10 +1258,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];
|
||||
|
|
@ -1290,12 +1297,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);
|
||||
}
|
||||
|
||||
|
|
@ -1342,7 +1349,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 */
|
||||
|
|
@ -1372,7 +1379,7 @@ static void linphone_core_init(LinphoneCore * lc, const LinphoneCoreVTable *vtab
|
|||
linphone_core_assign_payload_type(lc,&payload_type_opus,-1,"useinbandfec=1; usedtx=0; cbr=1");
|
||||
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() */
|
||||
|
|
@ -1384,15 +1391,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);
|
||||
|
|
@ -1494,7 +1501,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;
|
||||
}
|
||||
|
|
@ -1940,7 +1947,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
|
||||
|
|
@ -2212,7 +2219,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();
|
||||
|
|
@ -2223,7 +2230,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);
|
||||
|
|
@ -2246,7 +2253,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*/
|
||||
|
|
@ -2266,7 +2273,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){
|
||||
|
|
@ -2359,7 +2366,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> .
|
||||
|
|
@ -2378,7 +2385,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)){
|
||||
|
|
@ -2419,7 +2426,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;
|
||||
|
|
@ -2428,7 +2435,7 @@ LinphoneAddress * linphone_core_interpret_url(LinphoneCore *lc, const char *url)
|
|||
if (uri!=NULL){
|
||||
return uri;
|
||||
}
|
||||
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
@ -2466,7 +2473,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.
|
||||
|
|
@ -2475,13 +2482,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*/
|
||||
}
|
||||
|
|
@ -2521,7 +2528,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);
|
||||
|
|
@ -2816,7 +2823,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"));
|
||||
|
|
@ -2848,7 +2855,7 @@ LinphoneCall * linphone_core_invite_address_with_params(LinphoneCore *lc, const
|
|||
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. */
|
||||
if (linphone_call_prepare_ice(call,FALSE)==1)
|
||||
|
|
@ -2880,7 +2887,7 @@ LinphoneCall * linphone_core_invite_address_with_params(LinphoneCore *lc, const
|
|||
defer = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (defer==FALSE) linphone_core_start_invite(lc,call,NULL);
|
||||
|
||||
if (real_url!=NULL) ms_free(real_url);
|
||||
|
|
@ -2893,7 +2900,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.
|
||||
|
|
@ -2925,7 +2932,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.
|
||||
|
|
@ -2933,7 +2940,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.
|
||||
|
|
@ -2958,7 +2965,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){
|
||||
|
|
@ -2998,10 +3005,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){
|
||||
|
|
@ -3031,11 +3038,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);
|
||||
}
|
||||
|
|
@ -3061,7 +3068,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);
|
||||
|
||||
|
|
@ -3072,7 +3079,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");
|
||||
|
|
@ -3202,15 +3209,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){
|
||||
|
|
@ -3268,7 +3275,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);
|
||||
|
|
@ -3384,7 +3391,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);
|
||||
}
|
||||
}
|
||||
|
|
@ -3416,7 +3423,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);
|
||||
|
|
@ -3425,7 +3432,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);
|
||||
}
|
||||
|
|
@ -3543,9 +3550,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
|
||||
|
|
@ -3679,12 +3686,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.");
|
||||
|
|
@ -3703,7 +3710,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;
|
||||
|
|
@ -3718,7 +3725,7 @@ 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);
|
||||
|
|
@ -3754,7 +3761,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){
|
||||
|
|
@ -3765,7 +3772,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)){
|
||||
|
|
@ -4122,7 +4129,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;
|
||||
|
|
@ -4357,7 +4364,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){
|
||||
|
|
@ -4474,7 +4481,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);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -4560,7 +4567,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);
|
||||
|
|
@ -4570,7 +4577,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);
|
||||
}
|
||||
|
|
@ -4627,7 +4634,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;
|
||||
}
|
||||
|
|
@ -4996,7 +5003,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
|
||||
|
|
@ -5033,7 +5040,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;
|
||||
|
|
@ -5071,7 +5078,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;
|
||||
|
|
@ -5235,7 +5242,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 }
|
||||
};
|
||||
|
||||
|
|
@ -5480,7 +5487,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.");
|
||||
|
|
@ -5546,7 +5553,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){
|
||||
|
|
@ -5640,7 +5647,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);
|
||||
|
|
@ -5655,7 +5662,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++){
|
||||
|
|
@ -5687,7 +5694,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) {
|
||||
|
|
@ -5893,7 +5900,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");
|
||||
|
|
@ -5902,7 +5909,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");
|
||||
|
|
@ -5919,7 +5926,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);
|
||||
|
|
@ -6393,7 +6400,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)
|
||||
|
|
@ -6429,10 +6436,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);
|
||||
|
|
@ -6444,10 +6451,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);
|
||||
|
|
@ -6458,7 +6465,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))
|
||||
|
|
@ -6470,7 +6477,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);
|
||||
|
|
@ -6481,12 +6488,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);
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -6494,7 +6501,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.
|
||||
|
|
|
|||
|
|
@ -288,13 +288,14 @@ LpConfig * lp_config_new(const char *filename){
|
|||
|
||||
LpConfig * lp_config_new_from_buffer(const char *buffer){
|
||||
LpConfig* conf = lp_new0(LpConfig,1);
|
||||
conf->refcnt=1;
|
||||
LpSection* current_section = NULL;
|
||||
|
||||
char* ptr = ms_strdup(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);
|
||||
|
|
|
|||
|
|
@ -88,7 +88,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){
|
||||
|
|
@ -129,7 +129,7 @@ static double get_audio_payload_bandwidth(LinphoneCore *lc, const PayloadType *p
|
|||
/*special case of aac 44K because ptime= 10ms*/
|
||||
npacket=100;
|
||||
}
|
||||
|
||||
|
||||
bitrate=get_codec_bitrate(lc,pt);
|
||||
packet_size= (((double)bitrate)/(npacket*8))+UDP_HDR_SZ+RTP_HDR_SZ+IP4_HDR_SZ;
|
||||
return packet_size*8.0*npacket;
|
||||
|
|
@ -162,7 +162,7 @@ bool_t linphone_core_is_payload_type_usable_for_bandwidth(LinphoneCore *lc, Payl
|
|||
{
|
||||
double codec_band;
|
||||
bool_t ret=FALSE;
|
||||
|
||||
|
||||
switch (pt->type){
|
||||
case PAYLOAD_AUDIO_CONTINUOUS:
|
||||
case PAYLOAD_AUDIO_PACKETIZED:
|
||||
|
|
@ -278,7 +278,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 +301,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 +324,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 +346,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 +370,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 +389,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 +408,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 +487,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 +536,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 +957,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*/
|
||||
|
|
@ -987,7 +987,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))
|
||||
|
|
@ -1042,8 +1042,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);
|
||||
|
|
@ -1078,19 +1078,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 +1103,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){
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ static PayloadType * find_payload_type_best_match(const MSList *l, const Payload
|
|||
/* 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 ))
|
||||
(strcasecmp(pt->mime_type, "G729") == 0 && strcasecmp(refpt->mime_type, "G729A") == 0 ))
|
||||
&& pt->clock_rate==refpt->clock_rate){
|
||||
candidate=pt;
|
||||
/*good candidate, check fmtp for H264 */
|
||||
|
|
@ -56,7 +56,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 +69,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 +85,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 +95,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
|
||||
|
|
@ -132,28 +132,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 +205,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 +233,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 +254,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 +388,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;
|
||||
|
|
@ -399,10 +403,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;
|
||||
|
|
@ -415,6 +421,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;
|
||||
|
|
@ -669,7 +676,7 @@ 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];
|
||||
|
|
@ -804,6 +811,7 @@ void linphone_configure_op(LinphoneCore *lc, SalOp *op, const LinphoneAddress *d
|
|||
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);
|
||||
|
|
@ -852,11 +860,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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
528
coreapi/quality_reporting.c
Normal file
528
coreapi/quality_reporting.c
Normal file
|
|
@ -0,0 +1,528 @@
|
|||
/*
|
||||
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
|
||||
****************************************************************************/
|
||||
// to discuss
|
||||
// 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 env 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 hungup too early, we might have invalid IPs information
|
||||
// in that case, we abort the report since it's not useful data
|
||||
if (strlen(report->info.local_addr.ip) == 0 || 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);
|
||||
}
|
||||
149
coreapi/quality_reporting.h
Normal file
149
coreapi/quality_reporting.h
Normal file
|
|
@ -0,0 +1,149 @@
|
|||
/*
|
||||
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
|
||||
|
||||
typedef struct reporting_addr {
|
||||
char * ip;
|
||||
int port;
|
||||
uint32_t ssrc;
|
||||
} reporting_addr_t;
|
||||
|
||||
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
|
||||
// int frame_ocets;
|
||||
// int frames_per_sec;
|
||||
// int packets_per_sec;
|
||||
char * fmtp;
|
||||
int packet_loss_concealment; // in voip metrics - audio only
|
||||
// char * silence_suppression_state;
|
||||
} session_description;
|
||||
|
||||
// jitter buffet - optional
|
||||
struct {
|
||||
int adaptive; // constant
|
||||
// int rate; // 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; // voip metrics (loss rate) + conversion
|
||||
float jitter_buffer_discard_rate; //idem
|
||||
} packet_loss;
|
||||
|
||||
// burst gap loss - optional
|
||||
// (no) currently not implemented
|
||||
// struct {
|
||||
// int burst_loss_density;
|
||||
// int burst_duration;
|
||||
// float gap_loss_density;
|
||||
// int gap_duration;
|
||||
// int min_gap_threshold;
|
||||
// } burst_gap_loss;
|
||||
|
||||
// delay - optional
|
||||
struct {
|
||||
int round_trip_delay; // no - vary
|
||||
int end_system_delay; // no - not implemented yet
|
||||
// int one_way_delay;
|
||||
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
|
||||
// int residual_echo_return_loss;
|
||||
} 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]
|
||||
|
||||
|
||||
// int extri;
|
||||
// int extro;
|
||||
// char * rlqestalg;
|
||||
// char * rcqestalg;
|
||||
// char * moslqestalg;
|
||||
// char * moscqestalg;
|
||||
// char * extriestalg;
|
||||
// char * extroutestalg;
|
||||
// char * qoestalg;
|
||||
} quality_estimates;
|
||||
} reporting_content_metrics_t;
|
||||
|
||||
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);
|
||||
void linphone_reporting_update(LinphoneCall * call, int stats_type);
|
||||
void linphone_reporting_update_ip(LinphoneCall * call);
|
||||
void linphone_reporting_publish(LinphoneCall* call);
|
||||
void linphone_reporting_call_stats_updated(LinphoneCall *call, int stats_type);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
@ -57,11 +57,14 @@ 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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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...
|
||||
**/
|
||||
|
||||
|
|
@ -571,6 +571,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);
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Subproject commit a66959cdc9ffa2eb2736c465dfe942ce8a74dbda
|
||||
Subproject commit 69cf3ba35c3533f8092b177bdc854a6fb45ceaa3
|
||||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -119,10 +119,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++) {
|
||||
|
|
@ -339,7 +339,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);
|
||||
|
|
@ -374,7 +374,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);
|
||||
|
|
@ -382,7 +382,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);
|
||||
|
|
@ -395,21 +395,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);
|
||||
|
|
@ -449,7 +449,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) {
|
||||
|
|
@ -489,7 +489,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);
|
||||
|
|
@ -503,7 +503,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));
|
||||
|
|
@ -523,7 +523,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);
|
||||
|
||||
|
|
@ -556,7 +556,7 @@ static bool_t check_ice(LinphoneCoreManager* caller, LinphoneCoreManager* callee
|
|||
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");
|
||||
|
||||
|
||||
if (callee_with_ice){
|
||||
linphone_core_set_firewall_policy(marie->lc,LinphonePolicyUseIce);
|
||||
linphone_core_set_stun_server(marie->lc,"stun.linphone.org");
|
||||
|
|
@ -565,7 +565,7 @@ static void _call_with_ice(bool_t caller_with_ice, bool_t callee_with_ice, bool_
|
|||
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);
|
||||
|
|
@ -580,10 +580,10 @@ static void _call_with_ice(bool_t caller_with_ice, bool_t callee_with_ice, bool_
|
|||
/*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);
|
||||
|
|
@ -629,17 +629,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);
|
||||
|
||||
|
|
@ -824,12 +824,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));
|
||||
|
|
@ -922,17 +922,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);
|
||||
|
|
@ -1018,7 +1018,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);
|
||||
|
|
@ -1212,8 +1212,6 @@ static void simple_conference(void) {
|
|||
ms_list_free(lcs);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void srtp_call() {
|
||||
call_base(LinphoneMediaEncryptionSRTP,FALSE,FALSE,LinphonePolicyNoFirewall);
|
||||
}
|
||||
|
|
@ -1349,19 +1347,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);
|
||||
}
|
||||
|
|
@ -1378,7 +1376,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);
|
||||
|
|
@ -1414,7 +1412,7 @@ static void early_media_call_with_ringing(void){
|
|||
|
||||
|
||||
ms_list_free(lcs);
|
||||
|
||||
|
||||
linphone_core_manager_destroy(marie);
|
||||
linphone_core_manager_destroy(pauline);
|
||||
}
|
||||
|
|
@ -1537,9 +1535,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));
|
||||
|
|
@ -1549,11 +1547,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*/
|
||||
|
|
@ -1587,11 +1585,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));
|
||||
|
|
@ -1628,21 +1626,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);
|
||||
|
|
@ -1796,7 +1794,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);
|
||||
|
||||
|
|
@ -1841,7 +1839,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);
|
||||
|
|
@ -1879,7 +1877,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);
|
||||
|
|
@ -1968,6 +1966,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
|
||||
|
||||
|
|
@ -2027,7 +2117,10 @@ test_t call_tests[] = {
|
|||
{ "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},
|
||||
};
|
||||
|
||||
test_suite_t call_test_suite = {
|
||||
|
|
@ -2037,4 +2130,3 @@ test_suite_t call_test_suite = {
|
|||
sizeof(call_tests) / sizeof(call_tests[0]),
|
||||
call_tests
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -95,6 +95,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:
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue