mirror of
https://github.com/elua/elua.git
synced 2025-01-08 20:56:17 +08:00
- corrected the uIP support code in send mode
- added the eLua web server example (romfs/lhttpd.lua, romfs/index.pht, romfs/test.lua). Use "lua /rom/lhttpd.lua" from the console to run the server. The server code is largely WIP.
This commit is contained in:
parent
27c9fb4a2c
commit
2acd3cf89d
51
romfs/index.pht
Normal file
51
romfs/index.pht
Normal file
@ -0,0 +1,51 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
|
||||
<html><head>
|
||||
<meta content="text/html; charset=ISO-8859-1" http-equiv="content-type"><title>eLua webserver test</title>
|
||||
</head><body>
|
||||
<div style="text-align: center;"><big>Welcome to the <span style="font-weight: bold;">eLua</span> web server!<span style="font-weight: bold;"></span></big><br> </div>
|
||||
<br>
|
||||
<div style="text-align: left;">The right column of the following table is generated by embedded Lua code:<br>
|
||||
<br>
|
||||
<table style="text-align: left; width: 400px;" border="1" cellpadding="2" cellspacing="2">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><span style="font-weight: bold;">eLua CPU</span></td>
|
||||
<td><?lua print(pd.cpu()) ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span style="font-weight: bold;">eLua board</span></td>
|
||||
<td><?lua print(pd.board()) ?></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<br>
|
||||
And now let's test CGI. Use the form below to control the on-board LED.<br><br>
|
||||
<form method="get" action="http://elua/index.pht" name="led">
|
||||
<table style="text-align: left; width: 400px;" border="0" cellpadding="2" cellspacing="2">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style="text-align: center;" valign="undefined"><button value="ledon" name="ledon">Led ON</button></td>
|
||||
<td style="text-align: center;" valign="undefined"><button value="ledoff" name="ledoff">Led OFF</button></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</form>
|
||||
<?lua
|
||||
local ledpin = pio.PF_0
|
||||
pio.output(ledpin)
|
||||
if reqdata['ledon'] == 'ledon' then
|
||||
pio.set(ledpin)
|
||||
print '<br><font color="blue"><b>The LED is now ON</b></font><br>'
|
||||
elseif reqdata['ledoff'] == 'ledoff' then
|
||||
pio.clear(ledpin)
|
||||
print '<br><font color="blue"><b>The LED is now OFF</b></font><br>'
|
||||
elseif next(reqdata) ~= nil then
|
||||
print '<br><font color="red"><b>Invalid CGI request!</b></font><br>'
|
||||
end
|
||||
?>
|
||||
<br>
|
||||
Press <a href="http://elua/test.lua">here</a> to go to a test page generated completely by a Lua script.<br>
|
||||
<br>
|
||||
<span style="font-weight: bold;">AND MOST IMPORTANTLY ... remember to have fun with eLua :)</span><br>
|
||||
</div>
|
||||
</body></html>
|
116
romfs/lhttpd.lua
Normal file
116
romfs/lhttpd.lua
Normal file
@ -0,0 +1,116 @@
|
||||
-- Mapping between file extension (and request) and HTTP response
|
||||
local extmap = {
|
||||
txt = "text/plain",
|
||||
htm = "text/html",
|
||||
pht = "text/html",
|
||||
gif = "image/gif",
|
||||
jpg = "imge/jpeg",
|
||||
png = "image/png",
|
||||
lua = "text/html"
|
||||
}
|
||||
|
||||
local basedir = "/rom/"
|
||||
reqdata = {}
|
||||
|
||||
-- Auxiliary function: execute the given code with a substituted "print"
|
||||
-- that prints everything to a string, return the code output
|
||||
local function docode(thecode)
|
||||
local strbuf = {}
|
||||
local oldprint, newprint = print, function(...)
|
||||
local total, idx = select('#', ...)
|
||||
for idx = 1, total do
|
||||
strbuf[#strbuf + 1] = tostring(select(idx, ...)) .. (idx == total and '\n' or '\t')
|
||||
end
|
||||
end
|
||||
print = newprint
|
||||
local f = loadstring(thecode)
|
||||
if f then
|
||||
f()
|
||||
else
|
||||
print ">>> Invalid Lua code <<<"
|
||||
end
|
||||
print = oldprint
|
||||
collectgarbage('collect')
|
||||
return table.concat(strbuf)
|
||||
end
|
||||
|
||||
function process(header)
|
||||
-- look for first line
|
||||
local s, e = header:find("[^\n]+\n")
|
||||
local reqstr = header:sub(s, e)
|
||||
local respheader, respdata = '', ''
|
||||
|
||||
reqdata = {}
|
||||
-- check if the request is valid, also keep the actual request
|
||||
local i, valid, req = 0, false
|
||||
for w in reqstr:gmatch("%S+") do
|
||||
valid = ( i == 0 and w == "GET" ) or valid
|
||||
req = ( i == 1 and w ) or req
|
||||
i = i + 1
|
||||
end
|
||||
|
||||
-- valid is true if the request is valid, req has the request string
|
||||
if valid then
|
||||
-- now look for all parameters in this request (if any)
|
||||
local fname = ""
|
||||
if req:find("%?") then
|
||||
local rest
|
||||
_, _, fname, rest = req:find("(.*)%?(.*)")
|
||||
-- small trick: end "rest" with a "&" for easier processing
|
||||
-- now look for "var=value" pairs in the request (GET encoding)
|
||||
rest = rest .. "&"
|
||||
for crtpair in rest:gmatch("[^&]+") do
|
||||
local _, __, k, v = crtpair:find("(.*)=(.*)")
|
||||
-- replace all "%xx" characters with their actual value
|
||||
v = v:gsub("(%%%x%x)", function(s) return string.char(tonumber(s:sub(2, -1), 16)) end)
|
||||
reqdata[k] = v
|
||||
end
|
||||
else
|
||||
fname = req
|
||||
end
|
||||
fname = ( fname == "/" ) and "index.pht" or fname:sub(2, -1)
|
||||
s, e = fname:find("%.[%a%d]+$")
|
||||
local ftype = fname:sub(s+1, e):lower()
|
||||
ftype = (#ftype > 0 and ftype) or "txt"
|
||||
fname = basedir .. fname
|
||||
|
||||
-- now "fname" has the name of the requested file, and "reqdata" the actual request data
|
||||
-- also "ftype" holds the file type (actually its extension)
|
||||
local tf = io.open(fname, "r")
|
||||
if tf then
|
||||
respheader = "HTTP/1.1 200 OK\r\nConnection: close\r\nServer: eLua-miniweb\r\nContent-Type: " .. extmap[ftype or "txt"] .. "\r\n\r\n"
|
||||
-- Preprocess "lua" and "pht" files: run the Lua ones, parse the .htm ones for "<?lua ... ?>" sequences
|
||||
if ftype == "pht" or ftype == "lua" then
|
||||
local fdata = tf:read("*a")
|
||||
if ftype == "lua" then
|
||||
respdata = docode(fdata)
|
||||
else
|
||||
-- Look for <?lua ... lua> patterns and execute them accordingly
|
||||
respdata = fdata:gsub("<%?lua(.-)%?>", docode)
|
||||
end
|
||||
else
|
||||
respdata = tf:read("*a")
|
||||
end
|
||||
tf:close()
|
||||
else
|
||||
respheader = "HTTP/1.1 404 Not Found\r\nConnection: close\r\nServer: eLua-miniweb\r\nContent-Type: text/html\r\n\r\nPage not found"
|
||||
end
|
||||
end
|
||||
return respheader .. respdata
|
||||
end
|
||||
|
||||
while true do
|
||||
local sock, remoteip, err = net.accept( 80 )
|
||||
print( "Got connection on socket", sock )
|
||||
print( "Remote ip: " .. net.unpackip( remoteip, "*s" ) )
|
||||
local response, err2 = net.recv( sock, 1024 )
|
||||
print "Got request"
|
||||
local httpdata = process( response )
|
||||
if #httpdata > 0 then
|
||||
print "Sending response"
|
||||
net.send( sock, httpdata )
|
||||
end
|
||||
net.close( sock )
|
||||
reqdata = {}
|
||||
collectgarbage('collect')
|
||||
end
|
4
romfs/test.lua
Normal file
4
romfs/test.lua
Normal file
@ -0,0 +1,4 @@
|
||||
print "<html><body>"
|
||||
print "Hello from eLua!<br>"
|
||||
print 'Press <a href="http://elua/">here</a> to return to the main page.'
|
||||
print "</body></html>"
|
@ -342,17 +342,11 @@ void elua_uip_appcall()
|
||||
// We write directly in UIP's buffer
|
||||
if( uip_acked() )
|
||||
{
|
||||
// Send next part of the buffer (if needed)
|
||||
if( s->len <= uip_mss() ) // end of transmission
|
||||
{
|
||||
s->len = 0;
|
||||
elua_net_size minlen = UMIN( s->len, uip_mss() );
|
||||
s->len -= minlen;
|
||||
s->ptr += minlen;
|
||||
if( s->len == 0 )
|
||||
s->state = ELUA_UIP_STATE_IDLE;
|
||||
}
|
||||
else
|
||||
{
|
||||
s->len -= uip_conn->len;
|
||||
s->ptr += uip_conn->len;
|
||||
}
|
||||
}
|
||||
if( s->len > 0 ) // need to (re)transmit?
|
||||
{
|
||||
@ -364,7 +358,7 @@ void elua_uip_appcall()
|
||||
}
|
||||
else
|
||||
#endif
|
||||
uip_send( s->ptr, s->len );
|
||||
uip_send( s->ptr, UMIN( s->len, uip_mss() ) );
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user