wip
This commit is contained in:
parent
ff6f3f3ee2
commit
ab01430aae
|
@ -38,7 +38,12 @@ enum Event {
|
||||||
case bindStream
|
case bindStream
|
||||||
case bindStreamDone(String)
|
case bindStreamDone(String)
|
||||||
case bindStreamError
|
case bindStreamError
|
||||||
|
|
||||||
|
// stream established, RFC-6120 procedure done
|
||||||
case streamReady
|
case streamReady
|
||||||
|
|
||||||
|
case requestRoster
|
||||||
|
// case gotRoster // by request or by server push
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: State
|
// MARK: State
|
||||||
|
@ -83,6 +88,7 @@ struct ClientState: Codable & Equatable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MARK: Client
|
||||||
final class XMPPClient {
|
final class XMPPClient {
|
||||||
private var state = ClientState.initial
|
private var state = ClientState.initial
|
||||||
private let logger = ClientLogger()
|
private let logger = ClientLogger()
|
||||||
|
@ -94,7 +100,8 @@ final class XMPPClient {
|
||||||
SessionModule(),
|
SessionModule(),
|
||||||
AuthorizationModule(self.storage),
|
AuthorizationModule(self.storage),
|
||||||
StanzaModule(self.storage),
|
StanzaModule(self.storage),
|
||||||
DiscoveryModule()
|
DiscoveryModule(),
|
||||||
|
RosterModule()
|
||||||
]
|
]
|
||||||
|
|
||||||
init(storage: any XMPPClientStorageProtocol, userAgent: UserAgent) {
|
init(storage: any XMPPClientStorageProtocol, userAgent: UserAgent) {
|
||||||
|
@ -103,7 +110,7 @@ final class XMPPClient {
|
||||||
}
|
}
|
||||||
|
|
||||||
func tryLogin(jid: JID, credentialsId: UUID) {
|
func tryLogin(jid: JID, credentialsId: UUID) {
|
||||||
logger.update(jid.description)
|
logger.update(jid.full)
|
||||||
Task {
|
Task {
|
||||||
await fire(.startClientLogin(jid: jid, credsId: credentialsId))
|
await fire(.startClientLogin(jid: jid, credsId: credentialsId))
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ struct JID: Hashable, CustomStringConvertible, Codable, Equatable {
|
||||||
resourcePart = parts.2
|
resourcePart = parts.2
|
||||||
}
|
}
|
||||||
|
|
||||||
var description: String {
|
var full: String {
|
||||||
var str = "\(localPart)@\(domainPart)"
|
var str = "\(localPart)@\(domainPart)"
|
||||||
if let resource = resourcePart {
|
if let resource = resourcePart {
|
||||||
str += "/\(resource)"
|
str += "/\(resource)"
|
||||||
|
@ -18,6 +18,10 @@ struct JID: Hashable, CustomStringConvertible, Codable, Equatable {
|
||||||
return str
|
return str
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var description: String {
|
||||||
|
full
|
||||||
|
}
|
||||||
|
|
||||||
var hash: Int {
|
var hash: Int {
|
||||||
if let resourcePart {
|
if let resourcePart {
|
||||||
return "\(localPart)@\(domainPart)/\(resourcePart)".hashValue
|
return "\(localPart)@\(domainPart)/\(resourcePart)".hashValue
|
||||||
|
|
|
@ -75,18 +75,26 @@ struct Stanza {
|
||||||
|
|
||||||
// MARK: Init
|
// MARK: Init
|
||||||
extension Stanza {
|
extension Stanza {
|
||||||
static func iqGet(payload: XMLElement) -> Stanza? {
|
static func iqGet(jid: String? = nil, payload: XMLElement) -> Stanza? {
|
||||||
|
var attributes = ["id": XMLElement.randomId, "type": "get"]
|
||||||
|
if let jid {
|
||||||
|
attributes["from"] = jid
|
||||||
|
}
|
||||||
let req = XMLElement(
|
let req = XMLElement(
|
||||||
name: "iq",
|
name: "iq",
|
||||||
xmlns: nil,
|
xmlns: nil,
|
||||||
attributes: ["type": "get", "id": XMLElement.randomId],
|
attributes: attributes,
|
||||||
content: nil,
|
content: nil,
|
||||||
nodes: [payload]
|
nodes: [payload]
|
||||||
)
|
)
|
||||||
return Stanza(wrap: req)
|
return Stanza(wrap: req)
|
||||||
}
|
}
|
||||||
|
|
||||||
static func iqSet(payload: XMLElement) -> Stanza? {
|
static func iqSet(jid: String? = nil, payload: XMLElement) -> Stanza? {
|
||||||
|
var attributes = ["id": XMLElement.randomId, "type": "get"]
|
||||||
|
if let jid {
|
||||||
|
attributes["from"] = jid
|
||||||
|
}
|
||||||
let req = XMLElement(
|
let req = XMLElement(
|
||||||
name: "iq",
|
name: "iq",
|
||||||
xmlns: nil,
|
xmlns: nil,
|
||||||
|
|
28
AnotherIM/xmpp/modules/roster/RosterModule.swift
Normal file
28
AnotherIM/xmpp/modules/roster/RosterModule.swift
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
final class RosterModule: XmppModule {
|
||||||
|
let id = "Roseter module"
|
||||||
|
|
||||||
|
func reduce(oldState: ClientState, with _: Event) -> ClientState {
|
||||||
|
oldState
|
||||||
|
}
|
||||||
|
|
||||||
|
func process(state: ClientState, with event: Event) async -> Event? {
|
||||||
|
switch event {
|
||||||
|
case .streamReady:
|
||||||
|
return .requestRoster
|
||||||
|
|
||||||
|
case .requestRoster:
|
||||||
|
// TODO: check version!
|
||||||
|
let req = Stanza.iqGet(jid: state.jid.full, payload: XMLElement(name: "query", xmlns: "jabber:iq:roster", attributes: [:], content: nil, nodes: []))
|
||||||
|
if let req {
|
||||||
|
return .stanzaOutbound(req)
|
||||||
|
} else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -92,7 +92,7 @@ final class SessionModule: XmppModule {
|
||||||
name: "stream:stream",
|
name: "stream:stream",
|
||||||
xmlns: nil,
|
xmlns: nil,
|
||||||
attributes: [
|
attributes: [
|
||||||
"from": state.jid.description,
|
"from": state.jid.bare,
|
||||||
"to": state.jid.domainPart,
|
"to": state.jid.domainPart,
|
||||||
"xml:lang": "en",
|
"xml:lang": "en",
|
||||||
"version": "1.0",
|
"version": "1.0",
|
||||||
|
|
Loading…
Reference in a new issue