diff --git a/coreapi/bellesip_sal/sal_impl.c b/coreapi/bellesip_sal/sal_impl.c index cf46d4f74..2ff7041e6 100644 --- a/coreapi/bellesip_sal/sal_impl.c +++ b/coreapi/bellesip_sal/sal_impl.c @@ -175,31 +175,32 @@ static void process_request_event(void *sal, const belle_sip_request_event_t *ev belle_sip_header_to_t* to; belle_sip_response_t* resp; belle_sip_header_t *evh; + const char *method=belle_sip_request_get_method(req); from_header=belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req),belle_sip_header_from_t); if (dialog) { op=(SalOp*)belle_sip_dialog_get_application_data(dialog); - } else if (strcmp("INVITE",belle_sip_request_get_method(req))==0) { + }else if (strcmp("INVITE",method)==0) { 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 && (evh=belle_sip_message_get_header(BELLE_SIP_MESSAGE(req),"Event"))!=NULL) { + }else if ((strcmp("SUBSCRIBE",method)==0 || strcmp("NOTIFY",method)==0) && (evh=belle_sip_message_get_header(BELLE_SIP_MESSAGE(req),"Event"))!=NULL) { op=sal_op_new((Sal*)sal); op->dir=SalOpDirIncoming; 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) { + }else if (strcmp("MESSAGE",method)==0) { op=sal_op_new((Sal*)sal); op->dir=SalOpDirIncoming; sal_op_message_fill_cbs(op); - } else if (strcmp("OPTIONS",belle_sip_request_get_method(req))==0) { + }else if (strcmp("OPTIONS",method)==0) { resp=belle_sip_response_create_from_request(req,200); belle_sip_provider_send_response(((Sal*)sal)->prov,resp); return; - }else if (strcmp("INFO",belle_sip_request_get_method(req))==0) { + }else if (strcmp("INFO",method)==0) { 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; diff --git a/coreapi/bellesip_sal/sal_op_events.c b/coreapi/bellesip_sal/sal_op_events.c index 952c58a6a..a1a88fec8 100644 --- a/coreapi/bellesip_sal/sal_op_events.c +++ b/coreapi/bellesip_sal/sal_op_events.c @@ -64,7 +64,7 @@ static void subscribe_response_event(void *op_base, const belle_sip_response_eve } 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); + ms_message("subscribe op [%p] received out of dialog answer [%i]",op,code); return; } dialog_state=belle_sip_dialog_get_state(op->dialog); @@ -112,18 +112,34 @@ static void subscribe_process_transaction_terminated(void *user_ctx, const belle ms_message("subscribe_process_transaction_terminated not implemented yet"); } +static void handle_notify(SalOp *op, belle_sip_request_t *req, const char *eventname, SalBody * body){ + SalSubscribeStatus sub_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_response_t* resp; + belle_sip_server_transaction_t* server_transaction = op->pending_server_trans; + + 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); +} + 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; + const char *method=belle_sip_request_get_method(req); belle_sip_object_ref(server_transaction); if (op->pending_server_trans) belle_sip_object_unref(op->pending_server_trans); @@ -141,10 +157,15 @@ static void subscribe_process_request_event(void *op_base, const belle_sip_reque } 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)); + if (strcmp(method,"SUBSCRIBE")==0){ + 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)); + }else{ /*this is a NOTIFY*/ + handle_notify(op,req,eventname,&body); + return; + } } dialog_state=belle_sip_dialog_get_state(op->dialog); switch(dialog_state) { @@ -158,17 +179,9 @@ static void subscribe_process_request_event(void *op_base, const belle_sip_reque 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) { + if (strcmp("NOTIFY",method)==0) { + handle_notify(op,req,eventname,&body); + } else if (strcmp("SUBSCRIBE",method)==0) { /*either a refresh of an unsubscribe*/ if (expires && belle_sip_header_expires_get_expires(expires)>0) { diff --git a/coreapi/bellesip_sal/sal_op_presence.c b/coreapi/bellesip_sal/sal_op_presence.c index a818fd511..62acc81aa 100644 --- a/coreapi/bellesip_sal/sal_op_presence.c +++ b/coreapi/bellesip_sal/sal_op_presence.c @@ -142,77 +142,94 @@ static SalPresenceModel * process_presence_notification(SalOp *op, belle_sip_req return result; } +static void handle_notify(SalOp *op, belle_sip_request_t *req){ + belle_sip_response_t* resp; + belle_sip_server_transaction_t* server_transaction=op->pending_server_trans; + belle_sip_header_subscription_state_t* subscription_state_header=belle_sip_message_get_header_by_type(req,belle_sip_header_subscription_state_t); + SalSubscribeStatus sub_state; + + if (strcmp("NOTIFY",belle_sip_request_get_method(req))==0) { + SalPresenceModel *presence_model = NULL; + const char* body = belle_sip_message_get_body(BELLE_SIP_MESSAGE(req)); + if (body==NULL){ + ms_error("No body in NOTIFY received from [%s]",sal_op_get_from(op)); + resp = sal_op_create_response_from_request(op, req, 415); + belle_sip_server_transaction_send_response(server_transaction,resp); + return; + } + presence_model = process_presence_notification(op, req); + if (presence_model != NULL) { + /* Presence notification body parsed successfully. */ + 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_presence(op, sub_state, presence_model, NULL); + resp = sal_op_create_response_from_request(op, req, 200); + } else { + /* Formatting error in presence notification body. */ + ms_error("Wrongly formatted presence notification received"); + resp = sal_op_create_response_from_request(op, req, 400); + } + belle_sip_server_transaction_send_response(server_transaction,resp); + } +} + 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)); 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); - const char* body = belle_sip_message_get_body(BELLE_SIP_MESSAGE(req)); - SalPresenceModel *presence_model = NULL; - SalSubscribeStatus sub_state; belle_sip_response_t* resp; + const char *method=belle_sip_request_get_method(req); + 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; 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)); + if (strcmp(method,"SUBSCRIBE")==0){ + 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)); + }else{ /* this is a NOTIFY */ + ms_message("Receiving out of dialog notify"); + handle_notify(op,req); + return; + } } 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)); - 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 (body==NULL){ - ms_error("No body in NOTIFY received from [%s]",sal_op_get_from(op)); - return; - } - presence_model = process_presence_notification(op, req); - if (presence_model != NULL) { - /* Presence notification body parsed successfully. */ - 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_presence(op, sub_state, presence_model, NULL); - resp = sal_op_create_response_from_request(op, req, 200); - } else { - /* Formatting error in presence notification body. */ - ms_error("Wrongly formatted presence notification received"); - resp = sal_op_create_response_from_request(op, req, 400); - } - 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) { - 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); - belle_sip_server_transaction_send_response(server_transaction,resp); - } + case BELLE_SIP_DIALOG_NULL: { + op->base.root->callbacks.subscribe_presence_received(op,sal_op_get_from(op)); + break; } - break; - default: { - ms_error("unexpected dialog state [%s]",belle_sip_dialog_state_to_string(dialog_state)); - } - /* no break */ + case BELLE_SIP_DIALOG_EARLY: + ms_error("unexpected method [%s] for dialog [%p] in state BELLE_SIP_DIALOG_EARLY ",method,op->dialog); + break; + + case BELLE_SIP_DIALOG_CONFIRMED: + if (strcmp("NOTIFY",method)==0) { + handle_notify(op,req); + } else if (strcmp("SUBSCRIBE",method)==0) { + /*either a refresh or an unsubscribe*/ + if (expires && belle_sip_header_expires_get_expires(expires)>0) { + 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); + belle_sip_server_transaction_send_response(server_transaction,resp); + } + } + break; + default: + ms_error("unexpected dialog state [%s]",belle_sip_dialog_state_to_string(dialog_state)); + break; } } diff --git a/coreapi/friend.c b/coreapi/friend.c index 3e3181888..38800f05d 100644 --- a/coreapi/friend.c +++ b/coreapi/friend.c @@ -73,16 +73,16 @@ const char *linphone_online_status_to_string(LinphoneOnlineStatus ss){ static int friend_compare(const void * a, const void * b){ LinphoneAddress *fa=((LinphoneFriend*)a)->uri; LinphoneAddress *fb=((LinphoneFriend*)b)->uri; - if (linphone_address_weak_equal (fa,fb)) return 0; + if (linphone_address_weak_equal(fa,fb)) return 0; return 1; } -MSList *linphone_find_friend(MSList *fl, const LinphoneAddress *friend, LinphoneFriend **lf){ +MSList *linphone_find_friend_by_addr(MSList *fl, const LinphoneAddress *addr, LinphoneFriend **lf){ MSList *res=NULL; LinphoneFriend dummy; if (lf!=NULL) *lf=NULL; - dummy.uri=(LinphoneAddress*)friend; + dummy.uri=(LinphoneAddress*)addr; res=ms_list_find_custom(fl,friend_compare,&dummy); if (lf!=NULL && res!=NULL) *lf=(LinphoneFriend*)res->data; return res; @@ -99,8 +99,9 @@ LinphoneFriend *linphone_find_friend_by_inc_subscribe(MSList *l, SalOp *op){ LinphoneFriend *linphone_find_friend_by_out_subscribe(MSList *l, SalOp *op){ MSList *elem; + LinphoneFriend *lf; for (elem=l;elem!=NULL;elem=elem->next){ - LinphoneFriend *lf=(LinphoneFriend*)elem->data; + lf=(LinphoneFriend*)elem->data; if (lf->outsub==op) return lf; } return NULL; diff --git a/coreapi/presence.c b/coreapi/presence.c index 0d244b28d..6148e3929 100644 --- a/coreapi/presence.c +++ b/coreapi/presence.c @@ -19,6 +19,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "linphonecore.h" #include "private.h" +#include "lpconfig.h" + #include #include #include @@ -1216,14 +1218,14 @@ void linphone_subscription_new(LinphoneCore *lc, SalOp *op, const char *from){ } /* check if we answer to this subscription */ - if (linphone_find_friend(lc->friends,uri,&lf)!=NULL){ + if (linphone_find_friend_by_addr(lc->friends,uri,&lf)!=NULL){ lf->insub=op; lf->inc_subscribe_pending=TRUE; sal_subscribe_accept(op); linphone_friend_done(lf); /*this will do all necessary actions */ }else{ /* check if this subscriber is in our black list */ - if (linphone_find_friend(lc->subscribers,uri,&lf)){ + if (linphone_find_friend_by_addr(lc->subscribers,uri,&lf)){ if (lf->pol==LinphoneSPDeny){ ms_message("Rejecting %s because we already rejected it once.",from); sal_subscribe_decline(op,SalReasonDeclined); @@ -1578,6 +1580,11 @@ void linphone_notify_recv(LinphoneCore *lc, SalOp *op, SalSubscribeStatus ss, Sa LinphonePresenceModel *presence = (LinphonePresenceModel *)model; lf=linphone_find_friend_by_out_subscribe(lc->friends,op); + if (lf==NULL && lp_config_get_int(lc->config,"sip","allow_out_of_subscribe_presence",0)){ + const SalAddress *addr=sal_op_get_from_address(op); + lf=NULL; + linphone_find_friend_by_addr(lc->friends,(LinphoneAddress*)addr,&lf); + } if (lf!=NULL){ LinphonePresenceActivity *activity = NULL; char *activity_str; diff --git a/coreapi/private.h b/coreapi/private.h index e85c169fc..d83ab161a 100644 --- a/coreapi/private.h +++ b/coreapi/private.h @@ -248,6 +248,7 @@ void linphone_friend_close_subscriptions(LinphoneFriend *lf); 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_addr(MSList *fl, const LinphoneAddress *addr, LinphoneFriend **lf); int parse_hostname_to_addr(const char *server, struct sockaddr_storage *ss, socklen_t *socklen); int set_lock_file(); @@ -297,7 +298,7 @@ void linphone_proxy_config_process_authentication_failure(LinphoneCore *lc, SalO void linphone_subscription_answered(LinphoneCore *lc, SalOp *op); void linphone_subscription_closed(LinphoneCore *lc, SalOp *op); -MSList *linphone_find_friend(MSList *fl, const LinphoneAddress *fri, LinphoneFriend **lf); +MSList *linphone_find_friend_by_addr(MSList *fl, const LinphoneAddress *fri, LinphoneFriend **lf); void linphone_core_update_allocated_audio_bandwidth(LinphoneCore *lc); void linphone_core_update_allocated_audio_bandwidth_in_call(LinphoneCall *call, const PayloadType *pt);