summaryrefslogtreecommitdiff
path: root/xmpp.lua
diff options
context:
space:
mode:
Diffstat (limited to 'xmpp.lua')
-rw-r--r--xmpp.lua180
1 files changed, 131 insertions, 49 deletions
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 = ([[
-<?xml version='1.0'?><stream:stream from='%s' to='%s' version='1.0' xml:lang='en' xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams'>]]):format(conf.jid, conf.server)
+<?xml version='1.0'?><stream:stream from='%s' to='%s' version='1.0' xml:lang='en' xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams'>]]):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 = ([[<stream:stream to='%s' xmlns='jabber:component:accept' xmlns:stream='http://etherx.jabber.org/streams'>]]):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('<handshake/>',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())