added seperate input and working on http / sockets
This commit is contained in:
@@ -1 +1,306 @@
|
||||
--:Minify:--
|
||||
local kernel = ...
|
||||
|
||||
local handler = {}
|
||||
|
||||
local http = kernel.apis.http
|
||||
|
||||
kernel.cct.httpqueue = kernel.cct.httpqueue or {}
|
||||
kernel.cct.httpresponse = kernel.cct.httpresponse or {}
|
||||
kernel.cct.httperror = kernel.cct.httperror or {}
|
||||
|
||||
local function parseRawRequest(raw)
|
||||
local sepLen = 4
|
||||
|
||||
local headerEnd =
|
||||
raw:find("\r\n\r\n", 1, true)
|
||||
|
||||
if not headerEnd then
|
||||
headerEnd =
|
||||
raw:find("\n\n", 1, true)
|
||||
|
||||
sepLen = 2
|
||||
end
|
||||
|
||||
local headerPart
|
||||
local body = ""
|
||||
|
||||
if headerEnd then
|
||||
headerPart = raw:sub(1, headerEnd - 1)
|
||||
body = raw:sub(headerEnd + sepLen)
|
||||
else
|
||||
headerPart = raw
|
||||
end
|
||||
|
||||
local lines = {}
|
||||
|
||||
for line in headerPart:gmatch("[^\r\n]+") do
|
||||
lines[#lines + 1] = line
|
||||
end
|
||||
|
||||
if #lines == 0 then
|
||||
return nil, "EINVAL"
|
||||
end
|
||||
|
||||
local method, path =
|
||||
lines[1]:match("^(%S+)%s+(%S+)")
|
||||
|
||||
if not method or not path then
|
||||
return nil, "EBADMSG"
|
||||
end
|
||||
|
||||
local headers = {}
|
||||
|
||||
for i = 2, #lines do
|
||||
local k, v =
|
||||
lines[i]:match("^([^:]+):%s*(.*)$")
|
||||
|
||||
if k then
|
||||
headers[k] = v
|
||||
end
|
||||
end
|
||||
|
||||
local host = headers.Host or headers.host
|
||||
|
||||
if not host and not path:match("^https?://") then
|
||||
return nil, "EHOSTUNREACH"
|
||||
end
|
||||
|
||||
local url
|
||||
|
||||
if path:match("^https?://") then
|
||||
url = path
|
||||
else
|
||||
url = "http://" .. host .. path
|
||||
end
|
||||
|
||||
local req = {
|
||||
url = url,
|
||||
method = method,
|
||||
headers = headers
|
||||
}
|
||||
|
||||
if body ~= "" then
|
||||
req.body = body
|
||||
end
|
||||
|
||||
return req
|
||||
end
|
||||
|
||||
local function buildResponse(resp)
|
||||
if not resp then
|
||||
return nil, "EINVAL"
|
||||
end
|
||||
|
||||
local code, msg = resp.getResponseCode()
|
||||
|
||||
local headers =
|
||||
resp:getResponseHeaders()
|
||||
|
||||
local body =
|
||||
resp:readAll() or ""
|
||||
|
||||
local out = {
|
||||
"HTTP/1.1 " ..
|
||||
tostring(code) ..
|
||||
" " ..
|
||||
tostring(msg)
|
||||
}
|
||||
|
||||
local hasLength = false
|
||||
|
||||
for k, v in pairs(headers or {}) do
|
||||
if k:lower() == "content-length" then
|
||||
hasLength = true
|
||||
end
|
||||
|
||||
out[#out + 1] =
|
||||
tostring(k) ..
|
||||
": " ..
|
||||
tostring(v)
|
||||
end
|
||||
|
||||
if not hasLength then
|
||||
out[#out + 1] =
|
||||
"Content-Length: " ..
|
||||
tostring(#body)
|
||||
end
|
||||
|
||||
out[#out + 1] = ""
|
||||
out[#out + 1] = body
|
||||
|
||||
return table.concat(out, "\r\n")
|
||||
end
|
||||
|
||||
function handler.connect(fd, address)
|
||||
local fdo = kernel.currentTask.fd[fd]
|
||||
|
||||
if not fdo then
|
||||
return nil, "EBADF"
|
||||
end
|
||||
|
||||
fdo.socket.rbuf = ""
|
||||
fdo.socket.closed = false
|
||||
fdo.socket.httpid = nil
|
||||
|
||||
fdo.handle.write = function(raw)
|
||||
local req, err =
|
||||
parseRawRequest(raw)
|
||||
|
||||
if not req then
|
||||
return nil, err
|
||||
end
|
||||
|
||||
local id =
|
||||
tostring(kernel.uuid())
|
||||
|
||||
fdo.socket.httpid = id
|
||||
|
||||
kernel.cct.httpqueue[id] = true
|
||||
|
||||
local ok, err =
|
||||
http.request(req, id)
|
||||
|
||||
if not ok then
|
||||
kernel.cct.httpqueue[id] = nil
|
||||
return nil, err
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
fdo.handle.read = function(count)
|
||||
count = count or 4096
|
||||
|
||||
local sock = fdo.socket
|
||||
|
||||
if #sock.rbuf > 0 then
|
||||
local out =
|
||||
sock.rbuf:sub(1, count)
|
||||
|
||||
sock.rbuf =
|
||||
sock.rbuf:sub(count + 1)
|
||||
|
||||
return out
|
||||
end
|
||||
|
||||
local id = sock.httpid
|
||||
|
||||
if not id then
|
||||
return ""
|
||||
end
|
||||
|
||||
local function finish(resp)
|
||||
sock.rbuf =
|
||||
buildResponse(resp) or ""
|
||||
|
||||
local out =
|
||||
sock.rbuf:sub(1, count)
|
||||
|
||||
sock.rbuf =
|
||||
sock.rbuf:sub(count + 1)
|
||||
|
||||
return out
|
||||
end
|
||||
|
||||
if kernel.cct.httpresponse[id] then
|
||||
local resp =
|
||||
kernel.cct.httpresponse[id]
|
||||
|
||||
kernel.cct.httpresponse[id] = nil
|
||||
kernel.cct.httpqueue[id] = nil
|
||||
|
||||
return finish(resp)
|
||||
end
|
||||
|
||||
if kernel.cct.httperror[id] then
|
||||
local err =
|
||||
kernel.cct.httperror[id]
|
||||
|
||||
kernel.cct.httperror[id] = nil
|
||||
kernel.cct.httpqueue[id] = nil
|
||||
|
||||
return nil, err
|
||||
end
|
||||
|
||||
kernel.currentTask.status = "D"
|
||||
|
||||
local coro
|
||||
|
||||
coro = function()
|
||||
if kernel.cct.httpresponse[id] then
|
||||
local resp =
|
||||
kernel.cct.httpresponse[id]
|
||||
|
||||
kernel.cct.httpresponse[id] = nil
|
||||
kernel.cct.httpqueue[id] = nil
|
||||
|
||||
kernel.asyncReturn(
|
||||
finish(resp)
|
||||
)
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
if kernel.cct.httperror[id] then
|
||||
local err =
|
||||
kernel.cct.httperror[id]
|
||||
|
||||
kernel.cct.httperror[id] = nil
|
||||
kernel.cct.httpqueue[id] = nil
|
||||
|
||||
kernel.asyncReturn(
|
||||
nil,
|
||||
err
|
||||
)
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
coroutine.yield()
|
||||
end
|
||||
|
||||
kernel.currentTask.ksh =
|
||||
coroutine.create(function()
|
||||
local ok, err =
|
||||
xpcall(
|
||||
coro,
|
||||
debug.traceback
|
||||
)
|
||||
|
||||
if not ok then
|
||||
kernel.asyncReturn(
|
||||
nil,
|
||||
err
|
||||
)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
fdo.handle.close = function()
|
||||
fdo.socket.closed = true
|
||||
|
||||
local id =
|
||||
fdo.socket.httpid
|
||||
|
||||
if id then
|
||||
kernel.cct.httpqueue[id] = nil
|
||||
kernel.cct.httpresponse[id] = nil
|
||||
kernel.cct.httperror[id] = nil
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
kernel.socket.registerProtocal(
|
||||
"http://",
|
||||
handler
|
||||
)
|
||||
|
||||
kernel.socket.registerProtocal(
|
||||
"https://",
|
||||
handler
|
||||
)
|
||||
@@ -223,6 +223,9 @@ local function newtty(obj, id, ev)
|
||||
gctrl=function()
|
||||
return serializeBool(kernel.cct.ctrl)..";"..serializeBool(kernel.cct.alt)
|
||||
end,
|
||||
isvirt=function()
|
||||
return false
|
||||
end,
|
||||
gplt=function()
|
||||
return plt
|
||||
end
|
||||
@@ -243,8 +246,39 @@ end
|
||||
local fifo = kernel.newFifo()
|
||||
kernel.cct.fifo=fifo
|
||||
|
||||
newtty(kernel.apis.term, "1", fifo.pop)
|
||||
newtty(kernel.apis.term, "1", function() end)
|
||||
|
||||
for i,v in ipairs({peripheral.find("monitor")}) do
|
||||
newtty(v,tostring(i+1),function () end)
|
||||
end
|
||||
|
||||
kernel.devfs.data["input"]["keyboard1"] = function(op, mode)
|
||||
if op=="type" then
|
||||
return "Keyboard"
|
||||
elseif op=="open" then
|
||||
local h = {
|
||||
read=function(amount)
|
||||
local rv=""
|
||||
for i=1, amount or 1 do
|
||||
local event = {fifo.pop()}
|
||||
if event[1] then
|
||||
rv=rv..event[1]
|
||||
end
|
||||
end
|
||||
if rv=="" then rv=nil end
|
||||
return rv
|
||||
end,
|
||||
write=function(content)
|
||||
end
|
||||
}
|
||||
if mode=="rw" then
|
||||
return h
|
||||
elseif mode=="r" then
|
||||
h["write"]=nil
|
||||
return h
|
||||
elseif mode=="w" then
|
||||
h["read"]=nil
|
||||
return h
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -4,6 +4,7 @@ local keys=kernel.apis.keys
|
||||
|
||||
kernel.processes.cctdeamon = function()
|
||||
local timeout = false
|
||||
kernel.log("CCT deamon started")
|
||||
while true do
|
||||
local event = {kernel.EFI:getMachineEvent()}
|
||||
|
||||
@@ -66,6 +67,12 @@ kernel.processes.cctdeamon = function()
|
||||
|
||||
elseif eventType == "keyTyped" then
|
||||
if charOrKey then kernel.cct.fifo.push(charOrKey) end
|
||||
elseif eventType == "mouse_scroll" then
|
||||
if event[2] == 1 then
|
||||
kernel.cct.fifo.push("[nS")
|
||||
else
|
||||
kernel.cct.fifo.push("[nT")
|
||||
end
|
||||
elseif eventType == "http_success" then
|
||||
kernel.cct.httpqueue[event[2]]=nil
|
||||
kernel.cct.httpresponse[event[2]]=event[3]
|
||||
@@ -83,4 +90,6 @@ kernel.processes.cctdeamon = function()
|
||||
sleep(0.05)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
kernel.log("CCT deamon queued for execution")
|
||||
Reference in New Issue
Block a user