forked from mirrors/linphone-iphone
Call encryption statistics
This commit is contained in:
parent
46c41c1218
commit
4949ca329a
7 changed files with 237 additions and 1 deletions
|
|
@ -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 */,
|
||||
|
|
|
|||
|
|
@ -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 à l’abri des regards." : {
|
||||
|
||||
},
|
||||
"Chiffrement du média" : {
|
||||
|
||||
},
|
||||
"Clear logs" : {
|
||||
|
||||
|
|
@ -374,6 +380,9 @@
|
|||
},
|
||||
"Etes-vous sûr de vouloir supprimer %@ ?" : {
|
||||
|
||||
},
|
||||
"Faire la validation à nouveau" : {
|
||||
|
||||
},
|
||||
"Favourites" : {
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
97
Linphone/UI/Call/Model/CallMediaEncryptionModel.swift
Normal file
97
Linphone/UI/Call/Model/CallMediaEncryptionModel.swift
Normal 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
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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!)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -263,4 +263,12 @@ class MeetingWaitingRoomViewModel: ObservableObject {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
func cancelMeeting() {
|
||||
coreContext.doOnCoreQueue { core in
|
||||
if core.currentCall != nil {
|
||||
self.telecomManager.terminateCall(call: core.currentCall!)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue