From a3c7a5377615fbe4c972ca0984117ceaf9321ac9 Mon Sep 17 00:00:00 2001 From: Emery Hemingway Date: Mon, 24 Apr 2023 14:15:05 -0500 Subject: [PATCH] XMPP sucks --- jabber_actor.nimble | 2 +- src/jabber_actor.nim | 61 ++++++++++++++++++++++++++++---------------- 2 files changed, 40 insertions(+), 23 deletions(-) diff --git a/jabber_actor.nimble b/jabber_actor.nimble index c6c91c7..9260233 100644 --- a/jabber_actor.nimble +++ b/jabber_actor.nimble @@ -1,6 +1,6 @@ # Package -version = "20230412" +version = "20230424" author = "Emery Hemingway" description = "Jabber Syndicate actor" license = "Unlicense" diff --git a/src/jabber_actor.nim b/src/jabber_actor.nim index b613269..9c29d94 100644 --- a/src/jabber_actor.nim +++ b/src/jabber_actor.nim @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: ☭ Emery Hemingway # SPDX-License-Identifier: Unlicense -import std/asyncdispatch, asyncnet, net, strutils +import std/[asyncdispatch, asyncnet, net, strutils, xmltree] import syndicate import getdns import ./protocol @@ -14,23 +14,35 @@ proc checkError(r: getdns_return_t) = type Client = ref object context: SslContext socket: AsyncSocket + domain, jid: string proc close(client: Client) = try: close(client.socket) except CatchableError: discard # stupid destroyContext(client.context) -proc connect(client: Client; jid: string) {.async.} = - stderr.writeLine "connecting as ", jid - var domains = rsplit(jid, '@', 1) - stderr.writeLine "domains is ", $domains - if domains.len != 2: - stderr.writeLine "invalid JID ", jid - raise newException(ValueError, "invalid JID " & jid) - var serviceProtoName = "_xmpps-client._tcp." & domains[1] +proc runStream(client: Client) {.async.} = + block: + var opening = newXmlTree( + "stream:stream", [], { + "from": client.jid, + "to": client.domain, + "version": "1.0", + "xml:lang": "en", + "xmlns": "jabber:client", + "xmlns:stream": "http://etherx.jabber.org/streams", + }.toXmlAttributes) + var txt = $opening + txt.setLen(text.high) + txt[text.high] = '>' + # XMPP streams are not an XML document + await send(client.socket, $opening) + +proc connect(client: Client) {.async.} = + var serviceProtoName = "_xmpps-client._tcp." & client.domain stderr.writeLine "lookup ", serviceProtoName - let dns = getdns.newContext(true) - # defer: context_destroy(dns) + var dns = getdns.newContext(true) + defer: context_destroy(dns) dns.setResolutionType(GETDNS_RESOLUTION_STUB) var response: Dict checkError service_sync(dns, serviceProtoName, nil, addr response) @@ -40,8 +52,8 @@ proc connect(client: Client; jid: string) {.async.} = wrapSocket(client.context, client.socket) try: let - host = srvAddr["domain_name"].bindata.toFqdn - port = srvAddr["port"].int.Port + host = "jabber.spam.works" # srvAddr["domain_name"].bindata.toFqdn + port = Port 5223 # srvAddr["port"].int.Port stderr.writeLine "connecting to ", host, ":", port await connect(client.socket, host, port) stderr.writeLine "successfully connected to ", host, ":", port @@ -51,16 +63,23 @@ proc connect(client: Client; jid: string) {.async.} = close(client) proc bootClient(turn: var Turn; jid, password: string; ds: Ref): Client = - result = Client( - context: newContext(protTLSv1, CVerifyNone), - socket: newAsyncSocket(), - ) - asyncCheck(turn, connect(result, jid)) + block: + var domains = rsplit(jid, '@', 1) + if domains.len != 2: + stderr.writeLine "invalid JID ", jid + raise newException(ValueError, "invalid JID " & jid) + result = Client( + context: newContext(protTLSv1, CVerifyNone), + socket: newAsyncSocket(), + domain: domains[1], + jid: jid, + ) + waitFor runStream(result) + waitFor connect(result) + waitFor runStream(result) bootDataspace("main") do (root: Ref; turn: var Turn): - stderr.writeLine "connectStdio…" connectStdio(root, turn) - stderr.writeLine "stdio connected" during(turn, root, ?XmppClient) do (jid: string, password: string, ds: Ref): let client = bootClient(turn, jid, password, ds) do: @@ -68,5 +87,3 @@ bootDataspace("main") do (root: Ref; turn: var Turn): close(client) runForever() - -{.error: "during clause not active until retraction".}