1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
|
local cqueues = require'cqueues'
local socket = require'cqueues.socket'
local condition = require'cqueues.condition'
local pprint = require'pprint'
local rirc = require'rirc'
local Irc = {}
function Irc.makepylon(pylonname, conf)
local self = {pylonname=pylonname}
local function conf_var(name)
assert(conf[name] ~= nil, 'missing conf field '..name)
self[name] = conf[name]
end
conf_var 'host'
conf_var 'port'
conf_var 'password'
conf_var 'nodename'
self.outqueue = {}
self.outcv = condition.new()
setmetatable(self, {__index=Irc})
return self
end
function Irc.send(self, args)
args.source = args.source or self.nodename
rirc.send(self.sock, args)
end
function Irc.connect(self)
self.sock = assert(socket.connect(self.host, self.port))
self:send{'PASS', self.password, '0210-IRC', 'wilson|'}
self:send{'SERVER', self.nodename, '1', 'i am wilson'}
end
function Irc.recving(self)
for line in self.sock:lines "*l" do
print('<', line)
local msg = rirc.parse(line)
if msg.op == 'PING' then
self:send{'PONG', msg.args[1]}
elseif msg.op == 'PRIVMSG' then
local ch = msg.args[1]
local body = msg.args[2]
local source = msg.source
local neighbors = self.network:neighbors_of(self.pylonname, ch)
pprint('gt neighbors', neighbors)
for _,other in ipairs(neighbors) do
other.pylon:enqueue {
channel = other.channel,
body = body,
source = source..'[i]'
}
end
end
end
end
function Irc.sending(self)
local nicks_channels = {}
local function ensure_joined(nick, channel)
if not nicks_channels[nick] then
self:send{'NICK', nick, 1, 'username', 'host', 1, '+', 'realname'}
nicks_channels[nick] = {}
end
if not nicks_channels[nick][channel] then
self:send{source=nick, 'JOIN', channel}
nicks_channels[nick][channel] = true
end
end
local function say(nick, channel, body)
ensure_joined(nick, channel)
self:send{source=nick, 'PRIVMSG', channel, body}
end
say('WILSON', '#test', 'i am wilson')
while true do
while #self.outqueue > 0 do
local queue = self.outqueue
self.outqueue = {}
for _, outmsg in pairs(queue) do
assert(say(outmsg.source, outmsg.channel, outmsg.body))
end
end
self.outcv:wait()
end
end
function Irc.enqueue(self, message)
table.insert(self.outqueue, message)
self.outcv:signal()
end
function Irc.run(self, cq, network)
self.network = network
self:connect()
cq:wrap(self.recving, self)
cq:wrap(self.sending, self)
end
local cq = cqueues.new()
local conf = {
host = 'localhost',
port = '6667',
password = 'mypassword',
nodename = 'wilson.ubq323',
}
local dummy_pylon = {
enqueue = function(self, msg)
print(string.format(
"%s <%s> | %s",
msg.channel, msg.source, msg.body))
end
}
local network = {neighbors_of = function(self, pylonname, channel)
print('looking for neighbors of '..pylonname..', '..channel)
return {
{pylon = dummy_pylon, channel='#bridge'}
}
end}
local pylon = Irc.makepylon('test', conf)
pylon:run(cq, network)
pprint(cq:loop())
|