Call encryption statistics

This commit is contained in:
Benoit Martins 2024-05-02 09:46:23 +02:00
parent 46c41c1218
commit 4949ca329a
7 changed files with 237 additions and 1 deletions

View file

@ -41,6 +41,7 @@
D70A26F02B7D02E6006CC8FC /* ConversationViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D70A26EF2B7D02E6006CC8FC /* ConversationViewModel.swift */; };
D70A26F22B7F5D95006CC8FC /* ConversationFragment.swift in Sources */ = {isa = PBXBuildFile; fileRef = D70A26F12B7F5D95006CC8FC /* ConversationFragment.swift */; };
D70C93DE2AC2D0F60063CA3B /* Localizable.xcstrings in Resources */ = {isa = PBXBuildFile; fileRef = D70C93DD2AC2D0F60063CA3B /* Localizable.xcstrings */; };
D714035B2BE11E00004BD8CA /* CallMediaEncryptionModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D714035A2BE11E00004BD8CA /* CallMediaEncryptionModel.swift */; };
D717071E2AC5922E0037746F /* ColorExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = D717071D2AC5922E0037746F /* ColorExtension.swift */; };
D71707202AC5989C0037746F /* TextExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = D717071F2AC5989C0037746F /* TextExtension.swift */; };
D7173EBE2B7A5C0A00BCC481 /* LinphoneUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7173EBD2B7A5C0A00BCC481 /* LinphoneUtils.swift */; };
@ -191,6 +192,7 @@
D70A26EF2B7D02E6006CC8FC /* ConversationViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConversationViewModel.swift; sourceTree = "<group>"; };
D70A26F12B7F5D95006CC8FC /* ConversationFragment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConversationFragment.swift; sourceTree = "<group>"; };
D70C93DD2AC2D0F60063CA3B /* Localizable.xcstrings */ = {isa = PBXFileReference; lastKnownFileType = text.json.xcstrings; path = Localizable.xcstrings; sourceTree = "<group>"; };
D714035A2BE11E00004BD8CA /* CallMediaEncryptionModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallMediaEncryptionModel.swift; sourceTree = "<group>"; };
D717071D2AC5922E0037746F /* ColorExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ColorExtension.swift; sourceTree = "<group>"; };
D717071F2AC5989C0037746F /* TextExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextExtension.swift; sourceTree = "<group>"; };
D7173EBD2B7A5C0A00BCC481 /* LinphoneUtils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LinphoneUtils.swift; sourceTree = "<group>"; };
@ -523,6 +525,7 @@
isa = PBXGroup;
children = (
D720E6AC2BAD822000DDFD87 /* ParticipantModel.swift */,
D714035A2BE11E00004BD8CA /* CallMediaEncryptionModel.swift */,
);
path = Model;
sourceTree = "<group>";
@ -1000,6 +1003,7 @@
6613A0B42BAEBE3F008923A4 /* MeetingViewModel.swift in Sources */,
D7173EBE2B7A5C0A00BCC481 /* LinphoneUtils.swift in Sources */,
66C492012B24DB6900CEA16D /* Log.swift in Sources */,
D714035B2BE11E00004BD8CA /* CallMediaEncryptionModel.swift in Sources */,
6613A0B62BAEBE5C008923A4 /* ScheduleMeetingViewModel.swift in Sources */,
D748BF2C2ACD82D2004844EB /* ThirdPartySipAccountLoginFragment.swift in Sources */,
D7CEE0382B7A214F00FD79B7 /* ConversationsListViewModel.swift in Sources */,

View file

@ -192,6 +192,9 @@
},
"All modifications will be canceled." : {
},
"Annuler" : {
},
"Appel" : {
@ -257,6 +260,9 @@
},
"Chiffrement de bout en bout de tous vos échanges, grâce au mode default vos communications sont à labri des regards." : {
},
"Chiffrement du média" : {
},
"Clear logs" : {
@ -374,6 +380,9 @@
},
"Etes-vous sûr de vouloir supprimer %@ ?" : {
},
"Faire la validation à nouveau" : {
},
"Favourites" : {

View file

@ -41,6 +41,7 @@ struct CallView: View {
@State var audioRouteSheet: Bool = false
@State var changeLayoutSheet: Bool = false
@State var mediaEncryptedSheet: Bool = false
@State var optionsAudioRoute: Int = 1
@State var optionsChangeLayout: Int = 2
@State var imageAudioRoute: String = ""
@ -64,6 +65,12 @@ struct CallView: View {
ZStack {
if #available(iOS 16.4, *), idiom != .pad {
innerView(geometry: geo)
.sheet(isPresented: $mediaEncryptedSheet, onDismiss: {
mediaEncryptedSheet = false
}) {
mediaEncryptedSheetBottomSheet()
.presentationDetents([.medium])
}
.sheet(isPresented: $audioRouteSheet, onDismiss: {
audioRouteSheet = false
}) {
@ -87,6 +94,12 @@ struct CallView: View {
}
} else if #available(iOS 16.0, *), idiom != .pad {
innerView(geometry: geo)
.sheet(isPresented: $mediaEncryptedSheet, onDismiss: {
mediaEncryptedSheet = false
}) {
mediaEncryptedSheetBottomSheet()
.presentationDetents([.medium])
}
.sheet(isPresented: $audioRouteSheet, onDismiss: {
audioRouteSheet = false
}) {
@ -109,6 +122,11 @@ struct CallView: View {
}
} else {
innerView(geometry: geo)
.halfSheet(showSheet: $mediaEncryptedSheet) {
mediaEncryptedSheetBottomSheet()
} onDismiss: {
mediaEncryptedSheet = false
}
.halfSheet(showSheet: $audioRouteSheet) {
audioRouteBottomSheet()
} onDismiss: {
@ -168,6 +186,83 @@ struct CallView: View {
}
}
@ViewBuilder
func mediaEncryptedSheetBottomSheet() -> some View {
VStack {
if idiom != .pad && (orientation == .landscapeLeft
|| orientation == .landscapeRight
|| UIScreen.main.bounds.size.width > UIScreen.main.bounds.size.height) {
Spacer()
HStack {
Spacer()
Button("Close") {
mediaEncryptedSheet = false
}
}
.padding(.trailing)
} else {
Capsule()
.fill(Color.grayMain2c300)
.frame(width: 75, height: 5)
.padding(15)
}
Text("Chiffrement du média")
.default_text_style_white_600(styleSize: 15)
.padding(.top, 10)
Spacer()
Text(callViewModel.callMediaEncryptionModel.mediaEncryption)
.default_text_style_white(styleSize: 15)
Spacer()
Text(callViewModel.callMediaEncryptionModel.zrtpCipher)
.default_text_style_white(styleSize: 15)
Spacer()
Text(callViewModel.callMediaEncryptionModel.zrtpKeyAgreement)
.default_text_style_white(styleSize: 15)
Spacer()
Text(callViewModel.callMediaEncryptionModel.zrtpHash)
.default_text_style_white(styleSize: 15)
Spacer()
Text(callViewModel.callMediaEncryptionModel.zrtpAuthTag)
.default_text_style_white(styleSize: 15)
Spacer()
Text(callViewModel.callMediaEncryptionModel.zrtpAuthSas)
.default_text_style_white(styleSize: 15)
.padding(.bottom, 10)
Spacer()
Button(action: {
callViewModel.showZrtpSasDialogIfPossible()
mediaEncryptedSheet = false
}, label: {
Text("Faire la validation à nouveau")
.default_text_style_white_600(styleSize: 20)
.frame(height: 35)
.frame(maxWidth: .infinity)
})
.padding(.horizontal, 20)
.padding(.vertical, 10)
.background(Color.orangeMain500)
.cornerRadius(60)
.padding(.bottom)
.padding(.horizontal, 10)
}
.background(Color.gray600)
}
@ViewBuilder
func audioRouteBottomSheet() -> some View {
VStack(spacing: 0) {
@ -479,7 +574,7 @@ struct CallView: View {
Spacer()
}
.onTapGesture {
callViewModel.showZrtpSasDialogIfPossible()
mediaEncryptedSheet = true
}
.frame(height: 40)
.zIndex(1)

View file

@ -386,6 +386,21 @@ struct MeetingWaitingRoomFragment: View {
.frame(width: 35, height: 35)
Spacer()
Button(action: {
meetingWaitingRoomViewModel.cancelMeeting()
}, label: {
Text("Annuler")
.default_text_style_white_600(styleSize: 20)
.frame(height: 35)
.frame(maxWidth: .infinity)
})
.padding(.horizontal, 20)
.padding(.vertical, 10)
.background(Color.orangeMain500)
.cornerRadius(60)
.padding(.bottom)
.padding(.horizontal, 10)
}
}

View file

@ -0,0 +1,97 @@
/*
* Copyright (c) 2010-2020 Belledonne Communications SARL.
*
* This file is part of linphone-iphone
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import Foundation
import linphonesw
class CallMediaEncryptionModel: ObservableObject {
var coreContext = CoreContext.shared
@Published var mediaEncryption = ""
@Published var isMediaEncryptionZrtp = false
@Published var zrtpCipher = ""
@Published var zrtpKeyAgreement = ""
@Published var zrtpHash = ""
@Published var zrtpAuthTag = ""
@Published var zrtpAuthSas = ""
func update(call: Call) {
coreContext.doOnCoreQueue { core in
var stats = call.getStats(type: StreamType.Audio)
if stats != nil {
// ZRTP stats are only available when authentication token isn't null !
if call.currentParams!.mediaEncryption == .ZRTP && call.authenticationToken != nil {
let isMediaEncryptionZrtpTmp = true
var mediaEncryptionTmp = ""
if stats!.isZrtpKeyAgreementAlgoPostQuantum {
mediaEncryptionTmp = "Media encryption: " + "Post Quantum ZRTP"
} else {
switch call.currentParams!.mediaEncryption {
case .None:
mediaEncryptionTmp = "Media encryption: " + "None"
case .SRTP:
mediaEncryptionTmp = "Media encryption: " + "SRTP"
case .ZRTP:
mediaEncryptionTmp = "Media encryption: " + "ZRTP"
case .DTLS:
mediaEncryptionTmp = "Media encryption: " + "DTLS"
default:
mediaEncryptionTmp = "Media encryption: " + "None"
}
}
let zrtpCipherTmp = "Cipher algorithm: " + stats!.zrtpCipherAlgo
let zrtpKeyAgreementTmp = "Key agreement algorithm: " + stats!.zrtpKeyAgreementAlgo
let zrtpHashTmp = "Hash algorithm: " + stats!.zrtpHashAlgo
let zrtpAuthTagTmp = "Authentication algorithm: " + stats!.zrtpAuthTagAlgo
let zrtpAuthSasTmp = "SAS algorithm: " + stats!.zrtpSasAlgo
DispatchQueue.main.async {
self.isMediaEncryptionZrtp = isMediaEncryptionZrtpTmp
self.mediaEncryption = mediaEncryptionTmp
self.zrtpCipher = zrtpCipherTmp
self.zrtpKeyAgreement = zrtpKeyAgreementTmp
self.zrtpHash = zrtpHashTmp
self.zrtpAuthTag = zrtpAuthTagTmp
self.zrtpAuthSas = zrtpAuthSasTmp
}
} else {
let mediaEncryptionTmp = "Media encryption: " + call.currentParams!.mediaEncryption.rawValue.description //call.currentParams.mediaEncryption
DispatchQueue.main.async {
self.mediaEncryption = mediaEncryptionTmp
}
}
}
}
}
}

View file

@ -53,6 +53,7 @@ class CallViewModel: ObservableObject {
@Published var activeSpeakerParticipant: ParticipantModel?
@Published var activeSpeakerName: String = ""
@Published var myParticipantModel: ParticipantModel?
@Published var callMediaEncryptionModel = CallMediaEncryptionModel()
private var mConferenceSuscriptions = Set<AnyCancellable?>()
@ -150,6 +151,10 @@ class CallViewModel: ObservableObject {
let isDeviceTrusted = self.currentCall!.authenticationTokenVerified && authToken != nil
let isRemoteDeviceTrustedTmp = self.telecomManager.callInProgress ? isDeviceTrusted : false
if self.currentCall != nil {
self.callMediaEncryptionModel.update(call: self.currentCall!)
}
DispatchQueue.main.async {
self.direction = directionTmp
self.remoteAddressString = remoteAddressStringTmp
@ -192,6 +197,9 @@ class CallViewModel: ObservableObject {
self.callSuscriptions.insert(self.currentCall!.publisher?.onEncryptionChanged?.postOnMainQueue {(cbVal: (call: Call, on: Bool, authenticationToken: String?)) in
_ = self.updateEncryption()
if self.currentCall != nil {
self.callMediaEncryptionModel.update(call: self.currentCall!)
}
})
}
}

View file

@ -263,4 +263,12 @@ class MeetingWaitingRoomViewModel: ObservableObject {
}
}
}
func cancelMeeting() {
coreContext.doOnCoreQueue { core in
if core.currentCall != nil {
self.telecomManager.terminateCall(call: core.currentCall!)
}
}
}
}