Files
2021-09-15 10:58:48 +02:00

277 lines
10 KiB
Swift

//
// GroupChat.swift
// GroupChat
//
// Created by QuentinArguillere on 08/09/2021.
// Copyright © 2021 BelledonneCommunications. All rights reserved.
//
import linphonesw
class AdvancedChatTutorialContext : ObservableObject
{
var mCore: Core!
@Published var coreVersion: String = Core.getVersion
var mRegistrationDelegate : CoreDelegate!
@Published var username : String = "user"
@Published var passwd : String = "pwd"
@Published var domain : String = "sip.example.org"
@Published var loggedIn: Bool = false
@Published var transportType : String = "TLS"
/*------------ Advanced chat tutorial related variables -------*/
var mChatroom : ChatRoom?
var mChatroomDelegate : ChatRoomDelegate!
var mChatMessageDelegate : ChatMessageDelegate!
var mChatMessage : ChatMessage?
var mLastFileMessageReceived : ChatMessage?
@Published var msgToSend : String = "msg"
@Published var remoteAddress : String = "sip:remote@sip.example.org"
@Published var canEditAddress : Bool = true
@Published var isDownloading : Bool = false
@Published var messagesReceived : String = ""
var fileFolderUrl : URL!
var fileUrl : URL!
init()
{
LoggingService.Instance.logLevel = LogLevel.Debug
try? mCore = Factory.Instance.createCore(configPath: "", factoryConfigPath: "", systemContext: nil)
try? mCore.start()
mRegistrationDelegate = CoreDelegateStub(onMessageReceived : { (core: Core, chatRoom: ChatRoom, message: ChatMessage) in
if (self.mChatroom == nil) {
// Check it is an one-to-one encrypted chat room
if (chatRoom.hasCapability(mask: ChatRoomCapabilities.OneToOne.rawValue) &&
chatRoom.hasCapability(mask: ChatRoomCapabilities.Encrypted.rawValue)) {
// Keep the chatRoom object to use it to send messages if it hasn't been created yet
self.mChatroom = chatRoom
self.mChatroom!.addDelegate(delegate: self.mChatroomDelegate)
self.enableEphemeral()
if let remoteAddress = chatRoom.peerAddress?.asStringUriOnly() {
self.remoteAddress = remoteAddress
}
self.canEditAddress = false
}
}
chatRoom.markAsRead()
for content in message.contents {
if (content.isFileTransfer) {
self.mLastFileMessageReceived = message
self.messagesReceived += "\n--File available for download--"
} else if (content.isText) {
self.messagesReceived += "\nThem: \(message.utf8Text)"
}
}
}, onAccountRegistrationStateChanged: { (core: Core, account: Account, state: RegistrationState, message: String) in
NSLog("New registration state is \(state) for user id \( String(describing: account.params?.identityAddress?.asString()))\n")
if (state == .Ok) {
self.loggedIn = true
} else if (state == .Cleared) {
self.loggedIn = false
}
})
mCore.addDelegate(delegate: mRegistrationDelegate)
// This delegate has to be attached to each specific chat message we want to monitor, before sending it
mChatMessageDelegate = ChatMessageDelegateStub(onMsgStateChanged : { (message: ChatMessage, state: ChatMessage.State) in
print("MessageTrace - msg state changed: \(state)\n")
if (state == .InProgress) {
} else if (state == .Delivered) {
// The proxy server has acknowledged the message with a 200 OK
self.messagesReceived += "\nMe: \(message.utf8Text)"
} else if (state == .DeliveredToUser) {
// User has received it
} else if (state == .Displayed) {
// User has read it (client called chatRoom.markAsRead()
} else if (state == .NotDelivered) {
// User might be invalid or not registered
} else if (state == .FileTransferDone && self.isDownloading == true) {
// We finished uploading/downloading the file
self.isDownloading = false
}
})
mChatroomDelegate = ChatRoomDelegateStub ( onStateChanged: { (chatRoom: ChatRoom, newState: ChatRoom.State?) in
if (newState == ChatRoom.State.Created) {
self.enableEphemeral()
}
}, onEphemeralEvent: { (chatRoom: ChatRoom, eventLog: EventLog) in
// This event is generated when the chat room ephemeral settings are being changed
}, onEphemeralMessageTimerStarted: { (chatRoom: ChatRoom, eventLog: EventLog) in
// This is called when a message has been read by all recipient, so the timer has started
}, onEphemeralMessageDeleted: { (chatRoom: ChatRoom, eventLog: EventLog) in
// This is called when a message has expired and we should remove it from the view
})
// example file to send
let documentsPath = NSURL(fileURLWithPath: NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0])
fileFolderUrl = documentsPath.appendingPathComponent("TutorialFiles")
fileUrl = fileFolderUrl?.appendingPathComponent("file_to_transfer.txt")
do{
try FileManager.default.createDirectory(atPath: fileFolderUrl!.path, withIntermediateDirectories: true, attributes: nil)
try String("My file content").write(to: fileUrl!, atomically: false, encoding: .utf8)
}catch let error as NSError{
print("Unable to create d)irectory",error)
}
}
func login() {
do {
var transport : TransportType
if (transportType == "TLS") { transport = TransportType.Tls }
else if (transportType == "TCP") { transport = TransportType.Tcp }
else { transport = TransportType.Udp }
let authInfo = try Factory.Instance.createAuthInfo(username: username, userid: "", passwd: passwd, ha1: "", realm: "", domain: domain)
let accountParams = try mCore.createAccountParams()
let identity = try Factory.Instance.createAddress(addr: String("sip:" + username + "@" + domain))
try! accountParams.setIdentityaddress(newValue: identity)
let address = try Factory.Instance.createAddress(addr: String("sip:" + domain))
try address.setTransport(newValue: transport)
try accountParams.setServeraddress(newValue: address)
accountParams.registerEnabled = true
// We need a conference factory URI set on the Account to be able to create chat rooms with flexisip backend
accountParams.conferenceFactoryUri = "sip:conference-factory@sip.linphone.org"
mCore.addAuthInfo(info: authInfo)
let account = try mCore.createAccount(params: accountParams)
try mCore.addAccount(account: account)
mCore.defaultAccount = account
// We also need a LIME X3DH server URL configured for end to end encryption
mCore.limeX3DhServerUrl = "https://lime.linphone.org/lime-server/lime-server.php"
} catch { NSLog(error.localizedDescription) }
}
func unregister()
{
if let account = mCore.defaultAccount {
let params = account.params
let clonedParams = params?.clone()
clonedParams?.registerEnabled = false
account.params = clonedParams
}
}
func delete() {
if let account = mCore.defaultAccount {
mCore.removeAccount(account: account)
mCore.clearAccounts()
mCore.clearAllAuthInfo()
}
}
func createFlexisipChatRoom() {
do {
// In this tutorial we will create a Flexisip one-to-one chat room with end-to-end encryption
// For it to work, the proxy server we connect to must be an instance of Flexisip
// And we must have configured on the Account a conference-factory URI
let params = try mCore.createDefaultChatRoomParams()
// We won't create a group chat, only a 1-1 with advanced features such as end-to-end encryption
params.backend = ChatRoomBackend.FlexisipChat
params.groupEnabled = false
// We will rely on LIME encryption backend (we must have configured the core.limex3dhServerUrl first)
params.encryptionEnabled = true
params.encryptionBackend = ChatRoomEncryptionBackend.Lime
// A flexisip chat room must have a subject
// But as we are doing a 1-1 chat room here we won't display it, so we can set whatever we want
params.subject = "dummy subject"
if (params.isValid) {
// We also need the SIP address of the person we will chat with
let remote = try Factory.Instance.createAddress(addr: remoteAddress)
// And finally we will need our local SIP address
let localAddress = mCore.defaultAccount?.params?.identityAddress
mChatroom = try mCore.createChatRoom(params: params, localAddr: localAddress, participants: [remote])
// If chat room isn't created yet, wait for it to go in state Created
// as Flexisip chat room creation process is asynchronous
mChatroom!.addDelegate(delegate: mChatroomDelegate)
// Chat room may already be created (for example if you logged in with an account for which the chat room already exists)
if (mChatroom!.state == ChatRoom.State.Created) {
enableEphemeral()
canEditAddress = false
}
}
} catch { NSLog(error.localizedDescription) }
}
func sendMessage() {
do {
if (mChatroom == nil) {
createFlexisipChatRoom()
}
mChatMessage = nil
mChatMessage = try mChatroom!.createMessageFromUtf8(message: msgToSend)
mChatMessage!.addDelegate(delegate: mChatMessageDelegate)
mChatMessage!.send()
msgToSend.removeAll()
} catch { NSLog(error.localizedDescription) }
}
func sendFile() {
do {
if (mChatroom == nil) {
createFlexisipChatRoom()
}
let content = try Factory.Instance.createContent()
content.name = "file_to_transfer.txt"
content.type = "text"
content.subtype = "plain"
content.filePath = fileUrl.path
let chatMessage = try mChatroom!.createFileTransferMessage(initialContent: content)
chatMessage.addDelegate(delegate: mChatMessageDelegate)
mCore.fileTransferServer = "https://www.linphone.org:444/lft.php"
chatMessage.send()
} catch { NSLog(error.localizedDescription) }
}
func downloadLastFileMessage() {
if let message = mLastFileMessageReceived {
for content in message.contents {
if (content.isFileTransfer && content.filePath.isEmpty) {
let contentName = content.name
if (!contentName.isEmpty) {
content.filePath = fileFolderUrl!.appendingPathComponent(contentName).path
print("Start downloading \(content.name) into \(content.filePath)")
isDownloading = true
if (!message.downloadContent(content: content)) {
print ("Download of \(contentName) failed")
}
}
}
}
}
}
func enableEphemeral() {
// Once chat room has been created, we can enable ephemeral feature
// We enable ephemeral messages at the chat room level
// Please note this only affects messages we send, not the ones we receive
mChatroom?.ephemeralEnabled = true
// Here we ask for a lifetime of 60 seconds, starting the moment the message has been read
mChatroom?.ephemeralLifetime = 60
}
}