From 483bc3bc6481b91b5b8be284cd6fd900f254f9c5 Mon Sep 17 00:00:00 2001 From: Nathaniel Wesley Filardo Date: Sun, 31 May 2020 19:55:17 +0100 Subject: [PATCH] telnetd: switch from fifosock to pipe --- telnetd/telnetd-diag.lua | 4 +- telnetd/telnetd.lua | 98 +++++++++++++++++++++++++++++++--------- 2 files changed, 79 insertions(+), 23 deletions(-) diff --git a/telnetd/telnetd-diag.lua b/telnetd/telnetd-diag.lua index 3d371d7..4e49b18 100644 --- a/telnetd/telnetd-diag.lua +++ b/telnetd/telnetd-diag.lua @@ -7,8 +7,8 @@ return { -- restart in some ticks, so that network callbacks have a chance to fire -- first, or else we might crash. Ick! -- - -- Apparently we need "some" because the fifosock sometimes takes one to do its uncorking - -- and the network stack is its own monstrosity. Either way, probably fine. + -- Apparently we need "some" because the pipe and socket sometimes take one to do its + -- uncorking and the network stack is its own monstrosity. Either way, probably fine. ["restart"] = function(_,s) tmr.create():alarm(10, tmr.ALARM_SINGLE, node.restart) end, ["exec"] = function(l,s) local f, err = loadstring(l) diff --git a/telnetd/telnetd.lua b/telnetd/telnetd.lua index 148dcc7..a427336 100644 --- a/telnetd/telnetd.lua +++ b/telnetd/telnetd.lua @@ -1,7 +1,9 @@ --- DEPEND: net ; fifosock -local self = {} -self.commands = { ["echo"] = function(r,s) s(r) end } -function self.tryin(i,ft,nc,ns,...) -- input, function table, no-command, no-space, args +-- DEPEND: net; pipe + +local M = {} + +M.commands = { ["echo"] = function(r,s) s(r) end } +function M.tryin(i,ft,nc,ns,...) -- input, function table, no-command, no-space, args local ix = i:find("%f[%s]",1,false) if (ix ~= nil) then local c, r = i:sub(1,ix-1), i:sub(ix+1); local cf = ft[c] @@ -9,15 +11,17 @@ function self.tryin(i,ft,nc,ns,...) -- input, function table, no-command, no-spa else ns(i,...) end end -self.on = { ["conn"] = nil, ["disconn"] = nil } -local function tryon(e,...) local c = self.on[e]; if c ~= nil then c(...) end end -function self.rx(tx,input,k) - self.tryin(input, self.commands, +M.on = { ["conn"] = nil, ["disconn"] = nil } + +local function tryon(e,...) local c = M.on[e]; if c ~= nil then c(...) end end + +function M.rx(tx,input,k) + M.tryin(input, M.commands, function(c,r) if c == "quit" then k(false) else local rt = OVL["telnetd-"..c] if type(rt) == 'function' - then self.tryin(r,rt(),function(c2) tx(c.." "..c2.."?") end, function() tx(c.." ??") end,tx) + then M.tryin(r,rt(),function(c2) tx(c.." "..c2.."?") end, function() tx(c.." ??") end,tx) else tx(c.."?") end k(true) @@ -25,18 +29,70 @@ function self.rx(tx,input,k) end, function(_) tx("?") k(true) end,tx) end -function self.server(sock_) - local fsend = (require "fifosock").wrap(sock_) + +-- called with an ESTABLISHED TCP socket +function M.server(sock) + + -- upval: sock + local function opipe_cb(opipe) + local resp = opipe:read(1400) + if resp and #resp > 0 then sock:send(resp) end + return false -- block pipe until onsent_cb + end + + -- opipe points at opipe_cb, points at sock. + local opipe = pipe.create(opipe_cb) + local function opw(s) opipe:write(s) end + + -- upval: opipe, opipe_cb + -- + -- so now sock points at onsent_cb which transitively points back at sock; + -- a circularity through the registry. This must be manually broken, which + -- we do in teardown or will happen when net kills off the connection due to + -- timeout. + local function onsent_cb(sock_) + -- sock_ == sock; we're already circular anyway, no reason to use sock_ + opipe_cb(opipe) + end + + local ipipe + + -- upval: ipipe, opipe, tryon local function teardown(rawsock) - rawsock:on("sent", nil) - rawsock:on("receive", nil) - rawsock:on("disconnection", nil) - tryon("disconn",fsend) - fsend=nil + if rawsock then + rawsock:on("sent", nil) + rawsock:on("receive", nil) + rawsock:on("disconnection", nil) + end + tryon("disconn",nil) + opipe = nil + ipipe = nil + end + + -- upval: M, sock, teardown, opw + local function ipipe_cb(i) + local inp = i:read('\n+') + if inp and inp:sub(-1) == "\n" + then M.rx(opw, inp, + function(c) if c + then opw("\n$ ") + else sock:close() teardown(sock) + end + end) + elseif inp then i:unread(inp) + else return false + end end - sock_:on("receive",function(s_,input) self.rx(fsend,input,function(c) if c then fsend("\n$ ") else s_:close() teardown(s_) end end) end) - sock_:on("disconnection",function(s_, x) teardown(s_) end) - tryon("conn",fsend) - fsend("\n$ ") + + ipipe = pipe.create(ipipe_cb) + + -- upval: ipipe + sock:on("receive",function(s_,input) ipipe:write(input) end) + + -- upval: teardown + sock:on("disconnection",function(s_, x) teardown(s_) end) + tryon("conn", opw) + opw("\n$ ") end -return self + +return M -- 2.50.1