diff --git a/coreapi/Makefile.am b/coreapi/Makefile.am index e9da0bf57..1a5975a09 100644 --- a/coreapi/Makefile.am +++ b/coreapi/Makefile.am @@ -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 \ diff --git a/coreapi/bellesip_sal/sal_address_impl.c b/coreapi/bellesip_sal/sal_address_impl.c new file mode 100644 index 000000000..b1b610cf8 --- /dev/null +++ b/coreapi/bellesip_sal/sal_address_impl.c @@ -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)); +} + + diff --git a/coreapi/bellesip_sal/sal_impl.c b/coreapi/bellesip_sal/sal_impl.c new file mode 100644 index 000000000..2dc887d53 --- /dev/null +++ b/coreapi/bellesip_sal/sal_impl.c @@ -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 ; +} diff --git a/coreapi/bellesip_sal/sal_impl.h b/coreapi/bellesip_sal/sal_impl.h new file mode 100644 index 000000000..63b97b351 --- /dev/null +++ b/coreapi/bellesip_sal/sal_impl.h @@ -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_ */ diff --git a/coreapi/bellesip_sal/sal_op_impl.c b/coreapi/bellesip_sal/sal_op_impl.c new file mode 100644 index 000000000..6de7ea051 --- /dev/null +++ b/coreapi/bellesip_sal/sal_op_impl.c @@ -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; +} + + diff --git a/coreapi/callbacks.c b/coreapi/callbacks.c index 63bff23a9..7a12c9ea7 100644 --- a/coreapi/callbacks.c +++ b/coreapi/callbacks.c @@ -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 }; diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index 78cda3e86..03db6aeb2 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -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 diff --git a/coreapi/proxy.c b/coreapi/proxy.c index 49e0ec3cc..ea530e6b2 100644 --- a/coreapi/proxy.c +++ b/coreapi/proxy.c @@ -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); } } diff --git a/coreapi/sal.c b/coreapi/sal.c index 761fbbe5c..09bb6e02d 100644 --- a/coreapi/sal.c +++ b/coreapi/sal.c @@ -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){ diff --git a/coreapi/sal.h b/coreapi/sal.h index 39aeb1984..5b3883d89 100644 --- a/coreapi/sal.h +++ b/coreapi/sal.h @@ -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*/ diff --git a/coreapi/sal_bellesip.c b/coreapi/sal_bellesip.c deleted file mode 100644 index ebb074c39..000000000 --- a/coreapi/sal_bellesip.c +++ /dev/null @@ -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 ; -} diff --git a/tester/liblinphone_tester.c b/tester/liblinphone_tester.c index a6df5714b..f834aedfe 100644 --- a/tester/liblinphone_tester.c +++ b/tester/liblinphone_tester.c @@ -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[]) {