mirror of
https://gitlab.linphone.org/BC/public/linphone-iphone.git
synced 2026-01-17 19:18:06 +00:00
Implement support of dialog created by Notify matching subscription
This commit is contained in:
parent
5872dddc3c
commit
026bbe8db3
10 changed files with 139 additions and 21 deletions
|
|
@ -235,7 +235,12 @@ static void process_request_event(void *ud, const belle_sip_request_event_t *eve
|
|||
|
||||
if (dialog) {
|
||||
op=(SalOp*)belle_sip_dialog_get_application_data(dialog);
|
||||
if (op==NULL || op->state==SalOpStateTerminated){
|
||||
|
||||
if (op == NULL && strcmp("NOTIFY",method) == 0) {
|
||||
/*special case for Dialog created by notify mathing subscribe*/
|
||||
belle_sip_transaction_t * sub_trans = belle_sip_dialog_get_last_transaction(dialog);
|
||||
op = (SalOp*)belle_sip_transaction_get_application_data(sub_trans);
|
||||
} else if (op==NULL || op->state==SalOpStateTerminated){
|
||||
ms_warning("Receiving request for null or terminated op [%p], ignored",op);
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -101,7 +101,7 @@ struct SalOp{
|
|||
int ref;
|
||||
SalOpType type;
|
||||
SalPrivacyMask privacy;
|
||||
belle_sip_header_t *event; /*used by SalOpSubscribe kinds*/
|
||||
belle_sip_header_event_t *event; /*used by SalOpSubscribe kinds*/
|
||||
SalOpSDPHandling sdp_handling;
|
||||
int auth_requests; /*number of auth requested for this op*/
|
||||
bool_t cnx_ip_to_0000_if_sendonly_enabled;
|
||||
|
|
@ -174,4 +174,6 @@ int sal_reason_to_sip_code(SalReason r);
|
|||
|
||||
void _sal_op_add_custom_headers(SalOp *op, belle_sip_message_t *msg);
|
||||
|
||||
SalSubscribeStatus belle_sip_message_get_subscription_state(const belle_sip_message_t *msg);
|
||||
|
||||
#endif /* SAL_IMPL_H_ */
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
*/
|
||||
#include "sal_impl.h"
|
||||
|
||||
SalSubscribeStatus get_subscription_state(belle_sip_message_t *msg){
|
||||
SalSubscribeStatus belle_sip_message_get_subscription_state(const 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){
|
||||
|
|
@ -73,7 +73,7 @@ static void subscribe_process_dialog_terminated(void *ctx, const belle_sip_dialo
|
|||
/*notify the app that our subscription is dead*/
|
||||
const char *eventname = NULL;
|
||||
if (op->event){
|
||||
eventname = belle_sip_header_get_unparsed_value(op->event);
|
||||
eventname = belle_sip_header_event_get_package_name(op->event);
|
||||
}
|
||||
op->base.root->callbacks.notify(op, SalSubscribeTerminated, eventname, NULL);
|
||||
}
|
||||
|
|
@ -115,7 +115,7 @@ static void subscribe_process_request_event(void *op_base, const belle_sip_reque
|
|||
belle_sip_request_t* req = belle_sip_request_event_get_request(event);
|
||||
belle_sip_dialog_state_t dialog_state;
|
||||
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;
|
||||
belle_sip_header_event_t *event_header;
|
||||
belle_sip_body_handler_t *body_handler;
|
||||
belle_sip_response_t* resp;
|
||||
const char *eventname=NULL;
|
||||
|
|
@ -125,7 +125,7 @@ static void subscribe_process_request_event(void *op_base, const belle_sip_reque
|
|||
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");
|
||||
event_header=belle_sip_message_get_header_by_type(req,belle_sip_header_event_t);
|
||||
body_handler = BELLE_SIP_BODY_HANDLER(sal_op_get_body_handler(op, BELLE_SIP_MESSAGE(req)));
|
||||
|
||||
if (event_header==NULL){
|
||||
|
|
@ -139,7 +139,7 @@ static void subscribe_process_request_event(void *op_base, const belle_sip_reque
|
|||
op->event=event_header;
|
||||
belle_sip_object_ref(op->event);
|
||||
}
|
||||
eventname=belle_sip_header_get_unparsed_value(event_header);
|
||||
eventname=belle_sip_header_event_get_package_name(event_header);
|
||||
|
||||
if (!op->dialog) {
|
||||
if (strcmp(method,"SUBSCRIBE")==0){
|
||||
|
|
@ -238,10 +238,10 @@ int sal_subscribe(SalOp *op, const char *from, const char *to, const char *event
|
|||
}
|
||||
if (eventname){
|
||||
if (op->event) belle_sip_object_unref(op->event);
|
||||
op->event=belle_sip_header_create("Event",eventname);
|
||||
op->event=belle_sip_header_event_create(eventname);
|
||||
belle_sip_object_ref(op->event);
|
||||
}
|
||||
belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),op->event);
|
||||
belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(op->event));
|
||||
belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(belle_sip_header_expires_create(expires)));
|
||||
belle_sip_message_set_body_handler(BELLE_SIP_MESSAGE(req), BELLE_SIP_BODY_HANDLER(body_handler));
|
||||
return sal_op_send_and_create_refresher(op,req,expires,subscribe_refresher_listener);
|
||||
|
|
@ -276,6 +276,29 @@ int sal_subscribe_accept(SalOp *op){
|
|||
return 0;
|
||||
}
|
||||
|
||||
int sal_notify_pending_state(SalOp *op){
|
||||
|
||||
if (op->dialog != NULL && op->pending_server_trans) {
|
||||
belle_sip_request_t* notify;
|
||||
belle_sip_header_subscription_state_t* sub_state;
|
||||
ms_message("Sending NOTIFY with subscription state pending for op [%p]",op);
|
||||
if (!(notify=belle_sip_dialog_create_request(op->dialog,"NOTIFY"))) {
|
||||
ms_error("Cannot create NOTIFY on op [%p]",op);
|
||||
return -1;
|
||||
}
|
||||
if (op->event) belle_sip_message_add_header(BELLE_SIP_MESSAGE(notify),BELLE_SIP_HEADER(op->event));
|
||||
sub_state=belle_sip_header_subscription_state_new();
|
||||
belle_sip_header_subscription_state_set_state(sub_state,BELLE_SIP_SUBSCRIPTION_STATE_PENDING);
|
||||
belle_sip_message_add_header(BELLE_SIP_MESSAGE(notify), BELLE_SIP_HEADER(sub_state));
|
||||
return sal_op_send_request(op,notify);
|
||||
} else {
|
||||
ms_warning("NOTIFY with subscription state pending for op [%p] not implemented in this case (either dialog pending trans does not exist",op);
|
||||
}
|
||||
|
||||
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));
|
||||
|
|
@ -290,7 +313,7 @@ int sal_notify(SalOp *op, const SalBodyHandler *body_handler){
|
|||
|
||||
if (!(notify=belle_sip_dialog_create_queued_request(op->dialog,"NOTIFY"))) return -1;
|
||||
|
||||
if (op->event) belle_sip_message_add_header(BELLE_SIP_MESSAGE(notify),op->event);
|
||||
if (op->event) belle_sip_message_add_header(BELLE_SIP_MESSAGE(notify),BELLE_SIP_HEADER(op->event));
|
||||
|
||||
belle_sip_message_add_header(BELLE_SIP_MESSAGE(notify)
|
||||
,BELLE_SIP_HEADER(belle_sip_header_subscription_state_create(BELLE_SIP_SUBSCRIPTION_STATE_ACTIVE,600)));
|
||||
|
|
@ -302,7 +325,7 @@ int sal_notify_close(SalOp *op){
|
|||
belle_sip_request_t* notify;
|
||||
if (!op->dialog) return -1;
|
||||
if (!(notify=belle_sip_dialog_create_queued_request(op->dialog,"NOTIFY"))) return -1;
|
||||
if (op->event) belle_sip_message_add_header(BELLE_SIP_MESSAGE(notify),op->event);
|
||||
if (op->event) belle_sip_message_add_header(BELLE_SIP_MESSAGE(notify),BELLE_SIP_HEADER(op->event));
|
||||
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);
|
||||
|
|
|
|||
|
|
@ -229,7 +229,7 @@ static void handle_notify(SalOp *op, belle_sip_request_t *req, belle_sip_dialog_
|
|||
sub_state=SalSubscribeTerminated;
|
||||
ms_message("Outgoing subscription terminated by remote [%s]",sal_op_get_to(op));
|
||||
} else {
|
||||
sub_state=SalSubscribeActive;
|
||||
sub_state=belle_sip_message_get_subscription_state(BELLE_SIP_MESSAGE(req));
|
||||
}
|
||||
presence_model = process_presence_notification(op, req);
|
||||
if (presence_model != NULL || body==NULL) {
|
||||
|
|
@ -255,10 +255,23 @@ static void presence_process_request_event(void *op_base, const belle_sip_reques
|
|||
belle_sip_dialog_state_t dialog_state;
|
||||
belle_sip_response_t* resp;
|
||||
const char *method=belle_sip_request_get_method(req);
|
||||
|
||||
belle_sip_header_event_t *event_header;
|
||||
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_by_type(req,belle_sip_header_event_t);
|
||||
|
||||
if (event_header==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);
|
||||
if (!op->dialog) sal_op_release(op);
|
||||
return;
|
||||
}
|
||||
if (op->event==NULL) {
|
||||
op->event=event_header;
|
||||
belle_sip_object_ref(op->event);
|
||||
}
|
||||
|
||||
|
||||
if (!op->dialog) {
|
||||
|
|
@ -272,7 +285,10 @@ static void presence_process_request_event(void *op_base, const belle_sip_reques
|
|||
}
|
||||
set_or_update_dialog(op, dialog);
|
||||
ms_message("new incoming subscription from [%s] to [%s]",sal_op_get_from(op),sal_op_get_to(op));
|
||||
}else{ /* this is a NOTIFY */
|
||||
}else if (strcmp(method,"NOTIFY")==0 && belle_sip_request_event_get_dialog(event)) {
|
||||
/*special case of dialog created by notify matching subscribe*/
|
||||
set_or_update_dialog(op, belle_sip_request_event_get_dialog(event));
|
||||
} else {/* this is a NOTIFY */
|
||||
ms_message("Receiving out of dialog notify");
|
||||
handle_notify(op, req, belle_sip_request_event_get_dialog(event));
|
||||
return;
|
||||
|
|
@ -281,7 +297,11 @@ static void presence_process_request_event(void *op_base, const belle_sip_reques
|
|||
dialog_state=belle_sip_dialog_get_state(op->dialog);
|
||||
switch(dialog_state) {
|
||||
case BELLE_SIP_DIALOG_NULL: {
|
||||
op->base.root->callbacks.subscribe_presence_received(op,sal_op_get_from(op));
|
||||
if (strcmp("NOTIFY",method)==0) {
|
||||
handle_notify(op, req, belle_sip_request_event_get_dialog(event));
|
||||
} else if (strcmp("SUBSCRIBE",method)==0) {
|
||||
op->base.root->callbacks.subscribe_presence_received(op,sal_op_get_from(op));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case BELLE_SIP_DIALOG_EARLY:
|
||||
|
|
@ -354,14 +374,14 @@ int sal_subscribe_presence(SalOp *op, const char *from, const char *to, int expi
|
|||
}
|
||||
}
|
||||
if (!op->event){
|
||||
op->event=belle_sip_header_create("Event","presence");
|
||||
op->event=belle_sip_header_event_create("presence");
|
||||
belle_sip_object_ref(op->event);
|
||||
}
|
||||
belle_sip_parameters_remove_parameter(BELLE_SIP_PARAMETERS(op->base.from_address),"tag");
|
||||
belle_sip_parameters_remove_parameter(BELLE_SIP_PARAMETERS(op->base.to_address),"tag");
|
||||
req=sal_op_build_request(op,"SUBSCRIBE");
|
||||
if( req ){
|
||||
belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),op->event);
|
||||
belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(op->event));
|
||||
belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(belle_sip_header_expires_create(expires)));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1552,3 +1552,6 @@ void linphone_core_migrate_friends_from_rc_to_db(LinphoneCore *lc) {
|
|||
ms_debug("friends migration successful: %i friends migrated", i);
|
||||
lp_config_set_int(lpc, "misc", "friends_migration_done", 1);
|
||||
}
|
||||
LinphoneSubscriptionState linphone_friend_get_subscription_state(const LinphoneFriend *lf) {
|
||||
return lf->out_sub_state;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -278,6 +278,14 @@ LINPHONE_PUBLIC void linphone_friend_done(LinphoneFriend *fr);
|
|||
*/
|
||||
LINPHONE_PUBLIC LinphoneOnlineStatus linphone_friend_get_status(const LinphoneFriend *lf);
|
||||
|
||||
/**
|
||||
* Get subscription state of a friend
|
||||
* @param[in] lf A #LinphoneFriend object
|
||||
* @return #LinphoneSubscriptionState
|
||||
*/
|
||||
|
||||
LINPHONE_PUBLIC LinphoneSubscriptionState linphone_friend_get_subscription_state(const LinphoneFriend *lf);
|
||||
|
||||
/**
|
||||
* Get the presence model of a friend
|
||||
* @param[in] lf A #LinphoneFriend object
|
||||
|
|
|
|||
|
|
@ -1513,6 +1513,9 @@ void linphone_subscription_new(LinphoneCore *lc, SalOp *op, const char *from){
|
|||
if (lf!=NULL){
|
||||
linphone_friend_add_incoming_subscription(lf, op);
|
||||
lf->inc_subscribe_pending=TRUE;
|
||||
if (lp_config_get_int(lc->config,"sip","notify_pending_state",0)) {
|
||||
sal_notify_pending_state(op);
|
||||
}
|
||||
sal_subscribe_accept(op);
|
||||
linphone_friend_done(lf); /*this will do all necessary actions */
|
||||
}else{
|
||||
|
|
@ -1904,6 +1907,7 @@ void linphone_notify_recv(LinphoneCore *lc, SalOp *op, SalSubscribeStatus ss, Sa
|
|||
linphone_friend_set_presence_model(lf, presence);
|
||||
lf->subscribe_active=TRUE;
|
||||
lf->presence_received = TRUE;
|
||||
lf->out_sub_state = linphone_subscription_state_from_sal(ss);
|
||||
linphone_core_notify_notify_presence_received(lc,(LinphoneFriend*)lf);
|
||||
ms_free(tmp);
|
||||
if (op != lf->outsub){
|
||||
|
|
|
|||
|
|
@ -702,6 +702,7 @@ struct _LinphoneFriend{
|
|||
LinphoneVcard *vcard;
|
||||
unsigned int storage_id;
|
||||
LinphoneFriendList *friend_list;
|
||||
LinphoneSubscriptionState out_sub_state;
|
||||
};
|
||||
|
||||
BELLE_SIP_DECLARE_VPTR(LinphoneFriend);
|
||||
|
|
|
|||
|
|
@ -770,6 +770,7 @@ int sal_subscribe(SalOp *op, const char *from, const char *to, const char *event
|
|||
int sal_unsubscribe(SalOp *op);
|
||||
int sal_subscribe_accept(SalOp *op);
|
||||
int sal_subscribe_decline(SalOp *op, SalReason reason);
|
||||
int sal_notify_pending_state(SalOp *op);
|
||||
int sal_notify(SalOp *op, const SalBodyHandler *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 SalBodyHandler *body);
|
||||
|
|
|
|||
|
|
@ -272,6 +272,54 @@ static void simple_subscribe(void) {
|
|||
|
||||
linphone_core_manager_destroy(pauline);
|
||||
}
|
||||
static void simple_subscribe_with_early_notify(void) {
|
||||
|
||||
LinphoneCoreManager* marie = presence_linphone_core_manager_new("marie");
|
||||
LinphoneCoreManager* pauline = presence_linphone_core_manager_new("pauline");
|
||||
LinphoneAddress *marie_identity_addr = linphone_address_clone(marie->identity);
|
||||
LpConfig *pauline_lp;
|
||||
pauline_lp = linphone_core_get_config(pauline->lc);
|
||||
lp_config_set_int(pauline_lp,"sip","notify_pending_state",1);
|
||||
|
||||
bool_t result=FALSE;
|
||||
char* pauline_identity=linphone_address_as_string_uri_only(pauline->identity);
|
||||
char* marie_identity;
|
||||
|
||||
LinphoneFriend* pauline_s_friend;
|
||||
LinphoneFriend* marie_s_friend=linphone_core_create_friend_with_address(marie->lc,pauline_identity);
|
||||
|
||||
|
||||
linphone_friend_edit(marie_s_friend);
|
||||
linphone_friend_enable_subscribes(marie_s_friend,TRUE);
|
||||
linphone_friend_done(marie_s_friend);
|
||||
linphone_core_add_friend(marie->lc,marie_s_friend);
|
||||
ms_free(pauline_identity);
|
||||
|
||||
|
||||
/*to simulate pending state.*/
|
||||
|
||||
linphone_address_set_port(marie_identity_addr,0);
|
||||
marie_identity=linphone_address_as_string_uri_only(marie_identity_addr);
|
||||
pauline_s_friend=linphone_core_create_friend_with_address(pauline->lc,marie_identity);
|
||||
linphone_core_add_friend(pauline->lc,pauline_s_friend);
|
||||
|
||||
ms_free(marie_identity);
|
||||
|
||||
BC_ASSERT_TRUE(wait_for(marie->lc,pauline->lc,&marie->stat.number_of_NotifyPresenceReceived,1));
|
||||
BC_ASSERT_EQUAL(linphone_friend_get_subscription_state(marie_s_friend), LinphoneSubscriptionPending,int, "%d");
|
||||
|
||||
result=wait_for(marie->lc,pauline->lc,&marie->stat.number_of_LinphonePresenceActivityOnline,marie->stat.number_of_LinphonePresenceActivityOnline+1);
|
||||
|
||||
BC_ASSERT_EQUAL(marie->stat.number_of_NotifyPresenceReceived,2, int, "%d");
|
||||
|
||||
linphone_friend_unref(marie_s_friend);
|
||||
linphone_friend_unref(pauline_s_friend);
|
||||
linphone_address_unref(marie_identity_addr);
|
||||
linphone_core_manager_destroy(marie);
|
||||
|
||||
linphone_core_manager_destroy(pauline);
|
||||
}
|
||||
|
||||
|
||||
static void unsubscribe_while_subscribing(void) {
|
||||
LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc");
|
||||
|
|
@ -399,8 +447,8 @@ static void presence_information(void) {
|
|||
|
||||
static void subscribe_presence_forked(void){
|
||||
LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc");
|
||||
LinphoneCoreManager* pauline1 = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc");
|
||||
LinphoneCoreManager* pauline2 = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc");
|
||||
LinphoneCoreManager* pauline1 = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_tcp_rc" : "pauline_tcp_rc");
|
||||
LinphoneCoreManager* pauline2 = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_tcp_rc" : "pauline_tcp_rc");
|
||||
LinphoneFriend *lf;
|
||||
MSList *lcs = NULL;
|
||||
|
||||
|
|
@ -417,8 +465,10 @@ static void subscribe_presence_forked(void){
|
|||
|
||||
BC_ASSERT_TRUE(wait_for_list(lcs,&pauline1->stat.number_of_NewSubscriptionRequest,1, 10000));
|
||||
BC_ASSERT_TRUE(wait_for_list(lcs,&pauline2->stat.number_of_NewSubscriptionRequest,1, 2000));
|
||||
/*we should get two notifies*/
|
||||
BC_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphonePresenceActivityOnline,2, 10000));
|
||||
|
||||
/*we should get only one notify*/
|
||||
BC_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphonePresenceActivityOnline,1, 10000));
|
||||
BC_ASSERT_FALSE(wait_for_list(lcs,&marie->stat.number_of_LinphonePresenceActivityOnline,2, 2000));
|
||||
|
||||
/*marie also shall receive two SUBSCRIBEs from the two paulines, but won't be notified to the app since
|
||||
Marie set Pauline as a friend.*/
|
||||
|
|
@ -501,6 +551,7 @@ static void simple_subscribe_with_friend_from_rc(void) {
|
|||
|
||||
test_t presence_tests[] = {
|
||||
TEST_ONE_TAG("Simple Subscribe", simple_subscribe,"presence"),
|
||||
TEST_ONE_TAG("Simple Subscribe with early NOTIFY", simple_subscribe_with_early_notify,"presence"),
|
||||
TEST_NO_TAG("Simple Subscribe with friend from rc", simple_subscribe_with_friend_from_rc),
|
||||
TEST_ONE_TAG("Simple Publish", simple_publish, "LeaksMemory"),
|
||||
TEST_ONE_TAG("Simple Publish with expires", publish_with_expires, "LeaksMemory"),
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue