First working version

This commit is contained in:
Jehan Monnier 2012-07-27 18:24:08 +02:00
parent 447076314e
commit e2d0579e6b
14 changed files with 711 additions and 260 deletions

View file

@ -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){

View file

@ -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");

View file

@ -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_ */

View file

@ -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;i<h->result->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");

View file

@ -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);
}

View file

@ -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);
}

View file

@ -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;
}
}

View file

@ -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){

View file

@ -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);

18
tester/flexisip.conf Normal file → Executable file
View file

@ -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

View file

@ -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 (*counter<value && retry++ <20) {
if (lc_1) linphone_core_iterate(lc_1);
if (lc_2) linphone_core_iterate(lc_2);
ms_usleep(100000);
}
if(*counter<value) return FALSE;
else return TRUE;
}
static void enable_codec(LinphoneCore* lc,const char* type,int rate) {
MSList* codecs=ms_list_copy(linphone_core_get_audio_codecs(lc));
MSList* codecs_it;
for (codecs_it=codecs;codecs_it!=NULL;codecs_it=codecs_it->next) {
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<argc;++i){
if (strcmp(argv[i],"--help")==0){
fprintf(stderr,"%s \t--help\n\t\t\t--verbose",argv[0]);
@ -359,6 +441,12 @@ int main (int argc, char *argv[]) {
}else if (strcmp(argv[i],"--domain")==0){
i++;
test_domain=argv[i];
}else if (strcmp(argv[i],"--test")==0){
i++;
test_name=argv[i];
}else if (strcmp(argv[i],"--suite")==0){
i++;
suite_name=argv[i];
}
}
@ -369,7 +457,21 @@ int main (int argc, char *argv[]) {
init_test_suite();
/* Run all tests using the CUnit Basic interface */
CU_basic_set_mode(CU_BRM_VERBOSE);
CU_basic_run_tests();
if (suite_name){
#if 1 /*HAVE_CU_GET_SUITE*/
CU_pSuite suite;
suite=CU_get_suite(suite_name);
if (test_name) {
CU_pTest test=CU_get_test_by_name(test_name, suite);
CU_basic_run_test(suite, test);
} else
CU_basic_run_suite(suite);
#else
fprintf(stderr,"Your CUnit version does not support suite selection.\n");
#endif
} else
CU_basic_run_tests();
CU_cleanup_registry();
return CU_get_error();

38
tester/marie_rc Normal file
View file

@ -0,0 +1,38 @@
[sip]
sip_port=5082
sip_tcp_port=5082
sip_tls_port=5083
default_proxy=0
ping_with_options=0
[auth_info_0]
username=marie
userid=marie
passwd=secret
realm="auth.example.org"
[proxy_0]
reg_proxy=auth.example.org;transport=tcp
reg_route=auth.example.org;transport=tcp;lr
reg_identity=sip:marie@auth.example.org
reg_expires=3600
reg_sendregister=1
publish=0
dial_escape_plus=0
[rtp]
audio_rtp_port=8070
video_rtp_port=8072
[video]
display=0
capture=0
show_local=0
size=vga
enabled=0
self_view=0
automatically_initiate=0
automatically_accept=0
device=StaticImage: Static picture

37
tester/pauline_rc Normal file
View file

@ -0,0 +1,37 @@
[sip]
sip_port=5072
sip_tcp_port=5072
sip_tls_port=5073
default_proxy=0
ping_with_options=0
[auth_info_0]
username=pauline
userid=pauline
passwd=secret
realm="auth.example.org"
[proxy_0]
reg_proxy=auth.example.org;transport=tls
reg_route=auth.example.org;transport=tls;lr
reg_identity=sip:pauline@auth.example.org
reg_expires=3600
reg_sendregister=1
publish=0
dial_escape_plus=0
[rtp]
audio_rtp_port=8090
video_rtp_port=8092
[video]
display=0
capture=0
show_local=0
size=vga
enabled=0
self_view=0
automatically_initiate=0
automatically_accept=0
device=StaticImage: Static picture

View file

@ -4,3 +4,5 @@ liblinphone_tester@auth2.example.org secret
pauline@auth.example.org secret
marie@auth.example.org secret
bellesip@auth.example.org secret