From 885d4a076dd290748214f49a80074e4ed29de2da Mon Sep 17 00:00:00 2001 From: Jehan Monnier Date: Fri, 11 May 2012 15:42:14 +0200 Subject: [PATCH] start incomming call implemention --- coreapi/Makefile.am | 2 + coreapi/bellesip_sal/sal_impl.c | 69 ++++- coreapi/bellesip_sal/sal_impl.h | 8 +- coreapi/bellesip_sal/sal_op_call.c | 170 +++++++++++ coreapi/bellesip_sal/sal_op_impl.c | 337 ++------------------- coreapi/bellesip_sal/sal_op_registration.c | 159 ++++++++++ coreapi/bellesip_sal/sal_sdp.c | 2 +- coreapi/sal.c | 22 +- coreapi/sal.h | 6 + tester/liblinphone_tester.c | 107 ++++++- tester/multi_account_lrc | 25 +- tester/userdb.conf | 3 + 12 files changed, 573 insertions(+), 337 deletions(-) create mode 100644 coreapi/bellesip_sal/sal_op_call.c create mode 100644 coreapi/bellesip_sal/sal_op_registration.c diff --git a/coreapi/Makefile.am b/coreapi/Makefile.am index 208ab3ff6..028db827c 100644 --- a/coreapi/Makefile.am +++ b/coreapi/Makefile.am @@ -43,6 +43,8 @@ if USE_BELLESIP liblinphone_la_SOURCES+= bellesip_sal/sal_address_impl.c \ bellesip_sal/sal_impl.c \ bellesip_sal/sal_op_impl.c \ + bellesip_sal/sal_op_call.c \ + bellesip_sal/sal_op_registration.c \ bellesip_sal/sal_sdp.c else liblinphone_la_SOURCES+= sal_eXosip2.c sal_eXosip2.h\ diff --git a/coreapi/bellesip_sal/sal_impl.c b/coreapi/bellesip_sal/sal_impl.c index 2dc887d53..0a0a1248c 100644 --- a/coreapi/bellesip_sal/sal_impl.c +++ b/coreapi/bellesip_sal/sal_impl.c @@ -24,6 +24,41 @@ void sal_enable_logs(){ void sal_disable_logs() { belle_sip_set_log_level(BELLE_SIP_LOG_ERROR); } +static void sal_add_pending_auth(Sal *sal, SalOp *op){ + sal->pending_auths=ms_list_append(sal->pending_auths,op); +} + + void sal_remove_pending_auth(Sal *sal, SalOp *op){ + sal->pending_auths=ms_list_remove(sal->pending_auths,op); +} + +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"); + } + +} static void process_dialog_terminated(void *user_ctx, const belle_sip_dialog_terminated_event_t *event){ ms_error("process_dialog_terminated not implemented yet"); } @@ -31,7 +66,9 @@ static void process_io_error(void *user_ctx, const belle_sip_io_error_event_t *e 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"); + belle_sip_server_transaction_t* server_transaction = belle_sip_request_event_get_server_transaction(event); + SalOp* op = (SalOp*)belle_sip_transaction_get_application_data(BELLE_SIP_TRANSACTION(server_transaction)); + ms_error("sal process_request_event not implemented yet"); } static void process_response_event(void *user_ctx, const belle_sip_response_event_t *event){ @@ -46,6 +83,9 @@ static void process_response_event(void *user_ctx, const belle_sip_response_even int rport; bool_t contact_updated=FALSE; char* new_contact; + belle_sip_request_t* old_request=NULL;; + belle_sip_response_t* old_response=NULL;; + int response_code = belle_sip_response_get_status_code(response); if (op->callbacks.process_response_event) { /*Fix contact if needed*/ @@ -76,6 +116,31 @@ static void process_response_event(void *user_ctx, const belle_sip_response_even belle_sip_object_unref(contact_address); } + } + /*update request/response + * maybe only the transaction should be kept*/ + old_request=op->request; + op->request=belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(client_transaction)); + belle_sip_object_ref(op->request); + if (old_request) belle_sip_object_unref(old_request); + + old_response=op->response; + op->response=response; /*kept for use at authorization time*/ + belle_sip_object_ref(op->response); + if (old_response) belle_sip_object_unref(old_response); + + /*handle authozation*/ + switch (response_code) { + case 200: { + sal_remove_pending_auth(op->base.root,op);/*just in case*/ + break; + } + case 401: + case 407:{ + + process_authentication(op,BELLE_SIP_MESSAGE(response)); + return; + } } op->callbacks.process_response_event(op,event); } else { @@ -221,7 +286,7 @@ unsigned int sal_get_keepalive_period(Sal *ctx){ return -1; } void sal_use_session_timers(Sal *ctx, int expires){ - ms_error("sal_use_session_timers not implemented yet"); + ctx->session_expires=expires; return ; } void sal_use_double_registrations(Sal *ctx, bool_t enabled){ diff --git a/coreapi/bellesip_sal/sal_impl.h b/coreapi/bellesip_sal/sal_impl.h index e322bd052..9fb6c73ba 100644 --- a/coreapi/bellesip_sal/sal_impl.h +++ b/coreapi/bellesip_sal/sal_impl.h @@ -30,20 +30,22 @@ struct Sal{ belle_sip_stack_t* stack; belle_sip_provider_t *prov; void *up; /*user pointer*/ + int session_expires; }; struct SalOp{ SalOpBase base; belle_sip_listener_callbacks_t callbacks; - belle_sip_request_t* register_request; - belle_sip_response_t* register_response; + belle_sip_request_t* request; + belle_sip_response_t* response; SalAuthInfo auth_info; unsigned long int registration_refresh_timer; + bool_t sdp_offering; }; belle_sdp_session_description_t * media_description_to_sdp(const SalMediaDescription *sal); int sdp_to_media_description(belle_sdp_session_description_t *sdp, SalMediaDescription *desc); - +belle_sip_request_t* sal_op_build_request(SalOp *op,const char* method); #endif /* SAL_IMPL_H_ */ diff --git a/coreapi/bellesip_sal/sal_op_call.c b/coreapi/bellesip_sal/sal_op_call.c new file mode 100644 index 000000000..543cdcd0c --- /dev/null +++ b/coreapi/bellesip_sal/sal_op_call.c @@ -0,0 +1,170 @@ +/* +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 call_process_io_error(void *user_ctx, const belle_sip_io_error_event_t *event){ + ms_error("process_io_error not implemented yet"); +} +static void call_response_event(void *user_ctx, const belle_sip_response_event_t *event){ + ms_error("response_event not implemented yet"); +} +static void call_process_timeout(void *user_ctx, const belle_sip_timeout_event_t *event) { + ms_error("process_timeout not implemented yet"); +} +static void call_process_transaction_terminated(void *user_ctx, const belle_sip_transaction_terminated_event_t *event) { + ms_error("process_transaction_terminated not implemented yet"); +} +static int set_sdp_from_desc(belle_sip_message_t *msg, const SalMediaDescription *desc){ + belle_sdp_session_description_t* session_desc=media_description_to_sdp(desc); + belle_sip_header_content_type_t* content_type ; + belle_sip_header_content_length_t* content_length; + int length; + char buff[1024]; + + if (session_desc) { + content_type = belle_sip_header_content_type_create("application","sdp"); + length = belle_sip_object_marshal(BELLE_SIP_OBJECT(session_desc),buff,0,sizeof(buff)); + if (length==sizeof(buff)) { + ms_error("Buffer too small or sdp too big"); + } + + content_length= belle_sip_header_content_length_create(length); + belle_sip_message_add_header(msg,BELLE_SIP_HEADER(content_type)); + belle_sip_message_add_header(msg,BELLE_SIP_HEADER(content_length)); + belle_sip_message_set_body(msg,buff,length); + return 0; + } else { + return -1; + } +} +/*Call API*/ +int sal_call_set_local_media_description(SalOp *op, SalMediaDescription *desc){ + if (desc) + sal_media_description_ref(desc); + if (op->base.local_media) + sal_media_description_unref(op->base.local_media); + op->base.local_media=desc; + return 0; +} +int sal_call(SalOp *op, const char *from, const char *to){ + belle_sip_request_t* req; + belle_sip_header_allow_t* header_allow; + belle_sip_client_transaction_t* client_transaction; + belle_sip_provider_t* prov=op->base.root->prov; + belle_sip_header_route_t* route_header; + + sal_op_set_from(op,from); + sal_op_set_to(op,to); + + req=sal_op_build_request(op,"INVITE"); + header_allow = belle_sip_header_allow_create("INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, NOTIFY, MESSAGE, SUBSCRIBE, INFO"); + belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(header_allow)); + + if (op->base.root->session_expires!=0){ + belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),belle_sip_header_create( "Session-expires", "200")); + belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),belle_sip_header_create( "Supported", "timer")); + } + if (op->base.local_media){ + op->sdp_offering=TRUE; + set_sdp_from_desc(BELLE_SIP_MESSAGE(req),op->base.local_media); + }else op->sdp_offering=FALSE; + + if (sal_op_get_route_address(op)) { + route_header = belle_sip_header_route_create(BELLE_SIP_HEADER_ADDRESS(sal_op_get_route_address(op))); + belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(route_header)); + } + + op->callbacks.process_io_error=call_process_io_error; + op->callbacks.process_response_event=call_response_event; + op->callbacks.process_timeout=call_process_timeout; + op->callbacks.process_transaction_terminated=call_process_transaction_terminated; + client_transaction = belle_sip_provider_create_client_transaction(prov,req); + belle_sip_transaction_set_application_data(BELLE_SIP_TRANSACTION(client_transaction),op); + belle_sip_client_transaction_send_request(client_transaction); + + return 0; +} +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){ + return h->sdp_offering; +} + + diff --git a/coreapi/bellesip_sal/sal_op_impl.c b/coreapi/bellesip_sal/sal_op_impl.c index 67a9ac098..cd5eeecc3 100644 --- a/coreapi/bellesip_sal/sal_op_impl.c +++ b/coreapi/bellesip_sal/sal_op_impl.c @@ -18,13 +18,6 @@ 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){ @@ -35,7 +28,7 @@ SalOp * sal_op_new(Sal *sal){ void sal_op_release(SalOp *op){ __sal_op_free(op); - if (op->register_request) belle_sip_object_unref(op->register_request); + if (op->request) belle_sip_object_unref(op->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); } @@ -55,28 +48,28 @@ void sal_op_authenticate(SalOp *op, const SalAuthInfo *info){ } else ha1=computed_ha1; } - if (!op->register_response) { + if (!op->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)); + authenticate = BELLE_SIP_HEADER_WWW_AUTHENTICATE(belle_sip_message_get_header(BELLE_SIP_MESSAGE(op->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)); + authenticate = BELLE_SIP_HEADER_WWW_AUTHENTICATE(belle_sip_message_get_header(BELLE_SIP_MESSAGE(op->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_uri(authorization,belle_sip_request_get_uri(op->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) + ,belle_sip_request_get_method(op->request) ,ha1)) { belle_sip_object_unref(authorization); goto error; } - belle_sip_message_set_header(BELLE_SIP_MESSAGE(op->register_request),BELLE_SIP_HEADER(authorization)); + belle_sip_message_set_header(BELLE_SIP_MESSAGE(op->request),BELLE_SIP_HEADER(authorization)); sal_register_refresh(op,-1); return; @@ -95,323 +88,41 @@ int sal_op_get_auth_requested(SalOp *op, const char **realm, const char **userna *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,expires*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); - belle_sip_header_route_t* route_header; - if (sal_op_get_route_address(op)) { - route_header = belle_sip_header_route_create(BELLE_SIP_HEADER_ADDRESS(sal_op_get_route_address(op))); - belle_sip_message_add_header(BELLE_SIP_MESSAGE(request),BELLE_SIP_HEADER(route_header)); - } - 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_request_t* sal_op_build_request(SalOp *op,const char* method) { belle_sip_header_from_t* from_header; - const char* from_user; belle_sip_header_to_t* to_header; + belle_sip_provider_t* prov=op->base.root->prov; + belle_sip_request_t *req; belle_sip_uri_t* req_uri; - belle_sip_uri_t* contact_uri; - sal_op_set_from(op,from); - sal_op_set_to(op,from); - belle_sip_uri_t* route_uri=NULL; - belle_sip_header_address_t* route_address; - + belle_sip_header_contact_t* contact_header; 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); + + from_header = belle_sip_header_from_create(BELLE_SIP_HEADER_ADDRESS(sal_op_get_from_address(op)) + ,belle_sip_random_token(token,sizeof(token))); + to_header = belle_sip_header_to_create(BELLE_SIP_HEADER_ADDRESS(sal_op_get_to_address(op)),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)); - from_user=belle_sip_uri_get_user(req_uri); /*save username for contact 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(); - belle_sip_uri_set_user(contact_uri,from_user); + if (sal_op_get_contact_address(op)) { + contact_header = belle_sip_header_contact_create(BELLE_SIP_HEADER_ADDRESS(sal_op_get_contact_address(op))); + } else { + contact_header= belle_sip_header_contact_new(); + belle_sip_header_address_set_uri((belle_sip_header_address_t*)contact_header,belle_sip_uri_new()); + belle_sip_uri_set_user(belle_sip_header_address_get_uri((belle_sip_header_address_t*)contact_header),belle_sip_uri_get_user(req_uri)); } - - 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*/ - if (proxy) { - route_uri=belle_sip_uri_parse(proxy); - } - req=belle_sip_request_create( req_uri, - "REGISTER", + method, belle_sip_provider_create_call_id(prov), - belle_sip_header_cseq_create(20,"REGISTER"), + belle_sip_header_cseq_create(20,method), from_header, to_header, belle_sip_header_via_new(), 70); - - belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(contact_header)); - - if (route_uri && !belle_sip_uri_equals(req_uri,route_uri)) { - belle_sip_uri_set_lr_param(route_uri,1); - route_address=belle_sip_header_address_new(); - belle_sip_header_address_set_uri(route_address,route_uri); - sal_op_set_route_address(op,(const SalAddress*)route_address); /*save route for subsequent register*/ - belle_sip_object_unref(route_address); - - } else if (route_uri){ - belle_sip_object_unref(route_uri); - route_uri=NULL; - } - 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); - if (route_uri) belle_sip_object_unref(route_uri); - return -1; + return req; } -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){ diff --git a/coreapi/bellesip_sal/sal_op_registration.c b/coreapi/bellesip_sal/sal_op_registration.c new file mode 100644 index 000000000..fb7257319 --- /dev/null +++ b/coreapi/bellesip_sal/sal_op_registration.c @@ -0,0 +1,159 @@ +/* +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 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->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->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; + + 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*/ + + + 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)); + } else { + 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,expires*1000); + } + + 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); + belle_sip_header_route_t* route_header; + if (sal_op_get_route_address(op)) { + route_header = belle_sip_header_route_create(BELLE_SIP_HEADER_ADDRESS(sal_op_get_route_address(op))); + belle_sip_message_add_header(BELLE_SIP_MESSAGE(request),BELLE_SIP_HEADER(route_header)); + } + 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; + + sal_op_set_from(op,from); + sal_op_set_to(op,from); + sal_op_set_route(op,proxy); + + req = sal_op_build_request(op,"REGISTER"); + belle_sip_uri_t* req_uri = belle_sip_request_get_uri(req); + belle_sip_uri_set_user(req_uri,NULL); /*remove userinfo if any*/ + + send_register_request_with_expires(op,req,expires); + return 0; +} + +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->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->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->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->request,0); + return 0; +} + + diff --git a/coreapi/bellesip_sal/sal_sdp.c b/coreapi/bellesip_sal/sal_sdp.c index 417ee58b7..7a2f918f1 100644 --- a/coreapi/bellesip_sal/sal_sdp.c +++ b/coreapi/bellesip_sal/sal_sdp.c @@ -73,7 +73,7 @@ belle_sdp_session_description_t * media_description_to_sdp(const SalMediaDescrip for (pt_it=desc->streams[i].payloads;pt_it!=NULL;pt_it=pt_it->next) { pt=(PayloadType*)pt_it->data; mime_param= belle_sdp_mime_parameter_create(pt->mime_type - , pt->type + , payload_type_get_number(pt) , pt->clock_rate ,desc->streams[i].type==SalAudio?1:-1); belle_sdp_mime_parameter_set_parameters(mime_param,pt->recv_fmtp); diff --git a/coreapi/sal.c b/coreapi/sal.c index afddc0e3a..77b2d5e6c 100644 --- a/coreapi/sal.c +++ b/coreapi/sal.c @@ -256,11 +256,20 @@ void sal_op_set_route_address(SalOp *op, const SalAddress *address){ ms_free(address_string); } void sal_op_set_from(SalOp *op, const char *from){ - assign_string(&((SalOpBase*)op)->from,from); + SET_PARAM(op,from); +} +void sal_op_set_from_address(SalOp *op, const SalAddress *from){ + char* address_string=sal_address_as_string(from); /*can probably be optimized*/ + sal_op_set_from(op,address_string); + ms_free(address_string); } - void sal_op_set_to(SalOp *op, const char *to){ - assign_string(&((SalOpBase*)op)->to,to); + SET_PARAM(op,to); +} +void sal_op_set_to_address(SalOp *op, const SalAddress *to){ + char* address_string=sal_address_as_string(to); /*can probably be optimized*/ + sal_op_set_to(op,address_string); + ms_free(address_string); } void sal_op_set_user_pointer(SalOp *op, void *up){ @@ -274,11 +283,17 @@ Sal *sal_op_get_sal(const SalOp *op){ const char *sal_op_get_from(const SalOp *op){ return ((SalOpBase*)op)->from; } +const SalAddress *sal_op_get_from_address(const SalOp *op){ + return ((SalOpBase*)op)->from_address; +} const char *sal_op_get_to(const SalOp *op){ return ((SalOpBase*)op)->to; } +const SalAddress *sal_op_get_to_address(const SalOp *op){ + return ((SalOpBase*)op)->to_address; +} const char *sal_op_get_contact(const SalOp *op){ return ((SalOpBase*)op)->contact; } @@ -392,4 +407,5 @@ const char* sal_stream_dir_to_string(SalStreamDir type) { case SalStreamInactive:return "inative"; default: return "unknown"; } + } diff --git a/coreapi/sal.h b/coreapi/sal.h index 6ca4deb32..32d5c514c 100644 --- a/coreapi/sal.h +++ b/coreapi/sal.h @@ -170,7 +170,9 @@ typedef struct SalOpBase{ char *contact; SalAddress* contact_address; char *from; + SalAddress* from_address; char *to; + SalAddress* to_address; char *origin; char *remote_ua; SalMediaDescription *local_media; @@ -315,14 +317,18 @@ 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_route_address(SalOp *op, const SalAddress* address); void sal_op_set_from(SalOp *op, const char *from); +void sal_op_set_from_address(SalOp *op, const SalAddress *from); void sal_op_set_to(SalOp *op, const char *to); +void sal_op_set_to_address(SalOp *op, const SalAddress *to); void sal_op_release(SalOp *h); void sal_op_authenticate(SalOp *h, const SalAuthInfo *info); void sal_op_cancel_authentication(SalOp *h); void sal_op_set_user_pointer(SalOp *h, void *up); int sal_op_get_auth_requested(SalOp *h, const char **realm, const char **username); const char *sal_op_get_from(const SalOp *op); +const SalAddress *sal_op_get_from_address(const SalOp *op); const char *sal_op_get_to(const SalOp *op); +const SalAddress *sal_op_get_to_address(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); diff --git a/tester/liblinphone_tester.c b/tester/liblinphone_tester.c index c86acbf65..1a4ec8d40 100644 --- a/tester/liblinphone_tester.c +++ b/tester/liblinphone_tester.c @@ -62,6 +62,26 @@ static int number_of_LinphoneRegistrationCleared =0; static int number_of_LinphoneRegistrationFailed =0; static int number_of_auth_info_requested =0; + +static int number_of_LinphoneCallIncomingReceived=0; +static int number_of_LinphoneCallOutgoingInit=0; +static int number_of_LinphoneCallOutgoingProgress=0; +static int number_of_LinphoneCallOutgoingRinging=0; +static int number_of_LinphoneCallOutgoingEarlyMedia=0; +static int number_of_LinphoneCallConnected=0; +static int number_of_LinphoneCallStreamsRunning=0; +static int number_of_LinphoneCallPausing=0; +static int number_of_LinphoneCallPaused=0; +static int number_of_LinphoneCallResuming=0; +static int number_of_LinphoneCallRefered=0; +static int number_of_LinphoneCallError=0; +static int number_of_LinphoneCallEnd=0; +static int number_of_LinphoneCallPausedByRemote=0; +static int number_of_LinphoneCallUpdatedByRemote=0; +static int number_of_LinphoneCallIncomingEarlyMedia=0; +static int number_of_LinphoneCallUpdated=0; +static int number_of_LinphoneCallReleased=0; + static void reset_counters() { number_of_LinphoneRegistrationNone=0; number_of_LinphoneRegistrationProgress =0; @@ -69,6 +89,24 @@ static void reset_counters() { number_of_LinphoneRegistrationCleared =0; number_of_LinphoneRegistrationFailed =0; number_of_auth_info_requested =0; + number_of_LinphoneCallIncomingReceived=0; + number_of_LinphoneCallOutgoingInit=0; + number_of_LinphoneCallOutgoingProgress=0; + number_of_LinphoneCallOutgoingRinging=0; + number_of_LinphoneCallOutgoingEarlyMedia=0; + number_of_LinphoneCallConnected=0; + number_of_LinphoneCallStreamsRunning=0; + number_of_LinphoneCallPausing=0; + number_of_LinphoneCallPaused=0; + number_of_LinphoneCallResuming=0; + number_of_LinphoneCallRefered=0; + number_of_LinphoneCallError=0; + number_of_LinphoneCallEnd=0; + number_of_LinphoneCallPausedByRemote=0; + number_of_LinphoneCallUpdatedByRemote=0; + number_of_LinphoneCallIncomingEarlyMedia=0; + number_of_LinphoneCallUpdated=0; + number_of_LinphoneCallReleased=0; } static void registration_state_changed(struct _LinphoneCore *lc, LinphoneProxyConfig *cfg, LinphoneRegistrationState cstate, const char *message){ @@ -202,14 +240,13 @@ static void authenticated_register_with_no_initial_credentials(){ } -static void multiple_proxy(){ - LinphoneCoreVTable v_table; +static LinphoneCore* configure_lc(LinphoneCoreVTable* v_table) { + LinphoneCore* lc; int retry=0; - memset (&v_table,0,sizeof(v_table)); + memset (v_table,0,sizeof(LinphoneCoreVTable)); reset_counters(); - v_table.registration_state_changed=registration_state_changed; - lc = linphone_core_new(&v_table,NULL,"./multi_account_lrc",NULL); + lc = linphone_core_new(v_table,NULL,"./multi_account_lrc",NULL); CU_ASSERT_EQUAL(ms_list_size(linphone_core_get_proxy_config_list(lc)),3); @@ -218,13 +255,68 @@ static void multiple_proxy(){ ms_usleep(100000); } CU_ASSERT_EQUAL(number_of_LinphoneRegistrationOk,3); + return lc; +} +static void multiple_proxy(){ + LinphoneCoreVTable v_table; + LinphoneCore* lc; + v_table.registration_state_changed=registration_state_changed; + lc=configure_lc(&v_table); linphone_core_destroy(lc); } +static void call_state_changed(LinphoneCore *lc, LinphoneCall *call, LinphoneCallState cstate, const char *msg){ + char* to=linphone_call_get_remote_address_as_string(call); + ms_message("call from [??] to [%s], new state is [%s]",to,linphone_call_state_to_string(cstate)); + ms_free(to); + switch (cstate) { + case LinphoneCallIncomingReceived:number_of_LinphoneCallIncomingReceived++;break; + case LinphoneCallOutgoingInit :number_of_LinphoneCallOutgoingInit++;break; + case LinphoneCallOutgoingProgress :number_of_LinphoneCallOutgoingProgress++;break; + case LinphoneCallOutgoingRinging :number_of_LinphoneCallOutgoingRinging++;break; + case LinphoneCallOutgoingEarlyMedia :number_of_LinphoneCallOutgoingEarlyMedia++;break; + case LinphoneCallConnected :number_of_LinphoneCallConnected++;break; + case LinphoneCallStreamsRunning :number_of_LinphoneCallStreamsRunning++;break; + case LinphoneCallPausing :number_of_LinphoneCallPausing++;break; + case LinphoneCallPaused :number_of_LinphoneCallPaused++;break; + case LinphoneCallResuming :number_of_LinphoneCallResuming++;break; + case LinphoneCallRefered :number_of_LinphoneCallRefered++;break; + case LinphoneCallError :number_of_LinphoneCallError++;break; + case LinphoneCallEnd :number_of_LinphoneCallEnd++;break; + case LinphoneCallPausedByRemote :number_of_LinphoneCallPausedByRemote++;break; + case LinphoneCallUpdatedByRemote :number_of_LinphoneCallUpdatedByRemote++;break; + case LinphoneCallIncomingEarlyMedia :number_of_LinphoneCallIncomingEarlyMedia++;break; + case LinphoneCallUpdated :number_of_LinphoneCallUpdated++;break; + case LinphoneCallReleased :number_of_LinphoneCallReleased++;break; + default: + CU_FAIL("unexpected event");break; + } +} +static void simple_call_declined() { + LinphoneCoreVTable v_table; + LinphoneCore* lc; + int retry=0; + v_table.registration_state_changed=registration_state_changed; + v_table.call_state_changed=call_state_changed; + lc=configure_lc(&v_table); + linphone_core_invite(lc,"marie"); + + while (number_of_LinphoneCallIncomingReceived<1 && retry++ <20) { + linphone_core_iterate(lc); + ms_usleep(100000); + } + CU_ASSERT_EQUAL(number_of_LinphoneCallIncomingReceived,1); + CU_ASSERT_TRUE(linphone_core_inc_invite_pending(lc)); + linphone_core_terminate_call(lc,linphone_core_get_current_call(lc)); + CU_ASSERT_EQUAL(number_of_LinphoneCallReleased,1); + linphone_core_destroy(lc); +} int init_test_suite () { CU_pSuite pSuite = CU_add_suite("liblinphone init test suite", init, uninit); - + if (NULL == CU_add_test(pSuite, "simple call declined", simple_call_declined)) { + return CU_get_error(); + } if (NULL == CU_add_test(pSuite, "linphone address tester", linphone_address_test)) { return CU_get_error(); } @@ -249,6 +341,9 @@ CU_pSuite pSuite = CU_add_suite("liblinphone init test suite", init, uninit); if (NULL == CU_add_test(pSuite, "multi account", multiple_proxy)) { return CU_get_error(); } + if (NULL == CU_add_test(pSuite, "simple call declined", simple_call_declined)) { + return CU_get_error(); + } return 0; } int main (int argc, char *argv[]) { diff --git a/tester/multi_account_lrc b/tester/multi_account_lrc index 5f1bf21a0..6f362c533 100644 --- a/tester/multi_account_lrc +++ b/tester/multi_account_lrc @@ -2,6 +2,7 @@ sip_port=5072 sip_tcp_port=5072 sip_tls_port=5073 +default_proxy=0 [auth_info_0] username=liblinphone_tester @@ -10,28 +11,34 @@ passwd=secret realm="auth.example.org" [auth_info_1] -username=liblinphone_tester -userid=liblinphone_tester +username=pauline +userid=pauline passwd=secret -realm="auth1.example.org" +realm="auth.example.org" [auth_info_2] username=liblinphone_tester userid=liblinphone_tester passwd=secret -realm="auth2.example.org" +realm="auth1.example.org" + +[auth_info_3] +username=marie +userid=marie +passwd=secret +realm="auth.example.org" [proxy_0] -reg_proxy=auth.example.org -reg_identity=sip:liblinphone_tester@auth.example.org +reg_proxy=auth.example.org;transport=tls +reg_identity=sip:pauline@auth.example.org reg_expires=3600 reg_sendregister=1 publish=0 dial_escape_plus=0 [proxy_1] -reg_proxy=auth.example.org -reg_identity=sip:liblinphone_tester@auth1.example.org +reg_proxy=auth.example.org;transport=tcp +reg_identity=sip:marie@auth.example.org reg_expires=3600 reg_sendregister=1 publish=0 @@ -39,7 +46,7 @@ dial_escape_plus=0 [proxy_2] reg_proxy=auth.example.org -reg_identity=sip:liblinphone_tester@auth2.example.org +reg_identity=sip:liblinphone_tester@auth1.example.org reg_expires=3600 reg_sendregister=1 publish=0 diff --git a/tester/userdb.conf b/tester/userdb.conf index 65e2b549d..14c510237 100644 --- a/tester/userdb.conf +++ b/tester/userdb.conf @@ -1,3 +1,6 @@ liblinphone_tester@auth.example.org secret liblinphone_tester@auth1.example.org secret liblinphone_tester@auth2.example.org secret + +pauline@auth.example.org secret +marie@auth.example.org secret