diff --git a/coreapi/bellesip_sal/sal_op_impl.c b/coreapi/bellesip_sal/sal_op_impl.c index 481fb4cbd..945882efe 100644 --- a/coreapi/bellesip_sal/sal_op_impl.c +++ b/coreapi/bellesip_sal/sal_op_impl.c @@ -695,4 +695,9 @@ bool_t sal_op_is_idle(SalOp *op){ return TRUE; } +void sal_op_stop_refreshing(SalOp *op){ + if (op->refresher){ + belle_sip_refresher_stop(op->refresher); + } +} diff --git a/coreapi/friend.c b/coreapi/friend.c index 1a9705ea3..a51ee7891 100644 --- a/coreapi/friend.c +++ b/coreapi/friend.c @@ -380,6 +380,37 @@ BuddyInfo * linphone_friend_get_info(const LinphoneFriend *lf){ return lf->info; } +/* + * updates the subscriptions. + * If only_when_registered is TRUE, subscribe will be sent only if the friend's corresponding proxy config is in registered. + * Otherwise if the proxy config goes to unregistered state, the subscription refresh will be suspended. + * An optional proxy whose state has changed can be passed to optimize the processing. +**/ +void linphone_friend_update_subscribes(LinphoneFriend *fr, LinphoneProxyConfig *proxy, bool_t only_when_registered){ + int can_subscribe=1; + + if (only_when_registered && (fr->subscribe || fr->subscribe_active)){ + LinphoneProxyConfig *cfg=linphone_core_lookup_known_proxy(fr->lc,fr->uri); + if (proxy && proxy!=cfg) return; + if (cfg && cfg->state!=LinphoneRegistrationOk){ + char *tmp=linphone_address_as_string(fr->uri); + ms_message("Friend [%s] belongs to proxy config with identity [%s], but this one isn't registered. Subscription is suspended.", + tmp,linphone_proxy_config_get_identity(cfg)); + ms_free(tmp); + can_subscribe=0; + } + } + if (can_subscribe && fr->subscribe && fr->subscribe_active==FALSE){ + ms_message("Sending a new SUBSCRIBE"); + __linphone_friend_do_subscribe(fr); + }else if (can_subscribe && fr->subscribe_active && !fr->subscribe){ + linphone_friend_unsubscribe(fr); + }else if (!can_subscribe && fr->outsub){ + fr->subscribe_active=FALSE; + sal_op_stop_refreshing(fr->outsub); + } +} + void linphone_friend_apply(LinphoneFriend *fr, LinphoneCore *lc){ LinphonePresenceModel *model; @@ -407,12 +438,8 @@ void linphone_friend_apply(LinphoneFriend *fr, LinphoneCore *lc){ } fr->inc_subscribe_pending=FALSE; } - if (fr->subscribe && fr->subscribe_active==FALSE){ - ms_message("Sending a new SUBSCRIBE"); - __linphone_friend_do_subscribe(fr); - }else if (fr->subscribe_active && !fr->subscribe){ - linphone_friend_unsubscribe(fr); - } + if (fr->lc) + linphone_friend_update_subscribes(fr,NULL,linphone_core_should_subscribe_friends_only_when_registered(fr->lc)); ms_message("linphone_friend_apply() done."); lc->bl_refresh=TRUE; fr->commit=FALSE; @@ -465,31 +492,22 @@ void linphone_core_remove_friend(LinphoneCore *lc, LinphoneFriend* fl){ } } -void linphone_core_send_initial_subscribes(LinphoneCore *lc){ +void linphone_core_update_friends_subscriptions(LinphoneCore *lc, LinphoneProxyConfig *cfg, bool_t only_when_registered){ const MSList *elem; - if (lc->initial_subscribes_sent) return; - lc->initial_subscribes_sent=TRUE; /*set to true and see if looping on friends will change this status*/ for(elem=lc->friends;elem!=NULL;elem=elem->next){ LinphoneFriend *f=(LinphoneFriend*)elem->data; - LinphoneProxyConfig* cfg; - if (f->subscribe && !f->initial_subscribes_sent) { - lc->initial_subscribes_sent=FALSE; /*at least 1 was not sent */ - if ((cfg=linphone_core_lookup_known_proxy(f->lc,linphone_friend_get_address(f)))) { - /*check if already registered*/ - if (linphone_proxy_config_get_state(cfg) != LinphoneRegistrationOk) - continue; /*skip this friend because not registered yet*/ - else { - char* lf_string = linphone_address_as_string(linphone_friend_get_address(f)); - ms_message("Identity [%s] registered, we can now subscribe to [%s]",linphone_proxy_config_get_identity(cfg),lf_string); - ms_free(lf_string); - } - } - linphone_friend_apply(f,lc); - f->initial_subscribes_sent=TRUE; - } - + linphone_friend_update_subscribes(f,cfg,only_when_registered); } +} +bool_t linphone_core_should_subscribe_friends_only_when_registered(const LinphoneCore *lc){ + return lp_config_get_int(lc->config,"sip","subscribe_presence_only_when_registered",1); +} + +void linphone_core_send_initial_subscribes(LinphoneCore *lc){ + if (lc->initial_subscribes_sent) return; + lc->initial_subscribes_sent=TRUE; + linphone_core_update_friends_subscriptions(lc,NULL,linphone_core_should_subscribe_friends_only_when_registered(lc)); } void linphone_core_invalidate_friend_subscriptions(LinphoneCore *lc){ diff --git a/coreapi/private.h b/coreapi/private.h index cd528994f..f0ddaaeaa 100644 --- a/coreapi/private.h +++ b/coreapi/private.h @@ -255,13 +255,14 @@ void linphone_proxy_config_write_all_to_config_file(LinphoneCore *lc); * */ const LinphoneAddress* linphone_proxy_config_get_service_route(const LinphoneProxyConfig* cfg); - -int linphone_online_status_to_eXosip(LinphoneOnlineStatus os); void linphone_friend_close_subscriptions(LinphoneFriend *lf); +void linphone_friend_update_subscribes(LinphoneFriend *fr, LinphoneProxyConfig *cfg, bool_t only_when_registered); void linphone_friend_notify(LinphoneFriend *lf, LinphonePresenceModel *presence); LinphoneFriend *linphone_find_friend_by_inc_subscribe(MSList *l, SalOp *op); LinphoneFriend *linphone_find_friend_by_out_subscribe(MSList *l, SalOp *op); MSList *linphone_find_friend_by_address(MSList *fl, const LinphoneAddress *addr, LinphoneFriend **lf); +bool_t linphone_core_should_subscribe_friends_only_when_registered(const LinphoneCore *lc); +void linphone_core_update_friends_subscriptions(LinphoneCore *lc, LinphoneProxyConfig *cfg, bool_t only_when_registered); int parse_hostname_to_addr(const char *server, struct sockaddr_storage *ss, socklen_t *socklen, int default_port); diff --git a/coreapi/proxy.c b/coreapi/proxy.c index 635d94ec5..5e0b8ff18 100644 --- a/coreapi/proxy.c +++ b/coreapi/proxy.c @@ -1319,14 +1319,21 @@ void * linphone_proxy_config_get_user_data(LinphoneProxyConfig *cr) { void linphone_proxy_config_set_state(LinphoneProxyConfig *cfg, LinphoneRegistrationState state, const char *message){ LinphoneCore *lc=cfg->lc; - - + bool_t update_friends=FALSE; + if (linphone_core_should_subscribe_friends_only_when_registered(lc)){ + update_friends=(state==LinphoneRegistrationOk && cfg->state!=LinphoneRegistrationOk) + || (state!=LinphoneRegistrationOk && cfg->state==LinphoneRegistrationOk); + } ms_message("Proxy config [%p] for identity [%s] moving from state [%s] to [%s]" , cfg, linphone_proxy_config_get_identity(cfg), linphone_registration_state_to_string(cfg->state), linphone_registration_state_to_string(state)); if (cfg->state!=state || state==LinphoneRegistrationOk) { /*allow multiple notification of LinphoneRegistrationOk for refreshing*/ cfg->state=state; + + if (update_friends){ + linphone_core_update_friends_subscriptions(lc,cfg,TRUE); + } if (lc && lc->vtable.registration_state_changed){ lc->vtable.registration_state_changed(lc,cfg,state,message); } diff --git a/include/sal/sal.h b/include/sal/sal.h index 7bbdb0d0a..44cc2dcef 100644 --- a/include/sal/sal.h +++ b/include/sal/sal.h @@ -567,6 +567,7 @@ void sal_op_set_from_address(SalOp *op, const SalAddress *from); void sal_op_set_to(SalOp *op, const char *to); void sal_op_set_to_address(SalOp *op, const SalAddress *to); SalOp *sal_op_ref(SalOp* h); +void sal_op_stop_refreshing(SalOp *op); void sal_op_release(SalOp *h); void sal_op_authenticate(SalOp *h, const SalAuthInfo *info); void sal_op_cancel_authentication(SalOp *h);