Commit 866af779 authored by Simon Morlat's avatar Simon Morlat
Browse files

handle out of dialogs incoming NOTIFY.

Use in [sip]:
allow_out_of_subscribe_presence=1

to allow them for presence (unsecure)
parent ce741028
......@@ -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;
......
......@@ -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) {
......
......@@ -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 ",method,op->dialog);
break;
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;
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);
}
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);
}
}
break;
default: {
ms_error("unexpected dialog state [%s]",belle_sip_dialog_state_to_string(dialog_state));
}
/* no break */
break;
default:
ms_error("unexpected dialog state [%s]",belle_sip_dialog_state_to_string(dialog_state));
break;
}
}
......
......@@ -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;
......
......@@ -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 <libxml/xmlreader.h>
#include <libxml/xmlwriter.h>
#include <libxml/xpath.h>
......@@ -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;
......
......@@ -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);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment