From 62cca99edd142e0bd9b182e5d4a74c583908088b Mon Sep 17 00:00:00 2001 From: cloudwebrtc Date: Wed, 14 Sep 2022 23:07:32 +0800 Subject: [PATCH] fix: Ensures that p2p/group calls are in progress to reject new call invitations, and emits a call reject events. --- lib/src/voip/call.dart | 24 ++++++++++++------------ lib/src/voip/voip.dart | 18 +++++++++++++++--- 2 files changed, 27 insertions(+), 15 deletions(-) diff --git a/lib/src/voip/call.dart b/lib/src/voip/call.dart index f6ec3f0a..6f6cf3ad 100644 --- a/lib/src/voip/call.dart +++ b/lib/src/voip/call.dart @@ -932,17 +932,16 @@ class CallSession { /// This used to be done by calling hangup, but is a separate method and protocol /// event as of MSC2746. /// - Future reject() async { + Future reject({String? reason, bool shouldEmit = true}) async { // stop play ringtone voip.delegate.stopRingtone(); - - if (state != CallState.kRinging) { - Logs().e('[VOIP] Call must be in \'ringing\' state to reject!'); + if (state != CallState.kRinging && state != CallState.kFledgling) { + Logs().e('[VOIP] Call must be in \'ringing|fledgling\' state to reject!'); return; } Logs().d('[VOIP] Rejecting call: $callId'); - await terminate(CallParty.kLocal, CallErrorCode.UserHangup, true); - await sendCallReject(room, callId, lifetimeMs, localPartyId); + await terminate(CallParty.kLocal, CallErrorCode.UserHangup, shouldEmit); + await sendCallReject(room, callId, lifetimeMs, localPartyId, reason); } Future hangup([String? reason, bool suppressEvent = true]) async { @@ -987,15 +986,15 @@ class CallSession { hangupParty = party; hangupReason = reason; - setCallState(CallState.kEnded); + if (shouldEmit) { + setCallState(CallState.kEnded); + } voip.currentCID = null; voip.calls.remove(callId); await cleanUp(); - - onCallHangup.add(this); - - voip.delegate.handleCallEnded(this); if (shouldEmit) { + onCallHangup.add(this); + voip.delegate.handleCallEnded(this); fireCallEvent(CallEvent.kHangup); } } @@ -1432,7 +1431,7 @@ class CallSession { /// [version] is the version of the VoIP specification this message adheres to. This specification is version 1. /// [party_id] The party ID for call, Can be set to client.deviceId. Future sendCallReject( - Room room, String callId, int lifetime, String party_id, + Room room, String callId, int lifetime, String party_id, String? reason, {String version = voipProtoVersion, String? txid}) async { txid ??= 'txid${DateTime.now().millisecondsSinceEpoch}'; @@ -1440,6 +1439,7 @@ class CallSession { 'call_id': callId, 'party_id': party_id, if (groupCallId != null) 'conf_id': groupCallId, + if (reason != null) 'reason': reason, 'version': version, 'lifetime': lifetime, }; diff --git a/lib/src/voip/voip.dart b/lib/src/voip/voip.dart index d9e69a08..0e9bf88e 100644 --- a/lib/src/voip/voip.dart +++ b/lib/src/voip/voip.dart @@ -19,12 +19,12 @@ abstract class WebRTCDelegate { void stopRingtone(); void handleNewCall(CallSession session); void handleCallEnded(CallSession session); - + void handleMissedCall(CallSession session); void handleNewGroupCall(GroupCall groupCall); void handleGroupCallEnded(GroupCall groupCall); - bool get isBackgroud; bool get isWeb; + bool get canHandleNewCall => true; } class VoIP { @@ -200,10 +200,20 @@ class VoIP { newCall.opponentDeviceId = deviceId; newCall.opponentSessionId = content['sender_session_id']; + if (!delegate.canHandleNewCall && + (confId == null || confId != currentGroupCID)) { + Logs().v( + '[VOIP] onCallInvite: canRespondNewCalls is false, maybe user is busy.'); + await newCall.reject(reason: 'busy', shouldEmit: false); + delegate.handleMissedCall(newCall); + return; + } + final offer = RTCSessionDescription( content['offer']['sdp'], content['offer']['type'], ); + await newCall.initWithInvite( callType, offer, sdpStreamMetadata, lifetime, confId != null); @@ -223,7 +233,9 @@ class VoIP { ///TODO: notify the callkeep that the call is incoming. } // Play ringtone - delegate.playRingtone(); + if (confId == null) { + delegate.playRingtone(); + } } Future onCallAnswer(