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 */ luaL_newmetatable(L, classname); /* mt */
/* create __index table to place methods */ /* create __index table to place methods */
lua_pushstring(L, "__index"); /* mt,"__index" */ lua_pushstring(L, "__index"); /* mt,"__index" */
lua_newtable(L); /* mt,"__index",it */ lua_newtable(L); /* mt,"__index",it */
/* put class name into class metatable */ /* put class name into class metatable */
lua_pushstring(L, "class"); /* mt,"__index",it,"class" */ lua_pushstring(L, "class"); /* mt,"__index",it,"class" */
lua_pushstring(L, classname); /* mt,"__index",it,"class",classname */ 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 * error otherwise
\*-------------------------------------------------------------------------*/ \*-------------------------------------------------------------------------*/
void *auxiliar_checkclass(lua_State *L, const char *classname, int objidx) { 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 * error otherwise
\*-------------------------------------------------------------------------*/ \*-------------------------------------------------------------------------*/
void *auxiliar_checkgroup(lua_State *L, const char *groupname, int objidx) { 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 * otherwise
\*-------------------------------------------------------------------------*/ \*-------------------------------------------------------------------------*/
void *auxiliar_getgroupudata(lua_State *L, const char *groupname, int objidx) { 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 * otherwise
\*-------------------------------------------------------------------------*/ \*-------------------------------------------------------------------------*/
void *auxiliar_getclassudata(lua_State *L, const char *classname, int objidx) { 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. * 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) { 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)); luaL_typename(L, narg));
return luaL_argerror(L, narg, msg); return luaL_argerror(L, narg, msg);
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,8 +1,8 @@
/*=========================================================================*\ /*=========================================================================*\
* Common option interface * Common option interface
* LuaSocket toolkit * LuaSocket toolkit
\*=========================================================================*/ \*=========================================================================*/
#include <string.h> #include <string.h>
#include "lauxlib.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_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_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_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); 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); 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 */ /* enables reuse of local address */
int opt_set_reuseaddr(lua_State *L, p_socket ps) 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) 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 */ /* enables reuse of local port */
int opt_set_reuseport(lua_State *L, p_socket ps) 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) 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 */ /* disables the Naggle algorithm */
int opt_set_tcp_nodelay(lua_State *L, p_socket ps) 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) 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) 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) 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) 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)); if (!lua_istable(L, 3)) auxiliar_typeerror(L,3,lua_typename(L, LUA_TTABLE));
lua_pushstring(L, "on"); lua_pushstring(L, "on");
lua_gettable(L, 3); lua_gettable(L, 3);
if (!lua_isboolean(L, -1)) if (!lua_isboolean(L, -1))
luaL_argerror(L, 3, "boolean 'on' field expected"); luaL_argerror(L, 3, "boolean 'on' field expected");
li.l_onoff = (u_short) lua_toboolean(L, -1); li.l_onoff = (u_short) lua_toboolean(L, -1);
lua_pushstring(L, "timeout"); lua_pushstring(L, "timeout");
lua_gettable(L, 3); lua_gettable(L, 3);
if (!lua_isnumber(L, -1)) if (!lua_isnumber(L, -1))
luaL_argerror(L, 3, "number 'timeout' field expected"); luaL_argerror(L, 3, "number 'timeout' field expected");
li.l_linger = (u_short) lua_tonumber(L, -1); li.l_linger = (u_short) lua_tonumber(L, -1);
return opt_set(L, ps, SOL_SOCKET, SO_LINGER, (char *) &li, sizeof(li)); 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); val.s_addr = htonl(INADDR_ANY);
if (strcmp(address, "*") && !inet_aton(address, &val)) if (strcmp(address, "*") && !inet_aton(address, &val))
luaL_argerror(L, 3, "ip expected"); 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)); (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)); if (!lua_istable(L, 3)) auxiliar_typeerror(L,3,lua_typename(L, LUA_TTABLE));
lua_pushstring(L, "multiaddr"); lua_pushstring(L, "multiaddr");
lua_gettable(L, 3); lua_gettable(L, 3);
if (!lua_isstring(L, -1)) if (!lua_isstring(L, -1))
luaL_argerror(L, 3, "string 'multiaddr' field expected"); 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"); luaL_argerror(L, 3, "invalid 'multiaddr' ip address");
lua_pushstring(L, "interface"); lua_pushstring(L, "interface");
lua_gettable(L, 3); lua_gettable(L, 3);
if (!lua_isstring(L, -1)) if (!lua_isstring(L, -1))
luaL_argerror(L, 3, "string 'interface' field expected"); luaL_argerror(L, 3, "string 'interface' field expected");
val.imr_interface.s_addr = htonl(INADDR_ANY); val.imr_interface.s_addr = htonl(INADDR_ANY);
if (strcmp(lua_tostring(L, -1), "*") && 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"); luaL_argerror(L, 3, "invalid 'interface' ip address");
return opt_set(L, ps, level, name, (char *) &val, sizeof(val)); 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)); if (!lua_istable(L, 3)) auxiliar_typeerror(L,3,lua_typename(L, LUA_TTABLE));
lua_pushstring(L, "multiaddr"); lua_pushstring(L, "multiaddr");
lua_gettable(L, 3); lua_gettable(L, 3);
if (!lua_isstring(L, -1)) if (!lua_isstring(L, -1))
luaL_argerror(L, 3, "string 'multiaddr' field expected"); 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"); luaL_argerror(L, 3, "invalid 'multiaddr' ip address");
lua_pushstring(L, "interface"); lua_pushstring(L, "interface");
lua_gettable(L, 3); lua_gettable(L, 3);
/* By default we listen to interface on default route /* 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 * support either number, or name for it. Waiting for
* windows port of if_nametoindex */ * windows port of if_nametoindex */
if (!lua_isnil(L, -1)) { 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)); 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) int opt_get(lua_State *L, p_socket ps, int level, int name, void *val, int* len)
{ {
socklen_t socklen = *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; return 0;
} }
static static
int opt_set(lua_State *L, p_socket ps, int level, int name, void *val, int len) 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) { if (setsockopt(*ps, level, name, (char *) val, len) < 0) {

View File

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

View File

@ -2,7 +2,7 @@
* Serial stream * Serial stream
* LuaSocket toolkit * LuaSocket toolkit
\*=========================================================================*/ \*=========================================================================*/
#include <string.h> #include <string.h>
#include "lua.h" #include "lua.h"
#include "lauxlib.h" #include "lauxlib.h"
@ -11,7 +11,7 @@
#include "socket.h" #include "socket.h"
#include "options.h" #include "options.h"
#include "unix.h" #include "unix.h"
#include <sys/un.h> #include <sys/un.h>
/* /*
Reuses userdata definition from unix.h, since it is useful for all 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 */ /* 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. */ * as such, do not include other functions in this array. */
static luaL_Reg func[] = { static luaL_Reg func[] = {
{"serial", global_create}, {"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 */ /* this is very dangerous, but can be handy for those that are brave enough */
static int meth_setfd(lua_State *L) { static int meth_setfd(lua_State *L) {
p_unix un = (p_unix) auxiliar_checkgroup(L, "serial{any}", 1); 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; 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) 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) { static int global_create(lua_State *L) {
const char* path = luaL_checkstring(L, 1); const char* path = luaL_checkstring(L, 1);
@ -180,7 +180,7 @@ static int global_create(lua_State *L) {
/* initialize remaining structure fields */ /* initialize remaining structure fields */
socket_setnonblocking(&sock); socket_setnonblocking(&sock);
un->sock = 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); (p_error) socket_ioerror, &un->sock);
timeout_init(&un->tm, -1, -1); timeout_init(&un->tm, -1, -1);
buffer_init(&un->buf, &un->io, &un->tm); buffer_init(&un->buf, &un->io, &un->tm);

View File

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

View File

@ -8,6 +8,7 @@
#include "lua.h" #include "lua.h"
#include "lauxlib.h" #include "lauxlib.h"
#include "compat.h"
#include "auxiliar.h" #include "auxiliar.h"
#include "timeout.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, * 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 * Input
* tm: timeout control structure * tm: timeout control structure
* Returns * 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 * Input
* tm: timeout control structure * 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 * Returns
* time in s. * time in s.
\*-------------------------------------------------------------------------*/ \*-------------------------------------------------------------------------*/
@ -144,11 +145,7 @@ double timeout_gettime(void) {
* Initializes module * Initializes module
\*-------------------------------------------------------------------------*/ \*-------------------------------------------------------------------------*/
int timeout_open(lua_State *L) { int timeout_open(lua_State *L) {
#if LUA_VERSION_NUM > 501 && !defined(LUA_COMPAT_MODULE)
luaL_setfuncs(L, func, 0); luaL_setfuncs(L, func, 0);
#else
luaL_openlib(L, NULL, func, 0);
#endif
return 0; return 0;
} }
@ -163,7 +160,7 @@ int timeout_meth_settimeout(lua_State *L, p_timeout tm) {
const char *mode = luaL_optstring(L, 3, "b"); const char *mode = luaL_optstring(L, 3, "b");
switch (*mode) { switch (*mode) {
case 'b': case 'b':
tm->block = t; tm->block = t;
break; break;
case 'r': case 't': case 'r': case 't':
tm->total = t; tm->total = t;

View File

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

View File

@ -1,8 +1,8 @@
/*=========================================================================*\ /*=========================================================================*\
* Unix domain socket * Unix domain socket
* LuaSocket toolkit * LuaSocket toolkit
\*=========================================================================*/ \*=========================================================================*/
#include <string.h> #include <string.h>
#include "lua.h" #include "lua.h"
#include "lauxlib.h" #include "lauxlib.h"
@ -11,7 +11,7 @@
#include "socket.h" #include "socket.h"
#include "options.h" #include "options.h"
#include "unix.h" #include "unix.h"
#include <sys/un.h> #include <sys/un.h>
/*=========================================================================*\ /*=========================================================================*\
* Internal function prototypes * Internal function prototypes
@ -68,15 +68,6 @@ static t_opt optset[] = {
{NULL, NULL} {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 * Initializes module
\*-------------------------------------------------------------------------*/ \*-------------------------------------------------------------------------*/
@ -89,15 +80,8 @@ int luaopen_socket_unix(lua_State *L) {
auxiliar_add2group(L, "unix{master}", "unix{any}"); auxiliar_add2group(L, "unix{master}", "unix{any}");
auxiliar_add2group(L, "unix{client}", "unix{any}"); auxiliar_add2group(L, "unix{client}", "unix{any}");
auxiliar_add2group(L, "unix{server}", "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 */ /* return the function instead of the 'socket' table */
lua_pushcfunction(L, global_create);
return 1; 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 */ /* this is very dangerous, but can be handy for those that are brave enough */
static int meth_setfd(lua_State *L) { static int meth_setfd(lua_State *L) {
p_unix un = (p_unix) auxiliar_checkgroup(L, "unix{any}", 1); 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; return 0;
} }
@ -158,8 +142,8 @@ static int meth_dirty(lua_State *L) {
} }
/*-------------------------------------------------------------------------*\ /*-------------------------------------------------------------------------*\
* Waits for and returns a client object attempting connection to the * Waits for and returns a client object attempting connection to the
* server object * server object
\*-------------------------------------------------------------------------*/ \*-------------------------------------------------------------------------*/
static int meth_accept(lua_State *L) { static int meth_accept(lua_State *L) {
p_unix server = (p_unix) auxiliar_checkclass(L, "unix{server}", 1); 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 */ /* initialize structure fields */
socket_setnonblocking(&sock); socket_setnonblocking(&sock);
clnt->sock = 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); (p_error) socket_ioerror, &clnt->sock);
timeout_init(&clnt->tm, -1, -1); timeout_init(&clnt->tm, -1, -1);
buffer_init(&clnt->buf, &clnt->io, &clnt->tm); buffer_init(&clnt->buf, &clnt->io, &clnt->tm);
return 1; return 1;
} else { } else {
lua_pushnil(L); lua_pushnil(L);
lua_pushstring(L, socket_strerror(err)); lua_pushstring(L, socket_strerror(err));
return 2; 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) { static const char *unix_trybind(p_unix un, const char *path) {
struct sockaddr_un local; struct sockaddr_un local;
@ -197,16 +181,16 @@ static const char *unix_trybind(p_unix un, const char *path) {
strcpy(local.sun_path, path); strcpy(local.sun_path, path);
local.sun_family = AF_UNIX; local.sun_family = AF_UNIX;
#ifdef UNIX_HAS_SUN_LEN #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; + len + 1;
err = socket_bind(&un->sock, (SA *) &local, local.sun_len); err = socket_bind(&un->sock, (SA *) &local, local.sun_len);
#else #else
err = socket_bind(&un->sock, (SA *) &local, err = socket_bind(&un->sock, (SA *) &local,
sizeof(local.sun_family) + len); sizeof(local.sun_family) + len);
#endif #endif
if (err != IO_DONE) socket_destroy(&un->sock); if (err != IO_DONE) socket_destroy(&un->sock);
return socket_strerror(err); return socket_strerror(err);
} }
static int meth_bind(lua_State *L) { 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; remote.sun_family = AF_UNIX;
timeout_markstart(&un->tm); timeout_markstart(&un->tm);
#ifdef UNIX_HAS_SUN_LEN #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; + len + 1;
err = socket_connect(&un->sock, (SA *) &remote, remote.sun_len, &un->tm); err = socket_connect(&un->sock, (SA *) &remote, remote.sun_len, &un->tm);
#else #else
err = socket_connect(&un->sock, (SA *) &remote, err = socket_connect(&un->sock, (SA *) &remote,
sizeof(remote.sun_family) + len, &un->tm); sizeof(remote.sun_family) + len, &un->tm);
#endif #endif
if (err != IO_DONE) socket_destroy(&un->sock); 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) static int meth_close(lua_State *L)
{ {
@ -319,13 +303,13 @@ static int meth_settimeout(lua_State *L) {
* Library functions * Library functions
\*=========================================================================*/ \*=========================================================================*/
/*-------------------------------------------------------------------------*\ /*-------------------------------------------------------------------------*\
* Creates a master unix object * Creates a master unix object
\*-------------------------------------------------------------------------*/ \*-------------------------------------------------------------------------*/
static int global_create(lua_State *L) { static int global_create(lua_State *L) {
t_socket sock; t_socket sock;
int err = socket_create(&sock, AF_UNIX, SOCK_STREAM, 0); int err = socket_create(&sock, AF_UNIX, SOCK_STREAM, 0);
/* try to allocate a system socket */ /* try to allocate a system socket */
if (err == IO_DONE) { if (err == IO_DONE) {
/* allocate unix object */ /* allocate unix object */
p_unix un = (p_unix) lua_newuserdata(L, sizeof(t_unix)); p_unix un = (p_unix) lua_newuserdata(L, sizeof(t_unix));
/* set its type as master object */ /* set its type as master object */
@ -333,7 +317,7 @@ static int global_create(lua_State *L) {
/* initialize remaining structure fields */ /* initialize remaining structure fields */
socket_setnonblocking(&sock); socket_setnonblocking(&sock);
un->sock = 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); (p_error) socket_ioerror, &un->sock);
timeout_init(&un->tm, -1, -1); timeout_init(&un->tm, -1, -1);
buffer_init(&un->buf, &un->io, &un->tm); buffer_init(&un->buf, &un->io, &un->tm);

View File

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

View File

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