Skip to content

Commit 3829674

Browse files
dummy_test
1 parent b4e7df7 commit 3829674

File tree

1 file changed

+113
-41
lines changed

1 file changed

+113
-41
lines changed

Monal/Classes/MLCall.m

Lines changed: 113 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,18 @@
2222
@import CallKit;
2323
@import WebRTC;
2424

25+
// Helper to wait for first local video frame before answering
26+
@interface MLFirstVideoFrameRenderer : NSObject<RTCVideoRenderer>
27+
@property (nonatomic, copy) void (^onFirstFrame)(void);
28+
@property (nonatomic, assign) BOOL fired;
29+
@end
30+
31+
@implementation MLFirstVideoFrameRenderer
32+
- (void)setSize:(CGSize)size {}
33+
- (void)renderFrame:(RTCVideoFrame*)frame
34+
{ if(!self.fired && self.onFirstFrame) { self.fired = YES; self.onFirstFrame(); } }
35+
@end
36+
2537
//this is our private interface only shared with MLVoIPProcessor
2638
@interface MLCall() <WebRTCClientDelegate>
2739
{
@@ -1676,47 +1688,7 @@ -(void) processIncomingSDP:(NSNotification*) notification
16761688
DDLogDebug(@"Successfully passed SDP to webRTCClient...");
16771689
//only send a "session-accept" if the remote is the initiator (e.g. this is an incoming call)
16781690
if(self.direction == MLCallDirectionIncoming)
1679-
{
1680-
[self.webRTCClient answerWithCompletion:^(RTCSessionDescription* localSdp) {
1681-
DDLogDebug(@"Sending SDP answer back...");
1682-
NSArray<MLXMLNode*>* children = [HelperTools sdp2xml:localSdp.sdp withInitiator:NO];
1683-
//we got a session-initiate jingle iq
1684-
//--> self.encryptionState will NOT be MLCallEncryptionStateClear, if that iq contained an encrypted fingerprint,
1685-
//--> self.encryptionState WILL be MLCallEncryptionStateClear, if it did not contain such an encrypted fingerprint
1686-
//(in this case we just don't try to decrypt anything, the call will simply be unencrypted but continue)
1687-
//we don't need to check self.remoteOmemoDeviceId, because self.encryptionState will only be different to
1688-
//MLCallEncryptionStateClear if the deviceid is not nil
1689-
if(self.encryptionState != MLCallEncryptionStateClear && ![self encryptFingerprintsInChildren:children])
1690-
{
1691-
DDLogError(@"Could not encrypt local SDP response fingerprint with OMEMO!");
1692-
XMPPIQ* errorIq = [[XMPPIQ alloc] initAsErrorTo:iqNode];
1693-
[errorIq addChildNode:[[MLXMLNode alloc] initWithElement:@"error" withAttributes:@{@"type": @"modify"} andChildren:@[
1694-
[[MLXMLNode alloc] initWithElement:@"not-acceptable" andNamespace:@"urn:ietf:params:xml:ns:xmpp-stanzas"],
1695-
[[MLXMLNode alloc] initWithElement:@"text" andNamespace:@"urn:ietf:params:xml:ns:xmpp-stanzas" andData:@"Could not encrypt call with OMEMO!"],
1696-
] andData:nil]];
1697-
[self.account send:errorIq];
1698-
1699-
[self handleEndCallActionWithReason:MLCallFinishReasonSecurityError];
1700-
return;
1701-
}
1702-
[self.account send:[[XMPPIQ alloc] initAsResponseTo:iqNode]];
1703-
1704-
XMPPIQ* sdpIQ = [[XMPPIQ alloc] initWithType:kiqSetType to:self.fullRemoteJid];
1705-
[sdpIQ addChildNode:[[MLXMLNode alloc] initWithElement:@"jingle" andNamespace:@"urn:xmpp:jingle:1" withAttributes:@{
1706-
@"action": @"session-accept",
1707-
@"sid": self.jmiid,
1708-
} andChildren:children andData:nil]];
1709-
[self.account send:sdpIQ];
1710-
1711-
@synchronized(self.candidateQueueLock) {
1712-
self.localSDP = sdpIQ;
1713-
1714-
DDLogDebug(@"Now handling queued incoming candidate iqs: %lu", (unsigned long)self.incomingCandidateQueue.count);
1715-
for(XMPPIQ* candidateIq in self.incomingCandidateQueue)
1716-
[self processRemoteICECandidate:candidateIq];
1717-
}
1718-
}];
1719-
}
1691+
[self ml_startVideoAndAnswerWhenFirstFrame:iqNode];
17201692
else
17211693
{
17221694
[self.account send:[[XMPPIQ alloc] initAsResponseTo:iqNode]];
@@ -1829,4 +1801,104 @@ -(BOOL) decryptFingerprintsInIqNode:(XMPPIQ*) iqNode
18291801
return retval;
18301802
}
18311803

1804+
- (void) ml_sendImmediateAnswerForIq:(XMPPIQ*) iqNode
1805+
{
1806+
[self.webRTCClient answerWithCompletion:^(RTCSessionDescription* localSdp) {
1807+
DDLogDebug(@"Sending SDP answer back...");
1808+
NSArray<MLXMLNode*>* children = [HelperTools sdp2xml:localSdp.sdp withInitiator:NO];
1809+
//we got a session-initiate jingle iq
1810+
//--> self.encryptionState will NOT be MLCallEncryptionStateClear, if that iq contained an encrypted fingerprint,
1811+
//--> self.encryptionState WILL be MLCallEncryptionStateClear, if it did not contain such an encrypted fingerprint
1812+
//(in this case we just don't try to decrypt anything, the call will simply be unencrypted but continue)
1813+
//we don't need to check self.remoteOmemoDeviceId, because self.encryptionState will only be different to
1814+
//MLCallEncryptionStateClear if the deviceid is not nil
1815+
if(self.encryptionState != MLCallEncryptionStateClear && ![self encryptFingerprintsInChildren:children])
1816+
{
1817+
DDLogError(@"Could not encrypt local SDP response fingerprint with OMEMO!");
1818+
XMPPIQ* errorIq = [[XMPPIQ alloc] initAsErrorTo:iqNode];
1819+
[errorIq addChildNode:[[MLXMLNode alloc] initWithElement:@"error" withAttributes:@{@"type": @"modify"} andChildren:@[
1820+
[[MLXMLNode alloc] initWithElement:@"not-acceptable" andNamespace:@"urn:ietf:params:xml:ns:xmpp-stanzas"],
1821+
[[MLXMLNode alloc] initWithElement:@"text" andNamespace:@"urn:ietf:params:xml:ns:xmpp-stanzas" andData:@"Could not encrypt call with OMEMO!"],
1822+
] andData:nil]];
1823+
[self.account send:errorIq];
1824+
1825+
[self handleEndCallActionWithReason:MLCallFinishReasonSecurityError];
1826+
return;
1827+
}
1828+
[self.account send:[[XMPPIQ alloc] initAsResponseTo:iqNode]];
1829+
1830+
XMPPIQ* sdpIQ = [[XMPPIQ alloc] initWithType:kiqSetType to:self.fullRemoteJid];
1831+
[sdpIQ addChildNode:[[MLXMLNode alloc] initWithElement:@"jingle" andNamespace:@"urn:xmpp:jingle:1" withAttributes:@{
1832+
@"action": @"session-accept",
1833+
@"sid": self.jmiid,
1834+
} andChildren:children andData:nil]];
1835+
[self.account send:sdpIQ];
1836+
1837+
@synchronized(self.candidateQueueLock) {
1838+
self.localSDP = sdpIQ;
1839+
1840+
DDLogDebug(@"Now handling queued incoming candidate iqs: %lu", (unsigned long)self.incomingCandidateQueue.count);
1841+
for(XMPPIQ* candidateIq in self.incomingCandidateQueue)
1842+
[self processRemoteICECandidate:candidateIq];
1843+
}
1844+
}];
1845+
/*
1846+
[self.webRTCClient answerWithCompletion:^(RTCSessionDescription* localSdp) {
1847+
DDLogDebug(@"Sending SDP answer back...");
1848+
NSArray<MLXMLNode*>* children = [HelperTools sdp2xml:localSdp.sdp withInitiator:NO];
1849+
if(self.encryptionState != MLCallEncryptionStateClear && ![self encryptFingerprintsInChildren:children])
1850+
{
1851+
DDLogError(@"Could not encrypt local SDP response fingerprint with OMEMO!");
1852+
XMPPIQ* errorIq = [[XMPPIQ alloc] initAsErrorTo:iqNode];
1853+
[errorIq addChildNode:[[MLXMLNode alloc] initWithElement:@"error" withAttributes:@{@"type": @"modify"} andChildren:@[
1854+
[[MLXMLNode alloc] initWithElement:@"not-acceptable" andNamespace:@"urn:ietf:params:xml:ns:xmpp-stanzas"],
1855+
[[MLXMLNode alloc] initWithElement:@"text" andNamespace:@"urn:ietf:params:xml:ns:xmpp-stanzas" andData:@"Could not encrypt call with OMEMO!"],
1856+
] andData:nil]];
1857+
[self.account send:errorIq];
1858+
[self handleEndCallActionWithReason:MLCallFinishReasonSecurityError];
1859+
return;
1860+
}
1861+
[self.account send:[[XMPPIQ alloc] initAsResponseTo:iqNode]];
1862+
XMPPIQ* sdpIQ = [[XMPPIQ alloc] initWithType:kiqSetType to:self.fullRemoteJid];
1863+
[sdpIQ addChildNode:[[MLXMLNode alloc] initWithElement:@"jingle" andNamespace:@"urn:xmpp:jingle:1" withAttributes:@{
1864+
@"action": @"session-accept",
1865+
@"sid": self.jmiid,
1866+
} andChildren:children andData:nil]];
1867+
[self.account send:sdpIQ];
1868+
@synchronized(self.candidateQueueLock) {
1869+
self.localSDP = sdpIQ;
1870+
DDLogDebug(@"Now handling queued incoming candidate iqs: %lu", (unsigned long)self.incomingCandidateQueue.count);
1871+
for(XMPPIQ* candidateIq in self.incomingCandidateQueue)
1872+
[self processRemoteICECandidate:candidateIq];
1873+
}
1874+
}];
1875+
*/
1876+
}
1877+
1878+
- (void) ml_startVideoAndAnswerWhenFirstFrame:(XMPPIQ*) iqNode
1879+
{
1880+
if(self.callType != MLCallTypeVideo)
1881+
{
1882+
[self ml_sendImmediateAnswerForIq:iqNode];
1883+
return;
1884+
}
1885+
MLFirstVideoFrameRenderer* latch = [MLFirstVideoFrameRenderer new];
1886+
weakify(self);
1887+
__block monal_void_block_t cancelTimeout = createTimer(2.5, (^{
1888+
strongify(self);
1889+
if(self == nil || self.isFinished) return;
1890+
DDLogInfo(@"%@: No local video frame within timeout — answering anyway.", [self short]);
1891+
cancelTimeout = nil;
1892+
[self ml_sendImmediateAnswerForIq:iqNode];
1893+
}));
1894+
latch.onFirstFrame = ^{
1895+
strongify(self);
1896+
if(self == nil || self.isFinished) return;
1897+
if(cancelTimeout) { cancelTimeout(); cancelTimeout = nil; }
1898+
DDLogInfo(@"%@: First local video frame observed — answering now.", [self short]);
1899+
[self ml_sendImmediateAnswerForIq:iqNode];
1900+
};
1901+
[self startCaptureLocalVideoWithRenderer:latch andCameraPosition:AVCaptureDevicePositionFront];
1902+
}
1903+
18321904
@end

0 commit comments

Comments
 (0)