Finished implementation of LuaSocket 2.0 alpha on Linux.

Some testing still needed.
This commit is contained in:
Diego Nehab 2003-06-26 18:47:49 +00:00
parent f330540576
commit 71f6bb60bf
41 changed files with 700 additions and 339 deletions

View file

@ -1,142 +1,167 @@
/*=========================================================================*\
* Auxiliar routines for class hierarchy manipulation
* LuaSocket toolkit
*
* RCS ID: $Id$
\*=========================================================================*/
#include <string.h>
#include "luasocket.h"
#include "auxiliar.h"
/*=========================================================================*\
* Exported functions
\*=========================================================================*/
/*-------------------------------------------------------------------------*\
* Creates a new class. A class has methods given by the func array and the
* field 'class' tells the object class. The table 'group' list the class
* groups the object belongs to.
* Initializes the module
\*-------------------------------------------------------------------------*/
void aux_newclass(lua_State *L, const char *name, luaL_reg *func)
void aux_open(lua_State *L)
{
lua_pushstring(L, name);
/* create namespace table */
lua_pushstring(L, LUASOCKET_LIBNAME);
lua_newtable(L);
lua_pushstring(L, "__index");
lua_newtable(L);
luaL_openlib(L, NULL, func, 0);
lua_pushstring(L, "class");
lua_pushstring(L, name);
lua_rawset(L, -3);
lua_pushstring(L, "group");
lua_newtable(L);
lua_rawset(L, -3);
lua_rawset(L, -3);
lua_rawset(L, LUA_REGISTRYINDEX);
}
/*-------------------------------------------------------------------------*\
* Add group to object list of groups.
\*-------------------------------------------------------------------------*/
void aux_add2group(lua_State *L, const char *name, const char *group)
{
lua_pushstring(L, name);
lua_rawget(L, LUA_REGISTRYINDEX);
lua_pushstring(L, "__index");
lua_rawget(L, -2);
lua_pushstring(L, "group");
lua_rawget(L, -2);
lua_pushstring(L, group);
#ifdef LUASOCKET_DEBUG
lua_pushstring(L, "debug");
lua_pushnumber(L, 1);
lua_rawset(L, -3);
lua_pop(L, 3);
#endif
lua_settable(L, LUA_GLOBALSINDEX);
/* make sure modules know what is our namespace */
lua_pushstring(L, "LUASOCKET_LIBNAME");
lua_pushstring(L, LUASOCKET_LIBNAME);
lua_settable(L, LUA_GLOBALSINDEX);
}
/*-------------------------------------------------------------------------*\
* Get a userdata making sure the object belongs to a given class.
* Creates a new class with given methods
\*-------------------------------------------------------------------------*/
void *aux_checkclass(lua_State *L, const char *name, int objidx)
void aux_newclass(lua_State *L, const char *classname, luaL_reg *func)
{
void *data = aux_getclassudata(L, name, objidx);
luaL_newmetatable(L, classname); /* mt */
lua_pushstring(L, "__index"); /* mt,"__index" */
lua_newtable(L); /* mt,"__index",it */
luaL_openlib(L, NULL, func, 0);
#ifdef LUASOCKET_DEBUG
lua_pushstring(L, "class"); /* mt,"__index",it,"class" */
lua_pushstring(L, classname); /* mt,"__index",it,"class",classname */
lua_rawset(L, -3); /* mt,"__index",it */
#endif
/* get __gc method from class and use it for garbage collection */
lua_pushstring(L, "__gc"); /* mt,"__index",it,"__gc" */
lua_pushstring(L, "__gc"); /* mt,"__index",it,"__gc","__gc" */
lua_rawget(L, -3); /* mt,"__index",it,"__gc",fn */
lua_rawset(L, -5); /* mt,"__index",it */
lua_rawset(L, -3); /* mt */
lua_pop(L, 1);
}
/*-------------------------------------------------------------------------*\
* Insert class into group
\*-------------------------------------------------------------------------*/
void aux_add2group(lua_State *L, const char *classname, const char *groupname)
{
luaL_getmetatable(L, classname);
lua_pushstring(L, groupname);
lua_pushboolean(L, 1);
lua_rawset(L, -3);
lua_pop(L, 1);
}
/*-------------------------------------------------------------------------*\
* Make sure argument is a boolean
\*-------------------------------------------------------------------------*/
int aux_checkboolean(lua_State *L, int objidx)
{
if (!lua_isboolean(L, objidx))
luaL_typerror(L, objidx, lua_typename(L, LUA_TBOOLEAN));
return lua_toboolean(L, objidx);
}
/*-------------------------------------------------------------------------*\
* Calls appropriate option handler
\*-------------------------------------------------------------------------*/
int aux_meth_setoption(lua_State *L, luaL_reg *opt)
{
const char *name = luaL_checkstring(L, 2); /* obj, name, args */
while (opt->name && strcmp(name, opt->name))
opt++;
if (!opt->func) {
char msg[45];
sprintf(msg, "unknown option `%.35s'", name);
luaL_argerror(L, 2, msg);
}
lua_remove(L, 2); /* obj, args */
lua_pushcfunction(L, opt->func); /* obj, args, func */
lua_insert(L, 1); /* func, obj, args */
lua_call(L, lua_gettop(L)-1, LUA_MULTRET);
return lua_gettop(L);
}
/*-------------------------------------------------------------------------*\
* Return userdata pointer if object belongs to a given class, abort with
* error otherwise
\*-------------------------------------------------------------------------*/
void *aux_checkclass(lua_State *L, const char *classname, int objidx)
{
void *data = aux_getclassudata(L, classname, objidx);
if (!data) {
char msg[45];
sprintf(msg, "%.35s expected", name);
sprintf(msg, "%.35s expected", classname);
luaL_argerror(L, objidx, msg);
}
return data;
}
/*-------------------------------------------------------------------------*\
* Get a userdata making sure the object belongs to a given group.
* Return userdata pointer if object belongs to a given group, abort with
* error otherwise
\*-------------------------------------------------------------------------*/
void *aux_checkgroup(lua_State *L, const char *group, int objidx)
void *aux_checkgroup(lua_State *L, const char *groupname, int objidx)
{
void *data = aux_getgroupudata(L, group, objidx);
void *data = aux_getgroupudata(L, groupname, objidx);
if (!data) {
char msg[45];
sprintf(msg, "%.35s expected", group);
sprintf(msg, "%.35s expected", groupname);
luaL_argerror(L, objidx, msg);
}
return data;
}
/*-------------------------------------------------------------------------*\
* Set object class.
* Set object class
\*-------------------------------------------------------------------------*/
void aux_setclass(lua_State *L, const char *name, int objidx)
void aux_setclass(lua_State *L, const char *classname, int objidx)
{
lua_pushstring(L, name);
lua_rawget(L, LUA_REGISTRYINDEX);
luaL_getmetatable(L, classname);
if (objidx < 0) objidx--;
lua_setmetatable(L, objidx);
}
/*=========================================================================*\
* Internal functions
\*=========================================================================*/
/*-------------------------------------------------------------------------*\
* Get a userdata if object belongs to a given group.
* Get a userdata pointer if object belongs to a given group. Return NULL
* otherwise
\*-------------------------------------------------------------------------*/
void *aux_getgroupudata(lua_State *L, const char *group, int objidx)
void *aux_getgroupudata(lua_State *L, const char *groupname, int objidx)
{
if (!lua_getmetatable(L, objidx))
if (!lua_getmetatable(L, objidx))
return NULL;
lua_pushstring(L, "__index");
lua_rawget(L, -2);
if (!lua_istable(L, -1)) {
lua_pop(L, 2);
return NULL;
}
lua_pushstring(L, "group");
lua_rawget(L, -2);
if (!lua_istable(L, -1)) {
lua_pop(L, 3);
return NULL;
}
lua_pushstring(L, group);
lua_pushstring(L, groupname);
lua_rawget(L, -2);
if (lua_isnil(L, -1)) {
lua_pop(L, 4);
lua_pop(L, 2);
return NULL;
} else {
lua_pop(L, 2);
return lua_touserdata(L, objidx);
}
lua_pop(L, 4);
return lua_touserdata(L, objidx);
}
/*-------------------------------------------------------------------------*\
* Get a userdata if object belongs to a given class.
* Get a userdata pointer if object belongs to a given class. Return NULL
* otherwise
\*-------------------------------------------------------------------------*/
void *aux_getclassudata(lua_State *L, const char *group, int objidx)
void *aux_getclassudata(lua_State *L, const char *classname, int objidx)
{
if (!lua_getmetatable(L, objidx))
return NULL;
lua_pushstring(L, "__index");
lua_rawget(L, -2);
if (!lua_istable(L, -1)) {
lua_pop(L, 2);
return NULL;
}
lua_pushstring(L, "class");
lua_rawget(L, -2);
if (lua_isnil(L, -1)) {
lua_pop(L, 3);
return NULL;
}
lua_pop(L, 3);
return lua_touserdata(L, objidx);
return luaL_checkudata(L, objidx, classname);
}

View file

@ -1,22 +1,37 @@
#ifndef AUX_H
#define AUX_H
/*=========================================================================*\
* Auxiliar routines for class hierarchy manipulation
* LuaSocket toolkit
*
* A LuaSocket class is a name associated with Lua metatables. A LuaSocket
* group is a name associated to a class. A class can belong to any number
* of groups. This module provides the functionality to:
*
* - create new classes
* - add classes to groups
* - set the class of object
* - check if an object belongs to a given class or group
*
* LuaSocket class names follow the convention <module>{<class>}. Modules
* can define any number of classes and groups. The module tcp.c, for
* example, defines the classes tcp{master}, tcp{client} and tcp{server} and
* the groups tcp{client, server} and tcp{any}. Module functions can then
* perform type-checking on it's arguments by either class or group.
*
* LuaSocket metatables define the __index metamethod as being a table. This
* table has one field for each method supported by the class. In DEBUG
* mode, it also has one field with the class name.
*
* The mapping from class name to the corresponding metatable and the
* reverse mapping are done using lauxlib.
*
* RCS ID: $Id$
\*=========================================================================*/
#ifndef AUX_H
#define AUX_H
#include <lua.h>
#include <lauxlib.h>
void aux_newclass(lua_State *L, const char *name, luaL_reg *func);
void aux_add2group(lua_State *L, const char *name, const char *group);
void *aux_checkclass(lua_State *L, const char *name, int objidx);
void *aux_checkgroup(lua_State *L, const char *group, int objidx);
void *aux_getclassudata(lua_State *L, const char *group, int objidx);
void *aux_getgroupudata(lua_State *L, const char *group, int objidx);
void aux_setclass(lua_State *L, const char *name, int objidx);
/* min and max macros */
#ifndef MIN
#define MIN(x, y) ((x) < (y) ? x : y)
@ -25,4 +40,15 @@ void aux_setclass(lua_State *L, const char *name, int objidx);
#define MAX(x, y) ((x) > (y) ? x : y)
#endif
#endif
void aux_open(lua_State *L);
void aux_newclass(lua_State *L, const char *classname, luaL_reg *func);
void aux_add2group(lua_State *L, const char *classname, const char *group);
void aux_setclass(lua_State *L, const char *classname, int objidx);
void *aux_checkclass(lua_State *L, const char *classname, int objidx);
void *aux_checkgroup(lua_State *L, const char *groupname, int objidx);
void *aux_getclassudata(lua_State *L, const char *groupname, int objidx);
void *aux_getgroupudata(lua_State *L, const char *groupname, int objidx);
int aux_meth_setoption(lua_State *L, luaL_reg *opt);
int aux_checkboolean(lua_State *L, int objidx);
#endif /* AUX_H */

View file

@ -1,12 +1,12 @@
/*=========================================================================*\
* Buffered input/output routines
* Input/Output interface for Lua programs
* LuaSocket toolkit
*
* RCS ID: $Id$
\*=========================================================================*/
#include <lua.h>
#include <lauxlib.h>
#include "error.h"
#include "auxiliar.h"
#include "buffer.h"
@ -42,7 +42,7 @@ void buf_init(p_buf buf, p_io io, p_tm tm)
}
/*-------------------------------------------------------------------------*\
* Send data through buffered object
* object:send() interface
\*-------------------------------------------------------------------------*/
int buf_meth_send(lua_State *L, p_buf buf)
{
@ -59,7 +59,7 @@ int buf_meth_send(lua_State *L, p_buf buf)
total += sent;
}
lua_pushnumber(L, total);
error_push(L, err);
io_pusherror(L, err);
#ifdef LUASOCKET_DEBUG
/* push time elapsed during operation as the last return value */
lua_pushnumber(L, (tm_gettime() - tm_getstart(tm))/1000.0);
@ -68,7 +68,7 @@ int buf_meth_send(lua_State *L, p_buf buf)
}
/*-------------------------------------------------------------------------*\
* Receive data from a buffered object
* object:receive() interface
\*-------------------------------------------------------------------------*/
int buf_meth_receive(lua_State *L, p_buf buf)
{
@ -101,13 +101,13 @@ int buf_meth_receive(lua_State *L, p_buf buf)
luaL_argcheck(L, 0, arg, "invalid receive pattern");
break;
}
/* raw pattern */
/* get a fixed number of bytes */
} else err = recvraw(L, buf, (size_t) lua_tonumber(L, arg));
}
/* push nil for each pattern after an error */
for ( ; arg <= top; arg++) lua_pushnil(L);
/* last return is an error code */
error_push(L, err);
io_pusherror(L, err);
#ifdef LUASOCKET_DEBUG
/* push time elapsed during operation as the last return value */
lua_pushnumber(L, (tm_gettime() - tm_getstart(tm))/1000.0);
@ -127,9 +127,10 @@ int buf_isempty(p_buf buf)
* Internal functions
\*=========================================================================*/
/*-------------------------------------------------------------------------*\
* Sends a raw block of data through a buffered object.
* Sends a block of data (unbuffered)
\*-------------------------------------------------------------------------*/
static int sendraw(p_buf buf, const char *data, size_t count, size_t *sent)
static
int sendraw(p_buf buf, const char *data, size_t count, size_t *sent)
{
p_io io = buf->io;
p_tm tm = buf->tm;
@ -145,7 +146,7 @@ static int sendraw(p_buf buf, const char *data, size_t count, size_t *sent)
}
/*-------------------------------------------------------------------------*\
* Reads a raw block of data from a buffered object.
* Reads a fixed number of bytes (buffered)
\*-------------------------------------------------------------------------*/
static
int recvraw(lua_State *L, p_buf buf, size_t wanted)
@ -167,7 +168,7 @@ int recvraw(lua_State *L, p_buf buf, size_t wanted)
}
/*-------------------------------------------------------------------------*\
* Reads everything until the connection is closed
* Reads everything until the connection is closed (buffered)
\*-------------------------------------------------------------------------*/
static
int recvall(lua_State *L, p_buf buf)
@ -187,12 +188,12 @@ int recvall(lua_State *L, p_buf buf)
/*-------------------------------------------------------------------------*\
* Reads a line terminated by a CR LF pair or just by a LF. The CR and LF
* are not returned by the function and are discarded from the buffer.
* are not returned by the function and are discarded from the buffer
\*-------------------------------------------------------------------------*/
static
int recvline(lua_State *L, p_buf buf)
{
int err = 0;
int err = IO_DONE;
luaL_Buffer b;
luaL_buffinit(L, &b);
while (err == IO_DONE) {
@ -215,7 +216,8 @@ int recvline(lua_State *L, p_buf buf)
}
/*-------------------------------------------------------------------------*\
* Skips a given number of bytes in read buffer
* Skips a given number of bytes from read buffer. No data is read from the
* transport layer
\*-------------------------------------------------------------------------*/
static
void buf_skip(p_buf buf, size_t count)
@ -227,7 +229,7 @@ void buf_skip(p_buf buf, size_t count)
/*-------------------------------------------------------------------------*\
* Return any data available in buffer, or get more data from transport layer
* if buffer is empty.
* if buffer is empty
\*-------------------------------------------------------------------------*/
static
int buf_get(p_buf buf, const char **data, size_t *count)
@ -245,3 +247,4 @@ int buf_get(p_buf buf, const char **data, size_t *count)
*data = buf->data + buf->first;
return err;
}

View file

@ -1,21 +1,31 @@
#ifndef BUF_H
#define BUF_H
/*=========================================================================*\
* Buffered input/output routines
* Input/Output interface for Lua programs
* LuaSocket toolkit
*
* Line patterns require buffering. Reading one character at a time involves
* too many system calls and is very slow. This module implements the
* LuaSocket interface for input/output on connected objects, as seen by
* Lua programs.
*
* Input is buffered. Output is *not* buffered because there was no simple
* way of making sure the buffered output data would ever be sent.
*
* The module is built on top of the I/O abstraction defined in io.h and the
* timeout management is done with the timeout.h interface.
*
* RCS ID: $Id$
\*=========================================================================*/
#ifndef BUF_H
#define BUF_H
#include <lua.h>
#include "io.h"
#include "timeout.h"
/* buffer size in bytes */
#define BUF_SIZE 8192
/*-------------------------------------------------------------------------*\
* Buffer control structure
\*-------------------------------------------------------------------------*/
/* buffer control structure */
typedef struct t_buf_ {
p_io io; /* IO driver used for this buffer */
p_tm tm; /* timeout management for this buffer */
@ -24,9 +34,6 @@ typedef struct t_buf_ {
} t_buf;
typedef t_buf *p_buf;
/*-------------------------------------------------------------------------*\
* Exported functions
\*-------------------------------------------------------------------------*/
void buf_open(lua_State *L);
void buf_init(p_buf buf, p_io io, p_tm tm);
int buf_meth_send(lua_State *L, p_buf buf);

View file

@ -1,6 +1,6 @@
-----------------------------------------------------------------------------
-- FTP support for the Lua language
-- LuaSocket 1.5 toolkit.
-- LuaSocket toolkit.
-- Author: Diego Nehab
-- Conforming to: RFC 959, LTN7
-- RCS ID: $Id$

View file

@ -1,6 +1,6 @@
-----------------------------------------------------------------------------
-- HTTP/1.1 client support for the Lua language.
-- LuaSocket 1.5 toolkit.
-- LuaSocket toolkit.
-- Author: Diego Nehab
-- Conforming to: RFC 2616, LTN7
-- RCS ID: $Id$

View file

@ -1,8 +1,10 @@
/*=========================================================================*\
* Internet domain functions
* LuaSocket toolkit
*
* RCS ID: $Id$
\*=========================================================================*/
#include <stdio.h>
#include <string.h>
#include <lua.h>
@ -16,7 +18,6 @@
\*=========================================================================*/
static int inet_global_toip(lua_State *L);
static int inet_global_tohostname(lua_State *L);
static void inet_pushresolved(lua_State *L, struct hostent *hp);
static luaL_reg func[] = {
@ -43,11 +44,6 @@ void inet_open(lua_State *L)
/*-------------------------------------------------------------------------*\
* Returns all information provided by the resolver given a host name
* or ip address
* Lua Input: address
* address: ip address or hostname to dns lookup
* Lua Returns
* On success: first IP address followed by a resolved table
* On error: nil, followed by an error message
\*-------------------------------------------------------------------------*/
static int inet_global_toip(lua_State *L)
{
@ -72,11 +68,6 @@ static int inet_global_toip(lua_State *L)
/*-------------------------------------------------------------------------*\
* Returns all information provided by the resolver given a host name
* or ip address
* Lua Input: address
* address: ip address or host name to reverse dns lookup
* Lua Returns
* On success: canonic name followed by a resolved table
* On error: nil, followed by an error message
\*-------------------------------------------------------------------------*/
static int inet_global_tohostname(lua_State *L)
{
@ -102,11 +93,6 @@ static int inet_global_tohostname(lua_State *L)
\*=========================================================================*/
/*-------------------------------------------------------------------------*\
* Retrieves socket peer name
* Input:
* sock: socket
* Lua Returns
* On success: ip address and port of peer
* On error: nil
\*-------------------------------------------------------------------------*/
int inet_meth_getpeername(lua_State *L, p_sock ps)
{
@ -123,11 +109,6 @@ int inet_meth_getpeername(lua_State *L, p_sock ps)
/*-------------------------------------------------------------------------*\
* Retrieves socket local name
* Input:
* sock: socket
* Lua Returns
* On success: local ip address and port
* On error: nil
\*-------------------------------------------------------------------------*/
int inet_meth_getsockname(lua_State *L, p_sock ps)
{
@ -147,8 +128,6 @@ int inet_meth_getsockname(lua_State *L, p_sock ps)
\*=========================================================================*/
/*-------------------------------------------------------------------------*\
* Passes all resolver information to Lua as a table
* Input
* hp: hostent structure returned by resolver
\*-------------------------------------------------------------------------*/
static void inet_pushresolved(lua_State *L, struct hostent *hp)
{
@ -185,12 +164,6 @@ static void inet_pushresolved(lua_State *L, struct hostent *hp)
/*-------------------------------------------------------------------------*\
* Tries to connect to remote address (address, port)
* Input
* ps: pointer to socket
* address: host name or ip address
* port: port number to bind to
* Returns
* NULL in case of success, error message otherwise
\*-------------------------------------------------------------------------*/
const char *inet_tryconnect(p_sock ps, const char *address,
unsigned short port)
@ -224,12 +197,6 @@ const char *inet_tryconnect(p_sock ps, const char *address,
/*-------------------------------------------------------------------------*\
* Tries to bind socket to (address, port)
* Input
* sock: pointer to socket
* address: host name or ip address
* port: port number to bind to
* Returns
* NULL in case of success, error message otherwise
\*-------------------------------------------------------------------------*/
const char *inet_trybind(p_sock ps, const char *address, unsigned short port,
int backlog)
@ -264,10 +231,6 @@ const char *inet_trybind(p_sock ps, const char *address, unsigned short port,
/*-------------------------------------------------------------------------*\
* Tries to create a new inet socket
* Input
* sock: pointer to socket
* Returns
* NULL if successfull, error message on error
\*-------------------------------------------------------------------------*/
const char *inet_trycreate(p_sock ps, int type)
{
@ -299,3 +262,5 @@ int inet_aton(const char *cp, struct in_addr *inp)
return 1;
}
#endif

View file

@ -1,25 +1,30 @@
#ifndef INET_H
#define INET_H
/*=========================================================================*\
* Internet domain functions
* LuaSocket toolkit
*
* This module implements the creation and connection of internet domain
* sockets, on top of the socket.h interface, and the interface of with the
* resolver.
*
* The function inet_aton is provided for the platforms where it is not
* available. The module also implements the interface of the internet
* getpeername and getsockname functions as seen by Lua programs.
*
* The Lua functions toip and tohostname are also implemented here.
*
* RCS ID: $Id$
\*=========================================================================*/
#ifndef INET_H
#define INET_H
#include <lua.h>
#include "socket.h"
/*-------------------------------------------------------------------------*\
* Exported functions
\*-------------------------------------------------------------------------*/
void inet_open(lua_State *L);
const char *inet_tryconnect(p_sock ps, const char *address,
unsigned short port);
const char *inet_trybind(p_sock ps, const char *address,
unsigned short port, int backlog);
const char *inet_trycreate(p_sock ps, int type);
int inet_meth_getpeername(lua_State *L, p_sock ps);
int inet_meth_getsockname(lua_State *L, p_sock ps);
@ -27,4 +32,4 @@ int inet_meth_getsockname(lua_State *L, p_sock ps);
int inet_aton(const char *cp, struct in_addr *inp);
#endif
#endif /* INET_H_ */
#endif /* INET_H */

View file

@ -1,8 +1,48 @@
/*=========================================================================*\
* Input/Output abstraction
* LuaSocket toolkit
*
* RCS ID: $Id$
\*=========================================================================*/
#include "io.h"
/*=========================================================================*\
* Exported functions
\*=========================================================================*/
/*-------------------------------------------------------------------------*\
* Initializes C structure
\*-------------------------------------------------------------------------*/
void io_init(p_io io, p_send send, p_recv recv, void *ctx)
{
io->send = send;
io->recv = recv;
io->ctx = ctx;
}
/*-------------------------------------------------------------------------*\
* Translate error codes to Lua
\*-------------------------------------------------------------------------*/
void io_pusherror(lua_State *L, int code)
{
switch (code) {
case IO_DONE:
lua_pushnil(L);
break;
case IO_TIMEOUT:
lua_pushstring(L, "timeout");
break;
case IO_LIMITED:
lua_pushstring(L, "limited");
break;
case IO_CLOSED:
lua_pushstring(L, "closed");
break;
case IO_REFUSED:
lua_pushstring(L, "refused");
break;
default:
lua_pushstring(L, "unknown error");
break;
}
}

View file

@ -1,16 +1,30 @@
#ifndef IO_H
#define IO_H
/*=========================================================================*\
* Input/Output abstraction
* LuaSocket toolkit
*
* This module defines the interface that LuaSocket expects from the
* transport layer for streamed input/output. The idea is that if any
* transport implements this interface, then the buffer.c functions
* automatically work on it.
*
* The module socket.h implements this interface, and thus the module tcp.h
* is very simple.
*
* RCS ID: $Id$
\*=========================================================================*/
#include <stdio.h>
#include <lua.h>
/* IO error codes */
enum {
IO_DONE, /* operation completed successfully */
IO_TIMEOUT, /* operation timed out */
IO_CLOSED, /* the connection has been closed */
IO_ERROR, /* something wrong... */
IO_REFUSED, /* transfer has been refused */
IO_LIMITED /* maximum number of bytes reached */
IO_DONE, /* operation completed successfully */
IO_TIMEOUT, /* operation timed out */
IO_CLOSED, /* the connection has been closed */
IO_ERROR, /* something wrong... */
IO_REFUSED, /* transfer has been refused */
IO_LIMITED /* maximum number of bytes reached */
};
/* interface to send function */
@ -39,6 +53,7 @@ typedef struct t_io_ {
} t_io;
typedef t_io *p_io;
void io_pusherror(lua_State *L, int code);
void io_init(p_io io, p_send send, p_recv recv, void *ctx);
#endif /* IO_H */

View file

@ -1,4 +1,5 @@
/*=========================================================================*\
* LuaSocket toolkit
* Networking support for the Lua language
* Diego Nehab
* 26/11/1999
@ -7,7 +8,7 @@
* connectivity of the Lua language. The Lua interface to networking
* functions follows the Sockets API closely, trying to simplify all tasks
* involved in setting up both client and server connections. The provided
* IO routines, however, follow the Lua style, being very similar to the
* IO routines, however, follow the Lua style, being very similar to the
* standard Lua read and write functions.
*
* RCS ID: $Id$
@ -24,6 +25,7 @@
\*=========================================================================*/
#include "luasocket.h"
#include "auxiliar.h"
#include "timeout.h"
#include "buffer.h"
#include "socket.h"
@ -38,23 +40,11 @@
/*-------------------------------------------------------------------------*\
* Initializes all library modules.
\*-------------------------------------------------------------------------*/
LUASOCKET_API int luaopen_socketlib(lua_State *L)
LUASOCKET_API int luaopen_socket(lua_State *L)
{
if (!sock_open()) return 0;
/* create namespace table */
lua_pushstring(L, LUASOCKET_LIBNAME);
lua_newtable(L);
#ifdef LUASOCKET_DEBUG
lua_pushstring(L, "debug");
lua_pushnumber(L, 1);
lua_settable(L, -3);
#endif
lua_settable(L, LUA_GLOBALSINDEX);
/* make sure modules know what is our namespace */
lua_pushstring(L, "LUASOCKET_LIBNAME");
lua_pushstring(L, LUASOCKET_LIBNAME);
lua_settable(L, LUA_GLOBALSINDEX);
/* initialize all modules */
aux_open(L);
tm_open(L);
buf_open(L);
inet_open(L);

View file

@ -1,17 +1,19 @@
#ifndef LUASOCKET_H
#define LUASOCKET_H
/*=========================================================================*\
* LuaSocket toolkit
* Networking support for the Lua language
* Diego Nehab
* 9/11/1999
*
* RCS ID: $Id$
\*=========================================================================*/
#ifndef LUASOCKET_H
#define LUASOCKET_H
#include <lua.h>
/*-------------------------------------------------------------------------*\
* Current luasocket version
\*-------------------------------------------------------------------------*/
#define LUASOCKET_VERSION "LuaSocket 1.5 (alpha)"
#define LUASOCKET_VERSION "LuaSocket 2.0 (alpha)"
/*-------------------------------------------------------------------------*\
* Library's namespace
@ -28,6 +30,6 @@
/*-------------------------------------------------------------------------*\
* Initializes the library.
\*-------------------------------------------------------------------------*/
LUASOCKET_API int luaopen_socketlib(lua_State *L);
LUASOCKET_API int luaopen_socket(lua_State *L);
#endif /* LUASOCKET_H */

View file

@ -1,5 +1,7 @@
/*=========================================================================*\
* Select implementation
* LuaSocket toolkit
*
* RCS ID: $Id$
\*=========================================================================*/
#include <string.h>
@ -12,6 +14,9 @@
#include "auxiliar.h"
#include "select.h"
/*=========================================================================*\
* Internal function prototypes.
\*=========================================================================*/
static int meth_set(lua_State *L);
static int meth_isset(lua_State *L);
static int c_select(lua_State *L);
@ -31,6 +36,12 @@ static luaL_reg func[] = {
{NULL, NULL}
};
/*=========================================================================*\
* Internal function prototypes.
\*=========================================================================*/
/*-------------------------------------------------------------------------*\
* Initializes module
\*-------------------------------------------------------------------------*/
void select_open(lua_State *L)
{
/* get select auxiliar lua function from lua code and register
@ -45,6 +56,9 @@ void select_open(lua_State *L)
aux_newclass(L, "select{fd_set}", set);
}
/*=========================================================================*\
* Global Lua functions
\*=========================================================================*/
/*-------------------------------------------------------------------------*\
* Waits for a set of sockets until a condition is met or timeout.
\*-------------------------------------------------------------------------*/
@ -63,10 +77,10 @@ static int global_select(lua_State *L)
lua_pushvalue(L, lua_upvalueindex(1));
lua_insert(L, 1);
/* pass fd_set objects */
read_fd_set = lua_newuserdata(L, sizeof(fd_set));
read_fd_set = (fd_set *) lua_newuserdata(L, sizeof(fd_set));
FD_ZERO(read_fd_set);
aux_setclass(L, "select{fd_set}", -1);
write_fd_set = lua_newuserdata(L, sizeof(fd_set));
write_fd_set = (fd_set *) lua_newuserdata(L, sizeof(fd_set));
FD_ZERO(write_fd_set);
aux_setclass(L, "select{fd_set}", -1);
/* pass select auxiliar C function */
@ -76,20 +90,9 @@ static int global_select(lua_State *L)
return 3;
}
static int c_select(lua_State *L)
{
int max_fd = (int) lua_tonumber(L, 1);
fd_set *read_fd_set = (fd_set *) aux_checkclass(L, "select{fd_set}", 2);
fd_set *write_fd_set = (fd_set *) aux_checkclass(L, "select{fd_set}", 3);
int timeout = lua_isnil(L, 4) ? -1 : (int)(lua_tonumber(L, 4) * 1000);
struct timeval tv;
tv.tv_sec = timeout / 1000;
tv.tv_usec = (timeout % 1000) * 1000;
lua_pushnumber(L, select(max_fd, read_fd_set, write_fd_set, NULL,
timeout < 0 ? NULL : &tv));
return 1;
}
/*=========================================================================*\
* Lua methods
\*=========================================================================*/
static int meth_set(lua_State *L)
{
fd_set *set = (fd_set *) aux_checkclass(L, "select{fd_set}", 1);
@ -107,6 +110,23 @@ static int meth_isset(lua_State *L)
return 1;
}
/*=========================================================================*\
* Internal functions
\*=========================================================================*/
static int c_select(lua_State *L)
{
int max_fd = (int) lua_tonumber(L, 1);
fd_set *read_fd_set = (fd_set *) aux_checkclass(L, "select{fd_set}", 2);
fd_set *write_fd_set = (fd_set *) aux_checkclass(L, "select{fd_set}", 3);
int timeout = lua_isnil(L, 4) ? -1 : (int)(lua_tonumber(L, 4) * 1000);
struct timeval tv;
tv.tv_sec = timeout / 1000;
tv.tv_usec = (timeout % 1000) * 1000;
lua_pushnumber(L, select(max_fd, read_fd_set, write_fd_set, NULL,
timeout < 0 ? NULL : &tv));
return 1;
}
static void check_obj_tab(lua_State *L, int tabidx)
{
if (tabidx < 0) tabidx = lua_gettop(L) + tabidx + 1;

View file

@ -1,9 +1,19 @@
/*=========================================================================*\
* Select implementation
* RCS ID: $Id$
\*=========================================================================*/
#ifndef SELECT_H
#define SELECT_H
/*=========================================================================*\
* Select implementation
* LuaSocket toolkit
*
* To make the code as simple as possible, the select function is
* implemented int Lua, with a few helper functions written in C.
*
* Each object that can be passed to the select function has to be in the
* group select{able} and export two methods: fd() and dirty(). Fd returns
* the descriptor to be passed to the select function. Dirty() should return
* true if there is data ready for reading (required for buffered input).
*
* RCS ID: $Id$
\*=========================================================================*/
void select_open(lua_State *L);

View file

@ -1,6 +1,6 @@
-----------------------------------------------------------------------------
-- SMTP support for the Lua language.
-- LuaSocket 1.5 toolkit
-- LuaSocket toolkit
-- Author: Diego Nehab
-- Conforming to: RFC 821, LTN7
-- RCS ID: $Id$

View file

@ -1,11 +1,16 @@
#ifndef SOCK_H
#define SOCK_H
/*=========================================================================*\
* Socket compatibilization module
* LuaSocket toolkit
*
* BSD Sockets and WinSock are similar, but there are a few irritating
* differences. Also, not all *nix platforms behave the same. This module
* (and the associated usocket.h and wsocket.h) factor these differences and
* creates a interface compatible with the io.h module.
*
* RCS ID: $Id$
\*=========================================================================*/
#ifndef SOCK_H
#define SOCK_H
#include "io.h"
/*=========================================================================*\
@ -32,7 +37,6 @@ int sock_accept(p_sock ps, p_sock pa, SA *addr, socklen_t *addr_len,
const char *sock_connect(p_sock ps, SA *addr, socklen_t addr_len);
const char *sock_bind(p_sock ps, SA *addr, socklen_t addr_len);
void sock_listen(p_sock ps, int backlog);
int sock_send(p_sock ps, const char *data, size_t count,
size_t *sent, int timeout);
int sock_recv(p_sock ps, char *data, size_t count,
@ -41,11 +45,8 @@ int sock_sendto(p_sock ps, const char *data, size_t count,
size_t *sent, SA *addr, socklen_t addr_len, int timeout);
int sock_recvfrom(p_sock ps, char *data, size_t count,
size_t *got, SA *addr, socklen_t *addr_len, int timeout);
void sock_setnonblocking(p_sock ps);
void sock_setblocking(p_sock ps);
void sock_setreuseaddr(p_sock ps);
const char *sock_hoststrerror(void);
const char *sock_createstrerror(void);
const char *sock_bindstrerror(void);

View file

@ -1,5 +1,6 @@
/*=========================================================================*\
* TCP object
* LuaSocket toolkit
*
* RCS ID: $Id$
\*=========================================================================*/
@ -13,7 +14,6 @@
#include "auxiliar.h"
#include "socket.h"
#include "inet.h"
#include "error.h"
#include "tcp.h"
/*=========================================================================*\
@ -28,9 +28,13 @@ static int meth_getpeername(lua_State *L);
static int meth_receive(lua_State *L);
static int meth_accept(lua_State *L);
static int meth_close(lua_State *L);
static int meth_setoption(lua_State *L);
static int meth_timeout(lua_State *L);
static int meth_fd(lua_State *L);
static int meth_dirty(lua_State *L);
static int opt_nodelay(lua_State *L);
static int opt_keepalive(lua_State *L);
static int opt_linger(lua_State *L);
/* tcp object methods */
static luaL_reg tcp[] = {
@ -45,11 +49,21 @@ static luaL_reg tcp[] = {
{"getsockname", meth_getsockname},
{"timeout", meth_timeout},
{"close", meth_close},
{"setoption", meth_setoption},
{"__gc", meth_close},
{"fd", meth_fd},
{"dirty", meth_dirty},
{NULL, NULL}
};
/* socket option handlers */
static luaL_reg opt[] = {
{"keepalive", opt_keepalive},
{"nodelay", opt_nodelay},
{"linger", opt_linger},
{NULL, NULL}
};
/* functions in library namespace */
static luaL_reg func[] = {
{"tcp", global_create},
@ -71,6 +85,7 @@ void tcp_open(lua_State *L)
aux_add2group(L, "tcp{server}", "tcp{any}");
aux_add2group(L, "tcp{client}", "tcp{client, server}");
aux_add2group(L, "tcp{server}", "tcp{client, server}");
/* both server and client objects are selectable */
aux_add2group(L, "tcp{client}", "select{able}");
aux_add2group(L, "tcp{server}", "select{able}");
/* define library functions */
@ -96,19 +111,81 @@ static int meth_receive(lua_State *L)
return buf_meth_receive(L, &tcp->buf);
}
/*-------------------------------------------------------------------------*\
* Option handlers
\*-------------------------------------------------------------------------*/
static int meth_setoption(lua_State *L)
{
return aux_meth_setoption(L, opt);
}
static int opt_boolean(lua_State *L, int level, int name)
{
p_tcp tcp = (p_tcp) aux_checkgroup(L, "tcp{any}", 1);
int val = aux_checkboolean(L, 2);
if (setsockopt(tcp->sock, level, name, (char *) &val, sizeof(val)) < 0) {
lua_pushnil(L);
lua_pushstring(L, "setsockopt failed");
return 2;
}
lua_pushnumber(L, 1);
return 1;
}
/* disables the Nagle algorithm */
static int opt_nodelay(lua_State *L)
{
struct protoent *pe = getprotobyname("TCP");
if (!pe) {
lua_pushnil(L);
lua_pushstring(L, "getprotobyname");
return 2;
}
return opt_boolean(L, pe->p_proto, TCP_NODELAY);
}
static int opt_keepalive(lua_State *L)
{
return opt_boolean(L, SOL_SOCKET, SO_KEEPALIVE);
}
int opt_linger(lua_State *L)
{
p_tcp tcp = (p_tcp) aux_checkclass(L, "tcp{client}", 1);
struct linger li;
if (!lua_istable(L, 2))
luaL_typerror(L, 2, lua_typename(L, LUA_TTABLE));
lua_pushstring(L, "onoff");
lua_gettable(L, 2);
if (!lua_isnumber(L, -1)) luaL_argerror(L, 2, "invalid onoff field");
li.l_onoff = (int) lua_tonumber(L, -1);
lua_pushstring(L, "linger");
lua_gettable(L, 2);
if (!lua_isnumber(L, -1)) luaL_argerror(L, 2, "invalid linger field");
li.l_linger = (int) lua_tonumber(L, -1);
if (setsockopt(tcp->sock, SOL_SOCKET, SO_LINGER,
(char *) &li, sizeof(li) < 0)) {
lua_pushnil(L);
lua_pushstring(L, "setsockopt failed");
return 2;
}
lua_pushnumber(L, 1);
return 1;
}
/*-------------------------------------------------------------------------*\
* Select support methods
\*-------------------------------------------------------------------------*/
static int meth_fd(lua_State *L)
{
p_tcp tcp = (p_tcp) aux_checkclass(L, "tcp{client, server}", 1);
p_tcp tcp = (p_tcp) aux_checkgroup(L, "tcp{client, server}", 1);
lua_pushnumber(L, tcp->sock);
return 1;
}
static int meth_dirty(lua_State *L)
{
p_tcp tcp = (p_tcp) aux_checkclass(L, "tcp{client, server}", 1);
p_tcp tcp = (p_tcp) aux_checkgroup(L, "tcp{client, server}", 1);
lua_pushboolean(L, !buf_isempty(&tcp->buf));
return 1;
}
@ -207,7 +284,7 @@ static int meth_accept(lua_State *L)
if (client->sock == SOCK_INVALID) {
if (tm_get(tm) == 0) {
lua_pushnil(L);
error_push(L, IO_TIMEOUT);
io_pusherror(L, IO_TIMEOUT);
return 2;
}
} else break;

View file

@ -1,6 +1,21 @@
#ifndef TCP_H
#define TCP_H
/*=========================================================================*\
* TCP object
* LuaSocket toolkit
*
* The tcp.h module is basicly a glue that puts together modules buffer.h,
* timeout.h socket.h and inet.h to provide the LuaSocket TCP (AF_INET,
* SOCK_STREAM) support.
*
* Three classes are defined: master, client and server. The master class is
* a newly created tcp object, that has not been bound or connected. Server
* objects are tcp objects bound to some local address. Client objects are
* tcp objects either connected to some address or returned by the accept
* method of a server object.
*
* RCS ID: $Id$
\*=========================================================================*/
#include <lua.h>
#include "buffer.h"
@ -17,4 +32,4 @@ typedef t_tcp *p_tcp;
void tcp_open(lua_State *L);
#endif
#endif /* TCP_H */

View file

@ -1,8 +1,6 @@
/*=========================================================================*\
* Timeout management functions
* Global Lua functions:
* _sleep
* _time
* LuaSocket toolkit
*
* RCS ID: $Id$
\*=========================================================================*/

View file

@ -1,11 +1,11 @@
#ifndef TM_H
#define TM_H
/*=========================================================================*\
* Timeout management functions
* LuaSocket toolkit
*
* RCS ID: $Id$
\*=========================================================================*/
#ifndef TM_H
#define TM_H
#include <lua.h>
/* timeout control structure */
@ -28,4 +28,4 @@ int tm_get(p_tm tm);
int tm_gettime(void);
int tm_meth_timeout(lua_State *L, p_tm tm);
#endif
#endif /* TM_H */

View file

@ -1,5 +1,6 @@
/*=========================================================================*\
* UDP object
* LuaSocket toolkit
*
* RCS ID: $Id$
\*=========================================================================*/
@ -13,7 +14,6 @@
#include "auxiliar.h"
#include "socket.h"
#include "inet.h"
#include "error.h"
#include "udp.h"
/*=========================================================================*\
@ -29,9 +29,12 @@ static int meth_getpeername(lua_State *L);
static int meth_setsockname(lua_State *L);
static int meth_setpeername(lua_State *L);
static int meth_close(lua_State *L);
static int meth_setoption(lua_State *L);
static int meth_timeout(lua_State *L);
static int meth_fd(lua_State *L);
static int meth_dirty(lua_State *L);
static int opt_dontroute(lua_State *L);
static int opt_broadcast(lua_State *L);
/* udp object methods */
static luaL_reg udp[] = {
@ -45,11 +48,20 @@ static luaL_reg udp[] = {
{"receivefrom", meth_receivefrom},
{"timeout", meth_timeout},
{"close", meth_close},
{"setoption", meth_setoption},
{"__gc", meth_close},
{"fd", meth_fd},
{"dirty", meth_dirty},
{NULL, NULL}
};
/* socket options */
static luaL_reg opt[] = {
{"dontroute", opt_dontroute},
{"broadcast", opt_broadcast},
{NULL, NULL}
};
/* functions in library namespace */
static luaL_reg func[] = {
{"udp", global_create},
@ -91,7 +103,9 @@ static int meth_send(lua_State *L)
err = sock_send(&udp->sock, data, count, &sent, tm_get(tm));
if (err == IO_DONE) lua_pushnumber(L, sent);
else lua_pushnil(L);
error_push(L, err);
/* a 'closed' error on an unconnected means the target address was not
* accepted by the transport layer */
io_pusherror(L, err == IO_CLOSED ? IO_REFUSED : err);
return 2;
}
@ -118,7 +132,9 @@ static int meth_sendto(lua_State *L)
(SA *) &addr, sizeof(addr), tm_get(tm));
if (err == IO_DONE) lua_pushnumber(L, sent);
else lua_pushnil(L);
error_push(L, err == IO_CLOSED ? IO_REFUSED : err);
/* a 'closed' error on an unconnected means the target address was not
* accepted by the transport layer */
io_pusherror(L, err == IO_CLOSED ? IO_REFUSED : err);
return 2;
}
@ -137,7 +153,7 @@ static int meth_receive(lua_State *L)
err = sock_recv(&udp->sock, buffer, count, &got, tm_get(tm));
if (err == IO_DONE) lua_pushlstring(L, buffer, got);
else lua_pushnil(L);
error_push(L, err);
io_pusherror(L, err);
return 2;
}
@ -164,7 +180,7 @@ static int meth_receivefrom(lua_State *L)
return 3;
} else {
lua_pushnil(L);
error_push(L, err);
io_pusherror(L, err);
return 2;
}
}
@ -174,14 +190,14 @@ static int meth_receivefrom(lua_State *L)
\*-------------------------------------------------------------------------*/
static int meth_fd(lua_State *L)
{
p_udp udp = (p_udp) aux_checkclass(L, "udp{any}", 1);
p_udp udp = (p_udp) aux_checkgroup(L, "udp{any}", 1);
lua_pushnumber(L, udp->sock);
return 1;
}
static int meth_dirty(lua_State *L)
{
p_udp udp = (p_udp) aux_checkclass(L, "udp{any}", 1);
p_udp udp = (p_udp) aux_checkgroup(L, "udp{any}", 1);
(void) udp;
lua_pushboolean(L, 0);
return 1;
@ -202,6 +218,37 @@ static int meth_getsockname(lua_State *L)
return inet_meth_getsockname(L, &udp->sock);
}
/*-------------------------------------------------------------------------*\
* Option handlers
\*-------------------------------------------------------------------------*/
static int meth_setoption(lua_State *L)
{
return aux_meth_setoption(L, opt);
}
static int opt_boolean(lua_State *L, int level, int name)
{
p_udp udp = (p_udp) aux_checkgroup(L, "udp{any}", 1);
int val = aux_checkboolean(L, 2);
if (setsockopt(udp->sock, level, name, (char *) &val, sizeof(val)) < 0) {
lua_pushnil(L);
lua_pushstring(L, "setsockopt failed");
return 2;
}
lua_pushnumber(L, 1);
return 1;
}
static int opt_dontroute(lua_State *L)
{
return opt_boolean(L, SOL_SOCKET, SO_DONTROUTE);
}
static int opt_broadcast(lua_State *L)
{
return opt_boolean(L, SOL_SOCKET, SO_BROADCAST);
}
/*-------------------------------------------------------------------------*\
* Just call tm methods
\*-------------------------------------------------------------------------*/

View file

@ -1,6 +1,19 @@
#ifndef UDP_H
#define UDP_H
/*=========================================================================*\
* UDP object
* LuaSocket toolkit
*
* The udp.h module provides LuaSocket with support for UDP protocol
* (AF_INET, SOCK_DGRAM).
*
* Two classes are defined: connected and unconnected. UDP objects are
* originally unconnected. They can be "connected" to a given address
* with a call to the setpeername function. The same function can be used to
* break the connection.
*
* RCS ID: $Id$
\*=========================================================================*/
#include <lua.h>
#include "timeout.h"
@ -16,4 +29,4 @@ typedef t_udp *p_udp;
void udp_open(lua_State *L);
#endif
#endif /* UDP_H */

View file

@ -1,6 +1,6 @@
-----------------------------------------------------------------------------
-- URI parsing, composition and relative URL resolution
-- LuaSocket 1.5 toolkit.
-- LuaSocket toolkit.
-- Author: Diego Nehab
-- Conforming to: RFC 2396, LTN7
-- RCS ID: $Id$

View file

@ -1,49 +1,78 @@
/*=========================================================================*\
* Socket compatibilization module for Unix
* LuaSocket toolkit
*
* RCS ID: $Id$
\*=========================================================================*/
#include <string.h>
#include "socket.h"
/*-------------------------------------------------------------------------*\
* Initializes module
\*-------------------------------------------------------------------------*/
int sock_open(void)
{
/* instals a handler to ignore sigpipe. */
struct sigaction new;
memset(&new, 0, sizeof(new));
new.sa_handler = SIG_IGN;
sigaction(SIGPIPE, &new, NULL);
/* instals a handler to ignore sigpipe or it will crash us */
struct sigaction ignore;
memset(&ignore, 0, sizeof(ignore));
ignore.sa_handler = SIG_IGN;
sigaction(SIGPIPE, &ignore, NULL);
return 1;
}
/*-------------------------------------------------------------------------*\
* Close and inutilize socket
\*-------------------------------------------------------------------------*/
void sock_destroy(p_sock ps)
{
close(*ps);
*ps = SOCK_INVALID;
}
/*-------------------------------------------------------------------------*\
* Creates and sets up a socket
\*-------------------------------------------------------------------------*/
const char *sock_create(p_sock ps, int domain, int type, int protocol)
{
int val = 1;
t_sock sock = socket(domain, type, protocol);
if (sock == SOCK_INVALID) return sock_createstrerror();
*ps = sock;
sock_setnonblocking(ps);
sock_setreuseaddr(ps);
setsockopt(*ps, SOL_SOCKET, SO_REUSEADDR, (char *) &val, sizeof(val));
return NULL;
}
/*-------------------------------------------------------------------------*\
* Connects or returns error message
\*-------------------------------------------------------------------------*/
const char *sock_connect(p_sock ps, SA *addr, socklen_t addr_len)
{
if (connect(*ps, addr, addr_len) < 0) return sock_connectstrerror();
else return NULL;
}
/*-------------------------------------------------------------------------*\
* Binds or returns error message
\*-------------------------------------------------------------------------*/
const char *sock_bind(p_sock ps, SA *addr, socklen_t addr_len)
{
if (bind(*ps, addr, addr_len) < 0) return sock_bindstrerror();
else return NULL;
}
/*-------------------------------------------------------------------------*\
*
\*-------------------------------------------------------------------------*/
void sock_listen(p_sock ps, int backlog)
{
listen(*ps, backlog);
}
/*-------------------------------------------------------------------------*\
* Accept with timeout
\*-------------------------------------------------------------------------*/
int sock_accept(p_sock ps, p_sock pa, SA *addr, socklen_t *addr_len,
int timeout)
{
@ -65,6 +94,9 @@ int sock_accept(p_sock ps, p_sock pa, SA *addr, socklen_t *addr_len,
else return IO_DONE;
}
/*-------------------------------------------------------------------------*\
* Send with timeout
\*-------------------------------------------------------------------------*/
int sock_send(p_sock ps, const char *data, size_t count, size_t *sent,
int timeout)
{
@ -99,6 +131,9 @@ int sock_send(p_sock ps, const char *data, size_t count, size_t *sent,
}
}
/*-------------------------------------------------------------------------*\
* Sendto with timeout
\*-------------------------------------------------------------------------*/
int sock_sendto(p_sock ps, const char *data, size_t count, size_t *sent,
SA *addr, socklen_t addr_len, int timeout)
{
@ -133,6 +168,9 @@ int sock_sendto(p_sock ps, const char *data, size_t count, size_t *sent,
}
}
/*-------------------------------------------------------------------------*\
* Receive with timeout
\*-------------------------------------------------------------------------*/
int sock_recv(p_sock ps, char *data, size_t count, size_t *got, int timeout)
{
t_sock sock = *ps;
@ -160,6 +198,9 @@ int sock_recv(p_sock ps, char *data, size_t count, size_t *got, int timeout)
}
}
/*-------------------------------------------------------------------------*\
* Recvfrom with timeout
\*-------------------------------------------------------------------------*/
int sock_recvfrom(p_sock ps, char *data, size_t count, size_t *got,
SA *addr, socklen_t *addr_len, int timeout)
{
@ -188,6 +229,29 @@ int sock_recvfrom(p_sock ps, char *data, size_t count, size_t *got,
}
}
/*-------------------------------------------------------------------------*\
* Put socket into blocking mode
\*-------------------------------------------------------------------------*/
void sock_setblocking(p_sock ps)
{
int flags = fcntl(*ps, F_GETFL, 0);
flags &= (~(O_NONBLOCK));
fcntl(*ps, F_SETFL, flags);
}
/*-------------------------------------------------------------------------*\
* Put socket into non-blocking mode
\*-------------------------------------------------------------------------*/
void sock_setnonblocking(p_sock ps)
{
int flags = fcntl(*ps, F_GETFL, 0);
flags |= O_NONBLOCK;
fcntl(*ps, F_SETFL, flags);
}
/*-------------------------------------------------------------------------*\
* Error translation functions
\*-------------------------------------------------------------------------*/
const char *sock_hoststrerror(void)
{
switch (h_errno) {
@ -238,23 +302,3 @@ const char *sock_connectstrerror(void)
default: return "unknown error";
}
}
void sock_setreuseaddr(p_sock ps)
{
int val = 1;
setsockopt(*ps, SOL_SOCKET, SO_REUSEADDR, (char *)&val, sizeof(val));
}
void sock_setblocking(p_sock ps)
{
int flags = fcntl(*ps, F_GETFL, 0);
flags &= (~(O_NONBLOCK));
fcntl(*ps, F_SETFL, flags);
}
void sock_setnonblocking(p_sock ps)
{
int flags = fcntl(*ps, F_GETFL, 0);
flags |= O_NONBLOCK;
fcntl(*ps, F_SETFL, flags);
}

View file

@ -1,10 +1,11 @@
#ifndef USOCKET_H
#define USOCKET_H
/*=========================================================================*\
* Socket compatibilization module for Unix
* LuaSocket toolkit
*
* RCS ID: $Id$
\*=========================================================================*/
#ifndef USOCKET_H
#define USOCKET_H
/*=========================================================================*\
* BSD include files
@ -30,9 +31,11 @@
/* IP stuff*/
#include <netinet/in.h>
#include <arpa/inet.h>
/* TCP options (nagle algorithm disable) */
#include <netinet/tcp.h>
#ifdef __APPLE__
/* for some reason socklen_t is not defined in mac os x */
/* for some reason socklen_t is not defined in Mac Os X */
typedef int socklen_t;
#endif

View file

@ -1,14 +1,21 @@
/*=========================================================================*\
* Socket compatibilization module for Win32
* LuaSocket toolkit
*
* RCS ID: $Id$
\*=========================================================================*/
#include <string.h>
#include "socket.h"
/*-------------------------------------------------------------------------*\
* Initializes module
\*-------------------------------------------------------------------------*/
int sock_open(void)
{
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD(2, 0);
err = WSAStartup(wVersionRequested, &wsaData );
WORD wVersionRequested = MAKEWORD(2, 0);
int err = WSAStartup(wVersionRequested, &wsaData );
if (err != 0) return 0;
if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 0) {
WSACleanup();
@ -17,38 +24,58 @@ int sock_open(void)
return 1;
}
/*-------------------------------------------------------------------------*\
* Close and inutilize socket
\*-------------------------------------------------------------------------*/
void sock_destroy(p_sock ps)
{
closesocket(*ps);
*ps = SOCK_INVALID;
}
/*-------------------------------------------------------------------------*\
* Creates and sets up a socket
\*-------------------------------------------------------------------------*/
const char *sock_create(p_sock ps, int domain, int type, int protocol)
{
int val = 1;
t_sock sock = socket(domain, type, protocol);
if (sock == SOCK_INVALID) return sock_createstrerror();
*ps = sock;
sock_setnonblocking(ps);
sock_setreuseaddr(ps);
setsockopt(*ps, SOL_SOCKET, SO_REUSEADDR, (char *) &val, sizeof(val));
return NULL;
}
/*-------------------------------------------------------------------------*\
* Connects or returns error message
\*-------------------------------------------------------------------------*/
const char *sock_connect(p_sock ps, SA *addr, socklen_t addr_len)
{
if (connect(*ps, addr, addr_len) < 0) return sock_connectstrerror();
else return NULL;
}
/*-------------------------------------------------------------------------*\
* Binds or returns error message
\*-------------------------------------------------------------------------*/
const char *sock_bind(p_sock ps, SA *addr, socklen_t addr_len)
{
if (bind(*ps, addr, addr_len) < 0) return sock_bindstrerror();
else return NULL;
}
/*-------------------------------------------------------------------------*\
*
\*-------------------------------------------------------------------------*/
void sock_listen(p_sock ps, int backlog)
{
listen(*ps, backlog);
}
/*-------------------------------------------------------------------------*\
* Accept with timeout
\*-------------------------------------------------------------------------*/
int sock_accept(p_sock ps, p_sock pa, SA *addr, socklen_t *addr_len,
int timeout)
{
@ -70,6 +97,9 @@ int sock_accept(p_sock ps, p_sock pa, SA *addr, socklen_t *addr_len,
else return IO_DONE;
}
/*-------------------------------------------------------------------------*\
* Send with timeout
\*-------------------------------------------------------------------------*/
int sock_send(p_sock ps, const char *data, size_t count, size_t *sent,
int timeout)
{
@ -104,6 +134,9 @@ int sock_send(p_sock ps, const char *data, size_t count, size_t *sent,
}
}
/*-------------------------------------------------------------------------*\
* Sendto with timeout
\*-------------------------------------------------------------------------*/
int sock_sendto(p_sock ps, const char *data, size_t count, size_t *sent,
SA *addr, socklen_t addr_len, int timeout)
{
@ -138,6 +171,9 @@ int sock_sendto(p_sock ps, const char *data, size_t count, size_t *sent,
}
}
/*-------------------------------------------------------------------------*\
* Receive with timeout
\*-------------------------------------------------------------------------*/
int sock_recv(p_sock ps, char *data, size_t count, size_t *got, int timeout)
{
t_sock sock = *ps;
@ -165,6 +201,9 @@ int sock_recv(p_sock ps, char *data, size_t count, size_t *got, int timeout)
}
}
/*-------------------------------------------------------------------------*\
* Recvfrom with timeout
\*-------------------------------------------------------------------------*/
int sock_recvfrom(p_sock ps, char *data, size_t count, size_t *got,
SA *addr, socklen_t *addr_len, int timeout)
{
@ -193,6 +232,27 @@ int sock_recvfrom(p_sock ps, char *data, size_t count, size_t *got,
}
}
/*-------------------------------------------------------------------------*\
* Put socket into blocking mode
\*-------------------------------------------------------------------------*/
void sock_setblocking(p_sock ps)
{
u_long argp = 0;
ioctlsocket(*ps, FIONBIO, &argp);
}
/*-------------------------------------------------------------------------*\
* Put socket into non-blocking mode
\*-------------------------------------------------------------------------*/
void sock_setnonblocking(p_sock ps)
{
u_long argp = 1;
ioctlsocket(*ps, FIONBIO, &argp);
}
/*-------------------------------------------------------------------------*\
* Error translation functions
\*-------------------------------------------------------------------------*/
const char *sock_hoststrerror(void)
{
switch (WSAGetLastError()) {
@ -241,21 +301,3 @@ const char *sock_connectstrerror(void)
default: return "unknown error";
}
}
void sock_setreuseaddr(p_sock ps)
{
int val = 1;
setsockopt(*ps, SOL_SOCKET, SO_REUSEADDR, (char *)&val, sizeof(val));
}
void sock_setblocking(p_sock ps)
{
u_long argp = 0;
ioctlsocket(*ps, FIONBIO, &argp);
}
void sock_setnonblocking(p_sock ps)
{
u_long argp = 1;
ioctlsocket(*ps, FIONBIO, &argp);
}

View file

@ -1,16 +1,16 @@
#ifndef WSOCKET_H
#define WSOCKET_H
/*=========================================================================*\
* Socket compatibilization module for Win32
* LuaSocket toolkit
*
* RCS ID: $Id$
\*=========================================================================*/
#ifndef WSOCKET_H
#define WSOCKET_H
/*=========================================================================*\
* WinSock2 include files
* WinSock include files
\*=========================================================================*/
#include <winsock2.h>
#include <winbase.h>
#include <winsock.h>
typedef int socklen_t;
typedef int ssize_t;