From 36e445f97f6d45239a3271f60fc3385892503741 Mon Sep 17 00:00:00 2001 From: Simon Morlat Date: Thu, 6 Jun 2013 10:49:28 +0200 Subject: [PATCH 1/7] generic subscribe notify api in progress --- console/linphonec.c | 15 +- coreapi/Makefile.am | 4 +- coreapi/bellesip_sal/sal_impl.c | 55 +++-- coreapi/bellesip_sal/sal_impl.h | 10 +- coreapi/bellesip_sal/sal_op_events.c | 303 +++++++++++++++++++++++++ coreapi/bellesip_sal/sal_op_impl.c | 162 +++++++++---- coreapi/bellesip_sal/sal_op_info.c | 23 +- coreapi/bellesip_sal/sal_op_message.c | 1 + coreapi/bellesip_sal/sal_op_presence.c | 41 +--- coreapi/bellesip_sal/sal_op_publish.c | 26 ++- coreapi/callbacks.c | 75 +++++- coreapi/event.c | 178 +++++++++++++++ coreapi/event.h | 51 ++++- coreapi/friend.c | 2 +- coreapi/info.c | 16 +- coreapi/linphonecore.c | 4 + coreapi/linphonecore.h | 90 ++++---- coreapi/misc.c | 60 +++++ coreapi/presence.c | 2 +- coreapi/private.h | 11 + coreapi/proxy.c | 2 +- include/sal/sal.h | 34 ++- mediastreamer2 | 2 +- tester/Makefile.am | 9 +- tester/eventapi_tester.c | 108 +++++++++ tester/liblinphone_tester.c | 3 + tester/liblinphone_tester.h | 9 + 27 files changed, 1084 insertions(+), 212 deletions(-) create mode 100644 coreapi/bellesip_sal/sal_op_events.c create mode 100644 coreapi/event.c create mode 100644 tester/eventapi_tester.c diff --git a/console/linphonec.c b/console/linphonec.c index 60c3c2af1..f9e329b51 100644 --- a/console/linphonec.c +++ b/console/linphonec.c @@ -123,7 +123,7 @@ static void linphonec_display_refer (LinphoneCore * lc, const char *refer_to); static void linphonec_display_something (LinphoneCore * lc, const char *something); static void linphonec_display_url (LinphoneCore * lc, const char *something, const char *url); static void linphonec_display_warning (LinphoneCore * lc, const char *something); -static void linphonec_notify_received(LinphoneCore *lc, LinphoneCall *call, const char *from,const char *event); +static void linphonec_transfer_state_changed(LinphoneCore *lc, LinphoneCall *call, LinphoneCallState new_call_state); static void linphonec_notify_presence_received(LinphoneCore *lc,LinphoneFriend *fid); static void linphonec_new_unknown_subscriber(LinphoneCore *lc, @@ -281,13 +281,14 @@ linphonec_prompt_for_auth(LinphoneCore *lc, const char *realm, const char *usern * Linphone core callback */ static void -linphonec_notify_received(LinphoneCore *lc, LinphoneCall *call, const char *from,const char *event) +linphonec_transfer_state_changed(LinphoneCore *lc, LinphoneCall *call, LinphoneCallState new_call_state) { - if(!strcmp(event,"refer")) - { - linphonec_out("The distand endpoint %s of call %li has been transfered, you can safely close the call.\n", - from,(long)linphone_call_get_user_pointer (call)); + char *remote=linphone_call_get_remote_address_as_string(call); + if (new_call_state==LinphoneCallConnected){ + linphonec_out("The distant endpoint %s of call %li has been transfered, you can safely close the call.\n", + remote,(long)linphone_call_get_user_pointer (call)); } + ms_free(remote); } @@ -638,7 +639,7 @@ main (int argc, char *argv[]) { linphonec_vtable.text_received=linphonec_text_received; linphonec_vtable.dtmf_received=linphonec_dtmf_received; linphonec_vtable.refer_received=linphonec_display_refer; - linphonec_vtable.notify_recv=linphonec_notify_received; + linphonec_vtable.transfer_state_changed=linphonec_transfer_state_changed; linphonec_vtable.call_encryption_changed=linphonec_call_encryption_changed; if (! linphonec_init(argc, argv) ) exit(EXIT_FAILURE); diff --git a/coreapi/Makefile.am b/coreapi/Makefile.am index 1180bfff9..c4c60fcf7 100644 --- a/coreapi/Makefile.am +++ b/coreapi/Makefile.am @@ -46,6 +46,7 @@ liblinphone_la_SOURCES=\ conference.c \ message_storage.c \ info.c \ + event.c \ $(GITVERSION_FILE) if BUILD_UPNP @@ -63,7 +64,8 @@ liblinphone_la_SOURCES+= bellesip_sal/sal_address_impl.c \ bellesip_sal/sal_op_presence.c \ bellesip_sal/sal_op_publish.c \ bellesip_sal/sal_op_call_transfer.c \ - bellesip_sal/sal_op_info.c + bellesip_sal/sal_op_info.c \ + bellesip_sal/sal_op_events.c else liblinphone_la_SOURCES+= sal_eXosip2.c sal_eXosip2.h\ sal_eXosip2_sdp.c \ diff --git a/coreapi/bellesip_sal/sal_impl.c b/coreapi/bellesip_sal/sal_impl.c index 960a50254..6f7fe2124 100644 --- a/coreapi/bellesip_sal/sal_impl.c +++ b/coreapi/bellesip_sal/sal_impl.c @@ -141,6 +141,7 @@ static void process_request_event(void *sal, const belle_sip_request_event_t *ev belle_sip_header_from_t* from_header; belle_sip_header_to_t* to; belle_sip_response_t* resp; + belle_sip_header_t *evh; from_header=belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req),belle_sip_header_from_t); @@ -150,10 +151,13 @@ static void process_request_event(void *sal, const belle_sip_request_event_t *ev op=sal_op_new((Sal*)sal); op->dir=SalOpDirIncoming; sal_op_call_fill_cbs(op); - } else if (strcmp("SUBSCRIBE",belle_sip_request_get_method(req))==0) { + } else if (strcmp("SUBSCRIBE",belle_sip_request_get_method(req))==0 && (evh=belle_sip_message_get_header(BELLE_SIP_MESSAGE(req),"Event"))!=NULL) { op=sal_op_new((Sal*)sal); op->dir=SalOpDirIncoming; - sal_op_presence_fill_cbs(op); + if (strncmp(belle_sip_header_get_unparsed_value(evh),"presence",strlen("presence"))==0){ + sal_op_presence_fill_cbs(op); + }else + sal_op_subscribe_fill_cbs(op); } else if (strcmp("MESSAGE",belle_sip_request_get_method(req))==0) { op=sal_op_new((Sal*)sal); op->dir=SalOpDirIncoming; @@ -259,7 +263,6 @@ static void process_response_event(void *user_ctx, const belle_sip_response_even } if (sal_op_get_contact(op)){ if (received!=NULL || rport>0) { - contact_address = BELLE_SIP_HEADER_ADDRESS(sal_address_clone(sal_op_get_contact_address(op))); contact_uri=belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(contact_address)); if (received && strcmp(received,belle_sip_uri_get_host(contact_uri))!=0) { @@ -302,30 +305,28 @@ static void process_response_event(void *user_ctx, const belle_sip_response_even /*handle authorization*/ switch (response_code) { - case 200: { - break; - } - case 401: - case 407:{ - - /*belle_sip_transaction_set_application_data(BELLE_SIP_TRANSACTION(client_transaction),NULL);*//*remove op from trans*/ - if (op->state == SalOpStateTerminating && strcmp("BYE",belle_sip_request_get_method(request))!=0) { - /*only bye are completed*/ - belle_sip_message("Op is in state terminating, nothing else to do "); - } else { - if (op->pending_auth_transaction){ - belle_sip_object_unref(op->pending_auth_transaction); - op->pending_auth_transaction=NULL; + case 200: { + break; + } + case 401: + case 407:{ + + /*belle_sip_transaction_set_application_data(BELLE_SIP_TRANSACTION(client_transaction),NULL);*//*remove op from trans*/ + if (op->state == SalOpStateTerminating && strcmp("BYE",belle_sip_request_get_method(request))!=0) { + /*only bye are completed*/ + belle_sip_message("Op is in state terminating, nothing else to do "); + } else { + if (op->pending_auth_transaction){ + belle_sip_object_unref(op->pending_auth_transaction); + op->pending_auth_transaction=NULL; + } + op->pending_auth_transaction=(belle_sip_client_transaction_t*)belle_sip_object_ref(client_transaction); + sal_process_authentication(op); + return; } - op->pending_auth_transaction=(belle_sip_client_transaction_t*)belle_sip_object_ref(client_transaction); - sal_process_authentication(op); - return; } } - } - op->callbacks.process_response_event(op,event); - } else { ms_error("Unhandled event response [%p]",event); } @@ -444,10 +445,14 @@ void sal_set_callbacks(Sal *ctx, const SalCallbacks *cbs){ ctx->callbacks.dtmf_received=(SalOnDtmfReceived)unimplemented_stub; if (ctx->callbacks.notify==NULL) ctx->callbacks.notify=(SalOnNotify)unimplemented_stub; - if (ctx->callbacks.notify_presence==NULL) - ctx->callbacks.notify_presence=(SalOnNotifyPresence)unimplemented_stub; if (ctx->callbacks.subscribe_received==NULL) ctx->callbacks.subscribe_received=(SalOnSubscribeReceived)unimplemented_stub; + if (ctx->callbacks.subscribe_closed==NULL) + ctx->callbacks.subscribe_closed=(SalOnSubscribeClosed)unimplemented_stub; + if (ctx->callbacks.notify_presence==NULL) + ctx->callbacks.notify_presence=(SalOnNotifyPresence)unimplemented_stub; + if (ctx->callbacks.subscribe_presence_received==NULL) + ctx->callbacks.subscribe_presence_received=(SalOnSubscribePresenceReceived)unimplemented_stub; if (ctx->callbacks.text_received==NULL) ctx->callbacks.text_received=(SalOnTextReceived)unimplemented_stub; if (ctx->callbacks.ping_reply==NULL) diff --git a/coreapi/bellesip_sal/sal_impl.h b/coreapi/bellesip_sal/sal_impl.h index 2a6f50cc5..0b3e7ae24 100644 --- a/coreapi/bellesip_sal/sal_impl.h +++ b/coreapi/bellesip_sal/sal_impl.h @@ -66,7 +66,8 @@ typedef enum SalOpType { SalOpMessage, SalOpPresence, SalOpPublish, - SalOpInfo + SalOpInfo, + SalOpSubscribe }SalOpType_t; const char* sal_op_type_to_string(const SalOpType_t type); @@ -127,6 +128,8 @@ void sal_op_message_fill_cbs(SalOp*op); /*info*/ void sal_op_info_fill_cbs(SalOp*op); +void sal_op_subscribe_fill_cbs(SalOp*op); + /*call transfer*/ void sal_op_process_refer(SalOp *op, const belle_sip_request_event_t *event); void sal_op_call_process_notify(SalOp *op, const belle_sip_request_event_t *event); @@ -140,4 +143,9 @@ belle_sip_response_t *sal_create_response_from_request(Sal *sal, belle_sip_reque void sal_op_assign_recv_headers(SalOp *op, belle_sip_message_t *incoming); +void sal_op_add_body(SalOp *op, belle_sip_message_t *req, const SalBody *body); +bool_t sal_op_get_body(SalOp *op, belle_sip_message_t *msg, SalBody *salbody); + +SalReason sal_reason_to_sip_code(SalReason r); + #endif /* SAL_IMPL_H_ */ diff --git a/coreapi/bellesip_sal/sal_op_events.c b/coreapi/bellesip_sal/sal_op_events.c new file mode 100644 index 000000000..4923f2269 --- /dev/null +++ b/coreapi/bellesip_sal/sal_op_events.c @@ -0,0 +1,303 @@ +/* +linphone +Copyright (C) 2012 Belledonne Communications, Grenoble, France + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ +#include "sal_impl.h" + + +static void subscribe_process_io_error(void *user_ctx, const belle_sip_io_error_event_t *event){ + ms_error("subscribe_process_io_error not implemented yet"); +} +static void subscribe_process_dialog_terminated(void *ctx, const belle_sip_dialog_terminated_event_t *event) { + SalOp* op= (SalOp*)ctx; + if (op->dialog) { + sal_op_unref(op); + op->dialog=NULL; + } +} + +SalSubscribeStatus get_subscription_state(belle_sip_message_t *msg){ + belle_sip_header_subscription_state_t* subscription_state_header=belle_sip_message_get_header_by_type(msg,belle_sip_header_subscription_state_t); + SalSubscribeStatus sss=SalSubscribeNone; + if (subscription_state_header){ + if (strcmp(belle_sip_header_subscription_state_get_state(subscription_state_header),BELLE_SIP_SUBSCRIPTION_STATE_TERMINATED)==0) + sss=SalSubscribeTerminated; + else if (strcmp(belle_sip_header_subscription_state_get_state(subscription_state_header),BELLE_SIP_SUBSCRIPTION_STATE_PENDING)==0) + sss=SalSubscribePending; + else if (strcmp(belle_sip_header_subscription_state_get_state(subscription_state_header),BELLE_SIP_SUBSCRIPTION_STATE_ACTIVE)==0) + sss=SalSubscribeActive; + } + return sss; +} + +static void subscribe_response_event(void *op_base, const belle_sip_response_event_t *event){ + SalOp* op = (SalOp*)op_base; + 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); + belle_sip_request_t* request=belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(client_transaction)); + int code = belle_sip_response_get_status_code(response); + char reason[256]={0}; + SalError error=SalErrorUnknown; + SalReason sr=SalReasonUnknown; + belle_sip_header_expires_t* expires; + SalSubscribeStatus sss=get_subscription_state(BELLE_SIP_MESSAGE(response)); + + if (sal_compute_sal_errors(response,&error,&sr,reason, sizeof(reason))) { + ms_error("subscription to [%s] rejected reason [%s]",sal_op_get_to(op),reason[0]!=0?reason:sal_reason_to_string(sr)); + op->base.root->callbacks.subscribe_response(op,SalSubscribeTerminated,error,sr); + return; + } + set_or_update_dialog(op_base,belle_sip_response_event_get_dialog(event)); + if (!op->dialog) { + ms_message("subscribe op [%p] receive out of dialog answer [%i]",op,code); + return; + } + dialog_state=belle_sip_dialog_get_state(op->dialog); + switch(dialog_state) { + case BELLE_SIP_DIALOG_NULL: + case BELLE_SIP_DIALOG_EARLY: { + ms_error("subscribe op [%p] receive an unexpected answer [%i]",op,code); + break; + } + case BELLE_SIP_DIALOG_CONFIRMED: { + if (strcmp("SUBSCRIBE",belle_sip_request_get_method(request))==0) { + expires=belle_sip_message_get_header_by_type(request,belle_sip_header_expires_t); + if(op->refresher) { + belle_sip_refresher_stop(op->refresher); + belle_sip_object_unref(op->refresher); + op->refresher=NULL; + } + if (expires>0){ + op->refresher=belle_sip_client_transaction_create_refresher(client_transaction); + } + op->base.root->callbacks.subscribe_response(op,sss,SalErrorNone,SalReasonUnknown); + } + break; + } + case BELLE_SIP_DIALOG_TERMINATED: + if (op->refresher) { + belle_sip_refresher_stop(op->refresher); + belle_sip_object_unref(op->refresher); + op->refresher=NULL; + } + break; + default: { + ms_error("subscribe op [%p] receive answer [%i] not implemented",op,code); + } + /* no break */ + } +} + +static void subscribe_process_timeout(void *user_ctx, const belle_sip_timeout_event_t *event) { + ms_message("subscribe_process_timeout not implemented yet"); +} + +static void subscribe_process_transaction_terminated(void *user_ctx, const belle_sip_transaction_terminated_event_t *event) { + ms_message("subscribe_process_transaction_terminated not implemented yet"); +} + +static void subscribe_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_request_t* req = belle_sip_request_event_get_request(event); + belle_sip_dialog_state_t dialog_state; + belle_sip_header_subscription_state_t* subscription_state_header=belle_sip_message_get_header_by_type(req,belle_sip_header_subscription_state_t); + belle_sip_header_expires_t* expires = belle_sip_message_get_header_by_type(req,belle_sip_header_expires_t); + belle_sip_header_t *event_header; + SalBody body; + SalSubscribeStatus sub_state; + belle_sip_response_t* resp; + const char *eventname=NULL; + + 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; + + event_header=belle_sip_message_get_header((belle_sip_message_t*)req,"Event"); + eventname=belle_sip_header_get_unparsed_value(event_header); + sal_op_get_body(op,(belle_sip_message_t*)req,&body); + + if (eventname==NULL){ + ms_warning("No event header in incoming SUBSCRIBE."); + resp=sal_op_create_response_from_request(op,req,400); + belle_sip_server_transaction_send_response(server_transaction,resp); + return; + } + + if (!op->dialog) { + op->dialog=belle_sip_provider_create_dialog(op->base.root->prov,BELLE_SIP_TRANSACTION(server_transaction)); + belle_sip_dialog_set_application_data(op->dialog,op); + sal_op_ref(op); + ms_message("new incoming subscription 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: { + op->base.root->callbacks.subscribe_received(op,eventname,body.type ? &body : NULL); + break; + } + case BELLE_SIP_DIALOG_EARLY: + ms_error("unexpected method [%s] for dialog [%p] in state BELLE_SIP_DIALOG_EARLY ",belle_sip_request_get_method(req),op->dialog); + break; + + case BELLE_SIP_DIALOG_CONFIRMED: + if (strcmp("NOTIFY",belle_sip_request_get_method(req))==0) { + if (!subscription_state_header || strcasecmp(BELLE_SIP_SUBSCRIPTION_STATE_TERMINATED,belle_sip_header_subscription_state_get_state(subscription_state_header)) ==0) { + sub_state=SalSubscribeTerminated; + ms_message("Outgoing subscription terminated by remote [%s]",sal_op_get_to(op)); + } else + sub_state=SalSubscribeActive; + + op->base.root->callbacks.notify(op,sub_state,eventname,&body); + resp=sal_op_create_response_from_request(op,req,200); + belle_sip_server_transaction_send_response(server_transaction,resp); + } else if (strcmp("SUBSCRIBE",belle_sip_request_get_method(req))==0) { + /*either a refresh of an unsubscribe*/ + if (expires && belle_sip_header_expires_get_expires(expires)>0) { + + } else if(expires) { + ms_message("Unsubscribe received from [%s]",sal_op_get_from(op)); + resp=sal_op_create_response_from_request(op,req,200); + belle_sip_server_transaction_send_response(server_transaction,resp); + op->base.root->callbacks.subscribe_closed(op); + } + } + break; + default: { + ms_error("unexpected dialog state [%s]",belle_sip_dialog_state_to_string(dialog_state)); + } + } +} + +void sal_op_subscribe_fill_cbs(SalOp*op) { + op->callbacks.process_io_error=subscribe_process_io_error; + op->callbacks.process_response_event=subscribe_response_event; + op->callbacks.process_timeout=subscribe_process_timeout; + op->callbacks.process_transaction_terminated=subscribe_process_transaction_terminated; + op->callbacks.process_request_event=subscribe_process_request_event; + op->callbacks.process_dialog_terminated=subscribe_process_dialog_terminated; + op->type=SalOpSubscribe; +} + +static int set_event_name(SalOp *op, belle_sip_message_t *msg){ + belle_sip_transaction_t *last_transaction; + belle_sip_request_t *req; + belle_sip_header_t *event; + + if (!op->dialog) return -1; + + last_transaction=belle_sip_dialog_get_last_transaction(op->dialog); + + if (!last_transaction) return -1; + + req=belle_sip_transaction_get_request(last_transaction); + event=belle_sip_message_get_header((belle_sip_message_t*)req,"Event"); + if (!event){ + ms_error("No event header in last request."); + return -1; + } + belle_sip_message_add_header(msg,event); + return 0; +} + +int sal_subscribe(SalOp *op, const char *from, const char *to, const char *eventname, int expires, const SalBody *body){ + belle_sip_request_t *req=NULL; + + if (from) + sal_op_set_from(op,from); + if (to) + sal_op_set_to(op,to); + + if (!op->dialog){ + sal_op_subscribe_fill_cbs(op); + /*???sal_exosip_fix_route(op); make sure to ha ;lr*/ + req=sal_op_build_request(op,"SUBSCRIBE"); + belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),belle_sip_header_create("Event",eventname)); + }else{ + belle_sip_transaction_t *last=belle_sip_dialog_get_last_transaction(op->dialog); + belle_sip_message_t *msg=BELLE_SIP_MESSAGE(belle_sip_transaction_get_request(last)); + req=belle_sip_dialog_create_request(op->dialog,"SUBSCRIBE"); + if (expires==-1){ + belle_sip_header_expires_t *eh=belle_sip_message_get_header_by_type(msg,belle_sip_header_expires_t); + expires=belle_sip_header_expires_get_expires(eh); + } + set_event_name(op,(belle_sip_message_t*)req); + } + belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(belle_sip_header_expires_create(expires))); + sal_op_add_body(op,(belle_sip_message_t*)req,body); + return sal_op_send_request(op,req); +} + +int sal_unsubscribe(SalOp *op){ + belle_sip_request_t* req=op->dialog?belle_sip_dialog_create_request(op->dialog,"SUBSCRIBE"):NULL; /*cannot create request if dialog not set yet*/ + if (!req) { + ms_error("Cannot unsubscribe to [%s]",sal_op_get_to(op)); + return -1; + } + if (op->refresher) + belle_sip_refresher_stop(op->refresher); + set_event_name(op,(belle_sip_message_t*)req); + belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(belle_sip_header_expires_create(0))); + return sal_op_send_request(op,req); +} + +int sal_subscribe_accept(SalOp *op){ + belle_sip_request_t* req=belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(op->pending_server_trans)); + belle_sip_header_expires_t* expires = belle_sip_message_get_header_by_type(req,belle_sip_header_expires_t); + belle_sip_response_t* resp = sal_op_create_response_from_request(op,req,200); + belle_sip_message_add_header(BELLE_SIP_MESSAGE(resp),BELLE_SIP_HEADER(expires)); + belle_sip_server_transaction_send_response(op->pending_server_trans,resp); + return 0; +} + +int sal_subscribe_decline(SalOp *op, SalReason reason){ + belle_sip_response_t* resp = belle_sip_response_create_from_request(belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(op->pending_server_trans)), + sal_reason_to_sip_code(reason)); + belle_sip_server_transaction_send_response(op->pending_server_trans,resp); + return 0; +} + +int sal_notify(SalOp *op, const SalBody *body){ + belle_sip_request_t* notify; + + if (!op->dialog) return -1; + + notify=belle_sip_dialog_create_request(op->dialog,"NOTIFY"); + if (set_event_name(op,(belle_sip_message_t*)notify)==-1){ + belle_sip_object_unref(notify); + return -1; + } + + belle_sip_message_add_header(BELLE_SIP_MESSAGE(notify) + ,BELLE_SIP_HEADER(belle_sip_header_subscription_state_create(BELLE_SIP_SUBSCRIPTION_STATE_ACTIVE,600))); + + sal_op_add_body(op,(belle_sip_message_t*)notify, body); + return sal_op_send_request(op,notify); +} + +int sal_notify_close(SalOp *op){ + belle_sip_request_t* notify; + if (!op->dialog) return -1; + notify=belle_sip_dialog_create_request(op->dialog,"NOTIFY"); + set_event_name(op,(belle_sip_message_t*)notify); + belle_sip_message_add_header(BELLE_SIP_MESSAGE(notify) + ,BELLE_SIP_HEADER(belle_sip_header_subscription_state_create(BELLE_SIP_SUBSCRIPTION_STATE_TERMINATED,-1))); + return sal_op_send_request(op,notify); +} + diff --git a/coreapi/bellesip_sal/sal_op_impl.c b/coreapi/bellesip_sal/sal_op_impl.c index ffd2b3b86..ea8dd9c34 100644 --- a/coreapi/bellesip_sal/sal_op_impl.c +++ b/coreapi/bellesip_sal/sal_op_impl.c @@ -256,56 +256,93 @@ int sal_op_send_request(SalOp* op, belle_sip_request_t* request) { return _sal_op_send_request_with_contact(op, request,need_contact); } +SalReason sal_reason_to_sip_code(SalReason r){ + int ret=500; + switch(r){ + case SalReasonUnknown: + ret=400; + break; + + case SalReasonBusy: + ret=486; + break; + case SalReasonDeclined: + ret=603; + break; + case SalReasonDoNotDisturb: + ret=600; + break; + case SalReasonForbidden: + ret=403; + break; + case SalReasonMedia: + ret=415; + break; + case SalReasonNotFound: + ret=404; + break; + case SalReasonRedirect: + ret=302; + break; + case SalReasonTemporarilyUnavailable: + ret=480; + break; + case SalReasonServiceUnavailable: + ret=503; + break; + } + return ret; +} void sal_compute_sal_errors_from_code(int code ,SalError* sal_err,SalReason* sal_reason) { - switch(code) { - case 400: - *sal_err=SalErrorUnknown; - break; - case 403: + switch(code) { + case 400: + *sal_err=SalErrorUnknown; + break; + case 403: + *sal_err=SalErrorFailure; + *sal_reason=SalReasonForbidden; + break; + case 404: + *sal_err=SalErrorFailure; + *sal_reason=SalReasonNotFound; + break; + case 415: + *sal_err=SalErrorFailure; + *sal_reason=SalReasonMedia; + break; + case 422: + ms_error ("422 not implemented yet");; + break; + case 480: + *sal_err=SalErrorFailure; + *sal_reason=SalReasonTemporarilyUnavailable; + break; + case 486: + *sal_err=SalErrorFailure; + *sal_reason=SalReasonBusy; + break; + case 487: + break; + case 600: + *sal_err=SalErrorFailure; + *sal_reason=SalReasonDoNotDisturb; + break; + case 603: + *sal_err=SalErrorFailure; + *sal_reason=SalReasonDeclined; + break; + case 503: + *sal_err=SalErrorFailure; + *sal_reason=SalReasonServiceUnavailable; + break; + default: + if (code>0){ *sal_err=SalErrorFailure; - *sal_reason=SalReasonForbidden; - break; - case 404: - *sal_err=SalErrorFailure; - *sal_reason=SalReasonNotFound; - break; - case 415: - *sal_err=SalErrorFailure; - *sal_reason=SalReasonMedia; - break; - case 422: - ms_error ("422 not implemented yet");; - break; - case 480: - *sal_err=SalErrorFailure; - *sal_reason=SalReasonTemporarilyUnavailable; - break; - case 486: - *sal_err=SalErrorFailure; - *sal_reason=SalReasonBusy; - break; - case 487: - break; - case 503: - *sal_err=SalErrorFailure; - *sal_reason=SalReasonServiceUnavailable; - break; - case 600: - *sal_err=SalErrorFailure; - *sal_reason=SalReasonDoNotDisturb; - break; - case 603: - *sal_err=SalErrorFailure; - *sal_reason=SalReasonDeclined; - break; - default: - if (code>0){ - *sal_err=SalErrorFailure; - *sal_reason=SalReasonUnknown; - }else *sal_err=SalErrorNoResponse; - /* no break */ - } + *sal_reason=SalReasonUnknown; + }else *sal_err=SalErrorNoResponse; + /* no break */ + } } /*return TRUE if error code*/ bool_t sal_compute_sal_errors(belle_sip_response_t* response,SalError* sal_err,SalReason* sal_reason,char* reason, size_t reason_size) { @@ -415,4 +452,35 @@ const char *sal_op_get_remote_contact(const SalOp *op){ return sal_custom_header_find(op->base.recv_custom_headers,"Contact"); } +void sal_op_add_body(SalOp *op, belle_sip_message_t *req, const SalBody *body){ + if (body && body->type && body->subtype && body->data){ + belle_sip_message_add_header((belle_sip_message_t*)req, + (belle_sip_header_t*)belle_sip_header_content_type_create(body->type,body->subtype)); + belle_sip_message_add_header((belle_sip_message_t*)req, + (belle_sip_header_t*)belle_sip_header_content_length_create(body->size)); + belle_sip_message_set_body((belle_sip_message_t*)req,(const char*)body->data,body->size); + } +} + +bool_t sal_op_get_body(SalOp *op, belle_sip_message_t *msg, SalBody *salbody){ + const char *body = NULL; + belle_sip_header_content_type_t *content_type; + belle_sip_header_content_length_t *clen=NULL; + + content_type=belle_sip_message_get_header_by_type(msg,belle_sip_header_content_type_t); + if (content_type){ + body=belle_sip_message_get_body(msg); + clen=belle_sip_message_get_header_by_type(msg,belle_sip_header_content_length_t); + } + + if (content_type && body && clen) { + salbody->type=belle_sip_header_content_type_get_type(content_type); + salbody->subtype=belle_sip_header_content_type_get_subtype(content_type); + salbody->data=body; + salbody->size=belle_sip_header_content_length_get_content_length(clen); + return TRUE; + } + memset(salbody,0,sizeof(salbody)); + return FALSE; +} diff --git a/coreapi/bellesip_sal/sal_op_info.c b/coreapi/bellesip_sal/sal_op_info.c index a86328fbb..c3f600aaa 100644 --- a/coreapi/bellesip_sal/sal_op_info.c +++ b/coreapi/bellesip_sal/sal_op_info.c @@ -31,23 +31,10 @@ static void process_request_event(void *op_base, const belle_sip_request_event_t SalOp* op = (SalOp*)op_base; belle_sip_request_t* req = belle_sip_request_event_get_request(event); belle_sip_server_transaction_t* server_transaction = belle_sip_provider_create_server_transaction(op->base.root->prov,req); - belle_sip_header_content_type_t* content_type; - belle_sip_header_content_length_t *clen=NULL; belle_sip_response_t* resp; SalBody salbody; - const char *body = NULL; - content_type=belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req),belle_sip_header_content_type_t); - if (content_type){ - body=belle_sip_message_get_body(BELLE_SIP_MESSAGE(req)); - clen=belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req),belle_sip_header_content_length_t); - } - - if (content_type && body && clen) { - salbody.type=belle_sip_header_content_type_get_type(content_type); - salbody.subtype=belle_sip_header_content_type_get_subtype(content_type); - salbody.data=body; - salbody.size=belle_sip_header_content_length_get_content_length(clen); + if (sal_op_get_body(op,(belle_sip_message_t*)req,&salbody)) { op->base.root->callbacks.info_received(op,&salbody); } else { op->base.root->callbacks.info_received(op,NULL); @@ -60,13 +47,7 @@ static void process_request_event(void *op_base, const belle_sip_request_event_t int sal_send_info(SalOp *op, const char *from, const char *to, const SalBody *body){ belle_sip_request_t *req=sal_op_build_request(op,"INFO"); sal_op_info_fill_cbs(op); - if (body && body->type && body->subtype && body->data){ - belle_sip_message_add_header((belle_sip_message_t*)req, - (belle_sip_header_t*)belle_sip_header_content_type_create(body->type,body->subtype)); - belle_sip_message_add_header((belle_sip_message_t*)req, - (belle_sip_header_t*)belle_sip_header_content_length_create(body->size)); - belle_sip_message_set_body((belle_sip_message_t*)req,(const char*)body->data,body->size); - } + sal_op_add_body(op,(belle_sip_message_t*)req,body); return sal_op_send_request(op,req); } diff --git a/coreapi/bellesip_sal/sal_op_message.c b/coreapi/bellesip_sal/sal_op_message.c index 08eef45c7..140dbe85f 100644 --- a/coreapi/bellesip_sal/sal_op_message.c +++ b/coreapi/bellesip_sal/sal_op_message.c @@ -149,6 +149,7 @@ int sal_message_send(SalOp *op, const char *from, const char *to, const char* co return sal_op_send_request(op,req); } + int sal_text_send(SalOp *op, const char *from, const char *to, const char *msg) { return sal_message_send(op,from,to,"text/plain",msg); } diff --git a/coreapi/bellesip_sal/sal_op_presence.c b/coreapi/bellesip_sal/sal_op_presence.c index 8d800ef9d..b68ef1f33 100644 --- a/coreapi/bellesip_sal/sal_op_presence.c +++ b/coreapi/bellesip_sal/sal_op_presence.c @@ -424,6 +424,7 @@ static void presence_response_event(void *op_base, const belle_sip_response_even SalError error=SalErrorUnknown; SalReason sr=SalReasonUnknown; belle_sip_header_expires_t* expires; + if (sal_compute_sal_errors(response,&error,&sr,reason, sizeof(reason))) { ms_error("subscription to [%s] rejected reason [%s]",sal_op_get_to(op),reason[0]!=0?reason:sal_reason_to_string(sr)); op->base.root->callbacks.notify_presence(op,SalSubscribeTerminated, SalPresenceOffline,NULL); @@ -436,9 +437,7 @@ static void presence_response_event(void *op_base, const belle_sip_response_even } dialog_state=belle_sip_dialog_get_state(op->dialog); - - switch(dialog_state) { - + switch(dialog_state) { case BELLE_SIP_DIALOG_NULL: case BELLE_SIP_DIALOG_EARLY: { ms_error("presence op [%p] receive an unexpected answer [%i]",op,code); @@ -450,6 +449,7 @@ static void presence_response_event(void *op_base, const belle_sip_response_even if(op->refresher) { belle_sip_refresher_stop(op->refresher); belle_sip_object_unref(op->refresher); + op->refresher=NULL; } if (expires>0){ op->refresher=belle_sip_client_transaction_create_refresher(client_transaction); @@ -475,9 +475,11 @@ static void presence_response_event(void *op_base, const belle_sip_response_even static void presence_process_timeout(void *user_ctx, const belle_sip_timeout_event_t *event) { ms_error("presence_process_timeout not implemented yet"); } + static void presence_process_transaction_terminated(void *user_ctx, const belle_sip_transaction_terminated_event_t *event) { ms_message("presence_process_transaction_terminated not implemented yet"); } + static void presence_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)); @@ -504,7 +506,7 @@ static void presence_process_request_event(void *op_base, const belle_sip_reques switch(dialog_state) { case BELLE_SIP_DIALOG_NULL: { - op->base.root->callbacks.subscribe_received(op,sal_op_get_from(op)); + op->base.root->callbacks.subscribe_presence_received(op,sal_op_get_from(op)); break; } case BELLE_SIP_DIALOG_EARLY: @@ -553,7 +555,7 @@ static void presence_process_request_event(void *op_base, const belle_sip_reques } else if (strcmp("SUBSCRIBE",belle_sip_request_get_method(req))==0) { /*either a refresh of an unsubscribe*/ if (expires && belle_sip_header_expires_get_expires(expires)>0) { - op->base.root->callbacks.subscribe_received(op,sal_op_get_from(op)); + op->base.root->callbacks.subscribe_presence_received(op,sal_op_get_from(op)); } else if(expires) { ms_message("Unsubscribe received from [%s]",sal_op_get_from(op)); resp=sal_op_create_response_from_request(op,req,200); @@ -566,9 +568,8 @@ static void presence_process_request_event(void *op_base, const belle_sip_reques } /* no break */ } - - } + void sal_op_presence_fill_cbs(SalOp*op) { op->callbacks.process_io_error=presence_process_io_error; op->callbacks.process_response_event=presence_response_event; @@ -597,29 +598,7 @@ int sal_subscribe_presence(SalOp *op, const char *from, const char *to){ return sal_op_send_request(op,req); } -int sal_unsubscribe(SalOp *op){ - belle_sip_request_t* req=op->dialog?belle_sip_dialog_create_request(op->dialog,"SUBSCRIBE"):NULL; /*cannot create request if dialog not set yet*/ - if (!req) { - ms_error("Cannot unsubscribe to [%s]",sal_op_get_to(op)); - return -1; - } - belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),belle_sip_header_create("Event","presence")); - belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(belle_sip_header_expires_create(0))); - return sal_op_send_request(op,req); -} -int sal_subscribe_accept(SalOp *op){ - belle_sip_request_t* req=belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(op->pending_server_trans)); - belle_sip_header_expires_t* expires = belle_sip_message_get_header_by_type(req,belle_sip_header_expires_t); - belle_sip_response_t* resp = sal_op_create_response_from_request(op,req,200); - belle_sip_message_add_header(BELLE_SIP_MESSAGE(resp),BELLE_SIP_HEADER(expires)); - belle_sip_server_transaction_send_response(op->pending_server_trans,resp); - return 0; -} -int sal_subscribe_decline(SalOp *op){ - belle_sip_response_t* resp = belle_sip_response_create_from_request(belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(op->pending_server_trans)),403); - belle_sip_server_transaction_send_response(op->pending_server_trans,resp); - return 0; -} + static belle_sip_request_t *create_presence_notify(SalOp *op){ belle_sip_request_t* notify=belle_sip_dialog_create_request(op->dialog,"NOTIFY"); @@ -635,7 +614,7 @@ int sal_notify_presence(SalOp *op, SalPresenceStatus status, const char *status_ return sal_op_send_request(op,notify); } -int sal_notify_close(SalOp *op){ +int sal_notify_presence_close(SalOp *op){ belle_sip_request_t* notify=create_presence_notify(op); sal_add_presence_info(BELLE_SIP_MESSAGE(notify),SalPresenceOffline); /*FIXME, what about expires ??*/ belle_sip_message_add_header(BELLE_SIP_MESSAGE(notify) diff --git a/coreapi/bellesip_sal/sal_op_publish.c b/coreapi/bellesip_sal/sal_op_publish.c index 29d78cd72..cf9dc8f54 100644 --- a/coreapi/bellesip_sal/sal_op_publish.c +++ b/coreapi/bellesip_sal/sal_op_publish.c @@ -30,7 +30,7 @@ static void publish_refresher_listener ( const belle_sip_refresher_t* refresher } /*presence publish */ -int sal_publish(SalOp *op, const char *from, const char *to, SalPresenceStatus status){ +int sal_publish_presence(SalOp *op, const char *from, const char *to, SalPresenceStatus status){ belle_sip_request_t *req=NULL; if(!op->refresher || !belle_sip_refresher_get_transaction(op->refresher)) { if (from) @@ -53,3 +53,27 @@ int sal_publish(SalOp *op, const char *from, const char *to, SalPresenceStatus s } } +int sal_publish(SalOp *op, const char *from, const char *to, const char *eventname, int expires, const SalBody *body){ + belle_sip_request_t *req=NULL; + if(!op->refresher || !belle_sip_refresher_get_transaction(op->refresher)) { + if (from) + sal_op_set_from(op,from); + if (to) + sal_op_set_to(op,to); + + op->type=SalOpPublish; + req=sal_op_build_request(op,"PUBLISH"); + belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),belle_sip_header_create("Event",eventname)); + if (body) sal_op_add_body(op,BELLE_SIP_MESSAGE(req),body); + return sal_op_send_and_create_refresher(op,req,expires,publish_refresher_listener); + } else { + /*update status*/ + const belle_sip_client_transaction_t* last_publish_trans=belle_sip_refresher_get_transaction(op->refresher); + belle_sip_request_t* last_publish=belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(last_publish_trans)); + /*update body*/ + if (body) sal_op_add_body(op,BELLE_SIP_MESSAGE(last_publish),body); + return belle_sip_refresher_refresh(op->refresher,BELLE_SIP_REFRESHER_REUSE_EXPIRES); + } +} + + diff --git a/coreapi/callbacks.c b/coreapi/callbacks.c index 35ae87a24..1fe12bd1a 100644 --- a/coreapi/callbacks.c +++ b/coreapi/callbacks.c @@ -872,25 +872,17 @@ static void text_received(SalOp *op, const SalMessage *msg){ } } -static void notify(SalOp *op, const char *from, const char *msg){ - LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op)); - LinphoneCall *call=(LinphoneCall*)sal_op_get_user_pointer (op); - ms_message("get a %s notify from %s",msg,from); - if(lc->vtable.notify_recv) - lc->vtable.notify_recv(lc,call,from,msg); -} - static void notify_presence(SalOp *op, SalSubscribeStatus ss, SalPresenceStatus status, const char *msg){ LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op)); linphone_notify_recv(lc,op,ss,status); } -static void subscribe_received(SalOp *op, const char *from){ +static void subscribe_presence_received(SalOp *op, const char *from){ LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op)); linphone_subscription_new(lc,op,from); } -static void subscribe_closed(SalOp *op, const char *from){ +static void subscribe_presence_closed(SalOp *op, const char *from){ LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op)); linphone_subscription_closed(lc,op); } @@ -1008,6 +1000,62 @@ static void info_received(SalOp *op, const SalBody *body){ linphone_core_notify_info_message(lc,op,body); } +static void subscribe_response(SalOp *op, SalSubscribeStatus status, SalError error, SalReason reason){ + LinphoneEvent *lev=(LinphoneEvent*)sal_op_get_user_pointer(op); + + if (lev==NULL) return; + + if (status==SalSubscribeActive){ + linphone_event_set_state(lev,LinphoneSubscriptionActive); + }else if (status==SalSubscribePending){ + linphone_event_set_state(lev,LinphoneSubscriptionPending); + }else{ + linphone_event_set_reason(lev, linphone_reason_from_sal(reason)); + linphone_event_set_state(lev,LinphoneSubscriptionError); + linphone_event_destroy(lev); + } +} + +static void notify(SalOp *op, SalSubscribeStatus st, const char *eventname, const SalBody *body){ + LinphoneEvent *lev=(LinphoneEvent*)sal_op_get_user_pointer(op); + LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op)); + LinphoneContent content; + + if (lev==NULL) { + /*out of subscribe notify */ + lev=linphone_event_new_with_op(lc,op,LinphoneSubscriptionOutgoing); + } + if (lc->vtable.notify_received){ + lc->vtable.notify_received(lc,lev,eventname,linphone_content_from_sal_body(&content,body)); + } + if (st!=SalSubscribeNone){ + linphone_event_set_state(lev,linphone_subscription_state_from_sal(st)); + if (st==SalSubscribeTerminated) + linphone_event_destroy(lev); + } + +} + +static void subscribe_received(SalOp *op, const char *eventname, const SalBody *body){ + LinphoneEvent *lev=(LinphoneEvent*)sal_op_get_user_pointer(op); + LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op)); + + if (lev==NULL) { + lev=linphone_event_new_with_op(lc,op,LinphoneSubscriptionIncoming); + linphone_event_set_state(lev,LinphoneSubscriptionIncomingReceived); + }else{ + /*subscribe refresh, unhandled*/ + } + +} + +static void subscribe_closed(SalOp *op){ + LinphoneEvent *lev=(LinphoneEvent*)sal_op_get_user_pointer(op); + + linphone_event_set_state(lev,LinphoneSubscriptionTerminated); + linphone_event_destroy(lev); +} + SalCallbacks linphone_sal_callbacks={ call_received, call_ringing, @@ -1030,11 +1078,14 @@ SalCallbacks linphone_sal_callbacks={ refer_received, text_received, text_delivery_update, - notify, - notify_presence, notify_refer, subscribe_received, subscribe_closed, + subscribe_response, + notify, + subscribe_presence_received, + subscribe_presence_closed, + notify_presence, ping_reply, auth_requested, info_received diff --git a/coreapi/event.c b/coreapi/event.c new file mode 100644 index 000000000..d3a774fb1 --- /dev/null +++ b/coreapi/event.c @@ -0,0 +1,178 @@ +/* +linphone +Copyright (C) 2000 - 2010 Simon MORLAT (simon.morlat@linphone.org) + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "private.h" + + +struct _LinphoneEvent{ + LinphoneSubscriptionDir dir; + LinphoneCore *lc; + SalOp *op; + LinphoneSubscriptionState state; + LinphoneReason reason; + void *userdata; +}; + +LinphoneSubscriptionState linphone_subscription_state_from_sal(SalSubscribeStatus ss){ + switch(ss){ + case SalSubscribeNone: return LinphoneSubscriptionNone; + case SalSubscribePending: return LinphoneSubscriptionPending; + case SalSubscribeTerminated: return LinphoneSubscriptionTerminated; + case SalSubscribeActive: return LinphoneSubscriptionActive; + } + return LinphoneSubscriptionNone; +} + +LinphoneEvent *linphone_event_new(LinphoneCore *lc, LinphoneSubscriptionDir dir){ + LinphoneEvent *lev=ms_new0(LinphoneEvent,1); + lev->lc=lc; + lev->dir=dir; + lev->op=sal_op_new(lc->sal); + sal_op_set_user_pointer(lev->op,lev); + return lev; +} + +LinphoneEvent *linphone_event_new_with_op(LinphoneCore *lc, SalOp *op, LinphoneSubscriptionDir dir){ + LinphoneEvent *lev=ms_new0(LinphoneEvent,1); + lev->lc=lc; + lev->dir=LinphoneSubscriptionIncoming; + lev->op=op; + sal_op_set_user_pointer(lev->op,lev); + return lev; +} + +void linphone_event_set_state(LinphoneEvent *lev, LinphoneSubscriptionState state){ + LinphoneCore *lc=lev->lc; + if (lev->state!=state){ + lev->state=state; + if (lc->vtable.subscription_state_changed){ + lc->vtable.subscription_state_changed(lev->lc,lev,state); + } + } +} + +void linphone_event_set_reason(LinphoneEvent *lev, LinphoneReason reason){ + lev->reason=reason; +} + +LinphoneReason linphone_event_get_reason(const LinphoneEvent *lev){ + return lev->reason; +} + +LinphoneEvent *linphone_core_subscribe(LinphoneCore *lc, const LinphoneAddress *resource, const char *event, int expires, const LinphoneContent *body){ + LinphoneEvent *lev=linphone_event_new(lc, LinphoneSubscriptionOutgoing); + SalBody salbody; + linphone_configure_op(lc,lev->op,resource,NULL,TRUE); + sal_subscribe(lev->op,NULL,NULL,event,expires,sal_body_from_content(&salbody,body)); + linphone_event_set_state(lev,LinphoneSubscriptionOutoingInit); + return lev; +} + + +int linphone_event_update_subscribe(LinphoneEvent *lev, const LinphoneContent *body){ + SalBody salbody; + if (lev->state!=LinphoneSubscriptionActive){ + ms_error("linphone_event_update_subscribe(): cannot update subscription if subscription wasn't accepted."); + return -1; + } + if (lev->dir!=LinphoneSubscriptionOutgoing){ + ms_error("linphone_event_deny_subscription(): cannot update an incoming subscription."); + return -1; + } + return sal_subscribe(lev->op,NULL,NULL,NULL,-1,sal_body_from_content(&salbody,body)); +} + +int linphone_event_accept_subscription(LinphoneEvent *lev){ + int err; + if (lev->state!=LinphoneSubscriptionIncomingReceived){ + ms_error("linphone_event_accept_subscription(): cannot accept subscription if subscription wasn't just received."); + return -1; + } + err=sal_subscribe_accept(lev->op); + if (err==0){ + linphone_event_set_state(lev,LinphoneSubscriptionActive); + } + return err; +} + +int linphone_event_deny_subscription(LinphoneEvent *lev, LinphoneReason reason){ + if (lev->state!=LinphoneSubscriptionIncomingReceived){ + ms_error("linphone_event_deny_subscription(): cannot deny subscription if subscription wasn't just received."); + return -1; + } + return sal_subscribe_decline(lev->op,linphone_reason_to_sal(reason)); +} + +int linphone_event_notify(LinphoneEvent *lev, const LinphoneContent *body){ + SalBody salbody; + if (lev->state!=LinphoneSubscriptionActive){ + ms_error("linphone_event_notify(): cannot notify if subscription is not active."); + return -1; + } + if (lev->dir!=LinphoneSubscriptionIncoming){ + ms_error("linphone_event_notify(): cannot notify if not an incoming subscription."); + return -1; + } + return sal_notify(lev->op,sal_body_from_content(&salbody,body)); +} + +LinphoneEvent *linphone_core_publish(LinphoneCore *lc, const LinphoneAddress *resource, const char *event, int expires, const LinphoneContent *body){ + SalBody salbody; + LinphoneEvent *lev=linphone_event_new(lc,LinphoneSubscriptionInvalidDir); + linphone_configure_op(lc,lev->op,resource,NULL,FALSE); + sal_publish(lev->op,NULL,NULL,event,expires,sal_body_from_content(&salbody,body)); + return lev; +} + + +int linphone_event_update_publish(LinphoneEvent *lev, const LinphoneContent *body){ + SalBody salbody; + return sal_publish(lev->op,NULL,NULL,NULL,-1,sal_body_from_content(&salbody,body)); +} + +void linphone_event_set_user_pointer(LinphoneEvent *ev, void *up){ + ev->userdata=up; +} + +void *linphone_event_get_user_pointer(const LinphoneEvent *ev){ + return ev->userdata; +} + +void linphone_event_terminate(LinphoneEvent *lev){ + if (lev->dir==LinphoneSubscriptionIncoming){ + sal_notify_close(lev->op); + }else if (lev->dir==LinphoneSubscriptionOutgoing){ + sal_unsubscribe(lev->op); + } + + if (lev->state!=LinphoneSubscriptionNone){ + linphone_event_set_state(lev,LinphoneSubscriptionTerminated); + } + linphone_event_destroy(lev); +} + +void linphone_event_destroy(LinphoneEvent *lev){ + if (lev->op) + sal_op_release(lev->op); + ms_free(lev); +} + +LinphoneSubscriptionDir linphone_event_get_dir(LinphoneEvent *lev){ + return lev->dir; +} diff --git a/coreapi/event.h b/coreapi/event.h index 68417a846..aa87a42cc 100644 --- a/coreapi/event.h +++ b/coreapi/event.h @@ -19,6 +19,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #ifndef LINPHONEEVENT_H #define LINPHONEEVENT_H +/** + * @addtogroup subscriptions + * @{ +**/ + struct _LinphoneEvent; typedef struct _LinphoneEvent LinphoneEvent; @@ -28,13 +33,14 @@ typedef struct _LinphoneEvent LinphoneEvent; **/ enum _LinphoneSubscriptionDir{ LinphoneSubscriptionIncoming, - LinphoneSubscriptionOutgoing + LinphoneSubscriptionOutgoing, + LinphoneSubscriptionInvalidDir }; /** * Typedef alias for _LinphoneSubscriptionDir **/ -typedef _LinphoneSubscriptionDir LinphoneSubscriptionDir; +typedef enum _LinphoneSubscriptionDir LinphoneSubscriptionDir; /** * Enum for subscription states. @@ -49,7 +55,7 @@ enum _LinphoneSubscriptionState{ LinphoneSubscriptionError /**insub){ - sal_notify_close(lf->insub); + sal_notify_presence_close(lf->insub); } } diff --git a/coreapi/info.c b/coreapi/info.c index 961fa0b04..11ec0b7fd 100644 --- a/coreapi/info.c +++ b/coreapi/info.c @@ -58,13 +58,13 @@ static void linphone_content_copy(LinphoneContent *obj, const LinphoneContent *r obj->size=ref->size; } -static void linphone_content_uninit(LinphoneContent * obj){ +void linphone_content_uninit(LinphoneContent * obj){ if (obj->type) ms_free(obj->type); if (obj->subtype) ms_free(obj->subtype); if (obj->data) ms_free(obj->data); } -static LinphoneContent *linphone_content_copy_from_sal_body(LinphoneContent *obj, const SalBody *ref){ +LinphoneContent *linphone_content_copy_from_sal_body(LinphoneContent *obj, const SalBody *ref){ SET_STRING(obj,type,ref->type); SET_STRING(obj,subtype,ref->subtype); if (obj->data) { @@ -80,7 +80,17 @@ static LinphoneContent *linphone_content_copy_from_sal_body(LinphoneContent *obj return obj; } -static SalBody *sal_body_from_content(SalBody *body, const LinphoneContent *lc){ +const LinphoneContent *linphone_content_from_sal_body(LinphoneContent *obj, const SalBody *ref){ + if (ref && ref->type){ + obj->type=(char*)ref->type; + obj->subtype=(char*)ref->subtype; + obj->data=(void*)ref->data; + obj->size=ref->size; + } + return NULL; +} + +SalBody *sal_body_from_content(SalBody *body, const LinphoneContent *lc){ if (lc->type){ body->type=lc->type; body->subtype=lc->subtype; diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index b420dbd3c..f90124fd0 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -5655,6 +5655,10 @@ const char *linphone_reason_to_string(LinphoneReason err){ return "Not answered"; case LinphoneReasonBusy: return "Busy"; + case LinphoneReasonMedia: + return "Incompatible media capabilities"; + case LinphoneReasonIOError: + return "IO error"; } return "unknown error"; } diff --git a/coreapi/linphonecore.h b/coreapi/linphonecore.h index e363192ac..5cbffe51c 100644 --- a/coreapi/linphonecore.h +++ b/coreapi/linphonecore.h @@ -91,10 +91,58 @@ typedef struct _LCSipTransports{ * @var LinphoneAddress */ typedef struct SalAddress LinphoneAddress; + +/** + * The LinphoneContent struct holds data that can be embedded in a signaling message. + * @ingroup misc +**/ +struct _LinphoneContent{ + char *type; /**subscribers,uri,&lf)){ if (lf->pol==LinphoneSPDeny){ ms_message("Rejecting %s because we already rejected it once.",from); - sal_subscribe_decline(op); + sal_subscribe_decline(op,SalReasonDeclined); } else { /* else it is in wait for approval state, because otherwise it is in the friend list.*/ diff --git a/coreapi/private.h b/coreapi/private.h index 6afc16c4b..a93bcec47 100644 --- a/coreapi/private.h +++ b/coreapi/private.h @@ -742,6 +742,17 @@ const char *linphone_core_create_uuid(LinphoneCore *lc); void linphone_configure_op(LinphoneCore *lc, SalOp *op, const LinphoneAddress *dest, SalCustomHeader *headers, bool_t with_contact); void linphone_call_create_op(LinphoneCall *call); void linphone_core_notify_info_message(LinphoneCore* lc,SalOp *op, const SalBody *body); +LinphoneContent *linphone_content_copy_from_sal_body(LinphoneContent *obj, const SalBody *ref); +SalBody *sal_body_from_content(SalBody *body, const LinphoneContent *lc); +SalReason linphone_reason_to_sal(LinphoneReason reason); +LinphoneReason linphone_reason_from_sal(SalReason reason); +LinphoneEvent *linphone_event_new(LinphoneCore *lc, LinphoneSubscriptionDir dir); +LinphoneEvent *linphone_event_new_with_op(LinphoneCore *lc, SalOp *op, LinphoneSubscriptionDir dir); +void linphone_event_destroy(LinphoneEvent *lev); +void linphone_event_set_state(LinphoneEvent *lev, LinphoneSubscriptionState state); +void linphone_event_set_reason(LinphoneEvent *lev, LinphoneReason reason); +LinphoneSubscriptionState linphone_subscription_state_from_sal(SalSubscribeStatus ss); +const LinphoneContent *linphone_content_from_sal_body(LinphoneContent *obj, const SalBody *ref); #ifdef __cplusplus } diff --git a/coreapi/proxy.c b/coreapi/proxy.c index 253922713..b5d613f5f 100644 --- a/coreapi/proxy.c +++ b/coreapi/proxy.c @@ -858,7 +858,7 @@ int linphone_proxy_config_send_publish(LinphoneProxyConfig *proxy, sal_op_set_from(proxy->publish_op,linphone_proxy_config_get_identity(proxy)); sal_op_set_to(proxy->publish_op,linphone_proxy_config_get_identity(proxy)); } - err=sal_publish(proxy->publish_op,NULL,NULL,linphone_online_status_to_sal(presence_mode)); + err=sal_publish_presence(proxy->publish_op,NULL,NULL,linphone_online_status_to_sal(presence_mode)); return err; } diff --git a/include/sal/sal.h b/include/sal/sal.h index 9759f2931..d3efc5722 100644 --- a/include/sal/sal.h +++ b/include/sal/sal.h @@ -255,6 +255,7 @@ typedef struct SalOpBase{ typedef enum SalError{ + SalErrorNone, SalErrorNoResponse, SalErrorProtocol, SalErrorFailure, /* see SalReason for more details */ @@ -298,6 +299,8 @@ typedef enum SalReferStatus{ }SalReferStatus; typedef enum SalSubscribeStatus{ + SalSubscribeNone, + SalSubscribePending, SalSubscribeActive, SalSubscribeTerminated }SalSubscribeStatus; @@ -345,11 +348,14 @@ typedef void (*SalOnDtmfReceived)(SalOp *op, char dtmf); typedef void (*SalOnRefer)(Sal *sal, SalOp *op, const char *referto); typedef void (*SalOnTextReceived)(SalOp *op, const SalMessage *msg); typedef void (*SalOnTextDeliveryUpdate)(SalOp *op, SalTextDeliveryStatus status); -typedef void (*SalOnNotify)(SalOp *op, const char *from, const char *event); typedef void (*SalOnNotifyRefer)(SalOp *op, SalReferStatus state); +typedef void (*SalOnSubscribeResponse)(SalOp *op, SalSubscribeStatus status, SalError error, SalReason reason); +typedef void (*SalOnNotify)(SalOp *op, SalSubscribeStatus status, const char *event, const SalBody *body); +typedef void (*SalOnSubscribeReceived)(SalOp *salop, const char *event, const SalBody *body); +typedef void (*SalOnSubscribeClosed)(SalOp *salop); typedef void (*SalOnNotifyPresence)(SalOp *op, SalSubscribeStatus ss, SalPresenceStatus status, const char *msg); -typedef void (*SalOnSubscribeReceived)(SalOp *salop, const char *from); -typedef void (*SalOnSubscribeClosed)(SalOp *salop, const char *from); +typedef void (*SalOnSubscribePresenceReceived)(SalOp *salop, const char *from); +typedef void (*SalOnSubscribePresenceClosed)(SalOp *salop, const char *from); typedef void (*SalOnPingReply)(SalOp *salop); typedef void (*SalOnInfoReceived)(SalOp *salop, const SalBody *body); /*allows sal implementation to access auth info if available, return TRUE if found*/ @@ -378,11 +384,14 @@ typedef struct SalCallbacks{ SalOnRefer refer_received; SalOnTextReceived text_received; SalOnTextDeliveryUpdate text_delivery_update; - SalOnNotify notify; - SalOnNotifyPresence notify_presence; SalOnNotifyRefer notify_refer; SalOnSubscribeReceived subscribe_received; SalOnSubscribeClosed subscribe_closed; + SalOnSubscribeResponse subscribe_response; + SalOnNotify notify; + SalOnSubscribePresenceReceived subscribe_presence_received; + SalOnSubscribePresenceClosed subscribe_presence_closed; + SalOnNotifyPresence notify_presence; SalOnPingReply ping_reply; SalOnAuthRequested auth_requested; SalOnInfoReceived info_received; @@ -516,14 +525,11 @@ int sal_message_send(SalOp *op, const char *from, const char *to, const char* co /*presence Subscribe/notify*/ int sal_subscribe_presence(SalOp *op, const char *from, const char *to); -int sal_unsubscribe(SalOp *op); -int sal_subscribe_accept(SalOp *op); -int sal_subscribe_decline(SalOp *op); int sal_notify_presence(SalOp *op, SalPresenceStatus status, const char *status_message); -int sal_notify_close(SalOp *op); +int sal_notify_presence_close(SalOp *op); /*presence publish */ -int sal_publish(SalOp *op, const char *from, const char *to, SalPresenceStatus status); +int sal_publish_presence(SalOp *op, const char *from, const char *to, SalPresenceStatus status); /*ping: main purpose is to obtain its own contact address behind firewalls*/ @@ -532,6 +538,14 @@ int sal_ping(SalOp *op, const char *from, const char *to); /*info messages*/ int sal_send_info(SalOp *op, const char *from, const char *to, const SalBody *body); +/*generic subscribe/notify/publish api*/ +int sal_subscribe(SalOp *op, const char *from, const char *to, const char *eventname, int expires, const SalBody *body); +int sal_unsubscribe(SalOp *op); +int sal_subscribe_accept(SalOp *op); +int sal_subscribe_decline(SalOp *op, SalReason reason); +int sal_notify(SalOp *op, const SalBody *body); +int sal_notify_close(SalOp *op); +int sal_publish(SalOp *op, const char *from, const char *to, const char*event_name, int expires, const SalBody *body); #define payload_type_set_number(pt,n) (pt)->user_data=(void*)((long)n); diff --git a/mediastreamer2 b/mediastreamer2 index 5b7873ee3..dd0116eb8 160000 --- a/mediastreamer2 +++ b/mediastreamer2 @@ -1 +1 @@ -Subproject commit 5b7873ee3cbc460138015ba244330d99aa861d7f +Subproject commit dd0116eb8e26f128a2366b38115b602def4b4073 diff --git a/tester/Makefile.am b/tester/Makefile.am index 6b5e9edae..25ac64865 100644 --- a/tester/Makefile.am +++ b/tester/Makefile.am @@ -6,7 +6,14 @@ if BUILD_CUNIT_TESTS noinst_PROGRAMS=liblinphone_tester TESTS=$(noinst_PROGRAMS) -liblinphone_tester_SOURCES= liblinphone_tester.c setup_tester.c register_tester.c message_tester.c call_tester.c presence_tester.c upnp_tester.c +liblinphone_tester_SOURCES= liblinphone_tester.c \ + setup_tester.c \ + register_tester.c \ + message_tester.c \ + call_tester.c \ + presence_tester.c \ + upnp_tester.c \ + eventapi_tester.c #liblinphone_tester_CFLAGS=$(CUNIT_CFLAGS) diff --git a/tester/eventapi_tester.c b/tester/eventapi_tester.c new file mode 100644 index 000000000..c132abd65 --- /dev/null +++ b/tester/eventapi_tester.c @@ -0,0 +1,108 @@ +/* + belle-sip - SIP (RFC3261) library. + Copyright (C) 2010 Belledonne Communications SARL + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include +#include "CUnit/Basic.h" +#include "linphonecore.h" +#include "private.h" +#include +#include "liblinphone_tester.h" + + +static const char *subscribe_content="blabla"; +static const char *notify_content="blabla"; + +void linphone_notify_received(LinphoneCore *lc, LinphoneEvent *lev, const char *eventname, const LinphoneContent *content){ +} + +void linphone_subscription_state_change(LinphoneCore *lc, LinphoneEvent *lev, LinphoneSubscriptionState state) { + stats* counters = (stats*)linphone_core_get_user_data(lc); + LinphoneContent content; + + content.type="application"; + content.subtype="somexml2"; + content.data=(void*)notify_content; + content.size=strlen(notify_content); + + switch(state){ + case LinphoneSubscriptionNone: + break; + case LinphoneSubscriptionIncomingReceived: + counters->number_of_LinphoneSubscriptionIncomingReceived++; + linphone_event_accept_subscription(lev); + break; + case LinphoneSubscriptionOutoingInit: + counters->number_of_LinphoneSubscriptionOutgoingInit++; + break; + case LinphoneSubscriptionPending: + counters->number_of_LinphoneSubscriptionPending++; + break; + case LinphoneSubscriptionActive: + counters->number_of_LinphoneSubscriptionActive++; + if (linphone_event_get_dir(lev)==LinphoneSubscriptionIncoming) + linphone_event_notify(lev,&content); + break; + case LinphoneSubscriptionTerminated: + counters->number_of_LinphoneSubscriptionTerminated++; + break; + case LinphoneSubscriptionError: + counters->number_of_LinphoneSubscriptionError++; + break; + } +} + + + + + +static void subscribe_test() { + LinphoneCoreManager* marie = linphone_core_manager_new(liblinphone_tester_file_prefix, "marie_rc"); + LinphoneCoreManager* pauline = linphone_core_manager_new(liblinphone_tester_file_prefix, "pauline_rc"); + LinphoneContent content; + MSList* lcs=ms_list_append(NULL,marie->lc); + lcs=ms_list_append(lcs,pauline->lc); + + content.type="application"; + content.subtype="somexml"; + content.data=(char*)subscribe_content; + content.size=strlen(subscribe_content); + + linphone_core_subscribe(marie->lc,pauline->identity,"dodo",600,&content); + + CU_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneSubscriptionOutgoingInit,1,1000)); + CU_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneSubscriptionIncomingReceived,1,1000)); + CU_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneSubscriptionActive,1,1000)); + CU_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneSubscriptionActive,1,1000)); + + + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline); +} + +test_t subscribe_tests[] = { + { "Subscribe", subscribe_test }, +}; + +test_suite_t subscribe_test_suite = { + "Subscribe", + NULL, + NULL, + sizeof(subscribe_tests) / sizeof(subscribe_tests[0]), + subscribe_tests +}; + diff --git a/tester/liblinphone_tester.c b/tester/liblinphone_tester.c index 40cf3df09..f71b29345 100644 --- a/tester/liblinphone_tester.c +++ b/tester/liblinphone_tester.c @@ -192,6 +192,8 @@ LinphoneCoreManager* linphone_core_manager_new2(const char* path, const char* rc mgr->v_table.notify_presence_recv=notify_presence_received; mgr->v_table.transfer_state_changed=linphone_transfer_state_changed; mgr->v_table.info_received=info_message_received; + mgr->v_table.subscription_state_changed=linphone_subscription_state_change; + mgr->v_table.notify_received=linphone_notify_received; mgr->lc=configure_lc_from(&mgr->v_table, path, rc_file, check_for_proxies?(rc_file?1:0):0); enable_codec(mgr->lc,"PCMU",8000); linphone_core_set_user_data(mgr->lc,&mgr->stat); @@ -297,6 +299,7 @@ void liblinphone_tester_init(void) { #ifdef UPNP add_test_suite(&upnp_test_suite); #endif + add_test_suite(&subscribe_test_suite); } void liblinphone_tester_uninit(void) { diff --git a/tester/liblinphone_tester.h b/tester/liblinphone_tester.h index 7aa3cebb9..9e8eb6f24 100644 --- a/tester/liblinphone_tester.h +++ b/tester/liblinphone_tester.h @@ -51,6 +51,7 @@ extern test_suite_t call_test_suite; extern test_suite_t message_test_suite; extern test_suite_t presence_test_suite; extern test_suite_t upnp_test_suite; +extern test_suite_t subscribe_test_suite; extern int liblinphone_tester_nb_test_suites(void); @@ -137,6 +138,12 @@ typedef struct _stats { int number_of_inforeceived; int number_of_inforeceived_with_body; + int number_of_LinphoneSubscriptionIncomingReceived; + int number_of_LinphoneSubscriptionOutgoingInit; + int number_of_LinphoneSubscriptionPending; + int number_of_LinphoneSubscriptionActive; + int number_of_LinphoneSubscriptionTerminated; + int number_of_LinphoneSubscriptionError; }stats; @@ -162,6 +169,8 @@ void message_received(LinphoneCore *lc, LinphoneChatRoom *room, LinphoneChatMess void info_message_received(LinphoneCore *lc, const LinphoneInfoMessage *msg); void new_subscribtion_request(LinphoneCore *lc, LinphoneFriend *lf, const char *url); void auth_info_requested(LinphoneCore *lc, const char *realm, const char *username); +void linphone_subscription_state_change(LinphoneCore *lc, LinphoneEvent *ev, LinphoneSubscriptionState state); +void linphone_notify_received(LinphoneCore *lc, LinphoneEvent *lev, const char *eventname, const LinphoneContent *content); LinphoneCore* create_lc_with_auth(unsigned int with_auth) ; LinphoneAddress * create_linphone_address(const char * domain); From c1c4ff6e0acbee350810d99401c5e73067cdbdcb Mon Sep 17 00:00:00 2001 From: Ghislain MARY Date: Thu, 6 Jun 2013 15:32:22 +0200 Subject: [PATCH 2/7] Add missing exports. --- coreapi/linphonecore.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/coreapi/linphonecore.h b/coreapi/linphonecore.h index c8494434f..c5df3eadb 100644 --- a/coreapi/linphonecore.h +++ b/coreapi/linphonecore.h @@ -1403,11 +1403,11 @@ int linphone_core_set_static_picture_fps(LinphoneCore *lc, float fps); float linphone_core_get_static_picture_fps(LinphoneCore *lc); /*function to be used for eventually setting window decorations (icons, title...)*/ -unsigned long linphone_core_get_native_video_window_id(const LinphoneCore *lc); -void linphone_core_set_native_video_window_id(LinphoneCore *lc, unsigned long id); +LINPHONE_PUBLIC unsigned long linphone_core_get_native_video_window_id(const LinphoneCore *lc); +LINPHONE_PUBLIC void linphone_core_set_native_video_window_id(LinphoneCore *lc, unsigned long id); -unsigned long linphone_core_get_native_preview_window_id(const LinphoneCore *lc); -void linphone_core_set_native_preview_window_id(LinphoneCore *lc, unsigned long id); +LINPHONE_PUBLIC unsigned long linphone_core_get_native_preview_window_id(const LinphoneCore *lc); +LINPHONE_PUBLIC void linphone_core_set_native_preview_window_id(LinphoneCore *lc, unsigned long id); void linphone_core_use_preview_window(LinphoneCore *lc, bool_t yesno); int linphone_core_get_device_rotation(LinphoneCore *lc ); @@ -1422,7 +1422,7 @@ void linphone_core_set_device_rotation(LinphoneCore *lc, int rotation); * @param lc The linphone core related to the operation * @return The camera sensor rotation in degrees (0 to 360) or -1 if it could not be retrieved */ -int linphone_core_get_camera_sensor_rotation(LinphoneCore *lc); +LINPHONE_PUBLIC int linphone_core_get_camera_sensor_rotation(LinphoneCore *lc); /* start or stop streaming video in case of embedded window */ void linphone_core_show_video(LinphoneCore *lc, bool_t show); From 01f746a4b22bc57d7ecc16774e8e22e5f3571588 Mon Sep 17 00:00:00 2001 From: Ghislain MARY Date: Thu, 6 Jun 2013 15:41:22 +0200 Subject: [PATCH 3/7] Add missing files to compile in the Visual Studio project. --- build/vsx/LibLinphone/LibLinphone.vcxproj | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/build/vsx/LibLinphone/LibLinphone.vcxproj b/build/vsx/LibLinphone/LibLinphone.vcxproj index 693f6c9c7..f7f456fa3 100644 --- a/build/vsx/LibLinphone/LibLinphone.vcxproj +++ b/build/vsx/LibLinphone/LibLinphone.vcxproj @@ -176,6 +176,7 @@ + @@ -188,6 +189,7 @@ + @@ -209,6 +211,7 @@ + @@ -237,9 +240,6 @@ {d22bd217-d0f8-4274-9b3a-f3f35f46482c} - - {0565952a-ea62-46a2-8261-f5b4b490da42} - {ffc7b532-0502-4d88-ac98-9e89071cbc97} false @@ -268,4 +268,4 @@ - + \ No newline at end of file From 5183b2176146d09a83148e1736215dbe48bbb44f Mon Sep 17 00:00:00 2001 From: Simon Morlat Date: Thu, 6 Jun 2013 21:01:01 +0200 Subject: [PATCH 4/7] change info api so that INFO message can only be sent through calls (as requested by the RFC) --- coreapi/bellesip_sal/sal_impl.c | 6 +-- coreapi/bellesip_sal/sal_impl.h | 4 -- coreapi/bellesip_sal/sal_op_call.c | 19 ++++++-- coreapi/bellesip_sal/sal_op_events.c | 1 + coreapi/bellesip_sal/sal_op_info.c | 42 +++-------------- coreapi/event.c | 5 +- coreapi/info.c | 44 +++++++----------- coreapi/linphonecore.h | 28 +++++------ tester/call_tester.c | 11 +++-- tester/eventapi_tester.c | 69 ++++++++++++++++++++++++---- tester/liblinphone_tester.c | 20 ++++++-- tester/liblinphone_tester.h | 7 ++- tester/message_tester.c | 18 +++++--- tester/presence_tester.c | 4 +- tester/register_tester.c | 38 +++++++-------- 15 files changed, 179 insertions(+), 137 deletions(-) diff --git a/coreapi/bellesip_sal/sal_impl.c b/coreapi/bellesip_sal/sal_impl.c index 6f7fe2124..641884964 100644 --- a/coreapi/bellesip_sal/sal_impl.c +++ b/coreapi/bellesip_sal/sal_impl.c @@ -167,9 +167,9 @@ static void process_request_event(void *sal, const belle_sip_request_event_t *ev belle_sip_provider_send_response(((Sal*)sal)->prov,resp); return; }else if (strcmp("INFO",belle_sip_request_get_method(req))==0) { - op=sal_op_new((Sal*)sal); - op->dir=SalOpDirIncoming; - sal_op_info_fill_cbs(op); + resp=belle_sip_response_create_from_request(req,481);/*INFO out of call dialogs are not allowed*/ + belle_sip_provider_send_response(((Sal*)sal)->prov,resp); + return; }else { ms_error("sal process_request_event not implemented yet for method [%s]",belle_sip_request_get_method(req)); resp=belle_sip_response_create_from_request(req,501); diff --git a/coreapi/bellesip_sal/sal_impl.h b/coreapi/bellesip_sal/sal_impl.h index 0b3e7ae24..ef4db521d 100644 --- a/coreapi/bellesip_sal/sal_impl.h +++ b/coreapi/bellesip_sal/sal_impl.h @@ -66,7 +66,6 @@ typedef enum SalOpType { SalOpMessage, SalOpPresence, SalOpPublish, - SalOpInfo, SalOpSubscribe }SalOpType_t; const char* sal_op_type_to_string(const SalOpType_t type); @@ -125,9 +124,6 @@ void sal_op_presence_fill_cbs(SalOp*op); /*messaging*/ void sal_op_message_fill_cbs(SalOp*op); -/*info*/ -void sal_op_info_fill_cbs(SalOp*op); - void sal_op_subscribe_fill_cbs(SalOp*op); /*call transfer*/ diff --git a/coreapi/bellesip_sal/sal_op_call.c b/coreapi/bellesip_sal/sal_op_call.c index dd7ede609..f9cb812fe 100644 --- a/coreapi/bellesip_sal/sal_op_call.c +++ b/coreapi/bellesip_sal/sal_op_call.c @@ -192,6 +192,7 @@ static void cancelling_invite(SalOp* op ){ sal_op_send_request(op,cancel); op->state=SalOpStateTerminating; } + 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; @@ -438,7 +439,7 @@ static void process_request_event(void *op_base, const belle_sip_request_event_t resp=sal_op_create_response_from_request(op,req,200); belle_sip_server_transaction_send_response(server_transaction,resp); } else { - belle_sip_error("Unexpected method [%s] for dialog state BELLE_SIP_DIALOG_EARLY"); + belle_sip_error("Unexpected method [%s] for dialog state BELLE_SIP_DIALOG_EARLY",belle_sip_request_get_method(req)); unsupported_method(server_transaction,req); } break; @@ -480,8 +481,8 @@ static void process_request_event(void *op_base, const belle_sip_request_event_t process_sdp_for_invite(op,req); op->base.root->callbacks.call_updating(op); - } else if (strcmp("INFO",belle_sip_request_get_method(req))==0 - && belle_sip_message_get_body(BELLE_SIP_MESSAGE(req)) + } else if (strcmp("INFO",belle_sip_request_get_method(req))==0){ + if (belle_sip_message_get_body(BELLE_SIP_MESSAGE(req)) && strstr(belle_sip_message_get_body(BELLE_SIP_MESSAGE(req)),"picture_fast_update")) { /*vfu request*/ ms_message("Receiving VFU request on op [%p]",op); @@ -489,8 +490,16 @@ static void process_request_event(void *op_base, const belle_sip_request_event_t op->base.root->callbacks.vfu_request(op); } - resp=sal_op_create_response_from_request(op,req,200); - belle_sip_server_transaction_send_response(server_transaction,resp); + }else{ + SalBody salbody; + if (sal_op_get_body(op,(belle_sip_message_t*)req,&salbody)) { + op->base.root->callbacks.info_received(op,&salbody); + } else { + op->base.root->callbacks.info_received(op,NULL); + } + } + resp=sal_op_create_response_from_request(op,req,200); + belle_sip_server_transaction_send_response(server_transaction,resp); }else if (strcmp("REFER",belle_sip_request_get_method(req))==0) { sal_op_process_refer(op,event); } else if (strcmp("NOTIFY",belle_sip_request_get_method(req))==0) { diff --git a/coreapi/bellesip_sal/sal_op_events.c b/coreapi/bellesip_sal/sal_op_events.c index 4923f2269..952c58a6a 100644 --- a/coreapi/bellesip_sal/sal_op_events.c +++ b/coreapi/bellesip_sal/sal_op_events.c @@ -85,6 +85,7 @@ static void subscribe_response_event(void *op_base, const belle_sip_response_eve if (expires>0){ op->refresher=belle_sip_client_transaction_create_refresher(client_transaction); } + if (sss==SalSubscribeNone) sss=SalSubscribeActive; /*without Subscription-state header, consider subscription is accepted.*/ op->base.root->callbacks.subscribe_response(op,sss,SalErrorNone,SalReasonUnknown); } break; diff --git a/coreapi/bellesip_sal/sal_op_info.c b/coreapi/bellesip_sal/sal_op_info.c index c3f600aaa..3b329515f 100644 --- a/coreapi/bellesip_sal/sal_op_info.c +++ b/coreapi/bellesip_sal/sal_op_info.c @@ -18,43 +18,13 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "sal_impl.h" -static void process_io_error(void *user_ctx, const belle_sip_io_error_event_t *event){ -} - -static void process_timeout(void *user_ctx, const belle_sip_timeout_event_t *event) { -} - -static void process_response_event(void *op_base, const belle_sip_response_event_t *event){ -} - -static void process_request_event(void *op_base, const belle_sip_request_event_t *event) { - SalOp* op = (SalOp*)op_base; - belle_sip_request_t* req = belle_sip_request_event_get_request(event); - belle_sip_server_transaction_t* server_transaction = belle_sip_provider_create_server_transaction(op->base.root->prov,req); - belle_sip_response_t* resp; - SalBody salbody; - - if (sal_op_get_body(op,(belle_sip_message_t*)req,&salbody)) { - op->base.root->callbacks.info_received(op,&salbody); - } else { - op->base.root->callbacks.info_received(op,NULL); - } - resp = belle_sip_response_create_from_request(req,200); - belle_sip_server_transaction_send_response(server_transaction,resp); - sal_op_release(op); -} int sal_send_info(SalOp *op, const char *from, const char *to, const SalBody *body){ - belle_sip_request_t *req=sal_op_build_request(op,"INFO"); - sal_op_info_fill_cbs(op); - sal_op_add_body(op,(belle_sip_message_t*)req,body); - return sal_op_send_request(op,req); + if (op->dialog){ + belle_sip_request_t *req=belle_sip_dialog_create_request(op->dialog,"INFO"); + sal_op_add_body(op,(belle_sip_message_t*)req,body); + return sal_op_send_request(op,req); + } + return -1; } -void sal_op_info_fill_cbs(SalOp*op) { - op->callbacks.process_io_error=process_io_error; - op->callbacks.process_response_event=process_response_event; - op->callbacks.process_timeout=process_timeout; - op->callbacks.process_request_event=process_request_event; - op->type=SalOpInfo; -} diff --git a/coreapi/event.c b/coreapi/event.c index d3a774fb1..3d350b578 100644 --- a/coreapi/event.c +++ b/coreapi/event.c @@ -112,11 +112,14 @@ int linphone_event_accept_subscription(LinphoneEvent *lev){ } int linphone_event_deny_subscription(LinphoneEvent *lev, LinphoneReason reason){ + int err; if (lev->state!=LinphoneSubscriptionIncomingReceived){ ms_error("linphone_event_deny_subscription(): cannot deny subscription if subscription wasn't just received."); return -1; } - return sal_subscribe_decline(lev->op,linphone_reason_to_sal(reason)); + err=sal_subscribe_decline(lev->op,linphone_reason_to_sal(reason)); + linphone_event_set_state(lev,LinphoneSubscriptionTerminated); + return err; } int linphone_event_notify(LinphoneEvent *lev, const LinphoneContent *body){ diff --git a/coreapi/info.c b/coreapi/info.c index 11ec0b7fd..6d92a0db8 100644 --- a/coreapi/info.c +++ b/coreapi/info.c @@ -30,7 +30,6 @@ struct _LinphoneInfoMessage{ LinphoneContent content; - SalOp *op; SalCustomHeader *headers; }; @@ -105,8 +104,6 @@ SalBody *sal_body_from_content(SalBody *body, const LinphoneContent *lc){ * Destroy a LinphoneInfoMessage **/ void linphone_info_message_destroy(LinphoneInfoMessage *im){ - /* FIXME: op is leaked. If we release it now, there is a high risk that the request won't be resent with authentication*/ - /*if (im->op) sal_op_release(im->op);*/ linphone_content_uninit(&im->content); sal_custom_header_free(im->headers); ms_free(im); @@ -117,13 +114,12 @@ LinphoneInfoMessage *linphone_info_message_copy(const LinphoneInfoMessage *orig) LinphoneInfoMessage *im=ms_new0(LinphoneInfoMessage,1); linphone_content_copy(&im->content,&orig->content); if (orig->headers) im->headers=sal_custom_header_clone(orig->headers); - if (orig->op) im->op=sal_op_ref(orig->op); return im; } /** * Creates an empty info message. - * @param lc the LinphoneCore object. + * @param lc the LinphoneCore * @return a new LinphoneInfoMessage. * * The info message can later be filled with information using linphone_info_message_add_header() or linphone_info_message_set_content(), @@ -131,20 +127,18 @@ LinphoneInfoMessage *linphone_info_message_copy(const LinphoneInfoMessage *orig) **/ LinphoneInfoMessage *linphone_core_create_info_message(LinphoneCore *lc){ LinphoneInfoMessage *im=ms_new0(LinphoneInfoMessage,1); - im->op=sal_op_new(lc->sal); return im; } /** - * Send a LinphoneInfoMessage to a specified address. - * @param lc the LinphoneCore + * Send a LinphoneInfoMessage through an established call + * @param call the call * @param info the info message - * @param addr the destination address **/ -int linphone_core_send_info_message(LinphoneCore *lc, const LinphoneInfoMessage *info, const LinphoneAddress *addr){ +int linphone_call_send_info_message(LinphoneCall *call, const LinphoneInfoMessage *info){ SalBody body; - linphone_configure_op(lc,info->op,addr,info->headers,FALSE); - return sal_send_info(info->op,NULL, NULL, sal_body_from_content(&body,&info->content)); + sal_op_set_sent_custom_header(call->op,info->headers); + return sal_send_info(call->op,NULL, NULL, sal_body_from_content(&body,&info->content)); } /** @@ -164,15 +158,7 @@ void linphone_info_message_add_header(LinphoneInfoMessage *im, const char *name, * @return the corresponding header's value, or NULL if not exists. **/ const char *linphone_info_message_get_header(const LinphoneInfoMessage *im, const char *name){ - const SalCustomHeader *ch=sal_op_get_recv_custom_header(im->op); - return sal_custom_header_find(ch,name); -} - -/** - * Returns origin of received LinphoneInfoMessage -**/ -const char *linphone_info_message_get_from(const LinphoneInfoMessage *im){ - return sal_op_get_from(im->op); + return sal_custom_header_find(im->headers,name); } /** @@ -193,11 +179,13 @@ const LinphoneContent * linphone_info_message_get_content(const LinphoneInfoMess } void linphone_core_notify_info_message(LinphoneCore* lc,SalOp *op, const SalBody *body){ - LinphoneInfoMessage *info=ms_new0(LinphoneInfoMessage,1); - info->op=sal_op_ref(op); - info->headers=sal_custom_header_clone(sal_op_get_recv_custom_header(op)); - if (body) linphone_content_copy_from_sal_body(&info->content,body); - if (lc->vtable.info_received) - lc->vtable.info_received(lc,info); - linphone_info_message_destroy(info); + LinphoneCall *call=(LinphoneCall*)sal_op_get_user_pointer(op); + if (call){ + LinphoneInfoMessage *info=ms_new0(LinphoneInfoMessage,1); + info->headers=sal_custom_header_clone(sal_op_get_recv_custom_header(op)); + if (body) linphone_content_copy_from_sal_body(&info->content,body); + if (lc->vtable.info_received) + lc->vtable.info_received(lc,call,info); + linphone_info_message_destroy(info); + } } diff --git a/coreapi/linphonecore.h b/coreapi/linphonecore.h index c5df3eadb..b148e1f3e 100644 --- a/coreapi/linphonecore.h +++ b/coreapi/linphonecore.h @@ -109,6 +109,17 @@ struct _LinphoneContent{ **/ typedef struct _LinphoneContent LinphoneContent; +/** + * The LinphoneCall object represents a call issued or received by the LinphoneCore + * @ingroup call_control +**/ +struct _LinphoneCall; +/** + * The LinphoneCall object represents a call issued or received by the LinphoneCore + * @ingroup call_control +**/ +typedef struct _LinphoneCall LinphoneCall; + /** * Enum describing failure reasons. * @ingroup misc @@ -277,8 +288,8 @@ struct _LinphoneInfoMessage; **/ typedef struct _LinphoneInfoMessage LinphoneInfoMessage; -LINPHONE_PUBLIC LinphoneInfoMessage *linphone_core_create_info_message(LinphoneCore *lc); -LINPHONE_PUBLIC int linphone_core_send_info_message(LinphoneCore *lc, const LinphoneInfoMessage *info, const LinphoneAddress *addr); +LINPHONE_PUBLIC LinphoneInfoMessage *linphone_core_create_info_message(LinphoneCore*lc); +LINPHONE_PUBLIC int linphone_call_send_info_message(struct _LinphoneCall *call, const LinphoneInfoMessage *info); LINPHONE_PUBLIC void linphone_info_message_add_header(LinphoneInfoMessage *im, const char *name, const char *value); LINPHONE_PUBLIC const char *linphone_info_message_get_header(const LinphoneInfoMessage *im, const char *name); LINPHONE_PUBLIC void linphone_info_message_set_content(LinphoneInfoMessage *im, const LinphoneContent *content); @@ -305,16 +316,7 @@ struct _LinphoneVideoPolicy{ **/ typedef struct _LinphoneVideoPolicy LinphoneVideoPolicy; -/** - * The LinphoneCall object represents a call issued or received by the LinphoneCore - * @ingroup call_control -**/ -struct _LinphoneCall; -/** - * The LinphoneCall object represents a call issued or received by the LinphoneCore - * @ingroup call_control -**/ -typedef struct _LinphoneCall LinphoneCall; + /** @@ -872,7 +874,7 @@ typedef void (*LinphoneTransferStateChanged)(struct _LinphoneCore *lc, LinphoneC typedef void (*CallStatsUpdated)(struct _LinphoneCore *lc, LinphoneCall *call, const LinphoneCallStats *stats); /** Callback prototype for receiving info messages*/ -typedef void (*LinphoneInfoReceivedCb)(struct _LinphoneCore *lc, const LinphoneInfoMessage *msg); +typedef void (*LinphoneInfoReceivedCb)(struct _LinphoneCore *lc, LinphoneCall *call, const LinphoneInfoMessage *msg); /** * This structure holds all callbacks that the application should implement. * None is mandatory. diff --git a/tester/call_tester.c b/tester/call_tester.c index a5d05e0e4..32f43d9f4 100644 --- a/tester/call_tester.c +++ b/tester/call_tester.c @@ -34,7 +34,7 @@ void call_state_changed(LinphoneCore *lc, LinphoneCall *call, LinphoneCallState ,linphone_call_state_to_string(cstate)); ms_free(to); ms_free(from); - counters = (stats*)linphone_core_get_user_data(lc); + counters = get_stats(lc); switch (cstate) { case LinphoneCallIncomingReceived:counters->number_of_LinphoneCallIncomingReceived++;break; case LinphoneCallOutgoingInit :counters->number_of_LinphoneCallOutgoingInit++;break; @@ -67,7 +67,7 @@ void linphone_transfer_state_changed(LinphoneCore *lc, LinphoneCall *transfered, ms_free(to); ms_free(from); - counters = (stats*)linphone_core_get_user_data(lc); + counters = get_stats(lc); switch (new_call_state) { case LinphoneCallOutgoingInit :counters->number_of_LinphoneTransferCallOutgoingInit++;break; case LinphoneCallOutgoingProgress :counters->number_of_LinphoneTransferCallOutgoingProgress++;break; @@ -88,7 +88,7 @@ static void linphone_call_cb(LinphoneCall *call,void * user_data) { ms_message("call from [%s] to [%s] receive iFrame",from,to); ms_free(to); ms_free(from); - counters = (stats*)linphone_core_get_user_data(lc); + counters = (stats*)get_stats(lc); counters->number_of_IframeDecoded++; } @@ -444,8 +444,11 @@ static void call_with_ice(void) { CU_ASSERT_TRUE(call(pauline,marie)); CU_ASSERT_TRUE(check_ice(pauline,marie,LinphoneIceStateHostConnection)); + /*wait for the ICE reINVITE to complete*/ + CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallStreamsRunning,2)); + CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneCallStreamsRunning,2)); - /*just to sleep*/ + /*then close the call*/ linphone_core_terminate_all_calls(pauline->lc); CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallEnd,1)); CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneCallEnd,1)); diff --git a/tester/eventapi_tester.c b/tester/eventapi_tester.c index c132abd65..9b156771d 100644 --- a/tester/eventapi_tester.c +++ b/tester/eventapi_tester.c @@ -31,7 +31,8 @@ void linphone_notify_received(LinphoneCore *lc, LinphoneEvent *lev, const char * } void linphone_subscription_state_change(LinphoneCore *lc, LinphoneEvent *lev, LinphoneSubscriptionState state) { - stats* counters = (stats*)linphone_core_get_user_data(lc); + stats* counters = get_stats(lc); + LinphoneCoreManager *mgr=get_manager(lc); LinphoneContent content; content.type="application"; @@ -44,7 +45,10 @@ void linphone_subscription_state_change(LinphoneCore *lc, LinphoneEvent *lev, Li break; case LinphoneSubscriptionIncomingReceived: counters->number_of_LinphoneSubscriptionIncomingReceived++; - linphone_event_accept_subscription(lev); + if (!mgr->decline_subscribe) + linphone_event_accept_subscription(lev); + else + linphone_event_deny_subscription(lev, LinphoneReasonDeclined); break; case LinphoneSubscriptionOutoingInit: counters->number_of_LinphoneSubscriptionOutgoingInit++; @@ -54,48 +58,95 @@ void linphone_subscription_state_change(LinphoneCore *lc, LinphoneEvent *lev, Li break; case LinphoneSubscriptionActive: counters->number_of_LinphoneSubscriptionActive++; - if (linphone_event_get_dir(lev)==LinphoneSubscriptionIncoming) + if (linphone_event_get_dir(lev)==LinphoneSubscriptionIncoming){ + mgr->lev=lev; linphone_event_notify(lev,&content); + } break; case LinphoneSubscriptionTerminated: counters->number_of_LinphoneSubscriptionTerminated++; + mgr->lev=NULL; break; case LinphoneSubscriptionError: counters->number_of_LinphoneSubscriptionError++; + mgr->lev=NULL; break; } } - - - - -static void subscribe_test() { +static void subscribe_test_declined(void) { LinphoneCoreManager* marie = linphone_core_manager_new(liblinphone_tester_file_prefix, "marie_rc"); LinphoneCoreManager* pauline = linphone_core_manager_new(liblinphone_tester_file_prefix, "pauline_rc"); LinphoneContent content; MSList* lcs=ms_list_append(NULL,marie->lc); lcs=ms_list_append(lcs,pauline->lc); + content.type="application"; content.subtype="somexml"; content.data=(char*)subscribe_content; content.size=strlen(subscribe_content); + pauline->decline_subscribe=TRUE; + linphone_core_subscribe(marie->lc,pauline->identity,"dodo",600,&content); + CU_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneSubscriptionOutgoingInit,1,1000)); + CU_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneSubscriptionIncomingReceived,1,1000)); + CU_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneSubscriptionError,1,1000)); + CU_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneSubscriptionTerminated,1,1000)); + + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline); +} + + +static void subscribe_test_with_args(bool_t terminated_by_subscriber) { + LinphoneCoreManager* marie = linphone_core_manager_new(liblinphone_tester_file_prefix, "marie_rc"); + LinphoneCoreManager* pauline = linphone_core_manager_new(liblinphone_tester_file_prefix, "pauline_rc"); + LinphoneContent content; + LinphoneEvent *lev; + MSList* lcs=ms_list_append(NULL,marie->lc); + lcs=ms_list_append(lcs,pauline->lc); + + + content.type="application"; + content.subtype="somexml"; + content.data=(char*)subscribe_content; + content.size=strlen(subscribe_content); + + lev=linphone_core_subscribe(marie->lc,pauline->identity,"dodo",600,&content); + CU_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneSubscriptionOutgoingInit,1,1000)); CU_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneSubscriptionIncomingReceived,1,1000)); CU_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneSubscriptionActive,1,1000)); CU_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneSubscriptionActive,1,1000)); + if (terminated_by_subscriber){ + linphone_event_terminate(lev); + }else{ + linphone_event_terminate(pauline->lev); + } + + CU_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneSubscriptionTerminated,1,1000)); + CU_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneSubscriptionTerminated,1,1000)); linphone_core_manager_destroy(marie); linphone_core_manager_destroy(pauline); } +static void subscribe_test_terminated_by_subscriber(void){ + subscribe_test_with_args(TRUE); +} + +static void subscribe_test_terminated_by_notifier(void){ + subscribe_test_with_args(FALSE); +} + test_t subscribe_tests[] = { - { "Subscribe", subscribe_test }, + { "Subscribe declined" , subscribe_test_declined }, + { "Subscribe terminated by subscriber", subscribe_test_terminated_by_subscriber }, + { "Subscribe terminated by notifier", subscribe_test_terminated_by_notifier } }; test_suite_t subscribe_test_suite = { diff --git a/tester/liblinphone_tester.c b/tester/liblinphone_tester.c index f71b29345..05ea483d8 100644 --- a/tester/liblinphone_tester.c +++ b/tester/liblinphone_tester.c @@ -75,7 +75,7 @@ void auth_info_requested(LinphoneCore *lc, const char *realm, const char *userna ms_message("Auth info requested for user id [%s] at realm [%s]\n" ,username ,realm); - counters = (stats*)linphone_core_get_user_data(lc); + counters = get_stats(lc); counters->number_of_auth_info_requested++; 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*/ @@ -116,7 +116,7 @@ LinphoneCore* configure_lc_from(LinphoneCoreVTable* v_table, const char* path, c sprintf(filepath, "%s/%s", path, file); lc = linphone_core_new(v_table,NULL,filepath,NULL); linphone_core_set_user_data(lc,&global_stat); - counters = (stats*)linphone_core_get_user_data(lc); + counters = get_stats(lc); /* until we have good certificates on our test server... linphone_core_verify_server_certificates(lc,FALSE);*/ @@ -180,8 +180,18 @@ static void enable_codec(LinphoneCore* lc,const char* type,int rate) { ms_list_free(codecs); } +stats * get_stats(LinphoneCore *lc){ + LinphoneCoreManager *manager=(LinphoneCoreManager *)linphone_core_get_user_data(lc); + return &manager->stat; +} + +LinphoneCoreManager *get_manager(LinphoneCore *lc){ + LinphoneCoreManager *manager=(LinphoneCoreManager *)linphone_core_get_user_data(lc); + return manager; +} + LinphoneCoreManager* linphone_core_manager_new2(const char* path, const char* rc_file, int check_for_proxies) { - LinphoneCoreManager* mgr= malloc(sizeof(LinphoneCoreManager)); + LinphoneCoreManager* mgr= ms_new0(LinphoneCoreManager,1); LinphoneProxyConfig* proxy; memset (mgr,0,sizeof(LinphoneCoreManager)); mgr->v_table.registration_state_changed=registration_state_changed; @@ -196,7 +206,7 @@ LinphoneCoreManager* linphone_core_manager_new2(const char* path, const char* rc mgr->v_table.notify_received=linphone_notify_received; mgr->lc=configure_lc_from(&mgr->v_table, path, rc_file, check_for_proxies?(rc_file?1:0):0); enable_codec(mgr->lc,"PCMU",8000); - linphone_core_set_user_data(mgr->lc,&mgr->stat); + linphone_core_set_user_data(mgr->lc,mgr); linphone_core_get_default_proxy(mgr->lc,&proxy); if (proxy) { mgr->identity = linphone_address_new(linphone_proxy_config_get_identity(proxy)); @@ -212,7 +222,7 @@ LinphoneCoreManager* linphone_core_manager_new(const char* path, const char* rc_ void linphone_core_manager_destroy(LinphoneCoreManager* mgr) { if (mgr->lc) linphone_core_destroy(mgr->lc); if (mgr->identity) linphone_address_destroy(mgr->identity); - free(mgr); + ms_free(mgr); } diff --git a/tester/liblinphone_tester.h b/tester/liblinphone_tester.h index 9e8eb6f24..8a751d622 100644 --- a/tester/liblinphone_tester.h +++ b/tester/liblinphone_tester.h @@ -152,6 +152,8 @@ typedef struct _LinphoneCoreManager { LinphoneCore* lc; stats stat; LinphoneAddress* identity; + LinphoneEvent *lev; + bool_t decline_subscribe; } LinphoneCoreManager; LinphoneCoreManager* linphone_core_manager_new2(const char* path, const char* rc_file, int check_for_proxies); @@ -166,7 +168,7 @@ void linphone_transfer_state_changed(LinphoneCore *lc, LinphoneCall *transfered, void notify_presence_received(LinphoneCore *lc, LinphoneFriend * lf); void text_message_received(LinphoneCore *lc, LinphoneChatRoom *room, const LinphoneAddress *from_address, const char *message); void message_received(LinphoneCore *lc, LinphoneChatRoom *room, LinphoneChatMessage* message); -void info_message_received(LinphoneCore *lc, const LinphoneInfoMessage *msg); +void info_message_received(LinphoneCore *lc, LinphoneCall *call, const LinphoneInfoMessage *msg); void new_subscribtion_request(LinphoneCore *lc, LinphoneFriend *lf, const char *url); void auth_info_requested(LinphoneCore *lc, const char *realm, const char *username); void linphone_subscription_state_change(LinphoneCore *lc, LinphoneEvent *ev, LinphoneSubscriptionState state); @@ -179,5 +181,8 @@ bool_t wait_for(LinphoneCore* lc_1, LinphoneCore* lc_2,int* counter,int value); bool_t wait_for_list(MSList* lcs,int* counter,int value,int timeout_ms); bool_t call(LinphoneCoreManager* caller_mgr,LinphoneCoreManager* callee_mgr); +stats * get_stats(LinphoneCore *lc); +LinphoneCoreManager *get_manager(LinphoneCore *lc); + #endif /* LIBLINPHONE_TESTER_H_ */ diff --git a/tester/message_tester.c b/tester/message_tester.c index a9beef3ed..7d2b1ea7e 100644 --- a/tester/message_tester.c +++ b/tester/message_tester.c @@ -24,7 +24,7 @@ void text_message_received(LinphoneCore *lc, LinphoneChatRoom *room, const LinphoneAddress *from_address, const char *message) { - stats* counters = (stats*)linphone_core_get_user_data(lc); + stats* counters = get_stats(lc); counters->number_of_LinphoneMessageReceivedLegacy++; } @@ -35,7 +35,7 @@ void message_received(LinphoneCore *lc, LinphoneChatRoom *room, LinphoneChatMess ,linphone_chat_message_get_text(message) ,linphone_chat_message_get_external_body_url(message)); ms_free(from); - counters = (stats*)linphone_core_get_user_data(lc); + counters = get_stats(lc); counters->number_of_LinphoneMessageReceived++; if (linphone_chat_message_get_external_body_url(message)) counters->number_of_LinphoneMessageExtBodyReceived++; @@ -43,7 +43,7 @@ void message_received(LinphoneCore *lc, LinphoneChatRoom *room, LinphoneChatMess void linphone_chat_message_state_change(LinphoneChatMessage* msg,LinphoneChatMessageState state,void* ud) { LinphoneCore* lc=(LinphoneCore*)ud; - stats* counters = (stats*)linphone_core_get_user_data(lc); + stats* counters = get_stats(lc); ms_message("Message [%s] [%s]",linphone_chat_message_get_text(msg),linphone_chat_message_state_to_string(state)); switch (state) { case LinphoneChatMessageStateDelivered: @@ -163,8 +163,8 @@ static void text_message_with_send_error(void) { static const char *info_content="blabla"; -void info_message_received(LinphoneCore *lc, const LinphoneInfoMessage *msg){ - stats* counters = (stats*)linphone_core_get_user_data(lc); +void info_message_received(LinphoneCore *lc, LinphoneCall* call, const LinphoneInfoMessage *msg){ + stats* counters = get_stats(lc); const char *hvalue=linphone_info_message_get_header(msg, "Weather"); const LinphoneContent *content=linphone_info_message_get_content(msg); CU_ASSERT_PTR_NOT_NULL_FATAL(hvalue); @@ -189,7 +189,11 @@ void info_message_received(LinphoneCore *lc, const LinphoneInfoMessage *msg){ static void info_message_with_args(bool_t with_content) { LinphoneCoreManager* marie = linphone_core_manager_new(liblinphone_tester_file_prefix, "marie_rc"); LinphoneCoreManager* pauline = linphone_core_manager_new(liblinphone_tester_file_prefix, "pauline_rc"); - LinphoneInfoMessage *info=linphone_core_create_info_message(marie->lc); + LinphoneInfoMessage *info; + + CU_ASSERT_TRUE(call(pauline,marie)); + + info=linphone_core_create_info_message(marie->lc); linphone_info_message_add_header(info,"Weather","still bad"); if (with_content) { LinphoneContent ct; @@ -199,7 +203,7 @@ static void info_message_with_args(bool_t with_content) { ct.size=strlen(info_content); linphone_info_message_set_content(info,&ct); } - linphone_core_send_info_message(marie->lc,info,pauline->identity); + linphone_call_send_info_message(linphone_core_get_current_call(marie->lc),info); linphone_info_message_destroy(info); if (with_content){ diff --git a/tester/presence_tester.c b/tester/presence_tester.c index bc9bf24bd..18308f13e 100644 --- a/tester/presence_tester.c +++ b/tester/presence_tester.c @@ -36,7 +36,7 @@ void new_subscribtion_request(LinphoneCore *lc, LinphoneFriend *lf, const char * stats* counters; ms_message("New subscription request from [%s] url [%s]",from,url); ms_free(from); - counters = (stats*)linphone_core_get_user_data(lc); + counters = get_stats(lc); counters->number_of_NewSubscriptionRequest++; linphone_core_add_friend(lc,lf); /*accept subscription*/ } @@ -46,7 +46,7 @@ void notify_presence_received(LinphoneCore *lc, LinphoneFriend * lf) { char* from=linphone_address_as_string(linphone_friend_get_address(lf)); ms_message("New Notify request from [%s] ",from); ms_free(from); - counters = (stats*)linphone_core_get_user_data(lc); + counters = get_stats(lc); counters->number_of_NotifyReceived++; switch(linphone_friend_get_status(lf)) { diff --git a/tester/register_tester.c b/tester/register_tester.c index 16916df2c..2ca84945b 100644 --- a/tester/register_tester.c +++ b/tester/register_tester.c @@ -34,7 +34,7 @@ void registration_state_changed(struct _LinphoneCore *lc, LinphoneProxyConfig *c ,linphone_registration_state_to_string(cstate) ,linphone_proxy_config_get_identity(cfg) ,linphone_proxy_config_get_addr(cfg)); - counters = (stats*)linphone_core_get_user_data(lc); + counters = get_stats(lc); switch (cstate) { case LinphoneRegistrationNone:counters->number_of_LinphoneRegistrationNone++;break; case LinphoneRegistrationProgress:counters->number_of_LinphoneRegistrationProgress++;break; @@ -58,7 +58,7 @@ static void register_with_refresh_base_2(LinphoneCore* lc, bool_t refresh,const CU_ASSERT_PTR_NOT_NULL(lc); if (!lc) return; - counters = (stats*)linphone_core_get_user_data(lc); + counters = get_stats(lc); reset_counters(counters); linphone_core_set_sip_transports(lc,&transport); @@ -106,7 +106,7 @@ static void register_with_refresh_base(LinphoneCore* lc, bool_t refresh,const ch } static void register_with_refresh(LinphoneCore* lc, bool_t refresh,const char* domain,const char* route) { - stats* counters = (stats*)linphone_core_get_user_data(lc); + stats* counters = get_stats(lc); register_with_refresh_base(lc,refresh,domain,route); linphone_core_destroy(lc); CU_ASSERT_EQUAL(counters->number_of_LinphoneRegistrationCleared,1); @@ -117,7 +117,7 @@ static void register_with_refresh(LinphoneCore* lc, bool_t refresh,const char* d static void register_with_refresh_with_send_error() { int retry=0; LinphoneCore* lc = create_lc_with_auth(1); - stats* counters = (stats*)linphone_core_get_user_data(lc); + stats* counters = get_stats(lc); LinphoneAuthInfo *info=linphone_auth_info_new(test_username,NULL,test_password,NULL,auth_domain); /*create authentication structure from identity*/ char route[256]; sprintf(route,"sip:%s",test_route); @@ -140,7 +140,7 @@ static void register_with_refresh_with_send_error() { static void simple_register(){ LinphoneCore* lc = create_lc(); - stats* counters = (stats*)linphone_core_get_user_data(lc); + stats* counters = get_stats(lc); register_with_refresh(lc,FALSE,NULL,NULL); CU_ASSERT_EQUAL(counters->number_of_auth_info_requested,0); } @@ -148,14 +148,14 @@ static void simple_register(){ /*take care of min expires configuration from server*/ static void simple_register_with_refresh() { LinphoneCore* lc = create_lc(); - stats* counters = (stats*)linphone_core_get_user_data(lc); + stats* counters = get_stats(lc); register_with_refresh(lc,TRUE,NULL,NULL); CU_ASSERT_EQUAL(counters->number_of_auth_info_requested,0); } static void simple_auth_register_with_refresh() { LinphoneCore* lc = create_lc_with_auth(1); - stats* counters = (stats*)linphone_core_get_user_data(lc); + stats* counters = get_stats(lc); char route[256]; sprintf(route,"sip:%s",test_route); register_with_refresh(lc,TRUE,auth_domain,route); @@ -195,7 +195,7 @@ static void simple_authenticated_register(){ char route[256]; sprintf(route,"sip:%s",test_route); linphone_core_add_auth_info(lc,info); /*add authentication info to LinphoneCore*/ - counters = (stats*)linphone_core_get_user_data(lc); + counters = get_stats(lc); register_with_refresh(lc,FALSE,auth_domain,route); CU_ASSERT_EQUAL(counters->number_of_auth_info_requested,0); } @@ -210,7 +210,7 @@ static void ha1_authenticated_register(){ info=linphone_auth_info_new(test_username,NULL,NULL,ha1,auth_domain); /*create authentication structure from identity*/ sprintf(route,"sip:%s",test_route); linphone_core_add_auth_info(lc,info); /*add authentication info to LinphoneCore*/ - counters = (stats*)linphone_core_get_user_data(lc); + counters = get_stats(lc); register_with_refresh(lc,FALSE,auth_domain,route); CU_ASSERT_EQUAL(counters->number_of_auth_info_requested,0); } @@ -227,7 +227,7 @@ static void authenticated_register_with_no_initial_credentials(){ v_table.auth_info_requested=auth_info_requested; lc = linphone_core_new(&v_table,NULL,NULL,NULL); linphone_core_set_user_data(lc,&stat); - counters= (stats*)linphone_core_get_user_data(lc); + counters= get_stats(lc); counters->number_of_auth_info_requested=0; register_with_refresh(lc,FALSE,auth_domain,route); CU_ASSERT_EQUAL(counters->number_of_auth_info_requested,1); @@ -238,7 +238,7 @@ static void auth_info_requested2(LinphoneCore *lc, const char *realm, const char ms_message("Auth info requested for user id [%s] at realm [%s]\n" ,username ,realm); - counters = (stats*)linphone_core_get_user_data(lc); + counters = get_stats(lc); counters->number_of_auth_info_requested++; } @@ -255,7 +255,7 @@ static void authenticated_register_with_late_credentials(){ v_table.auth_info_requested=auth_info_requested2; lc = linphone_core_new(&v_table,NULL,NULL,NULL); linphone_core_set_user_data(lc,&stat); - counters = (stats*)linphone_core_get_user_data(lc); + counters = get_stats(lc); register_with_refresh_base_2(lc,FALSE,auth_domain,route,TRUE,transport); CU_ASSERT_EQUAL(counters->number_of_auth_info_requested,1); linphone_core_destroy(lc); @@ -276,7 +276,7 @@ static void authenticated_register_with_wrong_credentials(){ lc = linphone_core_new(&v_table,NULL,NULL,NULL); linphone_core_set_user_data(lc,&stat); linphone_core_add_auth_info(lc,info); /*add wrong authentication info to LinphoneCore*/ - counters = (stats*)linphone_core_get_user_data(lc); + counters = get_stats(lc); register_with_refresh_base_2(lc,TRUE,auth_domain,route,TRUE,transport); CU_ASSERT_EQUAL(counters->number_of_auth_info_requested,1); linphone_core_destroy(lc); @@ -304,7 +304,7 @@ static void network_state_change(){ memset (&v_table,0,sizeof(LinphoneCoreVTable)); v_table.registration_state_changed=registration_state_changed; lc=configure_lc(&v_table); - counters = (stats*)linphone_core_get_user_data(lc); + counters = get_stats(lc); register_ok=counters->number_of_LinphoneRegistrationOk; linphone_core_set_network_reachable(lc,FALSE); CU_ASSERT_TRUE(wait_for(lc,lc,&counters->number_of_LinphoneRegistrationNone,register_ok)); @@ -336,7 +336,7 @@ static void transport_change(){ memset (&v_table,0,sizeof(LinphoneCoreVTable)); v_table.registration_state_changed=registration_state_changed; lc=configure_lc(&v_table); - counters = (stats*)linphone_core_get_user_data(lc); + counters = get_stats(lc); register_ok=counters->number_of_LinphoneRegistrationOk; number_of_udp_proxy=get_number_of_udp_proxy(lc); @@ -364,7 +364,7 @@ static void io_recv_error(){ memset (&v_table,0,sizeof(LinphoneCoreVTable)); v_table.registration_state_changed=registration_state_changed; lc=configure_lc(&v_table); - counters = (stats*)linphone_core_get_user_data(lc); + counters = get_stats(lc); register_ok=counters->number_of_LinphoneRegistrationOk; number_of_udp_proxy=get_number_of_udp_proxy(lc); sal_set_recv_error(lc->sal, 0); @@ -388,7 +388,7 @@ static void io_recv_error_without_active_register(){ memset (&v_table,0,sizeof(LinphoneCoreVTable)); v_table.registration_state_changed=registration_state_changed; lc=configure_lc(&v_table); - counters = (stats*)linphone_core_get_user_data(lc); + counters = get_stats(lc); register_ok=counters->number_of_LinphoneRegistrationOk; number_of_udp_proxy=get_number_of_udp_proxy(lc); @@ -418,14 +418,14 @@ static void tls_certificate_failure(){ LinphoneCoreVTable v_table; LinphoneCore* lc; stats stat; - //stats* counters; + char rootcapath[256]; memset (&v_table,0,sizeof(v_table)); reset_counters(&stat); v_table.registration_state_changed=registration_state_changed; lc = configure_lc_from(&v_table,liblinphone_tester_file_prefix, "pauline_rc", 0); linphone_core_set_user_data(lc,&stat); - //counters = (stats*)linphone_core_get_user_data(lc); + snprintf(rootcapath,sizeof(rootcapath), "%s/certificates/agent.pem", liblinphone_tester_file_prefix); /*bad root ca*/ linphone_core_set_root_ca(lc,rootcapath); linphone_core_set_network_reachable(lc,TRUE); From fbf909e3b06dfb6dac072244e9804915e77c6725 Mon Sep 17 00:00:00 2001 From: Simon Morlat Date: Thu, 6 Jun 2013 21:03:51 +0200 Subject: [PATCH 5/7] update oRTP and ms2 --- mediastreamer2 | 2 +- oRTP | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mediastreamer2 b/mediastreamer2 index 3f06cd60f..795498987 160000 --- a/mediastreamer2 +++ b/mediastreamer2 @@ -1 +1 @@ -Subproject commit 3f06cd60f1864b8c811e0f4e4590991802ce5ea7 +Subproject commit 7954989874f35e23c6580e1ba9a0b17ce64bd0b3 diff --git a/oRTP b/oRTP index 1a103971b..462296433 160000 --- a/oRTP +++ b/oRTP @@ -1 +1 @@ -Subproject commit 1a103971b84d39510ad14f327bd6834b3d88063f +Subproject commit 462296433f10bd84cb605edb0b38d16a4cd81d9e From 8c3fd2d4325fe1be53e3fb26a07afa52f0361a10 Mon Sep 17 00:00:00 2001 From: Simon Morlat Date: Thu, 6 Jun 2013 21:39:57 +0200 Subject: [PATCH 6/7] adapt java to modifications of info api --- build/android/common.mk | 4 +++- .../core/tutorials/TutorialBuddyStatus.java | 2 +- .../core/tutorials/TutorialChatRoom.java | 2 +- .../core/tutorials/TutorialHelloWorld.java | 2 +- .../core/tutorials/TutorialRegistration.java | 2 +- coreapi/linphonecore_jni.cc | 20 ++++++------------- .../org/linphone/core/LinphoneCall.java | 5 +++++ .../org/linphone/core/LinphoneCore.java | 8 +------- .../linphone/core/LinphoneCoreListener.java | 2 +- .../linphone/core/LinphoneInfoMessage.java | 6 +----- .../org/linphone/core/LinphoneCallImpl.java | 5 +++++ .../org/linphone/core/LinphoneCoreImpl.java | 5 ----- .../core/LinphoneInfoMessageImpl.java | 6 ------ 13 files changed, 26 insertions(+), 43 deletions(-) diff --git a/build/android/common.mk b/build/android/common.mk index aeedab67b..67bcd336c 100644 --- a/build/android/common.mk +++ b/build/android/common.mk @@ -45,6 +45,7 @@ LOCAL_SRC_FILES := \ bellesip_sal/sal_op_registration.c \ bellesip_sal/sal_op_publish.c \ bellesip_sal/sal_op_info.c \ + bellesip_sal/sal_op_events.c \ bellesip_sal/sal_sdp.c \ sal.c \ offeranswer.c \ @@ -54,7 +55,8 @@ LOCAL_SRC_FILES := \ ec-calibrator.c \ linphone_tunnel_config.c \ message_storage.c \ - info.c + info.c \ + event.c ifndef LINPHONE_VERSION LINPHONE_VERSION = "Devel" diff --git a/coreapi/help/java/org/linphone/core/tutorials/TutorialBuddyStatus.java b/coreapi/help/java/org/linphone/core/tutorials/TutorialBuddyStatus.java index a65e0528c..1f1dce9f2 100644 --- a/coreapi/help/java/org/linphone/core/tutorials/TutorialBuddyStatus.java +++ b/coreapi/help/java/org/linphone/core/tutorials/TutorialBuddyStatus.java @@ -250,7 +250,7 @@ public class TutorialBuddyStatus implements LinphoneCoreListener { } @Override - public void infoReceived(LinphoneCore lc, LinphoneInfoMessage info) { + public void infoReceived(LinphoneCore lc, LinphoneCall call, LinphoneInfoMessage info) { // TODO Auto-generated method stub } diff --git a/coreapi/help/java/org/linphone/core/tutorials/TutorialChatRoom.java b/coreapi/help/java/org/linphone/core/tutorials/TutorialChatRoom.java index e64750122..ecd5846d6 100644 --- a/coreapi/help/java/org/linphone/core/tutorials/TutorialChatRoom.java +++ b/coreapi/help/java/org/linphone/core/tutorials/TutorialChatRoom.java @@ -172,7 +172,7 @@ public class TutorialChatRoom implements LinphoneCoreListener, LinphoneChatMessa } @Override - public void infoReceived(LinphoneCore lc, LinphoneInfoMessage info) { + public void infoReceived(LinphoneCore lc, LinphoneCall call, LinphoneInfoMessage info) { // TODO Auto-generated method stub } diff --git a/coreapi/help/java/org/linphone/core/tutorials/TutorialHelloWorld.java b/coreapi/help/java/org/linphone/core/tutorials/TutorialHelloWorld.java index ea659e60b..10d3a2ce5 100644 --- a/coreapi/help/java/org/linphone/core/tutorials/TutorialHelloWorld.java +++ b/coreapi/help/java/org/linphone/core/tutorials/TutorialHelloWorld.java @@ -176,7 +176,7 @@ public class TutorialHelloWorld implements LinphoneCoreListener { } @Override - public void infoReceived(LinphoneCore lc, LinphoneInfoMessage info) { + public void infoReceived(LinphoneCore lc, LinphoneCall call, LinphoneInfoMessage info) { // TODO Auto-generated method stub } diff --git a/coreapi/help/java/org/linphone/core/tutorials/TutorialRegistration.java b/coreapi/help/java/org/linphone/core/tutorials/TutorialRegistration.java index c8a827511..e8373b0d4 100644 --- a/coreapi/help/java/org/linphone/core/tutorials/TutorialRegistration.java +++ b/coreapi/help/java/org/linphone/core/tutorials/TutorialRegistration.java @@ -207,7 +207,7 @@ public class TutorialRegistration implements LinphoneCoreListener { } @Override - public void infoReceived(LinphoneCore lc, LinphoneInfoMessage info) { + public void infoReceived(LinphoneCore lc, LinphoneCall call, LinphoneInfoMessage info) { // TODO Auto-generated method stub } diff --git a/coreapi/linphonecore_jni.cc b/coreapi/linphonecore_jni.cc index 85dd369d5..0e0eae1b4 100644 --- a/coreapi/linphonecore_jni.cc +++ b/coreapi/linphonecore_jni.cc @@ -197,7 +197,8 @@ public: textReceivedId = env->GetMethodID(listenerClass,"textReceived","(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneChatRoom;Lorg/linphone/core/LinphoneAddress;Ljava/lang/String;)V"); messageReceivedId = env->GetMethodID(listenerClass,"messageReceived","(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneChatRoom;Lorg/linphone/core/LinphoneChatMessage;)V"); dtmfReceivedId = env->GetMethodID(listenerClass,"dtmfReceived","(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneCall;I)V"); - infoReceivedId = env->GetMethodID(listenerClass,"infoReceived","(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneInfoMessage;)V"); + infoReceivedId = env->GetMethodID(listenerClass,"infoReceived", + "(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneCall;Lorg/linphone/core/LinphoneInfoMessage;)V"); proxyClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/LinphoneProxyConfigImpl")); proxyCtrId = env->GetMethodID(proxyClass,"", "(J)V"); @@ -536,7 +537,7 @@ public: ,env->CallStaticObjectMethod(lcData->callStateClass,lcData->callStateFromIntId,(jint)remote_call_state) ); } - static void infoReceived(LinphoneCore *lc, const LinphoneInfoMessage *info){ + static void infoReceived(LinphoneCore *lc, LinphoneCall*call, const LinphoneInfoMessage *info){ JNIEnv *env = 0; jint result = jvm->AttachCurrentThread(&env,NULL); jobject jcall; @@ -549,6 +550,7 @@ public: env->CallVoidMethod(lcData->listener ,lcData->infoReceivedId ,lcData->core + ,lcData->getCall(env,call) ,env->NewObject(lcData->infoMessageClass,lcData->infoMessageCtor,(jlong)copy_info) ); } @@ -606,8 +608,8 @@ JNIEXPORT jlong JNICALL Java_org_linphone_core_LinphoneCoreImpl_createInfoMessag return (jlong) linphone_core_create_info_message((LinphoneCore*)lcptr); } -JNIEXPORT jint JNICALL Java_org_linphone_core_LinphoneCoreImpl_sendInfoMessage(JNIEnv *env, jobject jobj, jlong lcptr, jlong infoptr, jlong addrptr){ - return linphone_core_send_info_message((LinphoneCore*)lcptr,(LinphoneInfoMessage*)infoptr,(LinphoneAddress*)addrptr); +JNIEXPORT jint JNICALL Java_org_linphone_core_LinphoneCallImpl_sendInfoMessage(JNIEnv *env, jobject jobj, jlong callptr, jlong infoptr){ + return linphone_call_send_info_message((LinphoneCall*)callptr,(LinphoneInfoMessage*)infoptr); } extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setPrimaryContact(JNIEnv* env, jobject thiz, jlong lc, jstring jdisplayname, jstring jusername) { @@ -2696,16 +2698,6 @@ JNIEXPORT jstring JNICALL Java_org_linphone_core_LinphoneInfoMessageImpl_getHead return ret ? env->NewStringUTF(ret) : NULL; } -/* - * Class: org_linphone_core_LinphoneInfoMessageImpl - * Method: getFrom - * Signature: (J)Ljava/lang/String; - */ -JNIEXPORT jstring JNICALL Java_org_linphone_core_LinphoneInfoMessageImpl_getFrom(JNIEnv *env , jobject jobj, jlong infoptr){ - const char *from=linphone_info_message_get_from((LinphoneInfoMessage*)infoptr); - return from ? env->NewStringUTF(from) : NULL; -} - /* * Class: org_linphone_core_LinphoneInfoMessageImpl * Method: delete diff --git a/java/common/org/linphone/core/LinphoneCall.java b/java/common/org/linphone/core/LinphoneCall.java index 3328b2959..35dc9008b 100644 --- a/java/common/org/linphone/core/LinphoneCall.java +++ b/java/common/org/linphone/core/LinphoneCall.java @@ -298,4 +298,9 @@ public interface LinphoneCall { * @return the call state of the new call performed by the referee to the refer target. */ State getTransferState(); + + /** + * Send an info message to remote peer. + */ + void sendInfoMessage(LinphoneInfoMessage msg); } diff --git a/java/common/org/linphone/core/LinphoneCore.java b/java/common/org/linphone/core/LinphoneCore.java index c3c26e946..0424a797c 100644 --- a/java/common/org/linphone/core/LinphoneCore.java +++ b/java/common/org/linphone/core/LinphoneCore.java @@ -1262,16 +1262,10 @@ public interface LinphoneCore { /** * Create an empty INFO message. - * It can later be sent using {@link LinphoneCore.sendInfoMessage() }. + * It can later be sent using {@link LinphoneCall.sendInfoMessage() }. * @return the new info message. */ public LinphoneInfoMessage createInfoMessage(); - /** - * Send an INFO message to specified destination. - * @param info the info message - * @param dest the destination sip address. - */ - public void sendInfoMessage(LinphoneInfoMessage info, LinphoneAddress dest); } diff --git a/java/common/org/linphone/core/LinphoneCoreListener.java b/java/common/org/linphone/core/LinphoneCoreListener.java index 1d85a07ca..b3ff9bbfc 100644 --- a/java/common/org/linphone/core/LinphoneCoreListener.java +++ b/java/common/org/linphone/core/LinphoneCoreListener.java @@ -130,7 +130,7 @@ public interface LinphoneCoreListener { * @param lc the LinphoneCore. * @param info the info message */ - void infoReceived(LinphoneCore lc, LinphoneInfoMessage info); + void infoReceived(LinphoneCore lc, LinphoneCall call, LinphoneInfoMessage info); /**< @Deprecated Notifies the application that it should show up * @return */ diff --git a/java/common/org/linphone/core/LinphoneInfoMessage.java b/java/common/org/linphone/core/LinphoneInfoMessage.java index 93ee6a7ec..00362e987 100644 --- a/java/common/org/linphone/core/LinphoneInfoMessage.java +++ b/java/common/org/linphone/core/LinphoneInfoMessage.java @@ -2,6 +2,7 @@ package org.linphone.core; /** * The LinphoneInfoMessage represents an informational message (INFO) to be transmitted or received by the LinphoneCore. + * It can be created with {@link LinphoneCore.createInfoMessage() }. * @author smorlat * */ @@ -28,9 +29,4 @@ public interface LinphoneInfoMessage { * @return the header's value */ String getHeader(String name); - /** - * Get the origin of the info message as a string URI. - * @return origin of the message. - */ - String getFrom(); } diff --git a/java/impl/org/linphone/core/LinphoneCallImpl.java b/java/impl/org/linphone/core/LinphoneCallImpl.java index afe0afc00..5c681506f 100644 --- a/java/impl/org/linphone/core/LinphoneCallImpl.java +++ b/java/impl/org/linphone/core/LinphoneCallImpl.java @@ -212,4 +212,9 @@ class LinphoneCallImpl implements LinphoneCall { public State getTransferState() { return State.fromInt(getTransferState(nativePtr)); } + private native int sendInfoMessage(long callPtr, long msgptr); + @Override + public void sendInfoMessage(LinphoneInfoMessage msg) { + sendInfoMessage(nativePtr,((LinphoneInfoMessageImpl)msg).nativePtr); + } } diff --git a/java/impl/org/linphone/core/LinphoneCoreImpl.java b/java/impl/org/linphone/core/LinphoneCoreImpl.java index a414baf7a..4b0232113 100644 --- a/java/impl/org/linphone/core/LinphoneCoreImpl.java +++ b/java/impl/org/linphone/core/LinphoneCoreImpl.java @@ -954,9 +954,4 @@ class LinphoneCoreImpl implements LinphoneCore { public LinphoneInfoMessage createInfoMessage() { return new LinphoneInfoMessageImpl(createInfoMessage(nativePtr)); } - private native int sendInfoMessage(long corePtr, long infoptr, long destptr); - @Override - public void sendInfoMessage(LinphoneInfoMessage info, LinphoneAddress dest) { - sendInfoMessage(nativePtr,((LinphoneInfoMessageImpl)info).nativePtr, ((LinphoneAddressImpl)dest).nativePtr); - } } diff --git a/java/impl/org/linphone/core/LinphoneInfoMessageImpl.java b/java/impl/org/linphone/core/LinphoneInfoMessageImpl.java index 06c31dd42..7b9fad362 100644 --- a/java/impl/org/linphone/core/LinphoneInfoMessageImpl.java +++ b/java/impl/org/linphone/core/LinphoneInfoMessageImpl.java @@ -33,12 +33,6 @@ public class LinphoneInfoMessageImpl implements LinphoneInfoMessage { public String getHeader(String name) { return getHeader(nativePtr,name); } - - private native String getFrom(long nativePtr); - @Override - public String getFrom() { - return getFrom(nativePtr); - } private native void delete(long nativePtr); protected void finalize(){ From 59b86f49ccce0c3984e1619886dc192c3c6b504b Mon Sep 17 00:00:00 2001 From: Simon Morlat Date: Thu, 6 Jun 2013 22:06:37 +0200 Subject: [PATCH 7/7] fix test --- tester/eventapi_tester.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tester/eventapi_tester.c b/tester/eventapi_tester.c index 9b156771d..b21d9eb79 100644 --- a/tester/eventapi_tester.c +++ b/tester/eventapi_tester.c @@ -93,7 +93,7 @@ static void subscribe_test_declined(void) { CU_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneSubscriptionOutgoingInit,1,1000)); CU_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneSubscriptionIncomingReceived,1,1000)); - CU_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneSubscriptionError,1,1000)); + CU_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneSubscriptionError,1,21000));/*yes flexisip will wait 20 secs in case of forking*/ CU_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneSubscriptionTerminated,1,1000)); linphone_core_manager_destroy(marie);