From bf776624fb59d147b82d2a6a13c36292844a47b7 Mon Sep 17 00:00:00 2001 From: ubq323 Date: Fri, 6 Sep 2024 16:52:27 +0100 Subject: mysterious uncommited changes (actually committing 2025-02-20) --- xmpp.lua | 180 ++++++++++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 131 insertions(+), 49 deletions(-) (limited to 'xmpp.lua') diff --git a/xmpp.lua b/xmpp.lua index 84400bb..24a5a3c 100644 --- a/xmpp.lua +++ b/xmpp.lua @@ -1,26 +1,51 @@ -local xmpp_conf = { - jid='wilson@ubq323.website', - server='ubq323.website', - auth='AHdpbHNvbgBncmVnb3J5PDM=', - resource='cheese', - muc='d@conference.ubq323.website', -} local cqueues = require'cqueues' +local cqaux = require'cqueues.auxlib' local socket = require'cqueues.socket' local xml = require'xml' local X = xml.X local xmlify = xml.xmlify local pprint=require'pprint' -local discord=require'discord' +local Queue = require'queue' +local base64 = require'base64' +local sha1 = require'sha1' +local Xmpp = {} -local function connect(conf) - local sock = assert(socket.connect(conf.server, 5222)) +local function make_auth(authz, authn, password) + -- sasl plain (RFC4616) + return base64.encode(authz..'\0'..authn..'\0'..password) +end + +function Xmpp.makepylon(pylonname, conf, cq, network) + local self = { + pylonname = pylonname, + cq = cq, + network = network, + inbox = Queue.make(), + } + local function conf_var(name) + assert(conf[name] ~= nil, 'missing conf field '..name) + self[name] = conf[name] + end + conf_var 'jid' + conf_var 'server' + conf_var 'resource' + conf_var 'component' + conf_var 'component_secret' + + setmetatable(self, {__index=Xmpp}) + return self + +end + +function Xmpp._connect_c2s(self) + local sock = assert(socket.connect(self.server, 5222)) + self.sock = sock sock:setmode('bn','bn') local start = ([[ -]]):format(conf.jid, conf.server) +]]):format(self.jid, self.server) -- state of the art xml parser local function check_and_send(test, text) @@ -35,68 +60,125 @@ local function connect(conf) check_and_send('proceed', nil) sock:starttls() sock:write(start) + local auth = make_auth('', self.jid:match"(.*)@", self.password) check_and_send('PLAIN', - xmlify(X.auth{xmlns=ietf_urn"sasl", mechanism='PLAIN', conf.auth})) + xmlify(X.auth{xmlns=ietf_urn"sasl", mechanism='PLAIN', auth})) check_and_send('success',start) check_and_send('bind', xmlify(X.iq{type='set', id='aaaa', - X.bind{xmlns=ietf_urn"bind", X.resource{conf.resource}}})) + X.bind{xmlns=ietf_urn"bind", X.resource{self.resource}}})) check_and_send('jid',X.presence{X.show{'chat'}}) return sock end +-- this sucks! no tls! no security! only use on local connections! +function Xmpp._connect_component(self) + local sock = assert(socket.connect(self.server, 5347)) + self.sock = sock + sock:setmode('bn','bn') + -- yes, our component name goes in the 'to' field. don't ask me why + local start = ([[]]):format(self.component) --- local mucs = { --- 'ja@conference.ubq323.website', --- 'a@conference.ubq323.website', --- } - - -local function run_xmpp(cq) - local sock = connect(xmpp_conf) + print(start) - -- sock:write(xmlify( - -- X.presence{to=xmpp_conf.muc..'/wilson', - -- X.x{xmlns='http://jabber.org/protocol/muc', - -- X.history{maxstanzas='0'}}})) + -- state of the art xml parser + local function check_and_send(test, text) + local x = sock:read('-2048') + assert(x:find(test)) + if text then sock:write(text) end + end + sock:write(start) + local streamhead = sock:read('-2048') + print('streamhead', streamhead) + assert(streamhead:find'accept') + local streamid = streamhead:match"id='(.-)'" + sock:write(xmlify(X.handshake{sha1.sha1(streamid..self.component_secret)})) + check_and_send('',nil) - -- cq:wrap(function() - -- local n = 1 - -- while true do - -- sock:write(xmlify( - -- X.message{to=xmpp_conf.muc, type='groupchat', - -- id='wilson_episode_'..n, - -- X.body{'i too am in episode '..n}})) - -- n=n+1 - -- cqueues.sleep(60) - -- end - -- end) + return sock +end - sock:write(xmlify( - X.iq{type='get',to=xmpp_conf.muc, id='info1', - X.query{xmlns='http://jabber.org/protocol/disco#info'}})) +local THE_MUC = 'd@conference.ubq323.website' +function Xmpp.run(self) + self:_connect_component() + self.cq:wrap(self.recving, self) + self.cq:wrap(self.sending, self) +end - for x in xml.stanzae(function() return sock:read('-2048') end) do +function Xmpp.recving(self) + local function getmore() + local function t(...) + pprint(...) + return ... + end + return t(self.sock:read'-2048') + end + for x in xml.stanzae(getmore) do pprint(x) print(xmlify(x)) local body = x'body' and x'body'[1] if x.label == 'message' then - pprint('M', x.xarg.from, body) - if body == 'hi wilson' then - sock:write(xmlify( - X.message{to=xmpp_conf.muc, type='groupchat', - X.body{'hi '..x.xarg.from..'.'}})) + local fr = x.xarg.from + local t = x.xarg.to + if body and fr:match"/" and t == 'wilson@'..self.component then + self.network:post(self.pylonname, THE_MUC, { + body = body, + source = '[x]'..x.xarg.from:match("/(.*)") + }) end - -- discord.grom(x.xarg.from, body or '*(there\'s no body here)*') end end end -local cq = cqueues.new() -cq:wrap(run_xmpp, cq) +function Xmpp.sending(self) + local users_inuse = {} + local nicks_inuse = {} + local function ensure_joined(muc,user,nick) + if nicks_inuse[nick] then return end + user = user:gsub("[^a-zA-Z0-9%.]","."):match("^%.*(.-)%.*$") + while users_inuse[user] do user = user..'-' end + local jid = user..'@'..self.component + local mucjid = muc..'/'..nick + nicks_inuse[nick] = true + users_inuse[user] = true + + self.sock:write(xmlify( + X.presence{from=jid, to=mucjid, + X.x{xmlns='http://jabber.org/protocol/muc', + X.history{maxstanzas='0'}}})) + end + ensure_joined(THE_MUC, 'wilson', 'wilson') + for ch, msg in self.inbox:iter() do + pprint(ch,msg) + ensure_joined(THE_MUC, msg.source, msg.source) + local user = msg.source:gsub("[^a-zA-Z0-9%.]","."):match("^%.*(.-)%.*$") + local jid = user..'@'..self.component + self.sock:write(xmlify( + X.message{to=THE_MUC, type='groupchat', from=jid, + X.body{msg.body}})) + end +end + + +return Xmpp + +-- local cq = cqueues.new() +-- local conf = { +-- jid='wilson@ubq323.website', +-- server='ubq323.website', +-- password='gregory<3', +-- resource='cheese', +-- } +-- local dummy_network = { +-- post = function(self, pylonname, channel, message) +-- pprint(pylonname, channel, message) +-- end +-- } +-- local pylon = Xmpp.makepylon('xmpptest',conf, cq, dummy_network) +-- pylon:run() -pprint(cq:loop()) +-- pprint('peas', cq:loop()) -- cgit v1.2.3