Commit 38898c61 authored by jehan's avatar jehan

implements re-invite on belle-sip

parent ae2a40eb
......@@ -56,7 +56,7 @@
<folderInfo id="0.2131511368.593515799." name="/" resourcePath="">
<toolChain id="org.eclipse.cdt.build.core.prefbase.toolchain.1930099439" name="No ToolChain" resourceTypeBasedDiscovery="false" superClass="org.eclipse.cdt.build.core.prefbase.toolchain">
<targetPlatform binaryParser="org.eclipse.cdt.core.MachO64" id="org.eclipse.cdt.build.core.prefbase.toolchain.1930099439.714963030" name=""/>
<builder arguments="CFLAGS=&quot;-g -Wall -Werror&quot; V=1" command="make" id="org.eclipse.cdt.build.core.settings.default.builder.896899734" keepEnvironmentInBuildfile="false" managedBuildOn="false" name="Gnu Make Builder" superClass="org.eclipse.cdt.build.core.settings.default.builder"/>
<builder arguments="CFLAGS=&quot;-g -Wall -Werror -Wno-deprecated-declarations&quot; V=1" command="make" id="org.eclipse.cdt.build.core.settings.default.builder.896899734" keepEnvironmentInBuildfile="false" managedBuildOn="false" name="Gnu Make Builder" superClass="org.eclipse.cdt.build.core.settings.default.builder"/>
<tool id="org.eclipse.cdt.build.core.settings.holder.libs.1682581923" name="holder for library settings" superClass="org.eclipse.cdt.build.core.settings.holder.libs"/>
<tool id="org.eclipse.cdt.build.core.settings.holder.730520342" name="Assembly" superClass="org.eclipse.cdt.build.core.settings.holder">
<inputType id="org.eclipse.cdt.build.core.settings.holder.inType.552841386" languageId="org.eclipse.cdt.core.assembly" languageName="Assembly" sourceContentType="org.eclipse.cdt.core.asmSource" superClass="org.eclipse.cdt.build.core.settings.holder.inType"/>
......@@ -77,8 +77,13 @@
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
<project id="linphone-private.null.17244867" name="linphone-private"/>
</storageModule>
<storageModule moduleId="refreshScope" versionNumber="1">
<resource resourceType="PROJECT" workspacePath="/linphone-private"/>
<storageModule moduleId="refreshScope" versionNumber="2">
<configuration configurationName="Default">
<resource resourceType="PROJECT" workspacePath="/linphone-private"/>
</configuration>
<configuration configurationName="debug">
<resource resourceType="PROJECT" workspacePath="/linphone-private"/>
</configuration>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.make.core.buildtargets"/>
<storageModule moduleId="org.eclipse.cdt.internal.ui.text.commentOwnerProjectMappings"/>
......
......@@ -276,7 +276,7 @@ Sal * sal_init(){
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,listener=belle_sip_listener_create_from_callbacks(&sal->listener_callbacks,sal));
belle_sip_object_unref(listener);
/* belle_sip_callbacks_t is unowned, why ?belle_sip_object_unref(listener);*/
return sal;
}
void sal_set_user_pointer(Sal *sal, void *user_data){
......
......@@ -76,7 +76,7 @@ belle_sip_request_t* sal_op_build_request(SalOp *op,const char* method);
void sal_op_call_fill_cbs(SalOp*op);
void sal_op_set_remote_ua(SalOp*op,belle_sip_message_t* message);
void sal_op_send_request(SalOp* op, belle_sip_request_t* request);
int sal_op_send_request(SalOp* op, belle_sip_request_t* request);
void sal_op_resend_request(SalOp* op, belle_sip_request_t* request);
void sal_process_authentication(SalOp *op, belle_sip_response_t *response);
......
......@@ -194,8 +194,9 @@ static void call_response_event(void *op_base, const belle_sip_response_event_t
}
case BELLE_SIP_DIALOG_CONFIRMED: {
switch (op->state) {
case SalOpStateEarly:
handle_sdp_from_response(op,response);
case SalOpStateEarly:/*invite case*/
case SalOpStateActive: /*re-invite case*/
handle_sdp_from_response(op,response);
ack=belle_sip_dialog_create_ack(op->dialog,belle_sip_dialog_get_local_seq_number(op->dialog));
if (ack==NULL) {
ms_error("This call has been already terminated.");
......@@ -207,9 +208,10 @@ static void call_response_event(void *op_base, const belle_sip_response_event_t
op->sdp_answer=NULL;
}
belle_sip_dialog_send_ack(op->dialog,ack);
op->state=SalOpStateActive;
op->base.root->callbacks.call_accepted(op);
break;
case SalOpStateActive:
case SalOpStateTerminated:
default:
ms_error("op [%p] receive answer [%i] not implemented",op,code);
......@@ -246,17 +248,27 @@ static void unsupported_method(belle_sip_server_transaction_t* server_transactio
return;
}
static void process_sdp_for_invite(SalOp* op,belle_sip_request_t* invite) {
belle_sdp_session_description_t* sdp;
if ((sdp=belle_sdp_session_description_create(BELLE_SIP_MESSAGE(invite)))) {
op->sdp_offering=FALSE;
op->base.remote_media=sal_media_description_new();
sdp_to_media_description(sdp,op->base.remote_media);
belle_sip_object_unref(sdp);
}else
op->sdp_offering=TRUE;
}
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));
belle_sip_object_ref(server_transaction);
if (op->pending_server_trans) belle_sip_object_unref(op->pending_server_trans);
op->pending_server_trans=server_transaction;
belle_sdp_session_description_t* sdp;
belle_sip_request_t* req = belle_sip_request_event_get_request(event);
belle_sip_header_t* replace_header;
belle_sip_dialog_state_t dialog_state;
belle_sdp_session_description_t* sdp;
belle_sip_header_t* call_info;
if (!op->dialog) {
......@@ -274,13 +286,8 @@ static void process_request_event(void *op_base, const belle_sip_request_event_t
} else if(op->replaces) {
ms_warning("replace header already set");
}
if ((sdp=belle_sdp_session_description_create(BELLE_SIP_MESSAGE(req)))) {
op->sdp_offering=FALSE;
op->base.remote_media=sal_media_description_new();
sdp_to_media_description(sdp,op->base.remote_media);
belle_sip_object_unref(sdp);
}else
op->sdp_offering=TRUE;
process_sdp_for_invite(op,req);
if ((call_info=belle_sip_message_get_header(BELLE_SIP_MESSAGE(req),"Call-Info"))) {
if( strstr(belle_sip_header_extension_get_value(BELLE_SIP_HEADER_EXTENSION(call_info)),"answer-after=") != NULL) {
......@@ -337,6 +344,19 @@ 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) {
call_terminated(op,server_transaction,belle_sip_request_event_get_request(event),200);
} else if(strcmp("INVITE",belle_sip_request_get_method(req))==0) {
/*re-invite*/
if (op->base.remote_media){
sal_media_description_unref(op->base.remote_media);
op->base.remote_media=NULL;
}
if (op->result){
sal_media_description_unref(op->result);
op->result=NULL;
}
process_sdp_for_invite(op,req);
op->base.root->callbacks.call_updating(op);
} else {
ms_error("unexpected method [%s] for dialog [%p]",belle_sip_request_get_method(req),op->dialog);
}
......@@ -359,9 +379,24 @@ int sal_call_set_local_media_description(SalOp *op, SalMediaDescription *desc){
op->base.local_media=desc;
return 0;
}
static void sal_op_fill_invite(SalOp *op, belle_sip_request_t* invite) {
belle_sip_header_allow_t* header_allow;
header_allow = belle_sip_header_allow_create("INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, NOTIFY, MESSAGE, SUBSCRIBE, INFO");
belle_sip_message_add_header(BELLE_SIP_MESSAGE(invite),BELLE_SIP_HEADER(header_allow));
if (op->base.root->session_expires!=0){
belle_sip_message_add_header(BELLE_SIP_MESSAGE(invite),belle_sip_header_create( "Session-expires", "200"));
belle_sip_message_add_header(BELLE_SIP_MESSAGE(invite),belle_sip_header_create( "Supported", "timer"));
}
if (op->base.local_media){
op->sdp_offering=TRUE;
set_sdp_from_desc(BELLE_SIP_MESSAGE(invite),op->base.local_media);
}else op->sdp_offering=FALSE;
return;
}
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_provider_t* prov=op->base.root->prov;
belle_sip_header_route_t* route_header;*/
......@@ -370,22 +405,9 @@ int sal_call(SalOp *op, const char *from, const char *to){
sal_op_set_to(op,to);
req=sal_op_build_request(op,"INVITE");
header_allow = belle_sip_header_allow_create("INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, NOTIFY, MESSAGE, SUBSCRIBE, INFO");
belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(header_allow));
if (op->base.root->session_expires!=0){
belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),belle_sip_header_create( "Session-expires", "200"));
belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),belle_sip_header_create( "Supported", "timer"));
}
if (op->base.local_media){
op->sdp_offering=TRUE;
set_sdp_from_desc(BELLE_SIP_MESSAGE(req),op->base.local_media);
}else op->sdp_offering=FALSE;
sal_op_fill_invite(op,req);
/* 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);
sal_op_send_request(op,req);
/*op->pending_inv_client_trans = client_transaction = belle_sip_provider_create_client_transaction(prov,req);
......@@ -499,13 +521,14 @@ int sal_call_decline(SalOp *op, SalReason reason, const char *redirection /*opti
return 0;
}
int sal_call_update(SalOp *h, const char *subject){
ms_fatal("sal_call_update not implemented yet");
return -1;
int sal_call_update(SalOp *op, const char *subject){
belle_sip_request_t *reinvite=belle_sip_dialog_create_request(op->dialog,"INVITE");
belle_sip_message_add_header(BELLE_SIP_MESSAGE(reinvite),belle_sip_header_create( "Subject", subject));
sal_op_fill_invite(op, reinvite);
return sal_op_send_request(op,reinvite);
}
SalMediaDescription * sal_call_get_remote_media_description(SalOp *h){
ms_fatal("sal_call_get_remote_media_description not implemented yet");
return NULL;
return h->base.remote_media;;
}
......
......@@ -145,7 +145,7 @@ void sal_op_resend_request(SalOp* op, belle_sip_request_t* request) {
belle_sip_header_cseq_set_seq_number(cseq,belle_sip_header_cseq_get_seq_number(cseq)+1);
sal_op_send_request(op,request);
}
void sal_op_send_request(SalOp* op, belle_sip_request_t* request) {
int sal_op_send_request(SalOp* op, belle_sip_request_t* request) {
belle_sip_client_transaction_t* client_transaction;
belle_sip_provider_t* prov=op->base.root->prov;
belle_sip_header_route_t* route_header;
......@@ -168,6 +168,6 @@ void sal_op_send_request(SalOp* op, belle_sip_request_t* request) {
/*hmm just in case we already have authentication param in cache*/
belle_sip_provider_add_authorization(op->base.root->prov,request,NULL);
}
belle_sip_client_transaction_send_request(client_transaction);
return belle_sip_client_transaction_send_request(client_transaction);
}
......@@ -29,6 +29,7 @@ belle_sdp_session_description_t * media_description_to_sdp(const SalMediaDescrip
MSList* pt_it;
PayloadType* pt;
char buffer[1024];
char* dir;
if (strchr(desc->addr,':')!=NULL){
inet6=1;
......@@ -114,6 +115,23 @@ belle_sdp_session_description_t * media_description_to_sdp(const SalMediaDescrip
}
}
switch(desc->streams[i].dir){
case SalStreamSendRecv:
/*dir="sendrecv";*/
dir=NULL;
break;
case SalStreamRecvOnly:
dir="recvonly";
break;
case SalStreamSendOnly:
dir="sendonly";
break;
case SalStreamInactive:
dir="inactive";
break;
}
if (dir) belle_sdp_media_description_add_attribute(media_desc,belle_sdp_attribute_create(dir,NULL));
belle_sdp_session_description_add_media_description(session_desc,media_desc);
}
......
......@@ -18,7 +18,7 @@ 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=localhost
aliases=localhost sipopen.example.org sip.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'
......@@ -36,7 +36,7 @@ aliases=localhost
# '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:*
transports=sip:192.168.56.101:5060 sips:192.168.56.101:5061
# An absolute path of a directory where TLS server certificate and
# private key can be found, concatenated inside an 'agent.pem' file.
......@@ -128,12 +128,12 @@ enabled=true
# in 'a.org b.org c.org', (to.uri.domain in 'a.org b.org c.org')
# && (user-agent == 'Linphone v2')
# Default value:
filter=
filter= from.uri.domain contains 'sip.example.org'
# List of whitespace separated domain names to challenge. Others
# are denied.
# Default value:
auth-domains= auth.example.org
auth-domains= sip.example.org
# List of whitespace separated IP which will not be challenged.
# Default value:
......@@ -259,7 +259,7 @@ filter=
# List of whitelist separated domain names to be managed by the
# registrar.
# Default value: localhost
reg-domains=localhost auth.example.org
reg-domains=localhost sip.example.org sipopen.example.org
# Maximum number of registered contacts of an address of record.
# Default value: 15
......
......@@ -19,8 +19,8 @@
#include "CUnit/Basic.h"
#include "linphonecore.h"
const char *test_domain="sip.example.org";
const char *auth_domain="auth.example.org";
const char *test_domain="sipopen.example.org";
const char *auth_domain="sip.example.org";
const char* test_username="liblinphone_tester";
const char* test_password="secret";
......@@ -335,6 +335,39 @@ static void linphone_core_manager_destroy(LinphoneCoreManager* mgr) {
linphone_core_destroy(mgr->lc);
free(mgr);
}
static bool_t call(LinphoneCoreManager* caller_mgr,LinphoneCoreManager* callee_mgr) {
LinphoneProxyConfig* proxy;
linphone_core_get_default_proxy(callee_mgr->lc,&proxy);
CU_ASSERT_PTR_NOT_NULL_FATAL(proxy);
LinphoneAddress* dest_identity = linphone_address_new(linphone_proxy_config_get_identity(proxy));
linphone_address_clean(dest_identity);
CU_ASSERT_PTR_NOT_NULL_FATAL(linphone_core_invite_address(caller_mgr->lc,dest_identity));
linphone_address_destroy(dest_identity);
/*linphone_core_invite(caller_mgr->lc,"pauline");*/
CU_ASSERT_TRUE_FATAL(wait_for(callee_mgr->lc,caller_mgr->lc,&callee_mgr->stat.number_of_LinphoneCallIncomingReceived,1));
CU_ASSERT_TRUE(linphone_core_inc_invite_pending(callee_mgr->lc));
CU_ASSERT_EQUAL(caller_mgr->stat.number_of_LinphoneCallOutgoingProgress,1);
CU_ASSERT_TRUE_FATAL(wait_for(callee_mgr->lc,caller_mgr->lc,&caller_mgr->stat.number_of_LinphoneCallOutgoingRinging,1));
linphone_core_get_default_proxy(caller_mgr->lc,&proxy);
CU_ASSERT_PTR_NOT_NULL_FATAL(proxy);
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(callee_mgr->lc)));
linphone_address_destroy(identity);
linphone_core_accept_call(callee_mgr->lc,linphone_core_get_current_call(callee_mgr->lc));
CU_ASSERT_TRUE_FATAL(wait_for(callee_mgr->lc,caller_mgr->lc,&callee_mgr->stat.number_of_LinphoneCallConnected,1));
CU_ASSERT_TRUE_FATAL(wait_for(callee_mgr->lc,caller_mgr->lc,&caller_mgr->stat.number_of_LinphoneCallConnected,1));
/*just to sleep*/
return wait_for(callee_mgr->lc,caller_mgr->lc,&caller_mgr->stat.number_of_LinphoneCallStreamsRunning,1)
&&
wait_for(callee_mgr->lc,caller_mgr->lc,&callee_mgr->stat.number_of_LinphoneCallStreamsRunning,1);
}
static void simple_call() {
LinphoneCoreManager* marie = linphone_core_manager_new("./tester/marie_rc");
LinphoneCoreManager* pauline = linphone_core_manager_new("./tester/pauline_rc");
......@@ -430,6 +463,67 @@ static void call_early_declined() {
linphone_core_manager_destroy(marie);
linphone_core_manager_destroy(pauline);
}
static void call_terminated_by_caller() {
LinphoneCoreManager* marie = linphone_core_manager_new("./tester/marie_rc");
LinphoneCoreManager* pauline = linphone_core_manager_new("./tester/pauline_rc");
CU_ASSERT_TRUE(call(pauline,marie));
/*just to sleep*/
linphone_core_terminate_all_calls(pauline->lc);
CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallEnd,1));
CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneCallEnd,1));
linphone_core_manager_destroy(marie);
linphone_core_manager_destroy(pauline);
}
static void call_paused_resumed() {
LinphoneCoreManager* marie = linphone_core_manager_new("./tester/marie_rc");
LinphoneCoreManager* pauline = linphone_core_manager_new("./tester/pauline_rc");
LinphoneCall* call_obj;
CU_ASSERT_TRUE(call(pauline,marie));
call_obj = linphone_core_get_current_call(pauline->lc);
linphone_core_pause_call(pauline->lc,call_obj);
CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallPaused,1));
CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneCallPausedByRemote,1));
linphone_core_resume_call(pauline->lc,call_obj);
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));
/*just to sleep*/
linphone_core_terminate_all_calls(pauline->lc);
CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallEnd,1));
CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneCallEnd,1));
linphone_core_manager_destroy(marie);
linphone_core_manager_destroy(pauline);
}
static void call_srtp() {
LinphoneCoreManager* marie = linphone_core_manager_new("./tester/marie_rc");
LinphoneCoreManager* pauline = linphone_core_manager_new("./tester/pauline_rc");
linphone_core_set_media_encryption(marie->lc,LinphoneMediaEncryptionSRTP);
linphone_core_set_media_encryption(pauline->lc,LinphoneMediaEncryptionSRTP);
CU_ASSERT_TRUE(call(pauline,marie));
CU_ASSERT_EQUAL(linphone_core_get_media_encryption(marie->lc),LinphoneMediaEncryptionSRTP);
CU_ASSERT_EQUAL(linphone_core_get_media_encryption(pauline->lc),LinphoneMediaEncryptionSRTP);
/*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);
}
int init_test_suite () {
CU_pSuite pSuite = CU_add_suite("liblinphone", init, uninit);
......@@ -471,7 +565,15 @@ CU_pSuite pSuite = CU_add_suite("liblinphone", init, uninit);
if (NULL == CU_add_test(pSuite, "simple_call", simple_call)) {
return CU_get_error();
}
if (NULL == CU_add_test(pSuite, "call_terminated_by_caller", call_terminated_by_caller)) {
return CU_get_error();
}
if (NULL == CU_add_test(pSuite, "call_paused_resumed", call_paused_resumed)) {
return CU_get_error();
}
if (NULL == CU_add_test(pSuite, "call_srtp", call_srtp)) {
return CU_get_error();
}
return 0;
}
int main (int argc, char *argv[]) {
......
......@@ -9,13 +9,13 @@ ping_with_options=0
username=marie
userid=marie
passwd=secret
realm="auth.example.org"
realm="sip.example.org"
[proxy_0]
reg_proxy=auth.example.org;transport=tcp
reg_route=auth.example.org;transport=tcp;lr
reg_identity=sip:marie@auth.example.org
reg_proxy=sip.example.org;transport=tcp
reg_route=sip.example.org;transport=tcp;lr
reg_identity=sip:marie@sip.example.org
reg_expires=3600
reg_sendregister=1
publish=0
......
......@@ -9,13 +9,13 @@ ping_with_options=0
username=pauline
userid=pauline
passwd=secret
realm="auth.example.org"
realm="sip.example.org"
[proxy_0]
reg_proxy=auth.example.org;transport=tls
reg_route=auth.example.org;transport=tls;lr
reg_identity=sip:pauline@auth.example.org
reg_proxy=sip.example.org;transport=tls
reg_route=sip.example.org;transport=tls;lr
reg_identity=sip:pauline@sip.example.org
reg_expires=3600
reg_sendregister=1
publish=0
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment