Chatroom tutorial rework : add encryption, sending and receiving of files

This commit is contained in:
QuentinArguillere
2020-10-15 16:10:41 +02:00
parent 6f2684a0c1
commit a625d12c10
2 changed files with 132 additions and 66 deletions

View File

@@ -23,39 +23,30 @@ class ChatRoomExampleContext : ObservableObject
/*------------ Logs related variables ------------------------*/
var loggingUnit = LoggingUnit()
/*-------- Chatroom tutorial related variables ---------------
-------- "A" always initiates the chat, "B" answers --------*/
/*-------- Chatroom tutorial related variables ---------------*/
@Published var dest : String = "sip:chatdest@sip.linphone.org"
@Published var id : String = "sip:thisphone@sip.linphone.org"
@Published var passwd : String = "thispassword"
@Published var loggedIn: Bool = false
let mFactoryUri = "sip:conference-factory@sip.linphone.org"
var mProxyConfig : ProxyConfig!
var mChatMessage : ChatMessage?
var mLastFileMessageReceived : ChatMessage?
let mLinphoneCoreDelegate = LinphoneCoreDelegate()
let mChatMessageDelegate = LinphoneChatMessageTracker()
let mChatRoomDelegate = LinphoneChatRoomStateTracker()
var mChatRoom : ChatRoom?
@Published var encryptionEnabled : Bool = false
@Published var groupChatEnabled : Bool = true
@Published var chatroomState = ChatroomExampleState.Unstarted
@Published var isFlexiSip : Bool = true
@Published var textToSend: String = "msg to send"
@Published var sReceivedMessages : String = ""
@Published var dest : String = "sip:chatdest@sip.linphone.org"
@Published var id : String = "sip:thisphone@sip.linphone.org"
@Published var passwd : String = "mypassword"
@Published var loggedIn: Bool = false
//var fileFolderUrl : URL?
//var fileUrl : URL?
func getStateAsString() -> String
{
switch (chatroomState)
{
case ChatroomExampleState.Unstarted : return "Unstarted"
case ChatroomExampleState.Starting: return "Starting"
case ChatroomExampleState.Started: return "Started"
}
}
var fileFolderUrl : URL?
var fileUrl : URL?
init()
{
@@ -67,23 +58,24 @@ class ChatRoomExampleContext : ObservableObject
// main loop for receiving notifications and doing background linphonecore work:
mCore.autoIterateEnabled = true
mCore.limeX3DhEnabled = true;
mCore.limeX3DhServerUrl = "https://lime.linphone.org/lime-server/lime-server.php"
mCore.fileTransferServer = "https://www.linphone.org:444/lft.php"
try? mCore.start()
// Important ! Will notify when config are registered so that we can proceed with the chatroom creations
// Also handles chat message reception
// Important ! Will notify when config logged in, or when a message is received
mCore.addDelegate(delegate: mLinphoneCoreDelegate)
/*
let documentsPath = NSURL(fileURLWithPath: NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0])
let myFiles = documentsPath.appendingPathComponent("TutorialFiles")
fileUrl = myFiles?.appendingPathComponent("file_to_transfer.txt")
fileFolderUrl = documentsPath.appendingPathComponent("TutorialFiles")
fileUrl = fileFolderUrl?.appendingPathComponent("file_to_transfer.txt")
do{
try FileManager.default.createDirectory(atPath: myFiles!.path, withIntermediateDirectories: true, attributes: nil)
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 directory",error)
print("Unable to create d)irectory",error)
}
*/
}
func createProxyConfigAndRegister()
@@ -109,13 +101,15 @@ class ChatRoomExampleContext : ObservableObject
do {
let chatDest = [try Factory.Instance.createAddress(addr: dest)]
let chatParams = try mCore.createDefaultChatRoomParams()
if (isFlexiSip) {
if (groupChatEnabled) {
chatParams.backend = ChatRoomBackend.FlexisipChat
chatParams.encryptionEnabled = false
chatParams.groupEnabled = false
chatParams.encryptionEnabled = encryptionEnabled
if (encryptionEnabled) {
chatParams.encryptionBackend = ChatRoomEncryptionBackend.Lime
}
chatParams.groupEnabled = groupChatEnabled
chatParams.subject = "Tutorial Chatroom"
mChatRoom = try mCore.createChatRoom(params: chatParams, localAddr: mProxyConfig.contact!, participants: chatDest)
mChatRoom!.addDelegate(delegate: mChatRoomDelegate)
// Flexisip chatroom requires a setup time. The delegate will set the state to started when it is ready.
chatroomState = ChatroomExampleState.Starting
}
@@ -127,17 +121,21 @@ class ChatRoomExampleContext : ObservableObject
}
} catch {
print(error)
return;
}
mChatRoom!.addDelegate(delegate: mChatRoomDelegate)
DispatchQueue.global(qos: .userInitiated).async {
if (self.isFlexiSip) {
if (self.groupChatEnabled) {
// Wait until we're sure that the chatroom is ready to send messages
while(self.chatroomState != ChatroomExampleState.Started){
usleep(100000)
}
}
if let chatRoom = self.mChatRoom {
self.send(room: chatRoom, msg: "Hello, \((self.isFlexiSip) ? "Flexisip" : "Basic") World !")
self.send(room: chatRoom, msg: "Hello, \((self.groupChatEnabled) ? "Group" : "") World !")
}
}
}
@@ -154,7 +152,7 @@ class ChatRoomExampleContext : ObservableObject
{
do
{
self.mChatMessage = try room.createMessage(message: msg)
self.mChatMessage = try room.createMessageFromUtf8(message: msg)
self.mChatMessage!.addDelegate(delegate: self.mChatMessageDelegate)
self.mChatMessage!.send()
} catch {
@@ -168,19 +166,41 @@ class ChatRoomExampleContext : ObservableObject
send(room: chatRoom, msg: textToSend)
}
}
/*
func sendFile()
func sendExampleFile()
{
do {
let content = try mCore.createContent()
content.filePath = fileUrl!.absoluteString
content.filePath = fileUrl!.path
content.name = "file_to_transfer.txt"
content.type = "text"
content.subtype = "plain"
//mChatRoomA?.createFileTransferMessage(initialContent: <#T##Content#>)
print(try String(contentsOf: fileUrl!, encoding: .utf8))
mChatMessage = try mChatRoom!.createFileTransferMessage(initialContent: content)
mChatMessage!.addDelegate(delegate: self.mChatMessageDelegate)
mChatMessage!.send()
}catch let error as NSError {
print("Unable to create directory",error)
}
}*/
}
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)")
if (!message.downloadContent(content: content)) {
print ("Download of \(contentName) failed")
}
}
}
}
}
mLastFileMessageReceived = nil
}
}
@@ -200,29 +220,37 @@ class LinphoneCoreDelegate: CoreDelegate {
tutorialContext.mChatRoom = room
tutorialContext.chatroomState = ChatroomExampleState.Started
}
if (message.contentType == "text/plain") {
tutorialContext.sReceivedMessages += "\n\(message.textContent)"
if (message.hasTextContent()) {
tutorialContext.sReceivedMessages += "\n\(message.utf8Text)"
}
for content in message.contents {
if (content.isFileTransfer) {
tutorialContext.mLastFileMessageReceived = message
tutorialContext.sReceivedMessages += "\n File(s) available(s) for download"
break;
}
}
print(message.contents.count)
}
}
class LinphoneChatRoomStateTracker: ChatRoomDelegate {
var tutorialContext : ChatRoomExampleContext!
func onStateChanged(chatRoom cr: ChatRoom, newState: ChatRoom.State) {
if (newState == ChatRoom.State.Created)
{
// This will only have sense when WE are creating a flexisip chatroom.
print("ChatRoomTrace - Chatroom ready to start")
tutorialContext.chatroomState = ChatroomExampleState.Started
}
}
func onConferenceJoined(chatRoom: ChatRoom, eventLog: EventLog) {
print("ChatRoomTrace - Chatroom ready to start")
tutorialContext.chatroomState = ChatroomExampleState.Started
}
}
class LinphoneChatMessageTracker: ChatMessageDelegate {
func onMsgStateChanged(message msg: ChatMessage, state: ChatMessage.State) {
print("MessageTrace - msg state changed: \(state)\n")
}
func onFileTransferRecv(message: ChatMessage, content: Content, buffer: Buffer) {
}
}

View File

@@ -8,6 +8,16 @@
import SwiftUI
func getStateAsString(chatroomState : ChatroomExampleState) -> String
{
switch (chatroomState)
{
case ChatroomExampleState.Unstarted : return "Unstarted"
case ChatroomExampleState.Starting: return "Starting"
case ChatroomExampleState.Started: return "Started"
}
}
struct ContentView: View {
@ObservedObject var tutorialContext : ChatRoomExampleContext
@@ -36,7 +46,7 @@ struct ContentView: View {
.foregroundColor(Color.white)
.frame(width: 90.0, height: 42.0)
.background(Color.gray)
}
}.disabled(tutorialContext.loggedIn)
Text("Login State : ")
.font(.footnote)
Text(tutorialContext.loggedIn ? "Logged in" : "Unregistered")
@@ -48,20 +58,28 @@ struct ContentView: View {
Text("Chat destination :")
TextField("", text : $tutorialContext.dest)
.textFieldStyle(RoundedBorderTextFieldStyle())
}
}.disabled(tutorialContext.chatroomState != ChatroomExampleState.Unstarted)
.padding(.top, 5)
HStack {
VStack() {
Toggle(isOn: $tutorialContext.isFlexiSip) {
Text("FlexiSip ChatRoom")
}.frame(width: 210).padding(.top)
VStack {
Toggle(isOn: $tutorialContext.groupChatEnabled) {
Text("Group ChatRoom")
}.frame(width: 210)
.padding(.top)
.disabled(tutorialContext.chatroomState != ChatroomExampleState.Unstarted)
Toggle(isOn: $tutorialContext.encryptionEnabled) {
VStack {
Text("Lime Encryption")
Text("(group chat only)").italic().font(.footnote)
}
}.frame(width: 210)
.disabled(tutorialContext.chatroomState != ChatroomExampleState.Unstarted)
HStack {
Text("Chatroom state: ")
.font(.footnote)
Text(tutorialContext.getStateAsString())
Text(getStateAsString(chatroomState: tutorialContext.chatroomState))
.font(.footnote)
.foregroundColor((tutorialContext.chatroomState == ChatroomExampleState.Started) ? Color.green : Color.black)
.foregroundColor((tutorialContext.chatroomState == ChatroomExampleState.Started) ? Color.green : Color .black)
}
}
Button(action: {
@@ -74,9 +92,10 @@ struct ContentView: View {
{
Text((tutorialContext.chatroomState == ChatroomExampleState.Started) ? "Reset" : "Start\nChat")
.font(.largeTitle)
.foregroundColor(Color.white)
.frame(width: 100.0, height: 82.0)
.background(Color.gray)
.foregroundColor(Color.white)
.frame(width: 140.0, height: 100.0)
.background(Color.gray)
.padding()
}
}
HStack {
@@ -99,6 +118,25 @@ struct ContentView: View {
.background(Color.gray)
}.disabled(tutorialContext.chatroomState != ChatroomExampleState.Started)
}
HStack {
Button(action: tutorialContext.sendExampleFile)
{
Text("Send example \n file")
.foregroundColor(Color.white)
.multilineTextAlignment(.center)
.frame(width: 120.0, height: 50.0)
.background(Color.gray)
}.disabled(tutorialContext.chatroomState != ChatroomExampleState.Started)
Button(action: tutorialContext.downloadLastFileMessage)
{
Text("Download last files \n received")
.foregroundColor(Color.white)
.multilineTextAlignment(.center)
.frame(width: 150.0, height: 50.0)
.background(Color.gray)
}.disabled(tutorialContext.mLastFileMessageReceived == nil)
}
}
Spacer()
}.padding(.top)