ref: bc762e9c9294990c0d2480295637c792363dcc8c
dir: /lib/lua/net.lua/
---
-- plan9 network utilities
---
---
-- dial(2)
---
DialAux = {
new = function(self, proto)
local o = {}
setmetatable(o, self)
self.__index = self
if proto == nil then
o.proto = "tcp"
else
o.proto = proto
end
return o
end,
-- connect (compat method)
connect = function(self, host, port)
raddr = self.proto.."!"..host.."!"..port
end,
-- dial (needs more checks)
dial = function(self, raddr)
local cs_fd, clone_fd, data_fd, ctl_fd, proto
local data_fid, conn_param, clone_path, data_path, addr
if not(self.clone_path) and not(self.addr) then
cs_fd = io.open("/net/cs", "r+")
if not(cs_fd) then
return false, "unable to open cs file"
end
cs_fd:write(raddr)
cs_fd:seek("set")
conn_param = cs_fd:read("a")
cs_fd:close()
self.clone_path = string.sub(conn_param, 0, string.find(conn_param, " ") - 1)
self.addr = string.sub(conn_param, string.find(conn_param, " ") + 1)
end
clone_path = self.clone_path
addr = self.addr
clone_fd = io.open(clone_path, "r+")
if not(clone_fd) then
return false, "unable to open clone file"
end
data_fid = clone_fd:read()
clone_fd:seek("set")
local n = clone_fd:write("connect "..addr.."\n")
clone_fd:flush()
data_path = string.match(clone_path, "([a-zA-Z0-9/.]+)/clone")
data_path = data_path.."/"..data_fid.."/data"
data_fdin = io.open(data_path, "r+")
data_fdout = io.open(data_path, "a+")
if not(data_fdin) then
return false, "unable to open data"
end
self.data_fdin = data_fdin
self.data_fdout = data_fdout
self.clone_fd = clone_fd
return true, nil
end,
-- close connection and file descriptors
close = function(self)
self.data_fdin:close()
self.data_fdout:close()
self.clone_fd:write("close\n")
self.clone_fd:close()
self.data_fdin = nil
self.data_fdout = nil
self.clone_fd = nil
end,
-- dummy compat function
set_timeout = function(self, t)
self.timeout = t
end,
-- send data
send = function(self, d)
-- self.data_fdout:seek("set")
local fd = self.data_fdout:write(d)
self.data_fdout:flush()
if fd == nil then
return false, "connection dropped"
end
return true, d
end,
-- receive data
receive_bytes = function(self, sz)
if sz == nil then
sz = SOCKET_MAXSZ
end
local data = self.data_fdin:read(sz)
if not(data) then
return false, "eof"
end
return true, data
end,
-- receive all
receive_all = function(self)
local data = self.data_fdin:read("a")
if not(data) then
return false, "eof"
end
return true, data
end,
}
---
-- webfs(4) client
---
WebfsRequest = {
new = function(self, mtpt)
local o = {}
setmetatable(o, self)
self.__index = self
if mtpt == nil then
o.mtpt = "/mnt/web"
else
o.mtpt = mtpt
end
return o
end,
open = function(self)
local clone_fd
local web_fid, clone_path
clone_path=self.mtpt.."/clone"
clone_fd = io.open(clone_path, "r+")
if not(clone_fd) then
return false, "unable to clone"
end
web_fid = clone_fd:read()
clone_fd:seek("set")
self.clone_fd = clone_fd
self.web_fid = web_fid
return true, nil
end,
set_param = function(self, paramname, paramval)
-- self.clone_fd:seek("set")
self.clone_fd:write(paramname.." "..paramval.."\n")
self.clone_fd:flush()
end,
read_body = function(self)
local body_fd, buf
body_fd = io.open(self.mtpt.."/"..self.web_fid.."/body", "r")
if not(body_fd) then
return false, "body cannot be opened"
end
buf = body_fd:read("a")
body_fd:close()
if not(buf) then
return false, "unable to read body"
end
return true, buf
end,
post_body = function(self, body)
local body_fd, ofd
body_fd = io.open(self.mtpt.."/"..self.web_fid.."/postbody", "w")
if not(body_fd) then
return false, "body cannot be opened"
end
ofd = body_fd:write(body)
body_fd:close()
if not(ofd) then
return false, "unable to write to body fd"
end
return true, nil
end,
close = function(self)
self.clone_fd:close()
end,
}
Webfs = {
new = function(self, mtpt)
local o = {}
setmetatable(o, self)
self.__index = self
if mtpt == nil then
o.mtpt = "/mnt/web"
else
o.mtpt = mtpt
end
return o
end,
get = function(self, url, headers)
local request, status, data
if not(url) then
return false, "no url"
end
if not(headers) then
headers = {}
end
request = WebfsRequest:new(self.mtpt)
status, data = request:open()
if not(status) then
return status, data
end
request:set_param("url", url)
for hdrname,hdrval in pairs(headers) do
request:set_param("headers", string.format("%s: %s", hdrname, hdrval))
end
status, data = request:read_body()
request:close()
return status, data
end,
post = function(self, url, body, contenttype, headers)
local request, status, data
if not(url) then
return false, "no url"
end
if not(headers) then
headers = {}
end
request = WebfsRequest:new(self.mtpt)
status, data = request:open()
if not(status) then
return status, data
end
request:set_param("url", url)
request:set_param("request", "POST")
for k,header in pairs(headers) do
request:set_param("headers", header)
end
if contenttype then
request:set_param("contenttype", contenttype)
end
status, data = request:post_body(body)
if not(status) then
request:close()
return status, data
end
status, data = request:read_body()
request:close()
return status, data
end,
}
local net = {
DialAux = DialAux,
Socket = DialAux, -- nmap/unix compat (someday)
WebfsRequest = WebfsRequest,
Webfs = Webfs,
}
return net