mirror of
https://github.com/zenith391/OCEmu.git
synced 2025-09-30 00:28:05 -04:00
Some more internet fixes
Add logic for when the socket should be closed Same for HTTP requests Add support for when HTTP requests fail Remove and readd machine.lua's sethook to get around how slow http.request can be at times Patch socket.http to return a table for headers only when there are multiple values, only because other code will break Support table's for headers in our internet component Change header case to a more normal version
This commit is contained in:
parent
ca66a9e20c
commit
b3494872f1
@ -5,6 +5,7 @@ if not okay then
|
|||||||
cprint("Cannot use internet component: " .. socket)
|
cprint("Cannot use internet component: " .. socket)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
require("support.http_patch")
|
||||||
local url = require("socket.url")
|
local url = require("socket.url")
|
||||||
local okay, http = pcall(require, "ssl.https")
|
local okay, http = pcall(require, "ssl.https")
|
||||||
if not okay then
|
if not okay then
|
||||||
@ -53,6 +54,7 @@ function obj.connect(address, port) -- Opens a new TCP connection. Returns the h
|
|||||||
-- TODO: not OC behaviour, but needed to prevent hanging
|
-- TODO: not OC behaviour, but needed to prevent hanging
|
||||||
client:settimeout(10)
|
client:settimeout(10)
|
||||||
local connected = false
|
local connected = false
|
||||||
|
local closed = false
|
||||||
local function connect()
|
local function connect()
|
||||||
cprint("(socket) connect",host,port)
|
cprint("(socket) connect",host,port)
|
||||||
local did, err = client:connect(host,port)
|
local did, err = client:connect(host,port)
|
||||||
@ -60,39 +62,49 @@ function obj.connect(address, port) -- Opens a new TCP connection. Returns the h
|
|||||||
if did then
|
if did then
|
||||||
connected = true
|
connected = true
|
||||||
client:settimeout(0)
|
client:settimeout(0)
|
||||||
|
else
|
||||||
|
pcall(client.close,client)
|
||||||
|
closed = true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
local fakesocket = {
|
local fakesocket = {
|
||||||
read = function(n)
|
read = function(n)
|
||||||
cprint("(socket) read",n)
|
cprint("(socket) read",n)
|
||||||
-- TODO: Error handling
|
-- TODO: Better Error handling
|
||||||
|
if closed then return nil, "connection lost" end
|
||||||
if not connected then connect() return "" end
|
if not connected then connect() return "" end
|
||||||
if type(n) ~= "number" then n = math.huge end
|
if type(n) ~= "number" then n = math.huge end
|
||||||
local data, err, part = client:receive(n)
|
local data, err, part = client:receive(n)
|
||||||
if err == nil or err == "timeout" or part ~= "" then
|
if err == nil or err == "timeout" or part ~= "" then
|
||||||
return data or part
|
return data or part
|
||||||
else
|
else
|
||||||
|
if err == "closed" then closed = true err = "connection lost" end
|
||||||
return nil, err
|
return nil, err
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
write = function(data)
|
write = function(data)
|
||||||
cprint("(socket) write",data)
|
cprint("(socket) write",data)
|
||||||
|
-- TODO: Better Error handling
|
||||||
|
if closed then return nil, "connection lost" end
|
||||||
if not connected then connect() return 0 end
|
if not connected then connect() return 0 end
|
||||||
checkArg(1,data,"string")
|
checkArg(1,data,"string")
|
||||||
local data, err, part = client:send(data)
|
local data, err, part = client:send(data)
|
||||||
if err == nil or err == "timeout" or part ~= 0 then
|
if err == nil or err == "timeout" or part ~= 0 then
|
||||||
return data or part
|
return data or part
|
||||||
else
|
else
|
||||||
|
if err == "closed" then closed = true err = "connection lost" end
|
||||||
return nil, err
|
return nil, err
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
close = function()
|
close = function()
|
||||||
cprint("(socket) close")
|
cprint("(socket) close")
|
||||||
pcall(client.close,client)
|
pcall(client.close,client)
|
||||||
|
closed = true
|
||||||
end,
|
end,
|
||||||
finishConnect = function()
|
finishConnect = function()
|
||||||
cprint("(socket) finishConnect")
|
cprint("(socket) finishConnect")
|
||||||
-- TODO: Does this actually error?
|
-- TODO: Does this actually error?
|
||||||
|
if closed then return nil, "connection lost" end
|
||||||
return connected
|
return connected
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
@ -109,15 +121,43 @@ function obj.request(url, postData) -- Starts an HTTP request. If this returns t
|
|||||||
postData = nil
|
postData = nil
|
||||||
end
|
end
|
||||||
-- TODO: This works ... but is slow.
|
-- TODO: This works ... but is slow.
|
||||||
local page, _, headers, status = http.request(url, postData)
|
-- TODO: Infact so slow, it can trigger the machine's sethook, so we have to work around that.
|
||||||
local protocol, code, message = status:match("(.-) (.-) (.*)")
|
local hookf,hookm,hookc = debug.gethook()
|
||||||
code = tonumber(code)
|
local co = coroutine.running()
|
||||||
|
debug.sethook(co)
|
||||||
|
local page, err, headers, status = http.request(url, postData)
|
||||||
|
debug.sethook(co,hookf,hookm,hookc)
|
||||||
|
if not page then
|
||||||
|
cprint("(request) request failed",err)
|
||||||
|
end
|
||||||
|
-- Experimental fix for headers
|
||||||
|
if headers ~= nil then
|
||||||
|
local oldheaders = headers
|
||||||
|
headers = {}
|
||||||
|
for k,v in pairs(oldheaders) do
|
||||||
|
local name = k:gsub("^.",string.upper):gsub("%-.",string.upper)
|
||||||
|
if type(v) == "table" then
|
||||||
|
v.n = #v
|
||||||
|
headers[name] = v
|
||||||
|
else
|
||||||
|
headers[name] = {v,n=1}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local procotol, code, message
|
||||||
|
if status then
|
||||||
|
protocol, code, message = status:match("(.-) (.-) (.*)")
|
||||||
|
code = tonumber(code)
|
||||||
|
end
|
||||||
|
local closed = false
|
||||||
local fakesocket = {
|
local fakesocket = {
|
||||||
read = function(n)
|
read = function(n)
|
||||||
cprint("(socket) read",n)
|
cprint("(socket) read",n)
|
||||||
-- OC doesn't actually return n bytes when requested.
|
-- OC doesn't actually return n bytes when requested.
|
||||||
if page == nil then
|
if closed then
|
||||||
return nil, "connection lost"
|
return nil, "connection lost"
|
||||||
|
elseif headers == nil then
|
||||||
|
return nil, "Connection refused"
|
||||||
elseif page == "" then
|
elseif page == "" then
|
||||||
return nil
|
return nil
|
||||||
else
|
else
|
||||||
@ -129,14 +169,23 @@ function obj.request(url, postData) -- Starts an HTTP request. If this returns t
|
|||||||
end,
|
end,
|
||||||
response = function()
|
response = function()
|
||||||
cprint("(socket) response")
|
cprint("(socket) response")
|
||||||
|
if headers == nil then
|
||||||
|
return nil
|
||||||
|
end
|
||||||
return code, message, headers
|
return code, message, headers
|
||||||
end,
|
end,
|
||||||
close = function()
|
close = function()
|
||||||
cprint("(request) close")
|
cprint("(request) close")
|
||||||
|
closed = true
|
||||||
page = nil
|
page = nil
|
||||||
end,
|
end,
|
||||||
finishConnect = function()
|
finishConnect = function()
|
||||||
cprint("(socket) finishConnect")
|
cprint("(socket) finishConnect")
|
||||||
|
if closed then
|
||||||
|
return nil, "connection lost"
|
||||||
|
elseif headers == nil then
|
||||||
|
return nil, "Connection refused"
|
||||||
|
end
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
|
43
src/support/http_patch.lua
Normal file
43
src/support/http_patch.lua
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
-- Welcome to hack town!
|
||||||
|
-- Patch luasocket's http library to be less stupid
|
||||||
|
local function gsub_escape(str)
|
||||||
|
return str:gsub("[%(%)%.%%%+%-%*%?%[%]%^%$]", "%%%0")..""
|
||||||
|
end
|
||||||
|
cprint("http_patch start")
|
||||||
|
-- Patch data
|
||||||
|
local patches = {
|
||||||
|
{[[if headers[name] then headers[name] = headers[name] .. ", " .. value]],[[if headers[name] then if type(headers[name]) == "string" then headers[name] = {headers[name]} end headers[name][#headers[name]+1] = value]]},
|
||||||
|
}
|
||||||
|
package.loaded["socket.http"] = nil
|
||||||
|
local path = package.searchpath("socket.http",package.path)
|
||||||
|
if path then
|
||||||
|
local file, err = io.open(path,"rb")
|
||||||
|
if not file then
|
||||||
|
cprint("Failed to patch socket.http: " .. err)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local data = file:read("*a")
|
||||||
|
file:close()
|
||||||
|
for i = 1,#patches do
|
||||||
|
local newdata = data:gsub(gsub_escape(patches[i][1]), (patches[i][2]:gsub("%%","%%%%")..""))
|
||||||
|
if newdata == data then
|
||||||
|
cprint("Patch " .. i .. " failed")
|
||||||
|
else
|
||||||
|
data = newdata
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local fn, err = load(data,"="..path)
|
||||||
|
if not fn then
|
||||||
|
cprint("Failed to compile socket.http: " .. err)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local ok, err = pcall(fn)
|
||||||
|
if not ok then
|
||||||
|
cprint("Failed to load socket.http: " .. err)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
package.loaded["socket.http"] = err
|
||||||
|
else
|
||||||
|
cprint("Could not find socket.http")
|
||||||
|
end
|
||||||
|
cprint("http_patch end")
|
Loading…
x
Reference in New Issue
Block a user