implement sal_call_decline

This commit is contained in:
Jehan Monnier 2012-06-11 17:34:40 +02:00
parent 19f236fa8f
commit 447076314e
9 changed files with 220 additions and 48 deletions

View file

@ -45,8 +45,6 @@ static void process_authentication(SalOp *op, belle_sip_message_t *response) {
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) {
@ -67,10 +65,55 @@ static void process_dialog_terminated(void *user_ctx, const belle_sip_dialog_ter
static void process_io_error(void *user_ctx, const belle_sip_io_error_event_t *event){
ms_error("process_io_error not implemented yet");
}
static void process_request_event(void *user_ctx, const belle_sip_request_event_t *event) {
/*belle_sip_server_transaction_t* server_transaction = belle_sip_request_event_get_server_transaction(event);
SalOp* op = (SalOp*)belle_sip_transaction_get_application_data(BELLE_SIP_TRANSACTION(server_transaction));*/
ms_error("sal process_request_event not implemented yet");
static void process_request_event(void *sal, const belle_sip_request_event_t *event) {
SalOp* op;
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;
belle_sip_header_address_t* address;
belle_sip_header_from_t* from;
belle_sip_header_to_t* to;
if (dialog) {
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);
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));
}
if (!op->base.from_address) {
from=belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req),belle_sip_header_from_t);
address=belle_sip_header_address_create(belle_sip_header_address_get_displayname(BELLE_SIP_HEADER_ADDRESS(from))
,belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(from)));
sal_op_set_from_address(op,(SalAddress*)address);
belle_sip_object_unref(address);
}
if (!op->base.to_address) {
to=belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req),belle_sip_header_to_t);
address=belle_sip_header_address_create(belle_sip_header_address_get_displayname(BELLE_SIP_HEADER_ADDRESS(to))
,belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(to)));
sal_op_set_to_address(op,(SalAddress*)address);
belle_sip_object_unref(address);
}
if (!op->base.origin) {
/*set origin uri*/
origin_address=belle_sip_header_address_create(NULL,belle_sip_request_extract_origin(req));
__sal_op_set_network_origin_address(op,(SalAddress*)origin_address);
belle_sip_object_unref(origin_address);
}
if (!op->base.remote_ua) {
sal_op_set_remote_ua(op,BELLE_SIP_MESSAGE(req));
}
if (op->callbacks.process_request_event) {
op->callbacks.process_request_event(op,event);
} else {
ms_error("sal process_request_event not implemented yet");
}
}
static void process_response_event(void *user_ctx, const belle_sip_response_event_t *event){

View file

@ -40,13 +40,24 @@ struct SalOp{
belle_sip_listener_callbacks_t callbacks;
belle_sip_request_t* request;
belle_sip_response_t* response;
belle_sip_server_transaction_t* pending_server_trans;
SalAuthInfo auth_info;
unsigned long int registration_refresh_timer;
bool_t sdp_offering;
belle_sip_dialog_t* dialog;
belle_sip_header_address_t *replaces;
belle_sip_header_address_t *referred_by;
bool_t auto_answer_asked;
};
belle_sdp_session_description_t * media_description_to_sdp(const SalMediaDescription *sal);
int sdp_to_media_description(belle_sdp_session_description_t *sdp, SalMediaDescription *desc);
belle_sip_request_t* sal_op_build_request(SalOp *op,const char* method);
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);
#endif /* SAL_IMPL_H_ */

View file

@ -29,6 +29,59 @@ static void call_process_timeout(void *user_ctx, const belle_sip_timeout_event_t
}
static void call_process_transaction_terminated(void *user_ctx, const belle_sip_transaction_terminated_event_t *event) {
ms_error("process_transaction_terminated not implemented yet");
}
static void process_request_event(void *op_base, const belle_sip_request_event_t *event) {
SalOp* op = (SalOp*)op_base;
belle_sip_server_transaction_t* server_transaction = belle_sip_provider_create_server_transaction(op->base.root->prov,belle_sip_request_event_get_request(event));
belle_sip_object_ref(server_transaction);
if (op->pending_server_trans) belle_sip_object_unref(op->pending_server_trans);
op->pending_server_trans=server_transaction;
belle_sip_request_t* req = belle_sip_request_event_get_request(event);
belle_sip_header_t* replace_header;
belle_sip_dialog_state_t dialog_state;
belle_sdp_session_description_t* sdp;
belle_sip_header_t* call_info;
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);
ms_message("new incoming call from [%s] to [%s]",sal_op_get_from(op),sal_op_get_to(op));
}
dialog_state=belle_sip_dialog_get_state(op->dialog);
switch(dialog_state) {
case BELLE_SIP_DIALOG_NULL: {
if (!op->replaces && (replace_header=belle_sip_message_get_header(BELLE_SIP_MESSAGE(req),"replaces"))) {
op->replaces=belle_sip_header_address_parse(belle_sip_header_extension_get_value(BELLE_SIP_HEADER_EXTENSION(replace_header)));
belle_sip_object_ref(op->replaces);
} else if(op->replaces) {
ms_warning("replace header already set");
}
if ((sdp=belle_sdp_session_description_create(BELLE_SIP_MESSAGE(req)))) {
op->sdp_offering=FALSE;
op->base.remote_media=sal_media_description_new();
sdp_to_media_description(sdp,op->base.remote_media);
belle_sip_object_unref(sdp);
}else
op->sdp_offering=TRUE;
if ((call_info=belle_sip_message_get_header(BELLE_SIP_MESSAGE(req),"Call-Info"))) {
if( strstr(belle_sip_header_extension_get_value(BELLE_SIP_HEADER_EXTENSION(call_info)),"answer-after=") != NULL) {
op->auto_answer_asked=TRUE;
ms_message("The caller asked to automatically answer the call(Emergency?)\n");
}
}
op->base.root->callbacks.call_received(op);
break;
}
default: {
ms_error("unexpected dialog state [%s]",belle_sip_dialog_state_to_string(dialog_state));
}
}
}
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);
@ -89,16 +142,20 @@ int sal_call(SalOp *op, const char *from, const char *to){
route_header = belle_sip_header_route_create(BELLE_SIP_HEADER_ADDRESS(sal_op_get_route_address(op)));
belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(route_header));
}
sal_op_call_fill_cbs(op);
client_transaction = belle_sip_provider_create_client_transaction(prov,req);
belle_sip_transaction_set_application_data(BELLE_SIP_TRANSACTION(client_transaction),op);
op->dialog=belle_sip_provider_create_dialog(prov,BELLE_SIP_TRANSACTION(client_transaction));
belle_sip_client_transaction_send_request(client_transaction);
return 0;
}
void sal_op_call_fill_cbs(SalOp*op) {
op->callbacks.process_io_error=call_process_io_error;
op->callbacks.process_response_event=call_response_event;
op->callbacks.process_timeout=call_process_timeout;
op->callbacks.process_transaction_terminated=call_process_transaction_terminated;
client_transaction = belle_sip_provider_create_client_transaction(prov,req);
belle_sip_transaction_set_application_data(BELLE_SIP_TRANSACTION(client_transaction),op);
belle_sip_client_transaction_send_request(client_transaction);
return 0;
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");
@ -109,9 +166,45 @@ int sal_call_accept(SalOp*h){
ms_fatal("sal_call_accept not implemented yet");
return -1;
}
int sal_call_decline(SalOp *h, SalReason reason, const char *redirection /*optional*/){
ms_fatal("sal_call_decline not implemented yet");
return -1;
int sal_call_decline(SalOp *op, SalReason reason, const char *redirection /*optional*/){
belle_sip_response_t* response;
belle_sip_header_contact_t* contact=NULL;
int status;
switch(reason) {
case SalReasonBusy:
status=486;
break;
case SalReasonTemporarilyUnavailable:
status=480;
break;
case SalReasonDoNotDisturb:
status=600;
break;
case SalReasonMedia:
status=415;
break;
case SalReasonRedirect:
if(redirection!=NULL) {
if (strstr(redirection,"sip:")!=0) status=302;
status=380;
contact= belle_sip_header_contact_new();
belle_sip_header_address_set_uri(BELLE_SIP_HEADER_ADDRESS(contact),belle_sip_uri_parse(redirection));
break;
} else {
ms_error("Cannot redirect to null");
}
/* no break */
default:
status=500;
ms_error("Unexpected decline reason [%i]",reason);
/* no break */
}
response = belle_sip_response_create_from_request(belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(op->pending_server_trans)),status);
if (contact) belle_sip_message_add_header(BELLE_SIP_MESSAGE(response),BELLE_SIP_HEADER(contact));
belle_sip_server_transaction_send_response(op->pending_server_trans,response);
return 0;
}
int sal_call_update(SalOp *h, const char *subject){
ms_fatal("sal_call_update not implemented yet");

View file

@ -27,11 +27,11 @@ SalOp * sal_op_new(Sal *sal){
}
void sal_op_release(SalOp *op){
__sal_op_free(op);
if (op->request) belle_sip_object_unref(op->request);
if (op->registration_refresh_timer>0) {
belle_sip_main_loop_cancel_source(belle_sip_stack_get_main_loop(op->base.root->stack),op->registration_refresh_timer);
}
__sal_op_free(op);
return ;
}
void sal_op_authenticate(SalOp *op, const SalAuthInfo *info){
@ -70,7 +70,7 @@ void sal_op_authenticate(SalOp *op, const SalAuthInfo *info){
goto error;
}
belle_sip_message_set_header(BELLE_SIP_MESSAGE(op->request),BELLE_SIP_HEADER(authorization));
sal_register_refresh(op,-1);
sal_op_resend_request(op,op->request);
return;
error:
@ -78,6 +78,7 @@ error:
return ;
}
void sal_op_cancel_authentication(SalOp *h){
ms_fatal("sal_op_cancel_authentication not implemented yet");
return ;
@ -170,4 +171,29 @@ int sal_ping(SalOp *op, const char *from, const char *to){
return -1;
}
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) {
op->base.remote_ua=ms_strdup(user_agent_string);
}
}
void sal_op_resend_request(SalOp* op, belle_sip_request_t* request) {
belle_sip_header_cseq_t* cseq=(belle_sip_header_cseq_t*)belle_sip_message_get_header(BELLE_SIP_MESSAGE(op->request),BELLE_SIP_CSEQ);
belle_sip_header_cseq_set_seq_number(cseq,belle_sip_header_cseq_get_seq_number(cseq)+1);
sal_op_send_request(op,request);
}
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));
}
client_transaction = belle_sip_provider_create_client_transaction(prov,request);
belle_sip_transaction_set_application_data(BELLE_SIP_TRANSACTION(client_transaction),op);
belle_sip_client_transaction_send_request(client_transaction);
}

View file

@ -20,8 +20,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
static void send_register_request(SalOp* op, belle_sip_request_t* request);
static void register_process_io_error(void *user_ctx, const belle_sip_io_error_event_t *event){
ms_error("process_io_error not implemented yet");
}
@ -30,7 +28,7 @@ static void register_refresh(SalOp* op) {
op->registration_refresh_timer=0;
belle_sip_header_cseq_t* cseq=(belle_sip_header_cseq_t*)belle_sip_message_get_header(BELLE_SIP_MESSAGE(op->request),BELLE_SIP_CSEQ);
belle_sip_header_cseq_set_seq_number(cseq,belle_sip_header_cseq_get_seq_number(cseq)+1);
send_register_request(op,op->request);
sal_op_send_request(op,op->request);
}
static bool_t is_contact_equal(belle_sip_header_contact_t* a,belle_sip_header_contact_t* b) {
if (!a | !b) return FALSE;
@ -74,10 +72,12 @@ static void register_response_event(void *user_ctx, const belle_sip_response_eve
}
op->base.root->callbacks.register_success(op,expires_header&&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);
op->registration_refresh_timer=0;
}
if (expires>0) {
if (op->registration_refresh_timer>0) {
belle_sip_main_loop_cancel_source(belle_sip_stack_get_main_loop(op->base.root->stack),op->registration_refresh_timer);
}
op->registration_refresh_timer = belle_sip_main_loop_add_timeout(belle_sip_stack_get_main_loop(op->base.root->stack),(belle_sip_source_func_t)register_refresh,op,expires*1000);
}
@ -100,31 +100,15 @@ static void register_process_transaction_terminated(void *user_ctx, const belle_
static void send_register_request(SalOp* op, belle_sip_request_t* request) {
belle_sip_client_transaction_t* client_transaction;
belle_sip_provider_t* prov=op->base.root->prov;
op->callbacks.process_io_error=register_process_io_error;
op->callbacks.process_response_event=register_response_event;
op->callbacks.process_timeout=register_process_timeout;
op->callbacks.process_transaction_terminated=register_process_transaction_terminated;
client_transaction = belle_sip_provider_create_client_transaction(prov,request);
belle_sip_transaction_set_application_data(BELLE_SIP_TRANSACTION(client_transaction),op);
belle_sip_client_transaction_send_request(client_transaction);
}
/*if expire = -1, does not change expires*/
static void send_register_request_with_expires(SalOp* op, belle_sip_request_t* request,int expires) {
belle_sip_header_expires_t* expires_header=(belle_sip_header_expires_t*)belle_sip_message_get_header(BELLE_SIP_MESSAGE(request),BELLE_SIP_EXPIRES);
belle_sip_header_route_t* route_header;
if (sal_op_get_route_address(op)) {
route_header = belle_sip_header_route_create(BELLE_SIP_HEADER_ADDRESS(sal_op_get_route_address(op)));
belle_sip_message_add_header(BELLE_SIP_MESSAGE(request),BELLE_SIP_HEADER(route_header));
}
if (!expires_header) {
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>=0) belle_sip_header_expires_set_expires(expires_header,expires);
send_register_request(op,request);
sal_op_send_request(op,request);
}
@ -134,6 +118,10 @@ int sal_register(SalOp *op, const char *proxy, const char *from, int expires){
sal_op_set_from(op,from);
sal_op_set_to(op,from);
sal_op_set_route(op,proxy);
op->callbacks.process_io_error=register_process_io_error;
op->callbacks.process_response_event=register_response_event;
op->callbacks.process_timeout=register_process_timeout;
op->callbacks.process_transaction_terminated=register_process_transaction_terminated;
req = sal_op_build_request(op,"REGISTER");
belle_sip_uri_t* req_uri = belle_sip_request_get_uri(req);

View file

@ -2585,6 +2585,7 @@ int linphone_core_terminate_call(LinphoneCore *lc, LinphoneCall *the_call)
{
call = the_call;
}
sal_call_terminate(call->op);
terminate_call(lc,call);
@ -4179,7 +4180,7 @@ void sip_config_uninit(LinphoneCore *lc)
Sleep(100);
#endif
}
if (i>=20) ms_warning("Cannot complete unregistration, giving up");
ms_list_for_each(config->proxies,(void (*)(void*)) linphone_proxy_config_destroy);
ms_list_free(config->proxies);
config->proxies=NULL;

View file

@ -324,9 +324,14 @@ void __sal_op_init(SalOp *b, Sal *sal){
}
void __sal_op_set_network_origin(SalOp *op, const char *origin){
assign_string(&((SalOpBase*)op)->origin,origin);
SET_PARAM(op,origin);
}
void __sal_op_set_network_origin_address(SalOp *op, SalAddress *origin){
char* address_string=sal_address_as_string(origin); /*can probably be optimized*/
__sal_op_set_network_origin(op,address_string);
ms_free(address_string);
}
void __sal_op_free(SalOp *op){
SalOpBase *b=(SalOpBase *)op;

View file

@ -174,6 +174,7 @@ typedef struct SalOpBase{
char *to;
SalAddress* to_address;
char *origin;
SalAddress* origin_address;
char *remote_ua;
SalMediaDescription *local_media;
SalMediaDescription *remote_media;
@ -336,6 +337,7 @@ const SalAddress* sal_op_get_route_address(const SalOp *op);
const char *sal_op_get_proxy(const SalOp *op);
/*for incoming requests, returns the origin of the packet as a sip uri*/
const char *sal_op_get_network_origin(const SalOp *op);
const SalAddress *sal_op_get_network_origin_address(const SalOp *op);
/*returns far-end "User-Agent" string */
const char *sal_op_get_remote_ua(const SalOp *op);
void *sal_op_get_user_pointer(const SalOp *op);
@ -400,6 +402,7 @@ void sal_disable_logs();
/*internal API */
void __sal_op_init(SalOp *b, Sal *sal);
void __sal_op_set_network_origin(SalOp *op, const char *origin /*a sip uri*/);
void __sal_op_set_network_origin_address(SalOp *op, SalAddress *origin);
void __sal_op_free(SalOp *b);
#endif

View file

@ -244,7 +244,7 @@ static LinphoneCore* configure_lc(LinphoneCoreVTable* v_table) {
LinphoneCore* lc;
int retry=0;
memset (v_table,0,sizeof(LinphoneCoreVTable));
reset_counters();
lc = linphone_core_new(v_table,NULL,"./multi_account_lrc",NULL);
@ -260,6 +260,7 @@ static LinphoneCore* configure_lc(LinphoneCoreVTable* v_table) {
static void multiple_proxy(){
LinphoneCoreVTable v_table;
LinphoneCore* lc;
memset (&v_table,0,sizeof(LinphoneCoreVTable));
v_table.registration_state_changed=registration_state_changed;
lc=configure_lc(&v_table);
linphone_core_destroy(lc);
@ -296,6 +297,7 @@ static void simple_call_declined() {
LinphoneCore* lc;
int retry=0;
memset (&v_table,0,sizeof(LinphoneCoreVTable));
v_table.registration_state_changed=registration_state_changed;
v_table.call_state_changed=call_state_changed;
lc=configure_lc(&v_table);
@ -314,6 +316,7 @@ static void simple_call_declined() {
int init_test_suite () {
CU_pSuite pSuite = CU_add_suite("liblinphone init test suite", init, uninit);
if (NULL == CU_add_test(pSuite, "simple call declined", simple_call_declined)) {
return CU_get_error();
}
@ -341,9 +344,8 @@ CU_pSuite pSuite = CU_add_suite("liblinphone init test suite", init, uninit);
if (NULL == CU_add_test(pSuite, "multi account", multiple_proxy)) {
return CU_get_error();
}
if (NULL == CU_add_test(pSuite, "simple call declined", simple_call_declined)) {
return CU_get_error();
}
return 0;
}
int main (int argc, char *argv[]) {