In pre release mode!

This commit is contained in:
Diego Nehab 2005-11-20 08:56:19 +00:00
parent f20f4889bf
commit 5e09779c7f
13 changed files with 279 additions and 407 deletions

View file

@ -1,59 +1,50 @@
This directory contains some sample programs using LuaSocket. This code
is not supported.
This directory contains some sample programs using
LuaSocket. This code is not supported.
listener.lua -- socket to stdout
talker.lua -- stdin to socket
listener.lua and talker.lua are about the simplest applications you can
write using LuaSocket. Run
listener.lua and talker.lua are about the simplest
applications you can write using LuaSocket. Run
'lua listener.lua' and 'lua talker.lua'
on different terminals. Whatever you type on talk.lua will be
printed by listen.lua.
b64.lua
qp.lua
eol.lua
These are tiny programs that perform Base64, Quoted-Printable and
end-of-line marker conversions.
on different terminals. Whatever you type on talk.lua will
be printed by listen.lua.
lpr.lua -- lpr client
This is a cool program written by David Burgess to print files using the
Line Printer Daemon protocol, widely used in Unix machines. It uses the
lp.lua implementation, in the etc directory. Just run
'lua lpr.lua <filename> queue=<printername>' and the file will print!
This is a cool program written by David Burgess to print
files using the Line Printer Daemon protocol, widely used in
Unix machines. It uses the lp.lua implementation, in the
etc directory. Just run 'lua lpr.lua <filename>
queue=<printername>' and the file will print!
cddb.lua -- CDDB client
This is the first try on a simple CDDB client. Not really useful, but one
day it might become a module.
This is the first try on a simple CDDB client. Not really
useful, but one day it might become a module.
daytimeclnt.lua -- day time client
Just run the program to retrieve the hour and date in readable form from
any server running an UDP daytime daemon.
Just run the program to retrieve the hour and date in
readable form from any server running an UDP daytime daemon.
echoclnt.lua -- UDP echo client
echosrvr.lua -- UDP echo server
These are a UDP echo client/server pair. They work with other client and
servers as well.
These are a UDP echo client/server pair. They work with
other client and servers as well.
tinyirc.lua -- irc like broadcast server
This is a simple server that waits simultaneously on two server sockets
for telnet connections. Everything it receives from the telnet clients
is broadcasted to every other connected client. It tests the select
function and shows how to create a simple server whith LuaSocket. Just
run tinyirc.lua and then open as many telnet connections as you want
to ports 8080 and 8081.
check-memory.lua -- checks memory consumption
This is just to see how much memory each module uses.
This is a simple server that waits simultaneously on two
server sockets for telnet connections. Everything it
receives from the telnet clients is broadcasted to every
other connected client. It tests the select function and
shows how to create a simple server whith LuaSocket. Just
run tinyirc.lua and then open as many telnet connections
as you want to ports 8080 and 8081.
Good luck,
Diego.

View file

@ -1,207 +0,0 @@
-- load our favourite library
local socket = require"socket"
-- creates a new set data structure
function newset()
local reverse = {}
local set = {}
return setmetatable(set, {__index = {
insert = function(set, value)
if not reverse[value] then
table.insert(set, value)
reverse[value] = table.getn(set)
end
end,
remove = function(set, value)
local index = reverse[value]
if index then
reverse[value] = nil
local top = table.remove(set)
if top ~= value then
reverse[top] = index
set[index] = top
end
end
end
}})
end
-- timeout before an inactive thread is kicked
local TIMEOUT = 10
-- set of connections waiting to receive data
local receiving = newset(1)
-- set of sockets waiting to send data
local sending = newset()
-- context for connections and servers
local context = {}
function wait(who, what)
if what == "input" then receiving:insert(who)
else sending:insert(who) end
context[who].last = socket.gettime()
coroutine.yield()
end
-- initializes the forward server
function init()
if table.getn(arg) < 1 then
print("Usage")
print(" lua forward.lua <iport:ohost:oport> ...")
os.exit(1)
end
-- for each tunnel, start a new server socket
for i, v in ipairs(arg) do
-- capture forwarding parameters
local iport, ohost, oport =
socket.skip(2, string.find(v, "([^:]+):([^:]+):([^:]+)"))
assert(iport, "invalid arguments")
-- create our server socket
local server = assert(socket.bind("*", iport))
server:settimeout(0) -- we don't want to be killed by bad luck
-- make sure server is tested for readability
receiving:insert(server)
-- add server context
context[server] = {
thread = coroutine.create(accept),
ohost = ohost,
oport = oport
}
end
end
-- starts a connection in a non-blocking way
function connect(who, host, port)
who:settimeout(0)
local ret, err = who:connect(host, port)
if not ret and err == "timeout" then
wait(who, "output")
ret, err = who:connect(host, port)
if not ret and err ~= "already connected" then
kick(context[who].peer)
kick(who)
return
end
end
return forward(who)
end
-- gets rid of a client
function kick(who)
if who then
sending:remove(who)
receiving:remove(who)
who:close()
context[who] = nil
end
end
-- loops accepting connections and creating new threads to deal with them
function accept(server)
while true do
-- accept a new connection and start a new coroutine to deal with it
local client = server:accept()
if client then
-- create contexts for client and peer.
local peer, err = socket.tcp()
if peer then
context[client] = {
last = socket.gettime(),
-- client goes straight to forwarding loop
thread = coroutine.create(forward),
peer = peer,
}
context[peer] = {
last = socket.gettime(),
peer = client,
-- peer first tries to connect to forwarding address
thread = coroutine.create(connect),
last = socket.gettime()
}
-- resume peer and client so they can do their thing
local ohost = context[server].ohost
local oport = context[server].oport
coroutine.resume(context[peer].thread, peer, ohost, oport)
coroutine.resume(context[client].thread, client)
else
print(err)
client:close()
end
end
-- tell scheduler we are done for now
wait(server, "input")
end
end
-- forwards all data arriving to the appropriate peer
function forward(who)
who:settimeout(0)
while true do
-- wait until we have something to read
wait(who, "input")
-- try to read as much as possible
local data, rec_err, partial = who:receive("*a")
-- if we had an error other than timeout, abort
if rec_err and rec_err ~= "timeout" then return kick(who) end
-- if we got a timeout, we probably have partial results to send
data = data or partial
-- forward what we got right away
local peer = context[who].peer
while true do
-- tell scheduler we need to wait until we can send something
wait(who, "output")
local ret, snd_err
local start = 0
ret, snd_err, start = peer:send(data, start+1)
if ret then break
elseif snd_err ~= "timeout" then return kick(who) end
end
-- if we are done receiving, we are done
if not rec_err then
kick(who)
kick(peer)
break
end
end
end
-- loop waiting until something happens, restarting the thread to deal with
-- what happened, and routing it to wait until something else happens
function go()
while true do
-- check which sockets are interesting and act on them
readable, writable = socket.select(receiving, sending)
-- for all readable connections, resume its thread
for _, who in ipairs(readable) do
if context[who] then
receiving:remove(who)
coroutine.resume(context[who].thread, who)
end
end
-- for all writable connections, do the same
for _, who in ipairs(writable) do
if context[who] then
sending:remove(who)
coroutine.resume(context[who].thread, who)
end
end
-- put all inactive threads in death row
local now = socket.gettime()
local deathrow
for who, data in pairs(context) do
if data.peer then
if now - data.last > TIMEOUT then
-- only create table if at least one is doomed
deathrow = deathrow or {}
deathrow[who] = true
end
end
end
-- finally kick everyone in deathrow
if deathrow then
for who in pairs(deathrow) do kick(who) end
end
end
end
init()
go()

View file

@ -1,7 +1,7 @@
local lp = require("socket.lp")
local function usage()
print('\nUsage: lua lptest.lua [filename] [keyword=val...]\n')
print('\nUsage: lua lpr.lua [filename] [keyword=val...]\n')
print('Valid keywords are :')
print(
' host=remote host or IP address (default "localhost")\n' ..