local cqueues = require 'cqueues' local socket = require 'cqueues.socket' local class = require 'r.class' local BasePylon = require 'pylon' local Channel = require 'channel' local Nanochat = class.extend(BasePylon) function Nanochat:init() self:_check_fields "server port poll" end function Nanochat:_connect() self.sock = socket.connect(self.server, tonumber(self.port)) self.sock:write("LAST 0\n") self.sock:read("*l") -- discard count self.lastid = tonumber(assert(self.sock:read("*l"))) self.usids = {} end function Nanochat:recving() while true do self.sock:write("SKIP "..self.lastid.."\n") local deliverables = {} -- holey local n = tonumber(assert(self.sock:read("*l"))) for i=1,n do local msg = assert(self.sock:read("*l")) local chan, msgi = msg:match("^([^ ]+) ()") if chan then local sender, body = msg:match("^([^:]+): (.+)$", msgi) if sender then deliverables[i] = { source_channel=Channel(self, chan), sender=sender, body=body } else deliverables[i] = { source_channel=Channel(self, chan), sender="", body=msg:sub(msgi,-1) } end else -- ignore messages without a channel, they stay nanochat-local end end local s = self.sock:read("*l") self.lastid = tonumber(assert(s)) for i=1,n do local msg = deliverables[i] ; if msg then local id = i - n + self.lastid if self.usids[id] then self.usids[id] = nil else self.log:proto('<', msg.source_channel.descriptor, msg.sender, msg.body) self.wilson:deliver(msg) end end end cqueues.sleep(tonumber(self.poll)) end end function Nanochat:sending() for dest_channel, message in self.inbox:iter() do self.log:proto('>',dest_channel,message.sender,message.body) assert(self.sock:write("SEND "..dest_channel.descriptor.." ["..message.source_channel.pylon.shortname.."] "..message.sender..": "..message.body.."\n")) local id = tonumber(assert(self.sock:read("*l"))) self.usids[id] = true end end return Nanochat