Skip to content

Commit

Permalink
Ignore call loops spanning multiple accounts on local Monal instance
Browse files Browse the repository at this point in the history
Fixes #952
  • Loading branch information
tmolitor-stud-tu committed Oct 5, 2023
1 parent 9976a6a commit 8fcf0e4
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 15 deletions.
26 changes: 14 additions & 12 deletions Monal/Classes/MLIQProcessor.m
Original file line number Diff line number Diff line change
Expand Up @@ -77,21 +77,23 @@ +(void) processGetIq:(XMPPIQ*) iqNode forAccount:(xmpp*) account

+(void) processSetIq:(XMPPIQ*) iqNode forAccount:(xmpp*) account
{
//these iqs will be ignored if not matching an outgoing or incoming call
//--> no presence leak if the call was not outgoing, because the jmi stanzas creating the call will
//not be processed without isSubscribedFrom in the first place
if(([iqNode check:@"{urn:xmpp:jingle:1}jingle"] && ![iqNode check:@"{urn:xmpp:jingle:1}jingle<action=transport-info>"]))
{
[[MLNotificationQueue currentQueue] postNotificationName:kMonalIncomingSDP object:account userInfo:@{@"iqNode": iqNode}];
return;
}
if([iqNode check:@"{urn:xmpp:jingle:1}jingle<action=transport-info>"])
{
[[MLNotificationQueue currentQueue] postNotificationName:kMonalIncomingICECandidate object:account userInfo:@{@"iqNode": iqNode}];
return;
}

MLContact* contact = [MLContact createContactFromJid:iqNode.fromUser andAccountNo:account.accountNo];
if([account.connectionProperties.identity.jid isEqualToString:iqNode.fromUser] || (contact.isSubscribedFrom && !contact.isGroup))
{
if(([iqNode check:@"{urn:xmpp:jingle:1}jingle"] && ![iqNode check:@"{urn:xmpp:jingle:1}jingle<action=transport-info>"]))
{
[[MLNotificationQueue currentQueue] postNotificationName:kMonalIncomingSDP object:account userInfo:@{@"iqNode": iqNode}];
return;
}

if([iqNode check:@"{urn:xmpp:jingle:1}jingle<action=transport-info>"])
{
[[MLNotificationQueue currentQueue] postNotificationName:kMonalIncomingICECandidate object:account userInfo:@{@"iqNode": iqNode}];
return;
}

//its a roster push (sanity check will be done in processRosterWithAccount:andIqNode:)
if([iqNode check:@"{jabber:iq:roster}query"])
{
Expand Down
23 changes: 20 additions & 3 deletions Monal/Classes/MLVoIPProcessor.m
Original file line number Diff line number Diff line change
Expand Up @@ -226,10 +226,12 @@ -(void) handleIncomingVoipCall:(NSNotification*) notification
if(existingCall == nil || existingCall.state == MLCallStateFinished)
return [self processIncomingCall:notification.userInfo withCompletion:nil];

DDLogDebug(@"Found existing call, trying to break the tie: %@", existingCall);
MLCall* newCall = [self createCallWithJmiPropose:messageNode onAccountNo:accountNo];
if(newCall == nil)
return;

//handle tie breaking: both parties call each other "simultaneously"
DDLogDebug(@"Found existing call, trying to break the tie: %@", existingCall);
if(existingCall.state < MLCallStateConnecting) //e.g. MLCallStateDiscovering or MLCallStateRinging
{
//determine call sort order
Expand Down Expand Up @@ -275,8 +277,15 @@ -(void) processIncomingCall:(NSDictionary* _Nonnull) userInfo withCompletion:(vo
//TODO: handle jmi propose coming from other devices on our account (see TODO in MLMessageProcessor.m)
XMPPMessage* messageNode = userInfo[@"messageNode"];
NSNumber* accountNo = userInfo[@"accountNo"];
MLCall* call = [self createCallWithJmiPropose:messageNode onAccountNo:accountNo];

MLCall* call = [self createCallWithJmiPropose:messageNode onAccountNo:accountNo];
if(call == nil)
{
//call pushkit completion if given
if(completion != nil)
completion();
return;
}
DDLogInfo(@"Now processing new incoming call: %@", call);

//add call to pending calls list
Expand Down Expand Up @@ -745,13 +754,21 @@ -(CXCallUpdate*) constructUpdateForCall:(MLCall*) call
return update;
}

-(MLCall*) createCallWithJmiPropose:(XMPPMessage*) messageNode onAccountNo:(NSNumber*) accountNo
-(MLCall* _Nullable) createCallWithJmiPropose:(XMPPMessage*) messageNode onAccountNo:(NSNumber*) accountNo
{
//if the jmi id is a uuid, just use it, otherwise infer a uuid from the given jmi id
NSUUID* uuid = [messageNode findFirst:@"{urn:xmpp:jingle-message:0}propose@id|uuidcast"];
NSString* jmiid = [messageNode findFirst:@"{urn:xmpp:jingle-message:0}propose@id"];
MLAssert(uuid != nil, @"call uuid invalid!", (@{@"propose@id": nilWrapper(jmiid)}));

//check if we are in a loop (both accounts participating in this call on the same monal instance)
//--> ignore this incoming call if that is true
if([self getCallForJmiid:jmiid] != nil)
{
DDLogWarn(@"Call loop detected, ignoring incoming call...");
return nil;
}

MLCallType callType = MLCallTypeAudio;
if([messageNode check:@"{urn:xmpp:jingle-message:0}propose/{urn:xmpp:jingle:apps:rtp:1}description<media=video>"])
callType = MLCallTypeVideo;
Expand Down

0 comments on commit 8fcf0e4

Please sign in to comment.