You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
198 lines
4.9 KiB
198 lines
4.9 KiB
local async = require("async")
|
|
local computer = require("computer")
|
|
local component = require("component")
|
|
local coroutine = require("coroutine")
|
|
local dns = require("dns")
|
|
local serial = require("serialization")
|
|
local table = require("table")
|
|
local string = require("string")
|
|
local ll = require("liblua")
|
|
local modem = component.proxy(component.list("modem")())
|
|
|
|
local args = {...}
|
|
|
|
-- Take some existing modem functions and data
|
|
local net = {
|
|
addr = modem.address,
|
|
type = modem.type,
|
|
open = modem.open,
|
|
isOpen = modem.isOpen,
|
|
close = modem.close,
|
|
isWireless = modem.isWireless,
|
|
maxPacketSize = modem.maxPacketSize,
|
|
}
|
|
|
|
-- Used to determine if a string is a proper uuid
|
|
function isUUID(s)
|
|
local pattern = {8,4,4,4,12}
|
|
local t = ll.split(s, "-")
|
|
for i, v in ipairs(t) do
|
|
if #v ~= pattern[i] or tonumber(v, 16) == nil then
|
|
return false
|
|
end
|
|
end
|
|
return true
|
|
end
|
|
|
|
-- Resolve addresses if they aren't UUIDs
|
|
function checkAddr(addr)
|
|
if not isUUID(addr) then
|
|
return dns.query(addr)
|
|
end
|
|
return addr
|
|
end
|
|
|
|
-- Close all ports
|
|
function net.closeAll()
|
|
for i = 1, 65535 do
|
|
net.close(i)
|
|
end
|
|
end
|
|
|
|
-- Strength getter and setter
|
|
function net.strength(n)
|
|
if n ~= nil then
|
|
modem.setStrength(n)
|
|
else
|
|
return modem.getStrength()
|
|
|
|
end
|
|
end
|
|
|
|
-- Wake mesage getter and setter
|
|
function net.wakeMsg(msg, fuzzy)
|
|
if msg ~= nil then
|
|
modem.setWakeMessage(msg, fuzzy)
|
|
else
|
|
return modem.getWakeMessage()
|
|
end
|
|
end
|
|
|
|
-- Send network packets
|
|
-- Auto serializes data for you
|
|
function net.send(addr, port, ...)
|
|
addr = checkAddr(addr)
|
|
local arg = table.pack(...)
|
|
for k, v in ipairs(arg) do
|
|
-- Only serialize tables
|
|
if type(v) == "table" then
|
|
arg[k] = serial.serialize(v)
|
|
end
|
|
end
|
|
modem.send(addr, port, table.unpack(arg))
|
|
|
|
end
|
|
|
|
-- Broadcast network packets
|
|
-- Auto serializes data for you
|
|
function net.broadcast(port, ...)
|
|
local arg = table.pack(...)
|
|
for k, v in ipairs(arg) do
|
|
-- Only serialize tables
|
|
if type(v) == "table" then
|
|
arg[k] = serial.serialize(v)
|
|
end
|
|
end
|
|
modem.broadcast(port, table.unpack(arg))
|
|
|
|
end
|
|
|
|
-- Custom function to receive network packets
|
|
-- Can specify a port and or address for simple filtering
|
|
-- Can also supply a filter function in addition to simple filtering
|
|
-- If port supplied, default action is to open the port for you
|
|
-- If nonblocking, uses coroutine.yield() do be prepared to handle that
|
|
function net.recv(t)
|
|
local pkt = {}
|
|
local tmp = {}
|
|
-- This allows default and keyword args
|
|
if t ~= nil then
|
|
setmetatable(t,{__index={
|
|
port = nil,
|
|
addr = nil,
|
|
fuzzy = false,
|
|
timeout = nil,
|
|
filter = nil,
|
|
open = true,
|
|
nonblocking = false,
|
|
}})
|
|
local port, addr, timeout, filter, open, nonblocking =
|
|
t[1] or t.port,
|
|
t[2] or t.addr,
|
|
t[3] or t.timeout,
|
|
t[4] or t.filter,
|
|
t[5] or t.open,
|
|
t[6] or t.nonblocking
|
|
|
|
if addr ~= nil then
|
|
addr = checkAddr(addr)
|
|
end
|
|
|
|
-- Automatically open port to listen on
|
|
-- NOTE: Only works on a single port, if the filter function listens on
|
|
-- multiple you'll have to do that manually
|
|
if open and net ~= nil then net.open(port) end
|
|
|
|
----------------
|
|
-- Basic filter function used to call user defined filter functions
|
|
function f(name, ...)
|
|
-- Get rid of all non modem messages
|
|
if name ~= "modem_message" then return false end
|
|
local arg = {...}
|
|
local resAddress, resPort = arg[2], arg[3]
|
|
|
|
-- Check port is good
|
|
if port ~= nil and resPort ~= port then
|
|
return false
|
|
end
|
|
|
|
-- Check addr is good
|
|
if resAddr ~= nil and resAddr == addr then
|
|
return false
|
|
end
|
|
|
|
-- Do further filtering
|
|
if filter ~= nil then
|
|
return filter(name, ...)
|
|
else
|
|
return true
|
|
end
|
|
end
|
|
----------------
|
|
|
|
if timeout ~= nil then
|
|
tmp = {async.pullFiltered(timeout, f, not nonblocking)}
|
|
else
|
|
tmp = {async.pullFiltered(f, not nonblocking)}
|
|
end
|
|
end
|
|
|
|
-- Check for non-packets
|
|
if #tmp == 0 then
|
|
return nil, "timeout"
|
|
elseif tmp[1] == "interrupted" then
|
|
return nil, "interrupted"
|
|
end
|
|
|
|
-- Create basis of packet
|
|
pkt.laddr, pkt.raddr, pkt.port, pkt.distance, pkt.msg = tmp[2], tmp[3], tmp[4], tmp[5], tmp[6]
|
|
|
|
local data = {}
|
|
for i = 6, #tmp do
|
|
-- Unserialize any serialized data
|
|
if type(tmp[i]) == "string" then
|
|
nonblocking, res = pcall(serial.unserialize, tmp[i])
|
|
if nonblocking and res == nil then data[i-5] = tmp[i] else data[i-5] = res end
|
|
else
|
|
data[i-5] = tmp[i]
|
|
end
|
|
end
|
|
pkt.data = data
|
|
|
|
return pkt
|
|
end
|
|
|
|
-- wget -f http://localhost:8080/lib/net.lua /usr/lib/net.lua
|
|
-- wget -f http://mc.bashed.rocks:13699/lib/net.lua /usr/lib/net.lua
|
|
|
|
return net
|