mirror of
https://github.com/lunarmodules/luasocket.git
synced 2024-12-25 20:18:21 +01:00
Select re-implemented in a nicer way.
Few changes in internal class and group registration. Lua modules are compiled and built into library. Dynamic library tested in Linux and Mac OS X.
This commit is contained in:
parent
b2724ad2d1
commit
58bdb658aa
@ -1,6 +1,8 @@
|
||||
-----------------------------------------------------------------------------
|
||||
-- Little program that checks links in HTML files
|
||||
-- LuaSocket 1.5 sample files.
|
||||
-- Author: Diego Nehab
|
||||
-- RCS ID: $Id$
|
||||
-----------------------------------------------------------------------------
|
||||
socket.http.TIMEOUT = 10
|
||||
|
||||
|
@ -1,6 +1,8 @@
|
||||
-----------------------------------------------------------------------------
|
||||
-- Little program to download DICT word definitions
|
||||
-- LuaSocket 1.5 sample files
|
||||
-- Author: Diego Nehab
|
||||
-- RCS ID: $Id$
|
||||
-----------------------------------------------------------------------------
|
||||
function get_status(sock, valid)
|
||||
local line, err = sock:receive()
|
||||
|
@ -1,6 +1,8 @@
|
||||
-----------------------------------------------------------------------------
|
||||
-- Little program to download files from URLs
|
||||
-- LuaSocket 1.5 sample files
|
||||
-- Author: Diego Nehab
|
||||
-- RCS ID: $Id$
|
||||
-----------------------------------------------------------------------------
|
||||
-- formats a number of seconds into human readable form
|
||||
function nicetime(s)
|
||||
|
@ -2,22 +2,81 @@
|
||||
# Distribution makefile
|
||||
#--------------------------------------------------------------------------
|
||||
|
||||
DIST = luasocket-1.5-work
|
||||
DIST = luasocket-1.5-alpha
|
||||
|
||||
LUA = concat.lua code.lua url.lua http.lua smtp.lua ftp.lua lsselect.lua \
|
||||
cl-compat.lua
|
||||
LUA = \
|
||||
concat.lua \
|
||||
code.lua \
|
||||
url.lua \
|
||||
http.lua \
|
||||
smtp.lua \
|
||||
ftp.lua \
|
||||
select.lua \
|
||||
luasocket.lua
|
||||
|
||||
TESTS = testclnt.lua testsrvr.lua testcmd.lua codetest.lua \
|
||||
urltest.lua concattest.lua
|
||||
TESTS = \
|
||||
testclnt.lua \
|
||||
testsrvr.lua \
|
||||
testcmd.lua \
|
||||
codetest.lua \
|
||||
urltest.lua \
|
||||
concattest.lua \
|
||||
ftptest.lua \
|
||||
httptest.lua \
|
||||
smtptest.lua \
|
||||
mbox.lua \
|
||||
udptest.lua
|
||||
|
||||
EXAMPLES = check-links.lua daytimeclnt.lua dict.lua echoclnt.lua \
|
||||
echosrvr.lua get.lua listener.lua talker.lua tinyirc.lua tftpclnt.lua
|
||||
EXAMPLES = \
|
||||
check-links.lua \
|
||||
daytimeclnt.lua \
|
||||
echoclnt.lua \
|
||||
echosrvr.lua \
|
||||
get.lua \
|
||||
listener.lua \
|
||||
talker.lua \
|
||||
tinyirc.lua
|
||||
|
||||
ETC = \
|
||||
cl-compat.lua \
|
||||
tftp.lua \
|
||||
dict.lua
|
||||
|
||||
MAIN = \
|
||||
auxiliar.c \
|
||||
auxiliar.h \
|
||||
buffer.c \
|
||||
buffer.h \
|
||||
error.c \
|
||||
error.h \
|
||||
inet.c \
|
||||
inet.h \
|
||||
io.c \
|
||||
io.h \
|
||||
lua.c \
|
||||
luasocket.c \
|
||||
luasocket.h \
|
||||
makefile \
|
||||
select.c \
|
||||
select.h \
|
||||
socket.h \
|
||||
tcp.c \
|
||||
tcp.h \
|
||||
timeout.c \
|
||||
timeout.h \
|
||||
udp.c \
|
||||
udp.h \
|
||||
usocket.c \
|
||||
usocket.h \
|
||||
wsocket.c \
|
||||
wsocket.h \
|
||||
|
||||
dist:
|
||||
mkdir -p $(DIST)/examples
|
||||
mkdir -p $(DIST)/tests
|
||||
cp -vf *.c $(DIST)
|
||||
cp -vf *.h $(DIST)
|
||||
mkdir -p $(DIST)/etc
|
||||
mkdir -p $(DIST)/lua
|
||||
cp -vf $(MAIN) $(DIST)
|
||||
cp -vf $(LUA) $(DIST)
|
||||
cp -vf makefile $(DIST)
|
||||
cp -vf README $(DIST)
|
||||
@ -25,6 +84,8 @@ dist:
|
||||
cp -vf README.examples $(DIST)/examples/README
|
||||
cp -vf $(TESTS) $(DIST)/tests
|
||||
cp -vf README.tests $(DIST)/tests/README
|
||||
cp -vf $(ETC) $(DIST)/etc
|
||||
cp -vf README.etc $(DIST)/etc/README
|
||||
tar -zcvf $(DIST).tar.gz $(DIST)
|
||||
zip -r $(DIST).zip $(DIST)
|
||||
|
||||
|
@ -1,3 +1,9 @@
|
||||
-----------------------------------------------------------------------------
|
||||
-- UDP sample: daytime protocol client
|
||||
-- LuaSocket 1.5 sample files.
|
||||
-- Author: Diego Nehab
|
||||
-- RCS ID: $Id$
|
||||
-----------------------------------------------------------------------------
|
||||
host = host or "127.0.0.1"
|
||||
port = port or 13
|
||||
if arg then
|
||||
|
@ -1,3 +1,9 @@
|
||||
-----------------------------------------------------------------------------
|
||||
-- UDP sample: echo protocol client
|
||||
-- LuaSocket 1.5 sample files
|
||||
-- Author: Diego Nehab
|
||||
-- RCS ID: $Id$
|
||||
-----------------------------------------------------------------------------
|
||||
host = host or "localhost"
|
||||
port = port or 7
|
||||
if arg then
|
||||
|
@ -1,3 +1,9 @@
|
||||
-----------------------------------------------------------------------------
|
||||
-- UDP sample: echo protocol server
|
||||
-- LuaSocket 1.5 sample files
|
||||
-- Author: Diego Nehab
|
||||
-- RCS ID: $Id$
|
||||
-----------------------------------------------------------------------------
|
||||
host = host or "127.0.0.1"
|
||||
port = port or 7
|
||||
if arg then
|
||||
|
@ -1,6 +1,8 @@
|
||||
-----------------------------------------------------------------------------
|
||||
-- Little program to dump lines received at a given port
|
||||
-- TCP sample: Little program to dump lines received at a given port
|
||||
-- LuaSocket 1.5 sample files
|
||||
-- Author: Diego Nehab
|
||||
-- RCS ID: $Id$
|
||||
-----------------------------------------------------------------------------
|
||||
host = host or "*"
|
||||
port = port or 8080
|
||||
|
@ -1,3 +1,9 @@
|
||||
-----------------------------------------------------------------------------
|
||||
-- TCP sample: Little program to send text lines to a given host/port
|
||||
-- LuaSocket 1.5 sample files
|
||||
-- Author: Diego Nehab
|
||||
-- RCS ID: $Id$
|
||||
-----------------------------------------------------------------------------
|
||||
host = host or "localhost"
|
||||
port = port or 8080
|
||||
if arg then
|
||||
|
@ -1,16 +1,9 @@
|
||||
function set_add(set, sock)
|
||||
table.insert(set, sock)
|
||||
end
|
||||
|
||||
function set_remove(set, sock)
|
||||
for i = 1, table.getn(set) do
|
||||
if set[i] == sock then
|
||||
table.remove(set, i)
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- Select sample: simple text line server
|
||||
-- LuaSocket 1.5 sample files.
|
||||
-- Author: Diego Nehab
|
||||
-- RCS ID: $Id$
|
||||
-----------------------------------------------------------------------------
|
||||
host = host or "*"
|
||||
port1 = port1 or 8080
|
||||
port2 = port2 or 8081
|
||||
@ -21,49 +14,62 @@ if arg then
|
||||
end
|
||||
|
||||
server1, error = socket.bind(host, port1)
|
||||
if not server1 then print(error) exit() end
|
||||
assert(server1, error)
|
||||
server1:timeout(1)
|
||||
server2, error = socket.bind(host, port2)
|
||||
if not server2 then print(error) exit() end
|
||||
assert(server2, error)
|
||||
server2:timeout(1)
|
||||
|
||||
sock_set = {server1, server2}
|
||||
function newset()
|
||||
local reverse = {}
|
||||
local set = {}
|
||||
setmetatable(set, { __index = {
|
||||
insert = function(set, value)
|
||||
table.insert(set, value)
|
||||
reverse[value] = table.getn(set)
|
||||
end,
|
||||
remove = function(set, value)
|
||||
table.remove(set, reverse[value])
|
||||
reverse[value] = nil
|
||||
end,
|
||||
id = function(set, value)
|
||||
return reverse[value]
|
||||
end
|
||||
}})
|
||||
return set
|
||||
end
|
||||
|
||||
sock_id = {}
|
||||
sock_id[server1] = 1
|
||||
sock_id[server2] = 2
|
||||
next_id = 3
|
||||
sockets = newset()
|
||||
|
||||
sockets:insert(server1)
|
||||
sockets:insert(server2)
|
||||
|
||||
while 1 do
|
||||
local readable, _, error = socket.select(sock_set, nil)
|
||||
for _, sock in readable do
|
||||
-- is it a server socket
|
||||
if sock_id[sock] < 3 then
|
||||
local incomming = sock:accept()
|
||||
if incomming then
|
||||
incomming:timeout(1)
|
||||
sock_id[incomming] = next_id
|
||||
set_add(sock_set, incomming)
|
||||
io.write("Added client id ", next_id, ". ",
|
||||
table.getn(sock_set)-2, " total.\n")
|
||||
next_id = next_id + 1
|
||||
local readable, _, error = socket.select(sockets, nil)
|
||||
for _, input in readable do
|
||||
-- is it a server socket?
|
||||
local id = sockets:id(input)
|
||||
if input == server1 or input == server2 then
|
||||
local new = input:accept()
|
||||
if new then
|
||||
new:timeout(1)
|
||||
sockets:insert(new)
|
||||
io.write("Server ", id, " got client ", sockets:id(new), "\n")
|
||||
end
|
||||
-- it is a client socket
|
||||
else
|
||||
local line, error = sock:receive()
|
||||
local id = sock_id[sock]
|
||||
local line, error = input:receive()
|
||||
if error then
|
||||
sock:close()
|
||||
set_remove(sock_set, sock)
|
||||
io.write("Removed client number ", id, ". ",
|
||||
getn(sock_set)-2, " total.\n")
|
||||
input:close()
|
||||
io.write("Removing client ", id, "\n")
|
||||
sockets:remove(input)
|
||||
else
|
||||
io.write("Broadcasting line '", id, "> ", line, "'.\n")
|
||||
__, writable, error = socket.select(nil, sock_set, 1)
|
||||
__, writable, error = socket.select(nil, sockets, 1)
|
||||
if not error then
|
||||
for ___, outgoing in writable do
|
||||
io.write("Sending to client ", sock_id[outgoing], "\n")
|
||||
outgoing:send(id, "> ", line, "\r\n")
|
||||
for ___, output in writable do
|
||||
io.write("Sending to client ", sockets:id(output), "\n")
|
||||
output:send(id, "> ", line, "\r\n")
|
||||
end
|
||||
else io.write("No one ready to listen!!!\n") end
|
||||
end
|
||||
|
@ -3,12 +3,7 @@
|
||||
*
|
||||
* RCS ID: $Id$
|
||||
\*=========================================================================*/
|
||||
#include "aux.h"
|
||||
|
||||
/*=========================================================================*\
|
||||
* Internal function prototypes
|
||||
\*=========================================================================*/
|
||||
static void *aux_getgroupudata(lua_State *L, const char *group, int objidx);
|
||||
#include "auxiliar.h"
|
||||
|
||||
/*=========================================================================*\
|
||||
* Exported functions
|
||||
@ -20,18 +15,19 @@ static void *aux_getgroupudata(lua_State *L, const char *group, int objidx);
|
||||
\*-------------------------------------------------------------------------*/
|
||||
void aux_newclass(lua_State *L, const char *name, luaL_reg *func)
|
||||
{
|
||||
luaL_newmetatable(L, name);
|
||||
lua_pushstring(L, name);
|
||||
lua_newtable(L);
|
||||
lua_pushstring(L, "__index");
|
||||
lua_newtable(L);
|
||||
luaL_openlib(L, NULL, func, 0);
|
||||
lua_pushstring(L, "class");
|
||||
lua_pushstring(L, name);
|
||||
lua_settable(L, -3);
|
||||
lua_settable(L, -3);
|
||||
lua_rawset(L, -3);
|
||||
lua_pushstring(L, "group");
|
||||
lua_newtable(L);
|
||||
lua_settable(L, -3);
|
||||
lua_pop(L, 1);
|
||||
lua_rawset(L, -3);
|
||||
lua_rawset(L, -3);
|
||||
lua_rawset(L, LUA_REGISTRYINDEX);
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*\
|
||||
@ -39,13 +35,16 @@ void aux_newclass(lua_State *L, const char *name, luaL_reg *func)
|
||||
\*-------------------------------------------------------------------------*/
|
||||
void aux_add2group(lua_State *L, const char *name, const char *group)
|
||||
{
|
||||
luaL_getmetatable(L, name);
|
||||
lua_pushstring(L, name);
|
||||
lua_rawget(L, LUA_REGISTRYINDEX);
|
||||
lua_pushstring(L, "__index");
|
||||
lua_rawget(L, -2);
|
||||
lua_pushstring(L, "group");
|
||||
lua_gettable(L, -2);
|
||||
lua_rawget(L, -2);
|
||||
lua_pushstring(L, group);
|
||||
lua_pushnumber(L, 1);
|
||||
lua_settable(L, -3);
|
||||
lua_pop(L, 2);
|
||||
lua_rawset(L, -3);
|
||||
lua_pop(L, 3);
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*\
|
||||
@ -53,7 +52,7 @@ void aux_add2group(lua_State *L, const char *name, const char *group)
|
||||
\*-------------------------------------------------------------------------*/
|
||||
void *aux_checkclass(lua_State *L, const char *name, int objidx)
|
||||
{
|
||||
void *data = luaL_checkudata(L, objidx, name);
|
||||
void *data = aux_getclassudata(L, name, objidx);
|
||||
if (!data) {
|
||||
char msg[45];
|
||||
sprintf(msg, "%.35s expected", name);
|
||||
@ -81,7 +80,8 @@ void *aux_checkgroup(lua_State *L, const char *group, int objidx)
|
||||
\*-------------------------------------------------------------------------*/
|
||||
void aux_setclass(lua_State *L, const char *name, int objidx)
|
||||
{
|
||||
luaL_getmetatable(L, name);
|
||||
lua_pushstring(L, name);
|
||||
lua_rawget(L, LUA_REGISTRYINDEX);
|
||||
if (objidx < 0) objidx--;
|
||||
lua_setmetatable(L, objidx);
|
||||
}
|
||||
@ -92,17 +92,47 @@ void aux_setclass(lua_State *L, const char *name, int objidx)
|
||||
/*-------------------------------------------------------------------------*\
|
||||
* Get a userdata if object belongs to a given group.
|
||||
\*-------------------------------------------------------------------------*/
|
||||
static void *aux_getgroupudata(lua_State *L, const char *group, int objidx)
|
||||
void *aux_getgroupudata(lua_State *L, const char *group, int objidx)
|
||||
{
|
||||
if (!lua_getmetatable(L, objidx)) return NULL;
|
||||
lua_pushstring(L, "group");
|
||||
lua_gettable(L, -2);
|
||||
if (lua_isnil(L, -1)) {
|
||||
if (!lua_getmetatable(L, objidx))
|
||||
return NULL;
|
||||
lua_pushstring(L, "__index");
|
||||
lua_rawget(L, -2);
|
||||
if (!lua_istable(L, -1)) {
|
||||
lua_pop(L, 2);
|
||||
return NULL;
|
||||
}
|
||||
lua_pushstring(L, "group");
|
||||
lua_rawget(L, -2);
|
||||
if (!lua_istable(L, -1)) {
|
||||
lua_pop(L, 3);
|
||||
return NULL;
|
||||
}
|
||||
lua_pushstring(L, group);
|
||||
lua_gettable(L, -2);
|
||||
lua_rawget(L, -2);
|
||||
if (lua_isnil(L, -1)) {
|
||||
lua_pop(L, 4);
|
||||
return NULL;
|
||||
}
|
||||
lua_pop(L, 4);
|
||||
return lua_touserdata(L, objidx);
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*\
|
||||
* Get a userdata if object belongs to a given class.
|
||||
\*-------------------------------------------------------------------------*/
|
||||
void *aux_getclassudata(lua_State *L, const char *group, int objidx)
|
||||
{
|
||||
if (!lua_getmetatable(L, objidx))
|
||||
return NULL;
|
||||
lua_pushstring(L, "__index");
|
||||
lua_rawget(L, -2);
|
||||
if (!lua_istable(L, -1)) {
|
||||
lua_pop(L, 2);
|
||||
return NULL;
|
||||
}
|
||||
lua_pushstring(L, "class");
|
||||
lua_rawget(L, -2);
|
||||
if (lua_isnil(L, -1)) {
|
||||
lua_pop(L, 3);
|
||||
return NULL;
|
||||
@ -110,4 +140,3 @@ static void *aux_getgroupudata(lua_State *L, const char *group, int objidx)
|
||||
lua_pop(L, 3);
|
||||
return lua_touserdata(L, objidx);
|
||||
}
|
||||
|
||||
|
@ -13,6 +13,8 @@ void aux_newclass(lua_State *L, const char *name, luaL_reg *func);
|
||||
void aux_add2group(lua_State *L, const char *name, const char *group);
|
||||
void *aux_checkclass(lua_State *L, const char *name, int objidx);
|
||||
void *aux_checkgroup(lua_State *L, const char *group, int objidx);
|
||||
void *aux_getclassudata(lua_State *L, const char *group, int objidx);
|
||||
void *aux_getgroupudata(lua_State *L, const char *group, int objidx);
|
||||
void aux_setclass(lua_State *L, const char *name, int objidx);
|
||||
|
||||
/* min and max macros */
|
||||
|
@ -7,8 +7,8 @@
|
||||
#include <lauxlib.h>
|
||||
|
||||
#include "error.h"
|
||||
#include "aux.h"
|
||||
#include "buf.h"
|
||||
#include "auxiliar.h"
|
||||
#include "buffer.h"
|
||||
|
||||
/*=========================================================================*\
|
||||
* Internal function prototypes
|
||||
|
@ -8,7 +8,7 @@
|
||||
|
||||
#include <lua.h>
|
||||
#include "io.h"
|
||||
#include "tm.h"
|
||||
#include "timeout.h"
|
||||
|
||||
/* buffer size in bytes */
|
||||
#define BUF_SIZE 8192
|
||||
|
@ -38,6 +38,7 @@ static luaL_reg func[] = {
|
||||
void inet_open(lua_State *L)
|
||||
{
|
||||
luaL_openlib(L, LUASOCKET_LIBNAME, func, 0);
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
/*=========================================================================*\
|
||||
@ -114,7 +115,7 @@ static int inet_global_tohostname(lua_State *L)
|
||||
int inet_meth_getpeername(lua_State *L, p_sock ps)
|
||||
{
|
||||
struct sockaddr_in peer;
|
||||
size_t peer_len = sizeof(peer);
|
||||
socklen_t peer_len = sizeof(peer);
|
||||
if (getpeername(*ps, (SA *) &peer, &peer_len) < 0) {
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
@ -135,7 +136,7 @@ int inet_meth_getpeername(lua_State *L, p_sock ps)
|
||||
int inet_meth_getsockname(lua_State *L, p_sock ps)
|
||||
{
|
||||
struct sockaddr_in local;
|
||||
size_t local_len = sizeof(local);
|
||||
socklen_t local_len = sizeof(local);
|
||||
if (getsockname(*ps, (SA *) &local, &local_len) < 0) {
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
|
@ -7,7 +7,7 @@
|
||||
#define INET_H
|
||||
|
||||
#include <lua.h>
|
||||
#include "sock.h"
|
||||
#include "socket.h"
|
||||
|
||||
/*-------------------------------------------------------------------------*\
|
||||
* Exported functions
|
||||
|
12
src/io.h
12
src/io.h
@ -1,7 +1,17 @@
|
||||
#ifndef IO_H
|
||||
#define IO_H
|
||||
|
||||
#include "error.h"
|
||||
#include <stdio.h>
|
||||
|
||||
/* IO error codes */
|
||||
enum {
|
||||
IO_DONE, /* operation completed successfully */
|
||||
IO_TIMEOUT, /* operation timed out */
|
||||
IO_CLOSED, /* the connection has been closed */
|
||||
IO_ERROR, /* something wrong... */
|
||||
IO_REFUSED, /* transfer has been refused */
|
||||
IO_LIMITED /* maximum number of bytes reached */
|
||||
};
|
||||
|
||||
/* interface to send function */
|
||||
typedef int (*p_send) (
|
||||
|
@ -24,12 +24,13 @@
|
||||
\*=========================================================================*/
|
||||
#include "luasocket.h"
|
||||
|
||||
#include "tm.h"
|
||||
#include "buf.h"
|
||||
#include "sock.h"
|
||||
#include "timeout.h"
|
||||
#include "buffer.h"
|
||||
#include "socket.h"
|
||||
#include "inet.h"
|
||||
#include "tcp.h"
|
||||
#include "udp.h"
|
||||
#include "select.h"
|
||||
|
||||
/*=========================================================================*\
|
||||
* Exported functions
|
||||
@ -39,6 +40,7 @@
|
||||
\*-------------------------------------------------------------------------*/
|
||||
LUASOCKET_API int luaopen_socketlib(lua_State *L)
|
||||
{
|
||||
if (!sock_open()) return 0;
|
||||
/* create namespace table */
|
||||
lua_pushstring(L, LUASOCKET_LIBNAME);
|
||||
lua_newtable(L);
|
||||
@ -53,13 +55,28 @@ LUASOCKET_API int luaopen_socketlib(lua_State *L)
|
||||
lua_pushstring(L, LUASOCKET_LIBNAME);
|
||||
lua_settable(L, LUA_GLOBALSINDEX);
|
||||
/* initialize all modules */
|
||||
sock_open(L);
|
||||
tm_open(L);
|
||||
buf_open(L);
|
||||
inet_open(L);
|
||||
tcp_open(L);
|
||||
udp_open(L);
|
||||
/* load all Lua code */
|
||||
lua_dofile(L, "luasocket.lua");
|
||||
return 0;
|
||||
select_open(L);
|
||||
#ifdef LUASOCKET_COMPILED
|
||||
#include "auxiliar.lch"
|
||||
#include "concat.lch"
|
||||
#include "code.lch"
|
||||
#include "url.lch"
|
||||
#include "smtp.lch"
|
||||
#include "ftp.lch"
|
||||
#include "http.lch"
|
||||
#else
|
||||
lua_dofile(L, "auxiliar.lua");
|
||||
lua_dofile(L, "concat.lua");
|
||||
lua_dofile(L, "code.lua");
|
||||
lua_dofile(L, "url.lua");
|
||||
lua_dofile(L, "smtp.lua");
|
||||
lua_dofile(L, "ftp.lua");
|
||||
lua_dofile(L, "http.lua");
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
191
src/select.c
191
src/select.c
@ -1,154 +1,129 @@
|
||||
/*=========================================================================*\
|
||||
* Select implementation
|
||||
* Global Lua fuctions:
|
||||
* select: waits until socket ready
|
||||
* RCS ID: $Id$
|
||||
\*=========================================================================*/
|
||||
#include <string.h>
|
||||
|
||||
#include <lua.h>
|
||||
#include <lauxlib.h>
|
||||
|
||||
#include "luasocket.h"
|
||||
#include "lspriv.h"
|
||||
#include "lsselect.h"
|
||||
#include "lsfd.h"
|
||||
#include "socket.h"
|
||||
#include "auxiliar.h"
|
||||
#include "select.h"
|
||||
|
||||
/* auxiliar functions */
|
||||
static int local_select(lua_State *L);
|
||||
static int local_getfd(lua_State *L);
|
||||
static int local_pending(lua_State *L);
|
||||
static int local_FD_SET(lua_State *L);
|
||||
static int local_FD_ISSET(lua_State *L);
|
||||
static int meth_set(lua_State *L);
|
||||
static int meth_isset(lua_State *L);
|
||||
static int c_select(lua_State *L);
|
||||
static int global_select(lua_State *L);
|
||||
static void check_obj_tab(lua_State *L, int tabidx);
|
||||
|
||||
static int select_lua_select(lua_State *L);
|
||||
/* fd_set object methods */
|
||||
static luaL_reg set[] = {
|
||||
{"set", meth_set},
|
||||
{"isset", meth_isset},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
/*-------------------------------------------------------------------------*\
|
||||
* Marks type as selectable
|
||||
* Input
|
||||
* name: type name
|
||||
\*-------------------------------------------------------------------------*/
|
||||
void select_addclass(lua_State *L, cchar *lsclass)
|
||||
{
|
||||
lua_pushstring(L, "luasocket(select)");
|
||||
lua_gettable(L, LUA_REGISTRYINDEX);
|
||||
lua_pushstring(L, lsclass);
|
||||
lua_pushnumber(L, 1);
|
||||
lua_settable(L, -3);
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
/* functions in library namespace */
|
||||
static luaL_reg func[] = {
|
||||
{"select", global_select},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
void select_open(lua_State *L)
|
||||
{
|
||||
/* push select auxiliar lua function and register
|
||||
* select_lua_select with it as an upvalue */
|
||||
#ifdef LUASOCKET_DOFILE
|
||||
lua_dofile(L, "lsselect.lua");
|
||||
/* get select auxiliar lua function from lua code and register
|
||||
* pass it as an upvalue to global_select */
|
||||
#ifdef LUASOCKET_COMPILED
|
||||
#include "select.lch"
|
||||
#else
|
||||
#include "lsselect.loh"
|
||||
lua_dofile(L, "select.lua");
|
||||
#endif
|
||||
lua_getglobal(L, LUASOCKET_LIBNAME);
|
||||
lua_pushstring(L, "_select");
|
||||
lua_gettable(L, -2);
|
||||
lua_pushcclosure(L, select_lua_select, 1);
|
||||
priv_newglobal(L, "select");
|
||||
luaL_openlib(L, LUASOCKET_LIBNAME, func, 1);
|
||||
lua_pop(L, 1);
|
||||
/* create luasocket(select) table */
|
||||
lua_pushstring(L, "luasocket(select)");
|
||||
lua_newtable(L);
|
||||
lua_settable(L, LUA_REGISTRYINDEX);
|
||||
aux_newclass(L, "select{fd_set}", set);
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*\
|
||||
* Waits for a set of sockets until a condition is met or timeout.
|
||||
* Lua Input: {input}, {output} [, timeout]
|
||||
* {input}: table of sockets to be tested for input
|
||||
* {output}: table of sockets to be tested for output
|
||||
* timeout: maximum amount of time to wait for condition, in seconds
|
||||
* Lua Returns: {input}, {output}, err
|
||||
* {input}: table with sockets ready for input
|
||||
* {output}: table with sockets ready for output
|
||||
* err: "timeout" or nil
|
||||
\*-------------------------------------------------------------------------*/
|
||||
static int select_lua_select(lua_State *L)
|
||||
static int global_select(lua_State *L)
|
||||
{
|
||||
fd_set read, write;
|
||||
FD_ZERO(&read);
|
||||
FD_ZERO(&write);
|
||||
/* push select lua auxiliar function */
|
||||
lua_pushvalue(L, lua_upvalueindex(1)); lua_insert(L, 1);
|
||||
fd_set *read_fd_set, *write_fd_set;
|
||||
/* make sure we have enough arguments (nil is the default) */
|
||||
lua_settop(L, 4);
|
||||
/* pass FD_SET and manipulation functions */
|
||||
lua_boxpointer(L, &read);
|
||||
lua_boxpointer(L, &write);
|
||||
lua_pushcfunction(L, local_FD_SET);
|
||||
lua_pushcfunction(L, local_FD_ISSET);
|
||||
/* pass getfd function with selectable table as upvalue */
|
||||
lua_pushstring(L, "luasocket(select)"); lua_gettable(L, LUA_REGISTRYINDEX);
|
||||
lua_pushcclosure(L, local_getfd, 1);
|
||||
/* pass pending function */
|
||||
lua_pushstring(L, "luasocket(select)"); lua_gettable(L, LUA_REGISTRYINDEX);
|
||||
lua_pushcclosure(L, local_pending, 1);
|
||||
lua_settop(L, 3);
|
||||
/* check object tables */
|
||||
check_obj_tab(L, 1);
|
||||
check_obj_tab(L, 2);
|
||||
/* check timeout */
|
||||
if (!lua_isnil(L, 3) && !lua_isnumber(L, 3))
|
||||
luaL_argerror(L, 3, "number or nil expected");
|
||||
/* select auxiliar lua function to be called comes first */
|
||||
lua_pushvalue(L, lua_upvalueindex(1));
|
||||
lua_insert(L, 1);
|
||||
/* pass fd_set objects */
|
||||
read_fd_set = lua_newuserdata(L, sizeof(fd_set));
|
||||
FD_ZERO(read_fd_set);
|
||||
aux_setclass(L, "select{fd_set}", -1);
|
||||
write_fd_set = lua_newuserdata(L, sizeof(fd_set));
|
||||
FD_ZERO(write_fd_set);
|
||||
aux_setclass(L, "select{fd_set}", -1);
|
||||
/* pass select auxiliar C function */
|
||||
lua_pushcfunction(L, local_select);
|
||||
lua_pushcfunction(L, c_select);
|
||||
/* call select auxiliar lua function */
|
||||
lua_call(L, 10, 3);
|
||||
lua_call(L, 6, 3);
|
||||
return 3;
|
||||
}
|
||||
|
||||
static int local_getfd(lua_State *L)
|
||||
{
|
||||
priv_pushclass(L, 1);
|
||||
lua_gettable(L, lua_upvalueindex(1));
|
||||
if (!lua_isnil(L, -1)) {
|
||||
p_fd sock = (p_fd) lua_touserdata(L, 1);
|
||||
lua_pushnumber(L, sock->fd);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int local_pending(lua_State *L)
|
||||
{
|
||||
priv_pushclass(L, 1);
|
||||
lua_gettable(L, lua_upvalueindex(1));
|
||||
if (!lua_isnil(L, -1)) {
|
||||
p_fd sock = (p_fd) lua_touserdata(L, 1);
|
||||
if (sock->fd_pending(L, sock)) lua_pushnumber(L, 1);
|
||||
else lua_pushnil(L);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int local_select(lua_State *L)
|
||||
static int c_select(lua_State *L)
|
||||
{
|
||||
int max_fd = (int) lua_tonumber(L, 1);
|
||||
fd_set *read_set = (fd_set *) lua_touserdata(L, 2);
|
||||
fd_set *write_set = (fd_set *) lua_touserdata(L, 3);
|
||||
int deadline = lua_isnil(L, 4) ? -1 : (int)(lua_tonumber(L, 4) * 1000);
|
||||
fd_set *read_fd_set = (fd_set *) aux_checkclass(L, "select{fd_set}", 2);
|
||||
fd_set *write_fd_set = (fd_set *) aux_checkclass(L, "select{fd_set}", 3);
|
||||
int timeout = lua_isnil(L, 4) ? -1 : (int)(lua_tonumber(L, 4) * 1000);
|
||||
struct timeval tv;
|
||||
if (deadline >= 0) {
|
||||
tv.tv_sec = deadline / 1000;
|
||||
tv.tv_usec = (deadline % 1000) * 1000;
|
||||
lua_pushnumber(L, select(max_fd, read_set, write_set, NULL, &tv));
|
||||
} else {
|
||||
lua_pushnumber(L, select(max_fd, read_set, write_set, NULL, NULL));
|
||||
}
|
||||
tv.tv_sec = timeout / 1000;
|
||||
tv.tv_usec = (timeout % 1000) * 1000;
|
||||
lua_pushnumber(L, select(max_fd, read_fd_set, write_fd_set, NULL,
|
||||
timeout < 0 ? NULL : &tv));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int local_FD_SET(lua_State *L)
|
||||
static int meth_set(lua_State *L)
|
||||
{
|
||||
COMPAT_FD fd = (COMPAT_FD) lua_tonumber(L, 1);
|
||||
fd_set *set = (fd_set *) lua_topointer(L, 2);
|
||||
fd_set *set = (fd_set *) aux_checkclass(L, "select{fd_set}", 1);
|
||||
t_sock fd = (t_sock) lua_tonumber(L, 2);
|
||||
if (fd >= 0) FD_SET(fd, set);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int local_FD_ISSET(lua_State *L)
|
||||
static int meth_isset(lua_State *L)
|
||||
{
|
||||
COMPAT_FD fd = (COMPAT_FD) lua_tonumber(L, 1);
|
||||
fd_set *set = (fd_set *) lua_topointer(L, 2);
|
||||
fd_set *set = (fd_set *) aux_checkclass(L, "select{fd_set}", 1);
|
||||
t_sock fd = (t_sock) lua_tonumber(L, 2);
|
||||
if (fd >= 0 && FD_ISSET(fd, set)) lua_pushnumber(L, 1);
|
||||
else lua_pushnil(L);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void check_obj_tab(lua_State *L, int tabidx)
|
||||
{
|
||||
if (tabidx < 0) tabidx = lua_gettop(L) + tabidx + 1;
|
||||
if (lua_istable(L, tabidx)) {
|
||||
lua_pushnil(L);
|
||||
while (lua_next(L, tabidx) != 0) {
|
||||
if (aux_getgroupudata(L, "select{able}", -1) == NULL) {
|
||||
char msg[45];
|
||||
if (lua_isnumber(L, -2))
|
||||
sprintf(msg, "table entry #%g is invalid",
|
||||
lua_tonumber(L, -2));
|
||||
else
|
||||
sprintf(msg, "invalid entry found in table");
|
||||
luaL_argerror(L, tabidx, msg);
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
} else if (!lua_isnil(L, tabidx))
|
||||
luaL_argerror(L, tabidx, "table or nil expected");
|
||||
}
|
||||
|
@ -2,10 +2,9 @@
|
||||
* Select implementation
|
||||
* RCS ID: $Id$
|
||||
\*=========================================================================*/
|
||||
#ifndef SLCT_H_
|
||||
#define SLCT_H_
|
||||
#ifndef SELECT_H
|
||||
#define SELECT_H
|
||||
|
||||
void select_addclass(lua_State *L, cchar *lsclass);
|
||||
void select_open(lua_State *L);
|
||||
|
||||
#endif
|
||||
#endif /* SELECT_H */
|
||||
|
23
src/socket.h
23
src/socket.h
@ -6,16 +6,15 @@
|
||||
#ifndef SOCK_H
|
||||
#define SOCK_H
|
||||
|
||||
#include <lua.h>
|
||||
#include "error.h"
|
||||
#include "io.h"
|
||||
|
||||
/*=========================================================================*\
|
||||
* Platform specific compatibilization
|
||||
\*=========================================================================*/
|
||||
#ifdef WIN32
|
||||
#include "sockwin32.h"
|
||||
#include "wsocket.h"
|
||||
#else
|
||||
#include "sockunix.h"
|
||||
#include "usocket.h"
|
||||
#endif
|
||||
|
||||
/* we are lazy... */
|
||||
@ -25,13 +24,13 @@ typedef struct sockaddr SA;
|
||||
* Functions bellow implement a comfortable platform independent
|
||||
* interface to sockets
|
||||
\*=========================================================================*/
|
||||
int sock_open(lua_State *L);
|
||||
|
||||
int sock_open(void);
|
||||
const char *sock_create(p_sock ps, int domain, int type, int protocol);
|
||||
void sock_destroy(p_sock ps);
|
||||
void sock_accept(p_sock ps, p_sock pa, SA *addr, size_t *addr_len, int timeout);
|
||||
const char *sock_connect(p_sock ps, SA *addr, size_t addr_len);
|
||||
const char *sock_bind(p_sock ps, SA *addr, size_t addr_len);
|
||||
int sock_accept(p_sock ps, p_sock pa, SA *addr, socklen_t *addr_len,
|
||||
int timeout);
|
||||
const char *sock_connect(p_sock ps, SA *addr, socklen_t addr_len);
|
||||
const char *sock_bind(p_sock ps, SA *addr, socklen_t addr_len);
|
||||
void sock_listen(p_sock ps, int backlog);
|
||||
|
||||
int sock_send(p_sock ps, const char *data, size_t count,
|
||||
@ -39,9 +38,9 @@ int sock_send(p_sock ps, const char *data, size_t count,
|
||||
int sock_recv(p_sock ps, char *data, size_t count,
|
||||
size_t *got, int timeout);
|
||||
int sock_sendto(p_sock ps, const char *data, size_t count,
|
||||
size_t *sent, SA *addr, size_t addr_len, int timeout);
|
||||
size_t *sent, SA *addr, socklen_t addr_len, int timeout);
|
||||
int sock_recvfrom(p_sock ps, char *data, size_t count,
|
||||
size_t *got, SA *addr, size_t *addr_len, int timeout);
|
||||
size_t *got, SA *addr, socklen_t *addr_len, int timeout);
|
||||
|
||||
void sock_setnonblocking(p_sock ps);
|
||||
void sock_setblocking(p_sock ps);
|
||||
@ -52,6 +51,4 @@ const char *sock_createstrerror(void);
|
||||
const char *sock_bindstrerror(void);
|
||||
const char *sock_connectstrerror(void);
|
||||
|
||||
const char *sock_trysetoptions(lua_State *L, p_sock ps);
|
||||
|
||||
#endif /* SOCK_H */
|
||||
|
97
src/tcp.c
97
src/tcp.c
@ -10,43 +10,49 @@
|
||||
|
||||
#include "luasocket.h"
|
||||
|
||||
#include "aux.h"
|
||||
#include "auxiliar.h"
|
||||
#include "socket.h"
|
||||
#include "inet.h"
|
||||
#include "error.h"
|
||||
#include "tcp.h"
|
||||
|
||||
/*=========================================================================*\
|
||||
* Internal function prototypes
|
||||
\*=========================================================================*/
|
||||
static int tcp_global_create(lua_State *L);
|
||||
static int tcp_meth_connect(lua_State *L);
|
||||
static int tcp_meth_bind(lua_State *L);
|
||||
static int tcp_meth_send(lua_State *L);
|
||||
static int tcp_meth_getsockname(lua_State *L);
|
||||
static int tcp_meth_getpeername(lua_State *L);
|
||||
static int tcp_meth_receive(lua_State *L);
|
||||
static int tcp_meth_accept(lua_State *L);
|
||||
static int tcp_meth_close(lua_State *L);
|
||||
static int tcp_meth_timeout(lua_State *L);
|
||||
static int global_create(lua_State *L);
|
||||
static int meth_connect(lua_State *L);
|
||||
static int meth_bind(lua_State *L);
|
||||
static int meth_send(lua_State *L);
|
||||
static int meth_getsockname(lua_State *L);
|
||||
static int meth_getpeername(lua_State *L);
|
||||
static int meth_receive(lua_State *L);
|
||||
static int meth_accept(lua_State *L);
|
||||
static int meth_close(lua_State *L);
|
||||
static int meth_timeout(lua_State *L);
|
||||
static int meth_fd(lua_State *L);
|
||||
static int meth_dirty(lua_State *L);
|
||||
|
||||
/* tcp object methods */
|
||||
static luaL_reg tcp[] = {
|
||||
{"connect", tcp_meth_connect},
|
||||
{"send", tcp_meth_send},
|
||||
{"receive", tcp_meth_receive},
|
||||
{"bind", tcp_meth_bind},
|
||||
{"accept", tcp_meth_accept},
|
||||
{"setpeername", tcp_meth_connect},
|
||||
{"setsockname", tcp_meth_bind},
|
||||
{"getpeername", tcp_meth_getpeername},
|
||||
{"getsockname", tcp_meth_getsockname},
|
||||
{"timeout", tcp_meth_timeout},
|
||||
{"close", tcp_meth_close},
|
||||
{"connect", meth_connect},
|
||||
{"send", meth_send},
|
||||
{"receive", meth_receive},
|
||||
{"bind", meth_bind},
|
||||
{"accept", meth_accept},
|
||||
{"setpeername", meth_connect},
|
||||
{"setsockname", meth_bind},
|
||||
{"getpeername", meth_getpeername},
|
||||
{"getsockname", meth_getsockname},
|
||||
{"timeout", meth_timeout},
|
||||
{"close", meth_close},
|
||||
{"fd", meth_fd},
|
||||
{"dirty", meth_dirty},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
/* functions in library namespace */
|
||||
static luaL_reg func[] = {
|
||||
{"tcp", tcp_global_create},
|
||||
{"tcp", global_create},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
@ -60,11 +66,13 @@ void tcp_open(lua_State *L)
|
||||
aux_newclass(L, "tcp{client}", tcp);
|
||||
aux_newclass(L, "tcp{server}", tcp);
|
||||
/* create class groups */
|
||||
aux_add2group(L, "tcp{client}", "tcp{client, server}");
|
||||
aux_add2group(L, "tcp{server}", "tcp{client, server}");
|
||||
aux_add2group(L, "tcp{master}", "tcp{any}");
|
||||
aux_add2group(L, "tcp{client}", "tcp{any}");
|
||||
aux_add2group(L, "tcp{server}", "tcp{any}");
|
||||
aux_add2group(L, "tcp{client}", "tcp{client, server}");
|
||||
aux_add2group(L, "tcp{server}", "tcp{client, server}");
|
||||
aux_add2group(L, "tcp{client}", "select{able}");
|
||||
aux_add2group(L, "tcp{server}", "select{able}");
|
||||
/* define library functions */
|
||||
luaL_openlib(L, LUASOCKET_LIBNAME, func, 0);
|
||||
lua_pop(L, 1);
|
||||
@ -76,28 +84,45 @@ void tcp_open(lua_State *L)
|
||||
/*-------------------------------------------------------------------------*\
|
||||
* Just call buffered IO methods
|
||||
\*-------------------------------------------------------------------------*/
|
||||
static int tcp_meth_send(lua_State *L)
|
||||
static int meth_send(lua_State *L)
|
||||
{
|
||||
p_tcp tcp = (p_tcp) aux_checkclass(L, "tcp{client}", 1);
|
||||
return buf_meth_send(L, &tcp->buf);
|
||||
}
|
||||
|
||||
static int tcp_meth_receive(lua_State *L)
|
||||
static int meth_receive(lua_State *L)
|
||||
{
|
||||
p_tcp tcp = (p_tcp) aux_checkclass(L, "tcp{client}", 1);
|
||||
return buf_meth_receive(L, &tcp->buf);
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*\
|
||||
* Select support methods
|
||||
\*-------------------------------------------------------------------------*/
|
||||
static int meth_fd(lua_State *L)
|
||||
{
|
||||
p_tcp tcp = (p_tcp) aux_checkclass(L, "tcp{client, server}", 1);
|
||||
lua_pushnumber(L, tcp->sock);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int meth_dirty(lua_State *L)
|
||||
{
|
||||
p_tcp tcp = (p_tcp) aux_checkclass(L, "tcp{client, server}", 1);
|
||||
lua_pushboolean(L, !buf_isempty(&tcp->buf));
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*\
|
||||
* Just call inet methods
|
||||
\*-------------------------------------------------------------------------*/
|
||||
static int tcp_meth_getpeername(lua_State *L)
|
||||
static int meth_getpeername(lua_State *L)
|
||||
{
|
||||
p_tcp tcp = (p_tcp) aux_checkclass(L, "tcp{client}", 1);
|
||||
return inet_meth_getpeername(L, &tcp->sock);
|
||||
}
|
||||
|
||||
static int tcp_meth_getsockname(lua_State *L)
|
||||
static int meth_getsockname(lua_State *L)
|
||||
{
|
||||
p_tcp tcp = (p_tcp) aux_checkgroup(L, "tcp{client, server}", 1);
|
||||
return inet_meth_getsockname(L, &tcp->sock);
|
||||
@ -106,7 +131,7 @@ static int tcp_meth_getsockname(lua_State *L)
|
||||
/*-------------------------------------------------------------------------*\
|
||||
* Just call tm methods
|
||||
\*-------------------------------------------------------------------------*/
|
||||
static int tcp_meth_timeout(lua_State *L)
|
||||
static int meth_timeout(lua_State *L)
|
||||
{
|
||||
p_tcp tcp = (p_tcp) aux_checkgroup(L, "tcp{any}", 1);
|
||||
return tm_meth_timeout(L, &tcp->tm);
|
||||
@ -115,7 +140,7 @@ static int tcp_meth_timeout(lua_State *L)
|
||||
/*-------------------------------------------------------------------------*\
|
||||
* Closes socket used by object
|
||||
\*-------------------------------------------------------------------------*/
|
||||
static int tcp_meth_close(lua_State *L)
|
||||
static int meth_close(lua_State *L)
|
||||
{
|
||||
p_tcp tcp = (p_tcp) aux_checkgroup(L, "tcp{any}", 1);
|
||||
sock_destroy(&tcp->sock);
|
||||
@ -125,7 +150,7 @@ static int tcp_meth_close(lua_State *L)
|
||||
/*-------------------------------------------------------------------------*\
|
||||
* Turns a master tcp object into a client object.
|
||||
\*-------------------------------------------------------------------------*/
|
||||
static int tcp_meth_connect(lua_State *L)
|
||||
static int meth_connect(lua_State *L)
|
||||
{
|
||||
p_tcp tcp = (p_tcp) aux_checkclass(L, "tcp{master}", 1);
|
||||
const char *address = luaL_checkstring(L, 2);
|
||||
@ -145,7 +170,7 @@ static int tcp_meth_connect(lua_State *L)
|
||||
/*-------------------------------------------------------------------------*\
|
||||
* Turns a master object into a server object
|
||||
\*-------------------------------------------------------------------------*/
|
||||
static int tcp_meth_bind(lua_State *L)
|
||||
static int meth_bind(lua_State *L)
|
||||
{
|
||||
p_tcp tcp = (p_tcp) aux_checkclass(L, "tcp{master}", 1);
|
||||
const char *address = luaL_checkstring(L, 2);
|
||||
@ -167,10 +192,10 @@ static int tcp_meth_bind(lua_State *L)
|
||||
* Waits for and returns a client object attempting connection to the
|
||||
* server object
|
||||
\*-------------------------------------------------------------------------*/
|
||||
static int tcp_meth_accept(lua_State *L)
|
||||
static int meth_accept(lua_State *L)
|
||||
{
|
||||
struct sockaddr_in addr;
|
||||
size_t addr_len = sizeof(addr);
|
||||
socklen_t addr_len = sizeof(addr);
|
||||
p_tcp server = (p_tcp) aux_checkclass(L, "tcp{server}", 1);
|
||||
p_tm tm = &server->tm;
|
||||
p_tcp client = lua_newuserdata(L, sizeof(t_tcp));
|
||||
@ -200,7 +225,7 @@ static int tcp_meth_accept(lua_State *L)
|
||||
/*-------------------------------------------------------------------------*\
|
||||
* Creates a master tcp object
|
||||
\*-------------------------------------------------------------------------*/
|
||||
int tcp_global_create(lua_State *L)
|
||||
int global_create(lua_State *L)
|
||||
{
|
||||
/* allocate tcp object */
|
||||
p_tcp tcp = (p_tcp) lua_newuserdata(L, sizeof(t_tcp));
|
||||
|
@ -3,9 +3,9 @@
|
||||
|
||||
#include <lua.h>
|
||||
|
||||
#include "buf.h"
|
||||
#include "tm.h"
|
||||
#include "sock.h"
|
||||
#include "buffer.h"
|
||||
#include "timeout.h"
|
||||
#include "socket.h"
|
||||
|
||||
typedef struct t_tcp_ {
|
||||
t_sock sock;
|
||||
|
@ -12,8 +12,8 @@
|
||||
#include <lauxlib.h>
|
||||
|
||||
#include "luasocket.h"
|
||||
#include "aux.h"
|
||||
#include "tm.h"
|
||||
#include "auxiliar.h"
|
||||
#include "timeout.h"
|
||||
|
||||
#ifdef WIN32
|
||||
#include <windows.h>
|
||||
@ -118,6 +118,7 @@ int tm_gettime(void)
|
||||
void tm_open(lua_State *L)
|
||||
{
|
||||
luaL_openlib(L, LUASOCKET_LIBNAME, func, 0);
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*\
|
||||
|
98
src/udp.c
98
src/udp.c
@ -10,43 +10,49 @@
|
||||
|
||||
#include "luasocket.h"
|
||||
|
||||
#include "aux.h"
|
||||
#include "auxiliar.h"
|
||||
#include "socket.h"
|
||||
#include "inet.h"
|
||||
#include "error.h"
|
||||
#include "udp.h"
|
||||
|
||||
/*=========================================================================*\
|
||||
* Internal function prototypes
|
||||
\*=========================================================================*/
|
||||
static int udp_global_create(lua_State *L);
|
||||
static int udp_meth_send(lua_State *L);
|
||||
static int udp_meth_sendto(lua_State *L);
|
||||
static int udp_meth_receive(lua_State *L);
|
||||
static int udp_meth_receivefrom(lua_State *L);
|
||||
static int udp_meth_getsockname(lua_State *L);
|
||||
static int udp_meth_getpeername(lua_State *L);
|
||||
static int udp_meth_setsockname(lua_State *L);
|
||||
static int udp_meth_setpeername(lua_State *L);
|
||||
static int udp_meth_close(lua_State *L);
|
||||
static int udp_meth_timeout(lua_State *L);
|
||||
static int global_create(lua_State *L);
|
||||
static int meth_send(lua_State *L);
|
||||
static int meth_sendto(lua_State *L);
|
||||
static int meth_receive(lua_State *L);
|
||||
static int meth_receivefrom(lua_State *L);
|
||||
static int meth_getsockname(lua_State *L);
|
||||
static int meth_getpeername(lua_State *L);
|
||||
static int meth_setsockname(lua_State *L);
|
||||
static int meth_setpeername(lua_State *L);
|
||||
static int meth_close(lua_State *L);
|
||||
static int meth_timeout(lua_State *L);
|
||||
static int meth_fd(lua_State *L);
|
||||
static int meth_dirty(lua_State *L);
|
||||
|
||||
/* udp object methods */
|
||||
static luaL_reg udp[] = {
|
||||
{"setpeername", udp_meth_setpeername},
|
||||
{"setsockname", udp_meth_setsockname},
|
||||
{"getsockname", udp_meth_getsockname},
|
||||
{"getpeername", udp_meth_getpeername},
|
||||
{"send", udp_meth_send},
|
||||
{"sendto", udp_meth_sendto},
|
||||
{"receive", udp_meth_receive},
|
||||
{"receivefrom", udp_meth_receivefrom},
|
||||
{"timeout", udp_meth_timeout},
|
||||
{"close", udp_meth_close},
|
||||
{"setpeername", meth_setpeername},
|
||||
{"setsockname", meth_setsockname},
|
||||
{"getsockname", meth_getsockname},
|
||||
{"getpeername", meth_getpeername},
|
||||
{"send", meth_send},
|
||||
{"sendto", meth_sendto},
|
||||
{"receive", meth_receive},
|
||||
{"receivefrom", meth_receivefrom},
|
||||
{"timeout", meth_timeout},
|
||||
{"close", meth_close},
|
||||
{"fd", meth_fd},
|
||||
{"dirty", meth_dirty},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
/* functions in library namespace */
|
||||
static luaL_reg func[] = {
|
||||
{"udp", udp_global_create},
|
||||
{"udp", global_create},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
@ -59,8 +65,10 @@ void udp_open(lua_State *L)
|
||||
aux_newclass(L, "udp{connected}", udp);
|
||||
aux_newclass(L, "udp{unconnected}", udp);
|
||||
/* create class groups */
|
||||
aux_add2group(L, "udp{connected}", "udp{any}");
|
||||
aux_add2group(L, "udp{connected}", "udp{any}");
|
||||
aux_add2group(L, "udp{unconnected}", "udp{any}");
|
||||
aux_add2group(L, "udp{connected}", "select{able}");
|
||||
aux_add2group(L, "udp{unconnected}", "select{able}");
|
||||
/* define library functions */
|
||||
luaL_openlib(L, LUASOCKET_LIBNAME, func, 0);
|
||||
lua_pop(L, 1);
|
||||
@ -72,7 +80,7 @@ void udp_open(lua_State *L)
|
||||
/*-------------------------------------------------------------------------*\
|
||||
* Send data through connected udp socket
|
||||
\*-------------------------------------------------------------------------*/
|
||||
static int udp_meth_send(lua_State *L)
|
||||
static int meth_send(lua_State *L)
|
||||
{
|
||||
p_udp udp = (p_udp) aux_checkclass(L, "udp{connected}", 1);
|
||||
p_tm tm = &udp->tm;
|
||||
@ -90,7 +98,7 @@ static int udp_meth_send(lua_State *L)
|
||||
/*-------------------------------------------------------------------------*\
|
||||
* Send data through unconnected udp socket
|
||||
\*-------------------------------------------------------------------------*/
|
||||
static int udp_meth_sendto(lua_State *L)
|
||||
static int meth_sendto(lua_State *L)
|
||||
{
|
||||
p_udp udp = (p_udp) aux_checkclass(L, "udp{unconnected}", 1);
|
||||
size_t count, sent = 0;
|
||||
@ -117,7 +125,7 @@ static int udp_meth_sendto(lua_State *L)
|
||||
/*-------------------------------------------------------------------------*\
|
||||
* Receives data from a UDP socket
|
||||
\*-------------------------------------------------------------------------*/
|
||||
static int udp_meth_receive(lua_State *L)
|
||||
static int meth_receive(lua_State *L)
|
||||
{
|
||||
p_udp udp = (p_udp) aux_checkgroup(L, "udp{any}", 1);
|
||||
char buffer[UDP_DATAGRAMSIZE];
|
||||
@ -136,11 +144,11 @@ static int udp_meth_receive(lua_State *L)
|
||||
/*-------------------------------------------------------------------------*\
|
||||
* Receives data and sender from a UDP socket
|
||||
\*-------------------------------------------------------------------------*/
|
||||
static int udp_meth_receivefrom(lua_State *L)
|
||||
static int meth_receivefrom(lua_State *L)
|
||||
{
|
||||
p_udp udp = (p_udp) aux_checkclass(L, "udp{unconnected}", 1);
|
||||
struct sockaddr_in addr;
|
||||
size_t addr_len = sizeof(addr);
|
||||
socklen_t addr_len = sizeof(addr);
|
||||
char buffer[UDP_DATAGRAMSIZE];
|
||||
size_t got, count = (size_t) luaL_optnumber(L, 2, sizeof(buffer));
|
||||
int err;
|
||||
@ -161,16 +169,34 @@ static int udp_meth_receivefrom(lua_State *L)
|
||||
}
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*\
|
||||
* Select support methods
|
||||
\*-------------------------------------------------------------------------*/
|
||||
static int meth_fd(lua_State *L)
|
||||
{
|
||||
p_udp udp = (p_udp) aux_checkclass(L, "udp{any}", 1);
|
||||
lua_pushnumber(L, udp->sock);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int meth_dirty(lua_State *L)
|
||||
{
|
||||
p_udp udp = (p_udp) aux_checkclass(L, "udp{any}", 1);
|
||||
(void) udp;
|
||||
lua_pushboolean(L, 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*\
|
||||
* Just call inet methods
|
||||
\*-------------------------------------------------------------------------*/
|
||||
static int udp_meth_getpeername(lua_State *L)
|
||||
static int meth_getpeername(lua_State *L)
|
||||
{
|
||||
p_udp udp = (p_udp) aux_checkclass(L, "udp{connected}", 1);
|
||||
return inet_meth_getpeername(L, &udp->sock);
|
||||
}
|
||||
|
||||
static int udp_meth_getsockname(lua_State *L)
|
||||
static int meth_getsockname(lua_State *L)
|
||||
{
|
||||
p_udp udp = (p_udp) aux_checkgroup(L, "udp{any}", 1);
|
||||
return inet_meth_getsockname(L, &udp->sock);
|
||||
@ -179,7 +205,7 @@ static int udp_meth_getsockname(lua_State *L)
|
||||
/*-------------------------------------------------------------------------*\
|
||||
* Just call tm methods
|
||||
\*-------------------------------------------------------------------------*/
|
||||
static int udp_meth_timeout(lua_State *L)
|
||||
static int meth_timeout(lua_State *L)
|
||||
{
|
||||
p_udp udp = (p_udp) aux_checkgroup(L, "udp{any}", 1);
|
||||
return tm_meth_timeout(L, &udp->tm);
|
||||
@ -188,7 +214,7 @@ static int udp_meth_timeout(lua_State *L)
|
||||
/*-------------------------------------------------------------------------*\
|
||||
* Turns a master udp object into a client object.
|
||||
\*-------------------------------------------------------------------------*/
|
||||
static int udp_meth_setpeername(lua_State *L)
|
||||
static int meth_setpeername(lua_State *L)
|
||||
{
|
||||
p_udp udp = (p_udp) aux_checkclass(L, "udp{unconnected}", 1);
|
||||
const char *address = luaL_checkstring(L, 2);
|
||||
@ -211,7 +237,7 @@ static int udp_meth_setpeername(lua_State *L)
|
||||
/*-------------------------------------------------------------------------*\
|
||||
* Closes socket used by object
|
||||
\*-------------------------------------------------------------------------*/
|
||||
static int udp_meth_close(lua_State *L)
|
||||
static int meth_close(lua_State *L)
|
||||
{
|
||||
p_udp udp = (p_udp) aux_checkgroup(L, "udp{any}", 1);
|
||||
sock_destroy(&udp->sock);
|
||||
@ -221,7 +247,7 @@ static int udp_meth_close(lua_State *L)
|
||||
/*-------------------------------------------------------------------------*\
|
||||
* Turns a master object into a server object
|
||||
\*-------------------------------------------------------------------------*/
|
||||
static int udp_meth_setsockname(lua_State *L)
|
||||
static int meth_setsockname(lua_State *L)
|
||||
{
|
||||
p_udp udp = (p_udp) aux_checkclass(L, "udp{master}", 1);
|
||||
const char *address = luaL_checkstring(L, 2);
|
||||
@ -242,7 +268,7 @@ static int udp_meth_setsockname(lua_State *L)
|
||||
/*-------------------------------------------------------------------------*\
|
||||
* Creates a master udp object
|
||||
\*-------------------------------------------------------------------------*/
|
||||
int udp_global_create(lua_State *L)
|
||||
int global_create(lua_State *L)
|
||||
{
|
||||
/* allocate udp object */
|
||||
p_udp udp = (p_udp) lua_newuserdata(L, sizeof(t_udp));
|
||||
|
@ -3,8 +3,8 @@
|
||||
|
||||
#include <lua.h>
|
||||
|
||||
#include "tm.h"
|
||||
#include "sock.h"
|
||||
#include "timeout.h"
|
||||
#include "socket.h"
|
||||
|
||||
#define UDP_DATAGRAMSIZE 576
|
||||
|
||||
|
119
src/usocket.c
119
src/usocket.c
@ -1,24 +1,8 @@
|
||||
/*=========================================================================*\
|
||||
* Socket compatibilization module for Unix
|
||||
*
|
||||
* RCS ID: $Id$
|
||||
\*=========================================================================*/
|
||||
#include <lua.h>
|
||||
#include <lauxlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "sock.h"
|
||||
#include "socket.h"
|
||||
|
||||
/*=========================================================================*\
|
||||
* Internal function prototypes
|
||||
\*=========================================================================*/
|
||||
static const char *try_setoption(lua_State *L, p_sock ps);
|
||||
static const char *try_setbooloption(lua_State *L, p_sock ps, int name);
|
||||
|
||||
/*=========================================================================*\
|
||||
* Exported functions.
|
||||
\*=========================================================================*/
|
||||
int sock_open(lua_State *L)
|
||||
int sock_open(void)
|
||||
{
|
||||
/* instals a handler to ignore sigpipe. */
|
||||
struct sigaction new;
|
||||
@ -43,13 +27,13 @@ const char *sock_create(p_sock ps, int domain, int type, int protocol)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char *sock_connect(p_sock ps, SA *addr, size_t addr_len)
|
||||
const char *sock_connect(p_sock ps, SA *addr, socklen_t addr_len)
|
||||
{
|
||||
if (connect(*ps, addr, addr_len) < 0) return sock_connectstrerror();
|
||||
else return NULL;
|
||||
}
|
||||
|
||||
const char *sock_bind(p_sock ps, SA *addr, size_t addr_len)
|
||||
const char *sock_bind(p_sock ps, SA *addr, socklen_t addr_len)
|
||||
{
|
||||
if (bind(*ps, addr, addr_len) < 0) return sock_bindstrerror();
|
||||
else return NULL;
|
||||
@ -60,17 +44,25 @@ void sock_listen(p_sock ps, int backlog)
|
||||
listen(*ps, backlog);
|
||||
}
|
||||
|
||||
void sock_accept(p_sock ps, p_sock pa, SA *addr, size_t *addr_len, int timeout)
|
||||
int sock_accept(p_sock ps, p_sock pa, SA *addr, socklen_t *addr_len,
|
||||
int timeout)
|
||||
{
|
||||
t_sock sock = *ps;
|
||||
struct timeval tv;
|
||||
SA dummy_addr;
|
||||
socklen_t dummy_len;
|
||||
fd_set fds;
|
||||
tv.tv_sec = timeout / 1000;
|
||||
tv.tv_usec = (timeout % 1000) * 1000;
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(sock, &fds);
|
||||
select(sock+1, &fds, NULL, NULL, timeout >= 0 ? &tv : NULL);
|
||||
if (select(sock+1, &fds, NULL, NULL, timeout >= 0 ? &tv : NULL) <= 0)
|
||||
return IO_TIMEOUT;
|
||||
if (!addr) addr = &dummy_addr;
|
||||
if (!addr_len) addr_len = &dummy_len;
|
||||
*pa = accept(sock, addr, addr_len);
|
||||
if (*pa == SOCK_INVALID) return IO_ERROR;
|
||||
else return IO_DONE;
|
||||
}
|
||||
|
||||
int sock_send(p_sock ps, const char *data, size_t count, size_t *sent,
|
||||
@ -108,7 +100,7 @@ int sock_send(p_sock ps, const char *data, size_t count, size_t *sent,
|
||||
}
|
||||
|
||||
int sock_sendto(p_sock ps, const char *data, size_t count, size_t *sent,
|
||||
SA *addr, size_t addr_len, int timeout)
|
||||
SA *addr, socklen_t addr_len, int timeout)
|
||||
{
|
||||
t_sock sock = *ps;
|
||||
struct timeval tv;
|
||||
@ -169,7 +161,7 @@ int sock_recv(p_sock ps, char *data, size_t count, size_t *got, int timeout)
|
||||
}
|
||||
|
||||
int sock_recvfrom(p_sock ps, char *data, size_t count, size_t *got,
|
||||
SA *addr, size_t *addr_len, int timeout)
|
||||
SA *addr, socklen_t *addr_len, int timeout)
|
||||
{
|
||||
t_sock sock = *ps;
|
||||
struct timeval tv;
|
||||
@ -196,9 +188,6 @@ int sock_recvfrom(p_sock ps, char *data, size_t count, size_t *got,
|
||||
}
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*\
|
||||
* Returns a string describing the last host manipulation error.
|
||||
\*-------------------------------------------------------------------------*/
|
||||
const char *sock_hoststrerror(void)
|
||||
{
|
||||
switch (h_errno) {
|
||||
@ -210,9 +199,6 @@ const char *sock_hoststrerror(void)
|
||||
}
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*\
|
||||
* Returns a string describing the last socket manipulation error.
|
||||
\*-------------------------------------------------------------------------*/
|
||||
const char *sock_createstrerror(void)
|
||||
{
|
||||
switch (errno) {
|
||||
@ -224,9 +210,6 @@ const char *sock_createstrerror(void)
|
||||
}
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*\
|
||||
* Returns a string describing the last bind command error.
|
||||
\*-------------------------------------------------------------------------*/
|
||||
const char *sock_bindstrerror(void)
|
||||
{
|
||||
switch (errno) {
|
||||
@ -241,9 +224,6 @@ const char *sock_bindstrerror(void)
|
||||
}
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*\
|
||||
* Returns a string describing the last connect error.
|
||||
\*-------------------------------------------------------------------------*/
|
||||
const char *sock_connectstrerror(void)
|
||||
{
|
||||
switch (errno) {
|
||||
@ -259,20 +239,12 @@ const char *sock_connectstrerror(void)
|
||||
}
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*\
|
||||
* Sets the SO_REUSEADDR socket option
|
||||
* Input
|
||||
* sock: socket descriptor
|
||||
\*-------------------------------------------------------------------------*/
|
||||
void sock_setreuseaddr(p_sock ps)
|
||||
{
|
||||
int val = 1;
|
||||
setsockopt(*ps, SOL_SOCKET, SO_REUSEADDR, (char *)&val, sizeof(val));
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*\
|
||||
* Put socket into blocking mode.
|
||||
\*-------------------------------------------------------------------------*/
|
||||
void sock_setblocking(p_sock ps)
|
||||
{
|
||||
int flags = fcntl(*ps, F_GETFL, 0);
|
||||
@ -280,68 +252,9 @@ void sock_setblocking(p_sock ps)
|
||||
fcntl(*ps, F_SETFL, flags);
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*\
|
||||
* Put socket into non-blocking mode.
|
||||
\*-------------------------------------------------------------------------*/
|
||||
void sock_setnonblocking(p_sock ps)
|
||||
{
|
||||
int flags = fcntl(*ps, F_GETFL, 0);
|
||||
flags |= O_NONBLOCK;
|
||||
fcntl(*ps, F_SETFL, flags);
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*\
|
||||
* Tries to set extended udp socket options
|
||||
* Input
|
||||
* udp: udp structure
|
||||
* oldtop: top of stack
|
||||
* Returns
|
||||
* NULL if successfull, error message on error
|
||||
\*-------------------------------------------------------------------------*/
|
||||
const char *sock_trysetoptions(lua_State *L, p_sock ps)
|
||||
{
|
||||
if (!lua_istable(L, 1)) luaL_argerror(L, 1, "invalid options table");
|
||||
lua_pushnil(L);
|
||||
while (lua_next(L, 1)) {
|
||||
const char *err = try_setoption(L, ps);
|
||||
lua_pop(L, 1);
|
||||
if (err) return err;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*\
|
||||
* Set socket options from a table on top of Lua stack.
|
||||
* Supports SO_KEEPALIVE, SO_DONTROUTE, and SO_BROADCAST options.
|
||||
* Input
|
||||
* sock: socket
|
||||
* Returns
|
||||
* 1 if successful, 0 otherwise
|
||||
\*-------------------------------------------------------------------------*/
|
||||
static const char *try_setoption(lua_State *L, p_sock ps)
|
||||
{
|
||||
static const char *options[] = {
|
||||
"SO_KEEPALIVE", "SO_DONTROUTE", "SO_BROADCAST", NULL
|
||||
};
|
||||
const char *option = lua_tostring(L, -2);
|
||||
if (!lua_isstring(L, -2)) return "invalid option";
|
||||
switch (luaL_findstring(option, options)) {
|
||||
case 0: return try_setbooloption(L, ps, SO_KEEPALIVE);
|
||||
case 1: return try_setbooloption(L, ps, SO_DONTROUTE);
|
||||
case 2: return try_setbooloption(L, ps, SO_BROADCAST);
|
||||
default: return "unsupported option";
|
||||
}
|
||||
}
|
||||
|
||||
/*=========================================================================*\
|
||||
* Internal functions.
|
||||
\*=========================================================================*/
|
||||
static const char *try_setbooloption(lua_State *L, p_sock ps, int name)
|
||||
{
|
||||
int bool, res;
|
||||
if (!lua_isnumber(L, -1)) luaL_error(L, "invalid option value");
|
||||
bool = (int) lua_tonumber(L, -1);
|
||||
res = setsockopt(*ps, SOL_SOCKET, name, (char *) &bool, sizeof(bool));
|
||||
if (res < 0) return "error setting option";
|
||||
else return NULL;
|
||||
}
|
||||
|
@ -31,6 +31,11 @@
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#ifdef __APPLE__
|
||||
/* for some reason socklen_t is not defined in mac os x */
|
||||
typedef int socklen_t;
|
||||
#endif
|
||||
|
||||
typedef int t_sock;
|
||||
typedef t_sock *p_sock;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user