lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


On 7/19/06, Diego Nehab <diego@tecgraf.puc-rio.br> wrote:
> I met this in the LuaSocket library. And promptly used libhttpd
> instead (after extending it to use connection timeout) since
> LuaSockets seems to have everything but the kitchen sink.

Did you want the kitchen sink?

No. I tried LuaSocket first and it would have handled everything that
I wanted (and more).

wc -l *.[ch] gives me 4633 lines in luasocket-2.0.1. My extensions to
the lua interpreter consist of 838 lines of C, and my stripped down
libhttpd weighs in at 441 lines of C (including a ping implementation,
socket timeout and non-lingering sockets so that I can determine if
the network is usable or not).

1) It would be great if your build process could support being built
directly into the interpreter. My system doesn't have dynamic linking,
so I had to hack your Makefiles (needed in any way, because the
compiler flags have to be <just so> to get it to actually run on the
target system).

2) I tried to strip down LuaSockets but there's a lot of stuff in
there to strip out if all you want is a basic HTTP client similar to
wget but reading into a variable. I did improve my client by using a
table.concat of received packets, which was a trick I discovered while
reading your code.

3) It doesn't have ping functionality, though it wouldn't be hard to
do that, but why not? Pings that timeout are basically the only way I
can think of to check if the network is available or not.

I implemented my own (basic!) HTTP client instead. It fetches from a
URL and returns the response minus headers. Here's the implementation
(sans libhttpd which is a socket object built into the interpreter).

net = {}

function net.drain(s)
	local len, line
	local status = "INVALID"
	local code, content_length, in_body, sink = 501, 0, false, {}
	if s then
		repeat
			len, line = socket.read(s)
			if len and len > 0 then
			if not in_body then
				for c, s in string.gmatch(line, 'Status%: (%d+) ?(%w*)') do
					code, status = c, s
				end
				for cl in string.gmatch(line, 'Content%-Length%: (%d+)') do
					content_length = cl
				end	
				for rest in string.gmatch(line, '\r\n\r\n(.+)') do
					in_body = true
					line = rest
				end
			else
				 table.insert(sink, line)
			end
		until not len or len <= 0
	end
	return table.concat(sink), code, content_length
end

function net.get(host, port, uri, timeout)
	local s = socket.connect(host, port, timeout)
	socket.write(s, 'GET ' .. uri .. ' HTTP/1.1\r\n' ..
	 	'User-Agent: LuaBot/1.0\r\nAccept: text/plain\r\n' ..
		'Host: ' .. host .. ':' .. tostring(port) .. '\r\nConnection: close\r\n\r\n')
	local response, code = net.drain(s)
	socket.close(s)
	return response, code
end

So you can see (name of function: drain and variable name: sink) that
it is influenced by your code, which I thank you for.

I'm handling keyboard scancodes to input (currency, numeric and
alphanumeric mode with auto capitalization), graphical screens for
splash and transaction status, user login/logout, and I have a mini
language to drive the process of capturing user input and displaying
output so that I can write screens instead of writing code. The lua
parts are separated into a library, so I can build other applications,
and the application logic itself is now in 653 lines of Lua (mostly
the state machine that drives it) ...

It boils down to 4633 lines of code to add the functionality that I
wanted, versus 1279 for my entire extensions to Lua. As I mentioned
earlier, I don't have dynamic linking, and I'm building a static
executable and it seemed best to keep it trim. It's for the same
reasons that I'm searching for an alternative to json-lua because it's
taking 376 lines of Lua code, compared to 1274 of lines in my Lua
application.

-- G.