From 0b2d04d624b93c861d8487573164e98cb4ccf713 Mon Sep 17 00:00:00 2001 From: Simon Morlat Date: Fri, 5 Jul 2013 23:05:20 +0200 Subject: [PATCH] many improvements * re-send SUBSCRIBEs after network gets reachable again * allow to set the default SUBSCRIBE expires using [sip] "subscribe_expires" property * re-send initial SUBSCRIBE if remote peer lost the dialog context --- coreapi/bellesip_sal/sal_op_presence.c | 27 +++++++++++++++++++--- coreapi/friend.c | 31 ++++++++++++++++++++------ coreapi/linphonecore.c | 11 ++++----- coreapi/private.h | 2 ++ include/sal/sal.h | 2 +- 5 files changed, 57 insertions(+), 16 deletions(-) diff --git a/coreapi/bellesip_sal/sal_op_presence.c b/coreapi/bellesip_sal/sal_op_presence.c index 99769f326..4c65ff3f7 100644 --- a/coreapi/bellesip_sal/sal_op_presence.c +++ b/coreapi/bellesip_sal/sal_op_presence.c @@ -56,6 +56,20 @@ static void presence_process_dialog_terminated(void *ctx, const belle_sip_dialog } } +static void presence_refresher_listener( const belle_sip_refresher_t* refresher, void* user_pointer, unsigned int status_code, const char* reason_phrase){ + SalOp* op = (SalOp*)user_pointer; + switch(status_code){ + case 481: + ms_message("The server or remote ua lost the SUBSCRIBE dialog context. Let's restart a new one."); + belle_sip_refresher_stop(op->refresher); + belle_sip_object_unref(op->refresher); + op->refresher=NULL; + sal_subscribe_presence(op,NULL,NULL,-1); + break; + } +} + + static void presence_response_event(void *op_base, const belle_sip_response_event_t *event){ SalOp* op = (SalOp*)op_base; belle_sip_dialog_state_t dialog_state; @@ -96,6 +110,7 @@ static void presence_response_event(void *op_base, const belle_sip_response_even } if (expires>0){ op->refresher=belle_sip_client_transaction_create_refresher(client_transaction); + belle_sip_refresher_set_listener(op->refresher,presence_refresher_listener,op); } } break; @@ -246,7 +261,7 @@ void sal_op_presence_fill_cbs(SalOp*op) { /*presence Subscribe/notify*/ -int sal_subscribe_presence(SalOp *op, const char *from, const char *to){ +int sal_subscribe_presence(SalOp *op, const char *from, const char *to, int expires){ belle_sip_request_t *req=NULL; if (from) sal_op_set_from(op,from); @@ -255,10 +270,16 @@ int sal_subscribe_presence(SalOp *op, const char *from, const char *to){ sal_op_presence_fill_cbs(op); - /*???sal_exosip_fix_route(op); make sure to ha ;lr*/ + if (expires==-1){ + if (op->refresher){ + expires=belle_sip_refresher_get_expires(op->refresher); + }else{ + ms_error("sal_subscribe_presence(): cannot guess expires from previous refresher."); + } + } req=sal_op_build_request(op,"SUBSCRIBE"); 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(600))); + belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(belle_sip_header_expires_create(expires))); return sal_op_send_request(op,req); } diff --git a/coreapi/friend.c b/coreapi/friend.c index 80549e4f2..5437a5a03 100644 --- a/coreapi/friend.c +++ b/coreapi/friend.c @@ -111,6 +111,7 @@ void __linphone_friend_do_subscribe(LinphoneFriend *fr){ char *friend=NULL; const char *from=NULL; LinphoneProxyConfig *cfg; + LinphoneCore *lc=fr->lc; friend=linphone_address_as_string(fr->uri); cfg=linphone_core_lookup_known_proxy(fr->lc,linphone_friend_get_address(fr)); @@ -129,9 +130,9 @@ void __linphone_friend_do_subscribe(LinphoneFriend *fr){ sal_op_release(fr->outsub); fr->outsub=NULL; } - fr->outsub=sal_op_new(fr->lc->sal); - linphone_configure_op(fr->lc,fr->outsub,fr->uri,NULL,TRUE); - sal_subscribe_presence(fr->outsub,from,friend); + fr->outsub=sal_op_new(lc->sal); + linphone_configure_op(lc,fr->outsub,fr->uri,NULL,TRUE); + sal_subscribe_presence(fr->outsub,from,friend,lp_config_get_int(lc->config,"sip","subscribe_expires",600)); fr->subscribe_active=TRUE; ms_free(friend); } @@ -243,6 +244,14 @@ static void linphone_friend_unsubscribe(LinphoneFriend *lf){ } } +static void linphone_friend_invalidate_subscription(LinphoneFriend *lf){ + if (lf->outsub!=NULL) { + sal_op_release(lf->outsub); + lf->outsub=NULL; + lf->subscribe_active=FALSE; + } +} + void linphone_friend_close_subscriptions(LinphoneFriend *lf){ linphone_friend_unsubscribe(lf); if (lf->insub){ @@ -383,9 +392,7 @@ void linphone_friend_apply(LinphoneFriend *fr, LinphoneCore *lc){ break; case LinphoneSPAccept: if (fr->lc!=NULL) - { linphone_friend_notify(fr,fr->lc->presence_model); - } break; case LinphoneSPDeny: linphone_friend_notify(fr,NULL); @@ -441,11 +448,21 @@ void linphone_core_remove_friend(LinphoneCore *lc, LinphoneFriend* fl){ void linphone_core_send_initial_subscribes(LinphoneCore *lc){ const MSList *elem; + if (lc->initial_subscribes_sent) return; for(elem=lc->friends;elem!=NULL;elem=elem->next){ LinphoneFriend *f=(LinphoneFriend*)elem->data; - if (f->commit) - linphone_friend_apply(f,lc); + linphone_friend_apply(f,lc); } + lc->initial_subscribes_sent=TRUE; +} + +void linphone_core_invalidate_friend_subscriptions(LinphoneCore *lc){ + const MSList *elem; + for(elem=lc->friends;elem!=NULL;elem=elem->next){ + LinphoneFriend *f=(LinphoneFriend*)elem->data; + linphone_friend_invalidate_subscription(f); + } + lc->initial_subscribes_sent=FALSE; } void linphone_friend_set_ref_key(LinphoneFriend *lf, const char *key){ diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index 5f3aa37a1..15ca4867a 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -2206,10 +2206,9 @@ void linphone_core_iterate(LinphoneCore *lc){ linphone_core_run_hooks(lc); linphone_core_do_plugin_tasks(lc); - if (lc->initial_subscribes_sent==FALSE && lc->netup_time!=0 && - (curtime-lc->netup_time)>3){ + if (lc->network_reachable && lc->netup_time!=0 && (curtime-lc->netup_time)>3){ + /*not do that immediately, take your time.*/ linphone_core_send_initial_subscribes(lc); - lc->initial_subscribes_sent=TRUE; } if (one_second_elapsed) { @@ -5581,13 +5580,15 @@ static void set_network_reachable(LinphoneCore* lc,bool_t isReachable, time_t cu lc->netup_time=curtime; lc->network_reachable=isReachable; + if (!lc->network_reachable) linphone_core_invalidate_friend_subscriptions(lc); + if(!isReachable) { sal_reset_transports(lc->sal); } #ifdef BUILD_UPNP if(lc->upnp == NULL) { if(isReachable && lc->net_conf.firewall_policy == LinphonePolicyUseUpnp) { - lc->upnp = linphone_upnp_context_new(lc); + lc->upnp = linphone_upnp_context_new(lc); } } else { if(!isReachable && lc->net_conf.firewall_policy == LinphonePolicyUseUpnp) { @@ -5595,7 +5596,7 @@ static void set_network_reachable(LinphoneCore* lc,bool_t isReachable, time_t cu lc->upnp = NULL; } } -#endif +#endif } void linphone_core_refresh_registers(LinphoneCore* lc) { diff --git a/coreapi/private.h b/coreapi/private.h index 1e28939c9..984735ffe 100644 --- a/coreapi/private.h +++ b/coreapi/private.h @@ -758,6 +758,8 @@ 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); +void linphone_core_invalidate_friend_subscriptions(LinphoneCore *lc); + #ifdef __cplusplus } #endif diff --git a/include/sal/sal.h b/include/sal/sal.h index 48f9905be..9cbaba73e 100644 --- a/include/sal/sal.h +++ b/include/sal/sal.h @@ -534,7 +534,7 @@ int sal_text_send(SalOp *op, const char *from, const char *to, const char *text) int sal_message_send(SalOp *op, const char *from, const char *to, const char* content_type, const char *msg); /*presence Subscribe/notify*/ -int sal_subscribe_presence(SalOp *op, const char *from, const char *to); +int sal_subscribe_presence(SalOp *op, const char *from, const char *to, int expires); int sal_notify_presence(SalOp *op, SalPresenceModel *presence); int sal_notify_presence_close(SalOp *op);