From e2d0579e6b632f189af49c470f85ab10183303e4 Mon Sep 17 00:00:00 2001 From: Jehan Monnier Date: Fri, 27 Jul 2012 18:24:08 +0200 Subject: [PATCH] First working version --- coreapi/bellesip_sal/sal_address_impl.c | 4 +- coreapi/bellesip_sal/sal_impl.c | 105 ++++--- coreapi/bellesip_sal/sal_impl.h | 18 ++ coreapi/bellesip_sal/sal_op_call.c | 323 +++++++++++++++++--- coreapi/bellesip_sal/sal_op_impl.c | 65 ++-- coreapi/bellesip_sal/sal_op_registration.c | 4 +- coreapi/callbacks.c | 11 +- coreapi/friend.c | 6 +- coreapi/sal.h | 2 +- tester/flexisip.conf | 18 +- tester/liblinphone_tester.c | 338 ++++++++++++++------- tester/marie_rc | 38 +++ tester/pauline_rc | 37 +++ tester/userdb.conf | 2 + 14 files changed, 711 insertions(+), 260 deletions(-) mode change 100644 => 100755 tester/flexisip.conf create mode 100644 tester/marie_rc create mode 100644 tester/pauline_rc diff --git a/coreapi/bellesip_sal/sal_address_impl.c b/coreapi/bellesip_sal/sal_address_impl.c index b1b610cf8..e2bb58daf 100644 --- a/coreapi/bellesip_sal/sal_address_impl.c +++ b/coreapi/bellesip_sal/sal_address_impl.c @@ -107,9 +107,7 @@ void sal_address_set_port_int(SalAddress *addr, int 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()); + belle_sip_parameters_clean(BELLE_SIP_PARAMETERS(header_addr)); return ; } char *sal_address_as_string(const SalAddress *addr){ diff --git a/coreapi/bellesip_sal/sal_impl.c b/coreapi/bellesip_sal/sal_impl.c index 5176669ee..110a1b04f 100644 --- a/coreapi/bellesip_sal/sal_impl.c +++ b/coreapi/bellesip_sal/sal_impl.c @@ -34,28 +34,14 @@ static void sal_add_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"); +void sal_process_authentication(SalOp *op, belle_sip_response_t *response) { + belle_sip_message_remove_header(BELLE_SIP_MESSAGE(op->request),BELLE_SIP_AUTHORIZATION); + belle_sip_message_remove_header(BELLE_SIP_MESSAGE(op->request),BELLE_SIP_PROXY_AUTHORIZATION); + if (belle_sip_provider_add_authorization(op->base.root->prov,op->request,response)) { + sal_op_resend_request(op,op->request); + }else { + ms_message("No auth info found for [%s]",sal_op_get_from(op)); + sal_add_pending_auth(op->base.root,op); } } @@ -66,7 +52,7 @@ 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 *sal, const belle_sip_request_event_t *event) { - SalOp* op; + SalOp* op=NULL; belle_sip_request_t* req = belle_sip_request_event_get_request(event); belle_sip_dialog_t* dialog=belle_sip_request_event_get_dialog(event); belle_sip_header_address_t* origin_address; @@ -78,9 +64,11 @@ static void process_request_event(void *sal, const belle_sip_request_event_t *ev op=(SalOp*)belle_sip_dialog_get_application_data(dialog); } else if (strcmp("INVITE",belle_sip_request_get_method(req))==0) { op=sal_op_new((Sal*)sal); + op->dir=SalOpDirIncoming; sal_op_call_fill_cbs(op); } else { ms_error("sal process_request_event not implemented yet for method [%s]",belle_sip_request_get_method(req)); + return; } if (!op->base.from_address) { @@ -120,7 +108,7 @@ static void process_response_event(void *user_ctx, const belle_sip_response_even 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_address_t* contact_address=NULL; belle_sip_header_via_t* via_header; belle_sip_uri_t* contact_uri; unsigned int contact_port; @@ -132,11 +120,31 @@ static void process_response_event(void *user_ctx, const belle_sip_response_even belle_sip_response_t* old_response=NULL;; int response_code = belle_sip_response_get_status_code(response); + if (!op->base.remote_ua) { + sal_op_set_remote_ua(op,BELLE_SIP_MESSAGE(response)); + } + 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 (!sal_op_get_contact(op)) { + /*hmm update contact from via*/ + contact_address=belle_sip_header_address_new(); + contact_uri=belle_sip_uri_create(NULL,belle_sip_header_via_get_host(via_header)); + belle_sip_header_address_set_uri(contact_address,contact_uri); + + if (strcasecmp(belle_sip_header_via_get_transport(via_header),"UDP")!=0) { + belle_sip_uri_set_transport_param(contact_uri,belle_sip_header_via_get_transport_lowercase(via_header)); + } + if (belle_sip_header_via_get_listening_port(via_header) + != belle_sip_listening_point_get_well_known_port(belle_sip_header_via_get_transport(via_header))) { + belle_sip_uri_set_port(contact_uri,belle_sip_header_via_get_listening_port(via_header) ); + } + contact_updated=TRUE; + } + 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))); @@ -152,16 +160,30 @@ static void process_response_event(void *user_ctx, const belle_sip_response_even 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); - } + /*try to fix transport if needed (very unlikely)*/ + if (strcasecmp(belle_sip_header_via_get_transport(via_header),"UDP")!=0) { + if (!belle_sip_uri_get_transport_param(contact_uri) + ||strcasecmp(belle_sip_uri_get_transport_param(contact_uri),belle_sip_header_via_get_transport(via_header))!=0) { + belle_sip_uri_set_transport_param(contact_uri,belle_sip_header_via_get_transport_lowercase(via_header)); + contact_updated=TRUE; + } + } else { + if (belle_sip_uri_get_transport_param(contact_uri)) { + contact_updated=TRUE; + belle_sip_uri_set_transport_param(contact_uri,NULL); + } + } + } } + 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); + } + if (contact_address)belle_sip_object_unref(contact_address); + /*update request/response * maybe only the transaction should be kept*/ old_request=op->request; @@ -182,8 +204,7 @@ static void process_response_event(void *user_ctx, const belle_sip_response_even } case 401: case 407:{ - - process_authentication(op,BELLE_SIP_MESSAGE(response)); + sal_process_authentication(op,response); return; } } @@ -211,7 +232,17 @@ static void process_transaction_terminated(void *user_ctx, const belle_sip_trans ms_error("Unhandled transaction terminated [%p]",event); } } - +static void process_auth_requested(void *sal, belle_sip_auth_event_t *auth_event) { + SalAuthInfo auth_info; + memset(&auth_info,0,sizeof(SalAuthInfo)); + auth_info.username=(char*)belle_sip_auth_event_get_username(auth_event); + auth_info.realm=(char*)belle_sip_auth_event_get_realm(auth_event); + ((Sal*)sal)->callbacks.auth_requested(sal,&auth_info); + belle_sip_auth_event_set_passwd(auth_event,(const char*)auth_info.password); + belle_sip_auth_event_set_ha1(auth_event,(const char*)auth_info.ha1); + belle_sip_auth_event_set_userid(auth_event,(const char*)auth_info.userid); + return; +} Sal * sal_init(){ char stack_string[64]; Sal * sal=ms_new0(Sal,1); @@ -228,6 +259,7 @@ Sal * sal_init(){ 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; + sal->listener_callbacks.process_auth_requested=process_auth_requested; belle_sip_provider_add_sip_listener(sal->prov,belle_sip_listener_create_from_callbacks(&sal->listener_callbacks,sal)); return sal; } @@ -351,8 +383,7 @@ void sal_reuse_authorization(Sal *ctx, bool_t enabled){ 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 ; + ctx->one_matching_codec=one_matching_codec; } void sal_use_rport(Sal *ctx, bool_t use_rports){ ms_error("sal_use_rport not implemented yet"); diff --git a/coreapi/bellesip_sal/sal_impl.h b/coreapi/bellesip_sal/sal_impl.h index 4369e687f..309e779ba 100644 --- a/coreapi/bellesip_sal/sal_impl.h +++ b/coreapi/bellesip_sal/sal_impl.h @@ -32,8 +32,19 @@ struct Sal{ belle_sip_header_user_agent_t* user_agent; void *up; /*user pointer*/ int session_expires; + bool_t one_matching_codec; }; +typedef enum SalOpSate { + SalOpStateEarly=0 + ,SalOpStateActive + ,SalOpStateTerminated +}SalOpSate_t; + +typedef enum SalOpDir { + SalOpDirIncoming=0 + ,SalOpDirOutgoing +}SalOpDir_t; struct SalOp{ SalOpBase base; @@ -48,6 +59,11 @@ struct SalOp{ belle_sip_header_address_t *replaces; belle_sip_header_address_t *referred_by; bool_t auto_answer_asked; + SalMediaDescription *result; + belle_sdp_session_description_t *sdp_answer; + bool_t supports_session_timers; + SalOpSate_t state; + SalOpDir_t dir; }; belle_sdp_session_description_t * media_description_to_sdp(const SalMediaDescription *sal); @@ -60,4 +76,6 @@ void sal_op_call_fill_cbs(SalOp*op); void sal_op_set_remote_ua(SalOp*op,belle_sip_message_t* message); void sal_op_send_request(SalOp* op, belle_sip_request_t* request); void sal_op_resend_request(SalOp* op, belle_sip_request_t* request); +void sal_process_authentication(SalOp *op, belle_sip_response_t *response); + #endif /* SAL_IMPL_H_ */ diff --git a/coreapi/bellesip_sal/sal_op_call.c b/coreapi/bellesip_sal/sal_op_call.c index a2050616b..d5a65b44c 100644 --- a/coreapi/bellesip_sal/sal_op_call.c +++ b/coreapi/bellesip_sal/sal_op_call.c @@ -17,12 +17,193 @@ 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" +#include "offeranswer.h" +static void sdp_process(SalOp *h){ + ms_message("Doing SDP offer/answer process of type %s",h->sdp_offering ? "outgoing" : "incoming"); + if (h->result){ + sal_media_description_unref(h->result); + } + h->result=sal_media_description_new(); + if (h->sdp_offering){ + offer_answer_initiate_outgoing(h->base.local_media,h->base.remote_media,h->result); + }else{ + int i; + if (h->sdp_answer){ + belle_sip_object_unref(h->sdp_answer); + } + offer_answer_initiate_incoming(h->base.local_media,h->base.remote_media,h->result,h->base.root->one_matching_codec); + h->sdp_answer=media_description_to_sdp(h->result); + /*once we have generated the SDP answer, we modify the result description for processing by the upper layer. + It should contains media parameters constraint from the remote offer, not our response*/ + strcpy(h->result->addr,h->base.remote_media->addr); + h->result->bandwidth=h->base.remote_media->bandwidth; + + for(i=0;iresult->nstreams;++i){ + if (h->result->streams[i].port>0){ + strcpy(h->result->streams[i].addr,h->base.remote_media->streams[i].addr); + h->result->streams[i].ptime=h->base.remote_media->streams[i].ptime; + h->result->streams[i].bandwidth=h->base.remote_media->streams[i].bandwidth; + h->result->streams[i].port=h->base.remote_media->streams[i].port; + + if (h->result->streams[i].proto == SalProtoRtpSavp) { + h->result->streams[i].crypto[0] = h->base.remote_media->streams[i].crypto[0]; + } + } + } + } + +} +static int set_sdp(belle_sip_message_t *msg,belle_sdp_session_description_t* session_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; + } +} +static int set_sdp_from_desc(belle_sip_message_t *msg, const SalMediaDescription *desc){ + return set_sdp(msg,media_description_to_sdp(desc)); + +} 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 handle_sdp_from_response(SalOp* op,belle_sip_response_t* response) { + belle_sdp_session_description_t* sdp; + if ((sdp=belle_sdp_session_description_create(BELLE_SIP_MESSAGE(response)))) { + op->base.remote_media=sal_media_description_new(); + sdp_to_media_description(sdp,op->base.remote_media); + if (op->base.local_media) sdp_process(op); + } +} +static void call_response_event(void *op_base, const belle_sip_response_event_t *event){ + SalOp* op = (SalOp*)op_base; + belle_sip_request_t* ack; + belle_sip_dialog_state_t dialog_state; + /*belle_sip_client_transaction_t* client_transaction = belle_sip_response_event_get_client_transaction(event);*/ + belle_sip_response_t* response=belle_sip_response_event_get_response(event); + int code = belle_sip_response_get_status_code(response); + char* reason; + SalError error=SalErrorUnknown; + SalReason sr=SalReasonUnknown; + belle_sip_header_t* reason_header = belle_sip_message_get_header(BELLE_SIP_MESSAGE(response),"Reason"); + reason=(char*)belle_sip_response_get_reason_phrase(response); + if (reason_header){ + reason = ms_strdup_printf("%s %s",reason,belle_sip_header_extension_get_value(BELLE_SIP_HEADER_EXTENSION(reason_header))); + } + if (code >=400) { + switch(code) { + case 400: + error=SalErrorUnknown; + break; + case 404: + error=SalErrorFailure; + sr=SalReasonNotFound; + break; + case 415: + error=SalErrorFailure; + sr=SalReasonMedia; + break; + case 422: + ms_error ("422 not implemented yet");; + break; + case 480: + error=SalErrorFailure; + sr=SalReasonTemporarilyUnavailable; + break; + case 486: + error=SalErrorFailure; + sr=SalReasonBusy; + break; + case 487: + break; + case 600: + error=SalErrorFailure; + sr=SalReasonDoNotDisturb; + break; + case 603: + error=SalErrorFailure; + sr=SalReasonDeclined; + break; + default: + if (code>0){ + error=SalErrorFailure; + sr=SalReasonUnknown; + }else error=SalErrorNoResponse; + /* no break */ + } + + op->base.root->callbacks.call_failure(op,error,sr,reason,code); + if (reason_header != NULL){ + ms_free(reason); + } + return; + } + /*else dialog*/ + + dialog_state=belle_sip_dialog_get_state(op->dialog); + switch(dialog_state) { + + case BELLE_SIP_DIALOG_NULL: { + ms_error("op [%p] receive an unexpected answer [%i]",op,code); + break; + } + case BELLE_SIP_DIALOG_EARLY: { + if (code >= 180) { + handle_sdp_from_response(op,response); + op->base.root->callbacks.call_ringing(op); + } else { + ms_error("op [%p] receive an unexpected answer [%i]",op,code); + } + break; + } + case BELLE_SIP_DIALOG_CONFIRMED: { + switch (op->state) { + case SalOpStateEarly: + handle_sdp_from_response(op,response); + ack=belle_sip_dialog_create_ack(op->dialog,belle_sip_dialog_get_local_seq_number(op->dialog)); + if (ack==NULL) { + ms_error("This call has been already terminated."); + + return ; + } + if (op->sdp_answer){ + set_sdp(BELLE_SIP_MESSAGE(response),op->sdp_answer); + op->sdp_answer=NULL; + } + belle_sip_dialog_send_ack(op->dialog,ack); + op->base.root->callbacks.call_accepted(op); + break; + case SalOpStateActive: + case SalOpStateTerminated: + default: + ms_error("op [%p] receive answer [%i] not implemented",op,code); + } + break; + } + case BELLE_SIP_DIALOG_TERMINATED: + default: { + ms_error("op [%p] receive answer [%i] not implemented",op,code); + } + /* no break */ + } + + } static void call_process_timeout(void *user_ctx, const belle_sip_timeout_event_t *event) { ms_error("process_timeout not implemented yet"); @@ -42,6 +223,7 @@ static void process_request_event(void *op_base, const belle_sip_request_event_t belle_sip_dialog_state_t dialog_state; belle_sdp_session_description_t* sdp; belle_sip_header_t* call_info; + belle_sip_response_t* resp; if (!op->dialog) { op->dialog=belle_sip_provider_create_dialog(op->base.root->prov,BELLE_SIP_TRANSACTION(op->pending_server_trans)); belle_sip_dialog_set_application_data(op->dialog,op); @@ -76,36 +258,41 @@ static void process_request_event(void *op_base, const belle_sip_request_event_t break; } + case BELLE_SIP_DIALOG_CONFIRMED: + /*great ACK received*/ + if (strcmp("ACK",belle_sip_request_get_method(req))==0) { + if (op->sdp_offering){ + if ((sdp=belle_sdp_session_description_create(BELLE_SIP_MESSAGE(req)))){ + if (op->base.remote_media) + sal_media_description_unref(op->base.remote_media); + op->base.remote_media=sal_media_description_new(); + sdp_to_media_description(sdp,op->base.remote_media); + sdp_process(op); + belle_sip_object_unref(sdp); + } + } + /*FIXME + if (op->reinvite){ + op->reinvite=FALSE; + }*/ + op->base.root->callbacks.call_ack(op); + } else if(strcmp("BYE",belle_sip_request_get_method(req))==0) { + op->base.root->callbacks.call_terminated(op,op->dir==SalOpDirIncoming?sal_op_get_from(op):sal_op_get_to(op)); + resp=belle_sip_response_create_from_request(belle_sip_request_event_get_request(event),200); + belle_sip_server_transaction_send_response(server_transaction,resp); + } else { + ms_error("unexpected method [%s] for dialog [%p]",belle_sip_request_get_method(req),op->dialog); + } + break; default: { ms_error("unexpected dialog state [%s]",belle_sip_dialog_state_to_string(dialog_state)); } + /* no break */ } } -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) @@ -121,7 +308,7 @@ int sal_call(SalOp *op, const char *from, const char *to){ belle_sip_client_transaction_t* client_transaction; belle_sip_provider_t* prov=op->base.root->prov; belle_sip_header_route_t* route_header; - + op->dir=SalOpDirOutgoing; sal_op_set_from(op,from); sal_op_set_to(op,to); @@ -157,14 +344,58 @@ void sal_op_call_fill_cbs(SalOp*op) { op->callbacks.process_transaction_terminated=call_process_transaction_terminated; op->callbacks.process_request_event=process_request_event; } -int sal_call_notify_ringing(SalOp *h, bool_t early_media){ - ms_fatal("sal_call_notify_ringing not implemented yet"); - return -1; +int sal_call_notify_ringing(SalOp *op, bool_t early_media){ + belle_sip_response_t* ringing_response; + + /*if early media send also 180 and 183 */ + if (early_media){ + ms_fatal("not implemented yet"); + }else{ + ringing_response = belle_sip_response_create_from_request(belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(op->pending_server_trans)),180); + belle_sip_server_transaction_send_response(op->pending_server_trans,ringing_response); + } + return 0; } + + /*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; + belle_sip_response_t *response; + belle_sip_header_address_t* contact= (belle_sip_header_address_t*)sal_op_get_contact_address(h); + belle_sip_header_contact_t* contact_header; + /* sends a 200 OK */ + response = belle_sip_response_create_from_request(belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(h->pending_server_trans)),200); + + if (response==NULL){ + ms_error("Fail to build answer for call"); + return -1; + } + if (h->base.root->session_expires!=0){ + if (h->supports_session_timers) { + belle_sip_message_add_header(BELLE_SIP_MESSAGE(response),belle_sip_header_create( "Supported", "timer")); + } + } + + if (contact && (contact_header=belle_sip_header_contact_create(contact))) { + belle_sip_message_add_header(BELLE_SIP_MESSAGE(response),BELLE_SIP_HEADER(contact_header)); + } + + if (h->base.local_media){ + /*this is the case where we received an invite without SDP*/ + if (h->sdp_offering) { + set_sdp_from_desc(BELLE_SIP_MESSAGE(response),h->base.local_media); + }else{ + if (h->sdp_answer==NULL) sdp_process(h); + if (h->sdp_answer){ + set_sdp(BELLE_SIP_MESSAGE(response),h->sdp_answer); + h->sdp_answer=NULL; + } + } + }else{ + ms_error("You are accepting a call but not defined any media capabilities !"); + } + belle_sip_server_transaction_send_response(h->pending_server_trans,response); + return 0; } int sal_call_decline(SalOp *op, SalReason reason, const char *redirection /*optional*/){ belle_sip_response_t* response; @@ -214,9 +445,13 @@ 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; + if (h->base.local_media && h->base.remote_media && !h->result){ + sdp_process(h); + } + return h->result; } int sal_call_refer(SalOp *h, const char *refer_to){ ms_fatal("sal_call_refer not implemented yet"); @@ -237,20 +472,32 @@ int sal_call_set_referer(SalOp *h, SalOp *refered_call){ } /* 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"); + if (h!=NULL && h->replaces!=NULL){ + 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; +int sal_call_terminate(SalOp *op){ + belle_sip_dialog_state_t dialog_state=belle_sip_dialog_get_state(op->dialog); + + switch(dialog_state) { + case BELLE_SIP_DIALOG_CONFIRMED: { + sal_op_send_request(op,belle_sip_dialog_create_request(op->dialog,"BYE")); + } + break; + default: { + ms_fatal("sal_call_terminate not implemented yet for dialog state [%s]",belle_sip_dialog_state_to_string(dialog_state)); + return -1; + } + } + return 0; } bool_t sal_call_autoanswer_asked(SalOp *op){ - ms_fatal("sal_call_autoanswer_asked not implemented yet"); - return -1; + return op->auto_answer_asked; } void sal_call_send_vfu_request(SalOp *h){ ms_fatal("sal_call_send_vfu_request not implemented yet"); diff --git a/coreapi/bellesip_sal/sal_op_impl.c b/coreapi/bellesip_sal/sal_op_impl.c index 1fad0188f..2de7d8388 100644 --- a/coreapi/bellesip_sal/sal_op_impl.c +++ b/coreapi/bellesip_sal/sal_op_impl.c @@ -35,47 +35,8 @@ void sal_op_release(SalOp *op){ 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->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->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->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->request)); - belle_sip_header_authorization_set_username(authorization,info->userid); - - if (belle_sip_auth_helper_fill_authorization(authorization - ,belle_sip_request_get_method(op->request) - ,ha1)) { - belle_sip_object_unref(authorization); - goto error; - } - belle_sip_message_set_header(BELLE_SIP_MESSAGE(op->request),BELLE_SIP_HEADER(authorization)); - sal_op_resend_request(op,op->request); - return; - -error: - ms_error("cannot generate authorization for [%s] at [%s]",info->userid,info->realm); - + /*for sure auth info will be accesible from the provider*/ + sal_process_authentication(op, NULL); return ; } @@ -174,7 +135,7 @@ int sal_ping(SalOp *op, const char *from, const char *to){ void sal_op_set_remote_ua(SalOp*op,belle_sip_message_t* message) { belle_sip_header_user_agent_t* user_agent=belle_sip_message_get_header_by_type(message,belle_sip_header_user_agent_t); char user_agent_string[256]; - if(belle_sip_header_user_agent_get_products_as_string(user_agent,user_agent_string,sizeof(user_agent_string))>0) { + if(user_agent && belle_sip_header_user_agent_get_products_as_string(user_agent,user_agent_string,sizeof(user_agent_string))>0) { op->base.remote_ua=ms_strdup(user_agent_string); } } @@ -188,12 +149,26 @@ void sal_op_send_request(SalOp* op, belle_sip_request_t* request) { belle_sip_client_transaction_t* client_transaction; belle_sip_provider_t* prov=op->base.root->prov; belle_sip_header_route_t* route_header; - 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 (!op->dialog || belle_sip_dialog_get_state(op->dialog)!=BELLE_SIP_DIALOG_CONFIRMED) { + /*don't put route header if dialog is in confirmed state*/ + 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)); + } } client_transaction = belle_sip_provider_create_client_transaction(prov,request); belle_sip_transaction_set_application_data(BELLE_SIP_TRANSACTION(client_transaction),op); + /*in case DIALOG is in state NULL create a new dialog*/ + if (op->dialog && belle_sip_dialog_get_state(op->dialog)==BELLE_SIP_DIALOG_NULL) { + belle_sip_dialog_delete(op->dialog); + op->dialog=belle_sip_provider_create_dialog(prov,BELLE_SIP_TRANSACTION(client_transaction)); + belle_sip_dialog_set_application_data(op->dialog,op); + } else + if (!belle_sip_message_get_header(BELLE_SIP_MESSAGE(request),BELLE_SIP_AUTHORIZATION) + && !belle_sip_message_get_header(BELLE_SIP_MESSAGE(request),BELLE_SIP_PROXY_AUTHORIZATION)) { + /*hmm just in case we already have authentication param in cache*/ + belle_sip_provider_add_authorization(op->base.root->prov,request,NULL); + } belle_sip_client_transaction_send_request(client_transaction); } diff --git a/coreapi/bellesip_sal/sal_op_registration.c b/coreapi/bellesip_sal/sal_op_registration.c index 20ec119a9..ae7a6e116 100644 --- a/coreapi/bellesip_sal/sal_op_registration.c +++ b/coreapi/bellesip_sal/sal_op_registration.c @@ -71,7 +71,7 @@ static void register_response_event(void *user_ctx, const belle_sip_response_eve expires=0; } - op->base.root->callbacks.register_success(op,expires_header&&expires>=0); + op->base.root->callbacks.register_success(op,expires>0); /*always cancel pending refresh if any*/ 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); @@ -106,8 +106,8 @@ static void send_register_request_with_expires(SalOp* op, belle_sip_request_t* r if (!expires_header && expires>=0) { 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); } + if (expires_header) belle_sip_header_expires_set_expires(expires_header,expires); sal_op_send_request(op,request); } diff --git a/coreapi/callbacks.c b/coreapi/callbacks.c index 9ce4e1162..46975e732 100644 --- a/coreapi/callbacks.c +++ b/coreapi/callbacks.c @@ -795,8 +795,7 @@ static void ping_reply(SalOp *op){ } } -static bool_t fill_auth_info(SalOp*op, SalAuthInfo* sai) { - LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op)); +static bool_t fill_auth_info(LinphoneCore *lc, SalAuthInfo* sai) { LinphoneAuthInfo *ai=(LinphoneAuthInfo*)linphone_core_find_auth_info(lc,sai->realm,sai->username); if (ai) { sai->userid=ai->userid?ai->userid:ai->username; @@ -808,14 +807,14 @@ static bool_t fill_auth_info(SalOp*op, SalAuthInfo* sai) { return FALSE; } } -static bool_t auth_requested(SalOp*op, SalAuthInfo* sai) { - LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op)); - if (fill_auth_info(op,sai)) { +static bool_t auth_requested(Sal* sal, SalAuthInfo* sai) { + LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal); + if (fill_auth_info(lc,sai)) { return TRUE; } else { if (lc->vtable.auth_info_requested) { lc->vtable.auth_info_requested(lc,sai->realm,sai->username); - if (fill_auth_info(op,sai)) { + if (fill_auth_info(lc,sai)) { return TRUE; } } diff --git a/coreapi/friend.c b/coreapi/friend.c index 05a1baeec..d71dd25c6 100644 --- a/coreapi/friend.c +++ b/coreapi/friend.c @@ -198,8 +198,10 @@ void linphone_core_interpret_friend_uri(LinphoneCore *lc, const char *uri, char }else{ ms_warning("Fail to interpret friend uri %s",uri); } - }else *result=linphone_address_as_string(fr); - linphone_address_destroy(fr); + }else { + *result=linphone_address_as_string(fr); + linphone_address_destroy(fr); + } } int linphone_friend_set_addr(LinphoneFriend *lf, const LinphoneAddress *addr){ diff --git a/coreapi/sal.h b/coreapi/sal.h index 941b23516..543d7e9f2 100644 --- a/coreapi/sal.h +++ b/coreapi/sal.h @@ -236,7 +236,7 @@ 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 (*SalOnAuthRequestedLegacy)(SalOp *op, const char *realm, const char *username); -typedef bool_t (*SalOnAuthRequested)(SalOp *salop,SalAuthInfo* info); +typedef bool_t (*SalOnAuthRequested)(Sal *sal,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); diff --git a/tester/flexisip.conf b/tester/flexisip.conf old mode 100644 new mode 100755 index ffd6acf5f..5c1ee3ece --- a/tester/flexisip.conf +++ b/tester/flexisip.conf @@ -17,12 +17,12 @@ aliases=auth.example.org auth1.example.org auth2.example.org sip.example.org # The public ip address of the proxy. # Default value: guess -ip-address=guess +ip-address=auth.example.org # The local interface's ip address where to listen. The wildcard # (*) means all interfaces. # Default value: * -bind-address=sip.example.org +bind-address=auth.example.org # UDP/TCP port number to listen for sip messages. # Default value: 5060 @@ -45,7 +45,8 @@ port=5061 # The private key for TLS server must be in a agent.pem file within # this directory # Default value: /etc/flexisip/tls -certificates-dir=/Users/jehanmonnier/workspaces/workspace-macosx/flexisip +#certificates-dir=/Users/jehanmonnier/workspaces/workspace-macosx/flexisip +certificates-dir=/media/sf_workspaces/workspace-macosx/flexisip ## @@ -249,7 +250,7 @@ routes= [module::MediaRelay] # Indicate whether the module is activated. # Default value: true -enabled=false +enabled=true # List of domain names in sip from allowed to enter the module. # Default value: * @@ -279,15 +280,15 @@ to-domains=* [module::Transcoder] # Indicate whether the module is activated. # Default value: false -enabled=true +enabled=false # List of domain names in sip from allowed to enter the module. # Default value: * -from-domains=freephonie.net +from-domains=* # List of domain names in sip to allowed to enter the module. # Default value: * -to-domains=freephonie.net +to-domains=* # Nominal size of RTP jitter buffer, in milliseconds. A value of # 0 means no jitter buffer (packet processing). @@ -330,4 +331,5 @@ to-domains=* # Default value: false rewrite-req-uri=false - +[dos-protection] +enabled=false diff --git a/tester/liblinphone_tester.c b/tester/liblinphone_tester.c index 4f6ae1b16..4745dc4f0 100644 --- a/tester/liblinphone_tester.c +++ b/tester/liblinphone_tester.c @@ -55,58 +55,38 @@ static void linphone_address_test(void) { ms_free(create_linphone_address(NULL)); } -static int number_of_LinphoneRegistrationNone=0; -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; +typedef struct _stats { + int number_of_LinphoneRegistrationNone; + int number_of_LinphoneRegistrationProgress ; + int number_of_LinphoneRegistrationOk ; + int number_of_LinphoneRegistrationCleared ; + int number_of_LinphoneRegistrationFailed ; + int number_of_auth_info_requested ; -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; + int number_of_LinphoneCallIncomingReceived; + int number_of_LinphoneCallOutgoingInit; + int number_of_LinphoneCallOutgoingProgress; + int number_of_LinphoneCallOutgoingRinging; + int number_of_LinphoneCallOutgoingEarlyMedia; + int number_of_LinphoneCallConnected; + int number_of_LinphoneCallStreamsRunning; + int number_of_LinphoneCallPausing; + int number_of_LinphoneCallPaused; + int number_of_LinphoneCallResuming; + int number_of_LinphoneCallRefered; + int number_of_LinphoneCallError; + int number_of_LinphoneCallEnd; + int number_of_LinphoneCallPausedByRemote; + int number_of_LinphoneCallUpdatedByRemote; + int number_of_LinphoneCallIncomingEarlyMedia; + int number_of_LinphoneCallUpdated; + int number_of_LinphoneCallReleased; +}stats; +static stats global_stat; -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; - 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 reset_counters( stats* counters) { + memset(counters,0,sizeof(stats)); } static void registration_state_changed(struct _LinphoneCore *lc, LinphoneProxyConfig *cfg, LinphoneRegistrationState cstate, const char *message){ @@ -114,12 +94,13 @@ static void registration_state_changed(struct _LinphoneCore *lc, LinphoneProxyCo ,linphone_registration_state_to_string(cstate) ,linphone_proxy_config_get_identity(cfg) ,linphone_proxy_config_get_addr(cfg)); + stats* counters = (stats*)linphone_core_get_user_data(lc); switch (cstate) { - case LinphoneRegistrationNone:number_of_LinphoneRegistrationNone++;break; - case LinphoneRegistrationProgress:number_of_LinphoneRegistrationProgress++;break; - case LinphoneRegistrationOk:number_of_LinphoneRegistrationOk++;break; - case LinphoneRegistrationCleared:number_of_LinphoneRegistrationCleared++;break; - case LinphoneRegistrationFailed:number_of_LinphoneRegistrationFailed++;break; + case LinphoneRegistrationNone:counters->number_of_LinphoneRegistrationNone++;break; + case LinphoneRegistrationProgress:counters->number_of_LinphoneRegistrationProgress++;break; + case LinphoneRegistrationOk:counters->number_of_LinphoneRegistrationOk++;break; + case LinphoneRegistrationCleared:counters->number_of_LinphoneRegistrationCleared++;break; + case LinphoneRegistrationFailed:counters->number_of_LinphoneRegistrationFailed++;break; default: CU_FAIL("unexpected event");break; } @@ -129,17 +110,21 @@ static void registration_state_changed(struct _LinphoneCore *lc, LinphoneProxyCo static LinphoneCore* create_lc() { LinphoneCoreVTable v_table; - + LinphoneCore* lc; memset (&v_table,0,sizeof(v_table)); v_table.registration_state_changed=registration_state_changed; - return linphone_core_new(&v_table,NULL,NULL,NULL); + lc = linphone_core_new(&v_table,NULL,NULL,NULL); + linphone_core_set_user_data(lc,&global_stat); + return lc; } + 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); + CU_ASSERT_PTR_NOT_NULL_FATAL(lc); + stats* counters = (stats*)linphone_core_get_user_data(lc); + reset_counters(counters); linphone_core_set_sip_transports(lc,&transport); LinphoneProxyConfig* proxy_cfg; @@ -163,100 +148,111 @@ static void register_with_refresh(LinphoneCore* lc, bool_t refresh,const char* d linphone_core_add_proxy_config(lc,proxy_cfg); linphone_core_set_default_proxy(lc,proxy_cfg); - while (number_of_LinphoneRegistrationOk<1 && retry++ <20) { + while (counters->number_of_LinphoneRegistrationOk<1 && retry++ <20) { linphone_core_iterate(lc); ms_usleep(100000); } CU_ASSERT_TRUE(linphone_proxy_config_is_registered(proxy_cfg)); if (refresh) { /*wait until refresh*/ - while (number_of_LinphoneRegistrationOk<2 && retry++ <310) { + while (counters->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); + CU_ASSERT_EQUAL(counters->number_of_LinphoneRegistrationNone,0); + CU_ASSERT_EQUAL(counters->number_of_LinphoneRegistrationProgress,2); + CU_ASSERT_EQUAL(counters->number_of_LinphoneRegistrationOk,2); + CU_ASSERT_EQUAL(counters->number_of_LinphoneRegistrationCleared,1); + CU_ASSERT_EQUAL(counters->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); + CU_ASSERT_EQUAL(counters->number_of_LinphoneRegistrationNone,0); + CU_ASSERT_EQUAL(counters->number_of_LinphoneRegistrationProgress,1); + CU_ASSERT_EQUAL(counters->number_of_LinphoneRegistrationOk,1); + CU_ASSERT_EQUAL(counters->number_of_LinphoneRegistrationCleared,1); + CU_ASSERT_EQUAL(counters->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); + LinphoneCore* lc = create_lc(); + stats* counters = (stats*)linphone_core_get_user_data(lc); + register_with_refresh(lc,FALSE,NULL,NULL); + CU_ASSERT_EQUAL(counters->number_of_auth_info_requested,0); } static void simple_tcp_register(){ char route[256]; sprintf(route,"sip:%s;transport=tcp",test_domain); - register_with_refresh(create_lc(),FALSE,NULL,route); + LinphoneCore* lc = create_lc(); + register_with_refresh(lc,FALSE,NULL,route); } static void simple_tls_register(){ char route[256]; sprintf(route,"sip:%s;transport=tls",test_domain); - register_with_refresh(create_lc(),FALSE,NULL,route); + LinphoneCore* lc = create_lc(); + register_with_refresh(lc,FALSE,NULL,route); } static void simple_authenticated_register(){ 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*/ - + stats* counters = (stats*)linphone_core_get_user_data(lc); register_with_refresh(lc,FALSE,auth_domain,NULL); - CU_ASSERT_EQUAL(number_of_auth_info_requested,0); + CU_ASSERT_EQUAL(counters->number_of_auth_info_requested,0); } 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++; + stats* counters = (stats*)linphone_core_get_user_data(lc); + counters->number_of_auth_info_requested++; 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*/ } static void authenticated_register_with_no_initial_credentials(){ - number_of_auth_info_requested=0; LinphoneCoreVTable v_table; LinphoneCore* lc; memset (&v_table,0,sizeof(v_table)); v_table.registration_state_changed=registration_state_changed; v_table.auth_info_requested=auth_info_requested; lc = linphone_core_new(&v_table,NULL,NULL,NULL); - + linphone_core_set_user_data(lc,&global_stat); + stats* counters = (stats*)linphone_core_get_user_data(lc); + counters->number_of_auth_info_requested=0; register_with_refresh(lc,FALSE,auth_domain,NULL); - CU_ASSERT_EQUAL(number_of_auth_info_requested,1); + CU_ASSERT_EQUAL(counters->number_of_auth_info_requested,1); } -static LinphoneCore* configure_lc(LinphoneCoreVTable* v_table) { - +static LinphoneCore* configure_lc_from(LinphoneCoreVTable* v_table, const char* file,int proxy_count) { LinphoneCore* lc; int retry=0; + lc = linphone_core_new(v_table,NULL,file,NULL); + linphone_core_set_user_data(lc,&global_stat); + stats* counters = (stats*)linphone_core_get_user_data(lc); + linphone_core_set_ring(lc,"./share/rings/oldphone.wav"); + linphone_core_set_ringback(lc,"./share/ringback.wav"); - reset_counters(); - lc = linphone_core_new(v_table,NULL,"./multi_account_lrc",NULL); + reset_counters(counters); + CU_ASSERT_EQUAL(ms_list_size(linphone_core_get_proxy_config_list(lc)),proxy_count); - CU_ASSERT_EQUAL(ms_list_size(linphone_core_get_proxy_config_list(lc)),3); - - while (number_of_LinphoneRegistrationOk<3 && retry++ <20) { + while (counters->number_of_LinphoneRegistrationOk<3 && retry++ <20) { linphone_core_iterate(lc); ms_usleep(100000); } - CU_ASSERT_EQUAL(number_of_LinphoneRegistrationOk,3); + CU_ASSERT_EQUAL(counters->number_of_LinphoneRegistrationOk,proxy_count); return lc; } +static LinphoneCore* configure_lc(LinphoneCoreVTable* v_table) { + return configure_lc_from(v_table,"./tester/multi_account_lrc",3); +} static void multiple_proxy(){ LinphoneCoreVTable v_table; LinphoneCore* lc; @@ -266,28 +262,32 @@ static void multiple_proxy(){ 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)); + char* to=linphone_address_as_string(linphone_call_get_call_log(call)->to); + char* from=linphone_address_as_string(linphone_call_get_call_log(call)->from); + + ms_message("call from [%s] to [%s], new state is [%s]",from,to,linphone_call_state_to_string(cstate)); ms_free(to); + ms_free(from); + stats* counters = (stats*)linphone_core_get_user_data(lc); 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; + case LinphoneCallIncomingReceived:counters->number_of_LinphoneCallIncomingReceived++;break; + case LinphoneCallOutgoingInit :counters->number_of_LinphoneCallOutgoingInit++;break; + case LinphoneCallOutgoingProgress :counters->number_of_LinphoneCallOutgoingProgress++;break; + case LinphoneCallOutgoingRinging :counters->number_of_LinphoneCallOutgoingRinging++;break; + case LinphoneCallOutgoingEarlyMedia :counters->number_of_LinphoneCallOutgoingEarlyMedia++;break; + case LinphoneCallConnected :counters->number_of_LinphoneCallConnected++;break; + case LinphoneCallStreamsRunning :counters->number_of_LinphoneCallStreamsRunning++;break; + case LinphoneCallPausing :counters->number_of_LinphoneCallPausing++;break; + case LinphoneCallPaused :counters->number_of_LinphoneCallPaused++;break; + case LinphoneCallResuming :counters->number_of_LinphoneCallResuming++;break; + case LinphoneCallRefered :counters->number_of_LinphoneCallRefered++;break; + case LinphoneCallError :counters->number_of_LinphoneCallError++;break; + case LinphoneCallEnd :counters->number_of_LinphoneCallEnd++;break; + case LinphoneCallPausedByRemote :counters->number_of_LinphoneCallPausedByRemote++;break; + case LinphoneCallUpdatedByRemote :counters->number_of_LinphoneCallUpdatedByRemote++;break; + case LinphoneCallIncomingEarlyMedia :counters->number_of_LinphoneCallIncomingEarlyMedia++;break; + case LinphoneCallUpdated :counters->number_of_LinphoneCallUpdated++;break; + case LinphoneCallReleased :counters->number_of_LinphoneCallReleased++;break; default: CU_FAIL("unexpected event");break; } @@ -301,25 +301,100 @@ static void simple_call_declined() { v_table.registration_state_changed=registration_state_changed; v_table.call_state_changed=call_state_changed; lc=configure_lc(&v_table); + stats* counters = (stats*)linphone_core_get_user_data(lc); linphone_core_invite(lc,"marie"); - while (number_of_LinphoneCallIncomingReceived<1 && retry++ <20) { + while (counters->number_of_LinphoneCallIncomingReceived<1 && retry++ <20) { linphone_core_iterate(lc); ms_usleep(100000); } - CU_ASSERT_EQUAL(number_of_LinphoneCallIncomingReceived,1); + CU_ASSERT_EQUAL(counters->number_of_LinphoneCallIncomingReceived,1); CU_ASSERT_TRUE(linphone_core_inc_invite_pending(lc)); - linphone_core_terminate_call(lc,linphone_core_get_current_call(lc)); - CU_ASSERT_EQUAL(number_of_LinphoneCallReleased,1); + /*linphone_core_terminate_call(lc,linphone_core_get_current_call(lc));*/ + CU_ASSERT_EQUAL(counters->number_of_LinphoneCallReleased,1); linphone_core_destroy(lc); } +static bool_t wait_for(LinphoneCore* lc_1, LinphoneCore* lc_2,int* counter,int value) { + int retry=0; + while (*counternext) { + linphone_core_enable_payload_type(lc,(PayloadType*)codecs_it->data,0); + } + PayloadType* pt; + if((pt = linphone_core_find_payload_type(lc,type,rate))) { + linphone_core_enable_payload_type(lc,pt, 1); + } +} +static void simple_call() { + LinphoneCoreVTable v_table_marie; + LinphoneCore* lc_marie; + LinphoneCoreVTable v_table_pauline; + LinphoneCore* lc_pauline; + stats stat_marie; + stats stat_pauline; + reset_counters(&stat_marie); + reset_counters(&stat_pauline); + + + + memset (&v_table_marie,0,sizeof(LinphoneCoreVTable)); + v_table_marie.registration_state_changed=registration_state_changed; + v_table_marie.call_state_changed=call_state_changed; + + lc_marie=configure_lc_from(&v_table_marie,"./tester/marie_rc",1); + enable_codec(lc_marie,"PCMU",8000); + linphone_core_set_user_data(lc_marie,&stat_marie); + + memset (&v_table_pauline,0,sizeof(LinphoneCoreVTable)); + v_table_pauline.registration_state_changed=registration_state_changed; + v_table_pauline.call_state_changed=call_state_changed; + + lc_pauline=configure_lc_from(&v_table_pauline,"./tester/pauline_rc",1); + linphone_core_set_user_data(lc_pauline,&stat_pauline); + + linphone_core_invite(lc_marie,"pauline"); + + CU_ASSERT_TRUE_FATAL(wait_for(lc_pauline,lc_marie,&stat_pauline.number_of_LinphoneCallIncomingReceived,1)); + CU_ASSERT_TRUE(linphone_core_inc_invite_pending(lc_pauline)); + CU_ASSERT_EQUAL(stat_marie.number_of_LinphoneCallOutgoingProgress,1); + CU_ASSERT_TRUE_FATAL(wait_for(lc_pauline,lc_marie,&stat_marie.number_of_LinphoneCallOutgoingRinging,1)); + + LinphoneProxyConfig* proxy; + linphone_core_get_default_proxy(lc_marie,&proxy); + CU_ASSERT_PTR_NOT_NULL_FATAL(proxy); + + CU_ASSERT_STRING_EQUAL(linphone_proxy_config_get_identity(proxy),linphone_core_get_current_call_remote_address(lc_pauline)) + + linphone_core_accept_call(lc_pauline,linphone_core_get_current_call(lc_pauline)); + + CU_ASSERT_TRUE_FATAL(wait_for(lc_pauline,lc_marie,&stat_pauline.number_of_LinphoneCallConnected,1)); + CU_ASSERT_TRUE_FATAL(wait_for(lc_pauline,lc_marie,&stat_marie.number_of_LinphoneCallConnected,1)); + CU_ASSERT_TRUE_FATAL(wait_for(lc_pauline,lc_marie,&stat_pauline.number_of_LinphoneCallStreamsRunning,1)); + CU_ASSERT_TRUE_FATAL(wait_for(lc_pauline,lc_marie,&stat_marie.number_of_LinphoneCallStreamsRunning,1)); + /*just to sleep*/ + wait_for(lc_pauline,lc_marie,&stat_marie.number_of_LinphoneCallStreamsRunning,3); + linphone_core_terminate_all_calls(lc_pauline); + CU_ASSERT_TRUE(wait_for(lc_pauline,lc_marie,&stat_pauline.number_of_LinphoneCallEnd,1)); + CU_ASSERT_TRUE(wait_for(lc_pauline,lc_marie,&stat_marie.number_of_LinphoneCallEnd,1)); + + linphone_core_destroy(lc_marie); + linphone_core_destroy(lc_pauline); +} int init_test_suite () { -CU_pSuite pSuite = CU_add_suite("liblinphone init test suite", init, uninit); +CU_pSuite pSuite = CU_add_suite("liblinphone", 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(); } @@ -344,12 +419,19 @@ 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(); + } + if (NULL == CU_add_test(pSuite, "simple_call", simple_call)) { + return CU_get_error(); + } return 0; } int main (int argc, char *argv[]) { int i; + char *test_name=NULL; + char *suite_name=NULL; for(i=1;i