rework implementation of SUBSCRIBEs delayed to successful registration.

In case of network errors, SUBSCRIBE could be sent before registration refresh, this should be fixed.
This commit is contained in:
Simon Morlat 2014-03-11 17:23:42 +01:00
parent 526af17dd5
commit a0b7b1f3b0
5 changed files with 62 additions and 30 deletions

View file

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

View file

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

View file

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

View file

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

View file

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