simplify remote api, add ios api (#3213)
This commit is contained in:
parent
193361c09a
commit
5e6aaffb09
@ -882,6 +882,38 @@ func apiCancelFile(fileId: Int64) async -> AChatItem? {
|
||||
}
|
||||
}
|
||||
|
||||
func startRemoteCtrl() async throws {
|
||||
try await sendCommandOkResp(.startRemoteCtrl)
|
||||
}
|
||||
|
||||
func registerRemoteCtrl(_ remoteCtrlOOB: RemoteCtrlOOB) async throws -> Int64 {
|
||||
let r = await chatSendCmd(.registerRemoteCtrl(remoteCtrlOOB: remoteCtrlOOB))
|
||||
if case let .remoteCtrlRegistered(rcId) = r { return rcId }
|
||||
throw r
|
||||
}
|
||||
|
||||
func listRemoteCtrls() async throws -> [RemoteCtrlInfo] {
|
||||
let r = await chatSendCmd(.listRemoteCtrls)
|
||||
if case let .remoteCtrlList(rcInfo) = r { return rcInfo }
|
||||
throw r
|
||||
}
|
||||
|
||||
func acceptRemoteCtrl(_ rcId: Int64) async throws {
|
||||
try await sendCommandOkResp(.acceptRemoteCtrl(remoteCtrlId: rcId))
|
||||
}
|
||||
|
||||
func rejectRemoteCtrl(_ rcId: Int64) async throws {
|
||||
try await sendCommandOkResp(.rejectRemoteCtrl(remoteCtrlId: rcId))
|
||||
}
|
||||
|
||||
func stopRemoteCtrl() async throws {
|
||||
try await sendCommandOkResp(.stopRemoteCtrl)
|
||||
}
|
||||
|
||||
func deleteRemoteCtrl(_ rcId: Int64) async throws {
|
||||
try await sendCommandOkResp(.deleteRemoteCtrl(remoteCtrlId: rcId))
|
||||
}
|
||||
|
||||
func networkErrorAlert(_ r: ChatResponse) -> Alert? {
|
||||
switch r {
|
||||
case let .chatCmdError(_, .errorAgent(.BROKER(addr, .TIMEOUT))):
|
||||
|
@ -117,6 +117,13 @@ public enum ChatCommand {
|
||||
case receiveFile(fileId: Int64, encrypted: Bool, inline: Bool?)
|
||||
case setFileToReceive(fileId: Int64, encrypted: Bool)
|
||||
case cancelFile(fileId: Int64)
|
||||
case startRemoteCtrl
|
||||
case registerRemoteCtrl(remoteCtrlOOB: RemoteCtrlOOB)
|
||||
case listRemoteCtrls
|
||||
case acceptRemoteCtrl(remoteCtrlId: Int64)
|
||||
case rejectRemoteCtrl(remoteCtrlId: Int64)
|
||||
case stopRemoteCtrl
|
||||
case deleteRemoteCtrl(remoteCtrlId: Int64)
|
||||
case showVersion
|
||||
case string(String)
|
||||
|
||||
@ -255,6 +262,13 @@ public enum ChatCommand {
|
||||
return s
|
||||
case let .setFileToReceive(fileId, encrypted): return "/_set_file_to_receive \(fileId) encrypt=\(onOff(encrypted))"
|
||||
case let .cancelFile(fileId): return "/fcancel \(fileId)"
|
||||
case .startRemoteCtrl: return "/start remote ctrl"
|
||||
case let .registerRemoteCtrl(oob): return "/register remote ctrl \(oob.caFingerprint)"
|
||||
case let .acceptRemoteCtrl(rcId): return "/accept remote ctrl \(rcId)"
|
||||
case let .rejectRemoteCtrl(rcId): return "/reject remote ctrl \(rcId)"
|
||||
case .listRemoteCtrls: return "/list remote ctrls"
|
||||
case .stopRemoteCtrl: return "/stop remote ctrl"
|
||||
case let .deleteRemoteCtrl(rcId): return "/delete remote ctrl \(rcId)"
|
||||
case .showVersion: return "/version"
|
||||
case let .string(str): return str
|
||||
}
|
||||
@ -367,6 +381,13 @@ public enum ChatCommand {
|
||||
case .receiveFile: return "receiveFile"
|
||||
case .setFileToReceive: return "setFileToReceive"
|
||||
case .cancelFile: return "cancelFile"
|
||||
case .startRemoteCtrl: return "startRemoteCtrl"
|
||||
case .registerRemoteCtrl: return "registerRemoteCtrl"
|
||||
case .listRemoteCtrls: return "listRemoteCtrls"
|
||||
case .acceptRemoteCtrl: return "acceptRemoteCtrl"
|
||||
case .rejectRemoteCtrl: return "rejectRemoteCtrl"
|
||||
case .stopRemoteCtrl: return "stopRemoteCtrl"
|
||||
case .deleteRemoteCtrl: return "deleteRemoteCtrl"
|
||||
case .showVersion: return "showVersion"
|
||||
case .string: return "console command"
|
||||
}
|
||||
@ -563,6 +584,13 @@ public enum ChatResponse: Decodable, Error {
|
||||
case ntfMessages(user_: User?, connEntity: ConnectionEntity?, msgTs: Date?, ntfMessages: [NtfMsgInfo])
|
||||
case newContactConnection(user: UserRef, connection: PendingContactConnection)
|
||||
case contactConnectionDeleted(user: UserRef, connection: PendingContactConnection)
|
||||
case remoteCtrlList(remoteCtrls: [RemoteCtrlInfo])
|
||||
case remoteCtrlRegistered(remoteCtrlId: Int64)
|
||||
case remoteCtrlAnnounce(fingerprint: String)
|
||||
case remoteCtrlFound(remoteCtrl: RemoteCtrl)
|
||||
case remoteCtrlConnecting(remoteCtrlId: Int64, displayName: String)
|
||||
case remoteCtrlConnected(remoteCtrlId: Int64, displayName: String)
|
||||
case remoteCtrlStopped
|
||||
case versionInfo(versionInfo: CoreVersionInfo, chatMigrations: [UpMigration], agentMigrations: [UpMigration])
|
||||
case cmdOk(user: UserRef?)
|
||||
case chatCmdError(user_: UserRef?, chatError: ChatError)
|
||||
@ -699,6 +727,13 @@ public enum ChatResponse: Decodable, Error {
|
||||
case .ntfMessages: return "ntfMessages"
|
||||
case .newContactConnection: return "newContactConnection"
|
||||
case .contactConnectionDeleted: return "contactConnectionDeleted"
|
||||
case .remoteCtrlList: return "remoteCtrlList"
|
||||
case .remoteCtrlRegistered: return "remoteCtrlRegistered"
|
||||
case .remoteCtrlAnnounce: return "remoteCtrlAnnounce"
|
||||
case .remoteCtrlFound: return "remoteCtrlFound"
|
||||
case .remoteCtrlConnecting: return "remoteCtrlConnecting"
|
||||
case .remoteCtrlConnected: return "remoteCtrlConnected"
|
||||
case .remoteCtrlStopped: return "remoteCtrlStopped"
|
||||
case .versionInfo: return "versionInfo"
|
||||
case .cmdOk: return "cmdOk"
|
||||
case .chatCmdError: return "chatCmdError"
|
||||
@ -838,6 +873,13 @@ public enum ChatResponse: Decodable, Error {
|
||||
case let .ntfMessages(u, connEntity, msgTs, ntfMessages): return withUser(u, "connEntity: \(String(describing: connEntity))\nmsgTs: \(String(describing: msgTs))\nntfMessages: \(String(describing: ntfMessages))")
|
||||
case let .newContactConnection(u, connection): return withUser(u, String(describing: connection))
|
||||
case let .contactConnectionDeleted(u, connection): return withUser(u, String(describing: connection))
|
||||
case let .remoteCtrlList(remoteCtrls): return String(describing: remoteCtrls)
|
||||
case let .remoteCtrlRegistered(rcId): return "remote ctrl ID: \(rcId)"
|
||||
case let .remoteCtrlAnnounce(fingerprint): return "fingerprint: \(fingerprint)"
|
||||
case let .remoteCtrlFound(remoteCtrl): return "remote ctrl: \(String(describing: remoteCtrl))"
|
||||
case let .remoteCtrlConnecting(rcId, displayName): return "remote ctrl ID: \(rcId)\nhost displayName: \(displayName)"
|
||||
case let .remoteCtrlConnected(rcId, displayName): return "remote ctrl ID: \(rcId)\nhost displayName: \(displayName)"
|
||||
case .remoteCtrlStopped: return noDetails
|
||||
case let .versionInfo(versionInfo, chatMigrations, agentMigrations): return "\(String(describing: versionInfo))\n\nchat migrations: \(chatMigrations.map(\.upName))\n\nagent migrations: \(agentMigrations.map(\.upName))"
|
||||
case .cmdOk: return noDetails
|
||||
case let .chatCmdError(u, chatError): return withUser(u, String(describing: chatError))
|
||||
@ -1461,6 +1503,23 @@ public enum NotificationPreviewMode: String, SelectableItem {
|
||||
public static var values: [NotificationPreviewMode] = [.message, .contact, .hidden]
|
||||
}
|
||||
|
||||
public struct RemoteCtrlOOB {
|
||||
public var caFingerprint: String
|
||||
}
|
||||
|
||||
public struct RemoteCtrlInfo: Decodable {
|
||||
public var remoteCtrlId: Int64
|
||||
public var displayName: String
|
||||
public var sessionActive: Bool
|
||||
}
|
||||
|
||||
public struct RemoteCtrl: Decodable {
|
||||
var remoteCtrlId: Int64
|
||||
var displayName: String
|
||||
var fingerprint: String
|
||||
var accepted: Bool?
|
||||
}
|
||||
|
||||
public struct CoreVersionInfo: Decodable {
|
||||
public var version: String
|
||||
public var simplexmqVersion: String
|
||||
@ -1488,6 +1547,7 @@ public enum ChatError: Decodable {
|
||||
case errorAgent(agentError: AgentErrorType)
|
||||
case errorStore(storeError: StoreError)
|
||||
case errorDatabase(databaseError: DatabaseError)
|
||||
case errorRemoteCtrl(remoteCtrlError: RemoteCtrlError)
|
||||
case invalidJSON(json: String)
|
||||
}
|
||||
|
||||
@ -1739,3 +1799,15 @@ public enum ArchiveError: Decodable {
|
||||
case `import`(chatError: ChatError)
|
||||
case importFile(file: String, chatError: ChatError)
|
||||
}
|
||||
|
||||
public enum RemoteCtrlError: Decodable {
|
||||
case missing(remoteCtrlId: Int64)
|
||||
case inactive
|
||||
case busy
|
||||
case timeout
|
||||
case disconnected(remoteCtrlId: Int64, reason: String)
|
||||
case connectionLost(remoteCtrlId: Int64, reason: String)
|
||||
case certificateExpired(remoteCtrlId: Int64)
|
||||
case certificateUntrusted(remoteCtrlId: Int64)
|
||||
case badFingerprint
|
||||
}
|
||||
|
@ -1938,8 +1938,8 @@ sealed class CC {
|
||||
class StartRemoteHost(val remoteHostId: Long): CC()
|
||||
class StopRemoteHost(val remoteHostId: Long): CC()
|
||||
class DeleteRemoteHost(val remoteHostId: Long): CC()
|
||||
class RegisterRemoteCtrl(val remoteCtrlOOB: RemoteCtrlOOB): CC()
|
||||
class StartRemoteCtrl(): CC()
|
||||
class RegisterRemoteCtrl(val remoteCtrlOOB: RemoteCtrlOOB): CC()
|
||||
class ListRemoteCtrls(): CC()
|
||||
class AcceptRemoteCtrl(val remoteCtrlId: Long): CC()
|
||||
class RejectRemoteCtrl(val remoteCtrlId: Long): CC()
|
||||
@ -2167,8 +2167,8 @@ sealed class CC {
|
||||
is StartRemoteHost -> "startRemoteHost"
|
||||
is StopRemoteHost -> "stopRemoteHost"
|
||||
is DeleteRemoteHost -> "deleteRemoteHost"
|
||||
is RegisterRemoteCtrl -> "registerRemoteCtrl"
|
||||
is StartRemoteCtrl -> "startRemoteCtrl"
|
||||
is RegisterRemoteCtrl -> "registerRemoteCtrl"
|
||||
is ListRemoteCtrls -> "listRemoteCtrls"
|
||||
is AcceptRemoteCtrl -> "acceptRemoteCtrl"
|
||||
is RejectRemoteCtrl -> "rejectRemoteCtrl"
|
||||
@ -3483,30 +3483,24 @@ sealed class CR {
|
||||
@Serializable @SerialName("callEnded") class CallEnded(val user: UserRef, val contact: Contact): CR()
|
||||
@Serializable @SerialName("newContactConnection") class NewContactConnection(val user: UserRef, val connection: PendingContactConnection): CR()
|
||||
@Serializable @SerialName("contactConnectionDeleted") class ContactConnectionDeleted(val user: UserRef, val connection: PendingContactConnection): CR()
|
||||
// remote events (desktop)
|
||||
@Serializable @SerialName("remoteHostCreated") class RemoteHostCreated(val remoteHostId: Long, val oobData: RemoteCtrlOOB): CR()
|
||||
@Serializable @SerialName("remoteHostList") class RemoteHostList(val remoteHosts: List<RemoteHostInfo>): CR()
|
||||
@Serializable @SerialName("remoteHostConnected") class RemoteHostConnected(val remoteHostId: Long): CR()
|
||||
@Serializable @SerialName("remoteHostStopped") class RemoteHostStopped(val remoteHostId: Long): CR()
|
||||
// remote events (mobile)
|
||||
@Serializable @SerialName("remoteCtrlList") class RemoteCtrlList(val remoteCtrls: List<RemoteCtrlInfo>): CR()
|
||||
@Serializable @SerialName("remoteCtrlRegistered") class RemoteCtrlRegistered(val remoteCtrlId: Long): CR()
|
||||
@Serializable @SerialName("remoteCtrlAnnounce") class RemoteCtrlAnnounce(val fingerprint: String): CR()
|
||||
@Serializable @SerialName("remoteCtrlFound") class RemoteCtrlFound(val remoteCtrl: RemoteCtrl): CR()
|
||||
@Serializable @SerialName("remoteCtrlConnecting") class RemoteCtrlConnecting(val remoteCtrlId: Long, val displayName: String): CR()
|
||||
@Serializable @SerialName("remoteCtrlConnected") class RemoteCtrlConnected(val remoteCtrlId: Long, val displayName: String): CR()
|
||||
@Serializable @SerialName("remoteCtrlStopped") class RemoteCtrlStopped(): CR()
|
||||
@Serializable @SerialName("versionInfo") class VersionInfo(val versionInfo: CoreVersionInfo, val chatMigrations: List<UpMigration>, val agentMigrations: List<UpMigration>): CR()
|
||||
@Serializable @SerialName("cmdOk") class CmdOk(val user: UserRef?): CR()
|
||||
@Serializable @SerialName("chatCmdError") class ChatCmdError(val user_: UserRef?, val chatError: ChatError): CR()
|
||||
@Serializable @SerialName("chatError") class ChatRespError(val user_: UserRef?, val chatError: ChatError): CR()
|
||||
@Serializable @SerialName("archiveImported") class ArchiveImported(val archiveErrors: List<ArchiveError>): CR()
|
||||
// remote events (desktop)
|
||||
@Serializable @SerialName("remoteHostCreated") class RemoteHostCreated(val remoteHostId: Long, val oobData: RemoteCtrlOOB): CR()
|
||||
@Serializable @SerialName("remoteHostList") class RemoteHostList(val remoteHosts: List<RemoteHostInfo>): CR()
|
||||
@Serializable @SerialName("remoteHostStarted") class RemoteHostStarted(val remoteHostId: Long): CR()
|
||||
@Serializable @SerialName("remoteHostConnected") class RemoteHostConnected(val remoteHostId: Long): CR()
|
||||
@Serializable @SerialName("remoteHostStopped") class RemoteHostStopped(val remoteHostId: Long): CR()
|
||||
@Serializable @SerialName("remoteHostDeleted") class RemoteHostDeleted(val remoteHostId: Long): CR()
|
||||
// remote events (mobile)
|
||||
@Serializable @SerialName("remoteCtrlList") class RemoteCtrlList(val remoteCtrls: List<RemoteCtrlInfo>): CR()
|
||||
@Serializable @SerialName("remoteCtrlRegistered") class RemoteCtrlRegistered(val remoteCtrlId: Long): CR()
|
||||
@Serializable @SerialName("remoteCtrlStarted") class RemoteCtrlStarted(): CR()
|
||||
@Serializable @SerialName("remoteCtrlAnnounce") class RemoteCtrlAnnounce(val fingerprint: String): CR()
|
||||
@Serializable @SerialName("remoteCtrlFound") class RemoteCtrlFound(val remoteCtrl: RemoteCtrl): CR()
|
||||
@Serializable @SerialName("remoteCtrlAccepted") class RemoteCtrlAccepted(val remoteCtrlId: Long): CR()
|
||||
@Serializable @SerialName("remoteCtrlRejected") class RemoteCtrlRejected(val remoteCtrlId: Long): CR()
|
||||
@Serializable @SerialName("remoteCtrlConnecting") class RemoteCtrlConnecting(val remoteCtrlId: Long, val displayName: String): CR()
|
||||
@Serializable @SerialName("remoteCtrlConnected") class RemoteCtrlConnected(val remoteCtrlId: Long, val displayName: String): CR()
|
||||
@Serializable @SerialName("remoteCtrlStopped") class RemoteCtrlStopped(): CR()
|
||||
@Serializable @SerialName("remoteCtrlDeleted") class RemoteCtrlDeleted(val remoteCtrlId: Long): CR()
|
||||
// general
|
||||
@Serializable class Response(val type: String, val json: String): CR()
|
||||
@Serializable class Invalid(val str: String): CR()
|
||||
@ -3632,28 +3626,22 @@ sealed class CR {
|
||||
is CallEnded -> "callEnded"
|
||||
is NewContactConnection -> "newContactConnection"
|
||||
is ContactConnectionDeleted -> "contactConnectionDeleted"
|
||||
is RemoteHostCreated -> "remoteHostCreated"
|
||||
is RemoteHostList -> "remoteHostList"
|
||||
is RemoteHostConnected -> "remoteHostConnected"
|
||||
is RemoteHostStopped -> "remoteHostStopped"
|
||||
is RemoteCtrlList -> "remoteCtrlList"
|
||||
is RemoteCtrlRegistered -> "remoteCtrlRegistered"
|
||||
is RemoteCtrlAnnounce -> "remoteCtrlAnnounce"
|
||||
is RemoteCtrlFound -> "remoteCtrlFound"
|
||||
is RemoteCtrlConnecting -> "remoteCtrlConnecting"
|
||||
is RemoteCtrlConnected -> "remoteCtrlConnected"
|
||||
is RemoteCtrlStopped -> "remoteCtrlStopped"
|
||||
is VersionInfo -> "versionInfo"
|
||||
is CmdOk -> "cmdOk"
|
||||
is ChatCmdError -> "chatCmdError"
|
||||
is ChatRespError -> "chatError"
|
||||
is ArchiveImported -> "archiveImported"
|
||||
is RemoteHostCreated -> "remoteHostCreated"
|
||||
is RemoteHostList -> "remoteHostList"
|
||||
is RemoteHostStarted -> "remoteHostStarted"
|
||||
is RemoteHostConnected -> "remoteHostConnected"
|
||||
is RemoteHostStopped -> "remoteHostStopped"
|
||||
is RemoteHostDeleted -> "remoteHostDeleted"
|
||||
is RemoteCtrlList -> "remoteCtrlList"
|
||||
is RemoteCtrlRegistered -> "remoteCtrlRegistered"
|
||||
is RemoteCtrlStarted -> "remoteCtrlStarted"
|
||||
is RemoteCtrlAnnounce -> "remoteCtrlAnnounce"
|
||||
is RemoteCtrlFound -> "remoteCtrlFound"
|
||||
is RemoteCtrlAccepted -> "remoteCtrlAccepted"
|
||||
is RemoteCtrlRejected -> "remoteCtrlRejected"
|
||||
is RemoteCtrlConnecting -> "remoteCtrlConnecting"
|
||||
is RemoteCtrlConnected -> "remoteCtrlConnected"
|
||||
is RemoteCtrlStopped -> "remoteCtrlStopped"
|
||||
is RemoteCtrlDeleted -> "remoteCtrlDeleted"
|
||||
is Response -> "* $type"
|
||||
is Invalid -> "* invalid json"
|
||||
}
|
||||
@ -3779,6 +3767,17 @@ sealed class CR {
|
||||
is CallEnded -> withUser(user, "contact: ${contact.id}")
|
||||
is NewContactConnection -> withUser(user, json.encodeToString(connection))
|
||||
is ContactConnectionDeleted -> withUser(user, json.encodeToString(connection))
|
||||
is RemoteHostCreated -> "remote host ID: $remoteHostId\noobData ${json.encodeToString(oobData)}"
|
||||
is RemoteHostList -> "remote hosts: ${json.encodeToString(remoteHosts)}"
|
||||
is RemoteHostConnected -> "remote host ID: $remoteHostId"
|
||||
is RemoteHostStopped -> "remote host ID: $remoteHostId"
|
||||
is RemoteCtrlList -> json.encodeToString(remoteCtrls)
|
||||
is RemoteCtrlRegistered -> "remote ctrl ID: $remoteCtrlId"
|
||||
is RemoteCtrlAnnounce -> "fingerprint: $fingerprint"
|
||||
is RemoteCtrlFound -> "remote ctrl: ${json.encodeToString(remoteCtrl)}"
|
||||
is RemoteCtrlConnecting -> "remote ctrl ID: $remoteCtrlId\nhost displayName: $displayName"
|
||||
is RemoteCtrlConnected -> "remote ctrl ID: $remoteCtrlId\nhost displayName: $displayName"
|
||||
is RemoteCtrlStopped -> ""
|
||||
is VersionInfo -> "version ${json.encodeToString(versionInfo)}\n\n" +
|
||||
"chat migrations: ${json.encodeToString(chatMigrations.map { it.upName })}\n\n" +
|
||||
"agent migrations: ${json.encodeToString(agentMigrations.map { it.upName })}"
|
||||
@ -3786,23 +3785,6 @@ sealed class CR {
|
||||
is ChatCmdError -> withUser(user_, chatError.string)
|
||||
is ChatRespError -> withUser(user_, chatError.string)
|
||||
is ArchiveImported -> "${archiveErrors.map { it.string } }"
|
||||
is RemoteHostCreated -> "remote host ID: $remoteHostId\noobData ${json.encodeToString(oobData)}"
|
||||
is RemoteHostList -> "remote hosts: ${json.encodeToString(remoteHosts)}"
|
||||
is RemoteHostStarted -> "remote host $remoteHostId"
|
||||
is RemoteHostConnected -> "remote host ID: $remoteHostId"
|
||||
is RemoteHostStopped -> "remote host ID: $remoteHostId"
|
||||
is RemoteHostDeleted -> "remote host ID: $remoteHostId"
|
||||
is RemoteCtrlList -> json.encodeToString(remoteCtrls)
|
||||
is RemoteCtrlRegistered -> "remote ctrl ID: $remoteCtrlId"
|
||||
is RemoteCtrlStarted -> ""
|
||||
is RemoteCtrlAnnounce -> "fingerprint: $fingerprint"
|
||||
is RemoteCtrlFound -> "remote ctrl: ${json.encodeToString(remoteCtrl)}"
|
||||
is RemoteCtrlAccepted -> "remote ctrl ID: $remoteCtrlId"
|
||||
is RemoteCtrlRejected -> "remote ctrl ID: $remoteCtrlId"
|
||||
is RemoteCtrlConnecting -> "remote ctrl ID: $remoteCtrlId\nhost displayName: $displayName"
|
||||
is RemoteCtrlConnected -> "remote ctrl ID: $remoteCtrlId\nhost displayName: $displayName"
|
||||
is RemoteCtrlStopped -> ""
|
||||
is RemoteCtrlDeleted -> "remote ctrl ID: $remoteCtrlId"
|
||||
is Response -> json
|
||||
is Invalid -> str
|
||||
}
|
||||
@ -3948,16 +3930,16 @@ sealed class ChatError {
|
||||
is ChatErrorAgent -> "agent ${agentError.string}"
|
||||
is ChatErrorStore -> "store ${storeError.string}"
|
||||
is ChatErrorDatabase -> "database ${databaseError.string}"
|
||||
is ChatErrorRemoteCtrl -> "remoteCtrl ${remoteCtrlError.string}"
|
||||
is ChatErrorRemoteHost -> "remoteHost ${remoteHostError.string}"
|
||||
is ChatErrorRemoteCtrl -> "remoteCtrl ${remoteCtrlError.string}"
|
||||
is ChatErrorInvalidJSON -> "invalid json ${json}"
|
||||
}
|
||||
@Serializable @SerialName("error") class ChatErrorChat(val errorType: ChatErrorType): ChatError()
|
||||
@Serializable @SerialName("errorAgent") class ChatErrorAgent(val agentError: AgentErrorType): ChatError()
|
||||
@Serializable @SerialName("errorStore") class ChatErrorStore(val storeError: StoreError): ChatError()
|
||||
@Serializable @SerialName("errorDatabase") class ChatErrorDatabase(val databaseError: DatabaseError): ChatError()
|
||||
@Serializable @SerialName("errorRemoteCtrl") class ChatErrorRemoteCtrl(val remoteCtrlError: RemoteCtrlError): ChatError()
|
||||
@Serializable @SerialName("errorRemoteHost") class ChatErrorRemoteHost(val remoteHostError: RemoteHostError): ChatError()
|
||||
@Serializable @SerialName("errorRemoteCtrl") class ChatErrorRemoteCtrl(val remoteCtrlError: RemoteCtrlError): ChatError()
|
||||
@Serializable @SerialName("invalidJSON") class ChatErrorInvalidJSON(val json: String): ChatError()
|
||||
}
|
||||
|
||||
|
@ -1891,18 +1891,18 @@ processChatCommand = \case
|
||||
let pref = uncurry TimedMessagesGroupPreference $ maybe (FEOff, Just 86400) (\ttl -> (FEOn, Just ttl)) ttl_
|
||||
updateGroupProfileByName gName $ \p ->
|
||||
p {groupPreferences = Just . setGroupPreference' SGFTimedMessages pref $ groupPreferences p}
|
||||
CreateRemoteHost -> createRemoteHost
|
||||
ListRemoteHosts -> listRemoteHosts
|
||||
StartRemoteHost rh -> startRemoteHost rh
|
||||
StopRemoteHost rh -> closeRemoteHostSession rh
|
||||
DeleteRemoteHost rh -> deleteRemoteHost rh
|
||||
StartRemoteCtrl -> startRemoteCtrl (execChatCommand Nothing)
|
||||
AcceptRemoteCtrl rc -> acceptRemoteCtrl rc
|
||||
RejectRemoteCtrl rc -> rejectRemoteCtrl rc
|
||||
StopRemoteCtrl -> stopRemoteCtrl
|
||||
RegisterRemoteCtrl oob -> registerRemoteCtrl oob
|
||||
ListRemoteCtrls -> listRemoteCtrls
|
||||
DeleteRemoteCtrl rc -> deleteRemoteCtrl rc
|
||||
CreateRemoteHost -> uncurry CRRemoteHostCreated <$> createRemoteHost
|
||||
ListRemoteHosts -> CRRemoteHostList <$> listRemoteHosts
|
||||
StartRemoteHost rh -> startRemoteHost rh >> ok_
|
||||
StopRemoteHost rh -> closeRemoteHostSession rh >> ok_
|
||||
DeleteRemoteHost rh -> deleteRemoteHost rh >> ok_
|
||||
StartRemoteCtrl -> startRemoteCtrl (execChatCommand Nothing) >> ok_
|
||||
AcceptRemoteCtrl rc -> acceptRemoteCtrl rc >> ok_
|
||||
RejectRemoteCtrl rc -> rejectRemoteCtrl rc >> ok_
|
||||
StopRemoteCtrl -> stopRemoteCtrl >> ok_
|
||||
RegisterRemoteCtrl oob -> CRRemoteCtrlRegistered <$> registerRemoteCtrl oob
|
||||
ListRemoteCtrls -> CRRemoteCtrlList <$> listRemoteCtrls
|
||||
DeleteRemoteCtrl rc -> deleteRemoteCtrl rc >> ok_
|
||||
QuitChat -> liftIO exitSuccess
|
||||
ShowVersion -> do
|
||||
let versionInfo = coreVersionInfo $(simplexmqCommitQ)
|
||||
|
@ -425,8 +425,8 @@ data ChatCommand
|
||||
-- | SwitchRemoteHost (Maybe RemoteHostId) -- ^ Switch current remote host
|
||||
| StopRemoteHost RemoteHostId -- ^ Shut down a running session
|
||||
| DeleteRemoteHost RemoteHostId -- ^ Unregister remote host and remove its data
|
||||
| RegisterRemoteCtrl RemoteCtrlOOB -- ^ Register OOB data for satellite discovery and handshake
|
||||
| StartRemoteCtrl -- ^ Start listening for announcements from all registered controllers
|
||||
| RegisterRemoteCtrl RemoteCtrlOOB -- ^ Register OOB data for satellite discovery and handshake
|
||||
| ListRemoteCtrls
|
||||
| AcceptRemoteCtrl RemoteCtrlId -- ^ Accept discovered data and store confirmation
|
||||
| RejectRemoteCtrl RemoteCtrlId -- ^ Reject and blacklist discovered data
|
||||
@ -631,21 +631,15 @@ data ChatResponse
|
||||
| CRContactConnectionDeleted {user :: User, connection :: PendingContactConnection}
|
||||
| CRRemoteHostCreated {remoteHostId :: RemoteHostId, oobData :: RemoteCtrlOOB}
|
||||
| CRRemoteHostList {remoteHosts :: [RemoteHostInfo]} -- XXX: RemoteHostInfo is mostly concerned with session setup
|
||||
| CRRemoteHostStarted {remoteHostId :: RemoteHostId}
|
||||
| CRRemoteHostConnected {remoteHostId :: RemoteHostId}
|
||||
| CRRemoteHostStopped {remoteHostId :: RemoteHostId}
|
||||
| CRRemoteHostDeleted {remoteHostId :: RemoteHostId}
|
||||
| CRRemoteCtrlList {remoteCtrls :: [RemoteCtrlInfo]}
|
||||
| CRRemoteCtrlRegistered {remoteCtrlId :: RemoteCtrlId}
|
||||
| CRRemoteCtrlStarted
|
||||
| CRRemoteCtrlAnnounce {fingerprint :: C.KeyHash} -- unregistered fingerprint, needs confirmation
|
||||
| CRRemoteCtrlFound {remoteCtrl :: RemoteCtrl} -- registered fingerprint, may connect
|
||||
| CRRemoteCtrlAccepted {remoteCtrlId :: RemoteCtrlId}
|
||||
| CRRemoteCtrlRejected {remoteCtrlId :: RemoteCtrlId}
|
||||
| CRRemoteCtrlConnecting {remoteCtrlId :: RemoteCtrlId, displayName :: Text}
|
||||
| CRRemoteCtrlConnected {remoteCtrlId :: RemoteCtrlId, displayName :: Text}
|
||||
| CRRemoteCtrlStopped
|
||||
| CRRemoteCtrlDeleted {remoteCtrlId :: RemoteCtrlId}
|
||||
| CRSQLResult {rows :: [Text]}
|
||||
| CRSlowSQLQueries {chatQueries :: [SlowSQLQuery], agentQueries :: [SlowSQLQuery]}
|
||||
| CRDebugLocks {chatLockName :: Maybe String, agentLocks :: AgentLocks}
|
||||
@ -667,21 +661,15 @@ allowRemoteEvent :: ChatResponse -> Bool
|
||||
allowRemoteEvent = \case
|
||||
CRRemoteHostCreated {} -> False
|
||||
CRRemoteHostList {} -> False
|
||||
CRRemoteHostStarted {} -> False
|
||||
CRRemoteHostConnected {} -> False
|
||||
CRRemoteHostStopped {} -> False
|
||||
CRRemoteHostDeleted {} -> False
|
||||
CRRemoteCtrlList {} -> False
|
||||
CRRemoteCtrlRegistered {} -> False
|
||||
CRRemoteCtrlStarted {} -> False
|
||||
CRRemoteCtrlAnnounce {} -> False
|
||||
CRRemoteCtrlFound {} -> False
|
||||
CRRemoteCtrlAccepted {} -> False
|
||||
CRRemoteCtrlRejected {} -> False
|
||||
CRRemoteCtrlConnecting {} -> False
|
||||
CRRemoteCtrlConnected {} -> False
|
||||
CRRemoteCtrlStopped {} -> False
|
||||
CRRemoteCtrlDeleted {} -> False
|
||||
_ -> True
|
||||
|
||||
logResponseToFile :: ChatResponse -> Bool
|
||||
|
@ -79,21 +79,20 @@ withRemoteHost remoteHostId action =
|
||||
Nothing -> throwError $ ChatErrorRemoteHost remoteHostId RHMissing
|
||||
Just rh -> action rh
|
||||
|
||||
startRemoteHost :: (ChatMonad m) => RemoteHostId -> m ChatResponse
|
||||
startRemoteHost :: (ChatMonad m) => RemoteHostId -> m ()
|
||||
startRemoteHost remoteHostId = do
|
||||
asks remoteHostSessions >>= atomically . TM.lookup remoteHostId >>= \case
|
||||
Just _ -> throwError $ ChatErrorRemoteHost remoteHostId RHBusy
|
||||
Nothing -> withRemoteHost remoteHostId $ \rh -> do
|
||||
announcer <- async $ run rh
|
||||
chatModifyVar remoteHostSessions $ M.insert remoteHostId RemoteHostSessionStarting {announcer}
|
||||
pure CRRemoteHostStarted {remoteHostId}
|
||||
where
|
||||
cleanup finished = do
|
||||
logInfo "Remote host http2 client fininshed"
|
||||
atomically $ writeTVar finished True
|
||||
M.lookup remoteHostId <$> chatReadVar remoteHostSessions >>= \case
|
||||
Nothing -> logInfo $ "Session already closed for remote host " <> tshow remoteHostId
|
||||
Just _ -> closeRemoteHostSession remoteHostId >>= toView
|
||||
Just _ -> closeRemoteHostSession remoteHostId >> toView (CRRemoteHostStopped remoteHostId)
|
||||
run RemoteHost {storePath, caKey, caCert} = do
|
||||
finished <- newTVarIO False
|
||||
let parent = (C.signatureKeyPair caKey, caCert)
|
||||
@ -142,42 +141,41 @@ pollRemote finished http path action = loop
|
||||
readTVarIO finished >>= (`unless` loop)
|
||||
req = HTTP2Client.requestNoBody "GET" path mempty
|
||||
|
||||
closeRemoteHostSession :: (ChatMonad m) => RemoteHostId -> m ChatResponse
|
||||
closeRemoteHostSession :: (ChatMonad m) => RemoteHostId -> m ()
|
||||
closeRemoteHostSession remoteHostId = withRemoteHostSession remoteHostId $ \session -> do
|
||||
logInfo $ "Closing remote host session for " <> tshow remoteHostId
|
||||
liftIO $ cancelRemoteHostSession session
|
||||
chatWriteVar currentRemoteHost Nothing
|
||||
chatModifyVar remoteHostSessions $ M.delete remoteHostId
|
||||
pure CRRemoteHostStopped {remoteHostId}
|
||||
|
||||
cancelRemoteHostSession :: (MonadUnliftIO m) => RemoteHostSession -> m ()
|
||||
cancelRemoteHostSession = \case
|
||||
RemoteHostSessionStarting {announcer} -> cancel announcer
|
||||
RemoteHostSessionStarted {ctrlClient} -> liftIO $ HTTP2.closeHTTP2Client ctrlClient
|
||||
|
||||
createRemoteHost :: (ChatMonad m) => m ChatResponse
|
||||
createRemoteHost :: (ChatMonad m) => m (RemoteHostId, RemoteCtrlOOB)
|
||||
createRemoteHost = do
|
||||
let displayName = "TODO" -- you don't have remote host name here, it will be passed from remote host
|
||||
((_, caKey), caCert) <- liftIO $ genCredentials Nothing (-25, 24 * 365) displayName
|
||||
storePath <- liftIO randomStorePath
|
||||
remoteHostId <- withStore' $ \db -> insertRemoteHost db storePath displayName caKey caCert
|
||||
let oobData = RemoteCtrlOOB {caFingerprint = C.certificateFingerprint caCert}
|
||||
pure CRRemoteHostCreated {remoteHostId, oobData}
|
||||
pure (remoteHostId, oobData)
|
||||
|
||||
-- | Generate a random 16-char filepath without / in it by using base64url encoding.
|
||||
randomStorePath :: IO FilePath
|
||||
randomStorePath = B.unpack . B64U.encode <$> getRandomBytes 12
|
||||
|
||||
listRemoteHosts :: (ChatMonad m) => m ChatResponse
|
||||
listRemoteHosts :: (ChatMonad m) => m [RemoteHostInfo]
|
||||
listRemoteHosts = do
|
||||
stored <- withStore' getRemoteHosts
|
||||
active <- chatReadVar remoteHostSessions
|
||||
pure $ CRRemoteHostList $ do
|
||||
pure $ do
|
||||
RemoteHost {remoteHostId, storePath, displayName} <- stored
|
||||
let sessionActive = M.member remoteHostId active
|
||||
pure RemoteHostInfo {remoteHostId, storePath, displayName, sessionActive}
|
||||
|
||||
deleteRemoteHost :: (ChatMonad m) => RemoteHostId -> m ChatResponse
|
||||
deleteRemoteHost :: (ChatMonad m) => RemoteHostId -> m ()
|
||||
deleteRemoteHost remoteHostId = withRemoteHost remoteHostId $ \RemoteHost {storePath} -> do
|
||||
chatReadVar filesFolder >>= \case
|
||||
Just baseDir -> do
|
||||
@ -185,7 +183,6 @@ deleteRemoteHost remoteHostId = withRemoteHost remoteHostId $ \RemoteHost {store
|
||||
logError $ "TODO: remove " <> tshow hostStore
|
||||
Nothing -> logWarn "Local file store not available while deleting remote host"
|
||||
withStore' $ \db -> deleteRemoteHostRecord db remoteHostId
|
||||
pure CRRemoteHostDeleted {remoteHostId}
|
||||
|
||||
processRemoteCommand :: (ChatMonad m) => RemoteHostSession -> (ByteString, ChatCommand) -> m ChatResponse
|
||||
processRemoteCommand RemoteHostSessionStarting {} _ = pure . CRChatError Nothing . ChatError $ CEInternalError "sending remote commands before session started"
|
||||
@ -393,7 +390,7 @@ processControllerRequest execChatCommand HTTP2.HTTP2Request {request, reqBody, s
|
||||
|
||||
-- * ChatRequest handlers
|
||||
|
||||
startRemoteCtrl :: (ChatMonad m) => (ByteString -> m ChatResponse) -> m ChatResponse
|
||||
startRemoteCtrl :: (ChatMonad m) => (ByteString -> m ChatResponse) -> m ()
|
||||
startRemoteCtrl execChatCommand =
|
||||
chatReadVar remoteCtrlSession >>= \case
|
||||
Just _busy -> throwError $ ChatErrorRemoteCtrl RCEBusy
|
||||
@ -416,7 +413,6 @@ startRemoteCtrl execChatCommand =
|
||||
chatWriteVar remoteCtrlSession Nothing
|
||||
toView CRRemoteCtrlStopped
|
||||
chatWriteVar remoteCtrlSession $ Just RemoteCtrlSession {discoverer, supervisor, hostServer = Nothing, discovered, accepted, remoteOutputQ}
|
||||
pure CRRemoteCtrlStarted
|
||||
|
||||
discoverRemoteCtrls :: (ChatMonad m) => TM.TMap C.KeyHash TransportHost -> m ()
|
||||
discoverRemoteCtrls discovered = Discovery.withListener go
|
||||
@ -445,33 +441,32 @@ discoverRemoteCtrls discovered = Discovery.withListener go
|
||||
Just RemoteCtrlSession {accepted} -> atomically $ void $ tryPutTMVar accepted remoteCtrlId -- previously accepted controller, connect automatically
|
||||
_nonV4 -> go sock
|
||||
|
||||
registerRemoteCtrl :: (ChatMonad m) => RemoteCtrlOOB -> m ChatResponse
|
||||
registerRemoteCtrl :: (ChatMonad m) => RemoteCtrlOOB -> m RemoteCtrlId
|
||||
registerRemoteCtrl RemoteCtrlOOB {caFingerprint} = do
|
||||
let displayName = "TODO" -- maybe include into OOB data
|
||||
remoteCtrlId <- withStore' $ \db -> insertRemoteCtrl db displayName caFingerprint
|
||||
pure $ CRRemoteCtrlRegistered {remoteCtrlId}
|
||||
pure remoteCtrlId
|
||||
|
||||
listRemoteCtrls :: (ChatMonad m) => m ChatResponse
|
||||
listRemoteCtrls :: (ChatMonad m) => m [RemoteCtrlInfo]
|
||||
listRemoteCtrls = do
|
||||
stored <- withStore' getRemoteCtrls
|
||||
active <-
|
||||
chatReadVar remoteCtrlSession >>= \case
|
||||
Nothing -> pure Nothing
|
||||
Just RemoteCtrlSession {accepted} -> atomically (tryReadTMVar accepted)
|
||||
pure $ CRRemoteCtrlList $ do
|
||||
pure $ do
|
||||
RemoteCtrl {remoteCtrlId, displayName} <- stored
|
||||
let sessionActive = active == Just remoteCtrlId
|
||||
pure RemoteCtrlInfo {remoteCtrlId, displayName, sessionActive}
|
||||
|
||||
acceptRemoteCtrl :: (ChatMonad m) => RemoteCtrlId -> m ChatResponse
|
||||
acceptRemoteCtrl :: (ChatMonad m) => RemoteCtrlId -> m ()
|
||||
acceptRemoteCtrl remoteCtrlId = do
|
||||
withStore' $ \db -> markRemoteCtrlResolution db remoteCtrlId True
|
||||
chatReadVar remoteCtrlSession >>= \case
|
||||
Nothing -> throwError $ ChatErrorRemoteCtrl RCEInactive
|
||||
Just RemoteCtrlSession {accepted} -> atomically . void $ tryPutTMVar accepted remoteCtrlId -- the remote host can now proceed with connection
|
||||
pure $ CRRemoteCtrlAccepted {remoteCtrlId}
|
||||
|
||||
rejectRemoteCtrl :: (ChatMonad m) => RemoteCtrlId -> m ChatResponse
|
||||
rejectRemoteCtrl :: (ChatMonad m) => RemoteCtrlId -> m ()
|
||||
rejectRemoteCtrl remoteCtrlId = do
|
||||
withStore' $ \db -> markRemoteCtrlResolution db remoteCtrlId False
|
||||
chatReadVar remoteCtrlSession >>= \case
|
||||
@ -479,9 +474,8 @@ rejectRemoteCtrl remoteCtrlId = do
|
||||
Just RemoteCtrlSession {discoverer, supervisor} -> do
|
||||
cancel discoverer
|
||||
cancel supervisor
|
||||
pure $ CRRemoteCtrlRejected {remoteCtrlId}
|
||||
|
||||
stopRemoteCtrl :: (ChatMonad m) => m ChatResponse
|
||||
stopRemoteCtrl :: (ChatMonad m) => m ()
|
||||
stopRemoteCtrl =
|
||||
chatReadVar remoteCtrlSession >>= \case
|
||||
Nothing -> throwError $ ChatErrorRemoteCtrl RCEInactive
|
||||
@ -489,7 +483,6 @@ stopRemoteCtrl =
|
||||
cancelRemoteCtrlSession rcs $ do
|
||||
chatWriteVar remoteCtrlSession Nothing
|
||||
toView CRRemoteCtrlStopped
|
||||
pure $ CRCmdOk Nothing
|
||||
|
||||
cancelRemoteCtrlSession_ :: (MonadUnliftIO m) => RemoteCtrlSession -> m ()
|
||||
cancelRemoteCtrlSession_ rcs = cancelRemoteCtrlSession rcs $ pure ()
|
||||
@ -503,12 +496,10 @@ cancelRemoteCtrlSession RemoteCtrlSession {discoverer, supervisor, hostServer} c
|
||||
cancel supervisor -- supervisor is blocked until session progresses
|
||||
cleanup
|
||||
|
||||
deleteRemoteCtrl :: (ChatMonad m) => RemoteCtrlId -> m ChatResponse
|
||||
deleteRemoteCtrl :: (ChatMonad m) => RemoteCtrlId -> m ()
|
||||
deleteRemoteCtrl remoteCtrlId =
|
||||
chatReadVar remoteCtrlSession >>= \case
|
||||
Nothing -> do
|
||||
withStore' $ \db -> deleteRemoteCtrlRecord db remoteCtrlId
|
||||
pure $ CRRemoteCtrlDeleted {remoteCtrlId}
|
||||
Nothing -> withStore' $ \db -> deleteRemoteCtrlRecord db remoteCtrlId
|
||||
Just _ -> throwError $ ChatErrorRemoteCtrl RCEBusy
|
||||
|
||||
withRemoteCtrl :: (ChatMonad m) => RemoteCtrlId -> (RemoteCtrl -> m a) -> m a
|
||||
|
@ -264,21 +264,15 @@ responseToView (currentRH, user_) ChatConfig {logLevel, showReactions, showRecei
|
||||
CRNtfMessages {} -> []
|
||||
CRRemoteHostCreated rhId oobData -> ("remote host " <> sShow rhId <> " created") : viewRemoteCtrlOOBData oobData
|
||||
CRRemoteHostList hs -> viewRemoteHosts hs
|
||||
CRRemoteHostStarted rhId -> ["remote host " <> sShow rhId <> " started"]
|
||||
CRRemoteHostConnected rhId -> ["remote host " <> sShow rhId <> " connected"]
|
||||
CRRemoteHostStopped rhId -> ["remote host " <> sShow rhId <> " stopped"]
|
||||
CRRemoteHostDeleted rhId -> ["remote host " <> sShow rhId <> " deleted"]
|
||||
CRRemoteCtrlList cs -> viewRemoteCtrls cs
|
||||
CRRemoteCtrlRegistered rcId -> ["remote controller " <> sShow rcId <> " registered"]
|
||||
CRRemoteCtrlStarted -> ["remote controller started"]
|
||||
CRRemoteCtrlAnnounce fingerprint -> ["remote controller announced", "connection code:", plain $ strEncode fingerprint]
|
||||
CRRemoteCtrlFound rc -> ["remote controller found:", viewRemoteCtrl rc]
|
||||
CRRemoteCtrlAccepted rcId -> ["remote controller " <> sShow rcId <> " accepted"]
|
||||
CRRemoteCtrlRejected rcId -> ["remote controller " <> sShow rcId <> " rejected"]
|
||||
CRRemoteCtrlConnecting rcId rcName -> ["remote controller " <> sShow rcId <> " connecting to " <> plain rcName]
|
||||
CRRemoteCtrlConnected rcId rcName -> ["remote controller " <> sShow rcId <> " connected, " <> plain rcName]
|
||||
CRRemoteCtrlStopped -> ["remote controller stopped"]
|
||||
CRRemoteCtrlDeleted rcId -> ["remote controller " <> sShow rcId <> " deleted"]
|
||||
CRSQLResult rows -> map plain rows
|
||||
CRSlowSQLQueries {chatQueries, agentQueries} ->
|
||||
let viewQuery SlowSQLQuery {query, queryStats = SlowQueryStats {count, timeMax, timeAvg}} =
|
||||
|
@ -110,10 +110,10 @@ remoteHandshakeTest = testChat2 aliceProfile bobProfile $ \desktop mobile -> do
|
||||
desktop <## "Remote hosts:"
|
||||
desktop <## "1. TODO" -- TODO host name probably should be Maybe, as when host is created there is no name yet
|
||||
desktop ##> "/start remote host 1"
|
||||
desktop <## "remote host 1 started"
|
||||
desktop <## "ok"
|
||||
|
||||
mobile ##> "/start remote ctrl"
|
||||
mobile <## "remote controller started"
|
||||
mobile <## "ok"
|
||||
mobile <## "remote controller announced"
|
||||
mobile <## "connection code:"
|
||||
fingerprint' <- getTermLine mobile
|
||||
@ -126,7 +126,7 @@ remoteHandshakeTest = testChat2 aliceProfile bobProfile $ \desktop mobile -> do
|
||||
mobile <## "Remote controllers:"
|
||||
mobile <## "1. TODO"
|
||||
mobile ##> "/accept remote ctrl 1"
|
||||
mobile <## "remote controller 1 accepted" -- alternative scenario: accepted before controller start
|
||||
mobile <## "ok" -- alternative scenario: accepted before controller start
|
||||
mobile <## "remote controller 1 connecting to TODO"
|
||||
mobile <## "remote controller 1 connected, TODO"
|
||||
|
||||
@ -140,9 +140,9 @@ remoteHandshakeTest = testChat2 aliceProfile bobProfile $ \desktop mobile -> do
|
||||
|
||||
traceM " - Shutting desktop"
|
||||
desktop ##> "/stop remote host 1"
|
||||
desktop <## "remote host 1 stopped"
|
||||
desktop <## "ok"
|
||||
desktop ##> "/delete remote host 1"
|
||||
desktop <## "remote host 1 deleted"
|
||||
desktop <## "ok"
|
||||
desktop ##> "/list remote hosts"
|
||||
desktop <## "No remote hosts"
|
||||
|
||||
@ -151,7 +151,7 @@ remoteHandshakeTest = testChat2 aliceProfile bobProfile $ \desktop mobile -> do
|
||||
mobile <## "ok"
|
||||
mobile <## "remote controller stopped"
|
||||
mobile ##> "/delete remote ctrl 1"
|
||||
mobile <## "remote controller 1 deleted"
|
||||
mobile <## "ok"
|
||||
mobile ##> "/list remote ctrls"
|
||||
mobile <## "No remote controllers"
|
||||
|
||||
@ -173,10 +173,10 @@ remoteCommandTest = testChat3 aliceProfile aliceDesktopProfile bobProfile $ \mob
|
||||
fingerprint <- getTermLine desktop
|
||||
|
||||
desktop ##> "/start remote host 1"
|
||||
desktop <## "remote host 1 started"
|
||||
desktop <## "ok"
|
||||
|
||||
mobile ##> "/start remote ctrl"
|
||||
mobile <## "remote controller started"
|
||||
mobile <## "ok"
|
||||
mobile <## "remote controller announced"
|
||||
mobile <## "connection code:"
|
||||
fingerprint' <- getTermLine mobile
|
||||
@ -184,7 +184,7 @@ remoteCommandTest = testChat3 aliceProfile aliceDesktopProfile bobProfile $ \mob
|
||||
mobile ##> ("/register remote ctrl " <> fingerprint')
|
||||
mobile <## "remote controller 1 registered"
|
||||
mobile ##> "/accept remote ctrl 1"
|
||||
mobile <## "remote controller 1 accepted" -- alternative scenario: accepted before controller start
|
||||
mobile <## "ok" -- alternative scenario: accepted before controller start
|
||||
mobile <## "remote controller 1 connecting to TODO"
|
||||
mobile <## "remote controller 1 connected, TODO"
|
||||
desktop <## "remote host 1 connected"
|
||||
|
@ -33,7 +33,7 @@ main = do
|
||||
describe "SimpleX chat client" chatTests
|
||||
xdescribe'' "SimpleX Broadcast bot" broadcastBotTests
|
||||
xdescribe'' "SimpleX Directory service bot" directoryServiceTests
|
||||
describe "Remote session" remoteTests
|
||||
fdescribe "Remote session" remoteTests
|
||||
where
|
||||
testBracket test = do
|
||||
t <- getSystemTime
|
||||
|
Loading…
Reference in New Issue
Block a user