mirror of
https://github.com/lunarmodules/luasocket.git
synced 2024-12-25 20:18:21 +01:00
Finished implementation of LuaSocket 2.0 alpha on Linux.
Some testing still needed.
This commit is contained in:
parent
f330540576
commit
71f6bb60bf
4
NEW
4
NEW
@ -8,7 +8,9 @@ a given domain/family and protocol. Then connect or bind if needed. Then
|
||||
use IO functions.
|
||||
|
||||
All functions return a non-nil value as first return value if successful.
|
||||
All functions return nil followed by error message in case of error.
|
||||
All functions return whatever could be retrieved followed by error message
|
||||
in case of error. The best way to check for errors is to check for the
|
||||
presence of an error message.
|
||||
WARNING: The send function was affected.
|
||||
|
||||
Better error messages and parameter checking.
|
||||
|
26
TODO
26
TODO
@ -1,24 +1,26 @@
|
||||
- Melhorar a interface de setoptions (aceitar nada como true, por exemplo)
|
||||
- Inicializaccao das classes pode falhar?
|
||||
- Ajeitar melhor a hierarquia de classes. Ajeitar o file...
|
||||
- GARBAGE COLLECTOR!
|
||||
- Adicionar um método sock:setoption???
|
||||
- testar em várias plataformas
|
||||
- adicionar exemplos de expansão: pipe, local, named pipe
|
||||
|
||||
* Como mostrar um erro em lua_socketlibopen()...
|
||||
* O location do "redirect" pode ser relativo ao servidor atual (não pode,
|
||||
mas os servidores fazem merda...)
|
||||
* - Ajeitar para Lua 4.1
|
||||
* Ajeitar para Lua 5.0
|
||||
* Padronizar os retornos de funccao
|
||||
* Separar as classes em arquivos
|
||||
* Retorno de sendto em datagram sockets pode ser refused
|
||||
* Fazer compilar com g++
|
||||
|
||||
- Padronizar os retornos de funccao
|
||||
- Thread-safe
|
||||
- proteger gethostby*.* com um mutex GLOBAL!
|
||||
- proteger o atomizar o conjunto (timedout, receive), (timedout, send)
|
||||
- Usar "require" nos módulos
|
||||
- proteger ou atomizar o conjunto (timedout, receive), (timedout, send)
|
||||
- inet_ntoa também é uma merda.
|
||||
- SSL
|
||||
- Fazer compilar com g++
|
||||
- usar lua_verror
|
||||
- separar as classes em arquivos
|
||||
- criar mais uma classe, a de stream, entre p_sock e p_client
|
||||
- criar um internal include file ls.h
|
||||
- impedir que voe quando chamar accept(udpsocket())
|
||||
- trocar recv and send por read e write (ver se funciona)
|
||||
- Proxy support pro http
|
||||
|
||||
- checar operações em closed sockets
|
||||
- checar teste de writable socket com select
|
||||
@ -34,6 +36,4 @@
|
||||
- unix 92 bytes maximo no endereço, incluindo o zero
|
||||
- unix 9216 maximo de datagram size
|
||||
|
||||
- retorno de send/receive em datagram sockets pode ser refused...
|
||||
|
||||
- adicionar um método sock:setoption???
|
||||
|
@ -1,6 +1,6 @@
|
||||
-----------------------------------------------------------------------------
|
||||
-- Little program that checks links in HTML files
|
||||
-- LuaSocket 1.5 sample files.
|
||||
-- LuaSocket sample files
|
||||
-- Author: Diego Nehab
|
||||
-- RCS ID: $Id$
|
||||
-----------------------------------------------------------------------------
|
||||
|
@ -1,6 +1,6 @@
|
||||
-----------------------------------------------------------------------------
|
||||
-- Little program to download DICT word definitions
|
||||
-- LuaSocket 1.5 sample files
|
||||
-- LuaSocket sample files
|
||||
-- Author: Diego Nehab
|
||||
-- RCS ID: $Id$
|
||||
-----------------------------------------------------------------------------
|
||||
|
@ -1,6 +1,6 @@
|
||||
-----------------------------------------------------------------------------
|
||||
-- Little program to download files from URLs
|
||||
-- LuaSocket 1.5 sample files
|
||||
-- LuaSocket sample files
|
||||
-- Author: Diego Nehab
|
||||
-- RCS ID: $Id$
|
||||
-----------------------------------------------------------------------------
|
||||
|
@ -1,6 +1,6 @@
|
||||
-----------------------------------------------------------------------------
|
||||
-- TFTP support for the Lua language
|
||||
-- LuaSocket 1.5 toolkit.
|
||||
-- LuaSocket toolkit.
|
||||
-- Author: Diego Nehab
|
||||
-- Conforming to: RFC 783, LTN7
|
||||
-- RCS ID: $Id$
|
||||
|
@ -1,6 +1,6 @@
|
||||
-----------------------------------------------------------------------------
|
||||
-- UDP sample: daytime protocol client
|
||||
-- LuaSocket 1.5 sample files.
|
||||
-- LuaSocket sample files
|
||||
-- Author: Diego Nehab
|
||||
-- RCS ID: $Id$
|
||||
-----------------------------------------------------------------------------
|
||||
|
@ -1,6 +1,6 @@
|
||||
-----------------------------------------------------------------------------
|
||||
-- UDP sample: echo protocol client
|
||||
-- LuaSocket 1.5 sample files
|
||||
-- LuaSocket sample files
|
||||
-- Author: Diego Nehab
|
||||
-- RCS ID: $Id$
|
||||
-----------------------------------------------------------------------------
|
||||
|
@ -1,6 +1,6 @@
|
||||
-----------------------------------------------------------------------------
|
||||
-- UDP sample: echo protocol server
|
||||
-- LuaSocket 1.5 sample files
|
||||
-- LuaSocket sample files
|
||||
-- Author: Diego Nehab
|
||||
-- RCS ID: $Id$
|
||||
-----------------------------------------------------------------------------
|
||||
|
@ -1,6 +1,6 @@
|
||||
-----------------------------------------------------------------------------
|
||||
-- TCP sample: Little program to dump lines received at a given port
|
||||
-- LuaSocket 1.5 sample files
|
||||
-- LuaSocket sample files
|
||||
-- Author: Diego Nehab
|
||||
-- RCS ID: $Id$
|
||||
-----------------------------------------------------------------------------
|
||||
|
@ -1,6 +1,6 @@
|
||||
-----------------------------------------------------------------------------
|
||||
-- TCP sample: Little program to send text lines to a given host/port
|
||||
-- LuaSocket 1.5 sample files
|
||||
-- LuaSocket sample files
|
||||
-- Author: Diego Nehab
|
||||
-- RCS ID: $Id$
|
||||
-----------------------------------------------------------------------------
|
||||
|
@ -1,6 +1,6 @@
|
||||
-----------------------------------------------------------------------------
|
||||
-- Select sample: simple text line server
|
||||
-- LuaSocket 1.5 sample files.
|
||||
-- LuaSocket sample files.
|
||||
-- Author: Diego Nehab
|
||||
-- RCS ID: $Id$
|
||||
-----------------------------------------------------------------------------
|
||||
|
191
src/auxiliar.c
191
src/auxiliar.c
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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 */
|
||||
|
33
src/buffer.c
33
src/buffer.c
@ -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;
|
||||
}
|
||||
|
||||
|
27
src/buffer.h
27
src/buffer.h
@ -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);
|
||||
|
@ -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$
|
||||
|
@ -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$
|
||||
|
43
src/inet.c
43
src/inet.c
@ -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
|
||||
|
||||
|
||||
|
23
src/inet.h
23
src/inet.h
@ -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 */
|
||||
|
40
src/io.c
40
src/io.c
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
29
src/io.h
29
src/io.h
@ -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 */
|
||||
|
@ -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);
|
||||
|
@ -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 */
|
||||
|
52
src/select.c
52
src/select.c
@ -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;
|
||||
|
18
src/select.h
18
src/select.h
@ -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);
|
||||
|
||||
|
@ -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$
|
||||
|
15
src/socket.h
15
src/socket.h
@ -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);
|
||||
|
85
src/tcp.c
85
src/tcp.c
@ -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;
|
||||
|
19
src/tcp.h
19
src/tcp.h
@ -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 */
|
||||
|
@ -1,8 +1,6 @@
|
||||
/*=========================================================================*\
|
||||
* Timeout management functions
|
||||
* Global Lua functions:
|
||||
* _sleep
|
||||
* _time
|
||||
* LuaSocket toolkit
|
||||
*
|
||||
* RCS ID: $Id$
|
||||
\*=========================================================================*/
|
||||
|
@ -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 */
|
||||
|
61
src/udp.c
61
src/udp.c
@ -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
|
||||
\*-------------------------------------------------------------------------*/
|
||||
|
17
src/udp.h
17
src/udp.h
@ -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 */
|
||||
|
@ -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$
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -17,12 +17,14 @@ function warn(...)
|
||||
io.write("WARNING: ", s, "\n")
|
||||
end
|
||||
|
||||
pad = string.rep(" ", 8192)
|
||||
|
||||
function remote(...)
|
||||
local s = string.format(unpack(arg))
|
||||
s = string.gsub(s, "\n", ";")
|
||||
s = string.gsub(s, "%s+", " ")
|
||||
s = string.gsub(s, "^%s*", "")
|
||||
control:send(s, "\n")
|
||||
control:send(pad, s, "\n")
|
||||
control:receive()
|
||||
end
|
||||
|
||||
@ -82,16 +84,19 @@ function reconnect()
|
||||
remote [[
|
||||
if data then data:close() data = nil end
|
||||
data = server:accept()
|
||||
data:setoption("nodelay", true)
|
||||
]]
|
||||
data, err = socket.connect(host, port)
|
||||
if not data then fail(err)
|
||||
else pass("connected!") end
|
||||
data:setoption("nodelay", true)
|
||||
end
|
||||
|
||||
pass("attempting control connection...")
|
||||
control, err = socket.connect(host, port)
|
||||
if err then fail(err)
|
||||
else pass("connected!") end
|
||||
control:setoption("nodelay", true)
|
||||
|
||||
------------------------------------------------------------------------
|
||||
test("method registration")
|
||||
@ -157,16 +162,21 @@ remote "data:send(str); data:close()"
|
||||
end
|
||||
|
||||
|
||||
test_mixed(1)
|
||||
test_mixed(17)
|
||||
test_mixed(200)
|
||||
test_mixed(4091)
|
||||
test_mixed(80199)
|
||||
test_mixed(4091)
|
||||
test_mixed(200)
|
||||
test_mixed(17)
|
||||
test_mixed(1)
|
||||
--test_mixed(1)
|
||||
--test_mixed(17)
|
||||
--test_mixed(200)
|
||||
--test_mixed(4091)
|
||||
--test_mixed(80199)
|
||||
--test_mixed(4091)
|
||||
--test_mixed(200)
|
||||
--test_mixed(17)
|
||||
--test_mixed(1)
|
||||
|
||||
test_mixed(4091)
|
||||
test_mixed(4091)
|
||||
test_mixed(4091)
|
||||
test_mixed(4091)
|
||||
test_mixed(4091)
|
||||
------------------------------------------------------------------------
|
||||
test("character line")
|
||||
reconnect()
|
||||
|
@ -3,9 +3,11 @@ port = port or "8080"
|
||||
|
||||
server, error = socket.bind(host, port)
|
||||
if not server then print("server: " .. tostring(error)) os.exit() end
|
||||
ack = "\n"
|
||||
while 1 do
|
||||
print("server: waiting for client connection...");
|
||||
control = server:accept()
|
||||
control:setoption("nodelay", true)
|
||||
while 1 do
|
||||
command, error = control:receive()
|
||||
if error then
|
||||
@ -13,13 +15,12 @@ while 1 do
|
||||
print("server: closing connection...")
|
||||
break
|
||||
end
|
||||
sent, error = control:send("\n")
|
||||
sent, error = control:send(ack)
|
||||
if error then
|
||||
control:close()
|
||||
print("server: closing connection...")
|
||||
break
|
||||
end
|
||||
print(command);
|
||||
(loadstring(command))()
|
||||
end
|
||||
end
|
||||
|
Loading…
Reference in New Issue
Block a user