.@dave1707 I can certainly keep a record of my experiments. They aren’t very sophisticated as yet.
I installed the lua socket library and the http.parser libraries on my Mac. I installed luasocket via luarocks directly (luarocks install luasocket
) but you can also get it from http://w3.impa.br/~diego/software/luasocket/home.html. http.parser was a little trickier. I had to download a C library first, then install the parser. The link is: https://github.com/brimworks/lua-http-parser. What I did was:
cd local/include
git clone git://github.com/joyent/http-parser.git
export CFLAGS=-I$HOME/local/include
cd local/src
git clone https://github.com/brimworks/lua-http-parser.git
luarocks make CFLAGS=-g lua-http-parser-1.0-1.rockspec
I then took the sample TCP server program from the luasocket webpage and started adapting it to get something that would receive and send data to a Codea program. Here’s my current version:
-- debugging:
-- 1 everything
-- 2 warnings
-- 3 errors
debug_level = 1
debug_name = {
"LOG",
"WARNING",
"ERROR"
}
function debug(e,l)
if l >= debug_level then
print(debug_name[l] .. ": " .. e)
end
end
-- load namespace
local socket = require("socket")
local lhp = require("http.parser")
local connection_close = [[
HTTP/1.1 200 OK
Date: Wed, 02 Feb 2011 00:50:50 GMT
Connection: close
0123456789]]
connection_close = connection_close:gsub('\
', '\\r\
')
-- create a TCP socket and bind it to the local host, at any port
local server = assert(socket.bind("*", 50000))
-- find out which port the OS chose for us
local ip, port = server:getsockname()
-- print a message informing what's up
print("Please connect to " .. ip .. " on port " .. port)
-- loop forever waiting for clients
running = true
while running do
-- wait for a connection from any client
local client = server:accept()
-- make sure we don't block waiting for this client's line
client:settimeout(10)
local rip, rport = client:getpeername()
debug("Connection from " .. rip .. " on port " .. port,1)
-- receive the line
local get_headers = true
local request = ""
local headers = {}
local body = ""
local parser = lhp.request {
on_url = function(url) print("URL: " .. url) end,
on_header = function(hkey, hval) headers[hkey] = hval end,
on_body = function(b)
if b then
body = body .. b
end
end,
on_message_begin = function() print("Starting ...") end,
on_message_complete = function() print("Finishing ...") end,
on_headers_complete = function() get_headers = false end
}
while get_headers do
local line, err = client:receive()
if err then
debug(err,3)
get_headers = false
else
parser:execute(line .. "\\r\
")
end
end
if headers["Content-Length"] then
local line, err = client:receive(headers["Content-Length"])
if err then
debug(err,3)
else
if line then
parser:execute(line)
end
end
end
print("Body: " .. body)
client:send(connection_close)
client:close()
-- done with client, close the object
-- client:close()
end
On the Codea side, I have:
function setup()
http.request('http://<laptop-ip>:50000?hello',gotSomething,gotNothing,
{
method = "POST",
data = "hello world",
}
)
end
function draw()
end
function gotSomething(d,s,h)
print(s .. ":" .. d)
for k,v in pairs(h) do
print (k .. ":" .. v)
end
end
function gotNothing()
print("Got nothing")
end
Line endings were probably the most confusing part. When the socket receives data it can do so in one of three ways: get all the data, get a line, or get a fixed number of bytes. The first of these doesn’t work: the socket never returns. Getting lines is fine except that line endings get stripped. So I do this for headers and then read the given number of bytes (from Content-Length
) for the body. This ensures that there’s no character changes on the body.