local serial = require "serialization" local minitel = require "minitel" local thread = require "thread" local syslog = require "syslog" local lz16 = require "liblz16" local inv = require "inv" local rpc = require "rpc" local listeners = {} local coro = {} local config = {port=15,logfile="/tmp/dss.log"} function reload() local f = io.open("/etc/dss/dss.cfg","rb") if not f then os.execute("mkdir /etc/dss") f=io.open("/etc/dss/dss.cfg", "wb") f:write(serial.serialize(config)) f:close() end config = serial.unserialize(f:read("*a")) f:close() local alias = inv.getAliases() for fn,_ in pairs(inv) do for hn,_ in pairs(alias) do rpc.allow(fn,hn) end end end local function parseSearch(str) local criteria = {} for arg in str:gmatch("[^\t]+") do local k,v = arg:match("(.+)=(.*)") criteria[k] = tonumber(v) or v or "" end local fuzzy, compress = criteria.fuzzy or false, criteria.compress or false criteria.fuzzy, criteria.compress = nil, nil return criteria, fuzzy, compress end local function formatEntry(stack) local ft = {} for k,v in pairs(stack) do if type(v) == "string" or type(v) == "number" then ft[k] = v end end return serial.serialize(ft) .. "\n" end local function handleSocket(socket) coro[#coro+1] = thread.create(function() local query repeat os.sleep(0.5) query = socket:read() until query syslog(string.format("[%s:%i] %s",socket.addr,socket.port,query),syslog.info,"mtdss") local criteria, fuzzy, compress = parseSearch(query) local lsock if compress then socket.mode={w=true} lsock = lz16.buffer(socket) else lsock = socket end for slot, stack in pairs(inv.matchAll(criteria,fuzzy)) do lsock:write(formatEntry(stack)) end lsock:close() socket:close() end) syslog(string.format("Connection from %s:%i",socket.addr,socket.port),syslog.info, "mtdss") end function start() for k,v in pairs(inv) do rpc.register("inv_"..k, v) end reload() listeners[#listeners+1] = minitel.flisten(config.port,handleSocket) end function stop() thread.waitForAll(coro) for k,v in pairs(listeners) do event.ignore("net_msg",v) end end