Browse Source

remove old files and submodules

CherryWebdis
Markus Bergholz 4 years ago
parent
commit
e9bc80a3c3

+ 0
- 3
.gitmodules View File

@@ -1,6 +1,3 @@
[submodule "luadyad"]
path = luadyad
url = https://github.com/markuman/luadyad
[submodule "resp"]
path = resp
url = https://github.com/soveran/resp

+ 0
- 17
build.sh View File

@@ -1,17 +0,0 @@
#!/bin/bash

# take one c compiler of you choice!
if (("$#" == 0)); then
CC=gcc
else
CC=$1
fi

# build luadyad
$CC -Iluadyad/dyad/src/ luadyad/dyad/src/dyad.c -llua luadyad/luadyad.c -o tinywebdis

# build lsocket
$CC -fPIC -Ilsocket-1.3-1 -shared -llua lsocket-1.3-1/lsocket.c -o lsocket.so

# link resp.lua to ./
ln -s resp/resp.lua ./

+ 0
- 22
lsocket-1.3-1/LICENCE View File

@@ -1,22 +0,0 @@
Copyright (c) 2013-2014 Gunnar Zötl <gz@tset.de>

Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.

+ 0
- 72
lsocket-1.3-1/Makefile View File

@@ -1,72 +0,0 @@
# lsocket Makefile, works on Linux and Mac OS X, everywhere else roll your own.

ifdef DEBUG
DBG=-g
OPT=
else
DBG=
OPT=-O2
endif

OS = $(shell uname -s)

# if this does not work, just set it to your version number
LUA_VERSION=$(shell lua -e "print((string.gsub(_VERSION, '^.+ ', '')))")

LUA_DIR = /usr/local
LUA_LIBDIR=$(LUA_DIR)/lib/lua/$(LUA_VERSION)
LUA_SHAREDIR=$(LUA_DIR)/share/lua/$(LUA_VERSION)
LUA_INCLUDE=$(LUA_DIR)/include

ifndef LIBFLAG
ifeq ($(OS),Darwin)
LIBFLAG=-bundle -undefined dynamic_lookup -all_load
else
LIBFLAG=-shared
endif
endif

ifndef PTHRFLAG
PTHRFLAG=-pthread
endif

ifndef CC
CC=gcc
endif

CFLAGS=-Wall -fPIC $(OPT) $(DBG)
INCDIRS=-I$(LUA_INCLUDE)
LDFLAGS=$(LIBFLAG) $(DBG)

all: lsocket.so

debug:; make DEBUG=1

install: all
mkdir -p $(LUA_LIBDIR)
cp lsocket.so $(LUA_LIBDIR)

install-aresolver: async_resolver.so
mkdir -p $(LUA_LIBDIR)
cp async_resolver.so $(LUA_LIBDIR)

lsocket.so: lsocket.o
$(CC) $(LDFLAGS) -o $@ $<

async_resolver.so: async_resolver.o gai_async.o
$(CC) $(LDFLAGS) -o $@ $^ $(PTHRFLAG)

lsocket.o: lsocket.c
$(CC) $(CFLAGS) $(INCDIRS) -c $< -o $@

async_resolver.o: async_resolver.c gai_async.h
$(CC) $(CFLAGS) $(INCDIRS) -c $< -o $@

gai_async.o: gai_async.c gai_async.h
$(CC) $(CFLAGS) $(INCDIRS) -c $< -o $@ $(PTHRFLAG)

clean:
find . -name "*~" -exec rm {} \;
find . -name .DS_Store -exec rm {} \;
find . -name ._* -exec rm {} \;
rm -f *.o *.so core samples/testsocket

+ 0
- 362
lsocket-1.3-1/async_resolver.c View File

@@ -1,362 +0,0 @@
/* ares_aresolve.c
*
* provide asynchronous dns lookup support. This is a companion lib to
* lsocket, but can also be used without it.
*
* Gunnar Zötl <gz@tset.de>, 2013
* Released under MIT/X11 license. See file LICENSE for details.
*/

#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include "gai_async.h"
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

#include "lua.h"
#include "lauxlib.h"

#if LUA_VERSION_NUM == 501
#define luaL_newlib(L,funcs) lua_newtable(L); luaL_register(L, NULL, funcs)
#define luaL_setfuncs(L,funcs,x) luaL_register(L, NULL, funcs)
#endif

#define ARESOLVER "socket_aresolver"
#define TOSTRING_BUFSIZ 64
#define LSOCKET_INET "inet"
#define LSOCKET_INET6 "inet6"

/* structure for asynch resolver userdata */
typedef struct _aresolver {
struct gai_request *rq;
} aResolver;

/* ares_checkaResolver
*
* Checks whether the item at the index on the lua stack is a userdata of
* the type ARESOLVER. If so, returns its block address, else
* throw an error.
*
* Arguments:
* L Lua State
* index stack index where the userdata is expected
*/
static aResolver* ares_checkaResolver(lua_State *L, int index)
{
aResolver *ares = (aResolver*) luaL_checkudata(L, index, ARESOLVER);
return ares;
}

/* ares_pushaResolver
*
* create a new, empty aResolver userdata, attach its metatable
* and push it to the stack.
*
* Arguments:
* L Lua state
*
* Lua Returns:
* +1 aResolver userdata
*/
static aResolver* ares_pushaResolver(lua_State *L)
{
aResolver *ares = (aResolver*) lua_newuserdata(L, sizeof(aResolver));
luaL_getmetatable(L, ARESOLVER);
lua_setmetatable(L, -2);
return ares;
}

/*** Housekeeping metamethods ***/

/* ares__gc
*
* __gc metamethod for the ares userdata.
* cancels request if
*
* Arguments:
* L Lua State
*
* Lua Stack:
* 1 aResolver userdata
*/
static int ares__gc(lua_State *L)
{
aResolver *ares = (aResolver*) lua_touserdata(L, 1);
void *dummy;
gai_cancel(ares->rq);
gai_finalize(ares->rq, (struct addrinfo **) &dummy);
ares->rq = NULL;

return 0;
}

/* ares__toString
*
* __tostring metamethod for the lsock userdata.
* Returns a string representation of the aResolver
*
* Arguments:
* L Lua State
*
* Lua Stack:
* 1 aResolver userdata
*
* Lua Returns:
* +1 string representation of aResolver userdata
*/
static int ares__toString(lua_State *L)
{
aResolver *ares = ares_checkaResolver(L, 1);
char buf[TOSTRING_BUFSIZ];
if (snprintf(buf, TOSTRING_BUFSIZ, "%s: %p", ARESOLVER, ares) >= TOSTRING_BUFSIZ)
return luaL_error(L, "Whoopsie... the string representation seems to be too long.");
/* this should not happen, just to be sure! */
lua_pushstring(L, buf);
return 1;
}

/* metamethods for the ares userdata
*/
static const luaL_Reg ares_meta[] = {
{"__gc", ares__gc},
{"__tostring", ares__toString},
{0, 0}
};

/*** global helper functions ***/

/* ares_error
*
* pushes nil and an error message onto the lua stack and returns 2
*
* Arguments:
* L lua State
* msg error message
*
* Returns:
* 2 (number of items put on the lua stack)
*/
static int ares_error(lua_State *L, const char *msg)
{
lua_pushnil(L);
lua_pushstring(L, msg);
return 2;
}

/*** aresolver methods ***/

/* ares_poll
*
* checks the status of an asynchronous getaddrinfo request
*
* Arguments:
* L Lua State
*
* Lua Stack:
* 1 the aResolver userdata
*
* Lua Returns:
* +1 true, if the request is complete, false otherwise. nil + error
* message if an error occurred.
*/
static int ares_poll(lua_State *L)
{
aResolver *ares = ares_checkaResolver(L, 1);
if (!ares->rq)
return ares_error(L, "invalid request object, has already been finalized.");
int res = gai_poll(ares->rq);
if (res >= 0)
lua_pushboolean(L, res);
else
return ares_error(L, strerror(errno));
return 1;
}

/* ares_cancel
*
* cancels an asynchronous getaddrinfo request
*
* Arguments:
* L Lua State
*
* Lua Stack:
* 1 the aResolver userdata
*
* Lua Returns:
* +1 true, if the cancel request was sent, nil + error message if an
* error occurred.
*/
static int ares_cancel(lua_State *L)
{
aResolver *ares = ares_checkaResolver(L, 1);
if (!ares->rq)
return ares_error(L, "invalid request object, has already been finalized.");
int res = gai_cancel(ares->rq);
if (res == 0)
lua_pushboolean(L, 1);
else
return ares_error(L, strerror(errno));
return 1;
}

/* ares_finalize
*
* finalizes an asynchronous getaddrinfo request
*
* Arguments:
* L Lua State
*
* Lua Stack:
* 1 the aResolver userdata
*
* Lua Returns:
* +1 a table of resolved addresses if the request succceeded, nil +
* error message if an error occurred.
*/
static int ares_finalize(lua_State *L)
{
aResolver *ares = ares_checkaResolver(L, 1);
struct addrinfo *info;
char buf[TOSTRING_BUFSIZ];
if (!ares->rq)
return ares_error(L, "invalid request object, has already been finalized.");
int err = gai_finalize(ares->rq, &info);

if (err != 0) {
if (info) freeaddrinfo(info);
return ares_error(L, gai_strerror(err));
}

int i = 1;
lua_newtable(L);
while (info) {
if (info->ai_family == AF_INET || info->ai_family == AF_INET6) {
lua_newtable(L);
lua_pushliteral(L, "family");
lua_pushstring(L, info->ai_family == AF_INET ? LSOCKET_INET : LSOCKET_INET6);
lua_rawset(L, -3);
lua_pushliteral(L, "addr");
struct sockaddr *sa = info->ai_addr;
if (sa->sa_family == AF_INET)
lua_pushstring(L, inet_ntop(sa->sa_family, (const void*) &((struct sockaddr_in*)sa)->sin_addr, buf, TOSTRING_BUFSIZ));
else
lua_pushstring(L, inet_ntop(sa->sa_family, (const void*) &((struct sockaddr_in6*)sa)->sin6_addr, buf, TOSTRING_BUFSIZ));
lua_rawset(L, -3);
lua_rawseti(L, -2, i++);
info = info->ai_next;
}
/* silently ignore unknown address families */
}
freeaddrinfo(info);
ares->rq = NULL;
return 1;
}

/* aresolver method list
*/
static const struct luaL_Reg ares_methods [] ={
{"poll", ares_poll},
{"cancel", ares_cancel},
{"finalize", ares_finalize},
{NULL, NULL}
};

/*** constructor (returned when the lib is require()d) ***/

/* _needsnolookup
*
* helper function: checks if the address consists only of chars that
* make up a valid ip(v4 or v6) address, and thus needs no nslookup.
*
* Arguments:
* addr address to check
*
* Returns:
* 1 if the address consists only of chars that make up a valid ip(v4
* or v6) address, 0 otherwise.
*
* Note: this does not check whether the address is a valid ip address,
* just whether it consists of chars that make up one.
*/
static int _needsnolookup(const char *addr)
{
int len = strlen(addr);
int pfx = strspn(addr, "0123456789.");
if (pfx != len) {
pfx = strspn(addr, "0123456789abcdefABCDEF:");
/* last 2 words may be in dot notation */
if (addr[pfx] == '.') {
int lpfx = strrchr(addr, ':') - addr;
if (lpfx == 0 || lpfx > pfx) return 0;
pfx = lpfx + 1 + strspn(addr + lpfx + 1, "0123456789.");
}
}
return pfx == len;
}

/* ares_aresolver
*
* starts an asynchronous getaddrinfo request
*
* Arguments:
* L Lua State
*
* Lua Stack:
* 1 the name to resolve
*
* Lua Returns:
* +1 true, if the cancel request was sent, nil + error message if an
* error occurred.
*/
static int ares_aresolver(lua_State *L)
{
const char *name = luaL_checkstring(L, 1);
aResolver *ares = ares_pushaResolver(L);
struct addrinfo hint;

memset(&hint, 0, sizeof(hint));
hint.ai_family = AF_UNSPEC;
/* reduce the number of duplicate hits, this makes no difference for
* the actual dns resolving.
*/
hint.ai_protocol = IPPROTO_TCP;
hint.ai_socktype = SOCK_STREAM;
if (_needsnolookup(name))
hint.ai_flags = AI_NUMERICHOST;

ares->rq = gai_start(name, 0, &hint);
if (ares->rq == NULL)
return ares_error(L, strerror(errno));
return 1;
}

/* luaopen_async_resolve
*
* open and initialize this library
*/
int luaopen_async_resolver(lua_State *L)
{
/* add aResolver userdata metatable */
luaL_newmetatable(L, ARESOLVER);
luaL_setfuncs(L, ares_meta, 0);
/* methods */
lua_pushliteral(L, "__index");
luaL_newlib(L, ares_methods);
lua_rawset(L, -3);
/* type */
lua_pushliteral(L, "__type");
lua_pushstring(L, ARESOLVER);
lua_rawset(L, -3);
/* cleanup */
lua_pop(L, 1);

/* return resolver function instead of a table */
lua_pushcfunction(L, ares_aresolver);
return 1;
}

+ 0
- 23
lsocket-1.3-1/doc/LICENSE View File

@@ -1,23 +0,0 @@
Copyright (c) 2013 Gunnar Zötl <gz@tset.de>

Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.


+ 0
- 403
lsocket-1.3-1/doc/README View File

@@ -1,403 +0,0 @@
README

lsocket

A library that provides network programming support for Lua.

Author: Gunnar Zötl , 2013-2014.
Released under MIT/X11 license. See file LICENSE for details.

Introduction

lsocket provides not complete, but good enough support for socket
programming. It supports IPv4, IPv6 and unix domain sockets, and
selects automatically which one to use based on the address you bind or
connect to. Also, it is almost-nonblocking: except for lsocket.select()
and nameserver lookups, nothing ever blocks ([1]*). And you can also
make lsocket.select() nonblocking by passing 0 as a timeout value.
lsocket has been tested with lua 5.1.5, 5.2.3 and luajit 2.0.1 on Linux
and Mac OS X.

Installing

This uses only stuff that comes with your system. Normally, calling
sudo luarocks install lsocket

or when you have an unpacked source folder,
sudo luarocks make

should do the right thing.

There is also a Makefile in the distribution directory, which has been
created for and on Linux and Mac OS X. This does not cater for
installation, so the luarocks method is preferrable where possible.

Using

lsocket = require "lsocket"

Constructors

socket = lsocket.bind( [type], [address], [port], [backlog] )
creates a new socket and binds it locally.

Arguments

type
(optional) type of socket to create, may be "udp", "tcp",
or "mcast", defaults to "tcp". If the type is mcast, the
socket will be a udp socket that is additionally set up
for use as a ipv4 broadcast or ipv6 multicast client
socket. mcast is not available for unix domain sockets.

address
(optional) ip address or hostname to bind to, defaults to
lsocket.INADDR_ANY ('0.0.0.0'). If this is an IPv4
address, the socket will be an IP socket, if it is an IPv6
address, the socket will be an IPv6 socket, and if it
contains a slash (/) character, it will be a unix domain
socket with the address as the path on the file system. On
linux, if the first char is '@', then it will be a unix
domain socket with an abstract socket name, i.e. one that
does not exist in the file system.

port
port number to bind to, meaningless with unix domain
sockets.

backlog
(optional) length of connection backlog on this socket,
defaults to 5. This is only useful for tcp sockets.

Returns

the bound socket, or nil+error message on error.

socket = lsocket.connect( [type], address, port, [ttl] )
connects to a remote socket.

Arguments

type
(optional) type of socket to create, may be "udp", "tcp",
or "mcast", defaults to "tcp". If the type is mcast, the
socket will be a udp socket that is additionally set up
for use as a ipv4 broadcast or ipv6 multicast server
socket. mcast is not available for unix domain sockets.

address
ip address or hostname to connect to. See the address
parameter to bind() above for a more detailed explanation.

port
port number to connect to, meaningless with unix domain
sockets.

ttl
(optional) ttl for multicast packets, defaults to 1. Only
useful if type is "mcast".

Returns

the socket in connecting state, or nil+error message on error.
Note that you need to select() the socket for writing to wait
for the connect to finish. Of course you can also select the
socket for reading, but if you select for writing, select() will
return as soon as the socket is connected, whereas if you select
for reading, select() will return when the socket is connected
and the server has sent data. In any case select() will return
if the connection fails. You should call status() on a socket
that was created by connect() after it is first returned from
select() in order to see whether the connection was successful.

Socket Methods

tbl = socket:info( [what] )
returns a table with information about the socket.

Arguments

what
(optional) specify what info you are interested in. The
result is returned in a table.

Returns

a table with the requested information:

+ If what is omitted or nil, return a standard set of socket
infos.
These fields are in the table:

fd
socket file descriptor

family
ip protocol family, "inet" or "inet6"

type
"udp" or "tcp"

listening
true if the socket is listening (created by
lsocket.bind), false otherwise

multicast
true if the socket is a multicast socket, false
otherwise.

+ If what is "peer", return information about the socket peer.
These fields are in the table:

family
ip protocol family, "inet" or "inet6"

addr
ip address

port
port number

If called on unix domain sockets, this will only return useful
information for sockets created with lsocket.bind().
+ If what is "socket", return information about the local
socket. Fields as for "peer". If called on unix domain
sockets, this will only return useful information for sockets
created with lsocket.connect().

ok, err = socket:status()
check a sockets error status.

Returns

true if the socket has no errors, nil + error message otherwise.

fd = socket:getfd()
returns a socket file descriptor. You probably don't need this,
it is only for interaction with other packages.

Returns

the sockets file descriptor.

ok, err = socket.setfd(newfd)
sets a sockets file descriptor. Only -1 (incalid descriptor) is
allowed as argument. You probably don't need this, it is only
for interaction with other packages.

Returns

true if the descriptor was -1 and the sockets descriptor has
been set to -1, nil + error message otherwise.

sock, addr, port = socket:accept()
accept a new connection on a socket

Returns

a new socket with the accepted connection and ip address and
port of the remote end on success, false if no connection is
available to accept, or nil+error message on error. If called
with a unix domain socket, addr and port will be nil on success.

This only works on tcp type sockets.

string = socket:recv( [size] )
reads data from a socket

Arguments

size
(optional) the length of the buffer to use for reading,
defaults to some internal value

Returns

a string containing the data read, false if no data was
available to read, nil if the remote end closed the connection
(tcp connections only), or nil+error message on error.

This should only be used for tcp type sockets, or for udp type
sockets that have been created by lsocket.connect(). For udp
type sockets, that have been created with lsocket.bind(), see
socket:recvfrom()

string, address, port = socket:recvfrom( [size] )
reads data from a socket

Arguments

size
(optional) the length of the buffer to use for reading,
defaults to 4096

Returns

a string containing the data read, and the ip address and port
number of the remote end of the connection, false if no data was
available to read, or nil+error message on error.

This should only be used for udp type sockets. For tcp type
sockets, see socket:recv()

nbytes = socket:send(string)
writes data to a socket

Arguments

string
data to write to the socket

Returns

the number of bytes written, or false if the socket was not
ready to accept data, or nil+error message on error.

This should only be used for tcp type sockets, or for udp type
sockets that have been created by lsocket.connect(). For udp
type sockets, that have been created with lsocket.bind(), see
socket:sendto()

nbytes = socket:sendto(string, address, port)
writes data to a socket

Arguments

string
data to write to the socket

address
ip address of remote end of socket to send data to

port
port number of remote end of socket to send data to

Returns

the number of bytes written, or false if the socket was not
ready to accept data, or nil+error message on error.

This should only be used for udp type sockets. For tcp type
sockets, see socket:send()

ok = socket:close()
closes a socket

Returns

true if closing the socket went ok, or nil+error message on
error.

Functions

[read [, write]] = lsocket.select([read [, write]] , [timeout] )
calls select() on up to 2 tables of sockets, has timeout

Arguments

read
(opt) table of sockets to wait on for reading

write
(opt) table of sockets to wait on for writing

timeout
(opt) timeout in seconds (millisecond resolution),
defaults to infinite.

Either only the read socket table or values for both socket
tables must be given. That means, if you want to wait on sockets
for writing, you will also have to pass a table or nil for
reading. The timeout value can be specified without passing any
tables before it, so that lsocket.select(timeout) can be used as
a millisecond precision sleep function. Closed sockets are
ignored by lsocket.select(), and it is an error to call
lsocket.select() without any open sockets and timeout.

Returns

either as many tables as were passed as arguments, each one
filled with the sockets that became ready from the select, false
if a timeout occurred before any socket became ready, or
nil+error message on error.

Note: if you pass nil for the read sockets and some table for
the write sockets, when a socket you wait on becomes ready, an
empty table is returned as first return value.

tbl = lsocket.resolve(name)
attempts a name resolution of its argument.

Arguments

name
hostname to find ip address(es) for

Returns

a table of ip addresses that the hostname resolves to. For each
address, a record (subtable) is found in the result table with
the fields

family
IP protocol family, "inet" or "inet6"

addr
the ip address

On error, returns nil + error message.

tbl = lsocket.getinterfaces()
enumerate interfaces and their addresses

Returns

a list containing information about all available interfaces.
For each interface, one or more records (subtables) are found in
the result table with the fields

name
interface name

family
IP protocol family, "inet" or "inet6"

addr
the ip address

mask
the netmask

On error, returns nil + error message.

Constants

lsocket.INADDR_ANY
IPv4 "any" address, i.e. what you bind to if you intend to
accept connections on all addresses your computer has.

lsocket.IN6ADDR_ANY
IPv6 "any" address, see lsocket.INADDR_ANY.

lsocket._VERSION
Version number of the lsocket module.

Examples

There are a few examples in the samples folder, including a server and
client for tcp, udp and multicast. For all of those examples, if you
start them without command line arguments, they work with IPv4, if
start them with the argument 6, they work with IPv6.

Footnotes

[2](*) The functions connect, bind, resolve and the method sendto
transparently use name service resolution, which may block, if a name
server is not available or slow to respond. However, name service
resolution is not used if you pass an IP address (IPv4 or IPv6) or a
path (unix domain) as address argument to those functions.

Verweise

1. file:///home/gunnar/stuff/lsocket/html/README.html#fn1
2. file:///home/gunnar/stuff/lsocket/html/README.html#r_fn1

+ 0
- 75
lsocket-1.3-1/doc/README_ARESOLVER View File

@@ -1,75 +0,0 @@
README_ARESOLVER

Since version 1.2, lsocket comes with an additional library to do
asynchronous dns lookups. It works by spawning a separate thread for
each dns lookup and providing functions to check for completion and
for fetching the results. This is experimental, and thus not an
official part of lsocket, even though it comes with it. Since this is
only one function, requiring this library will return a function
instead of a table.

Building
As this is not an "official" part of lsocket, it can only be built
via the Makefile. To build, cd to the src directory and type:
make async_resolver.so
and then to install:
make install-aresolver

Using

async_resolve = require "async_resolver"

Constructor

request = async_resolve(hostname)
async_resolve here is the function returned by requiring
async_resolver. Calling it with a hostname returns a request
object.

Returns

a request object which you can poll and finally get your answer
from, or nil + error message if an error occurred.

Resolver Methods

ok = request:poll()
checks whether the request is completed.

Returns

true if the request is completed, false if not, and nil + error
message if an error occurred.

ok = request:cancel()
cancels an asynchronous dns lookup request.

Returns

true if the request has received the cancel, or nil + error
message if an error occurred.
Note that it is not guaranteed when the request will be
canceled, it may be immediately or some time in the future.
The cancel method returns immediately, though.

addrs = request:finalize()
fetch the results from an asynchronous dns request.

Returns

a table of ip addresses that the hostname resolves to. For each
address, a record (subtable) is found in the result table with
the fields

family IP protocol family, "inet" or "inet6"
addr the ip address

If an error occurred either in this method or in the course of
the dns resolving, returns nil + error message. This is also
true if the request has been canceled, in which case the error
message will indicate that it has been cancelled.

+ 0
- 191
lsocket-1.3-1/gai_async.c View File

@@ -1,191 +0,0 @@
/* gai_async.c
*
* a simple wrapper for getaddrinfo using pthreads to make it asynchronous.
*
* Gunnar Zötl <gz@tset.de>, 2013
* Released under MIT/X11 license. See file LICENSE for details.
*/

#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include "gai_async.h"
#include <pthread.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

/* handler for asynchronous getaddrinfo() requests. Carries everything
* getaddrinfo() needs and also some housekeeping stuff like the worker
* thread id, the run status of the request and the error code returned
* by getaddrinfo() upon completion.
*/
struct gai_request {
pthread_t worker;
int done;
int err;
char *node;
char *service;
struct addrinfo *hints;
struct addrinfo *res;
};

/* helper for gai_worker: this cleanup handler marks the request as done
* when it completed normally and also when it was canceled.
*/
static void gai_cleanup(void *arg)
{
struct gai_request *rq = (struct gai_request*) arg;
rq->done = 1;
}

/* gai_worker
*
* perform the getaddrinfo request. Started as a thread by gai_start.
*
* Arguments:
* arg pointer to a gai_request structure
*
* Returns:
* 0, is ignored by the call to pthread_join() in gai_finalize()
*/
static void *gai_worker(void *arg)
{
struct gai_request *rq = (struct gai_request*) arg;
pthread_cleanup_push(gai_cleanup, rq);
rq->err = getaddrinfo(rq->node, rq->service, rq->hints, &rq->res);
pthread_cleanup_pop(1);
return 0;
}

/* gai_start
*
* start the getaddrinfo worker thread.
*
* Arguments:
* node node name, as for getaddrinfo()
* service service name, as for getaddrinfo()
* hints criteria for name resolving, as for getaddrinfo()
*
* Returns:
* a pointer to the request handler on success, NULL on failure. If this
* function returns NULL, it is always because the worker thread could
* not be spawned.
*/
struct gai_request *gai_start(const char *node, const char *service, const struct addrinfo *hints)
{
struct gai_request *rq = malloc(sizeof(struct gai_request));
if (rq) {
rq->done = 0;
rq->node = node ? strdup(node) : NULL;
rq->service = service ? strdup(service) : NULL;
if (hints) {
rq->hints = malloc(sizeof(struct addrinfo));
memcpy(rq->hints, hints, sizeof(struct addrinfo));
} else
rq->hints = NULL;
rq->res = NULL;
int _err = pthread_create(&rq->worker, NULL, gai_worker, (void*) rq);
if (_err) {
free(rq);
rq = 0;
}
}
return rq;
}

/* gai_poll
*
* check whether the request has finished.
*
* Arguments:
* rq gai_request to check.
*
* Returns:
* 1 if finished, 0 if still running, and EAI_SYSTEM on error. An error
* can only occur if rq is invalid (a.k.a. NULL), in which case errno
* is set to EINVAL
*/
int gai_poll(struct gai_request *rq)
{
if (rq)
return rq->done;
errno = EINVAL;
return EAI_SYSTEM;
}

/* gai_cancel
*
* cancel a pending getaddrinfo request.
*
* Arguments:
* rq gai_request to cancel.
*
* Returns:
* 0 on success, EAI_SYSTEM on error. Errno will be set accordingly, either
* EINVAL if the rq pointer was NULL, or any error pthread_cancel returned,
* which, according to its manpage, will be ESRCH if there was no active
* thread with the id stored in the rq structure.
*
* Note: you must still call gai_finalize on a canceled request. No guarantee
* can be made about when the request will be canceled.
*/
int gai_cancel(struct gai_request *rq)
{
if (rq) {
int err = pthread_cancel(rq->worker);
if (err)
errno = err;
else
return 0;
} else
errno = EINVAL;
return EAI_SYSTEM;
}

/* gai_finalize
*
* finalize getaddrinfo request, clean up the gai_request structure and
* fetch the result from getaddrinfo.
*
* Arguments:
* rq gai_request to get results from
* res pointer to pointer for result, like the last argument to getaddrinfo()
*
* Returns:
* 0 on success, one of the EAI error codes if the request terminated
* successful, but getaddrinfo failed, or EAI_SYSTEM with errno set to
* EAGAIN if the request is not yet terminated, or to EINVAL if rq was
* NULL. If the request has previously been canceled, errno will be set
* to ECANCELED.
*
* After the call to gai_finalize, the gai_request handler in rq is no
* longer valid.
*/
int gai_finalize(struct gai_request *rq, struct addrinfo **res)
{
*res = NULL;
if (rq) {
if (rq->done) {
void *rv;
pthread_join(rq->worker, &rv);
int err = rq->err;
if (rq->node) free(rq->node);
if (rq->service) free(rq->service);
if (rq->hints) free(rq->hints);
*res = rq->res;
free(rq);
if (rv == PTHREAD_CANCELED) {
if (*res) freeaddrinfo(*res);
errno = ECANCELED;
*res = NULL;
} else
return err;
} else
errno = EAGAIN;
} else {
errno = EINVAL;
}
return EAI_SYSTEM;
}

+ 0
- 106
lsocket-1.3-1/gai_async.h View File

@@ -1,106 +0,0 @@
/* gai_async.h
*
* a simple wrapper for getaddrinfo using pthreads to make it asynchronous.
*
* Gunnar Zötl <gz@tset.de>, 2013
* Released under MIT/X11 license. See file LICENSE for details.
*
* Usage:
*
* Start request with gai_start(), for arguments see the manpage for
* getaddrinfo(). Call gai_poll() repeatedly on the gai_request handler
* returned by gai_start() until it returns 1, then call gai_finalize()
* to get the result and clean up the handler.
*
* Like so:
* -----------------------------------------------------------
char *node = "some.host.name";
char *service = NULL;
struct addrinfo hint, *res;
memset(&hint, 0, sizeof(hint));
hint.ai_family = AF_UNSPEC;
struct gai_request *rq = gai_start(node, service, &hint);
while (gai_poll(rq) == 0) {
puts("gai_poll() returned 0");
}
int err = gai_finalize(rq, &res);
* -----------------------------------------------------------
* results of the getaddrinfo request are now available in res, and must
* be free()d using freeaddrinfo()
*/

/* handler structure for asynchronous getaddrinfo() requests.
*/
struct gai_request;

/* gai_start
*
* start the getaddrinfo worker thread.
*
* Arguments:
* node node name, as for getaddrinfo()
* service service name, as for getaddrinfo()
* hints criteria for name resolving, as for getaddrinfo()
*
* Returns:
* a pointer to the request handler on success, NULL on failure. If this
* function returns NULL, it is always because the worker thread could
* not be spawned.
*/
struct gai_request *gai_start(const char *node, const char *service, const struct addrinfo *hints);

/* gai_poll
*
* check whether the request has finished.
*
* Arguments:
* rq gai_request to check.
*
* Returns:
* 1 if finished, 0 if still running, and -1 on error. An error can only
* occur if rq is invalid, in which case errno is set to EINVAL
*/
int gai_poll(struct gai_request *rq);

/* gai_cancel
*
* cancel a pending getaddrinfo request.
*
* Arguments:
* rq gai_request to cancel.
*
* Returns:
* 0 on success, EAI_SYSTEM on error. Errno will be set accordingly, either
* EINVAL if the rq pointer was NULL, or any error pthread_cancel returned,
* which, according to its manpage, will be ESRCH if there was no active
* thread with the id stored in the rq structure.
*
* Note: you must still call gai_finalize on a canceled request. No guarantee
* can be made about when the request will be canceled.
*/
int gai_cancel(struct gai_request *rq);

/* gai_finalize
*
* finalize getaddrinfo request, clean up the gai_request structure and
* fetch the result from getaddrinfo.
*
* Arguments:
* rq gai_request to get results from
* res pointer to pointer for result, like the last argument to getaddrinfo()
*
* Returns:
* 0 on success, one of the EAI error codes if the request terminated
* successful, but getaddrinfo failed, or EAI_SYSTEM with errno set to
* EAGAIN if the request is not yet terminated, or to EINVAL if rq was
* NULL. If the request has previously been canceled, errno will be set
* to ECANCELED.
*
* After the call to gai_finalize, the gai_request handler in rq is no
* longer valid.
*/
int gai_finalize(struct gai_request *rq, struct addrinfo **res);

+ 0
- 34
lsocket-1.3-1/lsocket-1.3-1.rockspec View File

@@ -1,34 +0,0 @@
package = "lsocket"
version = "1.3-1"
source = {
url = "http://www.tset.de/downloads/lsocket-1.3-1.tar.gz"
}
description = {
summary = "simple and easy socket support for lua.",
detailed = [[
lsocket is a library to provide socket programming support for
lua. It is not intended to be a complete socket api, but easy to
use and good enough for most tasks. Both IPv4 and IPv6 are
supported, as are tcp and udp, and also IPv4 broadcasts and
IPv6 multicasts.
]],
homepage = "http://www.tset.de/lsocket/",
license = "MIT",
maintainer = "Gunnar Zötl <gz@tset.de>"
}
supported_platforms = {
"unix"
}
dependencies = {
"lua >= 5.1, < 5.3"
}

build = {
type = "builtin",
modules = {
lsocket = {
sources = { "lsocket.c" },
},
},
copy_directories = { 'doc', 'samples' },
}

+ 0
- 1475
lsocket-1.3-1/lsocket.c
File diff suppressed because it is too large
View File


+ 0
- 27
lsocket-1.3-1/samples/README View File

@@ -1,27 +0,0 @@
This directory contains examples for lsocket. These are:

testsrv_tcp.lua a very simple tcp test server, just echoes what it
gets from the clients.
Start with argument 6 to use IPv6, otherwise use IPv4
testclt_tcp.lua a client for testsrv_tcp.lua, sends what you type to
the server and displays the response.
Start with argument 6 to use IPv6, otherwise use IPv4
testsrv_udp.lua like testsrv_tcp.lua, just for udp
testclt_udp.lua like testclnt_tcp.lua, just for udp
testsrv_mcast.lua a very simple multicast server, sends a counter.
Start with argument 6 to use IPv6 multicast, otherwise
use IPv4 broadcast
testclt_mcast.lua a very simple multicast client, displays what it
receives from the server.
Start with argument 6 to use IPv6 multicast, otherwise
use IPv4 broadcast

httpserver.lua a very simple http server, uses the rshttpd.lua library
to do the real work.
rshttpd.lua a ridiculously simple http server library. Documentation
is in the comment at the beginning.

httpclient.lua a simple http client. Call with the complete url you
want to fetch, httpclient.lua then issues a GET request
to the server at the specified address and prints the
data it receives to the standard output.

+ 0
- 54
lsocket-1.3-1/samples/httpclient.lua View File

@@ -1,66 +0,0 @@
--

ls = require "lsocket"

url = arg[1]
if url == nil then
error("Usage: " .. arg[0] .. " <url>")
end

if not string.find(url, "^http://") then
error("only http urls supported.")
end

local host, port, path = string.match(url, "^http://([^:/]+):?(%d*)(/?.*)$")
if not host then
error("invalid url.")
end
if #port == 0 then port = 80 end
if #path == 0 then path = "/" end

sock, err = ls.connect(host, port)
if not sock then
error(err)
end

ls.select(nil, {sock})
ok, err = sock:status()
if not ok then
error(err)
end

rq = "GET " .. path .. " HTTP/1.1\r\n"
rq = rq .. "Host: " .. host .. ":" .. port .. "\r\n"
rq = rq .. "Connection: close\r\n"
rq = rq .. "\r\n"

sent = 0
repeat
ls.select(nil, {sock})
sent = sent + sock:send(string.sub(rq, sent, -1))
until sent == #rq

reply = ""
repeat
ls.select({sock})
str, err = sock:recv()
if str then
reply = reply .. str
elseif err then
error(err)
end
until not str

print(reply)

+ 0
- 57
lsocket-1.3-1/samples/httpserver.lua View File

@@ -1,62 +0,0 @@
--

httpd = require "rshttpd"

local server = httpd.new('0.0.0.0', 8000, 1000, print)

local function tablify(tbl)
local res = '<table style="border: 1px solid grey">'
local k, v
for k, v in pairs(tbl) do
res = res .. '<tr><th align="right" valign="top" style="border: 1px solid grey">' .. k .. "</th><td>"
if type(v) == "table" then
res = res .. tablify(v)
else
res = res .. tostring(v)
end
res = res .. "</td></tr>"
end
res = res .. "</table>"
return res
end

server:addhandler("post", function(rq, header, data)
local res = table.concat{
"<html><head><title>", rq.url, "</title></head><body><pre>",
'<h1><b>POST</b> ', rq.url, "</h1>",
"<h2>Header</h2>",
tablify(header),
"<h2>Request</h2>",
tablify(rq),
"<b>data:</b><br>", data, "<br>",
"</pre></body></html>"}
return "200", res, { ["X-MyCustomHeader"] = "MyValue" }
end)

server:addhandler("get", function(rq, header)
local res = table.concat {
"<html><head><title>", rq.url, "</title></head><body><pre>",
'<h1><b>GET</b> ', rq.url, "</h1>"}
if rq.path == "/status" then
res = res .. "<h2>Status</h2>" .. tablify(server:status())
else
res = res .. table.concat{
"<h2>Header</h2>",
tablify(header),
"<h2>Request</h2>",
tablify(rq)}
end
res = res .. "</pre></body></html>"
return "200", res, { ["X-MyCustomHeader"] = "MyValue" }
end)

local doomsday = false

repeat
server:step(0.1)
until doomsday

+ 0
- 465
lsocket-1.3-1/samples/rshttpd.lua View File

@@ -1,498 +0,0 @@
--[[ ridiculously simple http server (library)

An example for lsocket

Gunnar Zötl <gz@tset.de>, 2013-03
Released under MIT/X11 license. See file LICENSE for details.

use:
httpd = require "rshttpd"
-- create server
server = httpd.new([addr], port, [ [backlog], logfn])

- Arguments:
- addr local ip address to bind to
- port local port to bind to
- backlog maximum unhandled connection requests
- logfn function to do out logging
- returns the http server object

-- add request method handler
server:add_handler("get", function(rq, header, data)
...
return "200", "All went well"
end)

- for each method METHOD you want to support, you can create a handler
by calling the method addhandler with a string containing METHOD in
lower case(!) as the first and the handler function as the second
argument.

For the handler function,
- Arguments:
- rq request data (url, peer, ...)
- header table of header fields
- data request body data
- Returns: status, res, hdr
- status http status code, usually 200
- res data to send to client
- hdr (optional) table of additional header fields to send to client.

-- run server
repeat
server:step([timeout])
-- do some other stuff
until done

- server:step() returns true if sockets were handled, or false if the
internal call to select() timed out.

-- request a status
status = server:status()
- server:status returns a table with these fields:
- methods supported methods
- rqlen number of sockets waiting to read data
- wqlen number of sockets waiting to send data
- nreqs number of requests served
- up_since date and time when the server has been started

-- handling keepalive connections
Connections are persistent (keep-alive) if requested by the client or
if the http version is 1.1 or more and the client does not forbid them
by requesting Connection: Close. The life time of a keepalive connection
can be set by setting server.keepalive to a value in seconds, default
is 10. If you do not want to support persistent connections, set
server.keepalive to false.

-- Notes:
As reads and writes in lsocket are non-blocking, and the data may not
be sent or received in one go from / to the socket, we set up the handlers
for the connections as coroutines. Whenever a handling process wants
some data, it enters its socket into a watch list for select, makes
a note of which coroutine to resume if the socket becomes ready for
read, and then yields. When data becomes ready, the coroutine will
be resumed, reads data from the socket and continues its processing.
Similarly for writing, we write as much as we can in one go and then
yield until we can write more. Repeat until all is written.
--]]

local ls = require "lsocket"

local gsub = string.gsub
local char = string.char
local format = string.format
local byte = string.byte
local sub = string.sub
local find = string.find
local match = string.match
local lower = string.lower
local yield = coroutine.yield
local date = os.date
local time = os.time
local remove = table.remove

local http_status_msg = {
["100"] = "Continue",
["101"] = "Switching Protocols",
["200"] = "OK",
["201"] = "Created",
["202"] = "Accepted",
["203"] = "Non-Authoritative Information",
["204"] = "No Content",
["205"] = "Reset Content",
["206"] = "Partial Content",
["300"] = "Multiple Choices",
["301"] = "Moved Permanently",
["302"] = "Found",
["303"] = "See Other",
["304"] = "Not Modified",
["305"] = "Use Proxy",
["307"] = "Temporary Redirect",
["400"] = "Bad Request",
["401"] = "Unauthorized",
["402"] = "Payment Required",
["403"] = "Forbidden",
["404"] = "Not Found",
["405"] = "Method Not Allowed",
["406"] = "Not Acceptable",
["407"] = "Proxy Authentication Required",
["408"] = "Request Time-out",
["409"] = "Conflict",
["410"] = "Gone",
["411"] = "Length Required",
["412"] = "Precondition Failed",
["413"] = "Request Entity Too Large",
["414"] = "Request-URI Too Large",
["415"] = "Unsupported Media Type",
["416"] = "Requested range not satisfiable",
["417"] = "Expectation Failed",
["500"] = "Internal Server Error",
["501"] = "Not Implemented",
["502"] = "Bad Gateway",
["503"] = "Service Unavailable",
["504"] = "Gateway Time-out",
["505"] = "HTTP Version not supported",
}

local function add_to_queue(tbl, sock)
local tid = #tbl + 1
tbl[tid] = sock
return tid
end

local function remove_from_queue(tbl, sock, tid)
local ts = #tbl
tid = tid or ts
tid = tid < ts and tid or ts
while tid > 0 do
if tbl[tid] == sock then
remove(tbl, tid)
break
end
tid = tid - 1
end
end

function waitfor(self, what, sock)
local tbl = self[what]
local tid = add_to_queue(tbl, sock)
self.requests[sock] = coroutine.running()
coroutine.yield()
self.requests[sock] = nil
remove_from_queue(tbl, sock, tid)
end

local function recv_data(self, sock)
waitfor(self, "rsocks", sock)
local ok, err = sock:recv()
if not ok and err then error(err) end
return ok
end

local function send_data(self, sock, data)
waitfor(self, "wsocks", sock)
local ok, err = sock:send(data)
if not ok then error(err) end
return ok
end

local function urldecode(str)
str = gsub(str, "+", " ")
str = gsub(str, "%%(%x%x)",
function(h) return char(tonumber(h,16)) end)
str = gsub (str, "\r\n", "\n")
return str
end

local function urlencode(str)
if (str) then
str = gsub(str, "\n", "\r\n")
str = gsub(str, "([^%w ])",
function (c) return format ("%%%02X", byte(c)) end)
str = gsub (str, " ", "+")
end
return str
end

local function next_line(self, sock, buf, pos)
while not find(buf, "\n", pos, true) do
local sb, err = recv_data(self, sock)
if not sb then error(err) end
buf = buf .. sb
end
local b, e, str = find(buf, "^([^\r\n]*)\r?\n", pos)
return b, e, str, buf
end

local function read_request(self, sock)
local request, header, body
local method, url, httpver, path, args
local pos = 1

-- read request line
local b, e, ln, rq = next_line(self, sock, "", pos)
method, url, httpver = match(ln, "^(%a+)%s+([^%s]+)%s+HTTP/([%d\.]+)$")
if not method then return error("can't find request line") end
if find(url, "?", 1, true) then
path, args = match(url, "^([^?]+)%?(.+)$")
else
path = url
end
request = {
method = lower(method),
url = url,
path = urldecode(path),
args = args,
httpver = tonumber(httpver),
peer = sock:info("peer")
}
pos = e + 1

-- read header
header = {}
repeat
b, e, ln, rq = next_line(self, sock, rq, pos)
if #ln > 0 then
local name, val = match(ln, "^([^%s:]+)%s*:%s*(.+)$")
header[lower(name)] = urldecode(val)
end
pos = e + 1
until #ln == 0

-- read body
if header["content-length"] then
local clen = tonumber(header["content-length"])
while #rq - pos + 1 ~= clen do
rq = rq .. recv_data(self, sock)
end
body = sub(rq, pos, pos + clen - 1)
end

return request, header, body
end

local function process_request(self, sock)
-- read request data
local rq, headers, body = read_request(self, sock)
local ok, status, res, hdr, answer, smsg, k, v
local keepalive = false
local conn = lower(headers.connection)

-- check whether we can process the request. If so, call the handler
if rq.httpver < 1.0 or rq.httpver > 1.1 then
res = "<html><head>Error</head><body><h1>HTTP version not supported</h1></body></html>"
status = "505"
else
if rq.method ~= nil and self.process[lower(rq.method)] ~= nil then
ok, status, res, hdr = pcall(self.process[lower(rq.method)], rq, headers, body)
end
if self.keepalive and (conn == 'keep-alive' or
(rq.httpver >= 1.1 and conn ~= 'close')) then
keepalive = true
end
-- check return status
if ok then
res = res or "(no data)"
status = tostring(status)
elseif not ok and res == nil then
res = "<html><head>Error</head><body><h1>Internal Error</h1>"
res = res .. "<p>" .. status .. "</p></body></html>"
status = "500"
keepalive = false
else
res = "<html><head>Error</head><body><h1>Not Implemented</h1></body></html>"
status = "501"
keepalive = false
end
end

-- compose reply to client: a simple http header and the result of the
-- handler as body.
smesg = http_status_msg[status] or "unknown status"
self:log(sock:info("peer").addr, rq.method, rq.url, "HTTP/" .. tostring(rq.httpver), status, smesg)
answer = "HTTP/" .. rq.httpver .. " " .. status .. " " .. smesg .. "\r\n"
answer = answer .. "Content-Type: text/html\r\n"
answer = answer .. "Content-Length: " .. tostring(#res) .. "\r\n"

if keepalive then
answer = answer .. "Connection: Keep-Alive\r\n"
answer = answer .. "Keep-Alive: timeout=" .. self.keepalive .. "\r\n"
end

if hdr then
for k, v in pairs(hdr) do
answer = answer .. k .. ": " .. tostring(v) .. "\r\n"
end
end
answer = answer .. "\r\n"
answer = answer .. res

-- send reply to client.
local tosend, sent = #answer, 0
repeat
sent = sent + send_data(self, sock, sub(answer, sent + 1, -1))
until sent == tosend
if keepalive then
self.stillalive[sock] = time() + self.keepalive
add_to_queue(self.rsocks, sock)
else
sock:close()
end
self.nreqs = self.nreqs + 1
return true
end

local function begin_request(self, sock)
local cr = coroutine.create(process_request)
local ok, err = coroutine.resume(cr, self, sock)
if not ok then
self:log(err)
sock:close()
end
return ok
end

local function continue_request(self, sock)
local cr = self.requests[sock]
local ok, err = coroutine.resume(cr)
if not ok then
self:log(err)
sock:close()
end
return ok
end

local httpd = {}
local httpd_methods = {}

function httpd.new(addr, port, backlog, logfn)
local emsg

-- check whether optional addr has been omitted
if tonumber(addr) then
logfn, backlog, port, addr = backlog, port, addr, ls.INADDR_ANY
end
backlog = backlog or 10

local self = setmetatable({}, {__index = httpd_methods})
self.socket, emsg = ls.bind(addr, port, backlog)
if not self.socket then
error(emsg)
end

self.rsocks = { self.socket }
self.wsocks = {}
self.requests = {}
self.stillalive = {}
self.keepalive = 10 -- seconds
self.logfn = logfn
self.started = time()
self.nreqs = 0

-- dummy handler
self.process = {
get = function(rq, header) return "200", "<html><body><pre>"..rq.url.."</pre></body></html>" end
}

return self
end

function httpd_methods:log(...)
if self.logfn then
self.logfn(date("%Y-%m-%d %H:%M:%S ") .. table.concat({...}, " "))
end
end

function httpd_methods:status()
local methods, m, _ = {}
for m, _ in pairs(self.process) do
methods[#methods+1] = m
end
return {
methods = methods,
rqlen = #self.rsocks,
wqlen = #self.wsocks,
nreqs = self.nreqs,
up_since = os.date("%Y-%m-%d %H:%M:%S", self.started)
}
end

function httpd_methods:addhandler(rq, fn)
if type(rq) == "string" and type(fn) == "function" then
self.process[rq] = fn
elseif type(rq) ~= "string" then
error("addhandler: invalid type for arg#1 (string expected)")
elseif type(fn) ~= "function" then
error("addhandler: invalid type for arg#2 (function expected)")
end
end

function httpd_methods:step(tmout)
local server = self.socket
local _, s, t
local rr, rw = ls.select(self.rsocks, self.wsocks, tmout)

-- handle sockets from the read queue: they may be either new connections,
-- reused keep-alive connections or running requests
if rr then
for _, s in ipairs(rr) do
if s == server then
local s1, ip, port = s:accept()
begin_request(self, s1)
elseif self.stillalive[s] then
self.stillalive[s] = nil
remove_from_queue(self.rsocks, s)
begin_request(self, s)
else
continue_request(self, s)
end
end
end
-- handle sockets from write queue: these can only be running requests
if rw then
for _, s in ipairs(rw) do
continue_request(self, s)
end
end
-- clean up timed out keepalive connections
local tm = time()
for s, t in pairs(self.stillalive) do
if t <= tm then
self.stillalive[s] = nil
s:close()
end
end
return not not rr
end

httpd.urldecode = urldecode
httpd.urlencode = urlencode

return httpd

+ 0
- 35
lsocket-1.3-1/samples/testclt_mcast.lua View File

@@ -1,41 +0,0 @@
--

if arg[1] == '6' then
addr = 'ff01::1'
else
addr = '127.255.255.255'
end
port = 8000

ls = require "lsocket"

client, err = ls.bind('mcast', addr, port)
if not client then
print("error: "..err)
os.exit(1)
end

print "Socket info:"
for k, v in pairs(client:info()) do
io.write(k..": "..tostring(v)..", ")
end
sock = client:info("socket")
print("\nSocket: "..sock.family.." "..sock.addr..":"..sock.port)

repeat
ls.select {client}
str, ip, port = client:recvfrom()
if str then
print("received from "..ip..":"..port..": "..str)
else
print("error: "..ip)
end
until false

client:close()

+ 0
- 52
lsocket-1.3-1/samples/testclt_tcp.lua View File

@@ -1,59 +0,0 @@
--

if arg[1] == '6' then
addr = '::1'
else
addr = '127.0.0.1'
end
port = 8000

ls = require "lsocket"

client, err = ls.connect(addr, port)
if not client then
print("error: "..err)
os.exit(1)
end

ls.select(nil, {client})
ok, err = client:status()
if not ok then
print("error: "..err)
os.exit(1)
end

print "Socket info:"
for k, v in pairs(client:info()) do
io.write(k..": "..tostring(v)..", ")
end
sock = client:info("socket")
print("\nSocket: "..sock.family.." "..sock.addr..":"..sock.port)
peer = client:info("peer")
print("Peer: "..peer.family.." "..peer.addr..":"..peer.port)

print("Type quit to quit.")
repeat
io.write("Enter some text: ")
s = io.read()
ok, err = client:send(s)
if not ok then print("error: "..err) end
ls.select({client})
str, err = client:recv()
if str then
print("reply: "..str)
elseif err then
print("error: "..err)
else
print("server died, exiting")
s = "quit"
end
until s == "quit"

client:close()

+ 0
- 49
lsocket-1.3-1/samples/testclt_udp.lua View File

@@ -1,56 +0,0 @@
--

if arg[1] == '6' then
addr = '::1'
else
addr = '127.0.0.1'
end
port = 8000

ls = require "lsocket"

client, err = ls.connect('udp', addr, port)
if not client then
print("error: "..err)
os.exit(1)
end

ls.select(nil, {client})
ok, err = client:status()
if not ok then
print("error: "..err)
os.exit(1)
end

print "Socket info:"
for k, v in pairs(client:info()) do
io.write(k..": "..tostring(v)..", ")
end
sock = client:info("socket")
print("\nSocket: "..sock.family.." "..sock.addr..":"..sock.port)
peer = client:info("peer")
print("Peer: "..peer.family.." "..peer.addr..":"..peer.port)

print("Type quit to quit.")
repeat
io.write("Enter some text: ")
s = io.read()
ok, err = client:send(s)
if not ok then print("error: "..err) end
ls.select({client})
str, err = client:recv()
if str then
print("reply: "..str)
else
print("error: "..err)
end
until s == "quit"

client:close()

+ 0
- 47
lsocket-1.3-1/samples/testclt_unix.lua View File

@@ -1,54 +0,0 @@
--

addr = "./testsocket"

ls = require "lsocket"

client, err = ls.connect(addr)
if not client then
print("error: "..err)
os.exit(1)
end

ls.select(nil, {client})
ok, err = client:status()
if not ok then
print("error: "..err)
os.exit(1)
end

print "Socket info:"
for k, v in pairs(client:info()) do
io.write(k..": "..tostring(v)..", ")
end
sock = client:info("socket")
print("\nSocket: "..sock.family)
peer = client:info("peer")
print("Peer: "..peer.family.." "..peer.addr)

print("Type quit to quit.")
repeat
io.write("Enter some text: ")
s = io.read()
ok, err = client:send(s)
if not ok then print("error: "..err) end
ls.select({client})
str, err = client:recv()
if str then
print("reply: "..str)
elseif err then
print("error: "..err)
else
print("server died, exiting")
s = "quit"
end