OC-Copper/oc/tcpdial.lua

86 lines
1.9 KiB
Lua

-- I, 20kdc, release this into the public domain.
-- No warranty is provided, implied or otherwise.
-- Light Copper Base node that communicates to a server via an
-- Internet Card.
-- Only handles one modem for now.
local args = {...}
if #args ~= 3 then error("name, tcphost, tcpport") end
local component = require("component")
local cdlib = require("cdlib")
local event = require("event")
-- Adjust to taste.
local tcp = require("internet").open(tostring(args[2]), tonumber(args[3]))
local md = component.modem
md.open(4957)
tcp:setTimeout(0.05)
tcp:write(string.char((#(args[1])) - 1) .. args[1])
tcp:flush()
print("TCP up")
local function verify(d)
local hops, src, dst, data = cdlib.decode(d)
if not data then return end
-- Just a bit of filtering
if dst:sub(1, 1) ~= "^" then return end
if d:len() > 2022 then return end
return true
end
local function readByte()
while true do
local ok, err = pcall(tcp.read, tcp, 1)
if ok then return err end
-- not nice :(
if err:find("timeout") then
coroutine.yield()
else
error(err)
end
end
end
local function readerRoutine()
while true do
local h = readByte()
local l = readByte()
local sz = string.byte(l) + (string.byte(h) * 256)
print("Incoming packet size " .. sz)
local dat = ""
for i = 1, sz do
dat = dat .. readByte()
end
if dat ~= "" then
md.broadcast(4957, "copper", dat)
end
end
end
event.timer(10, function ()
tcp:write("\x00\x00")
tcp:flush()
end, math.huge)
local primary = coroutine.create(readerRoutine)
while true do
local et, _, _, p, _, m, d = event.pull(0.1)
local ok, o = coroutine.resume(primary)
if not ok then error(o) end
if et == "modem_message" and p == 4957 then
if m == "copper" then
-- Incoming Copper packet.
if verify(d) then
local h = math.floor(d:len() / 256)
local l = d:len() % 256
tcp:write(string.char(h, l) .. d)
tcp:flush()
end
end
end
end