From c943c42bb977af0ae24a33025b83ee17d2a49ba4 Mon Sep 17 00:00:00 2001 From: gamax92 Date: Thu, 18 Jun 2015 19:01:57 -0600 Subject: [PATCH] TCP Sockets! Fix a typo in the readme Fix unicode.wtrunc Implement TCP Socket support in the internet card Correct name of machine.lua to machine >_> --- README.md | 2 +- src/apis/unicode.lua | 36 +++++++++++---------- src/component/internet.lua | 64 ++++++++++++++++++++++++++++++++++++-- src/main.lua | 2 +- 4 files changed, 83 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index 7e02ba8..f35de4c 100644 --- a/README.md +++ b/README.md @@ -26,4 +26,4 @@ Running ------- Launch boot.lua with lua5.2, and provided everything is installed, you'll have a working Emulator -OCEmu stores its files in $HOME/.ocemu or %APPDATA%\.ocemu, whichever happens to exist first +OCEmu stores its files in $HOME/.ocemu or %APPDATA%\\.ocemu, whichever happens to exist first diff --git a/src/apis/unicode.lua b/src/apis/unicode.lua index 42bb290..2f16edb 100644 --- a/src/apis/unicode.lua +++ b/src/apis/unicode.lua @@ -11,6 +11,13 @@ env.unicode = { sub = utf8.sub, } +local function getCharWidth(char) + if unifont[char] ~= nil then + return #unifont[char] / 32 + end + return 1 +end + function env.unicode.isWide(str) cprint("unicode.isWide", str) checkArg(1,str,"string") @@ -18,10 +25,7 @@ function env.unicode.isWide(str) error("String index out of range: 0",3) end local char = utf8.byte(str) - if unifont[char] ~= nil then - return #unifont[char] > 32 - end - return false + return getCharWidth(char) > 1 end function env.unicode.charWidth(str) cprint("unicode.charWidth", str) @@ -30,32 +34,30 @@ function env.unicode.charWidth(str) error("String index out of range: 0",3) end local char = utf8.byte(str) - if unifont[char] ~= nil then - return #unifont[char] / 32 - end - return 1 + return getCharWidth(char) end function env.unicode.wlen(str) cprint("unicode.wlen", str) checkArg(1,str,"string") local length = 0 for _,c in utf8.next, str do - if unifont[c] ~= nil then - length = length + #unifont[c] / 32 - else - length = length + 1 - end + length = length + getCharWidth(c) end return length end function env.unicode.wtrunc(str, count) - -- STUB cprint("unicode.wtrunc", str, count) checkArg(1,str,"string") checkArg(2,count,"number") + local width = 0 + local pos = 0 local len = utf8.len(str) - if count >= len then - error("String index out of range: " .. len,2) + while (width < count) do + pos = pos + 1 + if pos > len then + error("String index out of range: " .. pos-1,3) + end + width = width + getCharWidth(utf8.byte(str,pos,pos)) end - return utf8.sub(str, 1, count-1) + return utf8.sub(str, 1, pos-1) end diff --git a/src/component/internet.lua b/src/component/internet.lua index 1ca913c..2ce8053 100644 --- a/src/component/internet.lua +++ b/src/component/internet.lua @@ -1,6 +1,21 @@ -- internet component local obj = {} +local socket = require("socket") +local url = require("socket.url") + +local function checkUri(address, port) + local parsed = url.parse(address) + if parsed ~= nil and parsed.host ~= nil and (parsed.port ~= nil or port > -1) then + return parsed.host, parsed.port or port + end + local simple = url.parse("oc://" .. address) + if simple ~= nil and simple.host ~= nil and (simple.port ~= nil or port > -1) then + return simple.host, simple.port or port + end + error("address could not be parsed or no valid port given",4) +end + function obj.isTcpEnabled() -- Returns whether TCP connections can be made (config setting). cprint("internet.isTcpEnabled") return config.get("internet.enableTcp",true) @@ -10,7 +25,6 @@ function obj.isHttpEnabled() -- Returns whether HTTP requests can be made (confi return config.get("internet.enableHttp",true) end function obj.connect(address, port) -- Opens a new TCP connection. Returns the handle of the connection. - --STUB cprint("internet.connect",address, port) if port == nil then port = -1 end compCheckArg(1,address,"string") @@ -18,7 +32,53 @@ function obj.connect(address, port) -- Opens a new TCP connection. Returns the h if not config.get("internet.enableTcp",true) then return nil, "tcp connections are unavailable" end - return nil + -- TODO Check for too many connections + local host, port = checkUri(address, port) + if host == nil then + return host, port + end + local client = socket.tcp() + -- TODO: not OC behaviour, but needed to prevent hanging + client:settimeout(10) + local connected = false + local function connect() + local did, err = client:connect(address,port) + if did then + connected = true + client:settimeout(0) + end + end + local fakesocket = { + read = function(n) + -- TODO: Error handling + if not connected then connect() return "" end + if type(n) ~= "number" then n = math.huge end + local data, err, part = client:receive(n) + if err == nil or err == "timeout" or part ~= "" then + return data or part + else + return nil, err + end + end, + write = function(data) + if not connected then connect() return 0 end + checkArg(1,data,"string") + local data, err, part = client:send(data) + if err == nil or err == "timeout" or part ~= 0 then + return data or part + else + return nil, err + end + end, + close = function() + pcall(client.close,client) + end, + finishConnect = function() + -- TODO: Does this actually error? + return connected + end + } + return fakesocket end function obj.request(url, postData) -- Starts an HTTP request. If this returns true, further results will be pushed using `http_response` signals. --STUB diff --git a/src/main.lua b/src/main.lua index c4be1be..6a08b7d 100644 --- a/src/main.lua +++ b/src/main.lua @@ -246,7 +246,7 @@ function boot_machine() if machine_data == nil then error("Failed to load machine.lua:\n\t" .. tostring(err)) end - local machine_fn, err = load(machine_data,"=kernel","t",env) + local machine_fn, err = load(machine_data,"=machine","t",env) if machine_fn == nil then error("Failed to parse machine.lua\n\t" .. tostring(err)) end