forked from mirrors/linphone-iphone
first registration with authentication
This commit is contained in:
parent
9e6f05e470
commit
3b025defd5
12 changed files with 1037 additions and 706 deletions
|
|
@ -40,7 +40,9 @@ liblinphone_la_SOURCES=\
|
|||
conference.c \
|
||||
linphone_tunnel.cc
|
||||
if USE_BELLESIP
|
||||
liblinphone_la_SOURCES+= sal_bellesip.c
|
||||
liblinphone_la_SOURCES+= bellesip_sal/sal_address_impl.c \
|
||||
bellesip_sal/sal_impl.c \
|
||||
bellesip_sal/sal_op_impl.c
|
||||
else
|
||||
liblinphone_la_SOURCES+= sal_eXosip2.c sal_eXosip2.h\
|
||||
sal_eXosip2_sdp.c \
|
||||
|
|
|
|||
137
coreapi/bellesip_sal/sal_address_impl.c
Normal file
137
coreapi/bellesip_sal/sal_address_impl.c
Normal file
|
|
@ -0,0 +1,137 @@
|
|||
/*
|
||||
linphone
|
||||
Copyright (C) 2012 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.
|
||||
*/
|
||||
#include "sal_impl.h"
|
||||
/**/
|
||||
/* Address manipulation API*/
|
||||
SalAddress * sal_address_new(const char *uri){
|
||||
belle_sip_header_address_t* result;
|
||||
if (uri) {
|
||||
return (SalAddress *)belle_sip_header_address_parse (uri);
|
||||
} else {
|
||||
result = belle_sip_header_address_new();
|
||||
belle_sip_header_address_set_uri(result,belle_sip_uri_new());
|
||||
return (SalAddress *)result;
|
||||
}
|
||||
}
|
||||
SalAddress * sal_address_clone(const SalAddress *addr){
|
||||
return (SalAddress *) belle_sip_object_clone(BELLE_SIP_OBJECT(addr));
|
||||
}
|
||||
const char *sal_address_get_scheme(const SalAddress *addr){
|
||||
belle_sip_header_address_t* header_addr = BELLE_SIP_HEADER_ADDRESS(addr);
|
||||
belle_sip_uri_t* uri = belle_sip_header_address_get_uri(header_addr);
|
||||
if (uri) {
|
||||
if (belle_sip_uri_is_secure(uri)) return "sips";
|
||||
else return "sip";
|
||||
} else
|
||||
return NULL;
|
||||
}
|
||||
const char *sal_address_get_display_name(const SalAddress* addr){
|
||||
belle_sip_header_address_t* header_addr = BELLE_SIP_HEADER_ADDRESS(addr);
|
||||
return belle_sip_header_address_get_displayname(header_addr);
|
||||
|
||||
}
|
||||
const char *sal_address_get_display_name_unquoted(const SalAddress *addr){
|
||||
return sal_address_get_display_name(addr);
|
||||
}
|
||||
#define SAL_ADDRESS_GET(addr,param) \
|
||||
belle_sip_header_address_t* header_addr = BELLE_SIP_HEADER_ADDRESS(addr);\
|
||||
belle_sip_uri_t* uri = belle_sip_header_address_get_uri(header_addr);\
|
||||
if (uri) {\
|
||||
return belle_sip_uri_get_##param(uri);\
|
||||
} else\
|
||||
return NULL;
|
||||
|
||||
#define SAL_ADDRESS_SET(addr,param,value) \
|
||||
belle_sip_header_address_t* header_addr = BELLE_SIP_HEADER_ADDRESS(addr);\
|
||||
belle_sip_uri_t* uri = belle_sip_header_address_get_uri(header_addr);\
|
||||
belle_sip_uri_set_##param(uri,value);
|
||||
|
||||
const char *sal_address_get_username(const SalAddress *addr){
|
||||
SAL_ADDRESS_GET(addr,user)
|
||||
}
|
||||
const char *sal_address_get_domain(const SalAddress *addr){
|
||||
SAL_ADDRESS_GET(addr,host)
|
||||
}
|
||||
const char * sal_address_get_port(const SalAddress *addr){
|
||||
ms_fatal("sal_address_get_port not implemented yet");
|
||||
return NULL;
|
||||
}
|
||||
int sal_address_get_port_int(const SalAddress *addr){
|
||||
belle_sip_header_address_t* header_addr = BELLE_SIP_HEADER_ADDRESS(addr);
|
||||
belle_sip_uri_t* uri = belle_sip_header_address_get_uri(header_addr);
|
||||
if (uri) {
|
||||
return belle_sip_uri_get_port(uri);
|
||||
} else
|
||||
return -1;
|
||||
}
|
||||
SalTransport sal_address_get_transport(const SalAddress* addr){
|
||||
belle_sip_header_address_t* header_addr = BELLE_SIP_HEADER_ADDRESS(addr);
|
||||
belle_sip_uri_t* uri = belle_sip_header_address_get_uri(header_addr);
|
||||
if (uri) {
|
||||
return sal_transport_parse(belle_sip_uri_get_transport_param(uri));
|
||||
} else
|
||||
return SalTransportUDP;
|
||||
};
|
||||
|
||||
void sal_address_set_display_name(SalAddress *addr, const char *display_name){
|
||||
belle_sip_header_address_t* header_addr = BELLE_SIP_HEADER_ADDRESS(addr);
|
||||
belle_sip_header_address_set_displayname(header_addr,display_name);
|
||||
}
|
||||
void sal_address_set_username(SalAddress *addr, const char *username){
|
||||
SAL_ADDRESS_SET(addr,user,username);
|
||||
}
|
||||
void sal_address_set_domain(SalAddress *addr, const char *host){
|
||||
SAL_ADDRESS_SET(addr,host,host);
|
||||
}
|
||||
void sal_address_set_port(SalAddress *addr, const char *port){
|
||||
SAL_ADDRESS_SET(addr,port,atoi(port));
|
||||
}
|
||||
void sal_address_set_port_int(SalAddress *addr, int port){
|
||||
SAL_ADDRESS_SET(addr,port,port);
|
||||
}
|
||||
void sal_address_clean(SalAddress *addr){
|
||||
belle_sip_header_address_t* header_addr = BELLE_SIP_HEADER_ADDRESS(addr);
|
||||
belle_sip_header_address_set_displayname(header_addr,NULL);
|
||||
belle_sip_object_unref(belle_sip_header_address_get_uri(header_addr));
|
||||
belle_sip_header_address_set_uri(header_addr,belle_sip_uri_new());
|
||||
return ;
|
||||
}
|
||||
char *sal_address_as_string(const SalAddress *addr){
|
||||
return belle_sip_object_to_string(BELLE_SIP_OBJECT(addr));
|
||||
}
|
||||
char *sal_address_as_string_uri_only(const SalAddress *addr){
|
||||
belle_sip_header_address_t* header_addr = BELLE_SIP_HEADER_ADDRESS(addr);
|
||||
belle_sip_uri_t* uri = belle_sip_header_address_get_uri(header_addr);
|
||||
return belle_sip_object_to_string(BELLE_SIP_OBJECT(uri));
|
||||
}
|
||||
void sal_address_destroy(SalAddress *addr){
|
||||
belle_sip_header_address_t* header_addr = BELLE_SIP_HEADER_ADDRESS(addr);
|
||||
belle_sip_object_unref(header_addr);
|
||||
return ;
|
||||
}
|
||||
void sal_address_set_param(SalAddress *addr,const char* name,const char* value){
|
||||
belle_sip_parameters_t* parameters = BELLE_SIP_PARAMETERS(addr);
|
||||
belle_sip_parameters_set_parameter(parameters,name,value);
|
||||
return ;
|
||||
}
|
||||
void sal_address_set_transport(SalAddress* addr,SalTransport transport){
|
||||
SAL_ADDRESS_SET(addr,transport_param,sal_transport_to_string(transport));
|
||||
}
|
||||
|
||||
|
||||
272
coreapi/bellesip_sal/sal_impl.c
Normal file
272
coreapi/bellesip_sal/sal_impl.c
Normal file
|
|
@ -0,0 +1,272 @@
|
|||
/*
|
||||
linphone
|
||||
Copyright (C) 2012 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.
|
||||
*/
|
||||
#include "sal_impl.h"
|
||||
|
||||
void sal_enable_logs(){
|
||||
belle_sip_set_log_level(BELLE_SIP_LOG_MESSAGE);
|
||||
}
|
||||
void sal_disable_logs() {
|
||||
belle_sip_set_log_level(BELLE_SIP_LOG_ERROR);
|
||||
}
|
||||
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_io_error(void *user_ctx, const belle_sip_io_error_event_t *event){
|
||||
ms_error("process_io_error not implemented yet");
|
||||
}
|
||||
static void process_request_event(void *user_ctx, const belle_sip_request_event_t *event) {
|
||||
ms_error("process_request_event not implemented yet");
|
||||
}
|
||||
|
||||
static void process_response_event(void *user_ctx, const belle_sip_response_event_t *event){
|
||||
belle_sip_client_transaction_t* client_transaction = belle_sip_response_event_get_client_transaction(event);
|
||||
SalOp* op = (SalOp*)belle_sip_transaction_get_application_data(BELLE_SIP_TRANSACTION(client_transaction));
|
||||
belle_sip_response_t* response = belle_sip_response_event_get_response(event);
|
||||
belle_sip_header_address_t* contact_address;
|
||||
belle_sip_header_via_t* via_header;
|
||||
belle_sip_uri_t* contact_uri;
|
||||
unsigned int contact_port;
|
||||
const char* received;
|
||||
int rport;
|
||||
bool_t contact_updated=FALSE;
|
||||
char* new_contact;
|
||||
|
||||
if (op->callbacks.process_response_event) {
|
||||
/*Fix contact if needed*/
|
||||
via_header= (belle_sip_header_via_t*)belle_sip_message_get_header(BELLE_SIP_MESSAGE(response),BELLE_SIP_VIA);
|
||||
received = belle_sip_header_via_get_received(via_header);
|
||||
rport = belle_sip_header_via_get_rport(via_header);
|
||||
if (received!=NULL || rport>0) {
|
||||
if (sal_op_get_contact(op)){
|
||||
contact_address = BELLE_SIP_HEADER_ADDRESS(sal_address_clone(sal_op_get_contact_address(op)));
|
||||
contact_uri=belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(contact_address));
|
||||
if (received && strcmp(received,belle_sip_uri_get_host(contact_uri))!=0) {
|
||||
/*need to update host*/
|
||||
belle_sip_uri_set_host(contact_uri,received);
|
||||
contact_updated=TRUE;
|
||||
}
|
||||
contact_port = belle_sip_uri_get_port(contact_uri);
|
||||
if (rport>0 && rport!=contact_port && (contact_port+rport)!=5060) {
|
||||
/*need to update port*/
|
||||
belle_sip_uri_set_port(contact_uri,rport);
|
||||
contact_updated=TRUE;
|
||||
}
|
||||
if (contact_updated) {
|
||||
new_contact=belle_sip_object_to_string(BELLE_SIP_OBJECT(contact_address));
|
||||
ms_message("Updating contact from [%s] to [%s] for [%p]",sal_op_get_contact(op),new_contact,op);
|
||||
sal_op_set_contact(op,new_contact);
|
||||
belle_sip_free(new_contact);
|
||||
}
|
||||
belle_sip_object_unref(contact_address);
|
||||
}
|
||||
|
||||
}
|
||||
op->callbacks.process_response_event(op,event);
|
||||
} else {
|
||||
ms_error("Unhandled event response [%p]",event);
|
||||
}
|
||||
|
||||
}
|
||||
static void process_timeout(void *user_ctx, const belle_sip_timeout_event_t *event) {
|
||||
/* belle_sip_client_transaction_t* client_transaction = belle_sip_timeout_event_get_client_transaction(event);
|
||||
SalOp* op = (SalOp*)belle_sip_transaction_get_application_data(BELLE_SIP_TRANSACTION(client_transaction));
|
||||
if (op->callbacks.process_timeout) {
|
||||
op->callbacks.process_timeout(op,event);
|
||||
} else*/ {
|
||||
ms_error("Unhandled event timeout [%p]",event);
|
||||
}
|
||||
}
|
||||
static void process_transaction_terminated(void *user_ctx, const belle_sip_transaction_terminated_event_t *event) {
|
||||
/* belle_sip_client_transaction_t* client_transaction = belle_sip_transaction_terminated_event_get_client_transaction(event);
|
||||
SalOp* op = (SalOp*)belle_sip_transaction_get_application_data(client_transaction);
|
||||
if (op->calbacks.process_transaction_terminated) {
|
||||
op->calbacks.process_transaction_terminated(op,event);
|
||||
} else */{
|
||||
ms_error("Unhandled transaction terminated [%p]",event);
|
||||
}
|
||||
}
|
||||
|
||||
Sal * sal_init(){
|
||||
Sal * sal=ms_new0(Sal,1);
|
||||
sal->stack = belle_sip_stack_new(NULL);
|
||||
sal->prov = belle_sip_stack_create_provider(sal->stack,NULL);
|
||||
sal->listener_callbacks.process_dialog_terminated=process_dialog_terminated;
|
||||
sal->listener_callbacks.process_io_error=process_io_error;
|
||||
sal->listener_callbacks.process_request_event=process_request_event;
|
||||
sal->listener_callbacks.process_response_event=process_response_event;
|
||||
sal->listener_callbacks.process_timeout=process_timeout;
|
||||
sal->listener_callbacks.process_transaction_terminated=process_transaction_terminated;
|
||||
belle_sip_provider_add_sip_listener(sal->prov,belle_sip_listener_create_from_callbacks(&sal->listener_callbacks,sal));
|
||||
return sal;
|
||||
}
|
||||
void sal_set_user_pointer(Sal *sal, void *user_data){
|
||||
sal->up=user_data;
|
||||
}
|
||||
|
||||
void *sal_get_user_pointer(const Sal *sal){
|
||||
return sal->up;
|
||||
}
|
||||
|
||||
static void unimplemented_stub(){
|
||||
ms_warning("Unimplemented SAL callback");
|
||||
}
|
||||
|
||||
void sal_set_callbacks(Sal *ctx, const SalCallbacks *cbs){
|
||||
memcpy(&ctx->callbacks,cbs,sizeof(*cbs));
|
||||
if (ctx->callbacks.call_received==NULL)
|
||||
ctx->callbacks.call_received=(SalOnCallReceived)unimplemented_stub;
|
||||
if (ctx->callbacks.call_ringing==NULL)
|
||||
ctx->callbacks.call_ringing=(SalOnCallRinging)unimplemented_stub;
|
||||
if (ctx->callbacks.call_accepted==NULL)
|
||||
ctx->callbacks.call_accepted=(SalOnCallAccepted)unimplemented_stub;
|
||||
if (ctx->callbacks.call_failure==NULL)
|
||||
ctx->callbacks.call_failure=(SalOnCallFailure)unimplemented_stub;
|
||||
if (ctx->callbacks.call_terminated==NULL)
|
||||
ctx->callbacks.call_terminated=(SalOnCallTerminated)unimplemented_stub;
|
||||
if (ctx->callbacks.call_released==NULL)
|
||||
ctx->callbacks.call_released=(SalOnCallReleased)unimplemented_stub;
|
||||
if (ctx->callbacks.call_updating==NULL)
|
||||
ctx->callbacks.call_updating=(SalOnCallUpdating)unimplemented_stub;
|
||||
if (ctx->callbacks.auth_requested_legacy==NULL)
|
||||
ctx->callbacks.auth_requested_legacy=(SalOnAuthRequestedLegacy)unimplemented_stub;
|
||||
if (ctx->callbacks.auth_success==NULL)
|
||||
ctx->callbacks.auth_success=(SalOnAuthSuccess)unimplemented_stub;
|
||||
if (ctx->callbacks.register_success==NULL)
|
||||
ctx->callbacks.register_success=(SalOnRegisterSuccess)unimplemented_stub;
|
||||
if (ctx->callbacks.register_failure==NULL)
|
||||
ctx->callbacks.register_failure=(SalOnRegisterFailure)unimplemented_stub;
|
||||
if (ctx->callbacks.dtmf_received==NULL)
|
||||
ctx->callbacks.dtmf_received=(SalOnDtmfReceived)unimplemented_stub;
|
||||
if (ctx->callbacks.notify==NULL)
|
||||
ctx->callbacks.notify=(SalOnNotify)unimplemented_stub;
|
||||
if (ctx->callbacks.notify_presence==NULL)
|
||||
ctx->callbacks.notify_presence=(SalOnNotifyPresence)unimplemented_stub;
|
||||
if (ctx->callbacks.subscribe_received==NULL)
|
||||
ctx->callbacks.subscribe_received=(SalOnSubscribeReceived)unimplemented_stub;
|
||||
if (ctx->callbacks.text_received==NULL)
|
||||
ctx->callbacks.text_received=(SalOnTextReceived)unimplemented_stub;
|
||||
if (ctx->callbacks.ping_reply==NULL)
|
||||
ctx->callbacks.ping_reply=(SalOnPingReply)unimplemented_stub;
|
||||
if (ctx->callbacks.auth_requested==NULL)
|
||||
ctx->callbacks.auth_requested=(SalOnAuthRequested)unimplemented_stub;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void sal_uninit(Sal* sal){
|
||||
belle_sip_object_unref(sal->prov);
|
||||
belle_sip_object_unref(sal->stack);
|
||||
ms_free(sal);
|
||||
return ;
|
||||
};
|
||||
|
||||
int sal_listen_port(Sal *ctx, const char *addr, int port, SalTransport tr, int is_secure){
|
||||
int result;
|
||||
belle_sip_listening_point_t* lp = belle_sip_stack_create_listening_point(ctx->stack,addr,port,sal_transport_to_string(tr));
|
||||
if (lp) {
|
||||
result = belle_sip_provider_add_listening_point(ctx->prov,lp);
|
||||
belle_sip_object_unref(lp);
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
static void remove_listening_point(belle_sip_listening_point_t* lp,belle_sip_provider_t* prov) {
|
||||
belle_sip_provider_remove_listening_point(prov,lp);
|
||||
}
|
||||
int sal_unlisten_ports(Sal *ctx){
|
||||
const belle_sip_list_t * lps = belle_sip_provider_get_listening_points(ctx->prov);
|
||||
belle_sip_list_t * tmp_list = belle_sip_list_copy(lps);
|
||||
belle_sip_list_for_each2 (tmp_list,(void (*)(void*,void*))remove_listening_point,ctx->prov);
|
||||
belle_sip_list_free(tmp_list);
|
||||
|
||||
ms_message("sal_unlisten_ports done");
|
||||
return 0;
|
||||
}
|
||||
ortp_socket_t sal_get_socket(Sal *ctx){
|
||||
ms_fatal("sal_get_socket not implemented yet");
|
||||
return -1;
|
||||
}
|
||||
void sal_set_user_agent(Sal *ctx, const char *user_agent){
|
||||
ms_error("sal_set_user_agent not implemented yet");
|
||||
return ;
|
||||
}
|
||||
/*keepalive period in ms*/
|
||||
void sal_set_keepalive_period(Sal *ctx,unsigned int value){
|
||||
ms_error("sal_set_keepalive_period not implemented yet");
|
||||
return ;
|
||||
}
|
||||
/**
|
||||
* returns keepalive period in ms
|
||||
* 0 desactiaved
|
||||
* */
|
||||
unsigned int sal_get_keepalive_period(Sal *ctx){
|
||||
ms_fatal("sal_get_keepalive_period not implemented yet");
|
||||
return -1;
|
||||
}
|
||||
void sal_use_session_timers(Sal *ctx, int expires){
|
||||
ms_error("sal_use_session_timers not implemented yet");
|
||||
return ;
|
||||
}
|
||||
void sal_use_double_registrations(Sal *ctx, bool_t enabled){
|
||||
ms_error("sal_use_double_registrations not implemented yet");
|
||||
return ;
|
||||
}
|
||||
void sal_reuse_authorization(Sal *ctx, bool_t enabled){
|
||||
ms_error("sal_reuse_authorization not implemented yet");
|
||||
return ;
|
||||
}
|
||||
void sal_use_one_matching_codec_policy(Sal *ctx, bool_t one_matching_codec){
|
||||
ms_error("sal_use_one_matching_codec_policy not implemented yet");
|
||||
return ;
|
||||
}
|
||||
void sal_use_rport(Sal *ctx, bool_t use_rports){
|
||||
ms_error("sal_use_rport not implemented yet");
|
||||
return ;
|
||||
}
|
||||
void sal_use_101(Sal *ctx, bool_t use_101){
|
||||
ms_error("sal_use_101 not implemented yet");
|
||||
return ;
|
||||
}
|
||||
void sal_set_root_ca(Sal* ctx, const char* rootCa){
|
||||
ms_error("sal_set_root_ca not implemented yet");
|
||||
return ;
|
||||
}
|
||||
void sal_verify_server_certificates(Sal *ctx, bool_t verify){
|
||||
ms_error("sal_verify_server_certificates not implemented yet");
|
||||
return ;
|
||||
}
|
||||
|
||||
int sal_iterate(Sal *sal){
|
||||
/*FIXME should be zero*/
|
||||
belle_sip_stack_sleep(sal->stack,0);
|
||||
return 0;
|
||||
}
|
||||
MSList * sal_get_pending_auths(Sal *sal){
|
||||
return ms_list_copy(sal->pending_auths);
|
||||
}
|
||||
|
||||
#define payload_type_set_number(pt,n) (pt)->user_data=(void*)((long)n);
|
||||
#define payload_type_get_number(pt) ((int)(long)(pt)->user_data)
|
||||
|
||||
/*misc*/
|
||||
void sal_get_default_local_ip(Sal *sal, int address_family, char *ip, size_t iplen){
|
||||
ms_fatal("sal_get_default_local_ip not implemented yet");
|
||||
return ;
|
||||
}
|
||||
45
coreapi/bellesip_sal/sal_impl.h
Normal file
45
coreapi/bellesip_sal/sal_impl.h
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
linphone
|
||||
Copyright (C) 2012 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 SAL_IMPL_H_
|
||||
#define SAL_IMPL_H_
|
||||
#include "sal.h"
|
||||
#include "belle-sip/belle-sip.h"
|
||||
|
||||
struct Sal{
|
||||
SalCallbacks callbacks;
|
||||
MSList *pending_auths;/*MSList of SalOp */
|
||||
belle_sip_listener_callbacks_t listener_callbacks;
|
||||
belle_sip_stack_t* stack;
|
||||
belle_sip_provider_t *prov;
|
||||
void *up; /*user pointer*/
|
||||
};
|
||||
|
||||
|
||||
struct SalOp{
|
||||
SalOpBase base;
|
||||
belle_sip_listener_callbacks_t callbacks;
|
||||
belle_sip_request_t* register_request;
|
||||
belle_sip_response_t* register_response;
|
||||
SalAuthInfo auth_info;
|
||||
unsigned long int registration_refresh_timer;
|
||||
};
|
||||
|
||||
|
||||
#endif /* SAL_IMPL_H_ */
|
||||
435
coreapi/bellesip_sal/sal_op_impl.c
Normal file
435
coreapi/bellesip_sal/sal_op_impl.c
Normal file
|
|
@ -0,0 +1,435 @@
|
|||
/*
|
||||
linphone
|
||||
Copyright (C) 2012 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.
|
||||
*/
|
||||
#include "sal_impl.h"
|
||||
|
||||
static void sal_add_pending_auth(Sal *sal, SalOp *op){
|
||||
sal->pending_auths=ms_list_append(sal->pending_auths,op);
|
||||
}
|
||||
|
||||
static void sal_remove_pending_auth(Sal *sal, SalOp *op){
|
||||
sal->pending_auths=ms_list_remove(sal->pending_auths,op);
|
||||
}
|
||||
|
||||
/*create an operation */
|
||||
SalOp * sal_op_new(Sal *sal){
|
||||
SalOp *op=ms_new0(SalOp,1);
|
||||
__sal_op_init(op,sal);
|
||||
return op;
|
||||
}
|
||||
|
||||
void sal_op_release(SalOp *op){
|
||||
__sal_op_free(op);
|
||||
if (op->register_request) belle_sip_object_unref(op->register_request);
|
||||
if (op->registration_refresh_timer>0) {
|
||||
belle_sip_main_loop_cancel_source(belle_sip_stack_get_main_loop(op->base.root->stack),op->registration_refresh_timer);
|
||||
}
|
||||
return ;
|
||||
}
|
||||
void sal_op_authenticate(SalOp *op, const SalAuthInfo *info){
|
||||
belle_sip_header_www_authenticate_t* authenticate;
|
||||
belle_sip_header_authorization_t* authorization;
|
||||
const char* ha1;
|
||||
char computed_ha1[33];
|
||||
|
||||
if (info->ha1) {
|
||||
ha1=info->ha1;
|
||||
} else {
|
||||
if(belle_sip_auth_helper_compute_ha1(info->userid,info->realm,info->password, computed_ha1)) {
|
||||
goto error;
|
||||
} else
|
||||
ha1=computed_ha1;
|
||||
}
|
||||
if (!op->register_response) {
|
||||
ms_error("try to authenticate an unchallenged op [%p]",op);
|
||||
goto error;
|
||||
}
|
||||
authenticate = BELLE_SIP_HEADER_WWW_AUTHENTICATE(belle_sip_message_get_header(BELLE_SIP_MESSAGE(op->register_response),BELLE_SIP_WWW_AUTHENTICATE));
|
||||
if (authenticate) {
|
||||
authorization = belle_sip_auth_helper_create_authorization(authenticate);
|
||||
} else {
|
||||
/*proxy inerite from www*/
|
||||
authenticate = BELLE_SIP_HEADER_WWW_AUTHENTICATE(belle_sip_message_get_header(BELLE_SIP_MESSAGE(op->register_response),BELLE_SIP_PROXY_AUTHENTICATE));
|
||||
authorization = BELLE_SIP_HEADER_AUTHORIZATION(belle_sip_auth_helper_create_proxy_authorization(BELLE_SIP_HEADER_PROXY_AUTHENTICATE(authenticate)));
|
||||
}
|
||||
belle_sip_header_authorization_set_uri(authorization,belle_sip_request_get_uri(op->register_request));
|
||||
belle_sip_header_authorization_set_username(authorization,info->userid);
|
||||
|
||||
if (belle_sip_auth_helper_fill_authorization(authorization
|
||||
,belle_sip_request_get_method(op->register_request)
|
||||
,ha1)) {
|
||||
belle_sip_object_unref(authorization);
|
||||
goto error;
|
||||
}
|
||||
belle_sip_message_set_header(BELLE_SIP_MESSAGE(op->register_request),BELLE_SIP_HEADER(authorization));
|
||||
sal_register_refresh(op,-1);
|
||||
return;
|
||||
|
||||
error:
|
||||
ms_error("cannot generate authorization for [%s] at [%s]",info->userid,info->realm);
|
||||
|
||||
return ;
|
||||
}
|
||||
void sal_op_cancel_authentication(SalOp *h){
|
||||
ms_fatal("sal_op_cancel_authentication not implemented yet");
|
||||
return ;
|
||||
}
|
||||
|
||||
int sal_op_get_auth_requested(SalOp *op, const char **realm, const char **username){
|
||||
*realm=op->auth_info.realm;
|
||||
*username=op->auth_info.username;
|
||||
return 0;
|
||||
}
|
||||
/*Call API*/
|
||||
int sal_call_set_local_media_description(SalOp *h, SalMediaDescription *desc){
|
||||
ms_fatal("sal_call_set_local_media_description not implemented yet");
|
||||
return -1;
|
||||
}
|
||||
int sal_call(SalOp *h, const char *from, const char *to){
|
||||
ms_fatal("sal_call not implemented yet");
|
||||
return -1;
|
||||
}
|
||||
int sal_call_notify_ringing(SalOp *h, bool_t early_media){
|
||||
ms_fatal("sal_call_notify_ringing not implemented yet");
|
||||
return -1;
|
||||
}
|
||||
/*accept an incoming call or, during a call accept a reINVITE*/
|
||||
int sal_call_accept(SalOp*h){
|
||||
ms_fatal("sal_call_accept not implemented yet");
|
||||
return -1;
|
||||
}
|
||||
int sal_call_decline(SalOp *h, SalReason reason, const char *redirection /*optional*/){
|
||||
ms_fatal("sal_call_decline not implemented yet");
|
||||
return -1;
|
||||
}
|
||||
int sal_call_update(SalOp *h, const char *subject){
|
||||
ms_fatal("sal_call_update not implemented yet");
|
||||
return -1;
|
||||
}
|
||||
SalMediaDescription * sal_call_get_remote_media_description(SalOp *h){
|
||||
ms_fatal("sal_call_get_remote_media_description not implemented yet");
|
||||
return NULL;
|
||||
}
|
||||
SalMediaDescription * sal_call_get_final_media_description(SalOp *h){
|
||||
ms_fatal("sal_call_get_final_media_description not implemented yet");
|
||||
return NULL;
|
||||
}
|
||||
int sal_call_refer(SalOp *h, const char *refer_to){
|
||||
ms_fatal("sal_call_refer not implemented yet");
|
||||
return -1;
|
||||
}
|
||||
int sal_call_refer_with_replaces(SalOp *h, SalOp *other_call_h){
|
||||
ms_fatal("sal_call_refer_with_replaces not implemented yet");
|
||||
return -1;
|
||||
}
|
||||
int sal_call_accept_refer(SalOp *h){
|
||||
ms_fatal("sal_call_accept_refer not implemented yet");
|
||||
return -1;
|
||||
}
|
||||
/*informs this call is consecutive to an incoming refer */
|
||||
int sal_call_set_referer(SalOp *h, SalOp *refered_call){
|
||||
ms_fatal("sal_call_set_referer not implemented yet");
|
||||
return -1;
|
||||
}
|
||||
/* returns the SalOp of a call that should be replaced by h, if any */
|
||||
SalOp *sal_call_get_replaces(SalOp *h){
|
||||
ms_fatal("sal_call_get_replaces not implemented yet");
|
||||
return NULL;
|
||||
}
|
||||
int sal_call_send_dtmf(SalOp *h, char dtmf){
|
||||
ms_fatal("sal_call_send_dtmf not implemented yet");
|
||||
return -1;
|
||||
}
|
||||
int sal_call_terminate(SalOp *h){
|
||||
ms_fatal("sal_call_terminate not implemented yet");
|
||||
return -1;
|
||||
}
|
||||
bool_t sal_call_autoanswer_asked(SalOp *op){
|
||||
ms_fatal("sal_call_autoanswer_asked not implemented yet");
|
||||
return -1;
|
||||
}
|
||||
void sal_call_send_vfu_request(SalOp *h){
|
||||
ms_fatal("sal_call_send_vfu_request not implemented yet");
|
||||
return ;
|
||||
}
|
||||
int sal_call_is_offerer(const SalOp *h){
|
||||
ms_fatal("sal_call_is_offerer not implemented yet");
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void process_authentication(SalOp *op, belle_sip_message_t *response) {
|
||||
/*only process a single header for now*/
|
||||
belle_sip_header_www_authenticate_t* authenticate;
|
||||
belle_sip_header_address_t* from = BELLE_SIP_HEADER_ADDRESS(belle_sip_message_get_header(response,BELLE_SIP_FROM));
|
||||
belle_sip_uri_t* uri = belle_sip_header_address_get_uri(from);
|
||||
authenticate = BELLE_SIP_HEADER_WWW_AUTHENTICATE(belle_sip_message_get_header(response,BELLE_SIP_WWW_AUTHENTICATE));
|
||||
if (!authenticate) {
|
||||
/*search for proxy authenticate*/
|
||||
authenticate = BELLE_SIP_HEADER_WWW_AUTHENTICATE(belle_sip_message_get_header(response,BELLE_SIP_PROXY_AUTHENTICATE));
|
||||
|
||||
}
|
||||
|
||||
|
||||
op->auth_info.realm=(char*)belle_sip_header_www_authenticate_get_realm(authenticate);
|
||||
op->auth_info.username=(char*)belle_sip_uri_get_user(uri);
|
||||
if (authenticate) {
|
||||
if (op->base.root->callbacks.auth_requested(op,&op->auth_info)) {
|
||||
sal_op_authenticate(op,&op->auth_info);
|
||||
} else {
|
||||
ms_message("No auth info found for [%s] at [%s]",op->auth_info.username,op->auth_info.realm);
|
||||
sal_add_pending_auth(op->base.root,op);
|
||||
}
|
||||
} else {
|
||||
ms_error(" missing authenticate header");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**************************REGISTRATION***************************///////////
|
||||
static void send_register_request(SalOp* op, belle_sip_request_t* request);
|
||||
|
||||
static void register_process_io_error(void *user_ctx, const belle_sip_io_error_event_t *event){
|
||||
ms_error("process_io_error not implemented yet");
|
||||
}
|
||||
|
||||
static void register_refresh(SalOp* op) {
|
||||
op->registration_refresh_timer=0;
|
||||
belle_sip_header_cseq_t* cseq=(belle_sip_header_cseq_t*)belle_sip_message_get_header(BELLE_SIP_MESSAGE(op->register_request),BELLE_SIP_CSEQ);
|
||||
belle_sip_header_cseq_set_seq_number(cseq,belle_sip_header_cseq_get_seq_number(cseq)+1);
|
||||
send_register_request(op,op->register_request);
|
||||
}
|
||||
static bool_t is_contact_equal(belle_sip_header_contact_t* a,belle_sip_header_contact_t* b) {
|
||||
if (!a | !b) return FALSE;
|
||||
return !belle_sip_uri_equals(belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(a))
|
||||
,belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(b)));
|
||||
}
|
||||
static void register_response_event(void *user_ctx, const belle_sip_response_event_t *event){
|
||||
belle_sip_client_transaction_t* client_transaction = belle_sip_response_event_get_client_transaction(event);
|
||||
SalOp* op = (SalOp*)belle_sip_transaction_get_application_data(BELLE_SIP_TRANSACTION(client_transaction));
|
||||
belle_sip_response_t* response = belle_sip_response_event_get_response(event);
|
||||
belle_sip_header_expires_t* expires_header;
|
||||
belle_sip_request_t* old_register_request=NULL;;
|
||||
belle_sip_response_t* old_register_response=NULL;;
|
||||
const belle_sip_list_t* contact_header_list;
|
||||
int response_code = belle_sip_response_get_status_code(response);
|
||||
int expires=-1;
|
||||
if (response_code<200) return;/*nothing to do*/
|
||||
|
||||
/*begin
|
||||
* maybe only the transaction should be kept*/
|
||||
old_register_request=op->register_request;
|
||||
op->register_request=belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(client_transaction));
|
||||
belle_sip_object_ref(op->register_request);
|
||||
if (old_register_request) belle_sip_object_unref(old_register_request);
|
||||
|
||||
old_register_response=op->register_response;
|
||||
op->register_response=response; /*kept for use at authorization time*/
|
||||
belle_sip_object_ref(op->register_response);
|
||||
if (old_register_response) belle_sip_object_unref(old_register_response);
|
||||
/*end*/
|
||||
switch (response_code) {
|
||||
case 200: {
|
||||
|
||||
contact_header_list = belle_sip_message_get_headers(BELLE_SIP_MESSAGE(response),BELLE_SIP_CONTACT);
|
||||
if (contact_header_list) {
|
||||
contact_header_list = belle_sip_list_find_custom((belle_sip_list_t*)contact_header_list,(belle_sip_compare_func)is_contact_equal, (const void*)sal_op_get_contact_address(op));
|
||||
if (!contact_header_list) {
|
||||
ms_error("no matching contact for [%s]", sal_op_get_contact(op));
|
||||
return;
|
||||
}
|
||||
expires=belle_sip_header_contact_get_expires(BELLE_SIP_HEADER_CONTACT(contact_header_list->data));
|
||||
|
||||
}
|
||||
|
||||
if (expires<0 ) {
|
||||
/*no contact with expire, looking for Expires header*/
|
||||
if ((expires_header=(belle_sip_header_expires_t*)belle_sip_message_get_header(BELLE_SIP_MESSAGE(response),BELLE_SIP_EXPIRES))) {
|
||||
expires = belle_sip_header_expires_get_expires(expires_header);
|
||||
}
|
||||
}
|
||||
if (expires<0) {
|
||||
ms_message("Neither Expires header nor corresponding Contact header found");
|
||||
expires=0;
|
||||
}
|
||||
|
||||
op->base.root->callbacks.register_success(op,expires_header&&expires>=0);
|
||||
if (expires>0) {
|
||||
if (op->registration_refresh_timer>0) {
|
||||
belle_sip_main_loop_cancel_source(belle_sip_stack_get_main_loop(op->base.root->stack),op->registration_refresh_timer);
|
||||
}
|
||||
op->registration_refresh_timer = belle_sip_main_loop_add_timeout(belle_sip_stack_get_main_loop(op->base.root->stack),(belle_sip_source_func_t)register_refresh,op,belle_sip_header_expires_get_expires(expires_header)*1000);
|
||||
}
|
||||
sal_remove_pending_auth(op->base.root,op);/*just in case*/
|
||||
break;
|
||||
}
|
||||
case 401:
|
||||
case 407:{
|
||||
|
||||
process_authentication(op,BELLE_SIP_MESSAGE(response));
|
||||
break;
|
||||
}
|
||||
default:{
|
||||
ms_error("Unexpected answer [%s] for registration request bound to [%s]",belle_sip_response_get_reason_phrase(response),op->base.from);
|
||||
op->base.root->callbacks.register_failure(op,SalErrorFailure,SalReasonUnknown,belle_sip_response_get_reason_phrase(response));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
static void register_process_timeout(void *user_ctx, const belle_sip_timeout_event_t *event) {
|
||||
ms_error("process_timeout not implemented yet");
|
||||
}
|
||||
static void register_process_transaction_terminated(void *user_ctx, const belle_sip_transaction_terminated_event_t *event) {
|
||||
ms_error("process_transaction_terminated not implemented yet");
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void send_register_request(SalOp* op, belle_sip_request_t* request) {
|
||||
belle_sip_client_transaction_t* client_transaction;
|
||||
belle_sip_provider_t* prov=op->base.root->prov;
|
||||
op->callbacks.process_io_error=register_process_io_error;
|
||||
op->callbacks.process_response_event=register_response_event;
|
||||
op->callbacks.process_timeout=register_process_timeout;
|
||||
op->callbacks.process_transaction_terminated=register_process_transaction_terminated;
|
||||
client_transaction = belle_sip_provider_create_client_transaction(prov,request);
|
||||
belle_sip_transaction_set_application_data(BELLE_SIP_TRANSACTION(client_transaction),op);
|
||||
belle_sip_client_transaction_send_request(client_transaction);
|
||||
|
||||
}
|
||||
/*if expire = -1, does not change expires*/
|
||||
static void send_register_request_with_expires(SalOp* op, belle_sip_request_t* request,int expires) {
|
||||
belle_sip_header_expires_t* expires_header=(belle_sip_header_expires_t*)belle_sip_message_get_header(BELLE_SIP_MESSAGE(request),BELLE_SIP_EXPIRES);
|
||||
|
||||
if (!expires_header) {
|
||||
belle_sip_message_add_header(BELLE_SIP_MESSAGE(request),BELLE_SIP_HEADER(expires_header=belle_sip_header_expires_new()));
|
||||
}
|
||||
if (expires>=0) belle_sip_header_expires_set_expires(expires_header,expires);
|
||||
send_register_request(op,request);
|
||||
}
|
||||
|
||||
int sal_register(SalOp *op, const char *proxy, const char *from, int expires){
|
||||
belle_sip_request_t *req;
|
||||
belle_sip_provider_t* prov=op->base.root->prov;
|
||||
belle_sip_header_contact_t* contact_header =belle_sip_header_contact_new();
|
||||
belle_sip_header_from_t* from_header;
|
||||
belle_sip_header_to_t* to_header;
|
||||
belle_sip_uri_t* req_uri;
|
||||
belle_sip_uri_t* contact_uri;
|
||||
sal_op_set_from(op,from);
|
||||
sal_op_set_to(op,from);
|
||||
char token[10];
|
||||
if (expires<0) goto error;
|
||||
from_header = belle_sip_header_from_create(from,belle_sip_random_token(token,sizeof(token)));
|
||||
if (!from_header) goto error;
|
||||
to_header=belle_sip_header_to_create(from,NULL);
|
||||
req_uri = (belle_sip_uri_t*)belle_sip_object_clone((belle_sip_object_t*)belle_sip_header_address_get_uri((belle_sip_header_address_t*)to_header));
|
||||
belle_sip_uri_set_user(req_uri,NULL);
|
||||
|
||||
if (sal_op_get_contact(op))
|
||||
contact_uri= belle_sip_uri_parse(sal_op_get_contact(op));
|
||||
else
|
||||
contact_uri=belle_sip_uri_new();
|
||||
|
||||
if (!contact_uri) goto error;
|
||||
belle_sip_header_address_set_uri((belle_sip_header_address_t*)contact_header,contact_uri);
|
||||
sal_op_set_route(op,proxy);
|
||||
/*FIXME use route info if needed*/
|
||||
|
||||
|
||||
req=belle_sip_request_create(
|
||||
req_uri,
|
||||
"REGISTER",
|
||||
belle_sip_provider_create_call_id(prov),
|
||||
belle_sip_header_cseq_create(20,"REGISTER"),
|
||||
from_header,
|
||||
to_header,
|
||||
belle_sip_header_via_new(),
|
||||
70);
|
||||
|
||||
|
||||
belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(contact_header));
|
||||
send_register_request_with_expires(op,req,expires);
|
||||
|
||||
return 0;
|
||||
error:
|
||||
ms_error("Cannot initiate register to [%s] for [%s], expire [%i]",proxy,from,expires);
|
||||
if (contact_header) belle_sip_object_unref(contact_header);
|
||||
if (from_header) belle_sip_object_unref(from_header);
|
||||
if (to_header) belle_sip_object_unref(to_header);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int sal_register_refresh(SalOp *op, int expires){
|
||||
belle_sip_header_cseq_t* cseq=(belle_sip_header_cseq_t*)belle_sip_message_get_header(BELLE_SIP_MESSAGE(op->register_request),BELLE_SIP_CSEQ);
|
||||
belle_sip_header_cseq_set_seq_number(cseq,belle_sip_header_cseq_get_seq_number(cseq)+1);
|
||||
send_register_request_with_expires(op,op->register_request,expires);
|
||||
return 0;
|
||||
}
|
||||
int sal_unregister(SalOp *op){
|
||||
belle_sip_header_cseq_t* cseq=(belle_sip_header_cseq_t*)belle_sip_message_get_header(BELLE_SIP_MESSAGE(op->register_request),BELLE_SIP_CSEQ);
|
||||
belle_sip_header_cseq_set_seq_number(cseq,belle_sip_header_cseq_get_seq_number(cseq)+1);
|
||||
send_register_request_with_expires(op,op->register_request,0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*Messaging */
|
||||
int sal_text_send(SalOp *op, const char *from, const char *to, const char *text){
|
||||
ms_fatal("sal_text_send not implemented yet");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*presence Subscribe/notify*/
|
||||
int sal_subscribe_presence(SalOp *op, const char *from, const char *to){
|
||||
ms_fatal("sal_subscribe_presence not implemented yet");
|
||||
return -1;
|
||||
}
|
||||
int sal_unsubscribe(SalOp *op){
|
||||
ms_fatal("sal_unsubscribe not implemented yet");
|
||||
return -1;
|
||||
}
|
||||
int sal_subscribe_accept(SalOp *op){
|
||||
ms_fatal("sal_subscribe_accept not implemented yet");
|
||||
return -1;
|
||||
}
|
||||
int sal_subscribe_decline(SalOp *op){
|
||||
ms_fatal("sal_subscribe_decline not implemented yet");
|
||||
return -1;
|
||||
}
|
||||
int sal_notify_presence(SalOp *op, SalPresenceStatus status, const char *status_message){
|
||||
ms_fatal("sal_notify_presence not implemented yet");
|
||||
return -1;
|
||||
}
|
||||
int sal_notify_close(SalOp *op){
|
||||
ms_fatal("sal_notify_close not implemented yet");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*presence publish */
|
||||
int sal_publish(SalOp *op, const char *from, const char *to, SalPresenceStatus status){
|
||||
ms_fatal("sal_publish not implemented yet");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/*ping: main purpose is to obtain its own contact address behind firewalls*/
|
||||
int sal_ping(SalOp *op, const char *from, const char *to){
|
||||
ms_fatal("sal_ping not implemented yet");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -600,7 +600,7 @@ static void call_released(SalOp *op){
|
|||
}else ms_error("call_released() for already destroyed call ?");
|
||||
}
|
||||
|
||||
static void auth_requested(SalOp *h, const char *realm, const char *username){
|
||||
static void auth_requested_legacy(SalOp *h, const char *realm, const char *username){
|
||||
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(h));
|
||||
LinphoneAuthInfo *ai=(LinphoneAuthInfo*)linphone_core_find_auth_info(lc,realm,username);
|
||||
LinphoneCall *call=is_a_linphone_call(sal_op_get_user_pointer(h));
|
||||
|
|
@ -794,7 +794,19 @@ static void ping_reply(SalOp *op){
|
|||
ms_warning("ping reply without call attached...");
|
||||
}
|
||||
}
|
||||
|
||||
static bool_t auth_requested(SalOp*op, SalAuthInfo* sai) {
|
||||
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op));
|
||||
LinphoneAuthInfo *ai=(LinphoneAuthInfo*)linphone_core_find_auth_info(lc,sai->realm,sai->username);
|
||||
if (ai) {
|
||||
sai->userid=ai->userid?ai->userid:ai->username;
|
||||
sai->password=ai->passwd;
|
||||
ai->usecount++;
|
||||
ai->last_use_time=ms_time(NULL);
|
||||
return TRUE;
|
||||
} else {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
SalCallbacks linphone_sal_callbacks={
|
||||
call_received,
|
||||
call_ringing,
|
||||
|
|
@ -804,7 +816,7 @@ SalCallbacks linphone_sal_callbacks={
|
|||
call_terminated,
|
||||
call_failure,
|
||||
call_released,
|
||||
auth_requested,
|
||||
auth_requested_legacy,
|
||||
auth_success,
|
||||
register_success,
|
||||
register_failure,
|
||||
|
|
@ -816,7 +828,8 @@ SalCallbacks linphone_sal_callbacks={
|
|||
notify_presence,
|
||||
subscribe_received,
|
||||
subscribe_closed,
|
||||
ping_reply
|
||||
ping_reply,
|
||||
auth_requested
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1621,13 +1621,13 @@ void linphone_core_enable_ipv6(LinphoneCore *lc, bool_t val){
|
|||
|
||||
|
||||
static void monitor_network_state(LinphoneCore *lc, time_t curtime){
|
||||
static time_t last_check=0;
|
||||
static bool_t last_status=FALSE;
|
||||
static time_t last_check=0; /*shared beetwen multi linphonecore*/
|
||||
bool_t last_status=linphone_core_is_network_reachabled(lc);
|
||||
char result[LINPHONE_IPADDR_SIZE];
|
||||
bool_t new_status=last_status;
|
||||
|
||||
/* only do the network up checking every five seconds */
|
||||
if (last_check==0 || (curtime-last_check)>=5){
|
||||
if (lc->netup_time==0 || (curtime-last_check)>=5){
|
||||
linphone_core_get_local_ip_for(lc->sip_conf.ipv6_enabled ? AF_INET6 : AF_INET,NULL,result);
|
||||
if (strcmp(result,"::1")!=0 && strcmp(result,"127.0.0.1")!=0){
|
||||
new_status=TRUE;
|
||||
|
|
@ -4144,6 +4144,7 @@ void sip_config_uninit(LinphoneCore *lc)
|
|||
MSList *elem;
|
||||
int i;
|
||||
sip_config_t *config=&lc->sip_conf;
|
||||
bool_t all_unregistered=FALSE;
|
||||
|
||||
lp_config_set_int(lc->config,"sip","guess_hostname",config->guess_hostname);
|
||||
lp_config_set_string(lc->config,"sip","contact",config->contact);
|
||||
|
|
@ -4156,13 +4157,17 @@ void sip_config_uninit(LinphoneCore *lc)
|
|||
|
||||
|
||||
|
||||
for(elem=config->proxies,i=0;elem!=NULL;elem=ms_list_next(elem),i++){
|
||||
for(elem=config->proxies;elem!=NULL;elem=ms_list_next(elem)){
|
||||
LinphoneProxyConfig *cfg=(LinphoneProxyConfig*)(elem->data);
|
||||
linphone_proxy_config_edit(cfg); /* to unregister */
|
||||
}
|
||||
|
||||
for (i=0;i<20;i++){
|
||||
for (i=0;i<20&&!all_unregistered;i++){
|
||||
sal_iterate(lc->sal);
|
||||
for(elem=config->proxies;elem!=NULL;elem=ms_list_next(elem)){
|
||||
LinphoneProxyConfig *cfg=(LinphoneProxyConfig*)(elem->data);
|
||||
all_unregistered|=!linphone_proxy_config_is_registered(cfg);
|
||||
}
|
||||
#ifndef WIN32
|
||||
usleep(100000);
|
||||
#else
|
||||
|
|
|
|||
|
|
@ -237,7 +237,7 @@ void linphone_proxy_config_enable_publish(LinphoneProxyConfig *obj, bool_t val){
|
|||
void linphone_proxy_config_edit(LinphoneProxyConfig *obj){
|
||||
if (obj->reg_sendregister){
|
||||
/* unregister */
|
||||
if (obj->state != LinphoneRegistrationNone && obj->state != LinphoneRegistrationCleared) {
|
||||
if (obj->state == LinphoneRegistrationOk) {
|
||||
sal_unregister(obj->op);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -203,6 +203,14 @@ bool_t sal_media_description_equals(const SalMediaDescription *md1, const SalMed
|
|||
}
|
||||
return TRUE;
|
||||
}
|
||||
static void assign_address(SalAddress** address, const char *value){
|
||||
if (*address){
|
||||
sal_address_destroy(*address);
|
||||
*address=NULL;
|
||||
}
|
||||
if (value)
|
||||
*address=sal_address_new(value);
|
||||
}
|
||||
|
||||
static void assign_string(char **str, const char *arg){
|
||||
if (*str){
|
||||
|
|
@ -212,9 +220,22 @@ static void assign_string(char **str, const char *arg){
|
|||
if (arg)
|
||||
*str=ms_strdup(arg);
|
||||
}
|
||||
|
||||
void sal_op_set_contact_address(SalOp *op, const SalAddress *address){
|
||||
char* address_string=sal_address_as_string(address); /*can probably be optimized*/
|
||||
sal_op_set_contact(op,address_string);
|
||||
ms_free(address_string);
|
||||
}
|
||||
const SalAddress* sal_op_get_contact_address(const SalOp *op) {
|
||||
return ((SalOpBase*)op)->contact_address;
|
||||
}
|
||||
void sal_op_set_contact(SalOp *op, const char *contact){
|
||||
assign_string(&((SalOpBase*)op)->contact,contact);
|
||||
char* contact_string=NULL;
|
||||
assign_address(&((SalOpBase*)op)->contact_address,contact);
|
||||
if (((SalOpBase*)op)->contact_address) {
|
||||
contact_string=sal_address_as_string(((SalOpBase*)op)->contact_address);
|
||||
}
|
||||
assign_string(&((SalOpBase*)op)->contact,contact_string);
|
||||
if(contact_string) ms_free(contact_string);
|
||||
}
|
||||
|
||||
void sal_op_set_route(SalOp *op, const char *route){
|
||||
|
|
|
|||
|
|
@ -164,6 +164,7 @@ typedef struct SalOpBase{
|
|||
Sal *root;
|
||||
char *route; /*or request-uri for REGISTER*/
|
||||
char *contact;
|
||||
SalAddress* contact_address;
|
||||
char *from;
|
||||
char *to;
|
||||
char *origin;
|
||||
|
|
@ -211,6 +212,14 @@ typedef enum SalSubscribeState{
|
|||
SalSubscribeTerminated
|
||||
}SalSubscribeState;
|
||||
|
||||
typedef struct SalAuthInfo{
|
||||
char *username;
|
||||
char *userid;
|
||||
char *password;
|
||||
char *realm;
|
||||
char *ha1;
|
||||
}SalAuthInfo;
|
||||
|
||||
typedef void (*SalOnCallReceived)(SalOp *op);
|
||||
typedef void (*SalOnCallRinging)(SalOp *op);
|
||||
typedef void (*SalOnCallAccepted)(SalOp *op);
|
||||
|
|
@ -219,7 +228,8 @@ typedef void (*SalOnCallUpdating)(SalOp *op);/*< Called when a reINVITE is recei
|
|||
typedef void (*SalOnCallTerminated)(SalOp *op, const char *from);
|
||||
typedef void (*SalOnCallFailure)(SalOp *op, SalError error, SalReason reason, const char *details, int code);
|
||||
typedef void (*SalOnCallReleased)(SalOp *salop);
|
||||
typedef void (*SalOnAuthRequested)(SalOp *op, const char *realm, const char *username);
|
||||
typedef void (*SalOnAuthRequestedLegacy)(SalOp *op, const char *realm, const char *username);
|
||||
typedef bool_t (*SalOnAuthRequested)(SalOp *salop,SalAuthInfo* info);
|
||||
typedef void (*SalOnAuthSuccess)(SalOp *op, const char *realm, const char *username);
|
||||
typedef void (*SalOnRegisterSuccess)(SalOp *op, bool_t registered);
|
||||
typedef void (*SalOnRegisterFailure)(SalOp *op, SalError error, SalReason reason, const char *details);
|
||||
|
|
@ -232,6 +242,9 @@ typedef void (*SalOnNotifyPresence)(SalOp *op, SalSubscribeState ss, SalPresence
|
|||
typedef void (*SalOnSubscribeReceived)(SalOp *salop, const char *from);
|
||||
typedef void (*SalOnSubscribeClosed)(SalOp *salop, const char *from);
|
||||
typedef void (*SalOnPingReply)(SalOp *salop);
|
||||
/*allows sal implementation to access auth info if available, return TRUE if found*/
|
||||
|
||||
|
||||
|
||||
typedef struct SalCallbacks{
|
||||
SalOnCallReceived call_received;
|
||||
|
|
@ -242,7 +255,7 @@ typedef struct SalCallbacks{
|
|||
SalOnCallTerminated call_terminated;
|
||||
SalOnCallFailure call_failure;
|
||||
SalOnCallReleased call_released;
|
||||
SalOnAuthRequested auth_requested;
|
||||
SalOnAuthRequestedLegacy auth_requested_legacy;
|
||||
SalOnAuthSuccess auth_success;
|
||||
SalOnRegisterSuccess register_success;
|
||||
SalOnRegisterFailure register_failure;
|
||||
|
|
@ -255,14 +268,10 @@ typedef struct SalCallbacks{
|
|||
SalOnSubscribeReceived subscribe_received;
|
||||
SalOnSubscribeClosed subscribe_closed;
|
||||
SalOnPingReply ping_reply;
|
||||
SalOnAuthRequested auth_requested;
|
||||
}SalCallbacks;
|
||||
|
||||
typedef struct SalAuthInfo{
|
||||
char *username;
|
||||
char *userid;
|
||||
char *password;
|
||||
char *realm;
|
||||
}SalAuthInfo;
|
||||
|
||||
|
||||
SalAuthInfo* sal_auth_info_new();
|
||||
SalAuthInfo* sal_auth_info_clone(const SalAuthInfo* auth_info);
|
||||
|
|
@ -298,6 +307,7 @@ SalOp * sal_op_new(Sal *sal);
|
|||
/*generic SalOp API, working for all operations */
|
||||
Sal *sal_op_get_sal(const SalOp *op);
|
||||
void sal_op_set_contact(SalOp *op, const char *contact);
|
||||
void sal_op_set_contact_address(SalOp *op, const SalAddress* address);
|
||||
void sal_op_set_route(SalOp *op, const char *route);
|
||||
void sal_op_set_from(SalOp *op, const char *from);
|
||||
void sal_op_set_to(SalOp *op, const char *to);
|
||||
|
|
@ -309,6 +319,7 @@ int sal_op_get_auth_requested(SalOp *h, const char **realm, const char **usernam
|
|||
const char *sal_op_get_from(const SalOp *op);
|
||||
const char *sal_op_get_to(const SalOp *op);
|
||||
const char *sal_op_get_contact(const SalOp *op);
|
||||
const SalAddress *sal_op_get_contact_address(const SalOp *op);
|
||||
const char *sal_op_get_route(const SalOp *op);
|
||||
const char *sal_op_get_proxy(const SalOp *op);
|
||||
/*for incoming requests, returns the origin of the packet as a sip uri*/
|
||||
|
|
|
|||
|
|
@ -1,661 +0,0 @@
|
|||
/*
|
||||
linphone
|
||||
Copyright (C) 2012 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.
|
||||
*/
|
||||
#include "sal.h"
|
||||
#include "belle-sip/belle-sip.h"
|
||||
/**/
|
||||
|
||||
|
||||
/* Address manipulation API*/
|
||||
SalAddress * sal_address_new(const char *uri){
|
||||
belle_sip_header_address_t* result;
|
||||
if (uri) {
|
||||
return (SalAddress *)belle_sip_header_address_parse (uri);
|
||||
} else {
|
||||
result = belle_sip_header_address_new();
|
||||
belle_sip_header_address_set_uri(result,belle_sip_uri_new());
|
||||
return (SalAddress *)result;
|
||||
}
|
||||
}
|
||||
SalAddress * sal_address_clone(const SalAddress *addr){
|
||||
return (SalAddress *) belle_sip_object_clone(BELLE_SIP_OBJECT(addr));
|
||||
}
|
||||
const char *sal_address_get_scheme(const SalAddress *addr){
|
||||
belle_sip_header_address_t* header_addr = BELLE_SIP_HEADER_ADDRESS(addr);
|
||||
belle_sip_uri_t* uri = belle_sip_header_address_get_uri(header_addr);
|
||||
if (uri) {
|
||||
if (belle_sip_uri_is_secure(uri)) return "sips";
|
||||
else return "sip";
|
||||
} else
|
||||
return NULL;
|
||||
}
|
||||
const char *sal_address_get_display_name(const SalAddress* addr){
|
||||
belle_sip_header_address_t* header_addr = BELLE_SIP_HEADER_ADDRESS(addr);
|
||||
return belle_sip_header_address_get_displayname(header_addr);
|
||||
|
||||
}
|
||||
const char *sal_address_get_display_name_unquoted(const SalAddress *addr){
|
||||
return sal_address_get_display_name(addr);
|
||||
}
|
||||
#define SAL_ADDRESS_GET(addr,param) \
|
||||
belle_sip_header_address_t* header_addr = BELLE_SIP_HEADER_ADDRESS(addr);\
|
||||
belle_sip_uri_t* uri = belle_sip_header_address_get_uri(header_addr);\
|
||||
if (uri) {\
|
||||
return belle_sip_uri_get_##param(uri);\
|
||||
} else\
|
||||
return NULL;
|
||||
|
||||
#define SAL_ADDRESS_SET(addr,param,value) \
|
||||
belle_sip_header_address_t* header_addr = BELLE_SIP_HEADER_ADDRESS(addr);\
|
||||
belle_sip_uri_t* uri = belle_sip_header_address_get_uri(header_addr);\
|
||||
belle_sip_uri_set_##param(uri,value);
|
||||
|
||||
const char *sal_address_get_username(const SalAddress *addr){
|
||||
SAL_ADDRESS_GET(addr,user)
|
||||
}
|
||||
const char *sal_address_get_domain(const SalAddress *addr){
|
||||
SAL_ADDRESS_GET(addr,host)
|
||||
}
|
||||
const char * sal_address_get_port(const SalAddress *addr){
|
||||
ms_fatal("sal_address_get_port not implemented yet");
|
||||
return NULL;
|
||||
}
|
||||
int sal_address_get_port_int(const SalAddress *addr){
|
||||
belle_sip_header_address_t* header_addr = BELLE_SIP_HEADER_ADDRESS(addr);
|
||||
belle_sip_uri_t* uri = belle_sip_header_address_get_uri(header_addr);
|
||||
if (uri) {
|
||||
return belle_sip_uri_get_port(uri);
|
||||
} else
|
||||
return -1;
|
||||
}
|
||||
SalTransport sal_address_get_transport(const SalAddress* addr){
|
||||
belle_sip_header_address_t* header_addr = BELLE_SIP_HEADER_ADDRESS(addr);
|
||||
belle_sip_uri_t* uri = belle_sip_header_address_get_uri(header_addr);
|
||||
if (uri) {
|
||||
return sal_transport_parse(belle_sip_uri_get_transport_param(uri));
|
||||
} else
|
||||
return SalTransportUDP;
|
||||
};
|
||||
|
||||
void sal_address_set_display_name(SalAddress *addr, const char *display_name){
|
||||
belle_sip_header_address_t* header_addr = BELLE_SIP_HEADER_ADDRESS(addr);
|
||||
belle_sip_header_address_set_displayname(header_addr,display_name);
|
||||
}
|
||||
void sal_address_set_username(SalAddress *addr, const char *username){
|
||||
SAL_ADDRESS_SET(addr,user,username);
|
||||
}
|
||||
void sal_address_set_domain(SalAddress *addr, const char *host){
|
||||
SAL_ADDRESS_SET(addr,host,host);
|
||||
}
|
||||
void sal_address_set_port(SalAddress *addr, const char *port){
|
||||
SAL_ADDRESS_SET(addr,port,atoi(port));
|
||||
}
|
||||
void sal_address_set_port_int(SalAddress *addr, int port){
|
||||
SAL_ADDRESS_SET(addr,port,port);
|
||||
}
|
||||
void sal_address_clean(SalAddress *addr){
|
||||
belle_sip_header_address_t* header_addr = BELLE_SIP_HEADER_ADDRESS(addr);
|
||||
belle_sip_header_address_set_displayname(header_addr,NULL);
|
||||
belle_sip_object_unref(belle_sip_header_address_get_uri(header_addr));
|
||||
belle_sip_header_address_set_uri(header_addr,belle_sip_uri_new());
|
||||
return ;
|
||||
}
|
||||
char *sal_address_as_string(const SalAddress *addr){
|
||||
return belle_sip_object_to_string(BELLE_SIP_OBJECT(addr));
|
||||
}
|
||||
char *sal_address_as_string_uri_only(const SalAddress *addr){
|
||||
belle_sip_header_address_t* header_addr = BELLE_SIP_HEADER_ADDRESS(addr);
|
||||
belle_sip_uri_t* uri = belle_sip_header_address_get_uri(header_addr);
|
||||
return belle_sip_object_to_string(BELLE_SIP_OBJECT(uri));
|
||||
}
|
||||
void sal_address_destroy(SalAddress *addr){
|
||||
belle_sip_header_address_t* header_addr = BELLE_SIP_HEADER_ADDRESS(addr);
|
||||
belle_sip_object_unref(header_addr);
|
||||
return ;
|
||||
}
|
||||
void sal_address_set_param(SalAddress *addr,const char* name,const char* value){
|
||||
belle_sip_parameters_t* parameters = BELLE_SIP_PARAMETERS(addr);
|
||||
belle_sip_parameters_set_parameter(parameters,name,value);
|
||||
return ;
|
||||
}
|
||||
void sal_address_set_transport(SalAddress* addr,SalTransport transport){
|
||||
SAL_ADDRESS_SET(addr,transport_param,sal_transport_to_string(transport));
|
||||
}
|
||||
|
||||
|
||||
struct Sal{
|
||||
SalCallbacks callbacks;
|
||||
belle_sip_listener_callbacks_t listener_callbacks;
|
||||
belle_sip_stack_t* stack;
|
||||
belle_sip_provider_t *prov;
|
||||
void *up; /*user pointer*/
|
||||
};
|
||||
|
||||
|
||||
struct SalOp{
|
||||
SalOpBase base;
|
||||
belle_sip_listener_callbacks_t callbacks;
|
||||
belle_sip_request_t* register_request;
|
||||
unsigned long int registration_refresh_timer;
|
||||
};
|
||||
|
||||
void sal_enable_logs(){
|
||||
belle_sip_set_log_level(BELLE_SIP_LOG_MESSAGE);
|
||||
}
|
||||
void sal_disable_logs() {
|
||||
belle_sip_set_log_level(BELLE_SIP_LOG_ERROR);
|
||||
}
|
||||
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_io_error(void *user_ctx, const belle_sip_io_error_event_t *event){
|
||||
ms_error("process_io_error not implemented yet");
|
||||
}
|
||||
static void process_request_event(void *user_ctx, const belle_sip_request_event_t *event) {
|
||||
ms_error("process_request_event not implemented yet");
|
||||
}
|
||||
static void process_response_event(void *user_ctx, const belle_sip_response_event_t *event){
|
||||
belle_sip_client_transaction_t* client_transaction = belle_sip_response_event_get_client_transaction(event);
|
||||
SalOp* op = (SalOp*)belle_sip_transaction_get_application_data(BELLE_SIP_TRANSACTION(client_transaction));
|
||||
if (op->callbacks.process_response_event) {
|
||||
op->callbacks.process_response_event(op,event);
|
||||
} else {
|
||||
ms_error("Unhandled event response [%p]",event);
|
||||
}
|
||||
|
||||
}
|
||||
static void process_timeout(void *user_ctx, const belle_sip_timeout_event_t *event) {
|
||||
/* belle_sip_client_transaction_t* client_transaction = belle_sip_timeout_event_get_client_transaction(event);
|
||||
SalOp* op = (SalOp*)belle_sip_transaction_get_application_data(BELLE_SIP_TRANSACTION(client_transaction));
|
||||
if (op->callbacks.process_timeout) {
|
||||
op->callbacks.process_timeout(op,event);
|
||||
} else*/ {
|
||||
ms_error("Unhandled event timeout [%p]",event);
|
||||
}
|
||||
}
|
||||
static void process_transaction_terminated(void *user_ctx, const belle_sip_transaction_terminated_event_t *event) {
|
||||
/* belle_sip_client_transaction_t* client_transaction = belle_sip_transaction_terminated_event_get_client_transaction(event);
|
||||
SalOp* op = (SalOp*)belle_sip_transaction_get_application_data(client_transaction);
|
||||
if (op->calbacks.process_transaction_terminated) {
|
||||
op->calbacks.process_transaction_terminated(op,event);
|
||||
} else */{
|
||||
ms_error("Unhandled transaction terminated [%p]",event);
|
||||
}
|
||||
}
|
||||
|
||||
Sal * sal_init(){
|
||||
Sal * sal=ms_new0(Sal,1);
|
||||
sal->stack = belle_sip_stack_new(NULL);
|
||||
sal->prov = belle_sip_stack_create_provider(sal->stack,NULL);
|
||||
sal->listener_callbacks.process_dialog_terminated=process_dialog_terminated;
|
||||
sal->listener_callbacks.process_io_error=process_io_error;
|
||||
sal->listener_callbacks.process_request_event=process_request_event;
|
||||
sal->listener_callbacks.process_response_event=process_response_event;
|
||||
sal->listener_callbacks.process_timeout=process_timeout;
|
||||
sal->listener_callbacks.process_transaction_terminated=process_transaction_terminated;
|
||||
belle_sip_provider_add_sip_listener(sal->prov,belle_sip_listener_create_from_callbacks(&sal->listener_callbacks,sal));
|
||||
return sal;
|
||||
}
|
||||
void sal_set_user_pointer(Sal *sal, void *user_data){
|
||||
sal->up=user_data;
|
||||
}
|
||||
|
||||
void *sal_get_user_pointer(const Sal *sal){
|
||||
return sal->up;
|
||||
}
|
||||
|
||||
static void unimplemented_stub(){
|
||||
ms_warning("Unimplemented SAL callback");
|
||||
}
|
||||
|
||||
void sal_set_callbacks(Sal *ctx, const SalCallbacks *cbs){
|
||||
memcpy(&ctx->callbacks,cbs,sizeof(*cbs));
|
||||
if (ctx->callbacks.call_received==NULL)
|
||||
ctx->callbacks.call_received=(SalOnCallReceived)unimplemented_stub;
|
||||
if (ctx->callbacks.call_ringing==NULL)
|
||||
ctx->callbacks.call_ringing=(SalOnCallRinging)unimplemented_stub;
|
||||
if (ctx->callbacks.call_accepted==NULL)
|
||||
ctx->callbacks.call_accepted=(SalOnCallAccepted)unimplemented_stub;
|
||||
if (ctx->callbacks.call_failure==NULL)
|
||||
ctx->callbacks.call_failure=(SalOnCallFailure)unimplemented_stub;
|
||||
if (ctx->callbacks.call_terminated==NULL)
|
||||
ctx->callbacks.call_terminated=(SalOnCallTerminated)unimplemented_stub;
|
||||
if (ctx->callbacks.call_released==NULL)
|
||||
ctx->callbacks.call_released=(SalOnCallReleased)unimplemented_stub;
|
||||
if (ctx->callbacks.call_updating==NULL)
|
||||
ctx->callbacks.call_updating=(SalOnCallUpdating)unimplemented_stub;
|
||||
if (ctx->callbacks.auth_requested==NULL)
|
||||
ctx->callbacks.auth_requested=(SalOnAuthRequested)unimplemented_stub;
|
||||
if (ctx->callbacks.auth_success==NULL)
|
||||
ctx->callbacks.auth_success=(SalOnAuthSuccess)unimplemented_stub;
|
||||
if (ctx->callbacks.register_success==NULL)
|
||||
ctx->callbacks.register_success=(SalOnRegisterSuccess)unimplemented_stub;
|
||||
if (ctx->callbacks.register_failure==NULL)
|
||||
ctx->callbacks.register_failure=(SalOnRegisterFailure)unimplemented_stub;
|
||||
if (ctx->callbacks.dtmf_received==NULL)
|
||||
ctx->callbacks.dtmf_received=(SalOnDtmfReceived)unimplemented_stub;
|
||||
if (ctx->callbacks.notify==NULL)
|
||||
ctx->callbacks.notify=(SalOnNotify)unimplemented_stub;
|
||||
if (ctx->callbacks.notify_presence==NULL)
|
||||
ctx->callbacks.notify_presence=(SalOnNotifyPresence)unimplemented_stub;
|
||||
if (ctx->callbacks.subscribe_received==NULL)
|
||||
ctx->callbacks.subscribe_received=(SalOnSubscribeReceived)unimplemented_stub;
|
||||
if (ctx->callbacks.text_received==NULL)
|
||||
ctx->callbacks.text_received=(SalOnTextReceived)unimplemented_stub;
|
||||
if (ctx->callbacks.ping_reply==NULL)
|
||||
ctx->callbacks.ping_reply=(SalOnPingReply)unimplemented_stub;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void sal_uninit(Sal* sal){
|
||||
belle_sip_object_unref(sal->prov);
|
||||
belle_sip_object_unref(sal->stack);
|
||||
ms_free(sal);
|
||||
return ;
|
||||
};
|
||||
|
||||
int sal_listen_port(Sal *ctx, const char *addr, int port, SalTransport tr, int is_secure){
|
||||
int result;
|
||||
belle_sip_listening_point_t* lp = belle_sip_stack_create_listening_point(ctx->stack,addr,port,sal_transport_to_string(tr));
|
||||
if (lp) {
|
||||
result = belle_sip_provider_add_listening_point(ctx->prov,lp);
|
||||
belle_sip_object_unref(lp);
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
static void remove_listening_point(belle_sip_listening_point_t* lp,belle_sip_provider_t* prov) {
|
||||
belle_sip_provider_remove_listening_point(prov,lp);
|
||||
}
|
||||
int sal_unlisten_ports(Sal *ctx){
|
||||
const belle_sip_list_t * lps = belle_sip_provider_get_listening_points(ctx->prov);
|
||||
belle_sip_list_t * tmp_list = belle_sip_list_copy(lps);
|
||||
belle_sip_list_for_each2 (tmp_list,(void (*)(void*,void*))remove_listening_point,ctx->prov);
|
||||
belle_sip_list_free(tmp_list);
|
||||
|
||||
ms_message("sal_unlisten_ports done");
|
||||
return 0;
|
||||
}
|
||||
ortp_socket_t sal_get_socket(Sal *ctx){
|
||||
ms_fatal("sal_get_socket not implemented yet");
|
||||
return -1;
|
||||
}
|
||||
void sal_set_user_agent(Sal *ctx, const char *user_agent){
|
||||
ms_error("sal_set_user_agent not implemented yet");
|
||||
return ;
|
||||
}
|
||||
/*keepalive period in ms*/
|
||||
void sal_set_keepalive_period(Sal *ctx,unsigned int value){
|
||||
ms_error("sal_set_keepalive_period not implemented yet");
|
||||
return ;
|
||||
}
|
||||
/**
|
||||
* returns keepalive period in ms
|
||||
* 0 desactiaved
|
||||
* */
|
||||
unsigned int sal_get_keepalive_period(Sal *ctx){
|
||||
ms_fatal("sal_get_keepalive_period not implemented yet");
|
||||
return -1;
|
||||
}
|
||||
void sal_use_session_timers(Sal *ctx, int expires){
|
||||
ms_error("sal_use_session_timers not implemented yet");
|
||||
return ;
|
||||
}
|
||||
void sal_use_double_registrations(Sal *ctx, bool_t enabled){
|
||||
ms_error("sal_use_double_registrations not implemented yet");
|
||||
return ;
|
||||
}
|
||||
void sal_reuse_authorization(Sal *ctx, bool_t enabled){
|
||||
ms_error("sal_reuse_authorization not implemented yet");
|
||||
return ;
|
||||
}
|
||||
void sal_use_one_matching_codec_policy(Sal *ctx, bool_t one_matching_codec){
|
||||
ms_error("sal_use_one_matching_codec_policy not implemented yet");
|
||||
return ;
|
||||
}
|
||||
void sal_use_rport(Sal *ctx, bool_t use_rports){
|
||||
ms_error("sal_use_rport not implemented yet");
|
||||
return ;
|
||||
}
|
||||
void sal_use_101(Sal *ctx, bool_t use_101){
|
||||
ms_error("sal_use_101 not implemented yet");
|
||||
return ;
|
||||
}
|
||||
void sal_set_root_ca(Sal* ctx, const char* rootCa){
|
||||
ms_error("sal_set_root_ca not implemented yet");
|
||||
return ;
|
||||
}
|
||||
void sal_verify_server_certificates(Sal *ctx, bool_t verify){
|
||||
ms_error("sal_verify_server_certificates not implemented yet");
|
||||
return ;
|
||||
}
|
||||
|
||||
int sal_iterate(Sal *sal){
|
||||
/*FIXME should be zero*/
|
||||
belle_sip_stack_sleep(sal->stack,1);
|
||||
return 0;
|
||||
}
|
||||
MSList * sal_get_pending_auths(Sal *sal){
|
||||
ms_fatal("sal_get_pending_auths not implemented yet");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*create an operation */
|
||||
SalOp * sal_op_new(Sal *sal){
|
||||
SalOp *op=ms_new0(SalOp,1);
|
||||
__sal_op_init(op,sal);
|
||||
return op;
|
||||
}
|
||||
|
||||
void sal_op_release(SalOp *op){
|
||||
__sal_op_free(op);
|
||||
if (op->register_request) belle_sip_object_unref(op->register_request);
|
||||
if (op->registration_refresh_timer>0) {
|
||||
belle_sip_main_loop_cancel_source(belle_sip_stack_get_main_loop(op->base.root->stack),op->registration_refresh_timer);
|
||||
}
|
||||
return ;
|
||||
}
|
||||
void sal_op_authenticate(SalOp *h, const SalAuthInfo *info){
|
||||
ms_fatal("sal_op_authenticate not implemented yet");
|
||||
return ;
|
||||
}
|
||||
void sal_op_cancel_authentication(SalOp *h){
|
||||
ms_fatal("sal_op_cancel_authentication not implemented yet");
|
||||
return ;
|
||||
}
|
||||
|
||||
int sal_op_get_auth_requested(SalOp *h, const char **realm, const char **username){
|
||||
ms_fatal("sal_op_get_auth_requested not implemented yet");
|
||||
return -1;
|
||||
}
|
||||
/*Call API*/
|
||||
int sal_call_set_local_media_description(SalOp *h, SalMediaDescription *desc){
|
||||
ms_fatal("sal_call_set_local_media_description not implemented yet");
|
||||
return -1;
|
||||
}
|
||||
int sal_call(SalOp *h, const char *from, const char *to){
|
||||
ms_fatal("sal_call not implemented yet");
|
||||
return -1;
|
||||
}
|
||||
int sal_call_notify_ringing(SalOp *h, bool_t early_media){
|
||||
ms_fatal("sal_call_notify_ringing not implemented yet");
|
||||
return -1;
|
||||
}
|
||||
/*accept an incoming call or, during a call accept a reINVITE*/
|
||||
int sal_call_accept(SalOp*h){
|
||||
ms_fatal("sal_call_accept not implemented yet");
|
||||
return -1;
|
||||
}
|
||||
int sal_call_decline(SalOp *h, SalReason reason, const char *redirection /*optional*/){
|
||||
ms_fatal("sal_call_decline not implemented yet");
|
||||
return -1;
|
||||
}
|
||||
int sal_call_update(SalOp *h, const char *subject){
|
||||
ms_fatal("sal_call_update not implemented yet");
|
||||
return -1;
|
||||
}
|
||||
SalMediaDescription * sal_call_get_remote_media_description(SalOp *h){
|
||||
ms_fatal("sal_call_get_remote_media_description not implemented yet");
|
||||
return NULL;
|
||||
}
|
||||
SalMediaDescription * sal_call_get_final_media_description(SalOp *h){
|
||||
ms_fatal("sal_call_get_final_media_description not implemented yet");
|
||||
return NULL;
|
||||
}
|
||||
int sal_call_refer(SalOp *h, const char *refer_to){
|
||||
ms_fatal("sal_call_refer not implemented yet");
|
||||
return -1;
|
||||
}
|
||||
int sal_call_refer_with_replaces(SalOp *h, SalOp *other_call_h){
|
||||
ms_fatal("sal_call_refer_with_replaces not implemented yet");
|
||||
return -1;
|
||||
}
|
||||
int sal_call_accept_refer(SalOp *h){
|
||||
ms_fatal("sal_call_accept_refer not implemented yet");
|
||||
return -1;
|
||||
}
|
||||
/*informs this call is consecutive to an incoming refer */
|
||||
int sal_call_set_referer(SalOp *h, SalOp *refered_call){
|
||||
ms_fatal("sal_call_set_referer not implemented yet");
|
||||
return -1;
|
||||
}
|
||||
/* returns the SalOp of a call that should be replaced by h, if any */
|
||||
SalOp *sal_call_get_replaces(SalOp *h){
|
||||
ms_fatal("sal_call_get_replaces not implemented yet");
|
||||
return NULL;
|
||||
}
|
||||
int sal_call_send_dtmf(SalOp *h, char dtmf){
|
||||
ms_fatal("sal_call_send_dtmf not implemented yet");
|
||||
return -1;
|
||||
}
|
||||
int sal_call_terminate(SalOp *h){
|
||||
ms_fatal("sal_call_terminate not implemented yet");
|
||||
return -1;
|
||||
}
|
||||
bool_t sal_call_autoanswer_asked(SalOp *op){
|
||||
ms_fatal("sal_call_autoanswer_asked not implemented yet");
|
||||
return -1;
|
||||
}
|
||||
void sal_call_send_vfu_request(SalOp *h){
|
||||
ms_fatal("sal_call_send_vfu_request not implemented yet");
|
||||
return ;
|
||||
}
|
||||
int sal_call_is_offerer(const SalOp *h){
|
||||
ms_fatal("sal_call_is_offerer not implemented yet");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/**************************REGISTRATION***************************///////////
|
||||
static void send_register_request(SalOp* op, belle_sip_request_t* request);
|
||||
|
||||
static void register_process_io_error(void *user_ctx, const belle_sip_io_error_event_t *event){
|
||||
ms_error("process_io_error not implemented yet");
|
||||
}
|
||||
|
||||
static void register_refresh(SalOp* op) {
|
||||
op->registration_refresh_timer=0;
|
||||
belle_sip_header_cseq_t* cseq=(belle_sip_header_cseq_t*)belle_sip_message_get_header(BELLE_SIP_MESSAGE(op->register_request),BELLE_SIP_CSEQ);
|
||||
belle_sip_header_cseq_set_seq_number(cseq,belle_sip_header_cseq_get_seq_number(cseq)+1);
|
||||
send_register_request(op,op->register_request);
|
||||
}
|
||||
static void register_response_event(void *user_ctx, const belle_sip_response_event_t *event){
|
||||
belle_sip_client_transaction_t* client_transaction = belle_sip_response_event_get_client_transaction(event);
|
||||
SalOp* op = (SalOp*)belle_sip_transaction_get_application_data(BELLE_SIP_TRANSACTION(client_transaction));
|
||||
belle_sip_response_t* response = belle_sip_response_event_get_response(event);
|
||||
belle_sip_header_expires_t* expires_header;
|
||||
belle_sip_request_t* old_register_request;
|
||||
int response_code = belle_sip_response_get_status_code(response);
|
||||
if (response_code<200) return;/*nothing to do*/
|
||||
switch (response_code) {
|
||||
case 200: {
|
||||
expires_header=(belle_sip_header_expires_t*)belle_sip_message_get_header(BELLE_SIP_MESSAGE(response),BELLE_SIP_EXPIRES);
|
||||
op->base.root->callbacks.register_success(op,expires_header&&belle_sip_header_expires_get_expires(expires_header)>0);
|
||||
old_register_request=op->register_request;
|
||||
op->register_request=belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(client_transaction));
|
||||
belle_sip_object_ref(op->register_request);
|
||||
if (old_register_request) belle_sip_object_unref(old_register_request);
|
||||
/*FIXME schedule refresh cb*/
|
||||
if (belle_sip_header_expires_get_expires(expires_header)>0) {
|
||||
if (op->registration_refresh_timer>0) {
|
||||
belle_sip_main_loop_cancel_source(belle_sip_stack_get_main_loop(op->base.root->stack),op->registration_refresh_timer);
|
||||
}
|
||||
op->registration_refresh_timer = belle_sip_main_loop_add_timeout(belle_sip_stack_get_main_loop(op->base.root->stack),(belle_sip_source_func_t)register_refresh,op,belle_sip_header_expires_get_expires(expires_header)*1000);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:{
|
||||
ms_error("Unexpected answer [%s] for registration request bound to [%s]",belle_sip_response_get_reason_phrase(response),op->base.from);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
static void register_process_timeout(void *user_ctx, const belle_sip_timeout_event_t *event) {
|
||||
ms_error("process_timeout not implemented yet");
|
||||
}
|
||||
static void register_process_transaction_terminated(void *user_ctx, const belle_sip_transaction_terminated_event_t *event) {
|
||||
ms_error("process_transaction_terminated not implemented yet");
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void send_register_request(SalOp* op, belle_sip_request_t* request) {
|
||||
belle_sip_client_transaction_t* client_transaction;
|
||||
belle_sip_provider_t* prov=op->base.root->prov;
|
||||
op->callbacks.process_io_error=register_process_io_error;
|
||||
op->callbacks.process_response_event=register_response_event;
|
||||
op->callbacks.process_timeout=register_process_timeout;
|
||||
op->callbacks.process_transaction_terminated=register_process_transaction_terminated;
|
||||
client_transaction = belle_sip_provider_create_client_transaction(prov,request);
|
||||
belle_sip_transaction_set_application_data(BELLE_SIP_TRANSACTION(client_transaction),op);
|
||||
belle_sip_client_transaction_send_request(client_transaction);
|
||||
|
||||
}
|
||||
static void send_register_request_with_expires(SalOp* op, belle_sip_request_t* request,int expires) {
|
||||
belle_sip_header_expires_t* expires_header=(belle_sip_header_expires_t*)belle_sip_message_get_header(BELLE_SIP_MESSAGE(request),BELLE_SIP_EXPIRES);
|
||||
|
||||
if (!expires_header) {
|
||||
belle_sip_message_add_header(BELLE_SIP_MESSAGE(request),BELLE_SIP_HEADER(expires_header=belle_sip_header_expires_new()));
|
||||
}
|
||||
belle_sip_header_expires_set_expires(expires_header,expires);
|
||||
send_register_request(op,request);
|
||||
}
|
||||
|
||||
int sal_register(SalOp *op, const char *proxy, const char *from, int expires){
|
||||
belle_sip_request_t *req;
|
||||
belle_sip_provider_t* prov=op->base.root->prov;
|
||||
belle_sip_header_contact_t* contact_header =belle_sip_header_contact_new();
|
||||
belle_sip_header_from_t* from_header;
|
||||
belle_sip_header_to_t* to_header;
|
||||
belle_sip_uri_t* req_uri;
|
||||
belle_sip_uri_t* contact_uri;
|
||||
|
||||
char token[10];
|
||||
if (expires<0) goto error;
|
||||
from_header = belle_sip_header_from_create(from,belle_sip_random_token(token,sizeof(token)));
|
||||
if (!from_header) goto error;
|
||||
to_header=belle_sip_header_to_create(from,NULL);
|
||||
req_uri = (belle_sip_uri_t*)belle_sip_object_clone((belle_sip_object_t*)belle_sip_header_address_get_uri((belle_sip_header_address_t*)to_header));
|
||||
belle_sip_uri_set_user(req_uri,NULL);
|
||||
|
||||
if (sal_op_get_contact(op))
|
||||
contact_uri= belle_sip_uri_parse(sal_op_get_contact(op));
|
||||
else
|
||||
contact_uri=belle_sip_uri_new();
|
||||
|
||||
if (!contact_uri) goto error;
|
||||
belle_sip_header_address_set_uri((belle_sip_header_address_t*)contact_header,contact_uri);
|
||||
sal_op_set_route(op,proxy);
|
||||
/*FIXME use route info if needed*/
|
||||
|
||||
|
||||
req=belle_sip_request_create(
|
||||
req_uri,
|
||||
"REGISTER",
|
||||
belle_sip_provider_create_call_id(prov),
|
||||
belle_sip_header_cseq_create(20,"REGISTER"),
|
||||
from_header,
|
||||
to_header,
|
||||
belle_sip_header_via_new(),
|
||||
70);
|
||||
|
||||
|
||||
belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(contact_header));
|
||||
send_register_request_with_expires(op,req,expires);
|
||||
|
||||
return 0;
|
||||
error:
|
||||
ms_error("Cannot initiate register to [%s] for [%s], expire [%i]",proxy,from,expires);
|
||||
if (contact_header) belle_sip_object_unref(contact_header);
|
||||
if (from_header) belle_sip_object_unref(from_header);
|
||||
if (to_header) belle_sip_object_unref(to_header);
|
||||
return -1;
|
||||
}
|
||||
int sal_register_refresh(SalOp *op, int expires){
|
||||
belle_sip_header_cseq_t* cseq=(belle_sip_header_cseq_t*)belle_sip_message_get_header(BELLE_SIP_MESSAGE(op->register_request),BELLE_SIP_CSEQ);
|
||||
belle_sip_header_cseq_set_seq_number(cseq,belle_sip_header_cseq_get_seq_number(cseq)+1);
|
||||
send_register_request_with_expires(op,op->register_request,expires);
|
||||
return 0;
|
||||
}
|
||||
int sal_unregister(SalOp *op){
|
||||
belle_sip_header_cseq_t* cseq=(belle_sip_header_cseq_t*)belle_sip_message_get_header(BELLE_SIP_MESSAGE(op->register_request),BELLE_SIP_CSEQ);
|
||||
belle_sip_header_cseq_set_seq_number(cseq,belle_sip_header_cseq_get_seq_number(cseq)+1);
|
||||
send_register_request_with_expires(op,op->register_request,0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*Messaging */
|
||||
int sal_text_send(SalOp *op, const char *from, const char *to, const char *text){
|
||||
ms_fatal("sal_text_send not implemented yet");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*presence Subscribe/notify*/
|
||||
int sal_subscribe_presence(SalOp *op, const char *from, const char *to){
|
||||
ms_fatal("sal_subscribe_presence not implemented yet");
|
||||
return -1;
|
||||
}
|
||||
int sal_unsubscribe(SalOp *op){
|
||||
ms_fatal("sal_unsubscribe not implemented yet");
|
||||
return -1;
|
||||
}
|
||||
int sal_subscribe_accept(SalOp *op){
|
||||
ms_fatal("sal_subscribe_accept not implemented yet");
|
||||
return -1;
|
||||
}
|
||||
int sal_subscribe_decline(SalOp *op){
|
||||
ms_fatal("sal_subscribe_decline not implemented yet");
|
||||
return -1;
|
||||
}
|
||||
int sal_notify_presence(SalOp *op, SalPresenceStatus status, const char *status_message){
|
||||
ms_fatal("sal_notify_presence not implemented yet");
|
||||
return -1;
|
||||
}
|
||||
int sal_notify_close(SalOp *op){
|
||||
ms_fatal("sal_notify_close not implemented yet");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*presence publish */
|
||||
int sal_publish(SalOp *op, const char *from, const char *to, SalPresenceStatus status){
|
||||
ms_fatal("sal_publish not implemented yet");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/*ping: main purpose is to obtain its own contact address behind firewalls*/
|
||||
int sal_ping(SalOp *op, const char *from, const char *to){
|
||||
ms_fatal("sal_ping not implemented yet");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#define payload_type_set_number(pt,n) (pt)->user_data=(void*)((long)n);
|
||||
#define payload_type_get_number(pt) ((int)(long)(pt)->user_data)
|
||||
|
||||
/*misc*/
|
||||
void sal_get_default_local_ip(Sal *sal, int address_family, char *ip, size_t iplen){
|
||||
ms_fatal("sal_get_default_local_ip not implemented yet");
|
||||
return ;
|
||||
}
|
||||
|
|
@ -19,8 +19,10 @@
|
|||
#include "CUnit/Basic.h"
|
||||
#include "linphonecore.h"
|
||||
|
||||
const char *test_domain="localhost";
|
||||
|
||||
const char *test_domain="sip.example.org";
|
||||
const char *auth_domain="auth.example.org";
|
||||
const char* test_username="liblinphone_tester";
|
||||
const char* test_password="secret";
|
||||
|
||||
static int init(void) {
|
||||
return 0;
|
||||
|
|
@ -36,20 +38,21 @@ static void core_init_test(void) {
|
|||
linphone_core_destroy(lc);
|
||||
}
|
||||
|
||||
static LinphoneAddress * create_linphone_address(void) {
|
||||
static LinphoneAddress * create_linphone_address(const char * domain) {
|
||||
LinphoneAddress *addr = linphone_address_new(NULL);
|
||||
CU_ASSERT_PTR_NOT_NULL_FATAL(addr);
|
||||
linphone_address_set_username(addr,"tester");
|
||||
CU_ASSERT_STRING_EQUAL("tester",linphone_address_get_username(addr));
|
||||
linphone_address_set_domain(addr,test_domain);
|
||||
CU_ASSERT_STRING_EQUAL(test_domain,linphone_address_get_domain(addr));
|
||||
linphone_address_set_username(addr,test_username);
|
||||
CU_ASSERT_STRING_EQUAL(test_username,linphone_address_get_username(addr));
|
||||
if (!domain) domain= test_domain;
|
||||
linphone_address_set_domain(addr,domain);
|
||||
CU_ASSERT_STRING_EQUAL(domain,linphone_address_get_domain(addr));
|
||||
linphone_address_set_display_name(addr, NULL);
|
||||
linphone_address_set_display_name(addr, "Mr Tester");
|
||||
CU_ASSERT_STRING_EQUAL("Mr Tester",linphone_address_get_display_name(addr));
|
||||
return addr;
|
||||
}
|
||||
static void linphone_address_test(void) {
|
||||
ms_free(create_linphone_address());
|
||||
ms_free(create_linphone_address(NULL));
|
||||
}
|
||||
|
||||
static int number_of_LinphoneRegistrationNone=0;
|
||||
|
|
@ -57,7 +60,16 @@ static int number_of_LinphoneRegistrationProgress =0;
|
|||
static int number_of_LinphoneRegistrationOk =0;
|
||||
static int number_of_LinphoneRegistrationCleared =0;
|
||||
static int number_of_LinphoneRegistrationFailed =0;
|
||||
static int number_of_auth_info_requested =0;
|
||||
|
||||
static void reset_counters() {
|
||||
number_of_LinphoneRegistrationNone=0;
|
||||
number_of_LinphoneRegistrationProgress =0;
|
||||
number_of_LinphoneRegistrationOk =0;
|
||||
number_of_LinphoneRegistrationCleared =0;
|
||||
number_of_LinphoneRegistrationFailed =0;
|
||||
number_of_auth_info_requested =0;
|
||||
}
|
||||
|
||||
static void registration_state_changed(struct _LinphoneCore *lc, LinphoneProxyConfig *cfg, LinphoneRegistrationState cstate, const char *message){
|
||||
ms_message("New registration state %s for user id [%s] at proxy [%s]\n"
|
||||
|
|
@ -76,26 +88,40 @@ static void registration_state_changed(struct _LinphoneCore *lc, LinphoneProxyCo
|
|||
|
||||
}
|
||||
|
||||
static void simple_register(void) {
|
||||
static void auth_info_requested(LinphoneCore *lc, const char *realm, const char *username) {
|
||||
ms_message("Auth info requested for user id [%s] at realm [%s]\n"
|
||||
,username
|
||||
,realm);
|
||||
number_of_auth_info_requested++;
|
||||
|
||||
}
|
||||
static LinphoneCore* create_lc() {
|
||||
LinphoneCoreVTable v_table;
|
||||
int retry=0;
|
||||
LCSipTransports transport = {5070,5070,0,5071};
|
||||
|
||||
memset (&v_table,0,sizeof(v_table));
|
||||
v_table.registration_state_changed=registration_state_changed;
|
||||
LinphoneCore* lc = linphone_core_new(&v_table,NULL,NULL,NULL);
|
||||
v_table.auth_info_requested=auth_info_requested;
|
||||
return linphone_core_new(&v_table,NULL,NULL,NULL);
|
||||
}
|
||||
static void register_with_refresh(LinphoneCore* lc, bool_t refresh,const char* domain,const char* route) {
|
||||
int retry=0;
|
||||
LCSipTransports transport = {5070,5070,0,5071};
|
||||
reset_counters();
|
||||
CU_ASSERT_PTR_NOT_NULL_FATAL(lc);
|
||||
|
||||
linphone_core_set_sip_transports(lc,&transport);
|
||||
LinphoneProxyConfig* proxy_cfg;
|
||||
|
||||
proxy_cfg = linphone_proxy_config_new();
|
||||
|
||||
LinphoneAddress *from = create_linphone_address();
|
||||
LinphoneAddress *from = create_linphone_address(domain);
|
||||
|
||||
linphone_proxy_config_set_identity(proxy_cfg,linphone_address_as_string(from));
|
||||
const char* server_addr = linphone_address_get_domain(from);
|
||||
linphone_proxy_config_set_server_addr(proxy_cfg,server_addr);
|
||||
linphone_proxy_config_enable_register(proxy_cfg,TRUE);
|
||||
linphone_proxy_config_expires(proxy_cfg,1);
|
||||
linphone_proxy_config_expires(proxy_cfg,30);
|
||||
if (route) linphone_proxy_config_set_route(proxy_cfg,route);
|
||||
linphone_address_destroy(from);
|
||||
|
||||
linphone_core_add_proxy_config(lc,proxy_cfg);
|
||||
|
|
@ -106,21 +132,43 @@ static void simple_register(void) {
|
|||
ms_usleep(100000);
|
||||
}
|
||||
CU_ASSERT_TRUE(linphone_proxy_config_is_registered(proxy_cfg));
|
||||
/*wait until refresh*/
|
||||
while (number_of_LinphoneRegistrationOk<2 && retry++ <20) {
|
||||
linphone_core_iterate(lc);
|
||||
ms_usleep(100000);
|
||||
if (refresh) {
|
||||
/*wait until refresh*/
|
||||
while (number_of_LinphoneRegistrationOk<2 && retry++ <310) {
|
||||
linphone_core_iterate(lc);
|
||||
ms_usleep(100000);
|
||||
}
|
||||
linphone_core_destroy(lc);
|
||||
CU_ASSERT_EQUAL(number_of_LinphoneRegistrationNone,0);
|
||||
CU_ASSERT_EQUAL(number_of_LinphoneRegistrationProgress,2);
|
||||
CU_ASSERT_EQUAL(number_of_LinphoneRegistrationOk,2);
|
||||
CU_ASSERT_EQUAL(number_of_LinphoneRegistrationCleared,1);
|
||||
CU_ASSERT_EQUAL(number_of_LinphoneRegistrationFailed,0);
|
||||
} else {
|
||||
linphone_core_destroy(lc);
|
||||
CU_ASSERT_EQUAL(number_of_LinphoneRegistrationNone,0);
|
||||
CU_ASSERT_EQUAL(number_of_LinphoneRegistrationProgress,1);
|
||||
CU_ASSERT_EQUAL(number_of_LinphoneRegistrationOk,1);
|
||||
CU_ASSERT_EQUAL(number_of_LinphoneRegistrationCleared,1);
|
||||
CU_ASSERT_EQUAL(number_of_LinphoneRegistrationFailed,0);
|
||||
}
|
||||
|
||||
linphone_core_destroy(lc);
|
||||
CU_ASSERT_EQUAL(number_of_LinphoneRegistrationNone,0);
|
||||
CU_ASSERT_EQUAL(number_of_LinphoneRegistrationProgress,2);
|
||||
CU_ASSERT_EQUAL(number_of_LinphoneRegistrationOk,2);
|
||||
CU_ASSERT_EQUAL(number_of_LinphoneRegistrationCleared,1);
|
||||
CU_ASSERT_EQUAL(number_of_LinphoneRegistrationFailed,0);
|
||||
|
||||
}
|
||||
|
||||
static void simple_register(){
|
||||
register_with_refresh(create_lc(),FALSE,NULL,NULL);
|
||||
CU_ASSERT_EQUAL(number_of_auth_info_requested,0);
|
||||
}
|
||||
static void simple_authenticated_register(){
|
||||
number_of_auth_info_requested=0;
|
||||
LinphoneCore* lc = create_lc();
|
||||
LinphoneAuthInfo *info=linphone_auth_info_new(test_username,NULL,test_password,NULL,auth_domain); /*create authentication structure from identity*/
|
||||
linphone_core_add_auth_info(lc,info); /*add authentication info to LinphoneCore*/
|
||||
|
||||
register_with_refresh(lc,FALSE,auth_domain,NULL);
|
||||
CU_ASSERT_EQUAL(number_of_auth_info_requested,1);
|
||||
}
|
||||
int init_test_suite () {
|
||||
|
||||
CU_pSuite pSuite = CU_add_suite("liblinphone init test suite", init, uninit);
|
||||
|
|
@ -134,6 +182,9 @@ CU_pSuite pSuite = CU_add_suite("liblinphone init test suite", init, uninit);
|
|||
if (NULL == CU_add_test(pSuite, "simple register tester", simple_register)) {
|
||||
return CU_get_error();
|
||||
}
|
||||
if (NULL == CU_add_test(pSuite, "simple register with digest auth tester", simple_authenticated_register)) {
|
||||
return CU_get_error();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
int main (int argc, char *argv[]) {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue