local net = require "net" local event = require "event" local syslog = require "syslog" local serial = require "serialization" local cfgfile = "/etc/chatd.cfg" local clients = {} local cfg = {} cfg.port = 194 cfg.topic = "Welcome to the "..os.getenv("HOSTNAME").." chat server." local timer = false local function saveconfig() local f = io.open(cfgfile,"wb") if f then f:write(serial.serialize(cfg)) f:close() end end local function loadconfig() local f = io.open(cfgfile,"rb") if f then local newcfg = serial.unserialize(f:read("*a")) f:close() for k,v in pairs(newcfg) do cfg[k] = v end else saveconfig() end end local function log(msg,level) syslog(msg,level,"chatd") end local function sendToAll(data) for k,v in pairs(clients) do v:write(data) end end local function formatLine(...) local tA = {...} return string.format("%s"..("\t%s"):rep(#tA-1).."\n", ...) end local function clientLoop() for sn, socket in pairs(clients) do local line = socket.rbuffer:match("(.+)\n") if line then socket:read(line:len()+1) local tCmd = {} for w in line:gmatch("[^\t]+") do tCmd[#tCmd+1] = w end if tCmd[1] == "nick" then if socket.nick then sendToAll(formatLine("nick",socket.nick,tCmd[2])) else log(tostring(socket.addr)..":"..tostring(socket.port).." connected as "..tCmd[2]) socket:write(formatLine("topic",cfg.topic)) sendToAll(formatLine("join",tCmd[2])) end socket.nick = tCmd[2] elseif tCmd[1] == "msg" and socket.nick then sendToAll(formatLine("msg",socket.nick,tCmd[2])) end end if socket.state ~= "open" then log(tostring(socket.addr)..":"..tostring(socket.port).." ("..tostring(socket.nick)..") quit") clients[sn] = nil if socket.nick then sendToAll(formatLine("quit",socket.nick)) end end end end local function handleSocket(s) clients[tostring(s.addr)..":"..tostring(s.port)] = s end function start() loadconfig() net.flisten(cfg.port,handleSocket) timer = event.timer(1,clientLoop,math.huge) end function stop() event.ignore("net_msg",handleSocket) event.cancel(timer) for k,v in pairs(clients) do v:close() end end