New compat.h module implements luaL_setfuncs.

Makes initialization code simpler everywhere.
This commit is contained in:
Diego Nehab 2015-08-21 15:39:34 -03:00
parent 321c0c9b1f
commit e75444ccd1
20 changed files with 164 additions and 173 deletions

View File

@ -26,7 +26,7 @@ void auxiliar_newclass(lua_State *L, const char *classname, luaL_Reg *func) {
luaL_newmetatable(L, classname); /* mt */
/* create __index table to place methods */
lua_pushstring(L, "__index"); /* mt,"__index" */
lua_newtable(L); /* mt,"__index",it */
lua_newtable(L); /* mt,"__index",it */
/* put class name into class metatable */
lua_pushstring(L, "class"); /* mt,"__index",it,"class" */
lua_pushstring(L, classname); /* mt,"__index",it,"class",classname */
@ -84,7 +84,7 @@ int auxiliar_checkboolean(lua_State *L, int objidx) {
}
/*-------------------------------------------------------------------------*\
* Return userdata pointer if object belongs to a given class, abort with
* Return userdata pointer if object belongs to a given class, abort with
* error otherwise
\*-------------------------------------------------------------------------*/
void *auxiliar_checkclass(lua_State *L, const char *classname, int objidx) {
@ -98,7 +98,7 @@ void *auxiliar_checkclass(lua_State *L, const char *classname, int objidx) {
}
/*-------------------------------------------------------------------------*\
* Return userdata pointer if object belongs to a given group, abort with
* Return userdata pointer if object belongs to a given group, abort with
* error otherwise
\*-------------------------------------------------------------------------*/
void *auxiliar_checkgroup(lua_State *L, const char *groupname, int objidx) {
@ -121,7 +121,7 @@ void auxiliar_setclass(lua_State *L, const char *classname, int objidx) {
}
/*-------------------------------------------------------------------------*\
* Get a userdata pointer if object belongs to a given group. Return NULL
* Get a userdata pointer if object belongs to a given group. Return NULL
* otherwise
\*-------------------------------------------------------------------------*/
void *auxiliar_getgroupudata(lua_State *L, const char *groupname, int objidx) {
@ -139,7 +139,7 @@ void *auxiliar_getgroupudata(lua_State *L, const char *groupname, int objidx) {
}
/*-------------------------------------------------------------------------*\
* Get a userdata pointer if object belongs to a given class. Return NULL
* Get a userdata pointer if object belongs to a given class. Return NULL
* otherwise
\*-------------------------------------------------------------------------*/
void *auxiliar_getclassudata(lua_State *L, const char *classname, int objidx) {
@ -151,7 +151,7 @@ void *auxiliar_getclassudata(lua_State *L, const char *classname, int objidx) {
* Used to be part of lauxlib in Lua 5.1, was dropped from 5.2.
\*-------------------------------------------------------------------------*/
int auxiliar_typeerror (lua_State *L, int narg, const char *tname) {
const char *msg = lua_pushfstring(L, "%s expected, got %s", tname,
const char *msg = lua_pushfstring(L, "%s expected, got %s", tname,
luaL_typename(L, narg));
return luaL_argerror(L, narg, msg);
}

View File

@ -4,12 +4,12 @@
* Auxiliar routines for class hierarchy manipulation
* LuaSocket toolkit (but completely independent of other LuaSocket modules)
*
* A LuaSocket class is a name associated with Lua metatables. A LuaSocket
* group is a name associated with a class. A class can belong to any number
* A LuaSocket class is a name associated with Lua metatables. A LuaSocket
* group is a name associated with a class. A class can belong to any number
* of groups. This module provides the functionality to:
*
* - create new classes
* - add classes to groups
* - create new classes
* - add classes to groups
* - set the class of objects
* - check if an object belongs to a given class or group
* - get the userdata associated to objects
@ -26,11 +26,12 @@
* "class" with the class name.
*
* The mapping from class name to the corresponding metatable and the
* reverse mapping are done using lauxlib.
* reverse mapping are done using lauxlib.
\*=========================================================================*/
#include "lua.h"
#include "lauxlib.h"
#include "compat.h"
int auxiliar_open(lua_State *L);
void auxiliar_newclass(lua_State *L, const char *classname, luaL_Reg *func);

View File

@ -4,6 +4,7 @@
\*=========================================================================*/
#include "lua.h"
#include "lauxlib.h"
#include "compat.h"
#include "buffer.h"

19
src/compat.c Normal file
View File

@ -0,0 +1,19 @@
#include "compat.h"
#if !defined(LUA_VERSION_NUM) || LUA_VERSION_NUM==501
/*
** Adapted from Lua 5.2
*/
void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) {
luaL_checkstack(L, nup+1, "too many upvalues");
for (; l->name != NULL; l++) { /* fill the table with given functions */
int i;
lua_pushstring(L, l->name);
for (i = 0; i < nup; i++) /* copy upvalues to the top */
lua_pushvalue(L, -(nup+1));
lua_pushcclosure(L, l->func, nup); /* closure with those upvalues */
lua_settable(L, -(nup + 3));
}
lua_pop(L, nup); /* remove upvalues */
}
#endif

11
src/compat.h Normal file
View File

@ -0,0 +1,11 @@
#ifndef COMPAT_H
#define COMPAT_H
#include "lua.h"
#include "lauxlib.h"
#if LUA_VERSION_NUM==501
void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup);
#endif
#endif

View File

@ -6,6 +6,7 @@
#include "lua.h"
#include "lauxlib.h"
#include "compat.h"
#include "except.h"
@ -117,10 +118,6 @@ static int global_protect(lua_State *L) {
* Init module
\*-------------------------------------------------------------------------*/
int except_open(lua_State *L) {
#if LUA_VERSION_NUM > 501 && !defined(LUA_COMPAT_MODULE)
luaL_setfuncs(L, func, 0);
#else
luaL_openlib(L, NULL, func, 0);
#endif
return 0;
}

View File

@ -8,6 +8,7 @@
#include "lua.h"
#include "lauxlib.h"
#include "compat.h"
#include "inet.h"
@ -41,11 +42,7 @@ int inet_open(lua_State *L)
{
lua_pushstring(L, "dns");
lua_newtable(L);
#if LUA_VERSION_NUM > 501 && !defined(LUA_COMPAT_MODULE)
luaL_setfuncs(L, func, 0);
#else
luaL_openlib(L, NULL, func, 0);
#endif
lua_settable(L, -3);
return 0;
}

View File

@ -25,6 +25,6 @@ const char *io_strerror(int err) {
case IO_DONE: return NULL;
case IO_CLOSED: return "closed";
case IO_TIMEOUT: return "timeout";
default: return "unknown error";
default: return "unknown error";
}
}

View File

@ -17,6 +17,7 @@
\*=========================================================================*/
#include "lua.h"
#include "lauxlib.h"
#include "compat.h"
/*=========================================================================*\
* LuaSocket includes
@ -83,12 +84,8 @@ static int global_unload(lua_State *L) {
static int base_open(lua_State *L) {
if (socket_open()) {
/* export functions (and leave namespace table on top of stack) */
#if LUA_VERSION_NUM > 501 && !defined(LUA_COMPAT_MODULE)
lua_newtable(L);
luaL_setfuncs(L, func, 0);
#else
luaL_openlib(L, "socket", func, 0);
#endif
#ifdef LUASOCKET_DEBUG
lua_pushstring(L, "_DEBUG");
lua_pushboolean(L, 1);

View File

@ -260,6 +260,7 @@ SOCKET_OBJS= \
buffer.$(O) \
io.$(O) \
auxiliar.$(O) \
compat.$(O) \
options.$(O) \
inet.$(O) \
$(SOCKET) \
@ -272,7 +273,8 @@ SOCKET_OBJS= \
# Modules belonging mime-core
#
MIME_OBJS= \
mime.$(O)
mime.$(O) \
compat.$(O)
#------
# Modules belonging unix (local domain sockets)
@ -383,6 +385,7 @@ clean:
#------
# List of dependencies
#
compat.$(O): compat.c compat.h
auxiliar.$(O): auxiliar.c auxiliar.h
buffer.$(O): buffer.c buffer.h io.h timeout.h
except.$(O): except.c except.h

View File

@ -6,10 +6,7 @@
#include "lua.h"
#include "lauxlib.h"
#if !defined(LUA_VERSION_NUM) || (LUA_VERSION_NUM < 501)
#include "compat-5.1.h"
#endif
#include "compat.h"
#include "mime.h"
@ -81,12 +78,8 @@ static UC b64unbase[256];
\*-------------------------------------------------------------------------*/
MIME_API int luaopen_mime_core(lua_State *L)
{
#if LUA_VERSION_NUM > 501 && !defined(LUA_COMPAT_MODULE)
lua_newtable(L);
luaL_setfuncs(L, func, 0);
#else
luaL_openlib(L, "mime", func, 0);
#endif
/* make version string available to scripts */
lua_pushstring(L, "_VERSION");
lua_pushstring(L, MIME_VERSION);

View File

@ -1,8 +1,8 @@
/*=========================================================================*\
* Common option interface
* Common option interface
* LuaSocket toolkit
\*=========================================================================*/
#include <string.h>
#include <string.h>
#include "lauxlib.h"
@ -20,9 +20,9 @@ static int opt_setboolean(lua_State *L, p_socket ps, int level, int name);
static int opt_getboolean(lua_State *L, p_socket ps, int level, int name);
static int opt_setint(lua_State *L, p_socket ps, int level, int name);
static int opt_getint(lua_State *L, p_socket ps, int level, int name);
static int opt_set(lua_State *L, p_socket ps, int level, int name,
static int opt_set(lua_State *L, p_socket ps, int level, int name,
void *val, int len);
static int opt_get(lua_State *L, p_socket ps, int level, int name,
static int opt_get(lua_State *L, p_socket ps, int level, int name,
void *val, int* len);
/*=========================================================================*\
@ -60,29 +60,29 @@ int opt_meth_getoption(lua_State *L, p_opt opt, p_socket ps)
/* enables reuse of local address */
int opt_set_reuseaddr(lua_State *L, p_socket ps)
{
return opt_setboolean(L, ps, SOL_SOCKET, SO_REUSEADDR);
return opt_setboolean(L, ps, SOL_SOCKET, SO_REUSEADDR);
}
int opt_get_reuseaddr(lua_State *L, p_socket ps)
{
return opt_getboolean(L, ps, SOL_SOCKET, SO_REUSEADDR);
return opt_getboolean(L, ps, SOL_SOCKET, SO_REUSEADDR);
}
/* enables reuse of local port */
int opt_set_reuseport(lua_State *L, p_socket ps)
{
return opt_setboolean(L, ps, SOL_SOCKET, SO_REUSEPORT);
return opt_setboolean(L, ps, SOL_SOCKET, SO_REUSEPORT);
}
int opt_get_reuseport(lua_State *L, p_socket ps)
{
return opt_getboolean(L, ps, SOL_SOCKET, SO_REUSEPORT);
return opt_getboolean(L, ps, SOL_SOCKET, SO_REUSEPORT);
}
/* disables the Naggle algorithm */
int opt_set_tcp_nodelay(lua_State *L, p_socket ps)
{
return opt_setboolean(L, ps, IPPROTO_TCP, TCP_NODELAY);
return opt_setboolean(L, ps, IPPROTO_TCP, TCP_NODELAY);
}
int opt_get_tcp_nodelay(lua_State *L, p_socket ps)
@ -92,12 +92,12 @@ int opt_get_tcp_nodelay(lua_State *L, p_socket ps)
int opt_set_keepalive(lua_State *L, p_socket ps)
{
return opt_setboolean(L, ps, SOL_SOCKET, SO_KEEPALIVE);
return opt_setboolean(L, ps, SOL_SOCKET, SO_KEEPALIVE);
}
int opt_get_keepalive(lua_State *L, p_socket ps)
{
return opt_getboolean(L, ps, SOL_SOCKET, SO_KEEPALIVE);
return opt_getboolean(L, ps, SOL_SOCKET, SO_KEEPALIVE);
}
int opt_set_dontroute(lua_State *L, p_socket ps)
@ -156,12 +156,12 @@ int opt_set_linger(lua_State *L, p_socket ps)
if (!lua_istable(L, 3)) auxiliar_typeerror(L,3,lua_typename(L, LUA_TTABLE));
lua_pushstring(L, "on");
lua_gettable(L, 3);
if (!lua_isboolean(L, -1))
if (!lua_isboolean(L, -1))
luaL_argerror(L, 3, "boolean 'on' field expected");
li.l_onoff = (u_short) lua_toboolean(L, -1);
lua_pushstring(L, "timeout");
lua_gettable(L, 3);
if (!lua_isnumber(L, -1))
if (!lua_isnumber(L, -1))
luaL_argerror(L, 3, "number 'timeout' field expected");
li.l_linger = (u_short) lua_tonumber(L, -1);
return opt_set(L, ps, SOL_SOCKET, SO_LINGER, (char *) &li, sizeof(li));
@ -194,7 +194,7 @@ int opt_set_ip_multicast_if(lua_State *L, p_socket ps)
val.s_addr = htonl(INADDR_ANY);
if (strcmp(address, "*") && !inet_aton(address, &val))
luaL_argerror(L, 3, "ip expected");
return opt_set(L, ps, IPPROTO_IP, IP_MULTICAST_IF,
return opt_set(L, ps, IPPROTO_IP, IP_MULTICAST_IF,
(char *) &val, sizeof(val));
}
@ -250,17 +250,17 @@ static int opt_setmembership(lua_State *L, p_socket ps, int level, int name)
if (!lua_istable(L, 3)) auxiliar_typeerror(L,3,lua_typename(L, LUA_TTABLE));
lua_pushstring(L, "multiaddr");
lua_gettable(L, 3);
if (!lua_isstring(L, -1))
if (!lua_isstring(L, -1))
luaL_argerror(L, 3, "string 'multiaddr' field expected");
if (!inet_aton(lua_tostring(L, -1), &val.imr_multiaddr))
if (!inet_aton(lua_tostring(L, -1), &val.imr_multiaddr))
luaL_argerror(L, 3, "invalid 'multiaddr' ip address");
lua_pushstring(L, "interface");
lua_gettable(L, 3);
if (!lua_isstring(L, -1))
if (!lua_isstring(L, -1))
luaL_argerror(L, 3, "string 'interface' field expected");
val.imr_interface.s_addr = htonl(INADDR_ANY);
if (strcmp(lua_tostring(L, -1), "*") &&
!inet_aton(lua_tostring(L, -1), &val.imr_interface))
!inet_aton(lua_tostring(L, -1), &val.imr_interface))
luaL_argerror(L, 3, "invalid 'interface' ip address");
return opt_set(L, ps, level, name, (char *) &val, sizeof(val));
}
@ -272,14 +272,14 @@ static int opt_ip6_setmembership(lua_State *L, p_socket ps, int level, int name)
if (!lua_istable(L, 3)) auxiliar_typeerror(L,3,lua_typename(L, LUA_TTABLE));
lua_pushstring(L, "multiaddr");
lua_gettable(L, 3);
if (!lua_isstring(L, -1))
if (!lua_isstring(L, -1))
luaL_argerror(L, 3, "string 'multiaddr' field expected");
if (!inet_pton(AF_INET6, lua_tostring(L, -1), &val.ipv6mr_multiaddr))
if (!inet_pton(AF_INET6, lua_tostring(L, -1), &val.ipv6mr_multiaddr))
luaL_argerror(L, 3, "invalid 'multiaddr' ip address");
lua_pushstring(L, "interface");
lua_gettable(L, 3);
/* By default we listen to interface on default route
* (sigh). However, interface= can override it. We should
* (sigh). However, interface= can override it. We should
* support either number, or name for it. Waiting for
* windows port of if_nametoindex */
if (!lua_isnil(L, -1)) {
@ -291,7 +291,7 @@ static int opt_ip6_setmembership(lua_State *L, p_socket ps, int level, int name)
return opt_set(L, ps, level, name, (char *) &val, sizeof(val));
}
static
static
int opt_get(lua_State *L, p_socket ps, int level, int name, void *val, int* len)
{
socklen_t socklen = *len;
@ -304,7 +304,7 @@ int opt_get(lua_State *L, p_socket ps, int level, int name, void *val, int* len)
return 0;
}
static
static
int opt_set(lua_State *L, p_socket ps, int level, int name, void *val, int len)
{
if (setsockopt(*ps, level, name, (char *) val, len) < 0) {

View File

@ -6,6 +6,7 @@
#include "lua.h"
#include "lauxlib.h"
#include "compat.h"
#include "socket.h"
#include "timeout.h"
@ -16,10 +17,10 @@
\*=========================================================================*/
static t_socket getfd(lua_State *L);
static int dirty(lua_State *L);
static void collect_fd(lua_State *L, int tab, int itab,
static void collect_fd(lua_State *L, int tab, int itab,
fd_set *set, t_socket *max_fd);
static int check_dirty(lua_State *L, int tab, int dtab, fd_set *set);
static void return_fd(lua_State *L, fd_set *set, t_socket max_fd,
static void return_fd(lua_State *L, fd_set *set, t_socket max_fd,
int itab, int tab, int start);
static void make_assoc(lua_State *L, int tab);
static int global_select(lua_State *L);
@ -40,11 +41,7 @@ int select_open(lua_State *L) {
lua_pushstring(L, "_SETSIZE");
lua_pushnumber(L, FD_SETSIZE);
lua_rawset(L, -3);
#if LUA_VERSION_NUM > 501 && !defined(LUA_COMPAT_MODULE)
luaL_setfuncs(L, func, 0);
#else
luaL_openlib(L, NULL, func, 0);
#endif
return 0;
}
@ -98,10 +95,10 @@ static t_socket getfd(lua_State *L) {
lua_pushvalue(L, -2);
lua_call(L, 1, 1);
if (lua_isnumber(L, -1)) {
double numfd = lua_tonumber(L, -1);
double numfd = lua_tonumber(L, -1);
fd = (numfd >= 0.0)? (t_socket) numfd: SOCKET_INVALID;
}
}
}
lua_pop(L, 1);
return fd;
}
@ -114,12 +111,12 @@ static int dirty(lua_State *L) {
lua_pushvalue(L, -2);
lua_call(L, 1, 1);
is = lua_toboolean(L, -1);
}
}
lua_pop(L, 1);
return is;
}
static void collect_fd(lua_State *L, int tab, int itab,
static void collect_fd(lua_State *L, int tab, int itab,
fd_set *set, t_socket *max_fd) {
int i = 1, n = 0;
/* nil is the same as an empty table */
@ -139,16 +136,16 @@ static void collect_fd(lua_State *L, int tab, int itab,
if (fd != SOCKET_INVALID) {
/* make sure we don't overflow the fd_set */
#ifdef _WIN32
if (n >= FD_SETSIZE)
if (n >= FD_SETSIZE)
luaL_argerror(L, tab, "too many sockets");
#else
if (fd >= FD_SETSIZE)
if (fd >= FD_SETSIZE)
luaL_argerror(L, tab, "descriptor too large for set size");
#endif
FD_SET(fd, set);
n++;
/* keep track of the largest descriptor so far */
if (*max_fd == SOCKET_INVALID || *max_fd < fd)
if (*max_fd == SOCKET_INVALID || *max_fd < fd)
*max_fd = fd;
/* make sure we can map back from descriptor to the object */
lua_pushnumber(L, (lua_Number) fd);
@ -162,9 +159,9 @@ static void collect_fd(lua_State *L, int tab, int itab,
static int check_dirty(lua_State *L, int tab, int dtab, fd_set *set) {
int ndirty = 0, i = 1;
if (lua_isnil(L, tab))
if (lua_isnil(L, tab))
return 0;
for ( ;; ) {
for ( ;; ) {
t_socket fd;
lua_pushnumber(L, i);
lua_gettable(L, tab);
@ -185,7 +182,7 @@ static int check_dirty(lua_State *L, int tab, int dtab, fd_set *set) {
return ndirty;
}
static void return_fd(lua_State *L, fd_set *set, t_socket max_fd,
static void return_fd(lua_State *L, fd_set *set, t_socket max_fd,
int itab, int tab, int start) {
t_socket fd;
for (fd = 0; fd < max_fd; fd++) {

View File

@ -2,7 +2,7 @@
* Serial stream
* LuaSocket toolkit
\*=========================================================================*/
#include <string.h>
#include <string.h>
#include "lua.h"
#include "lauxlib.h"
@ -11,7 +11,7 @@
#include "socket.h"
#include "options.h"
#include "unix.h"
#include <sys/un.h>
#include <sys/un.h>
/*
Reuses userdata definition from unix.h, since it is useful for all
@ -55,7 +55,7 @@ static luaL_Reg serial_methods[] = {
};
/* our socket creation function */
/* this is an ad-hoc module that returns a single function
/* this is an ad-hoc module that returns a single function
* as such, do not include other functions in this array. */
static luaL_Reg func[] = {
{"serial", global_create},
@ -120,7 +120,7 @@ static int meth_getfd(lua_State *L) {
/* this is very dangerous, but can be handy for those that are brave enough */
static int meth_setfd(lua_State *L) {
p_unix un = (p_unix) auxiliar_checkgroup(L, "serial{any}", 1);
un->sock = (t_socket) luaL_checknumber(L, 2);
un->sock = (t_socket) luaL_checknumber(L, 2);
return 0;
}
@ -131,7 +131,7 @@ static int meth_dirty(lua_State *L) {
}
/*-------------------------------------------------------------------------*\
* Closes socket used by object
* Closes socket used by object
\*-------------------------------------------------------------------------*/
static int meth_close(lua_State *L)
{
@ -156,7 +156,7 @@ static int meth_settimeout(lua_State *L) {
/*-------------------------------------------------------------------------*\
* Creates a serial object
* Creates a serial object
\*-------------------------------------------------------------------------*/
static int global_create(lua_State *L) {
const char* path = luaL_checkstring(L, 1);
@ -180,7 +180,7 @@ static int global_create(lua_State *L) {
/* initialize remaining structure fields */
socket_setnonblocking(&sock);
un->sock = sock;
io_init(&un->io, (p_send) socket_write, (p_recv) socket_read,
io_init(&un->io, (p_send) socket_write, (p_recv) socket_read,
(p_error) socket_ioerror, &un->sock);
timeout_init(&un->tm, -1, -1);
buffer_init(&un->buf, &un->io, &un->tm);

View File

@ -6,6 +6,7 @@
#include "lua.h"
#include "lauxlib.h"
#include "compat.h"
#include "auxiliar.h"
#include "socket.h"
@ -108,11 +109,7 @@ int tcp_open(lua_State *L)
auxiliar_add2group(L, "tcp{client}", "tcp{any}");
auxiliar_add2group(L, "tcp{server}", "tcp{any}");
/* define library functions */
#if LUA_VERSION_NUM > 501 && !defined(LUA_COMPAT_MODULE)
luaL_setfuncs(L, func, 0);
#else
luaL_openlib(L, NULL, func, 0);
#endif
return 0;
}

View File

@ -8,6 +8,7 @@
#include "lua.h"
#include "lauxlib.h"
#include "compat.h"
#include "auxiliar.h"
#include "timeout.h"
@ -52,7 +53,7 @@ void timeout_init(p_timeout tm, double block, double total) {
/*-------------------------------------------------------------------------*\
* Determines how much time we have left for the next system call,
* if the previous call was successful
* if the previous call was successful
* Input
* tm: timeout control structure
* Returns
@ -107,7 +108,7 @@ double timeout_getretry(p_timeout tm) {
}
/*-------------------------------------------------------------------------*\
* Marks the operation start time in structure
* Marks the operation start time in structure
* Input
* tm: timeout control structure
\*-------------------------------------------------------------------------*/
@ -117,7 +118,7 @@ p_timeout timeout_markstart(p_timeout tm) {
}
/*-------------------------------------------------------------------------*\
* Gets time in s, relative to January 1, 1970 (UTC)
* Gets time in s, relative to January 1, 1970 (UTC)
* Returns
* time in s.
\*-------------------------------------------------------------------------*/
@ -144,11 +145,7 @@ double timeout_gettime(void) {
* Initializes module
\*-------------------------------------------------------------------------*/
int timeout_open(lua_State *L) {
#if LUA_VERSION_NUM > 501 && !defined(LUA_COMPAT_MODULE)
luaL_setfuncs(L, func, 0);
#else
luaL_openlib(L, NULL, func, 0);
#endif
return 0;
}
@ -163,7 +160,7 @@ int timeout_meth_settimeout(lua_State *L, p_timeout tm) {
const char *mode = luaL_optstring(L, 3, "b");
switch (*mode) {
case 'b':
tm->block = t;
tm->block = t;
break;
case 'r': case 't':
tm->total = t;

View File

@ -7,6 +7,7 @@
#include "lua.h"
#include "lauxlib.h"
#include "compat.h"
#include "auxiliar.h"
#include "socket.h"
@ -120,11 +121,7 @@ int udp_open(lua_State *L)
auxiliar_add2group(L, "udp{connected}", "select{able}");
auxiliar_add2group(L, "udp{unconnected}", "select{able}");
/* define library functions */
#if LUA_VERSION_NUM > 501 && !defined(LUA_COMPAT_MODULE)
luaL_setfuncs(L, func, 0);
#else
luaL_openlib(L, NULL, func, 0);
#endif
return 0;
}

View File

@ -1,8 +1,8 @@
/*=========================================================================*\
* Unix domain socket
* Unix domain socket
* LuaSocket toolkit
\*=========================================================================*/
#include <string.h>
#include <string.h>
#include "lua.h"
#include "lauxlib.h"
@ -11,7 +11,7 @@
#include "socket.h"
#include "options.h"
#include "unix.h"
#include <sys/un.h>
#include <sys/un.h>
/*=========================================================================*\
* Internal function prototypes
@ -68,15 +68,6 @@ static t_opt optset[] = {
{NULL, NULL}
};
/* our socket creation function */
/* this is an ad-hoc module that returns a single function
* as such, do not include other functions in this array. */
static luaL_Reg func[] = {
{"unix", global_create},
{NULL, NULL}
};
/*-------------------------------------------------------------------------*\
* Initializes module
\*-------------------------------------------------------------------------*/
@ -89,15 +80,8 @@ int luaopen_socket_unix(lua_State *L) {
auxiliar_add2group(L, "unix{master}", "unix{any}");
auxiliar_add2group(L, "unix{client}", "unix{any}");
auxiliar_add2group(L, "unix{server}", "unix{any}");
#if LUA_VERSION_NUM > 501 && !defined(LUA_COMPAT_MODULE)
lua_pushcfunction(L, global_create);
(void) func;
#else
/* set function into socket namespace */
luaL_openlib(L, "socket", func, 0);
lua_pushcfunction(L, global_create);
#endif
/* return the function instead of the 'socket' table */
lua_pushcfunction(L, global_create);
return 1;
}
@ -147,7 +131,7 @@ static int meth_getfd(lua_State *L) {
/* this is very dangerous, but can be handy for those that are brave enough */
static int meth_setfd(lua_State *L) {
p_unix un = (p_unix) auxiliar_checkgroup(L, "unix{any}", 1);
un->sock = (t_socket) luaL_checknumber(L, 2);
un->sock = (t_socket) luaL_checknumber(L, 2);
return 0;
}
@ -158,8 +142,8 @@ static int meth_dirty(lua_State *L) {
}
/*-------------------------------------------------------------------------*\
* Waits for and returns a client object attempting connection to the
* server object
* Waits for and returns a client object attempting connection to the
* server object
\*-------------------------------------------------------------------------*/
static int meth_accept(lua_State *L) {
p_unix server = (p_unix) auxiliar_checkclass(L, "unix{server}", 1);
@ -173,20 +157,20 @@ static int meth_accept(lua_State *L) {
/* initialize structure fields */
socket_setnonblocking(&sock);
clnt->sock = sock;
io_init(&clnt->io, (p_send)socket_send, (p_recv)socket_recv,
io_init(&clnt->io, (p_send)socket_send, (p_recv)socket_recv,
(p_error) socket_ioerror, &clnt->sock);
timeout_init(&clnt->tm, -1, -1);
buffer_init(&clnt->buf, &clnt->io, &clnt->tm);
return 1;
} else {
lua_pushnil(L);
lua_pushnil(L);
lua_pushstring(L, socket_strerror(err));
return 2;
}
}
/*-------------------------------------------------------------------------*\
* Binds an object to an address
* Binds an object to an address
\*-------------------------------------------------------------------------*/
static const char *unix_trybind(p_unix un, const char *path) {
struct sockaddr_un local;
@ -197,16 +181,16 @@ static const char *unix_trybind(p_unix un, const char *path) {
strcpy(local.sun_path, path);
local.sun_family = AF_UNIX;
#ifdef UNIX_HAS_SUN_LEN
local.sun_len = sizeof(local.sun_family) + sizeof(local.sun_len)
local.sun_len = sizeof(local.sun_family) + sizeof(local.sun_len)
+ len + 1;
err = socket_bind(&un->sock, (SA *) &local, local.sun_len);
#else
err = socket_bind(&un->sock, (SA *) &local,
#else
err = socket_bind(&un->sock, (SA *) &local,
sizeof(local.sun_family) + len);
#endif
if (err != IO_DONE) socket_destroy(&un->sock);
return socket_strerror(err);
return socket_strerror(err);
}
static int meth_bind(lua_State *L) {
@ -236,11 +220,11 @@ static const char *unix_tryconnect(p_unix un, const char *path)
remote.sun_family = AF_UNIX;
timeout_markstart(&un->tm);
#ifdef UNIX_HAS_SUN_LEN
remote.sun_len = sizeof(remote.sun_family) + sizeof(remote.sun_len)
remote.sun_len = sizeof(remote.sun_family) + sizeof(remote.sun_len)
+ len + 1;
err = socket_connect(&un->sock, (SA *) &remote, remote.sun_len, &un->tm);
#else
err = socket_connect(&un->sock, (SA *) &remote,
err = socket_connect(&un->sock, (SA *) &remote,
sizeof(remote.sun_family) + len, &un->tm);
#endif
if (err != IO_DONE) socket_destroy(&un->sock);
@ -264,7 +248,7 @@ static int meth_connect(lua_State *L)
}
/*-------------------------------------------------------------------------*\
* Closes socket used by object
* Closes socket used by object
\*-------------------------------------------------------------------------*/
static int meth_close(lua_State *L)
{
@ -319,13 +303,13 @@ static int meth_settimeout(lua_State *L) {
* Library functions
\*=========================================================================*/
/*-------------------------------------------------------------------------*\
* Creates a master unix object
* Creates a master unix object
\*-------------------------------------------------------------------------*/
static int global_create(lua_State *L) {
t_socket sock;
int err = socket_create(&sock, AF_UNIX, SOCK_STREAM, 0);
/* try to allocate a system socket */
if (err == IO_DONE) {
if (err == IO_DONE) {
/* allocate unix object */
p_unix un = (p_unix) lua_newuserdata(L, sizeof(t_unix));
/* set its type as master object */
@ -333,7 +317,7 @@ static int global_create(lua_State *L) {
/* initialize remaining structure fields */
socket_setnonblocking(&sock);
un->sock = sock;
io_init(&un->io, (p_send) socket_send, (p_recv) socket_recv,
io_init(&un->io, (p_send) socket_send, (p_recv) socket_recv,
(p_error) socket_ioerror, &un->sock);
timeout_init(&un->tm, -1, -1);
buffer_init(&un->buf, &un->io, &un->tm);

View File

@ -3,7 +3,7 @@
* LuaSocket toolkit
*
* The penalty of calling select to avoid busy-wait is only paid when
* the I/O call fail in the first place.
* the I/O call fail in the first place.
\*=========================================================================*/
#include <string.h>
@ -14,23 +14,23 @@
static const char *wstrerror(int err);
/*-------------------------------------------------------------------------*\
* Initializes module
* Initializes module
\*-------------------------------------------------------------------------*/
int socket_open(void) {
WSADATA wsaData;
WORD wVersionRequested = MAKEWORD(2, 0);
WORD wVersionRequested = MAKEWORD(2, 0);
int err = WSAStartup(wVersionRequested, &wsaData );
if (err != 0) return 0;
if ((LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 0) &&
(LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1)) {
WSACleanup();
return 0;
return 0;
}
return 1;
}
/*-------------------------------------------------------------------------*\
* Close module
* Close module
\*-------------------------------------------------------------------------*/
int socket_close(void) {
WSACleanup();
@ -51,10 +51,10 @@ int socket_waitfd(p_socket ps, int sw, p_timeout tm) {
struct timeval tv, *tp = NULL;
double t;
if (timeout_iszero(tm)) return IO_TIMEOUT; /* optimize timeout == 0 case */
if (sw & WAITFD_R) {
FD_ZERO(&rfds);
if (sw & WAITFD_R) {
FD_ZERO(&rfds);
FD_SET(*ps, &rfds);
rp = &rfds;
rp = &rfds;
}
if (sw & WAITFD_W) { FD_ZERO(&wfds); FD_SET(*ps, &wfds); wp = &wfds; }
if (sw & WAITFD_C) { FD_ZERO(&efds); FD_SET(*ps, &efds); ep = &efds; }
@ -73,9 +73,9 @@ int socket_waitfd(p_socket ps, int sw, p_timeout tm) {
/*-------------------------------------------------------------------------*\
* Select with int timeout in ms
\*-------------------------------------------------------------------------*/
int socket_select(t_socket n, fd_set *rfds, fd_set *wfds, fd_set *efds,
int socket_select(t_socket n, fd_set *rfds, fd_set *wfds, fd_set *efds,
p_timeout tm) {
struct timeval tv;
struct timeval tv;
double t = timeout_get(tm);
tv.tv_sec = (int) t;
tv.tv_usec = (int) ((t - tv.tv_sec) * 1.0e6);
@ -97,7 +97,7 @@ void socket_destroy(p_socket ps) {
}
/*-------------------------------------------------------------------------*\
*
*
\*-------------------------------------------------------------------------*/
void socket_shutdown(p_socket ps, int how) {
socket_setblocking(ps);
@ -135,10 +135,10 @@ int socket_connect(p_socket ps, SA *addr, socklen_t len, p_timeout tm) {
/* give windows time to set the error (yes, disgusting) */
Sleep(10);
/* find out why we failed */
getsockopt(*ps, SOL_SOCKET, SO_ERROR, (char *)&err, &len);
getsockopt(*ps, SOL_SOCKET, SO_ERROR, (char *)&err, &len);
/* we KNOW there was an error. if 'why' is 0, we will return
* "unknown error", but it's not really our fault */
return err > 0? err: IO_UNKNOWN;
return err > 0? err: IO_UNKNOWN;
} else return err;
}
@ -155,7 +155,7 @@ int socket_bind(p_socket ps, SA *addr, socklen_t len) {
}
/*-------------------------------------------------------------------------*\
*
*
\*-------------------------------------------------------------------------*/
int socket_listen(p_socket ps, int backlog) {
int err = IO_DONE;
@ -168,7 +168,7 @@ int socket_listen(p_socket ps, int backlog) {
/*-------------------------------------------------------------------------*\
* Accept with timeout
\*-------------------------------------------------------------------------*/
int socket_accept(p_socket ps, p_socket pa, SA *addr, socklen_t *len,
int socket_accept(p_socket ps, p_socket pa, SA *addr, socklen_t *len,
p_timeout tm) {
if (*ps == SOCKET_INVALID) return IO_CLOSED;
for ( ;; ) {
@ -176,21 +176,21 @@ int socket_accept(p_socket ps, p_socket pa, SA *addr, socklen_t *len,
/* try to get client socket */
if ((*pa = accept(*ps, addr, len)) != SOCKET_INVALID) return IO_DONE;
/* find out why we failed */
err = WSAGetLastError();
err = WSAGetLastError();
/* if we failed because there was no connectoin, keep trying */
if (err != WSAEWOULDBLOCK && err != WSAECONNABORTED) return err;
/* call select to avoid busy wait */
if ((err = socket_waitfd(ps, WAITFD_R, tm)) != IO_DONE) return err;
}
}
}
/*-------------------------------------------------------------------------*\
* Send with timeout
* On windows, if you try to send 10MB, the OS will buffer EVERYTHING
* this can take an awful lot of time and we will end up blocked.
* On windows, if you try to send 10MB, the OS will buffer EVERYTHING
* this can take an awful lot of time and we will end up blocked.
* Therefore, whoever calls this function should not pass a huge buffer.
\*-------------------------------------------------------------------------*/
int socket_send(p_socket ps, const char *data, size_t count,
int socket_send(p_socket ps, const char *data, size_t count,
size_t *sent, p_timeout tm)
{
int err;
@ -207,18 +207,18 @@ int socket_send(p_socket ps, const char *data, size_t count,
return IO_DONE;
}
/* deal with failure */
err = WSAGetLastError();
err = WSAGetLastError();
/* we can only proceed if there was no serious error */
if (err != WSAEWOULDBLOCK) return err;
/* avoid busy wait */
if ((err = socket_waitfd(ps, WAITFD_W, tm)) != IO_DONE) return err;
}
}
}
/*-------------------------------------------------------------------------*\
* Sendto with timeout
\*-------------------------------------------------------------------------*/
int socket_sendto(p_socket ps, const char *data, size_t count, size_t *sent,
int socket_sendto(p_socket ps, const char *data, size_t count, size_t *sent,
SA *addr, socklen_t len, p_timeout tm)
{
int err;
@ -230,17 +230,17 @@ int socket_sendto(p_socket ps, const char *data, size_t count, size_t *sent,
*sent = put;
return IO_DONE;
}
err = WSAGetLastError();
err = WSAGetLastError();
if (err != WSAEWOULDBLOCK) return err;
if ((err = socket_waitfd(ps, WAITFD_W, tm)) != IO_DONE) return err;
}
}
}
/*-------------------------------------------------------------------------*\
* Receive with timeout
\*-------------------------------------------------------------------------*/
int socket_recv(p_socket ps, char *data, size_t count, size_t *got,
p_timeout tm)
int socket_recv(p_socket ps, char *data, size_t count, size_t *got,
p_timeout tm)
{
int err, prev = IO_DONE;
*got = 0;
@ -253,9 +253,9 @@ int socket_recv(p_socket ps, char *data, size_t count, size_t *got,
}
if (taken == 0) return IO_CLOSED;
err = WSAGetLastError();
/* On UDP, a connreset simply means the previous send failed.
* So we try again.
* On TCP, it means our socket is now useless, so the error passes.
/* On UDP, a connreset simply means the previous send failed.
* So we try again.
* On TCP, it means our socket is now useless, so the error passes.
* (We will loop again, exiting because the same error will happen) */
if (err != WSAEWOULDBLOCK) {
if (err != WSAECONNRESET || prev == WSAECONNRESET) return err;
@ -268,8 +268,8 @@ int socket_recv(p_socket ps, char *data, size_t count, size_t *got,
/*-------------------------------------------------------------------------*\
* Recvfrom with timeout
\*-------------------------------------------------------------------------*/
int socket_recvfrom(p_socket ps, char *data, size_t count, size_t *got,
SA *addr, socklen_t *len, p_timeout tm)
int socket_recvfrom(p_socket ps, char *data, size_t count, size_t *got,
SA *addr, socklen_t *len, p_timeout tm)
{
int err, prev = IO_DONE;
*got = 0;
@ -282,8 +282,8 @@ int socket_recvfrom(p_socket ps, char *data, size_t count, size_t *got,
}
if (taken == 0) return IO_CLOSED;
err = WSAGetLastError();
/* On UDP, a connreset simply means the previous send failed.
* So we try again.
/* On UDP, a connreset simply means the previous send failed.
* So we try again.
* On TCP, it means our socket is now useless, so the error passes.
* (We will loop again, exiting because the same error will happen) */
if (err != WSAEWOULDBLOCK) {
@ -311,7 +311,7 @@ void socket_setnonblocking(p_socket ps) {
}
/*-------------------------------------------------------------------------*\
* DNS helpers
* DNS helpers
\*-------------------------------------------------------------------------*/
int socket_gethostbyaddr(const char *addr, socklen_t len, struct hostent **hp) {
*hp = gethostbyaddr(addr, len, AF_INET);
@ -332,7 +332,7 @@ const char *socket_hoststrerror(int err) {
if (err <= 0) return io_strerror(err);
switch (err) {
case WSAHOST_NOT_FOUND: return PIE_HOST_NOT_FOUND;
default: return wstrerror(err);
default: return wstrerror(err);
}
}
@ -374,7 +374,7 @@ static const char *wstrerror(int err) {
case WSAESOCKTNOSUPPORT: return PIE_SOCKTYPE; // "Socket type not supported";
case WSAEOPNOTSUPP: return "Operation not supported";
case WSAEPFNOSUPPORT: return "Protocol family not supported";
case WSAEAFNOSUPPORT: return PIE_FAMILY; // "Address family not supported by protocol family";
case WSAEAFNOSUPPORT: return PIE_FAMILY; // "Address family not supported by protocol family";
case WSAEADDRINUSE: return PIE_ADDRINUSE; // "Address already in use";
case WSAEADDRNOTAVAIL: return "Cannot assign requested address";
case WSAENETDOWN: return "Network is down";
@ -393,19 +393,19 @@ static const char *wstrerror(int err) {
case WSAEPROCLIM: return "Too many processes";
case WSASYSNOTREADY: return "Network subsystem is unavailable";
case WSAVERNOTSUPPORTED: return "Winsock.dll version out of range";
case WSANOTINITIALISED:
case WSANOTINITIALISED:
return "Successful WSAStartup not yet performed";
case WSAEDISCON: return "Graceful shutdown in progress";
case WSAHOST_NOT_FOUND: return PIE_HOST_NOT_FOUND; // "Host not found";
case WSATRY_AGAIN: return "Nonauthoritative host not found";
case WSANO_RECOVERY: return PIE_FAIL; // "Nonrecoverable name lookup error";
case WSANO_RECOVERY: return PIE_FAIL; // "Nonrecoverable name lookup error";
case WSANO_DATA: return "Valid name, no data record of requested type";
default: return "Unknown error";
}
}
const char *socket_gaistrerror(int err) {
if (err == 0) return NULL;
if (err == 0) return NULL;
switch (err) {
case EAI_AGAIN: return PIE_AGAIN;
case EAI_BADFLAGS: return PIE_BADFLAGS;
@ -425,7 +425,7 @@ const char *socket_gaistrerror(int err) {
case EAI_SERVICE: return PIE_SERVICE;
case EAI_SOCKTYPE: return PIE_SOCKTYPE;
#ifdef EAI_SYSTEM
case EAI_SYSTEM: return strerror(errno);
case EAI_SYSTEM: return strerror(errno);
#endif
default: return gai_strerror(err);
}

View File

@ -590,7 +590,7 @@ function test_writeafterclose()
data = nil
]]))
local sent, err, errsent
while not err do
while not err do
sent, err, errsent, time = data:send(str)
end
assert(err == "closed", "should have returned 'closed'")