mirror of
https://gitlab.linphone.org/BC/public/linphone-iphone.git
synced 2026-01-21 21:28:08 +00:00
handle out of dialogs incoming NOTIFY.
Use in [sip]: allow_out_of_subscribe_presence=1 to allow them for presence (unsecure)
This commit is contained in:
parent
ce741028b2
commit
866af779ab
6 changed files with 124 additions and 84 deletions
|
|
@ -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 ",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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue