mirror of
https://gitlab.linphone.org/BC/public/linphone-iphone.git
synced 2026-01-29 09:09:21 +00:00
implement call cancel/call reject
This commit is contained in:
parent
e2d0579e6b
commit
ae2a40ebf5
8 changed files with 576 additions and 186 deletions
26
.cproject
26
.cproject
|
|
@ -81,6 +81,8 @@
|
|||
<resource resourceType="PROJECT" workspacePath="/linphone-private"/>
|
||||
</storageModule>
|
||||
<storageModule moduleId="org.eclipse.cdt.make.core.buildtargets"/>
|
||||
<storageModule moduleId="org.eclipse.cdt.internal.ui.text.commentOwnerProjectMappings"/>
|
||||
<storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/>
|
||||
<storageModule moduleId="scannerConfiguration">
|
||||
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
|
||||
<profile id="org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile">
|
||||
|
|
@ -133,6 +135,29 @@
|
|||
<parser enabled="true"/>
|
||||
</scannerInfoProvider>
|
||||
</profile>
|
||||
<scannerConfigBuildInfo instanceId="0.2131511368.593515799">
|
||||
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile"/>
|
||||
<profile id="org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile">
|
||||
<buildOutputProvider>
|
||||
<openAction enabled="true" filePath=""/>
|
||||
<parser enabled="true"/>
|
||||
</buildOutputProvider>
|
||||
<scannerInfoProvider id="specsFile">
|
||||
<runAction arguments="discovery" command="make" useDefault="true"/>
|
||||
<parser enabled="true"/>
|
||||
</scannerInfoProvider>
|
||||
</profile>
|
||||
<profile id="org.eclipse.cdt.make.core.GCCStandardMakePerFileProfile">
|
||||
<buildOutputProvider>
|
||||
<openAction enabled="true" filePath="/Users/jehanmonnier/workspaces/workspace-sip-parser/linphone-private/make discovery"/>
|
||||
<parser enabled="true"/>
|
||||
</buildOutputProvider>
|
||||
<scannerInfoProvider id="makefileGenerator">
|
||||
<runAction arguments="-E -P -v -dD" command="" useDefault="true"/>
|
||||
<parser enabled="true"/>
|
||||
</scannerInfoProvider>
|
||||
</profile>
|
||||
</scannerConfigBuildInfo>
|
||||
<scannerConfigBuildInfo instanceId="0.2079208171">
|
||||
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile"/>
|
||||
<profile id="org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile">
|
||||
|
|
@ -200,5 +225,4 @@
|
|||
</profile>
|
||||
</scannerConfigBuildInfo>
|
||||
</storageModule>
|
||||
<storageModule moduleId="org.eclipse.cdt.internal.ui.text.commentOwnerProjectMappings"/>
|
||||
</cproject>
|
||||
|
|
|
|||
|
|
@ -45,8 +45,14 @@ void sal_process_authentication(SalOp *op, belle_sip_response_t *response) {
|
|||
}
|
||||
|
||||
}
|
||||
static void process_dialog_terminated(void *user_ctx, const belle_sip_dialog_terminated_event_t *event){
|
||||
ms_error("process_dialog_terminated not implemented yet");
|
||||
static void process_dialog_terminated(void *sal, const belle_sip_dialog_terminated_event_t *event){
|
||||
belle_sip_dialog_t* dialog = belle_sip_dialog_terminated_get_dialog(event);
|
||||
SalOp* op = belle_sip_dialog_get_application_data(dialog);
|
||||
if (op->callbacks.process_dialog_terminated) {
|
||||
op->callbacks.process_dialog_terminated(op,event);
|
||||
} else {
|
||||
ms_error("sal process_dialog_terminated not implemented yet");
|
||||
}
|
||||
}
|
||||
static void process_io_error(void *user_ctx, const belle_sip_io_error_event_t *event){
|
||||
ms_error("process_io_error not implemented yet");
|
||||
|
|
@ -119,7 +125,10 @@ static void process_response_event(void *user_ctx, const belle_sip_response_even
|
|||
belle_sip_request_t* old_request=NULL;;
|
||||
belle_sip_response_t* old_response=NULL;;
|
||||
int response_code = belle_sip_response_get_status_code(response);
|
||||
|
||||
if (op->state == SalOpStateTerminated) {
|
||||
belle_sip_message("Op is terminated, nothing to do with this [%i]",response_code);
|
||||
return;
|
||||
}
|
||||
if (!op->base.remote_ua) {
|
||||
sal_op_set_remote_ua(op,BELLE_SIP_MESSAGE(response));
|
||||
}
|
||||
|
|
@ -204,8 +213,13 @@ static void process_response_event(void *user_ctx, const belle_sip_response_even
|
|||
}
|
||||
case 401:
|
||||
case 407:{
|
||||
sal_process_authentication(op,response);
|
||||
return;
|
||||
if (op->state == SalOpStateTerminating) {
|
||||
belle_sip_message("Op is in state terminating, nothing else to do");
|
||||
return;
|
||||
} else {
|
||||
sal_process_authentication(op,response);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
op->callbacks.process_response_event(op,event);
|
||||
|
|
@ -245,6 +259,7 @@ static void process_auth_requested(void *sal, belle_sip_auth_event_t *auth_event
|
|||
}
|
||||
Sal * sal_init(){
|
||||
char stack_string[64];
|
||||
belle_sip_listener_t* listener;
|
||||
Sal * sal=ms_new0(Sal,1);
|
||||
snprintf(stack_string,sizeof(stack_string)-1,"(belle-sip/%s)",belle_sip_version_to_string());
|
||||
sal->user_agent=belle_sip_header_user_agent_new();
|
||||
|
|
@ -260,7 +275,8 @@ Sal * sal_init(){
|
|||
sal->listener_callbacks.process_timeout=process_timeout;
|
||||
sal->listener_callbacks.process_transaction_terminated=process_transaction_terminated;
|
||||
sal->listener_callbacks.process_auth_requested=process_auth_requested;
|
||||
belle_sip_provider_add_sip_listener(sal->prov,belle_sip_listener_create_from_callbacks(&sal->listener_callbacks,sal));
|
||||
belle_sip_provider_add_sip_listener(sal->prov,listener=belle_sip_listener_create_from_callbacks(&sal->listener_callbacks,sal));
|
||||
belle_sip_object_unref(listener);
|
||||
return sal;
|
||||
}
|
||||
void sal_set_user_pointer(Sal *sal, void *user_data){
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ struct Sal{
|
|||
typedef enum SalOpSate {
|
||||
SalOpStateEarly=0
|
||||
,SalOpStateActive
|
||||
,SalOpStateTerminating /*this state is used to wait until a procedding state, so we can send the cancel*/
|
||||
,SalOpStateTerminated
|
||||
}SalOpSate_t;
|
||||
|
||||
|
|
@ -52,6 +53,7 @@ struct SalOp{
|
|||
belle_sip_request_t* request;
|
||||
belle_sip_response_t* response;
|
||||
belle_sip_server_transaction_t* pending_server_trans;
|
||||
belle_sip_client_transaction_t* pending_inv_client_trans;
|
||||
SalAuthInfo auth_info;
|
||||
unsigned long int registration_refresh_timer;
|
||||
bool_t sdp_offering;
|
||||
|
|
|
|||
|
|
@ -83,6 +83,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){
|
||||
ms_error("process_io_error not implemented yet");
|
||||
}
|
||||
static void process_dialog_terminated(void *op, const belle_sip_dialog_terminated_event_t *event) {
|
||||
if (((SalOp*)op)->dialog) ((SalOp*)op)->dialog=NULL;
|
||||
}
|
||||
static void handle_sdp_from_response(SalOp* op,belle_sip_response_t* response) {
|
||||
belle_sdp_session_description_t* sdp;
|
||||
if ((sdp=belle_sdp_session_description_create(BELLE_SIP_MESSAGE(response)))) {
|
||||
|
|
@ -91,6 +94,13 @@ static void handle_sdp_from_response(SalOp* op,belle_sip_response_t* response) {
|
|||
if (op->base.local_media) sdp_process(op);
|
||||
}
|
||||
}
|
||||
static void cancelling_invite(SalOp* op ){
|
||||
belle_sip_request_t* cancel;
|
||||
ms_message("Cancelling INVITE requets from [%s] to [%s] ",sal_op_get_from(op), sal_op_get_to(op));
|
||||
cancel = belle_sip_client_transaction_create_cancel(op->pending_inv_client_trans);
|
||||
sal_op_send_request(op,cancel);
|
||||
op->state=SalOpStateTerminated;
|
||||
}
|
||||
static void call_response_event(void *op_base, const belle_sip_response_event_t *event){
|
||||
SalOp* op = (SalOp*)op_base;
|
||||
belle_sip_request_t* ack;
|
||||
|
|
@ -154,9 +164,19 @@ static void call_response_event(void *op_base, const belle_sip_response_event_t
|
|||
}
|
||||
return;
|
||||
}
|
||||
/*check if op is terminating*/
|
||||
dialog_state=belle_sip_dialog_get_state(op->dialog);
|
||||
|
||||
if (op->state == SalOpStateTerminating
|
||||
&& (dialog_state==BELLE_SIP_DIALOG_NULL
|
||||
|| dialog_state==BELLE_SIP_DIALOG_EARLY)) {
|
||||
cancelling_invite(op);
|
||||
|
||||
return;
|
||||
}
|
||||
/*else dialog*/
|
||||
|
||||
dialog_state=belle_sip_dialog_get_state(op->dialog);
|
||||
|
||||
switch(dialog_state) {
|
||||
|
||||
case BELLE_SIP_DIALOG_NULL: {
|
||||
|
|
@ -211,6 +231,21 @@ static void call_process_timeout(void *user_ctx, const belle_sip_timeout_event_t
|
|||
static void call_process_transaction_terminated(void *user_ctx, const belle_sip_transaction_terminated_event_t *event) {
|
||||
ms_error("process_transaction_terminated not implemented yet");
|
||||
}
|
||||
static void call_terminated(SalOp* op,belle_sip_server_transaction_t* server_transaction, belle_sip_request_t* request,int status_code) {
|
||||
belle_sip_response_t* resp;
|
||||
op->base.root->callbacks.call_terminated(op,op->dir==SalOpDirIncoming?sal_op_get_from(op):sal_op_get_to(op));
|
||||
resp=belle_sip_response_create_from_request(request,status_code);
|
||||
belle_sip_server_transaction_send_response(server_transaction,resp);
|
||||
op->state=SalOpStateTerminated;
|
||||
return;
|
||||
}
|
||||
static void unsupported_method(belle_sip_server_transaction_t* server_transaction,belle_sip_request_t* request) {
|
||||
belle_sip_response_t* resp;
|
||||
resp=belle_sip_response_create_from_request(request,500);
|
||||
belle_sip_server_transaction_send_response(server_transaction,resp);
|
||||
return;
|
||||
}
|
||||
|
||||
static void process_request_event(void *op_base, const belle_sip_request_event_t *event) {
|
||||
SalOp* op = (SalOp*)op_base;
|
||||
belle_sip_server_transaction_t* server_transaction = belle_sip_provider_create_server_transaction(op->base.root->prov,belle_sip_request_event_get_request(event));
|
||||
|
|
@ -223,7 +258,7 @@ static void process_request_event(void *op_base, const belle_sip_request_event_t
|
|||
belle_sip_dialog_state_t dialog_state;
|
||||
belle_sdp_session_description_t* sdp;
|
||||
belle_sip_header_t* call_info;
|
||||
belle_sip_response_t* resp;
|
||||
|
||||
if (!op->dialog) {
|
||||
op->dialog=belle_sip_provider_create_dialog(op->base.root->prov,BELLE_SIP_TRANSACTION(op->pending_server_trans));
|
||||
belle_sip_dialog_set_application_data(op->dialog,op);
|
||||
|
|
@ -258,6 +293,30 @@ static void process_request_event(void *op_base, const belle_sip_request_event_t
|
|||
|
||||
break;
|
||||
}
|
||||
case BELLE_SIP_DIALOG_EARLY: {
|
||||
//hmm probably a cancel
|
||||
if (strcmp("CANCEL",belle_sip_request_get_method(req))==0) {
|
||||
if(belle_sip_request_event_get_server_transaction(event)) {
|
||||
/*first answer 200 ok to cancel*/
|
||||
belle_sip_server_transaction_send_response(server_transaction
|
||||
,belle_sip_response_create_from_request(req,200));
|
||||
/*terminate invite request*/
|
||||
call_terminated(op
|
||||
,belle_sip_request_event_get_server_transaction(event)
|
||||
,belle_sip_request_event_get_request(event),487);
|
||||
|
||||
|
||||
} else {
|
||||
/*call leg does not exist*/
|
||||
belle_sip_server_transaction_send_response(server_transaction
|
||||
,belle_sip_response_create_from_request(req,481));
|
||||
}
|
||||
} else {
|
||||
belle_sip_error("Unexpected method [%s] for dialog state BELLE_SIP_DIALOG_EARLY");
|
||||
unsupported_method(server_transaction,belle_sip_request_event_get_request(event));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case BELLE_SIP_DIALOG_CONFIRMED:
|
||||
/*great ACK received*/
|
||||
if (strcmp("ACK",belle_sip_request_get_method(req))==0) {
|
||||
|
|
@ -277,9 +336,7 @@ static void process_request_event(void *op_base, const belle_sip_request_event_t
|
|||
}*/
|
||||
op->base.root->callbacks.call_ack(op);
|
||||
} else if(strcmp("BYE",belle_sip_request_get_method(req))==0) {
|
||||
op->base.root->callbacks.call_terminated(op,op->dir==SalOpDirIncoming?sal_op_get_from(op):sal_op_get_to(op));
|
||||
resp=belle_sip_response_create_from_request(belle_sip_request_event_get_request(event),200);
|
||||
belle_sip_server_transaction_send_response(server_transaction,resp);
|
||||
call_terminated(op,server_transaction,belle_sip_request_event_get_request(event),200);
|
||||
} else {
|
||||
ms_error("unexpected method [%s] for dialog [%p]",belle_sip_request_get_method(req),op->dialog);
|
||||
}
|
||||
|
|
@ -305,9 +362,9 @@ int sal_call_set_local_media_description(SalOp *op, SalMediaDescription *desc){
|
|||
int sal_call(SalOp *op, const char *from, const char *to){
|
||||
belle_sip_request_t* req;
|
||||
belle_sip_header_allow_t* header_allow;
|
||||
belle_sip_client_transaction_t* client_transaction;
|
||||
/* belle_sip_client_transaction_t* client_transaction;
|
||||
belle_sip_provider_t* prov=op->base.root->prov;
|
||||
belle_sip_header_route_t* route_header;
|
||||
belle_sip_header_route_t* route_header;*/
|
||||
op->dir=SalOpDirOutgoing;
|
||||
sal_op_set_from(op,from);
|
||||
sal_op_set_to(op,to);
|
||||
|
|
@ -325,16 +382,17 @@ int sal_call(SalOp *op, const char *from, const char *to){
|
|||
set_sdp_from_desc(BELLE_SIP_MESSAGE(req),op->base.local_media);
|
||||
}else op->sdp_offering=FALSE;
|
||||
|
||||
if (sal_op_get_route_address(op)) {
|
||||
/* if (sal_op_get_route_address(op)) {
|
||||
route_header = belle_sip_header_route_create(BELLE_SIP_HEADER_ADDRESS(sal_op_get_route_address(op)));
|
||||
belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(route_header));
|
||||
}
|
||||
}*/
|
||||
sal_op_call_fill_cbs(op);
|
||||
client_transaction = belle_sip_provider_create_client_transaction(prov,req);
|
||||
sal_op_send_request(op,req);
|
||||
/*op->pending_inv_client_trans = client_transaction = belle_sip_provider_create_client_transaction(prov,req);
|
||||
belle_sip_transaction_set_application_data(BELLE_SIP_TRANSACTION(client_transaction),op);
|
||||
op->dialog=belle_sip_provider_create_dialog(prov,BELLE_SIP_TRANSACTION(client_transaction));
|
||||
belle_sip_client_transaction_send_request(client_transaction);
|
||||
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
void sal_op_call_fill_cbs(SalOp*op) {
|
||||
|
|
@ -343,6 +401,7 @@ void sal_op_call_fill_cbs(SalOp*op) {
|
|||
op->callbacks.process_timeout=call_process_timeout;
|
||||
op->callbacks.process_transaction_terminated=call_process_transaction_terminated;
|
||||
op->callbacks.process_request_event=process_request_event;
|
||||
op->callbacks.process_dialog_terminated=process_dialog_terminated;
|
||||
}
|
||||
int sal_call_notify_ringing(SalOp *op, bool_t early_media){
|
||||
belle_sip_response_t* ringing_response;
|
||||
|
|
@ -414,6 +473,9 @@ int sal_call_decline(SalOp *op, SalReason reason, const char *redirection /*opti
|
|||
case SalReasonMedia:
|
||||
status=415;
|
||||
break;
|
||||
case SalReasonDeclined:
|
||||
status=603;
|
||||
break;
|
||||
case SalReasonRedirect:
|
||||
if(redirection!=NULL) {
|
||||
if (strstr(redirection,"sip:")!=0) status=302;
|
||||
|
|
@ -483,12 +545,35 @@ int sal_call_send_dtmf(SalOp *h, char dtmf){
|
|||
}
|
||||
int sal_call_terminate(SalOp *op){
|
||||
belle_sip_dialog_state_t dialog_state=belle_sip_dialog_get_state(op->dialog);
|
||||
|
||||
op->state=SalOpStateTerminating;
|
||||
switch(dialog_state) {
|
||||
case BELLE_SIP_DIALOG_CONFIRMED: {
|
||||
sal_op_send_request(op,belle_sip_dialog_create_request(op->dialog,"BYE"));
|
||||
op->state=SalOpStateTerminated;
|
||||
break;
|
||||
}
|
||||
case BELLE_SIP_DIALOG_NULL: {
|
||||
if (op->dir == SalOpDirIncoming) {
|
||||
sal_call_decline(op, SalReasonDeclined,NULL);
|
||||
op->state=SalOpStateTerminated;
|
||||
} else if (op->pending_inv_client_trans
|
||||
&& belle_sip_transaction_get_state(BELLE_SIP_TRANSACTION(op->pending_inv_client_trans)) == BELLE_SIP_TRANSACTION_PROCEEDING){
|
||||
cancelling_invite(op);
|
||||
break;
|
||||
} else {
|
||||
ms_error("Don't know how to termination NUL dialog [%p]",op->dialog);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case BELLE_SIP_DIALOG_EARLY: {
|
||||
if (op->dir == SalOpDirIncoming) {
|
||||
sal_call_decline(op, SalReasonDeclined,NULL);
|
||||
op->state=SalOpStateTerminated;
|
||||
} else {
|
||||
cancelling_invite(op);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default: {
|
||||
ms_fatal("sal_call_terminate not implemented yet for dialog state [%s]",belle_sip_dialog_state_to_string(dialog_state));
|
||||
return -1;
|
||||
|
|
|
|||
|
|
@ -159,12 +159,11 @@ void sal_op_send_request(SalOp* op, belle_sip_request_t* request) {
|
|||
client_transaction = belle_sip_provider_create_client_transaction(prov,request);
|
||||
belle_sip_transaction_set_application_data(BELLE_SIP_TRANSACTION(client_transaction),op);
|
||||
/*in case DIALOG is in state NULL create a new dialog*/
|
||||
if (op->dialog && belle_sip_dialog_get_state(op->dialog)==BELLE_SIP_DIALOG_NULL) {
|
||||
belle_sip_dialog_delete(op->dialog);
|
||||
if (!op->dialog && strcmp("INVITE",belle_sip_request_get_method(request))==0) {
|
||||
op->dialog=belle_sip_provider_create_dialog(prov,BELLE_SIP_TRANSACTION(client_transaction));
|
||||
op->pending_inv_client_trans=client_transaction; /*update pending inv for being able to cancel*/
|
||||
belle_sip_dialog_set_application_data(op->dialog,op);
|
||||
} else
|
||||
if (!belle_sip_message_get_header(BELLE_SIP_MESSAGE(request),BELLE_SIP_AUTHORIZATION)
|
||||
} else if (!belle_sip_message_get_header(BELLE_SIP_MESSAGE(request),BELLE_SIP_AUTHORIZATION)
|
||||
&& !belle_sip_message_get_header(BELLE_SIP_MESSAGE(request),BELLE_SIP_PROXY_AUTHORIZATION)) {
|
||||
/*hmm just in case we already have authentication param in cache*/
|
||||
belle_sip_provider_add_authorization(op->base.root->prov,request,NULL);
|
||||
|
|
|
|||
|
|
@ -3548,6 +3548,9 @@ const LinphoneVideoPolicy *linphone_core_get_video_policy(LinphoneCore *lc){
|
|||
**/
|
||||
void linphone_core_enable_video_preview(LinphoneCore *lc, bool_t val){
|
||||
lc->video_conf.show_local=val;
|
||||
if (linphone_core_ready(lc)) {
|
||||
lp_config_set_int(lc->config,"video","show_local",linphone_core_video_preview_enabled(lc));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -3570,6 +3573,9 @@ void linphone_core_enable_self_view(LinphoneCore *lc, bool_t val){
|
|||
#ifdef VIDEO_ENABLED
|
||||
LinphoneCall *call=linphone_core_get_current_call (lc);
|
||||
lc->video_conf.selfview=val;
|
||||
if (linphone_core_ready(lc)) {
|
||||
lp_config_set_int(lc->config,"video","self_view",linphone_core_self_view_enabled(lc));
|
||||
}
|
||||
if (call && call->videostream){
|
||||
video_stream_enable_self_view(call->videostream,val);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,44 +10,39 @@
|
|||
# Default value: false
|
||||
debug=false
|
||||
|
||||
# Automatically respawn flexisip in case of abnormal termination
|
||||
# (crashes)
|
||||
# Default value: true
|
||||
auto-respawn=true
|
||||
|
||||
# List of white space separated host names pointing to this machine.
|
||||
# This is to prevent loops while routing SIP messages.
|
||||
# Default value: localhost
|
||||
aliases=auth.example.org auth1.example.org auth2.example.org sip.example.org
|
||||
aliases=localhost
|
||||
|
||||
# The public ip address of the proxy.
|
||||
# Default value: guess
|
||||
ip-address=auth.example.org
|
||||
# List of white space separated SIP uris where the proxy must listen.Wildcard
|
||||
# (*) can be used to mean 'all local ip addresses'. If 'transport'
|
||||
# prameter is unspecified, it will listen to both udp and tcp. An
|
||||
# local address to bind can be indicated in the 'maddr' parameter,
|
||||
# while the domain part of the uris are used as public domain or
|
||||
# ip address. Here some examples to understand:
|
||||
# * listen on all local interfaces for udp and tcp, on standart
|
||||
# port:
|
||||
# transports=sip:*
|
||||
# * listen on all local interfaces for udp,tcp and tls, on standart
|
||||
# ports:
|
||||
# transports=sip:* sips:*
|
||||
# * listen on 192.168.0.29:6060 with tls, but public hostname is
|
||||
# 'sip.linphone.org' used in SIP messages. Bind address won't appear:
|
||||
# transports=sips:sip.linphone.org:6060;maddr=192.168.0.29
|
||||
# Default value: sip:*
|
||||
transports=sip:* sips:*
|
||||
|
||||
# The local interface's ip address where to listen. The wildcard
|
||||
# (*) means all interfaces.
|
||||
# Default value: *
|
||||
bind-address=auth.example.org
|
||||
|
||||
# UDP/TCP port number to listen for sip messages.
|
||||
# Default value: 5060
|
||||
port=5060
|
||||
|
||||
|
||||
##
|
||||
## TLS specific parameters.
|
||||
##
|
||||
[tls]
|
||||
# Enable SIP/TLS (sips)
|
||||
# Default value: true
|
||||
enabled=true
|
||||
|
||||
# The port used for SIP/TLS
|
||||
# Default value: 5061
|
||||
port=5061
|
||||
|
||||
# An absolute path of a directory where TLS certificate can be found.
|
||||
# The private key for TLS server must be in a agent.pem file within
|
||||
# this directory
|
||||
# An absolute path of a directory where TLS server certificate and
|
||||
# private key can be found, concatenated inside an 'agent.pem' file.
|
||||
# Default value: /etc/flexisip/tls
|
||||
#certificates-dir=/Users/jehanmonnier/workspaces/workspace-macosx/flexisip
|
||||
certificates-dir=/media/sf_workspaces/workspace-macosx/flexisip
|
||||
|
||||
#tls-certificates-dir=/etc/flexisip/tls
|
||||
tls-certificates-dir=/media/sf_workspaces/workspace-macosx/flexisip
|
||||
|
||||
##
|
||||
## STUN server parameters.
|
||||
|
|
@ -57,10 +52,43 @@ certificates-dir=/media/sf_workspaces/workspace-macosx/flexisip
|
|||
# Default value: true
|
||||
enabled=true
|
||||
|
||||
# Local ip address where to bind the socket.
|
||||
# Default value: 0.0.0.0
|
||||
bind-address=0.0.0.0
|
||||
|
||||
# STUN server port number.
|
||||
# Default value: 3478
|
||||
port=3478
|
||||
|
||||
##
|
||||
## DOS protection parameters.
|
||||
##
|
||||
[dos-protection]
|
||||
# Enable or disable DOS protection using IPTables firewall.
|
||||
# Default value: false
|
||||
enabled=false
|
||||
|
||||
# List of whitelist IPs which won't be affected by DOS protection.
|
||||
# Default value: 127.0.0.1
|
||||
authorized-ip=127.0.0.1
|
||||
|
||||
# Local ports to protect.
|
||||
# Default value: 5060
|
||||
port=5060
|
||||
|
||||
# Time (in seconds) while an IP have to not send any packet in order
|
||||
# to leave the blacklist.
|
||||
# Default value: 60
|
||||
ban-duration=60
|
||||
|
||||
# Number of packets authorized in 1sec before considering them as
|
||||
# DOS attack.
|
||||
# Default value: 20
|
||||
packets-limit=20
|
||||
|
||||
# Maximal amount of simultaneous connections to accept.
|
||||
# Default value: 1000
|
||||
maximum-connections=1000
|
||||
|
||||
##
|
||||
## The NatHelper module executes small tasks to make SIP work smoothly
|
||||
|
|
@ -72,16 +100,19 @@ port=3478
|
|||
[module::NatHelper]
|
||||
# Indicate whether the module is activated.
|
||||
# Default value: true
|
||||
enabled=false
|
||||
enabled=true
|
||||
|
||||
# List of domain names in sip from allowed to enter the module.
|
||||
# Default value: *
|
||||
from-domains=*
|
||||
|
||||
# List of domain names in sip to allowed to enter the module.
|
||||
# Default value: *
|
||||
to-domains=*
|
||||
# A request/response enters module if the boolean filter evaluates
|
||||
# to true. Ex: from.uri.domain contains 'sip.linphone.org', from.uri.domain
|
||||
# in 'a.org b.org c.org', (to.uri.domain in 'a.org b.org c.org')
|
||||
# && (user-agent == 'Linphone v2')
|
||||
# Default value:
|
||||
filter=
|
||||
|
||||
# Internal URI parameter added to response contact by first proxy
|
||||
# and cleaned by last one.
|
||||
# Default value: verified
|
||||
contact-verified-param=verified
|
||||
|
||||
##
|
||||
## The authentication module challenges SIP requests according to
|
||||
|
|
@ -92,18 +123,17 @@ to-domains=*
|
|||
# Default value: false
|
||||
enabled=true
|
||||
|
||||
# List of domain names in sip from allowed to enter the module.
|
||||
# Default value: *
|
||||
from-domains=auth.example.org auth1.example.org auth2.example.org
|
||||
|
||||
# List of domain names in sip to allowed to enter the module.
|
||||
# Default value: *
|
||||
to-domains=*
|
||||
# A request/response enters module if the boolean filter evaluates
|
||||
# to true. Ex: from.uri.domain contains 'sip.linphone.org', from.uri.domain
|
||||
# in 'a.org b.org c.org', (to.uri.domain in 'a.org b.org c.org')
|
||||
# && (user-agent == 'Linphone v2')
|
||||
# Default value:
|
||||
filter=
|
||||
|
||||
# List of whitespace separated domain names to challenge. Others
|
||||
# are denied.
|
||||
# Default value:
|
||||
auth-domains=auth.example.org auth1.example.org auth2.example.org
|
||||
auth-domains= auth.example.org
|
||||
|
||||
# List of whitespace separated IP which will not be challenged.
|
||||
# Default value:
|
||||
|
|
@ -114,14 +144,16 @@ trusted-hosts=
|
|||
db-implementation=file
|
||||
|
||||
# Odbc connection string to use for connecting to database. ex1:
|
||||
# DSN=myodbc3; where 'myodbc3' is the datasource name. ex2: DRIVER={MySQL};SERVER=localhost;DATABASE=dbname;USER=username;PASSWORD=passname;OPTION=3;
|
||||
# DSN=myodbc3; where 'myodbc3' is the datasource name. ex2: DRIVER={MySQL};SERVER=host;DATABASE=db;USER=user;PASSWORD=pass;OPTION=3;
|
||||
# for a DSN-less connection. ex3: /etc/flexisip/passwd; for a file
|
||||
# containing one 'user@domain password' by line.
|
||||
# Default value:
|
||||
datasource=./userdb.conf
|
||||
|
||||
# Odbc SQL request to execute to obtain the password. Named parameters
|
||||
# are :id, :domain and :authid.'
|
||||
# Odbc SQL request to execute to obtain the password
|
||||
# . Named parameters are :id (the user found in the from header),
|
||||
# :domain (the authorization realm) and :authid (the authorization
|
||||
# username). The use of the :id parameter is mandatory.
|
||||
# Default value: select password from accounts where id = :id and domain = :domain and authid=:authid
|
||||
request=select password from accounts where id = :id and domain = :domain and authid=:authid
|
||||
|
||||
|
|
@ -160,12 +192,52 @@ cache-expire=1800
|
|||
# Default value: true
|
||||
immediate-retrieve-password=true
|
||||
|
||||
# True if the passwords retrieved from the database are already
|
||||
# SIP hashed (HA1=MD5(A1)=MD5(username:realm:password)).
|
||||
# True if retrieved passwords from the database are hashed. HA1=MD5(A1)
|
||||
# = MD5(username:realm:pass).
|
||||
# Default value: false
|
||||
hashed-passwords=false
|
||||
|
||||
# When receiving a proxy authenticate challenge, generate a new
|
||||
# challenge for this proxy.
|
||||
# Default value: false
|
||||
new-auth-on-407=false
|
||||
|
||||
##
|
||||
## ...
|
||||
##
|
||||
[module::GatewayAdapter]
|
||||
# Indicate whether the module is activated.
|
||||
# Default value: false
|
||||
enabled=false
|
||||
|
||||
# A request/response enters module if the boolean filter evaluates
|
||||
# to true. Ex: from.uri.domain contains 'sip.linphone.org', from.uri.domain
|
||||
# in 'a.org b.org c.org', (to.uri.domain in 'a.org b.org c.org')
|
||||
# && (user-agent == 'Linphone v2')
|
||||
# Default value:
|
||||
filter=
|
||||
|
||||
# A gateway uri where to send all requests, as a SIP url (eg 'sip:gateway.example.net')
|
||||
# Default value:
|
||||
gateway=
|
||||
|
||||
# Modify the from and to domains of incoming register
|
||||
# Default value:
|
||||
gateway-domain=
|
||||
|
||||
# The gateway will be added to the incoming register contacts.
|
||||
# Default value: true
|
||||
fork-to-gateway=true
|
||||
|
||||
# Send a REGISTER to the gateway using this server as a contact
|
||||
# in order to be notified on incoming calls by the gateway.
|
||||
# Default value: true
|
||||
register-on-gateway=true
|
||||
|
||||
# Parameter name hosting the incoming domain that will be sent in
|
||||
# the register to the gateway.
|
||||
# Default value: routing-domain
|
||||
routing-param=routing-domain
|
||||
|
||||
##
|
||||
## The Registrar module accepts REGISTERs for domains it manages,
|
||||
|
|
@ -177,19 +249,135 @@ hashed-passwords=false
|
|||
# Default value: true
|
||||
enabled=true
|
||||
|
||||
# List of domain names in sip from allowed to enter the module.
|
||||
# Default value: *
|
||||
from-domains=auth.example.org auth1.example.org auth2.example.org sip.example.org
|
||||
|
||||
# List of domain names in sip to allowed to enter the module.
|
||||
# Default value: *
|
||||
to-domains=*
|
||||
# A request/response enters module if the boolean filter evaluates
|
||||
# to true. Ex: from.uri.domain contains 'sip.linphone.org', from.uri.domain
|
||||
# in 'a.org b.org c.org', (to.uri.domain in 'a.org b.org c.org')
|
||||
# && (user-agent == 'Linphone v2')
|
||||
# Default value:
|
||||
filter=
|
||||
|
||||
# List of whitelist separated domain names to be managed by the
|
||||
# registrar.
|
||||
# Default value: localhost
|
||||
reg-domains=auth.example.org auth1.example.org auth2.example.org sip.example.org
|
||||
reg-domains=localhost auth.example.org
|
||||
|
||||
# Maximum number of registered contacts of an address of record.
|
||||
# Default value: 15
|
||||
max-contacts-by-aor=15
|
||||
|
||||
# List of contact uri parameters that can be used to identify a
|
||||
# user's device.
|
||||
# Default value: line
|
||||
unique-id-parameters=line
|
||||
|
||||
# Maximum expire time for a REGISTER, in seconds.
|
||||
# Default value: 86400
|
||||
max-expires=86400
|
||||
|
||||
# Minimum expire time for a REGISTER, in seconds.
|
||||
# Default value: 60
|
||||
min-expires=60
|
||||
|
||||
# File containing the static records to add to database at startup.
|
||||
# Format: one 'sip_uri contact_header' by line. Example:
|
||||
# <sip:contact@domain> <sip:127.0.0.1:5460>,<sip:192.168.0.1:5160>
|
||||
# Default value:
|
||||
static-records-file=
|
||||
|
||||
# Timeout in seconds after which the static records file is re-read
|
||||
# and the contacts updated.
|
||||
# Default value: 600
|
||||
static-records-timeout=600
|
||||
|
||||
# Implementation used for storing address of records contact uris.
|
||||
# [redis-async, redis-sync, internal]
|
||||
# Default value: internal
|
||||
db-implementation=internal
|
||||
|
||||
# Store and retrieve contacts without using the domain.
|
||||
# Default value: false
|
||||
use-global-domain=false
|
||||
|
||||
# Fork messages to all registered devices
|
||||
# Default value: true
|
||||
fork=true
|
||||
|
||||
# Force forking and thus the creation of an outgoing transaction
|
||||
# even when only one contact found
|
||||
# Default value: true
|
||||
stateful=true
|
||||
|
||||
# Fork invites to late registers
|
||||
# Default value: false
|
||||
fork-late=false
|
||||
|
||||
# Only forward one response of forked invite to the caller
|
||||
# Default value: true
|
||||
fork-one-response=true
|
||||
|
||||
# All the forked have to decline in order to decline the caller
|
||||
# invite
|
||||
# Default value: false
|
||||
fork-no-global-decline=false
|
||||
|
||||
# Maximum duration for delivering a message (text)
|
||||
# Default value: 3600
|
||||
message-delivery-timeout=3600
|
||||
|
||||
# Generate a contact from the TO header and route it to the above
|
||||
# destination. [sip:host:port]
|
||||
# Default value:
|
||||
generated-contact-route=
|
||||
|
||||
# Require presence of authorization header for specified realm.
|
||||
# [Realm]
|
||||
# Default value:
|
||||
generated-contact-expected-realm=
|
||||
|
||||
##
|
||||
## This module performs push notifications
|
||||
##
|
||||
[module::PushNotification]
|
||||
# Indicate whether the module is activated.
|
||||
# Default value: false
|
||||
enabled=false
|
||||
|
||||
# A request/response enters module if the boolean filter evaluates
|
||||
# to true. Ex: from.uri.domain contains 'sip.linphone.org', from.uri.domain
|
||||
# in 'a.org b.org c.org', (to.uri.domain in 'a.org b.org c.org')
|
||||
# && (user-agent == 'Linphone v2')
|
||||
# Default value:
|
||||
filter=
|
||||
|
||||
# Number of second to wait before sending a push notification to
|
||||
# device(if <=0 then disabled)
|
||||
# Default value: 5
|
||||
timeout=5
|
||||
|
||||
# Maximum number of notifications queued for each client
|
||||
# Default value: 10
|
||||
max-queue-size=10
|
||||
|
||||
# Enable push notification for apple devices
|
||||
# Default value: true
|
||||
apple=true
|
||||
|
||||
# Path to directory where to find Apple Push Notification service
|
||||
# certificates. They should bear the appid of the application, suffixed
|
||||
# by the release mode and .pem extension. For example: org.linphone.dev.pem
|
||||
# org.linphone.prod.pem com.somephone.dev.pem etc... The files should
|
||||
# be .pem format, and made of certificate followed by private key.
|
||||
# Default value: /etc/flexisip/apn
|
||||
apple-certificate-dir=/etc/flexisip/apn
|
||||
|
||||
# Enable push notification for android devices
|
||||
# Default value: true
|
||||
google=true
|
||||
|
||||
# List of couple projectId:ApiKey for each android project which
|
||||
# support push notifications
|
||||
# Default value:
|
||||
google-projects-api-keys=
|
||||
|
||||
##
|
||||
## The purpose of the ContactRouteInserter module is to masquerade
|
||||
|
|
@ -204,19 +392,17 @@ reg-domains=auth.example.org auth1.example.org auth2.example.org sip.example.org
|
|||
# Default value: true
|
||||
enabled=false
|
||||
|
||||
# List of domain names in sip from allowed to enter the module.
|
||||
# Default value: *
|
||||
from-domains=*
|
||||
|
||||
# List of domain names in sip to allowed to enter the module.
|
||||
# Default value: *
|
||||
to-domains=*
|
||||
# A request/response enters module if the boolean filter evaluates
|
||||
# to true. Ex: from.uri.domain contains 'sip.linphone.org', from.uri.domain
|
||||
# in 'a.org b.org c.org', (to.uri.domain in 'a.org b.org c.org')
|
||||
# && (user-agent == 'Linphone v2')
|
||||
# Default value:
|
||||
filter=
|
||||
|
||||
# Hack for workarounding Nortel CS2k gateways bug.
|
||||
# Default value: false
|
||||
masquerade-contacts-for-invites=false
|
||||
|
||||
|
||||
##
|
||||
## This module performs load balancing between a set of configured
|
||||
## destination proxies.
|
||||
|
|
@ -226,20 +412,18 @@ masquerade-contacts-for-invites=false
|
|||
# Default value: false
|
||||
enabled=false
|
||||
|
||||
# List of domain names in sip from allowed to enter the module.
|
||||
# Default value: *
|
||||
from-domains=*
|
||||
|
||||
# List of domain names in sip to allowed to enter the module.
|
||||
# Default value: *
|
||||
to-domains=*
|
||||
# A request/response enters module if the boolean filter evaluates
|
||||
# to true. Ex: from.uri.domain contains 'sip.linphone.org', from.uri.domain
|
||||
# in 'a.org b.org c.org', (to.uri.domain in 'a.org b.org c.org')
|
||||
# && (user-agent == 'Linphone v2')
|
||||
# Default value:
|
||||
filter=
|
||||
|
||||
# Whitespace separated list of sip routes to balance the requests.
|
||||
# Example: <sip:192.168.0.22> <sip:192.168.0.23>
|
||||
# Default value:
|
||||
routes=
|
||||
|
||||
|
||||
##
|
||||
## The MediaRelay module masquerades SDP message so that all RTP
|
||||
## and RTCP streams go through the proxy. The RTP and RTCP streams
|
||||
|
|
@ -250,16 +434,41 @@ routes=
|
|||
[module::MediaRelay]
|
||||
# Indicate whether the module is activated.
|
||||
# Default value: true
|
||||
enabled=true
|
||||
enabled=false
|
||||
|
||||
# List of domain names in sip from allowed to enter the module.
|
||||
# Default value: *
|
||||
from-domains=*
|
||||
# A request/response enters module if the boolean filter evaluates
|
||||
# to true. Ex: from.uri.domain contains 'sip.linphone.org', from.uri.domain
|
||||
# in 'a.org b.org c.org', (to.uri.domain in 'a.org b.org c.org')
|
||||
# && (user-agent == 'Linphone v2')
|
||||
# Default value:
|
||||
filter=
|
||||
|
||||
# List of domain names in sip to allowed to enter the module.
|
||||
# Default value: *
|
||||
to-domains=*
|
||||
# SDP attribute set by the first proxy to forbid subsequent proxies
|
||||
# to provide relay.
|
||||
# Default value: nortpproxy
|
||||
nortpproxy=nortpproxy
|
||||
|
||||
# Set the RTP direction during early media state (duplex, forward)
|
||||
# Default value: duplex
|
||||
early-media-rtp-dir=duplex
|
||||
|
||||
# The minimal value of SDP port range
|
||||
# Default value: 1024
|
||||
sdp-port-range-min=1024
|
||||
|
||||
# The maximal value of SDP port range
|
||||
# Default value: 65535
|
||||
sdp-port-range-max=65535
|
||||
|
||||
# Enable I-frame only filtering for video H264 for clients annoucing
|
||||
# a total bandwith below this value expressed in kbit/s. Use 0 to
|
||||
# disable the feature
|
||||
# Default value: 0
|
||||
h264-filtering-bandwidth=0
|
||||
|
||||
# When above option is activated, keep one I frame over this number.
|
||||
# Default value: 1
|
||||
h264-iframe-decim=1
|
||||
|
||||
##
|
||||
## The purpose of the Transcoder module is to transparently transcode
|
||||
|
|
@ -282,13 +491,12 @@ to-domains=*
|
|||
# Default value: false
|
||||
enabled=false
|
||||
|
||||
# List of domain names in sip from allowed to enter the module.
|
||||
# Default value: *
|
||||
from-domains=*
|
||||
|
||||
# List of domain names in sip to allowed to enter the module.
|
||||
# Default value: *
|
||||
to-domains=*
|
||||
# A request/response enters module if the boolean filter evaluates
|
||||
# to true. Ex: from.uri.domain contains 'sip.linphone.org', from.uri.domain
|
||||
# in 'a.org b.org c.org', (to.uri.domain in 'a.org b.org c.org')
|
||||
# && (user-agent == 'Linphone v2')
|
||||
# Default value:
|
||||
filter=
|
||||
|
||||
# Nominal size of RTP jitter buffer, in milliseconds. A value of
|
||||
# 0 means no jitter buffer (packet processing).
|
||||
|
|
@ -302,9 +510,13 @@ rc-user-agents=
|
|||
|
||||
# Whitespace seprated list of audio codecs, in order of preference.
|
||||
# Default value: speex/8000 amr/8000 iLBC/8000 gsm/8000 pcmu/8000 pcma/8000
|
||||
#audio-codecs=speex/8000 amr/8000 iLBC/8000 gsm/8000 pcmu/8000 pcma/8000 telephone-event/8000
|
||||
audio-codecs=amr/8000 pcmu/8000 pcma/8000 telephone-event/8000
|
||||
audio-codecs=speex/8000 amr/8000 iLBC/8000 gsm/8000 pcmu/8000 pcma/8000
|
||||
|
||||
# If true, retransmissions of INVITEs will be blocked. The purpose
|
||||
# of this option is to limit bandwidth usage and server load on
|
||||
# reliable networks.
|
||||
# Default value: false
|
||||
block-retransmissions=false
|
||||
|
||||
##
|
||||
## This module executes the basic routing task of SIP requests and
|
||||
|
|
@ -315,21 +527,18 @@ audio-codecs=amr/8000 pcmu/8000 pcma/8000 telephone-event/8000
|
|||
# Default value: true
|
||||
enabled=true
|
||||
|
||||
# List of domain names in sip from allowed to enter the module.
|
||||
# Default value: *
|
||||
from-domains=*
|
||||
|
||||
# List of domain names in sip to allowed to enter the module.
|
||||
# Default value: *
|
||||
to-domains=*
|
||||
# A request/response enters module if the boolean filter evaluates
|
||||
# to true. Ex: from.uri.domain contains 'sip.linphone.org', from.uri.domain
|
||||
# in 'a.org b.org c.org', (to.uri.domain in 'a.org b.org c.org')
|
||||
# && (user-agent == 'Linphone v2')
|
||||
# Default value:
|
||||
filter=
|
||||
|
||||
# A sip uri where to send all requests
|
||||
# Default value:
|
||||
#route=<sip:sip.linphone.org>
|
||||
route=
|
||||
|
||||
# Rewrite request-uri's host and port according to above route
|
||||
# Default value: false
|
||||
rewrite-req-uri=false
|
||||
|
||||
[dos-protection]
|
||||
enabled=false
|
||||
|
|
|
|||
|
|
@ -292,28 +292,7 @@ static void call_state_changed(LinphoneCore *lc, LinphoneCall *call, LinphoneCal
|
|||
CU_FAIL("unexpected event");break;
|
||||
}
|
||||
}
|
||||
static void simple_call_declined() {
|
||||
LinphoneCoreVTable v_table;
|
||||
LinphoneCore* lc;
|
||||
int retry=0;
|
||||
|
||||
memset (&v_table,0,sizeof(LinphoneCoreVTable));
|
||||
v_table.registration_state_changed=registration_state_changed;
|
||||
v_table.call_state_changed=call_state_changed;
|
||||
lc=configure_lc(&v_table);
|
||||
stats* counters = (stats*)linphone_core_get_user_data(lc);
|
||||
linphone_core_invite(lc,"marie");
|
||||
|
||||
while (counters->number_of_LinphoneCallIncomingReceived<1 && retry++ <20) {
|
||||
linphone_core_iterate(lc);
|
||||
ms_usleep(100000);
|
||||
}
|
||||
CU_ASSERT_EQUAL(counters->number_of_LinphoneCallIncomingReceived,1);
|
||||
CU_ASSERT_TRUE(linphone_core_inc_invite_pending(lc));
|
||||
/*linphone_core_terminate_call(lc,linphone_core_get_current_call(lc));*/
|
||||
CU_ASSERT_EQUAL(counters->number_of_LinphoneCallReleased,1);
|
||||
linphone_core_destroy(lc);
|
||||
}
|
||||
static bool_t wait_for(LinphoneCore* lc_1, LinphoneCore* lc_2,int* counter,int value) {
|
||||
int retry=0;
|
||||
while (*counter<value && retry++ <20) {
|
||||
|
|
@ -335,60 +314,121 @@ static void enable_codec(LinphoneCore* lc,const char* type,int rate) {
|
|||
linphone_core_enable_payload_type(lc,pt, 1);
|
||||
}
|
||||
}
|
||||
typedef struct _LinphoneCoreManager {
|
||||
LinphoneCoreVTable v_table;
|
||||
LinphoneCore* lc;
|
||||
stats stat;
|
||||
} LinphoneCoreManager;
|
||||
|
||||
static LinphoneCoreManager* linphone_core_manager_new(const char* rc_file) {
|
||||
LinphoneCoreManager* mgr= malloc(sizeof(LinphoneCoreManager));
|
||||
memset (mgr,0,sizeof(LinphoneCoreManager));
|
||||
mgr->v_table.registration_state_changed=registration_state_changed;
|
||||
mgr->v_table.call_state_changed=call_state_changed;
|
||||
|
||||
mgr->lc=configure_lc_from(&mgr->v_table,rc_file,1);
|
||||
enable_codec(mgr->lc,"PCMU",8000);
|
||||
linphone_core_set_user_data(mgr->lc,&mgr->stat);
|
||||
return mgr;
|
||||
}
|
||||
static void linphone_core_manager_destroy(LinphoneCoreManager* mgr) {
|
||||
linphone_core_destroy(mgr->lc);
|
||||
free(mgr);
|
||||
}
|
||||
static void simple_call() {
|
||||
LinphoneCoreVTable v_table_marie;
|
||||
LinphoneCore* lc_marie;
|
||||
LinphoneCoreVTable v_table_pauline;
|
||||
LinphoneCore* lc_pauline;
|
||||
stats stat_marie;
|
||||
stats stat_pauline;
|
||||
reset_counters(&stat_marie);
|
||||
reset_counters(&stat_pauline);
|
||||
LinphoneCoreManager* marie = linphone_core_manager_new("./tester/marie_rc");
|
||||
LinphoneCoreManager* pauline = linphone_core_manager_new("./tester/pauline_rc");
|
||||
|
||||
LinphoneCore* lc_marie=marie->lc;
|
||||
LinphoneCore* lc_pauline=pauline->lc;
|
||||
stats* stat_marie=&marie->stat;
|
||||
stats* stat_pauline=&pauline->stat;
|
||||
|
||||
|
||||
|
||||
memset (&v_table_marie,0,sizeof(LinphoneCoreVTable));
|
||||
v_table_marie.registration_state_changed=registration_state_changed;
|
||||
v_table_marie.call_state_changed=call_state_changed;
|
||||
|
||||
lc_marie=configure_lc_from(&v_table_marie,"./tester/marie_rc",1);
|
||||
enable_codec(lc_marie,"PCMU",8000);
|
||||
linphone_core_set_user_data(lc_marie,&stat_marie);
|
||||
|
||||
memset (&v_table_pauline,0,sizeof(LinphoneCoreVTable));
|
||||
v_table_pauline.registration_state_changed=registration_state_changed;
|
||||
v_table_pauline.call_state_changed=call_state_changed;
|
||||
|
||||
lc_pauline=configure_lc_from(&v_table_pauline,"./tester/pauline_rc",1);
|
||||
linphone_core_set_user_data(lc_pauline,&stat_pauline);
|
||||
|
||||
linphone_core_invite(lc_marie,"pauline");
|
||||
|
||||
CU_ASSERT_TRUE_FATAL(wait_for(lc_pauline,lc_marie,&stat_pauline.number_of_LinphoneCallIncomingReceived,1));
|
||||
CU_ASSERT_TRUE_FATAL(wait_for(lc_pauline,lc_marie,&stat_pauline->number_of_LinphoneCallIncomingReceived,1));
|
||||
CU_ASSERT_TRUE(linphone_core_inc_invite_pending(lc_pauline));
|
||||
CU_ASSERT_EQUAL(stat_marie.number_of_LinphoneCallOutgoingProgress,1);
|
||||
CU_ASSERT_TRUE_FATAL(wait_for(lc_pauline,lc_marie,&stat_marie.number_of_LinphoneCallOutgoingRinging,1));
|
||||
CU_ASSERT_EQUAL(stat_marie->number_of_LinphoneCallOutgoingProgress,1);
|
||||
CU_ASSERT_TRUE_FATAL(wait_for(lc_pauline,lc_marie,&stat_marie->number_of_LinphoneCallOutgoingRinging,1));
|
||||
|
||||
LinphoneProxyConfig* proxy;
|
||||
linphone_core_get_default_proxy(lc_marie,&proxy);
|
||||
CU_ASSERT_PTR_NOT_NULL_FATAL(proxy);
|
||||
|
||||
CU_ASSERT_STRING_EQUAL(linphone_proxy_config_get_identity(proxy),linphone_core_get_current_call_remote_address(lc_pauline))
|
||||
LinphoneAddress* identity = linphone_address_new(linphone_proxy_config_get_identity(proxy));
|
||||
CU_ASSERT_TRUE(linphone_address_weak_equal(identity,linphone_core_get_current_call_remote_address(lc_pauline)));
|
||||
linphone_address_destroy(identity);
|
||||
|
||||
linphone_core_accept_call(lc_pauline,linphone_core_get_current_call(lc_pauline));
|
||||
|
||||
CU_ASSERT_TRUE_FATAL(wait_for(lc_pauline,lc_marie,&stat_pauline.number_of_LinphoneCallConnected,1));
|
||||
CU_ASSERT_TRUE_FATAL(wait_for(lc_pauline,lc_marie,&stat_marie.number_of_LinphoneCallConnected,1));
|
||||
CU_ASSERT_TRUE_FATAL(wait_for(lc_pauline,lc_marie,&stat_pauline.number_of_LinphoneCallStreamsRunning,1));
|
||||
CU_ASSERT_TRUE_FATAL(wait_for(lc_pauline,lc_marie,&stat_marie.number_of_LinphoneCallStreamsRunning,1));
|
||||
CU_ASSERT_TRUE_FATAL(wait_for(lc_pauline,lc_marie,&stat_pauline->number_of_LinphoneCallConnected,1));
|
||||
CU_ASSERT_TRUE_FATAL(wait_for(lc_pauline,lc_marie,&stat_marie->number_of_LinphoneCallConnected,1));
|
||||
CU_ASSERT_TRUE_FATAL(wait_for(lc_pauline,lc_marie,&stat_pauline->number_of_LinphoneCallStreamsRunning,1));
|
||||
CU_ASSERT_TRUE_FATAL(wait_for(lc_pauline,lc_marie,&stat_marie->number_of_LinphoneCallStreamsRunning,1));
|
||||
/*just to sleep*/
|
||||
wait_for(lc_pauline,lc_marie,&stat_marie.number_of_LinphoneCallStreamsRunning,3);
|
||||
wait_for(lc_pauline,lc_marie,&stat_marie->number_of_LinphoneCallStreamsRunning,3);
|
||||
linphone_core_terminate_all_calls(lc_pauline);
|
||||
CU_ASSERT_TRUE(wait_for(lc_pauline,lc_marie,&stat_pauline.number_of_LinphoneCallEnd,1));
|
||||
CU_ASSERT_TRUE(wait_for(lc_pauline,lc_marie,&stat_marie.number_of_LinphoneCallEnd,1));
|
||||
CU_ASSERT_TRUE(wait_for(lc_pauline,lc_marie,&stat_pauline->number_of_LinphoneCallEnd,1));
|
||||
CU_ASSERT_TRUE(wait_for(lc_pauline,lc_marie,&stat_marie->number_of_LinphoneCallEnd,1));
|
||||
|
||||
linphone_core_destroy(lc_marie);
|
||||
linphone_core_destroy(lc_pauline);
|
||||
linphone_core_manager_destroy(marie);
|
||||
linphone_core_manager_destroy(pauline);
|
||||
}
|
||||
static void call_canceled() {
|
||||
LinphoneCoreManager* marie = linphone_core_manager_new("./tester/marie_rc");
|
||||
LinphoneCoreManager* pauline = linphone_core_manager_new("./tester/pauline_rc");
|
||||
|
||||
LinphoneCall* out_call = linphone_core_invite(pauline->lc,"marie");
|
||||
linphone_call_ref(out_call);
|
||||
CU_ASSERT_TRUE_FATAL(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallOutgoingInit,1));
|
||||
|
||||
linphone_core_terminate_call(pauline->lc,out_call);
|
||||
CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallEnd,1));
|
||||
//CU_ASSERT_EQUAL(linphone_call_get_reason(out_call),LinphoneReasonCanceled);
|
||||
CU_ASSERT_EQUAL(pauline->stat.number_of_LinphoneCallEnd,1);
|
||||
CU_ASSERT_EQUAL(marie->stat.number_of_LinphoneCallIncomingReceived,0);
|
||||
linphone_call_unref(out_call);
|
||||
linphone_core_manager_destroy(marie);
|
||||
linphone_core_manager_destroy(pauline);
|
||||
}
|
||||
static void call_ringing_canceled() {
|
||||
LinphoneCoreManager* marie = linphone_core_manager_new("./tester/marie_rc");
|
||||
LinphoneCoreManager* pauline = linphone_core_manager_new("./tester/pauline_rc");
|
||||
|
||||
LinphoneCall* out_call = linphone_core_invite(pauline->lc,"marie");
|
||||
linphone_call_ref(out_call);
|
||||
CU_ASSERT_TRUE_FATAL(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneCallIncomingReceived,1));
|
||||
|
||||
linphone_core_terminate_call(pauline->lc,out_call);
|
||||
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_LinphoneCallEnd,1));
|
||||
//CU_ASSERT_EQUAL(linphone_call_get_reason(in_call),LinphoneReasonDeclined);
|
||||
//CU_ASSERT_EQUAL(linphone_call_get_reason(out_call),LinphoneReasonDeclined);
|
||||
linphone_call_unref(out_call);
|
||||
linphone_core_manager_destroy(marie);
|
||||
linphone_core_manager_destroy(pauline);
|
||||
}
|
||||
|
||||
static void call_early_declined() {
|
||||
LinphoneCoreManager* marie = linphone_core_manager_new("./tester/marie_rc");
|
||||
LinphoneCoreManager* pauline = linphone_core_manager_new("./tester/pauline_rc");
|
||||
|
||||
LinphoneCall* out_call = linphone_core_invite(pauline->lc,"marie");
|
||||
linphone_call_ref(out_call);
|
||||
CU_ASSERT_TRUE_FATAL(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneCallIncomingReceived,1));
|
||||
LinphoneCall* in_call=linphone_core_get_current_call(marie->lc);
|
||||
linphone_call_ref(in_call);
|
||||
|
||||
linphone_core_terminate_call(marie->lc,in_call);
|
||||
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_LinphoneCallEnd,1));
|
||||
CU_ASSERT_EQUAL(linphone_call_get_reason(in_call),LinphoneReasonDeclined);
|
||||
CU_ASSERT_EQUAL(linphone_call_get_reason(out_call),LinphoneReasonDeclined);
|
||||
linphone_call_unref(in_call);
|
||||
linphone_call_unref(out_call);
|
||||
linphone_core_manager_destroy(marie);
|
||||
linphone_core_manager_destroy(pauline);
|
||||
}
|
||||
int init_test_suite () {
|
||||
|
||||
|
|
@ -419,7 +459,13 @@ CU_pSuite pSuite = CU_add_suite("liblinphone", init, uninit);
|
|||
if (NULL == CU_add_test(pSuite, "multi account", multiple_proxy)) {
|
||||
return CU_get_error();
|
||||
}
|
||||
if (NULL == CU_add_test(pSuite, "simple_call_declined", simple_call_declined)) {
|
||||
if (NULL == CU_add_test(pSuite, "call_early_declined", call_early_declined)) {
|
||||
return CU_get_error();
|
||||
}
|
||||
if (NULL == CU_add_test(pSuite, "call_canceled", call_canceled)) {
|
||||
return CU_get_error();
|
||||
}
|
||||
if (NULL == CU_add_test(pSuite, "call_ringing_canceled", call_ringing_canceled)) {
|
||||
return CU_get_error();
|
||||
}
|
||||
if (NULL == CU_add_test(pSuite, "simple_call", simple_call)) {
|
||||
|
|
@ -441,6 +487,9 @@ int main (int argc, char *argv[]) {
|
|||
}else if (strcmp(argv[i],"--domain")==0){
|
||||
i++;
|
||||
test_domain=argv[i];
|
||||
} else if (strcmp(argv[i],"--auth-domain")==0){
|
||||
i++;
|
||||
auth_domain=argv[i];
|
||||
}else if (strcmp(argv[i],"--test")==0){
|
||||
i++;
|
||||
test_name=argv[i];
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue