From cda871410a070dea600852f4f4a8b97dc8a605aa Mon Sep 17 00:00:00 2001 From: Izaya Date: Wed, 4 Apr 2018 14:25:18 +1000 Subject: [PATCH] added the net library for sockets and stuff for KittenOS --- KittenOS/apps/svc-minitel.lua | 3 - KittenOS/libs/net.lua | 168 ++++++++++++++++++++++++++++++++++ 2 files changed, 168 insertions(+), 3 deletions(-) create mode 100644 KittenOS/libs/net.lua diff --git a/KittenOS/apps/svc-minitel.lua b/KittenOS/apps/svc-minitel.lua index 2725575..453c72a 100644 --- a/KittenOS/apps/svc-minitel.lua +++ b/KittenOS/apps/svc-minitel.lua @@ -241,7 +241,4 @@ while true do if hooks[ev[1]] then pcall(hooks[ev[1]],table.unpack(ev)) end - for k,v in pairs(ev) do - neo.emergency(v) - end end diff --git a/KittenOS/libs/net.lua b/KittenOS/libs/net.lua new file mode 100644 index 0000000..7118e07 --- /dev/null +++ b/KittenOS/libs/net.lua @@ -0,0 +1,168 @@ +function returnNet(event,computer,minitel) + +function print(...) + for k,v in pairs({...}) do + neo.emergency(tostring(k)..": "..tostring(v)) + end +end + +event.listen("x.svc.minitel",print) + +local function svcpull(id) + repeat + te={event.pull("x.svc.minitel")} + until te[2] == id + table.remove(te,1) + return table.unpack(te) +end + +function svclisten(id,fn) + return event.listen("x.svc.minitel",function(...) + tA = {...} + if tA[2] == id then + table.remove(tA,1) + fn(table.unpack(tA)) + end + end) +end + +local net = {} +net.mtu = 4096 +net.streamdelay = 60 +net.minport = 32768 +net.maxport = 65535 +net.openports = {} + +function net.genPacketID() + local npID = "" + for i = 1, 16 do + npID = npID .. string.char(math.random(32,126)) + end + return npID +end + +function net.usend(to,port,data,npID) + minitel.sendPacket(0,to,port,data,npID) +end + +function net.rsend(to,port,data) + local pid = net.genPacketID() + minitel.sendPacket(1,to,port,data,pid) + repeat + _,rpid = svcpull("net_ack") + until rpid == pid +end + +-- ordered packet delivery, layer 4? + +function net.send(to,port,ldata) + local tdata = {} + if ldata:len() > net.mtu then + for i = 1, ldata:len(), net.mtu do + tdata[#tdata+1] = ldata:sub(1,net.mtu) + ldata = ldata:sub(net.mtu+1) + end + else + tdata = {ldata} + end + for k,v in ipairs(tdata) do + net.rsend(to,port,v) + end +end + +-- socket stuff, layer 5? + +local function cwrite(self,data) + if self.state == "open" then + net.send(self.addr,self.port,data) + end +end +local function cread(self,length) + local rdata = "" + rdata = self.rbuffer:sub(1,length) + self.rbuffer = self.rbuffer:sub(length+1) + return rdata +end + +local function socket(addr,port,sclose) -- todo, add remote closing of sockets + local conn = {} + conn.addr,conn.port = addr,tonumber(port) + conn.rbuffer = "" + conn.write = cwrite + conn.read = cread + conn.state = "open" + local function listener(_,t,f,p,d) + if f == conn.addr and p == conn.port then + if d == sclose then + conn:close() + else + conn.rbuffer = conn.rbuffer .. d + end + end + end + local lf = svclisten("net_msg",listener) + function conn.close(self) + event.ignore("x.svc.minitel",lf) + conn.state = "closed" + net.rsend(addr,port,sclose) + end + return conn +end + +function net.open(to,port) + net.rsend(to,port,"openstream") + local st = computer.uptime()+net.streamdelay + local est = false + while true do + _,from,rport,data = svcpull("net_msg") + print("from",from,"port",rport,"data",data) + if to == from and rport == port then + print("Connection",from,rport,data) + if tonumber(data) then + est = true + end + break + end + if st < computer.uptime() then + return nil, "timed out" + end + end + if not est then + return nil, "refused" + end + data = tonumber(data) + sclose = "" + repeat + _,from,nport,sclose = svcpull("net_msg") + until from == to and nport == data + return socket(to,data,sclose) +end + +function net.listen(port) + repeat + _, from, rport, data = svcpull("net_msg") + until rport == port and data == "openstream" + local nport = math.random(net.minport,net.maxport) + local sclose = net.genPacketID() + net.rsend(from,rport,tostring(nport)) + net.rsend(from,nport,sclose) + return socket(from,nport,sclose) +end + +function net.flisten(port,listener) + local function helper(_,t,from,rport,data) + if rport == port and data == "openstream" then + local nport = math.random(net.minport,net.maxport) + local sclose = net.genPacketID() + net.rsend(from,rport,tostring(nport)) + net.rsend(from,nport,sclose) + listener(socket(from,nport,sclose)) + end + end + return svclisten("net_msg",helper) +end + +return net + +end +return returnNet