aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDiego Nehab <diego@tecgraf.puc-rio.br>2003-06-26 18:47:49 +0000
committerDiego Nehab <diego@tecgraf.puc-rio.br>2003-06-26 18:47:49 +0000
commit71f6bb60bf2b7457091c7106190f92ab7e51f7c6 (patch)
tree8ad3668667bd3da3c34f7ff7ae0a9a7a4daa4679
parentf330540576031528f0daac231c61d4dd06e8ba1e (diff)
downloadluasocket-71f6bb60bf2b7457091c7106190f92ab7e51f7c6.tar.gz
luasocket-71f6bb60bf2b7457091c7106190f92ab7e51f7c6.tar.bz2
luasocket-71f6bb60bf2b7457091c7106190f92ab7e51f7c6.zip
Finished implementation of LuaSocket 2.0 alpha on Linux.
Some testing still needed.
-rw-r--r--NEW4
-rw-r--r--TODO26
-rw-r--r--etc/check-links.lua2
-rw-r--r--etc/dict.lua2
-rw-r--r--etc/get.lua2
-rw-r--r--etc/tftp.lua2
-rw-r--r--samples/daytimeclnt.lua2
-rw-r--r--samples/echoclnt.lua2
-rw-r--r--samples/echosrvr.lua2
-rw-r--r--samples/listener.lua2
-rw-r--r--samples/talker.lua2
-rw-r--r--samples/tinyirc.lua2
-rw-r--r--src/auxiliar.c181
-rw-r--r--src/auxiliar.h48
-rw-r--r--src/buffer.c33
-rw-r--r--src/buffer.h27
-rw-r--r--src/ftp.lua2
-rw-r--r--src/http.lua2
-rw-r--r--src/inet.c43
-rw-r--r--src/inet.h23
-rw-r--r--src/io.c40
-rw-r--r--src/io.h29
-rw-r--r--src/luasocket.c20
-rw-r--r--src/luasocket.h10
-rw-r--r--src/select.c52
-rw-r--r--src/select.h14
-rw-r--r--src/smtp.lua2
-rw-r--r--src/socket.h15
-rw-r--r--src/tcp.c85
-rw-r--r--src/tcp.h19
-rw-r--r--src/timeout.c4
-rw-r--r--src/timeout.h8
-rw-r--r--src/udp.c61
-rw-r--r--src/udp.h17
-rw-r--r--src/url.lua2
-rw-r--r--src/usocket.c96
-rw-r--r--src/usocket.h9
-rw-r--r--src/wsocket.c88
-rw-r--r--src/wsocket.h10
-rw-r--r--test/testclnt.lua28
-rw-r--r--test/testsrvr.lua5
41 files changed, 692 insertions, 331 deletions
diff --git a/NEW b/NEW
index 879f12c..e5efc97 100644
--- a/NEW
+++ b/NEW
@@ -8,7 +8,9 @@ a given domain/family and protocol. Then connect or bind if needed. Then
8use IO functions. 8use IO functions.
9 9
10All functions return a non-nil value as first return value if successful. 10All functions return a non-nil value as first return value if successful.
11All functions return nil followed by error message in case of error. 11All functions return whatever could be retrieved followed by error message
12in case of error. The best way to check for errors is to check for the
13presence of an error message.
12WARNING: The send function was affected. 14WARNING: The send function was affected.
13 15
14Better error messages and parameter checking. 16Better error messages and parameter checking.
diff --git a/TODO b/TODO
index 25d2586..5c2492d 100644
--- a/TODO
+++ b/TODO
@@ -1,24 +1,26 @@
1- Melhorar a interface de setoptions (aceitar nada como true, por exemplo)
1- Inicializaccao das classes pode falhar? 2- Inicializaccao das classes pode falhar?
2- Ajeitar melhor a hierarquia de classes. Ajeitar o file... 3- Ajeitar melhor a hierarquia de classes. Ajeitar o file...
4- GARBAGE COLLECTOR!
5- Adicionar um método sock:setoption???
6- testar em várias plataformas
7- adicionar exemplos de expansão: pipe, local, named pipe
3 8
4* Como mostrar um erro em lua_socketlibopen()... 9* Como mostrar um erro em lua_socketlibopen()...
5* O location do "redirect" pode ser relativo ao servidor atual (não pode, 10* O location do "redirect" pode ser relativo ao servidor atual (não pode,
6 mas os servidores fazem merda...) 11 mas os servidores fazem merda...)
7* - Ajeitar para Lua 4.1 12* Ajeitar para Lua 5.0
13* Padronizar os retornos de funccao
14* Separar as classes em arquivos
15* Retorno de sendto em datagram sockets pode ser refused
16* Fazer compilar com g++
8 17
9- Padronizar os retornos de funccao
10- Thread-safe 18- Thread-safe
11 - proteger gethostby*.* com um mutex GLOBAL! 19 - proteger gethostby*.* com um mutex GLOBAL!
12 - proteger o atomizar o conjunto (timedout, receive), (timedout, send) 20 - proteger ou atomizar o conjunto (timedout, receive), (timedout, send)
13- Usar "require" nos módulos 21 - inet_ntoa também é uma merda.
14- SSL 22- SSL
15- Fazer compilar com g++ 23- Proxy support pro http
16- usar lua_verror
17- separar as classes em arquivos
18- criar mais uma classe, a de stream, entre p_sock e p_client
19- criar um internal include file ls.h
20- impedir que voe quando chamar accept(udpsocket())
21- trocar recv and send por read e write (ver se funciona)
22 24
23- checar operações em closed sockets 25- checar operações em closed sockets
24- checar teste de writable socket com select 26- checar teste de writable socket com select
@@ -34,6 +36,4 @@
34- unix 92 bytes maximo no endereço, incluindo o zero 36- unix 92 bytes maximo no endereço, incluindo o zero
35- unix 9216 maximo de datagram size 37- unix 9216 maximo de datagram size
36 38
37- retorno de send/receive em datagram sockets pode ser refused...
38 39
39- adicionar um método sock:setoption???
diff --git a/etc/check-links.lua b/etc/check-links.lua
index 4c96fdc..c45131c 100644
--- a/etc/check-links.lua
+++ b/etc/check-links.lua
@@ -1,6 +1,6 @@
1----------------------------------------------------------------------------- 1-----------------------------------------------------------------------------
2-- Little program that checks links in HTML files 2-- Little program that checks links in HTML files
3-- LuaSocket 1.5 sample files. 3-- LuaSocket sample files
4-- Author: Diego Nehab 4-- Author: Diego Nehab
5-- RCS ID: $Id$ 5-- RCS ID: $Id$
6----------------------------------------------------------------------------- 6-----------------------------------------------------------------------------
diff --git a/etc/dict.lua b/etc/dict.lua
index 89bdb4f..9926538 100644
--- a/etc/dict.lua
+++ b/etc/dict.lua
@@ -1,6 +1,6 @@
1----------------------------------------------------------------------------- 1-----------------------------------------------------------------------------
2-- Little program to download DICT word definitions 2-- Little program to download DICT word definitions
3-- LuaSocket 1.5 sample files 3-- LuaSocket sample files
4-- Author: Diego Nehab 4-- Author: Diego Nehab
5-- RCS ID: $Id$ 5-- RCS ID: $Id$
6----------------------------------------------------------------------------- 6-----------------------------------------------------------------------------
diff --git a/etc/get.lua b/etc/get.lua
index e972d16..caaa607 100644
--- a/etc/get.lua
+++ b/etc/get.lua
@@ -1,6 +1,6 @@
1----------------------------------------------------------------------------- 1-----------------------------------------------------------------------------
2-- Little program to download files from URLs 2-- Little program to download files from URLs
3-- LuaSocket 1.5 sample files 3-- LuaSocket sample files
4-- Author: Diego Nehab 4-- Author: Diego Nehab
5-- RCS ID: $Id$ 5-- RCS ID: $Id$
6----------------------------------------------------------------------------- 6-----------------------------------------------------------------------------
diff --git a/etc/tftp.lua b/etc/tftp.lua
index a0db68e..d1b5594 100644
--- a/etc/tftp.lua
+++ b/etc/tftp.lua
@@ -1,6 +1,6 @@
1----------------------------------------------------------------------------- 1-----------------------------------------------------------------------------
2-- TFTP support for the Lua language 2-- TFTP support for the Lua language
3-- LuaSocket 1.5 toolkit. 3-- LuaSocket toolkit.
4-- Author: Diego Nehab 4-- Author: Diego Nehab
5-- Conforming to: RFC 783, LTN7 5-- Conforming to: RFC 783, LTN7
6-- RCS ID: $Id$ 6-- RCS ID: $Id$
diff --git a/samples/daytimeclnt.lua b/samples/daytimeclnt.lua
index 85ddca1..5064fff 100644
--- a/samples/daytimeclnt.lua
+++ b/samples/daytimeclnt.lua
@@ -1,6 +1,6 @@
1----------------------------------------------------------------------------- 1-----------------------------------------------------------------------------
2-- UDP sample: daytime protocol client 2-- UDP sample: daytime protocol client
3-- LuaSocket 1.5 sample files. 3-- LuaSocket sample files
4-- Author: Diego Nehab 4-- Author: Diego Nehab
5-- RCS ID: $Id$ 5-- RCS ID: $Id$
6----------------------------------------------------------------------------- 6-----------------------------------------------------------------------------
diff --git a/samples/echoclnt.lua b/samples/echoclnt.lua
index bca0b4d..e028b86 100644
--- a/samples/echoclnt.lua
+++ b/samples/echoclnt.lua
@@ -1,6 +1,6 @@
1----------------------------------------------------------------------------- 1-----------------------------------------------------------------------------
2-- UDP sample: echo protocol client 2-- UDP sample: echo protocol client
3-- LuaSocket 1.5 sample files 3-- LuaSocket sample files
4-- Author: Diego Nehab 4-- Author: Diego Nehab
5-- RCS ID: $Id$ 5-- RCS ID: $Id$
6----------------------------------------------------------------------------- 6-----------------------------------------------------------------------------
diff --git a/samples/echosrvr.lua b/samples/echosrvr.lua
index 18bd84e..127ccb8 100644
--- a/samples/echosrvr.lua
+++ b/samples/echosrvr.lua
@@ -1,6 +1,6 @@
1----------------------------------------------------------------------------- 1-----------------------------------------------------------------------------
2-- UDP sample: echo protocol server 2-- UDP sample: echo protocol server
3-- LuaSocket 1.5 sample files 3-- LuaSocket sample files
4-- Author: Diego Nehab 4-- Author: Diego Nehab
5-- RCS ID: $Id$ 5-- RCS ID: $Id$
6----------------------------------------------------------------------------- 6-----------------------------------------------------------------------------
diff --git a/samples/listener.lua b/samples/listener.lua
index 4846419..dff4d25 100644
--- a/samples/listener.lua
+++ b/samples/listener.lua
@@ -1,6 +1,6 @@
1----------------------------------------------------------------------------- 1-----------------------------------------------------------------------------
2-- TCP sample: Little program to dump lines received at a given port 2-- TCP sample: Little program to dump lines received at a given port
3-- LuaSocket 1.5 sample files 3-- LuaSocket sample files
4-- Author: Diego Nehab 4-- Author: Diego Nehab
5-- RCS ID: $Id$ 5-- RCS ID: $Id$
6----------------------------------------------------------------------------- 6-----------------------------------------------------------------------------
diff --git a/samples/talker.lua b/samples/talker.lua
index c7a239a..1b0652f 100644
--- a/samples/talker.lua
+++ b/samples/talker.lua
@@ -1,6 +1,6 @@
1----------------------------------------------------------------------------- 1-----------------------------------------------------------------------------
2-- TCP sample: Little program to send text lines to a given host/port 2-- TCP sample: Little program to send text lines to a given host/port
3-- LuaSocket 1.5 sample files 3-- LuaSocket sample files
4-- Author: Diego Nehab 4-- Author: Diego Nehab
5-- RCS ID: $Id$ 5-- RCS ID: $Id$
6----------------------------------------------------------------------------- 6-----------------------------------------------------------------------------
diff --git a/samples/tinyirc.lua b/samples/tinyirc.lua
index 0b20303..0ad00ab 100644
--- a/samples/tinyirc.lua
+++ b/samples/tinyirc.lua
@@ -1,6 +1,6 @@
1----------------------------------------------------------------------------- 1-----------------------------------------------------------------------------
2-- Select sample: simple text line server 2-- Select sample: simple text line server
3-- LuaSocket 1.5 sample files. 3-- LuaSocket sample files.
4-- Author: Diego Nehab 4-- Author: Diego Nehab
5-- RCS ID: $Id$ 5-- RCS ID: $Id$
6----------------------------------------------------------------------------- 6-----------------------------------------------------------------------------
diff --git a/src/auxiliar.c b/src/auxiliar.c
index 96138f1..8b2fa37 100644
--- a/src/auxiliar.c
+++ b/src/auxiliar.c
@@ -1,142 +1,167 @@
1/*=========================================================================*\ 1/*=========================================================================*\
2* Auxiliar routines for class hierarchy manipulation 2* Auxiliar routines for class hierarchy manipulation
3* LuaSocket toolkit
3* 4*
4* RCS ID: $Id$ 5* RCS ID: $Id$
5\*=========================================================================*/ 6\*=========================================================================*/
7#include <string.h>
8
9#include "luasocket.h"
6#include "auxiliar.h" 10#include "auxiliar.h"
7 11
8/*=========================================================================*\ 12/*=========================================================================*\
9* Exported functions 13* Exported functions
10\*=========================================================================*/ 14\*=========================================================================*/
11/*-------------------------------------------------------------------------*\ 15/*-------------------------------------------------------------------------*\
12* Creates a new class. A class has methods given by the func array and the 16* Initializes the module
13* field 'class' tells the object class. The table 'group' list the class
14* groups the object belongs to.
15\*-------------------------------------------------------------------------*/ 17\*-------------------------------------------------------------------------*/
16void aux_newclass(lua_State *L, const char *name, luaL_reg *func) 18void aux_open(lua_State *L)
17{ 19{
18 lua_pushstring(L, name); 20 /* create namespace table */
19 lua_newtable(L); 21 lua_pushstring(L, LUASOCKET_LIBNAME);
20 lua_pushstring(L, "__index");
21 lua_newtable(L); 22 lua_newtable(L);
22 luaL_openlib(L, NULL, func, 0); 23#ifdef LUASOCKET_DEBUG
23 lua_pushstring(L, "class"); 24 lua_pushstring(L, "debug");
24 lua_pushstring(L, name); 25 lua_pushnumber(L, 1);
25 lua_rawset(L, -3);
26 lua_pushstring(L, "group");
27 lua_newtable(L);
28 lua_rawset(L, -3);
29 lua_rawset(L, -3); 26 lua_rawset(L, -3);
30 lua_rawset(L, LUA_REGISTRYINDEX); 27#endif
28 lua_settable(L, LUA_GLOBALSINDEX);
29 /* make sure modules know what is our namespace */
30 lua_pushstring(L, "LUASOCKET_LIBNAME");
31 lua_pushstring(L, LUASOCKET_LIBNAME);
32 lua_settable(L, LUA_GLOBALSINDEX);
31} 33}
32 34
33/*-------------------------------------------------------------------------*\ 35/*-------------------------------------------------------------------------*\
34* Add group to object list of groups. 36* Creates a new class with given methods
35\*-------------------------------------------------------------------------*/ 37\*-------------------------------------------------------------------------*/
36void aux_add2group(lua_State *L, const char *name, const char *group) 38void aux_newclass(lua_State *L, const char *classname, luaL_reg *func)
37{ 39{
38 lua_pushstring(L, name); 40 luaL_newmetatable(L, classname); /* mt */
39 lua_rawget(L, LUA_REGISTRYINDEX); 41 lua_pushstring(L, "__index"); /* mt,"__index" */
40 lua_pushstring(L, "__index"); 42 lua_newtable(L); /* mt,"__index",it */
41 lua_rawget(L, -2); 43 luaL_openlib(L, NULL, func, 0);
42 lua_pushstring(L, "group"); 44#ifdef LUASOCKET_DEBUG
43 lua_rawget(L, -2); 45 lua_pushstring(L, "class"); /* mt,"__index",it,"class" */
44 lua_pushstring(L, group); 46 lua_pushstring(L, classname); /* mt,"__index",it,"class",classname */
45 lua_pushnumber(L, 1); 47 lua_rawset(L, -3); /* mt,"__index",it */
48#endif
49 /* get __gc method from class and use it for garbage collection */
50 lua_pushstring(L, "__gc"); /* mt,"__index",it,"__gc" */
51 lua_pushstring(L, "__gc"); /* mt,"__index",it,"__gc","__gc" */
52 lua_rawget(L, -3); /* mt,"__index",it,"__gc",fn */
53 lua_rawset(L, -5); /* mt,"__index",it */
54 lua_rawset(L, -3); /* mt */
55 lua_pop(L, 1);
56}
57
58/*-------------------------------------------------------------------------*\
59* Insert class into group
60\*-------------------------------------------------------------------------*/
61void aux_add2group(lua_State *L, const char *classname, const char *groupname)
62{
63 luaL_getmetatable(L, classname);
64 lua_pushstring(L, groupname);
65 lua_pushboolean(L, 1);
46 lua_rawset(L, -3); 66 lua_rawset(L, -3);
47 lua_pop(L, 3); 67 lua_pop(L, 1);
68}
69
70/*-------------------------------------------------------------------------*\
71* Make sure argument is a boolean
72\*-------------------------------------------------------------------------*/
73int aux_checkboolean(lua_State *L, int objidx)
74{
75 if (!lua_isboolean(L, objidx))
76 luaL_typerror(L, objidx, lua_typename(L, LUA_TBOOLEAN));
77 return lua_toboolean(L, objidx);
48} 78}
49 79
50/*-------------------------------------------------------------------------*\ 80/*-------------------------------------------------------------------------*\
51* Get a userdata making sure the object belongs to a given class. 81* Calls appropriate option handler
52\*-------------------------------------------------------------------------*/ 82\*-------------------------------------------------------------------------*/
53void *aux_checkclass(lua_State *L, const char *name, int objidx) 83int aux_meth_setoption(lua_State *L, luaL_reg *opt)
54{ 84{
55 void *data = aux_getclassudata(L, name, objidx); 85 const char *name = luaL_checkstring(L, 2); /* obj, name, args */
86 while (opt->name && strcmp(name, opt->name))
87 opt++;
88 if (!opt->func) {
89 char msg[45];
90 sprintf(msg, "unknown option `%.35s'", name);
91 luaL_argerror(L, 2, msg);
92 }
93 lua_remove(L, 2); /* obj, args */
94 lua_pushcfunction(L, opt->func); /* obj, args, func */
95 lua_insert(L, 1); /* func, obj, args */
96 lua_call(L, lua_gettop(L)-1, LUA_MULTRET);
97 return lua_gettop(L);
98}
99
100/*-------------------------------------------------------------------------*\
101* Return userdata pointer if object belongs to a given class, abort with
102* error otherwise
103\*-------------------------------------------------------------------------*/
104void *aux_checkclass(lua_State *L, const char *classname, int objidx)
105{
106 void *data = aux_getclassudata(L, classname, objidx);
56 if (!data) { 107 if (!data) {
57 char msg[45]; 108 char msg[45];
58 sprintf(msg, "%.35s expected", name); 109 sprintf(msg, "%.35s expected", classname);
59 luaL_argerror(L, objidx, msg); 110 luaL_argerror(L, objidx, msg);
60 } 111 }
61 return data; 112 return data;
62} 113}
63 114
64/*-------------------------------------------------------------------------*\ 115/*-------------------------------------------------------------------------*\
65* Get a userdata making sure the object belongs to a given group. 116* Return userdata pointer if object belongs to a given group, abort with
117* error otherwise
66\*-------------------------------------------------------------------------*/ 118\*-------------------------------------------------------------------------*/
67void *aux_checkgroup(lua_State *L, const char *group, int objidx) 119void *aux_checkgroup(lua_State *L, const char *groupname, int objidx)
68{ 120{
69 void *data = aux_getgroupudata(L, group, objidx); 121 void *data = aux_getgroupudata(L, groupname, objidx);
70 if (!data) { 122 if (!data) {
71 char msg[45]; 123 char msg[45];
72 sprintf(msg, "%.35s expected", group); 124 sprintf(msg, "%.35s expected", groupname);
73 luaL_argerror(L, objidx, msg); 125 luaL_argerror(L, objidx, msg);
74 } 126 }
75 return data; 127 return data;
76} 128}
77 129
78/*-------------------------------------------------------------------------*\ 130/*-------------------------------------------------------------------------*\
79* Set object class. 131* Set object class
80\*-------------------------------------------------------------------------*/ 132\*-------------------------------------------------------------------------*/
81void aux_setclass(lua_State *L, const char *name, int objidx) 133void aux_setclass(lua_State *L, const char *classname, int objidx)
82{ 134{
83 lua_pushstring(L, name); 135 luaL_getmetatable(L, classname);
84 lua_rawget(L, LUA_REGISTRYINDEX);
85 if (objidx < 0) objidx--; 136 if (objidx < 0) objidx--;
86 lua_setmetatable(L, objidx); 137 lua_setmetatable(L, objidx);
87} 138}
88 139
89/*=========================================================================*\
90* Internal functions
91\*=========================================================================*/
92/*-------------------------------------------------------------------------*\ 140/*-------------------------------------------------------------------------*\
93* Get a userdata if object belongs to a given group. 141* Get a userdata pointer if object belongs to a given group. Return NULL
142* otherwise
94\*-------------------------------------------------------------------------*/ 143\*-------------------------------------------------------------------------*/
95void *aux_getgroupudata(lua_State *L, const char *group, int objidx) 144void *aux_getgroupudata(lua_State *L, const char *groupname, int objidx)
96{ 145{
97 if (!lua_getmetatable(L, objidx)) 146 if (!lua_getmetatable(L, objidx))
98 return NULL;
99 lua_pushstring(L, "__index");
100 lua_rawget(L, -2);
101 if (!lua_istable(L, -1)) {
102 lua_pop(L, 2);
103 return NULL;
104 }
105 lua_pushstring(L, "group");
106 lua_rawget(L, -2);
107 if (!lua_istable(L, -1)) {
108 lua_pop(L, 3);
109 return NULL; 147 return NULL;
110 } 148 lua_pushstring(L, groupname);
111 lua_pushstring(L, group);
112 lua_rawget(L, -2); 149 lua_rawget(L, -2);
113 if (lua_isnil(L, -1)) { 150 if (lua_isnil(L, -1)) {
114 lua_pop(L, 4); 151 lua_pop(L, 2);
115 return NULL; 152 return NULL;
153 } else {
154 lua_pop(L, 2);
155 return lua_touserdata(L, objidx);
116 } 156 }
117 lua_pop(L, 4);
118 return lua_touserdata(L, objidx);
119} 157}
120 158
121/*-------------------------------------------------------------------------*\ 159/*-------------------------------------------------------------------------*\
122* Get a userdata if object belongs to a given class. 160* Get a userdata pointer if object belongs to a given class. Return NULL
161* otherwise
123\*-------------------------------------------------------------------------*/ 162\*-------------------------------------------------------------------------*/
124void *aux_getclassudata(lua_State *L, const char *group, int objidx) 163void *aux_getclassudata(lua_State *L, const char *classname, int objidx)
125{ 164{
126 if (!lua_getmetatable(L, objidx)) 165 return luaL_checkudata(L, objidx, classname);
127 return NULL;
128 lua_pushstring(L, "__index");
129 lua_rawget(L, -2);
130 if (!lua_istable(L, -1)) {
131 lua_pop(L, 2);
132 return NULL;
133 }
134 lua_pushstring(L, "class");
135 lua_rawget(L, -2);
136 if (lua_isnil(L, -1)) {
137 lua_pop(L, 3);
138 return NULL;
139 }
140 lua_pop(L, 3);
141 return lua_touserdata(L, objidx);
142} 166}
167
diff --git a/src/auxiliar.h b/src/auxiliar.h
index 66be31d..324e800 100644
--- a/src/auxiliar.h
+++ b/src/auxiliar.h
@@ -1,22 +1,37 @@
1#ifndef AUX_H
2#define AUX_H
1/*=========================================================================*\ 3/*=========================================================================*\
2* Auxiliar routines for class hierarchy manipulation 4* Auxiliar routines for class hierarchy manipulation
5* LuaSocket toolkit
6*
7* A LuaSocket class is a name associated with Lua metatables. A LuaSocket
8* group is a name associated to a class. A class can belong to any number
9* of groups. This module provides the functionality to:
10*
11* - create new classes
12* - add classes to groups
13* - set the class of object
14* - check if an object belongs to a given class or group
15*
16* LuaSocket class names follow the convention <module>{<class>}. Modules
17* can define any number of classes and groups. The module tcp.c, for
18* example, defines the classes tcp{master}, tcp{client} and tcp{server} and
19* the groups tcp{client, server} and tcp{any}. Module functions can then
20* perform type-checking on it's arguments by either class or group.
21*
22* LuaSocket metatables define the __index metamethod as being a table. This
23* table has one field for each method supported by the class. In DEBUG
24* mode, it also has one field with the class name.
25*
26* The mapping from class name to the corresponding metatable and the
27* reverse mapping are done using lauxlib.
3* 28*
4* RCS ID: $Id$ 29* RCS ID: $Id$
5\*=========================================================================*/ 30\*=========================================================================*/
6#ifndef AUX_H
7#define AUX_H
8 31
9#include <lua.h> 32#include <lua.h>
10#include <lauxlib.h> 33#include <lauxlib.h>
11 34
12void aux_newclass(lua_State *L, const char *name, luaL_reg *func);
13void aux_add2group(lua_State *L, const char *name, const char *group);
14void *aux_checkclass(lua_State *L, const char *name, int objidx);
15void *aux_checkgroup(lua_State *L, const char *group, int objidx);
16void *aux_getclassudata(lua_State *L, const char *group, int objidx);
17void *aux_getgroupudata(lua_State *L, const char *group, int objidx);
18void aux_setclass(lua_State *L, const char *name, int objidx);
19
20/* min and max macros */ 35/* min and max macros */
21#ifndef MIN 36#ifndef MIN
22#define MIN(x, y) ((x) < (y) ? x : y) 37#define MIN(x, y) ((x) < (y) ? x : y)
@@ -25,4 +40,15 @@ void aux_setclass(lua_State *L, const char *name, int objidx);
25#define MAX(x, y) ((x) > (y) ? x : y) 40#define MAX(x, y) ((x) > (y) ? x : y)
26#endif 41#endif
27 42
28#endif 43void aux_open(lua_State *L);
44void aux_newclass(lua_State *L, const char *classname, luaL_reg *func);
45void aux_add2group(lua_State *L, const char *classname, const char *group);
46void aux_setclass(lua_State *L, const char *classname, int objidx);
47void *aux_checkclass(lua_State *L, const char *classname, int objidx);
48void *aux_checkgroup(lua_State *L, const char *groupname, int objidx);
49void *aux_getclassudata(lua_State *L, const char *groupname, int objidx);
50void *aux_getgroupudata(lua_State *L, const char *groupname, int objidx);
51int aux_meth_setoption(lua_State *L, luaL_reg *opt);
52int aux_checkboolean(lua_State *L, int objidx);
53
54#endif /* AUX_H */
diff --git a/src/buffer.c b/src/buffer.c
index ab059bb..c860f35 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -1,12 +1,12 @@
1/*=========================================================================*\ 1/*=========================================================================*\
2* Buffered input/output routines 2* Input/Output interface for Lua programs
3* LuaSocket toolkit
3* 4*
4* RCS ID: $Id$ 5* RCS ID: $Id$
5\*=========================================================================*/ 6\*=========================================================================*/
6#include <lua.h> 7#include <lua.h>
7#include <lauxlib.h> 8#include <lauxlib.h>
8 9
9#include "error.h"
10#include "auxiliar.h" 10#include "auxiliar.h"
11#include "buffer.h" 11#include "buffer.h"
12 12
@@ -42,7 +42,7 @@ void buf_init(p_buf buf, p_io io, p_tm tm)
42} 42}
43 43
44/*-------------------------------------------------------------------------*\ 44/*-------------------------------------------------------------------------*\
45* Send data through buffered object 45* object:send() interface
46\*-------------------------------------------------------------------------*/ 46\*-------------------------------------------------------------------------*/
47int buf_meth_send(lua_State *L, p_buf buf) 47int buf_meth_send(lua_State *L, p_buf buf)
48{ 48{
@@ -59,7 +59,7 @@ int buf_meth_send(lua_State *L, p_buf buf)
59 total += sent; 59 total += sent;
60 } 60 }
61 lua_pushnumber(L, total); 61 lua_pushnumber(L, total);
62 error_push(L, err); 62 io_pusherror(L, err);
63#ifdef LUASOCKET_DEBUG 63#ifdef LUASOCKET_DEBUG
64 /* push time elapsed during operation as the last return value */ 64 /* push time elapsed during operation as the last return value */
65 lua_pushnumber(L, (tm_gettime() - tm_getstart(tm))/1000.0); 65 lua_pushnumber(L, (tm_gettime() - tm_getstart(tm))/1000.0);
@@ -68,7 +68,7 @@ int buf_meth_send(lua_State *L, p_buf buf)
68} 68}
69 69
70/*-------------------------------------------------------------------------*\ 70/*-------------------------------------------------------------------------*\
71* Receive data from a buffered object 71* object:receive() interface
72\*-------------------------------------------------------------------------*/ 72\*-------------------------------------------------------------------------*/
73int buf_meth_receive(lua_State *L, p_buf buf) 73int buf_meth_receive(lua_State *L, p_buf buf)
74{ 74{
@@ -101,13 +101,13 @@ int buf_meth_receive(lua_State *L, p_buf buf)
101 luaL_argcheck(L, 0, arg, "invalid receive pattern"); 101 luaL_argcheck(L, 0, arg, "invalid receive pattern");
102 break; 102 break;
103 } 103 }
104 /* raw pattern */ 104 /* get a fixed number of bytes */
105 } else err = recvraw(L, buf, (size_t) lua_tonumber(L, arg)); 105 } else err = recvraw(L, buf, (size_t) lua_tonumber(L, arg));
106 } 106 }
107 /* push nil for each pattern after an error */ 107 /* push nil for each pattern after an error */
108 for ( ; arg <= top; arg++) lua_pushnil(L); 108 for ( ; arg <= top; arg++) lua_pushnil(L);
109 /* last return is an error code */ 109 /* last return is an error code */
110 error_push(L, err); 110 io_pusherror(L, err);
111#ifdef LUASOCKET_DEBUG 111#ifdef LUASOCKET_DEBUG
112 /* push time elapsed during operation as the last return value */ 112 /* push time elapsed during operation as the last return value */
113 lua_pushnumber(L, (tm_gettime() - tm_getstart(tm))/1000.0); 113 lua_pushnumber(L, (tm_gettime() - tm_getstart(tm))/1000.0);
@@ -127,9 +127,10 @@ int buf_isempty(p_buf buf)
127* Internal functions 127* Internal functions
128\*=========================================================================*/ 128\*=========================================================================*/
129/*-------------------------------------------------------------------------*\ 129/*-------------------------------------------------------------------------*\
130* Sends a raw block of data through a buffered object. 130* Sends a block of data (unbuffered)
131\*-------------------------------------------------------------------------*/ 131\*-------------------------------------------------------------------------*/
132static int sendraw(p_buf buf, const char *data, size_t count, size_t *sent) 132static
133int sendraw(p_buf buf, const char *data, size_t count, size_t *sent)
133{ 134{
134 p_io io = buf->io; 135 p_io io = buf->io;
135 p_tm tm = buf->tm; 136 p_tm tm = buf->tm;
@@ -145,7 +146,7 @@ static int sendraw(p_buf buf, const char *data, size_t count, size_t *sent)
145} 146}
146 147
147/*-------------------------------------------------------------------------*\ 148/*-------------------------------------------------------------------------*\
148* Reads a raw block of data from a buffered object. 149* Reads a fixed number of bytes (buffered)
149\*-------------------------------------------------------------------------*/ 150\*-------------------------------------------------------------------------*/
150static 151static
151int recvraw(lua_State *L, p_buf buf, size_t wanted) 152int 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)
167} 168}
168 169
169/*-------------------------------------------------------------------------*\ 170/*-------------------------------------------------------------------------*\
170* Reads everything until the connection is closed 171* Reads everything until the connection is closed (buffered)
171\*-------------------------------------------------------------------------*/ 172\*-------------------------------------------------------------------------*/
172static 173static
173int recvall(lua_State *L, p_buf buf) 174int recvall(lua_State *L, p_buf buf)
@@ -187,12 +188,12 @@ int recvall(lua_State *L, p_buf buf)
187 188
188/*-------------------------------------------------------------------------*\ 189/*-------------------------------------------------------------------------*\
189* Reads a line terminated by a CR LF pair or just by a LF. The CR and LF 190* Reads a line terminated by a CR LF pair or just by a LF. The CR and LF
190* are not returned by the function and are discarded from the buffer. 191* are not returned by the function and are discarded from the buffer
191\*-------------------------------------------------------------------------*/ 192\*-------------------------------------------------------------------------*/
192static 193static
193int recvline(lua_State *L, p_buf buf) 194int recvline(lua_State *L, p_buf buf)
194{ 195{
195 int err = 0; 196 int err = IO_DONE;
196 luaL_Buffer b; 197 luaL_Buffer b;
197 luaL_buffinit(L, &b); 198 luaL_buffinit(L, &b);
198 while (err == IO_DONE) { 199 while (err == IO_DONE) {
@@ -215,7 +216,8 @@ int recvline(lua_State *L, p_buf buf)
215} 216}
216 217
217/*-------------------------------------------------------------------------*\ 218/*-------------------------------------------------------------------------*\
218* Skips a given number of bytes in read buffer 219* Skips a given number of bytes from read buffer. No data is read from the
220* transport layer
219\*-------------------------------------------------------------------------*/ 221\*-------------------------------------------------------------------------*/
220static 222static
221void buf_skip(p_buf buf, size_t count) 223void buf_skip(p_buf buf, size_t count)
@@ -227,7 +229,7 @@ void buf_skip(p_buf buf, size_t count)
227 229
228/*-------------------------------------------------------------------------*\ 230/*-------------------------------------------------------------------------*\
229* Return any data available in buffer, or get more data from transport layer 231* Return any data available in buffer, or get more data from transport layer
230* if buffer is empty. 232* if buffer is empty
231\*-------------------------------------------------------------------------*/ 233\*-------------------------------------------------------------------------*/
232static 234static
233int buf_get(p_buf buf, const char **data, size_t *count) 235int 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)
245 *data = buf->data + buf->first; 247 *data = buf->data + buf->first;
246 return err; 248 return err;
247} 249}
250
diff --git a/src/buffer.h b/src/buffer.h
index 1502ef0..12b90a0 100644
--- a/src/buffer.h
+++ b/src/buffer.h
@@ -1,21 +1,31 @@
1#ifndef BUF_H
2#define BUF_H
1/*=========================================================================*\ 3/*=========================================================================*\
2* Buffered input/output routines 4* Input/Output interface for Lua programs
5* LuaSocket toolkit
6*
7* Line patterns require buffering. Reading one character at a time involves
8* too many system calls and is very slow. This module implements the
9* LuaSocket interface for input/output on connected objects, as seen by
10* Lua programs.
11*
12* Input is buffered. Output is *not* buffered because there was no simple
13* way of making sure the buffered output data would ever be sent.
14*
15* The module is built on top of the I/O abstraction defined in io.h and the
16* timeout management is done with the timeout.h interface.
3* 17*
4* RCS ID: $Id$ 18* RCS ID: $Id$
5\*=========================================================================*/ 19\*=========================================================================*/
6#ifndef BUF_H
7#define BUF_H
8
9#include <lua.h> 20#include <lua.h>
21
10#include "io.h" 22#include "io.h"
11#include "timeout.h" 23#include "timeout.h"
12 24
13/* buffer size in bytes */ 25/* buffer size in bytes */
14#define BUF_SIZE 8192 26#define BUF_SIZE 8192
15 27
16/*-------------------------------------------------------------------------*\ 28/* buffer control structure */
17* Buffer control structure
18\*-------------------------------------------------------------------------*/
19typedef struct t_buf_ { 29typedef struct t_buf_ {
20 p_io io; /* IO driver used for this buffer */ 30 p_io io; /* IO driver used for this buffer */
21 p_tm tm; /* timeout management for this buffer */ 31 p_tm tm; /* timeout management for this buffer */
@@ -24,9 +34,6 @@ typedef struct t_buf_ {
24} t_buf; 34} t_buf;
25typedef t_buf *p_buf; 35typedef t_buf *p_buf;
26 36
27/*-------------------------------------------------------------------------*\
28* Exported functions
29\*-------------------------------------------------------------------------*/
30void buf_open(lua_State *L); 37void buf_open(lua_State *L);
31void buf_init(p_buf buf, p_io io, p_tm tm); 38void buf_init(p_buf buf, p_io io, p_tm tm);
32int buf_meth_send(lua_State *L, p_buf buf); 39int buf_meth_send(lua_State *L, p_buf buf);
diff --git a/src/ftp.lua b/src/ftp.lua
index c48f2c7..9d75d2a 100644
--- a/src/ftp.lua
+++ b/src/ftp.lua
@@ -1,6 +1,6 @@
1----------------------------------------------------------------------------- 1-----------------------------------------------------------------------------
2-- FTP support for the Lua language 2-- FTP support for the Lua language
3-- LuaSocket 1.5 toolkit. 3-- LuaSocket toolkit.
4-- Author: Diego Nehab 4-- Author: Diego Nehab
5-- Conforming to: RFC 959, LTN7 5-- Conforming to: RFC 959, LTN7
6-- RCS ID: $Id$ 6-- RCS ID: $Id$
diff --git a/src/http.lua b/src/http.lua
index d531a2f..4ef2c87 100644
--- a/src/http.lua
+++ b/src/http.lua
@@ -1,6 +1,6 @@
1----------------------------------------------------------------------------- 1-----------------------------------------------------------------------------
2-- HTTP/1.1 client support for the Lua language. 2-- HTTP/1.1 client support for the Lua language.
3-- LuaSocket 1.5 toolkit. 3-- LuaSocket toolkit.
4-- Author: Diego Nehab 4-- Author: Diego Nehab
5-- Conforming to: RFC 2616, LTN7 5-- Conforming to: RFC 2616, LTN7
6-- RCS ID: $Id$ 6-- RCS ID: $Id$
diff --git a/src/inet.c b/src/inet.c
index b7f3ae5..312a45b 100644
--- a/src/inet.c
+++ b/src/inet.c
@@ -1,8 +1,10 @@
1/*=========================================================================*\ 1/*=========================================================================*\
2* Internet domain functions 2* Internet domain functions
3* LuaSocket toolkit
3* 4*
4* RCS ID: $Id$ 5* RCS ID: $Id$
5\*=========================================================================*/ 6\*=========================================================================*/
7#include <stdio.h>
6#include <string.h> 8#include <string.h>
7 9
8#include <lua.h> 10#include <lua.h>
@@ -16,7 +18,6 @@
16\*=========================================================================*/ 18\*=========================================================================*/
17static int inet_global_toip(lua_State *L); 19static int inet_global_toip(lua_State *L);
18static int inet_global_tohostname(lua_State *L); 20static int inet_global_tohostname(lua_State *L);
19
20static void inet_pushresolved(lua_State *L, struct hostent *hp); 21static void inet_pushresolved(lua_State *L, struct hostent *hp);
21 22
22static luaL_reg func[] = { 23static luaL_reg func[] = {
@@ -43,11 +44,6 @@ void inet_open(lua_State *L)
43/*-------------------------------------------------------------------------*\ 44/*-------------------------------------------------------------------------*\
44* Returns all information provided by the resolver given a host name 45* Returns all information provided by the resolver given a host name
45* or ip address 46* or ip address
46* Lua Input: address
47* address: ip address or hostname to dns lookup
48* Lua Returns
49* On success: first IP address followed by a resolved table
50* On error: nil, followed by an error message
51\*-------------------------------------------------------------------------*/ 47\*-------------------------------------------------------------------------*/
52static int inet_global_toip(lua_State *L) 48static int inet_global_toip(lua_State *L)
53{ 49{
@@ -72,11 +68,6 @@ static int inet_global_toip(lua_State *L)
72/*-------------------------------------------------------------------------*\ 68/*-------------------------------------------------------------------------*\
73* Returns all information provided by the resolver given a host name 69* Returns all information provided by the resolver given a host name
74* or ip address 70* or ip address
75* Lua Input: address
76* address: ip address or host name to reverse dns lookup
77* Lua Returns
78* On success: canonic name followed by a resolved table
79* On error: nil, followed by an error message
80\*-------------------------------------------------------------------------*/ 71\*-------------------------------------------------------------------------*/
81static int inet_global_tohostname(lua_State *L) 72static int inet_global_tohostname(lua_State *L)
82{ 73{
@@ -102,11 +93,6 @@ static int inet_global_tohostname(lua_State *L)
102\*=========================================================================*/ 93\*=========================================================================*/
103/*-------------------------------------------------------------------------*\ 94/*-------------------------------------------------------------------------*\
104* Retrieves socket peer name 95* Retrieves socket peer name
105* Input:
106* sock: socket
107* Lua Returns
108* On success: ip address and port of peer
109* On error: nil
110\*-------------------------------------------------------------------------*/ 96\*-------------------------------------------------------------------------*/
111int inet_meth_getpeername(lua_State *L, p_sock ps) 97int inet_meth_getpeername(lua_State *L, p_sock ps)
112{ 98{
@@ -123,11 +109,6 @@ int inet_meth_getpeername(lua_State *L, p_sock ps)
123 109
124/*-------------------------------------------------------------------------*\ 110/*-------------------------------------------------------------------------*\
125* Retrieves socket local name 111* Retrieves socket local name
126* Input:
127* sock: socket
128* Lua Returns
129* On success: local ip address and port
130* On error: nil
131\*-------------------------------------------------------------------------*/ 112\*-------------------------------------------------------------------------*/
132int inet_meth_getsockname(lua_State *L, p_sock ps) 113int inet_meth_getsockname(lua_State *L, p_sock ps)
133{ 114{
@@ -147,8 +128,6 @@ int inet_meth_getsockname(lua_State *L, p_sock ps)
147\*=========================================================================*/ 128\*=========================================================================*/
148/*-------------------------------------------------------------------------*\ 129/*-------------------------------------------------------------------------*\
149* Passes all resolver information to Lua as a table 130* Passes all resolver information to Lua as a table
150* Input
151* hp: hostent structure returned by resolver
152\*-------------------------------------------------------------------------*/ 131\*-------------------------------------------------------------------------*/
153static void inet_pushresolved(lua_State *L, struct hostent *hp) 132static void inet_pushresolved(lua_State *L, struct hostent *hp)
154{ 133{
@@ -185,12 +164,6 @@ static void inet_pushresolved(lua_State *L, struct hostent *hp)
185 164
186/*-------------------------------------------------------------------------*\ 165/*-------------------------------------------------------------------------*\
187* Tries to connect to remote address (address, port) 166* Tries to connect to remote address (address, port)
188* Input
189* ps: pointer to socket
190* address: host name or ip address
191* port: port number to bind to
192* Returns
193* NULL in case of success, error message otherwise
194\*-------------------------------------------------------------------------*/ 167\*-------------------------------------------------------------------------*/
195const char *inet_tryconnect(p_sock ps, const char *address, 168const char *inet_tryconnect(p_sock ps, const char *address,
196 unsigned short port) 169 unsigned short port)
@@ -224,12 +197,6 @@ const char *inet_tryconnect(p_sock ps, const char *address,
224 197
225/*-------------------------------------------------------------------------*\ 198/*-------------------------------------------------------------------------*\
226* Tries to bind socket to (address, port) 199* Tries to bind socket to (address, port)
227* Input
228* sock: pointer to socket
229* address: host name or ip address
230* port: port number to bind to
231* Returns
232* NULL in case of success, error message otherwise
233\*-------------------------------------------------------------------------*/ 200\*-------------------------------------------------------------------------*/
234const char *inet_trybind(p_sock ps, const char *address, unsigned short port, 201const char *inet_trybind(p_sock ps, const char *address, unsigned short port,
235 int backlog) 202 int backlog)
@@ -264,10 +231,6 @@ const char *inet_trybind(p_sock ps, const char *address, unsigned short port,
264 231
265/*-------------------------------------------------------------------------*\ 232/*-------------------------------------------------------------------------*\
266* Tries to create a new inet socket 233* Tries to create a new inet socket
267* Input
268* sock: pointer to socket
269* Returns
270* NULL if successfull, error message on error
271\*-------------------------------------------------------------------------*/ 234\*-------------------------------------------------------------------------*/
272const char *inet_trycreate(p_sock ps, int type) 235const char *inet_trycreate(p_sock ps, int type)
273{ 236{
@@ -299,3 +262,5 @@ int inet_aton(const char *cp, struct in_addr *inp)
299 return 1; 262 return 1;
300} 263}
301#endif 264#endif
265
266
diff --git a/src/inet.h b/src/inet.h
index 60be9e4..244a310 100644
--- a/src/inet.h
+++ b/src/inet.h
@@ -1,25 +1,30 @@
1#ifndef INET_H
2#define INET_H
1/*=========================================================================*\ 3/*=========================================================================*\
2* Internet domain functions 4* Internet domain functions
5* LuaSocket toolkit
6*
7* This module implements the creation and connection of internet domain
8* sockets, on top of the socket.h interface, and the interface of with the
9* resolver.
10*
11* The function inet_aton is provided for the platforms where it is not
12* available. The module also implements the interface of the internet
13* getpeername and getsockname functions as seen by Lua programs.
14*
15* The Lua functions toip and tohostname are also implemented here.
3* 16*
4* RCS ID: $Id$ 17* RCS ID: $Id$
5\*=========================================================================*/ 18\*=========================================================================*/
6#ifndef INET_H
7#define INET_H
8
9#include <lua.h> 19#include <lua.h>
10#include "socket.h" 20#include "socket.h"
11 21
12/*-------------------------------------------------------------------------*\
13* Exported functions
14\*-------------------------------------------------------------------------*/
15void inet_open(lua_State *L); 22void inet_open(lua_State *L);
16
17const char *inet_tryconnect(p_sock ps, const char *address, 23const char *inet_tryconnect(p_sock ps, const char *address,
18 unsigned short port); 24 unsigned short port);
19const char *inet_trybind(p_sock ps, const char *address, 25const char *inet_trybind(p_sock ps, const char *address,
20 unsigned short port, int backlog); 26 unsigned short port, int backlog);
21const char *inet_trycreate(p_sock ps, int type); 27const char *inet_trycreate(p_sock ps, int type);
22
23int inet_meth_getpeername(lua_State *L, p_sock ps); 28int inet_meth_getpeername(lua_State *L, p_sock ps);
24int inet_meth_getsockname(lua_State *L, p_sock ps); 29int inet_meth_getsockname(lua_State *L, p_sock ps);
25 30
@@ -27,4 +32,4 @@ int inet_meth_getsockname(lua_State *L, p_sock ps);
27int inet_aton(const char *cp, struct in_addr *inp); 32int inet_aton(const char *cp, struct in_addr *inp);
28#endif 33#endif
29 34
30#endif /* INET_H_ */ 35#endif /* INET_H */
diff --git a/src/io.c b/src/io.c
index 902124a..2d62147 100644
--- a/src/io.c
+++ b/src/io.c
@@ -1,8 +1,48 @@
1/*=========================================================================*\
2* Input/Output abstraction
3* LuaSocket toolkit
4*
5* RCS ID: $Id$
6\*=========================================================================*/
1#include "io.h" 7#include "io.h"
2 8
9/*=========================================================================*\
10* Exported functions
11\*=========================================================================*/
12/*-------------------------------------------------------------------------*\
13* Initializes C structure
14\*-------------------------------------------------------------------------*/
3void io_init(p_io io, p_send send, p_recv recv, void *ctx) 15void io_init(p_io io, p_send send, p_recv recv, void *ctx)
4{ 16{
5 io->send = send; 17 io->send = send;
6 io->recv = recv; 18 io->recv = recv;
7 io->ctx = ctx; 19 io->ctx = ctx;
8} 20}
21
22/*-------------------------------------------------------------------------*\
23* Translate error codes to Lua
24\*-------------------------------------------------------------------------*/
25void io_pusherror(lua_State *L, int code)
26{
27 switch (code) {
28 case IO_DONE:
29 lua_pushnil(L);
30 break;
31 case IO_TIMEOUT:
32 lua_pushstring(L, "timeout");
33 break;
34 case IO_LIMITED:
35 lua_pushstring(L, "limited");
36 break;
37 case IO_CLOSED:
38 lua_pushstring(L, "closed");
39 break;
40 case IO_REFUSED:
41 lua_pushstring(L, "refused");
42 break;
43 default:
44 lua_pushstring(L, "unknown error");
45 break;
46 }
47}
48
diff --git a/src/io.h b/src/io.h
index 30d445b..f56094a 100644
--- a/src/io.h
+++ b/src/io.h
@@ -1,16 +1,30 @@
1#ifndef IO_H 1#ifndef IO_H
2#define IO_H 2#define IO_H
3 3/*=========================================================================*\
4* Input/Output abstraction
5* LuaSocket toolkit
6*
7* This module defines the interface that LuaSocket expects from the
8* transport layer for streamed input/output. The idea is that if any
9* transport implements this interface, then the buffer.c functions
10* automatically work on it.
11*
12* The module socket.h implements this interface, and thus the module tcp.h
13* is very simple.
14*
15* RCS ID: $Id$
16\*=========================================================================*/
4#include <stdio.h> 17#include <stdio.h>
18#include <lua.h>
5 19
6/* IO error codes */ 20/* IO error codes */
7enum { 21enum {
8 IO_DONE, /* operation completed successfully */ 22 IO_DONE, /* operation completed successfully */
9 IO_TIMEOUT, /* operation timed out */ 23 IO_TIMEOUT, /* operation timed out */
10 IO_CLOSED, /* the connection has been closed */ 24 IO_CLOSED, /* the connection has been closed */
11 IO_ERROR, /* something wrong... */ 25 IO_ERROR, /* something wrong... */
12 IO_REFUSED, /* transfer has been refused */ 26 IO_REFUSED, /* transfer has been refused */
13 IO_LIMITED /* maximum number of bytes reached */ 27 IO_LIMITED /* maximum number of bytes reached */
14}; 28};
15 29
16/* interface to send function */ 30/* interface to send function */
@@ -39,6 +53,7 @@ typedef struct t_io_ {
39} t_io; 53} t_io;
40typedef t_io *p_io; 54typedef t_io *p_io;
41 55
56void io_pusherror(lua_State *L, int code);
42void io_init(p_io io, p_send send, p_recv recv, void *ctx); 57void io_init(p_io io, p_send send, p_recv recv, void *ctx);
43 58
44#endif /* IO_H */ 59#endif /* IO_H */
diff --git a/src/luasocket.c b/src/luasocket.c
index 5541d7f..96deac1 100644
--- a/src/luasocket.c
+++ b/src/luasocket.c
@@ -1,4 +1,5 @@
1/*=========================================================================*\ 1/*=========================================================================*\
2* LuaSocket toolkit
2* Networking support for the Lua language 3* Networking support for the Lua language
3* Diego Nehab 4* Diego Nehab
4* 26/11/1999 5* 26/11/1999
@@ -7,7 +8,7 @@
7* connectivity of the Lua language. The Lua interface to networking 8* connectivity of the Lua language. The Lua interface to networking
8* functions follows the Sockets API closely, trying to simplify all tasks 9* functions follows the Sockets API closely, trying to simplify all tasks
9* involved in setting up both client and server connections. The provided 10* involved in setting up both client and server connections. The provided
10* IO routines, however, follow the Lua style, being very similar to the 11* IO routines, however, follow the Lua style, being very similar to the
11* standard Lua read and write functions. 12* standard Lua read and write functions.
12* 13*
13* RCS ID: $Id$ 14* RCS ID: $Id$
@@ -24,6 +25,7 @@
24\*=========================================================================*/ 25\*=========================================================================*/
25#include "luasocket.h" 26#include "luasocket.h"
26 27
28#include "auxiliar.h"
27#include "timeout.h" 29#include "timeout.h"
28#include "buffer.h" 30#include "buffer.h"
29#include "socket.h" 31#include "socket.h"
@@ -38,23 +40,11 @@
38/*-------------------------------------------------------------------------*\ 40/*-------------------------------------------------------------------------*\
39* Initializes all library modules. 41* Initializes all library modules.
40\*-------------------------------------------------------------------------*/ 42\*-------------------------------------------------------------------------*/
41LUASOCKET_API int luaopen_socketlib(lua_State *L) 43LUASOCKET_API int luaopen_socket(lua_State *L)
42{ 44{
43 if (!sock_open()) return 0; 45 if (!sock_open()) return 0;
44 /* create namespace table */
45 lua_pushstring(L, LUASOCKET_LIBNAME);
46 lua_newtable(L);
47#ifdef LUASOCKET_DEBUG
48 lua_pushstring(L, "debug");
49 lua_pushnumber(L, 1);
50 lua_settable(L, -3);
51#endif
52 lua_settable(L, LUA_GLOBALSINDEX);
53 /* make sure modules know what is our namespace */
54 lua_pushstring(L, "LUASOCKET_LIBNAME");
55 lua_pushstring(L, LUASOCKET_LIBNAME);
56 lua_settable(L, LUA_GLOBALSINDEX);
57 /* initialize all modules */ 46 /* initialize all modules */
47 aux_open(L);
58 tm_open(L); 48 tm_open(L);
59 buf_open(L); 49 buf_open(L);
60 inet_open(L); 50 inet_open(L);
diff --git a/src/luasocket.h b/src/luasocket.h
index 6c25af2..7756605 100644
--- a/src/luasocket.h
+++ b/src/luasocket.h
@@ -1,17 +1,19 @@
1#ifndef LUASOCKET_H
2#define LUASOCKET_H
1/*=========================================================================*\ 3/*=========================================================================*\
4* LuaSocket toolkit
2* Networking support for the Lua language 5* Networking support for the Lua language
3* Diego Nehab 6* Diego Nehab
4* 9/11/1999 7* 9/11/1999
5* 8*
6* RCS ID: $Id$ 9* RCS ID: $Id$
7\*=========================================================================*/ 10\*=========================================================================*/
8#ifndef LUASOCKET_H 11#include <lua.h>
9#define LUASOCKET_H
10 12
11/*-------------------------------------------------------------------------*\ 13/*-------------------------------------------------------------------------*\
12* Current luasocket version 14* Current luasocket version
13\*-------------------------------------------------------------------------*/ 15\*-------------------------------------------------------------------------*/
14#define LUASOCKET_VERSION "LuaSocket 1.5 (alpha)" 16#define LUASOCKET_VERSION "LuaSocket 2.0 (alpha)"
15 17
16/*-------------------------------------------------------------------------*\ 18/*-------------------------------------------------------------------------*\
17* Library's namespace 19* Library's namespace
@@ -28,6 +30,6 @@
28/*-------------------------------------------------------------------------*\ 30/*-------------------------------------------------------------------------*\
29* Initializes the library. 31* Initializes the library.
30\*-------------------------------------------------------------------------*/ 32\*-------------------------------------------------------------------------*/
31LUASOCKET_API int luaopen_socketlib(lua_State *L); 33LUASOCKET_API int luaopen_socket(lua_State *L);
32 34
33#endif /* LUASOCKET_H */ 35#endif /* LUASOCKET_H */
diff --git a/src/select.c b/src/select.c
index 3cabbd1..9769667 100644
--- a/src/select.c
+++ b/src/select.c
@@ -1,5 +1,7 @@
1/*=========================================================================*\ 1/*=========================================================================*\
2* Select implementation 2* Select implementation
3* LuaSocket toolkit
4*
3* RCS ID: $Id$ 5* RCS ID: $Id$
4\*=========================================================================*/ 6\*=========================================================================*/
5#include <string.h> 7#include <string.h>
@@ -12,6 +14,9 @@
12#include "auxiliar.h" 14#include "auxiliar.h"
13#include "select.h" 15#include "select.h"
14 16
17/*=========================================================================*\
18* Internal function prototypes.
19\*=========================================================================*/
15static int meth_set(lua_State *L); 20static int meth_set(lua_State *L);
16static int meth_isset(lua_State *L); 21static int meth_isset(lua_State *L);
17static int c_select(lua_State *L); 22static int c_select(lua_State *L);
@@ -31,6 +36,12 @@ static luaL_reg func[] = {
31 {NULL, NULL} 36 {NULL, NULL}
32}; 37};
33 38
39/*=========================================================================*\
40* Internal function prototypes.
41\*=========================================================================*/
42/*-------------------------------------------------------------------------*\
43* Initializes module
44\*-------------------------------------------------------------------------*/
34void select_open(lua_State *L) 45void select_open(lua_State *L)
35{ 46{
36 /* get select auxiliar lua function from lua code and register 47 /* get select auxiliar lua function from lua code and register
@@ -45,6 +56,9 @@ void select_open(lua_State *L)
45 aux_newclass(L, "select{fd_set}", set); 56 aux_newclass(L, "select{fd_set}", set);
46} 57}
47 58
59/*=========================================================================*\
60* Global Lua functions
61\*=========================================================================*/
48/*-------------------------------------------------------------------------*\ 62/*-------------------------------------------------------------------------*\
49* Waits for a set of sockets until a condition is met or timeout. 63* Waits for a set of sockets until a condition is met or timeout.
50\*-------------------------------------------------------------------------*/ 64\*-------------------------------------------------------------------------*/
@@ -63,10 +77,10 @@ static int global_select(lua_State *L)
63 lua_pushvalue(L, lua_upvalueindex(1)); 77 lua_pushvalue(L, lua_upvalueindex(1));
64 lua_insert(L, 1); 78 lua_insert(L, 1);
65 /* pass fd_set objects */ 79 /* pass fd_set objects */
66 read_fd_set = lua_newuserdata(L, sizeof(fd_set)); 80 read_fd_set = (fd_set *) lua_newuserdata(L, sizeof(fd_set));
67 FD_ZERO(read_fd_set); 81 FD_ZERO(read_fd_set);
68 aux_setclass(L, "select{fd_set}", -1); 82 aux_setclass(L, "select{fd_set}", -1);
69 write_fd_set = lua_newuserdata(L, sizeof(fd_set)); 83 write_fd_set = (fd_set *) lua_newuserdata(L, sizeof(fd_set));
70 FD_ZERO(write_fd_set); 84 FD_ZERO(write_fd_set);
71 aux_setclass(L, "select{fd_set}", -1); 85 aux_setclass(L, "select{fd_set}", -1);
72 /* pass select auxiliar C function */ 86 /* pass select auxiliar C function */
@@ -76,20 +90,9 @@ static int global_select(lua_State *L)
76 return 3; 90 return 3;
77} 91}
78 92
79static int c_select(lua_State *L) 93/*=========================================================================*\
80{ 94* Lua methods
81 int max_fd = (int) lua_tonumber(L, 1); 95\*=========================================================================*/
82 fd_set *read_fd_set = (fd_set *) aux_checkclass(L, "select{fd_set}", 2);
83 fd_set *write_fd_set = (fd_set *) aux_checkclass(L, "select{fd_set}", 3);
84 int timeout = lua_isnil(L, 4) ? -1 : (int)(lua_tonumber(L, 4) * 1000);
85 struct timeval tv;
86 tv.tv_sec = timeout / 1000;
87 tv.tv_usec = (timeout % 1000) * 1000;
88 lua_pushnumber(L, select(max_fd, read_fd_set, write_fd_set, NULL,
89 timeout < 0 ? NULL : &tv));
90 return 1;
91}
92
93static int meth_set(lua_State *L) 96static int meth_set(lua_State *L)
94{ 97{
95 fd_set *set = (fd_set *) aux_checkclass(L, "select{fd_set}", 1); 98 fd_set *set = (fd_set *) aux_checkclass(L, "select{fd_set}", 1);
@@ -107,6 +110,23 @@ static int meth_isset(lua_State *L)
107 return 1; 110 return 1;
108} 111}
109 112
113/*=========================================================================*\
114* Internal functions
115\*=========================================================================*/
116static int c_select(lua_State *L)
117{
118 int max_fd = (int) lua_tonumber(L, 1);
119 fd_set *read_fd_set = (fd_set *) aux_checkclass(L, "select{fd_set}", 2);
120 fd_set *write_fd_set = (fd_set *) aux_checkclass(L, "select{fd_set}", 3);
121 int timeout = lua_isnil(L, 4) ? -1 : (int)(lua_tonumber(L, 4) * 1000);
122 struct timeval tv;
123 tv.tv_sec = timeout / 1000;
124 tv.tv_usec = (timeout % 1000) * 1000;
125 lua_pushnumber(L, select(max_fd, read_fd_set, write_fd_set, NULL,
126 timeout < 0 ? NULL : &tv));
127 return 1;
128}
129
110static void check_obj_tab(lua_State *L, int tabidx) 130static void check_obj_tab(lua_State *L, int tabidx)
111{ 131{
112 if (tabidx < 0) tabidx = lua_gettop(L) + tabidx + 1; 132 if (tabidx < 0) tabidx = lua_gettop(L) + tabidx + 1;
diff --git a/src/select.h b/src/select.h
index 9521fae..0e1eeb4 100644
--- a/src/select.h
+++ b/src/select.h
@@ -1,9 +1,19 @@
1#ifndef SELECT_H
2#define SELECT_H
1/*=========================================================================*\ 3/*=========================================================================*\
2* Select implementation 4* Select implementation
5* LuaSocket toolkit
6*
7* To make the code as simple as possible, the select function is
8* implemented int Lua, with a few helper functions written in C.
9*
10* Each object that can be passed to the select function has to be in the
11* group select{able} and export two methods: fd() and dirty(). Fd returns
12* the descriptor to be passed to the select function. Dirty() should return
13* true if there is data ready for reading (required for buffered input).
14*
3* RCS ID: $Id$ 15* RCS ID: $Id$
4\*=========================================================================*/ 16\*=========================================================================*/
5#ifndef SELECT_H
6#define SELECT_H
7 17
8void select_open(lua_State *L); 18void select_open(lua_State *L);
9 19
diff --git a/src/smtp.lua b/src/smtp.lua
index 604f79b..209825b 100644
--- a/src/smtp.lua
+++ b/src/smtp.lua
@@ -1,6 +1,6 @@
1----------------------------------------------------------------------------- 1-----------------------------------------------------------------------------
2-- SMTP support for the Lua language. 2-- SMTP support for the Lua language.
3-- LuaSocket 1.5 toolkit 3-- LuaSocket toolkit
4-- Author: Diego Nehab 4-- Author: Diego Nehab
5-- Conforming to: RFC 821, LTN7 5-- Conforming to: RFC 821, LTN7
6-- RCS ID: $Id$ 6-- RCS ID: $Id$
diff --git a/src/socket.h b/src/socket.h
index 70ebc52..c7db5f2 100644
--- a/src/socket.h
+++ b/src/socket.h
@@ -1,11 +1,16 @@
1#ifndef SOCK_H
2#define SOCK_H
1/*=========================================================================*\ 3/*=========================================================================*\
2* Socket compatibilization module 4* Socket compatibilization module
5* LuaSocket toolkit
6*
7* BSD Sockets and WinSock are similar, but there are a few irritating
8* differences. Also, not all *nix platforms behave the same. This module
9* (and the associated usocket.h and wsocket.h) factor these differences and
10* creates a interface compatible with the io.h module.
3* 11*
4* RCS ID: $Id$ 12* RCS ID: $Id$
5\*=========================================================================*/ 13\*=========================================================================*/
6#ifndef SOCK_H
7#define SOCK_H
8
9#include "io.h" 14#include "io.h"
10 15
11/*=========================================================================*\ 16/*=========================================================================*\
@@ -32,7 +37,6 @@ int sock_accept(p_sock ps, p_sock pa, SA *addr, socklen_t *addr_len,
32const char *sock_connect(p_sock ps, SA *addr, socklen_t addr_len); 37const char *sock_connect(p_sock ps, SA *addr, socklen_t addr_len);
33const char *sock_bind(p_sock ps, SA *addr, socklen_t addr_len); 38const char *sock_bind(p_sock ps, SA *addr, socklen_t addr_len);
34void sock_listen(p_sock ps, int backlog); 39void sock_listen(p_sock ps, int backlog);
35
36int sock_send(p_sock ps, const char *data, size_t count, 40int sock_send(p_sock ps, const char *data, size_t count,
37 size_t *sent, int timeout); 41 size_t *sent, int timeout);
38int sock_recv(p_sock ps, char *data, size_t count, 42int 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,
41 size_t *sent, SA *addr, socklen_t addr_len, int timeout); 45 size_t *sent, SA *addr, socklen_t addr_len, int timeout);
42int sock_recvfrom(p_sock ps, char *data, size_t count, 46int sock_recvfrom(p_sock ps, char *data, size_t count,
43 size_t *got, SA *addr, socklen_t *addr_len, int timeout); 47 size_t *got, SA *addr, socklen_t *addr_len, int timeout);
44
45void sock_setnonblocking(p_sock ps); 48void sock_setnonblocking(p_sock ps);
46void sock_setblocking(p_sock ps); 49void sock_setblocking(p_sock ps);
47void sock_setreuseaddr(p_sock ps);
48
49const char *sock_hoststrerror(void); 50const char *sock_hoststrerror(void);
50const char *sock_createstrerror(void); 51const char *sock_createstrerror(void);
51const char *sock_bindstrerror(void); 52const char *sock_bindstrerror(void);
diff --git a/src/tcp.c b/src/tcp.c
index dc7683d..28f38f5 100644
--- a/src/tcp.c
+++ b/src/tcp.c
@@ -1,5 +1,6 @@
1/*=========================================================================*\ 1/*=========================================================================*\
2* TCP object 2* TCP object
3* LuaSocket toolkit
3* 4*
4* RCS ID: $Id$ 5* RCS ID: $Id$
5\*=========================================================================*/ 6\*=========================================================================*/
@@ -13,7 +14,6 @@
13#include "auxiliar.h" 14#include "auxiliar.h"
14#include "socket.h" 15#include "socket.h"
15#include "inet.h" 16#include "inet.h"
16#include "error.h"
17#include "tcp.h" 17#include "tcp.h"
18 18
19/*=========================================================================*\ 19/*=========================================================================*\
@@ -28,9 +28,13 @@ static int meth_getpeername(lua_State *L);
28static int meth_receive(lua_State *L); 28static int meth_receive(lua_State *L);
29static int meth_accept(lua_State *L); 29static int meth_accept(lua_State *L);
30static int meth_close(lua_State *L); 30static int meth_close(lua_State *L);
31static int meth_setoption(lua_State *L);
31static int meth_timeout(lua_State *L); 32static int meth_timeout(lua_State *L);
32static int meth_fd(lua_State *L); 33static int meth_fd(lua_State *L);
33static int meth_dirty(lua_State *L); 34static int meth_dirty(lua_State *L);
35static int opt_nodelay(lua_State *L);
36static int opt_keepalive(lua_State *L);
37static int opt_linger(lua_State *L);
34 38
35/* tcp object methods */ 39/* tcp object methods */
36static luaL_reg tcp[] = { 40static luaL_reg tcp[] = {
@@ -45,11 +49,21 @@ static luaL_reg tcp[] = {
45 {"getsockname", meth_getsockname}, 49 {"getsockname", meth_getsockname},
46 {"timeout", meth_timeout}, 50 {"timeout", meth_timeout},
47 {"close", meth_close}, 51 {"close", meth_close},
52 {"setoption", meth_setoption},
53 {"__gc", meth_close},
48 {"fd", meth_fd}, 54 {"fd", meth_fd},
49 {"dirty", meth_dirty}, 55 {"dirty", meth_dirty},
50 {NULL, NULL} 56 {NULL, NULL}
51}; 57};
52 58
59/* socket option handlers */
60static luaL_reg opt[] = {
61 {"keepalive", opt_keepalive},
62 {"nodelay", opt_nodelay},
63 {"linger", opt_linger},
64 {NULL, NULL}
65};
66
53/* functions in library namespace */ 67/* functions in library namespace */
54static luaL_reg func[] = { 68static luaL_reg func[] = {
55 {"tcp", global_create}, 69 {"tcp", global_create},
@@ -71,6 +85,7 @@ void tcp_open(lua_State *L)
71 aux_add2group(L, "tcp{server}", "tcp{any}"); 85 aux_add2group(L, "tcp{server}", "tcp{any}");
72 aux_add2group(L, "tcp{client}", "tcp{client, server}"); 86 aux_add2group(L, "tcp{client}", "tcp{client, server}");
73 aux_add2group(L, "tcp{server}", "tcp{client, server}"); 87 aux_add2group(L, "tcp{server}", "tcp{client, server}");
88 /* both server and client objects are selectable */
74 aux_add2group(L, "tcp{client}", "select{able}"); 89 aux_add2group(L, "tcp{client}", "select{able}");
75 aux_add2group(L, "tcp{server}", "select{able}"); 90 aux_add2group(L, "tcp{server}", "select{able}");
76 /* define library functions */ 91 /* define library functions */
@@ -97,18 +112,80 @@ static int meth_receive(lua_State *L)
97} 112}
98 113
99/*-------------------------------------------------------------------------*\ 114/*-------------------------------------------------------------------------*\
115* Option handlers
116\*-------------------------------------------------------------------------*/
117static int meth_setoption(lua_State *L)
118{
119 return aux_meth_setoption(L, opt);
120}
121
122static int opt_boolean(lua_State *L, int level, int name)
123{
124 p_tcp tcp = (p_tcp) aux_checkgroup(L, "tcp{any}", 1);
125 int val = aux_checkboolean(L, 2);
126 if (setsockopt(tcp->sock, level, name, (char *) &val, sizeof(val)) < 0) {
127 lua_pushnil(L);
128 lua_pushstring(L, "setsockopt failed");
129 return 2;
130 }
131 lua_pushnumber(L, 1);
132 return 1;
133}
134
135/* disables the Nagle algorithm */
136static int opt_nodelay(lua_State *L)
137{
138 struct protoent *pe = getprotobyname("TCP");
139 if (!pe) {
140 lua_pushnil(L);
141 lua_pushstring(L, "getprotobyname");
142 return 2;
143 }
144 return opt_boolean(L, pe->p_proto, TCP_NODELAY);
145}
146
147static int opt_keepalive(lua_State *L)
148{
149 return opt_boolean(L, SOL_SOCKET, SO_KEEPALIVE);
150}
151
152int opt_linger(lua_State *L)
153{
154 p_tcp tcp = (p_tcp) aux_checkclass(L, "tcp{client}", 1);
155 struct linger li;
156 if (!lua_istable(L, 2))
157 luaL_typerror(L, 2, lua_typename(L, LUA_TTABLE));
158 lua_pushstring(L, "onoff");
159 lua_gettable(L, 2);
160 if (!lua_isnumber(L, -1)) luaL_argerror(L, 2, "invalid onoff field");
161 li.l_onoff = (int) lua_tonumber(L, -1);
162 lua_pushstring(L, "linger");
163 lua_gettable(L, 2);
164 if (!lua_isnumber(L, -1)) luaL_argerror(L, 2, "invalid linger field");
165 li.l_linger = (int) lua_tonumber(L, -1);
166 if (setsockopt(tcp->sock, SOL_SOCKET, SO_LINGER,
167 (char *) &li, sizeof(li) < 0)) {
168 lua_pushnil(L);
169 lua_pushstring(L, "setsockopt failed");
170 return 2;
171 }
172 lua_pushnumber(L, 1);
173 return 1;
174}
175
176/*-------------------------------------------------------------------------*\
100* Select support methods 177* Select support methods
101\*-------------------------------------------------------------------------*/ 178\*-------------------------------------------------------------------------*/
102static int meth_fd(lua_State *L) 179static int meth_fd(lua_State *L)
103{ 180{
104 p_tcp tcp = (p_tcp) aux_checkclass(L, "tcp{client, server}", 1); 181 p_tcp tcp = (p_tcp) aux_checkgroup(L, "tcp{client, server}", 1);
105 lua_pushnumber(L, tcp->sock); 182 lua_pushnumber(L, tcp->sock);
106 return 1; 183 return 1;
107} 184}
108 185
109static int meth_dirty(lua_State *L) 186static int meth_dirty(lua_State *L)
110{ 187{
111 p_tcp tcp = (p_tcp) aux_checkclass(L, "tcp{client, server}", 1); 188 p_tcp tcp = (p_tcp) aux_checkgroup(L, "tcp{client, server}", 1);
112 lua_pushboolean(L, !buf_isempty(&tcp->buf)); 189 lua_pushboolean(L, !buf_isempty(&tcp->buf));
113 return 1; 190 return 1;
114} 191}
@@ -207,7 +284,7 @@ static int meth_accept(lua_State *L)
207 if (client->sock == SOCK_INVALID) { 284 if (client->sock == SOCK_INVALID) {
208 if (tm_get(tm) == 0) { 285 if (tm_get(tm) == 0) {
209 lua_pushnil(L); 286 lua_pushnil(L);
210 error_push(L, IO_TIMEOUT); 287 io_pusherror(L, IO_TIMEOUT);
211 return 2; 288 return 2;
212 } 289 }
213 } else break; 290 } else break;
diff --git a/src/tcp.h b/src/tcp.h
index f4319f3..82b88a9 100644
--- a/src/tcp.h
+++ b/src/tcp.h
@@ -1,6 +1,21 @@
1#ifndef TCP_H 1#ifndef TCP_H
2#define TCP_H 2#define TCP_H
3 3/*=========================================================================*\
4* TCP object
5* LuaSocket toolkit
6*
7* The tcp.h module is basicly a glue that puts together modules buffer.h,
8* timeout.h socket.h and inet.h to provide the LuaSocket TCP (AF_INET,
9* SOCK_STREAM) support.
10*
11* Three classes are defined: master, client and server. The master class is
12* a newly created tcp object, that has not been bound or connected. Server
13* objects are tcp objects bound to some local address. Client objects are
14* tcp objects either connected to some address or returned by the accept
15* method of a server object.
16*
17* RCS ID: $Id$
18\*=========================================================================*/
4#include <lua.h> 19#include <lua.h>
5 20
6#include "buffer.h" 21#include "buffer.h"
@@ -17,4 +32,4 @@ typedef t_tcp *p_tcp;
17 32
18void tcp_open(lua_State *L); 33void tcp_open(lua_State *L);
19 34
20#endif 35#endif /* TCP_H */
diff --git a/src/timeout.c b/src/timeout.c
index 1553069..6a30e3a 100644
--- a/src/timeout.c
+++ b/src/timeout.c
@@ -1,8 +1,6 @@
1/*=========================================================================*\ 1/*=========================================================================*\
2* Timeout management functions 2* Timeout management functions
3* Global Lua functions: 3* LuaSocket toolkit
4* _sleep
5* _time
6* 4*
7* RCS ID: $Id$ 5* RCS ID: $Id$
8\*=========================================================================*/ 6\*=========================================================================*/
diff --git a/src/timeout.h b/src/timeout.h
index 43476cb..32eb836 100644
--- a/src/timeout.h
+++ b/src/timeout.h
@@ -1,11 +1,11 @@
1#ifndef TM_H
2#define TM_H
1/*=========================================================================*\ 3/*=========================================================================*\
2* Timeout management functions 4* Timeout management functions
5* LuaSocket toolkit
3* 6*
4* RCS ID: $Id$ 7* RCS ID: $Id$
5\*=========================================================================*/ 8\*=========================================================================*/
6#ifndef TM_H
7#define TM_H
8
9#include <lua.h> 9#include <lua.h>
10 10
11/* timeout control structure */ 11/* timeout control structure */
@@ -28,4 +28,4 @@ int tm_get(p_tm tm);
28int tm_gettime(void); 28int tm_gettime(void);
29int tm_meth_timeout(lua_State *L, p_tm tm); 29int tm_meth_timeout(lua_State *L, p_tm tm);
30 30
31#endif 31#endif /* TM_H */
diff --git a/src/udp.c b/src/udp.c
index 79831e7..b772b2e 100644
--- a/src/udp.c
+++ b/src/udp.c
@@ -1,5 +1,6 @@
1/*=========================================================================*\ 1/*=========================================================================*\
2* UDP object 2* UDP object
3* LuaSocket toolkit
3* 4*
4* RCS ID: $Id$ 5* RCS ID: $Id$
5\*=========================================================================*/ 6\*=========================================================================*/
@@ -13,7 +14,6 @@
13#include "auxiliar.h" 14#include "auxiliar.h"
14#include "socket.h" 15#include "socket.h"
15#include "inet.h" 16#include "inet.h"
16#include "error.h"
17#include "udp.h" 17#include "udp.h"
18 18
19/*=========================================================================*\ 19/*=========================================================================*\
@@ -29,9 +29,12 @@ static int meth_getpeername(lua_State *L);
29static int meth_setsockname(lua_State *L); 29static int meth_setsockname(lua_State *L);
30static int meth_setpeername(lua_State *L); 30static int meth_setpeername(lua_State *L);
31static int meth_close(lua_State *L); 31static int meth_close(lua_State *L);
32static int meth_setoption(lua_State *L);
32static int meth_timeout(lua_State *L); 33static int meth_timeout(lua_State *L);
33static int meth_fd(lua_State *L); 34static int meth_fd(lua_State *L);
34static int meth_dirty(lua_State *L); 35static int meth_dirty(lua_State *L);
36static int opt_dontroute(lua_State *L);
37static int opt_broadcast(lua_State *L);
35 38
36/* udp object methods */ 39/* udp object methods */
37static luaL_reg udp[] = { 40static luaL_reg udp[] = {
@@ -45,11 +48,20 @@ static luaL_reg udp[] = {
45 {"receivefrom", meth_receivefrom}, 48 {"receivefrom", meth_receivefrom},
46 {"timeout", meth_timeout}, 49 {"timeout", meth_timeout},
47 {"close", meth_close}, 50 {"close", meth_close},
51 {"setoption", meth_setoption},
52 {"__gc", meth_close},
48 {"fd", meth_fd}, 53 {"fd", meth_fd},
49 {"dirty", meth_dirty}, 54 {"dirty", meth_dirty},
50 {NULL, NULL} 55 {NULL, NULL}
51}; 56};
52 57
58/* socket options */
59static luaL_reg opt[] = {
60 {"dontroute", opt_dontroute},
61 {"broadcast", opt_broadcast},
62 {NULL, NULL}
63};
64
53/* functions in library namespace */ 65/* functions in library namespace */
54static luaL_reg func[] = { 66static luaL_reg func[] = {
55 {"udp", global_create}, 67 {"udp", global_create},
@@ -91,7 +103,9 @@ static int meth_send(lua_State *L)
91 err = sock_send(&udp->sock, data, count, &sent, tm_get(tm)); 103 err = sock_send(&udp->sock, data, count, &sent, tm_get(tm));
92 if (err == IO_DONE) lua_pushnumber(L, sent); 104 if (err == IO_DONE) lua_pushnumber(L, sent);
93 else lua_pushnil(L); 105 else lua_pushnil(L);
94 error_push(L, err); 106 /* a 'closed' error on an unconnected means the target address was not
107 * accepted by the transport layer */
108 io_pusherror(L, err == IO_CLOSED ? IO_REFUSED : err);
95 return 2; 109 return 2;
96} 110}
97 111
@@ -118,7 +132,9 @@ static int meth_sendto(lua_State *L)
118 (SA *) &addr, sizeof(addr), tm_get(tm)); 132 (SA *) &addr, sizeof(addr), tm_get(tm));
119 if (err == IO_DONE) lua_pushnumber(L, sent); 133 if (err == IO_DONE) lua_pushnumber(L, sent);
120 else lua_pushnil(L); 134 else lua_pushnil(L);
121 error_push(L, err == IO_CLOSED ? IO_REFUSED : err); 135 /* a 'closed' error on an unconnected means the target address was not
136 * accepted by the transport layer */
137 io_pusherror(L, err == IO_CLOSED ? IO_REFUSED : err);
122 return 2; 138 return 2;
123} 139}
124 140
@@ -137,7 +153,7 @@ static int meth_receive(lua_State *L)
137 err = sock_recv(&udp->sock, buffer, count, &got, tm_get(tm)); 153 err = sock_recv(&udp->sock, buffer, count, &got, tm_get(tm));
138 if (err == IO_DONE) lua_pushlstring(L, buffer, got); 154 if (err == IO_DONE) lua_pushlstring(L, buffer, got);
139 else lua_pushnil(L); 155 else lua_pushnil(L);
140 error_push(L, err); 156 io_pusherror(L, err);
141 return 2; 157 return 2;
142} 158}
143 159
@@ -164,7 +180,7 @@ static int meth_receivefrom(lua_State *L)
164 return 3; 180 return 3;
165 } else { 181 } else {
166 lua_pushnil(L); 182 lua_pushnil(L);
167 error_push(L, err); 183 io_pusherror(L, err);
168 return 2; 184 return 2;
169 } 185 }
170} 186}
@@ -174,14 +190,14 @@ static int meth_receivefrom(lua_State *L)
174\*-------------------------------------------------------------------------*/ 190\*-------------------------------------------------------------------------*/
175static int meth_fd(lua_State *L) 191static int meth_fd(lua_State *L)
176{ 192{
177 p_udp udp = (p_udp) aux_checkclass(L, "udp{any}", 1); 193 p_udp udp = (p_udp) aux_checkgroup(L, "udp{any}", 1);
178 lua_pushnumber(L, udp->sock); 194 lua_pushnumber(L, udp->sock);
179 return 1; 195 return 1;
180} 196}
181 197
182static int meth_dirty(lua_State *L) 198static int meth_dirty(lua_State *L)
183{ 199{
184 p_udp udp = (p_udp) aux_checkclass(L, "udp{any}", 1); 200 p_udp udp = (p_udp) aux_checkgroup(L, "udp{any}", 1);
185 (void) udp; 201 (void) udp;
186 lua_pushboolean(L, 0); 202 lua_pushboolean(L, 0);
187 return 1; 203 return 1;
@@ -203,6 +219,37 @@ static int meth_getsockname(lua_State *L)
203} 219}
204 220
205/*-------------------------------------------------------------------------*\ 221/*-------------------------------------------------------------------------*\
222* Option handlers
223\*-------------------------------------------------------------------------*/
224static int meth_setoption(lua_State *L)
225{
226 return aux_meth_setoption(L, opt);
227}
228
229static int opt_boolean(lua_State *L, int level, int name)
230{
231 p_udp udp = (p_udp) aux_checkgroup(L, "udp{any}", 1);
232 int val = aux_checkboolean(L, 2);
233 if (setsockopt(udp->sock, level, name, (char *) &val, sizeof(val)) < 0) {
234 lua_pushnil(L);
235 lua_pushstring(L, "setsockopt failed");
236 return 2;
237 }
238 lua_pushnumber(L, 1);
239 return 1;
240}
241
242static int opt_dontroute(lua_State *L)
243{
244 return opt_boolean(L, SOL_SOCKET, SO_DONTROUTE);
245}
246
247static int opt_broadcast(lua_State *L)
248{
249 return opt_boolean(L, SOL_SOCKET, SO_BROADCAST);
250}
251
252/*-------------------------------------------------------------------------*\
206* Just call tm methods 253* Just call tm methods
207\*-------------------------------------------------------------------------*/ 254\*-------------------------------------------------------------------------*/
208static int meth_timeout(lua_State *L) 255static int meth_timeout(lua_State *L)
diff --git a/src/udp.h b/src/udp.h
index a6f17e2..699e31a 100644
--- a/src/udp.h
+++ b/src/udp.h
@@ -1,6 +1,19 @@
1#ifndef UDP_H 1#ifndef UDP_H
2#define UDP_H 2#define UDP_H
3 3/*=========================================================================*\
4* UDP object
5* LuaSocket toolkit
6*
7* The udp.h module provides LuaSocket with support for UDP protocol
8* (AF_INET, SOCK_DGRAM).
9*
10* Two classes are defined: connected and unconnected. UDP objects are
11* originally unconnected. They can be "connected" to a given address
12* with a call to the setpeername function. The same function can be used to
13* break the connection.
14*
15* RCS ID: $Id$
16\*=========================================================================*/
4#include <lua.h> 17#include <lua.h>
5 18
6#include "timeout.h" 19#include "timeout.h"
@@ -16,4 +29,4 @@ typedef t_udp *p_udp;
16 29
17void udp_open(lua_State *L); 30void udp_open(lua_State *L);
18 31
19#endif 32#endif /* UDP_H */
diff --git a/src/url.lua b/src/url.lua
index 06de9d3..65da57a 100644
--- a/src/url.lua
+++ b/src/url.lua
@@ -1,6 +1,6 @@
1----------------------------------------------------------------------------- 1-----------------------------------------------------------------------------
2-- URI parsing, composition and relative URL resolution 2-- URI parsing, composition and relative URL resolution
3-- LuaSocket 1.5 toolkit. 3-- LuaSocket toolkit.
4-- Author: Diego Nehab 4-- Author: Diego Nehab
5-- Conforming to: RFC 2396, LTN7 5-- Conforming to: RFC 2396, LTN7
6-- RCS ID: $Id$ 6-- RCS ID: $Id$
diff --git a/src/usocket.c b/src/usocket.c
index 062a0ff..cdd550c 100644
--- a/src/usocket.c
+++ b/src/usocket.c
@@ -1,49 +1,78 @@
1/*=========================================================================*\
2* Socket compatibilization module for Unix
3* LuaSocket toolkit
4*
5* RCS ID: $Id$
6\*=========================================================================*/
1#include <string.h> 7#include <string.h>
2 8
3#include "socket.h" 9#include "socket.h"
4 10
11/*-------------------------------------------------------------------------*\
12* Initializes module
13\*-------------------------------------------------------------------------*/
5int sock_open(void) 14int sock_open(void)
6{ 15{
7 /* instals a handler to ignore sigpipe. */ 16 /* instals a handler to ignore sigpipe or it will crash us */
8 struct sigaction new; 17 struct sigaction ignore;
9 memset(&new, 0, sizeof(new)); 18 memset(&ignore, 0, sizeof(ignore));
10 new.sa_handler = SIG_IGN; 19 ignore.sa_handler = SIG_IGN;
11 sigaction(SIGPIPE, &new, NULL); 20 sigaction(SIGPIPE, &ignore, NULL);
12 return 1; 21 return 1;
13} 22}
14 23
24/*-------------------------------------------------------------------------*\
25* Close and inutilize socket
26\*-------------------------------------------------------------------------*/
15void sock_destroy(p_sock ps) 27void sock_destroy(p_sock ps)
16{ 28{
17 close(*ps); 29 close(*ps);
30 *ps = SOCK_INVALID;
18} 31}
19 32
33/*-------------------------------------------------------------------------*\
34* Creates and sets up a socket
35\*-------------------------------------------------------------------------*/
20const char *sock_create(p_sock ps, int domain, int type, int protocol) 36const char *sock_create(p_sock ps, int domain, int type, int protocol)
21{ 37{
38 int val = 1;
22 t_sock sock = socket(domain, type, protocol); 39 t_sock sock = socket(domain, type, protocol);
23 if (sock == SOCK_INVALID) return sock_createstrerror(); 40 if (sock == SOCK_INVALID) return sock_createstrerror();
24 *ps = sock; 41 *ps = sock;
25 sock_setnonblocking(ps); 42 sock_setnonblocking(ps);
26 sock_setreuseaddr(ps); 43 setsockopt(*ps, SOL_SOCKET, SO_REUSEADDR, (char *) &val, sizeof(val));
27 return NULL; 44 return NULL;
28} 45}
29 46
47/*-------------------------------------------------------------------------*\
48* Connects or returns error message
49\*-------------------------------------------------------------------------*/
30const char *sock_connect(p_sock ps, SA *addr, socklen_t addr_len) 50const char *sock_connect(p_sock ps, SA *addr, socklen_t addr_len)
31{ 51{
32 if (connect(*ps, addr, addr_len) < 0) return sock_connectstrerror(); 52 if (connect(*ps, addr, addr_len) < 0) return sock_connectstrerror();
33 else return NULL; 53 else return NULL;
34} 54}
35 55
56/*-------------------------------------------------------------------------*\
57* Binds or returns error message
58\*-------------------------------------------------------------------------*/
36const char *sock_bind(p_sock ps, SA *addr, socklen_t addr_len) 59const char *sock_bind(p_sock ps, SA *addr, socklen_t addr_len)
37{ 60{
38 if (bind(*ps, addr, addr_len) < 0) return sock_bindstrerror(); 61 if (bind(*ps, addr, addr_len) < 0) return sock_bindstrerror();
39 else return NULL; 62 else return NULL;
40} 63}
41 64
65/*-------------------------------------------------------------------------*\
66*
67\*-------------------------------------------------------------------------*/
42void sock_listen(p_sock ps, int backlog) 68void sock_listen(p_sock ps, int backlog)
43{ 69{
44 listen(*ps, backlog); 70 listen(*ps, backlog);
45} 71}
46 72
73/*-------------------------------------------------------------------------*\
74* Accept with timeout
75\*-------------------------------------------------------------------------*/
47int sock_accept(p_sock ps, p_sock pa, SA *addr, socklen_t *addr_len, 76int sock_accept(p_sock ps, p_sock pa, SA *addr, socklen_t *addr_len,
48 int timeout) 77 int timeout)
49{ 78{
@@ -65,6 +94,9 @@ int sock_accept(p_sock ps, p_sock pa, SA *addr, socklen_t *addr_len,
65 else return IO_DONE; 94 else return IO_DONE;
66} 95}
67 96
97/*-------------------------------------------------------------------------*\
98* Send with timeout
99\*-------------------------------------------------------------------------*/
68int sock_send(p_sock ps, const char *data, size_t count, size_t *sent, 100int sock_send(p_sock ps, const char *data, size_t count, size_t *sent,
69 int timeout) 101 int timeout)
70{ 102{
@@ -99,6 +131,9 @@ int sock_send(p_sock ps, const char *data, size_t count, size_t *sent,
99 } 131 }
100} 132}
101 133
134/*-------------------------------------------------------------------------*\
135* Sendto with timeout
136\*-------------------------------------------------------------------------*/
102int sock_sendto(p_sock ps, const char *data, size_t count, size_t *sent, 137int sock_sendto(p_sock ps, const char *data, size_t count, size_t *sent,
103 SA *addr, socklen_t addr_len, int timeout) 138 SA *addr, socklen_t addr_len, int timeout)
104{ 139{
@@ -133,6 +168,9 @@ int sock_sendto(p_sock ps, const char *data, size_t count, size_t *sent,
133 } 168 }
134} 169}
135 170
171/*-------------------------------------------------------------------------*\
172* Receive with timeout
173\*-------------------------------------------------------------------------*/
136int sock_recv(p_sock ps, char *data, size_t count, size_t *got, int timeout) 174int sock_recv(p_sock ps, char *data, size_t count, size_t *got, int timeout)
137{ 175{
138 t_sock sock = *ps; 176 t_sock sock = *ps;
@@ -160,6 +198,9 @@ int sock_recv(p_sock ps, char *data, size_t count, size_t *got, int timeout)
160 } 198 }
161} 199}
162 200
201/*-------------------------------------------------------------------------*\
202* Recvfrom with timeout
203\*-------------------------------------------------------------------------*/
163int sock_recvfrom(p_sock ps, char *data, size_t count, size_t *got, 204int sock_recvfrom(p_sock ps, char *data, size_t count, size_t *got,
164 SA *addr, socklen_t *addr_len, int timeout) 205 SA *addr, socklen_t *addr_len, int timeout)
165{ 206{
@@ -188,6 +229,29 @@ int sock_recvfrom(p_sock ps, char *data, size_t count, size_t *got,
188 } 229 }
189} 230}
190 231
232/*-------------------------------------------------------------------------*\
233* Put socket into blocking mode
234\*-------------------------------------------------------------------------*/
235void sock_setblocking(p_sock ps)
236{
237 int flags = fcntl(*ps, F_GETFL, 0);
238 flags &= (~(O_NONBLOCK));
239 fcntl(*ps, F_SETFL, flags);
240}
241
242/*-------------------------------------------------------------------------*\
243* Put socket into non-blocking mode
244\*-------------------------------------------------------------------------*/
245void sock_setnonblocking(p_sock ps)
246{
247 int flags = fcntl(*ps, F_GETFL, 0);
248 flags |= O_NONBLOCK;
249 fcntl(*ps, F_SETFL, flags);
250}
251
252/*-------------------------------------------------------------------------*\
253* Error translation functions
254\*-------------------------------------------------------------------------*/
191const char *sock_hoststrerror(void) 255const char *sock_hoststrerror(void)
192{ 256{
193 switch (h_errno) { 257 switch (h_errno) {
@@ -238,23 +302,3 @@ const char *sock_connectstrerror(void)
238 default: return "unknown error"; 302 default: return "unknown error";
239 } 303 }
240} 304}
241
242void sock_setreuseaddr(p_sock ps)
243{
244 int val = 1;
245 setsockopt(*ps, SOL_SOCKET, SO_REUSEADDR, (char *)&val, sizeof(val));
246}
247
248void sock_setblocking(p_sock ps)
249{
250 int flags = fcntl(*ps, F_GETFL, 0);
251 flags &= (~(O_NONBLOCK));
252 fcntl(*ps, F_SETFL, flags);
253}
254
255void sock_setnonblocking(p_sock ps)
256{
257 int flags = fcntl(*ps, F_GETFL, 0);
258 flags |= O_NONBLOCK;
259 fcntl(*ps, F_SETFL, flags);
260}
diff --git a/src/usocket.h b/src/usocket.h
index 034ae74..85b7caa 100644
--- a/src/usocket.h
+++ b/src/usocket.h
@@ -1,10 +1,11 @@
1#ifndef USOCKET_H
2#define USOCKET_H
1/*=========================================================================*\ 3/*=========================================================================*\
2* Socket compatibilization module for Unix 4* Socket compatibilization module for Unix
5* LuaSocket toolkit
3* 6*
4* RCS ID: $Id$ 7* RCS ID: $Id$
5\*=========================================================================*/ 8\*=========================================================================*/
6#ifndef USOCKET_H
7#define USOCKET_H
8 9
9/*=========================================================================*\ 10/*=========================================================================*\
10* BSD include files 11* BSD include files
@@ -30,9 +31,11 @@
30/* IP stuff*/ 31/* IP stuff*/
31#include <netinet/in.h> 32#include <netinet/in.h>
32#include <arpa/inet.h> 33#include <arpa/inet.h>
34/* TCP options (nagle algorithm disable) */
35#include <netinet/tcp.h>
33 36
34#ifdef __APPLE__ 37#ifdef __APPLE__
35/* for some reason socklen_t is not defined in mac os x */ 38/* for some reason socklen_t is not defined in Mac Os X */
36typedef int socklen_t; 39typedef int socklen_t;
37#endif 40#endif
38 41
diff --git a/src/wsocket.c b/src/wsocket.c
index 56e65ec..2ce828e 100644
--- a/src/wsocket.c
+++ b/src/wsocket.c
@@ -1,14 +1,21 @@
1/*=========================================================================*\
2* Socket compatibilization module for Win32
3* LuaSocket toolkit
4*
5* RCS ID: $Id$
6\*=========================================================================*/
1#include <string.h> 7#include <string.h>
2 8
3#include "socket.h" 9#include "socket.h"
4 10
11/*-------------------------------------------------------------------------*\
12* Initializes module
13\*-------------------------------------------------------------------------*/
5int sock_open(void) 14int sock_open(void)
6{ 15{
7 WORD wVersionRequested;
8 WSADATA wsaData; 16 WSADATA wsaData;
9 int err; 17 WORD wVersionRequested = MAKEWORD(2, 0);
10 wVersionRequested = MAKEWORD(2, 0); 18 int err = WSAStartup(wVersionRequested, &wsaData );
11 err = WSAStartup(wVersionRequested, &wsaData );
12 if (err != 0) return 0; 19 if (err != 0) return 0;
13 if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 0) { 20 if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 0) {
14 WSACleanup(); 21 WSACleanup();
@@ -17,38 +24,58 @@ int sock_open(void)
17 return 1; 24 return 1;
18} 25}
19 26
27/*-------------------------------------------------------------------------*\
28* Close and inutilize socket
29\*-------------------------------------------------------------------------*/
20void sock_destroy(p_sock ps) 30void sock_destroy(p_sock ps)
21{ 31{
22 closesocket(*ps); 32 closesocket(*ps);
33 *ps = SOCK_INVALID;
23} 34}
24 35
36/*-------------------------------------------------------------------------*\
37* Creates and sets up a socket
38\*-------------------------------------------------------------------------*/
25const char *sock_create(p_sock ps, int domain, int type, int protocol) 39const char *sock_create(p_sock ps, int domain, int type, int protocol)
26{ 40{
41 int val = 1;
27 t_sock sock = socket(domain, type, protocol); 42 t_sock sock = socket(domain, type, protocol);
28 if (sock == SOCK_INVALID) return sock_createstrerror(); 43 if (sock == SOCK_INVALID) return sock_createstrerror();
29 *ps = sock; 44 *ps = sock;
30 sock_setnonblocking(ps); 45 sock_setnonblocking(ps);
31 sock_setreuseaddr(ps); 46 setsockopt(*ps, SOL_SOCKET, SO_REUSEADDR, (char *) &val, sizeof(val));
32 return NULL; 47 return NULL;
33} 48}
34 49
50/*-------------------------------------------------------------------------*\
51* Connects or returns error message
52\*-------------------------------------------------------------------------*/
35const char *sock_connect(p_sock ps, SA *addr, socklen_t addr_len) 53const char *sock_connect(p_sock ps, SA *addr, socklen_t addr_len)
36{ 54{
37 if (connect(*ps, addr, addr_len) < 0) return sock_connectstrerror(); 55 if (connect(*ps, addr, addr_len) < 0) return sock_connectstrerror();
38 else return NULL; 56 else return NULL;
39} 57}
40 58
59/*-------------------------------------------------------------------------*\
60* Binds or returns error message
61\*-------------------------------------------------------------------------*/
41const char *sock_bind(p_sock ps, SA *addr, socklen_t addr_len) 62const char *sock_bind(p_sock ps, SA *addr, socklen_t addr_len)
42{ 63{
43 if (bind(*ps, addr, addr_len) < 0) return sock_bindstrerror(); 64 if (bind(*ps, addr, addr_len) < 0) return sock_bindstrerror();
44 else return NULL; 65 else return NULL;
45} 66}
46 67
68/*-------------------------------------------------------------------------*\
69*
70\*-------------------------------------------------------------------------*/
47void sock_listen(p_sock ps, int backlog) 71void sock_listen(p_sock ps, int backlog)
48{ 72{
49 listen(*ps, backlog); 73 listen(*ps, backlog);
50} 74}
51 75
76/*-------------------------------------------------------------------------*\
77* Accept with timeout
78\*-------------------------------------------------------------------------*/
52int sock_accept(p_sock ps, p_sock pa, SA *addr, socklen_t *addr_len, 79int sock_accept(p_sock ps, p_sock pa, SA *addr, socklen_t *addr_len,
53 int timeout) 80 int timeout)
54{ 81{
@@ -70,6 +97,9 @@ int sock_accept(p_sock ps, p_sock pa, SA *addr, socklen_t *addr_len,
70 else return IO_DONE; 97 else return IO_DONE;
71} 98}
72 99
100/*-------------------------------------------------------------------------*\
101* Send with timeout
102\*-------------------------------------------------------------------------*/
73int sock_send(p_sock ps, const char *data, size_t count, size_t *sent, 103int sock_send(p_sock ps, const char *data, size_t count, size_t *sent,
74 int timeout) 104 int timeout)
75{ 105{
@@ -104,6 +134,9 @@ int sock_send(p_sock ps, const char *data, size_t count, size_t *sent,
104 } 134 }
105} 135}
106 136
137/*-------------------------------------------------------------------------*\
138* Sendto with timeout
139\*-------------------------------------------------------------------------*/
107int sock_sendto(p_sock ps, const char *data, size_t count, size_t *sent, 140int sock_sendto(p_sock ps, const char *data, size_t count, size_t *sent,
108 SA *addr, socklen_t addr_len, int timeout) 141 SA *addr, socklen_t addr_len, int timeout)
109{ 142{
@@ -138,6 +171,9 @@ int sock_sendto(p_sock ps, const char *data, size_t count, size_t *sent,
138 } 171 }
139} 172}
140 173
174/*-------------------------------------------------------------------------*\
175* Receive with timeout
176\*-------------------------------------------------------------------------*/
141int sock_recv(p_sock ps, char *data, size_t count, size_t *got, int timeout) 177int sock_recv(p_sock ps, char *data, size_t count, size_t *got, int timeout)
142{ 178{
143 t_sock sock = *ps; 179 t_sock sock = *ps;
@@ -165,6 +201,9 @@ int sock_recv(p_sock ps, char *data, size_t count, size_t *got, int timeout)
165 } 201 }
166} 202}
167 203
204/*-------------------------------------------------------------------------*\
205* Recvfrom with timeout
206\*-------------------------------------------------------------------------*/
168int sock_recvfrom(p_sock ps, char *data, size_t count, size_t *got, 207int sock_recvfrom(p_sock ps, char *data, size_t count, size_t *got,
169 SA *addr, socklen_t *addr_len, int timeout) 208 SA *addr, socklen_t *addr_len, int timeout)
170{ 209{
@@ -193,6 +232,27 @@ int sock_recvfrom(p_sock ps, char *data, size_t count, size_t *got,
193 } 232 }
194} 233}
195 234
235/*-------------------------------------------------------------------------*\
236* Put socket into blocking mode
237\*-------------------------------------------------------------------------*/
238void sock_setblocking(p_sock ps)
239{
240 u_long argp = 0;
241 ioctlsocket(*ps, FIONBIO, &argp);
242}
243
244/*-------------------------------------------------------------------------*\
245* Put socket into non-blocking mode
246\*-------------------------------------------------------------------------*/
247void sock_setnonblocking(p_sock ps)
248{
249 u_long argp = 1;
250 ioctlsocket(*ps, FIONBIO, &argp);
251}
252
253/*-------------------------------------------------------------------------*\
254* Error translation functions
255\*-------------------------------------------------------------------------*/
196const char *sock_hoststrerror(void) 256const char *sock_hoststrerror(void)
197{ 257{
198 switch (WSAGetLastError()) { 258 switch (WSAGetLastError()) {
@@ -241,21 +301,3 @@ const char *sock_connectstrerror(void)
241 default: return "unknown error"; 301 default: return "unknown error";
242 } 302 }
243} 303}
244
245void sock_setreuseaddr(p_sock ps)
246{
247 int val = 1;
248 setsockopt(*ps, SOL_SOCKET, SO_REUSEADDR, (char *)&val, sizeof(val));
249}
250
251void sock_setblocking(p_sock ps)
252{
253 u_long argp = 0;
254 ioctlsocket(*ps, FIONBIO, &argp);
255}
256
257void sock_setnonblocking(p_sock ps)
258{
259 u_long argp = 1;
260 ioctlsocket(*ps, FIONBIO, &argp);
261}
diff --git a/src/wsocket.h b/src/wsocket.h
index ceecae7..d77841e 100644
--- a/src/wsocket.h
+++ b/src/wsocket.h
@@ -1,16 +1,16 @@
1#ifndef WSOCKET_H
2#define WSOCKET_H
1/*=========================================================================*\ 3/*=========================================================================*\
2* Socket compatibilization module for Win32 4* Socket compatibilization module for Win32
5* LuaSocket toolkit
3* 6*
4* RCS ID: $Id$ 7* RCS ID: $Id$
5\*=========================================================================*/ 8\*=========================================================================*/
6#ifndef WSOCKET_H
7#define WSOCKET_H
8 9
9/*=========================================================================*\ 10/*=========================================================================*\
10* WinSock2 include files 11* WinSock include files
11\*=========================================================================*/ 12\*=========================================================================*/
12#include <winsock2.h> 13#include <winsock.h>
13#include <winbase.h>
14 14
15typedef int socklen_t; 15typedef int socklen_t;
16typedef int ssize_t; 16typedef int ssize_t;
diff --git a/test/testclnt.lua b/test/testclnt.lua
index b2b4b18..e38c248 100644
--- a/test/testclnt.lua
+++ b/test/testclnt.lua
@@ -17,12 +17,14 @@ function warn(...)
17 io.write("WARNING: ", s, "\n") 17 io.write("WARNING: ", s, "\n")
18end 18end
19 19
20pad = string.rep(" ", 8192)
21
20function remote(...) 22function remote(...)
21 local s = string.format(unpack(arg)) 23 local s = string.format(unpack(arg))
22 s = string.gsub(s, "\n", ";") 24 s = string.gsub(s, "\n", ";")
23 s = string.gsub(s, "%s+", " ") 25 s = string.gsub(s, "%s+", " ")
24 s = string.gsub(s, "^%s*", "") 26 s = string.gsub(s, "^%s*", "")
25 control:send(s, "\n") 27 control:send(pad, s, "\n")
26 control:receive() 28 control:receive()
27end 29end
28 30
@@ -82,16 +84,19 @@ function reconnect()
82 remote [[ 84 remote [[
83 if data then data:close() data = nil end 85 if data then data:close() data = nil end
84 data = server:accept() 86 data = server:accept()
87 data:setoption("nodelay", true)
85 ]] 88 ]]
86 data, err = socket.connect(host, port) 89 data, err = socket.connect(host, port)
87 if not data then fail(err) 90 if not data then fail(err)
88 else pass("connected!") end 91 else pass("connected!") end
92 data:setoption("nodelay", true)
89end 93end
90 94
91pass("attempting control connection...") 95pass("attempting control connection...")
92control, err = socket.connect(host, port) 96control, err = socket.connect(host, port)
93if err then fail(err) 97if err then fail(err)
94else pass("connected!") end 98else pass("connected!") end
99control:setoption("nodelay", true)
95 100
96------------------------------------------------------------------------ 101------------------------------------------------------------------------
97test("method registration") 102test("method registration")
@@ -157,16 +162,21 @@ remote "data:send(str); data:close()"
157end 162end
158 163
159 164
160test_mixed(1) 165--test_mixed(1)
161test_mixed(17) 166--test_mixed(17)
162test_mixed(200) 167--test_mixed(200)
168--test_mixed(4091)
169--test_mixed(80199)
170--test_mixed(4091)
171--test_mixed(200)
172--test_mixed(17)
173--test_mixed(1)
174
175test_mixed(4091)
176test_mixed(4091)
177test_mixed(4091)
163test_mixed(4091) 178test_mixed(4091)
164test_mixed(80199)
165test_mixed(4091) 179test_mixed(4091)
166test_mixed(200)
167test_mixed(17)
168test_mixed(1)
169
170------------------------------------------------------------------------ 180------------------------------------------------------------------------
171test("character line") 181test("character line")
172reconnect() 182reconnect()
diff --git a/test/testsrvr.lua b/test/testsrvr.lua
index 3c40840..39fe274 100644
--- a/test/testsrvr.lua
+++ b/test/testsrvr.lua
@@ -3,9 +3,11 @@ port = port or "8080"
3 3
4server, error = socket.bind(host, port) 4server, error = socket.bind(host, port)
5if not server then print("server: " .. tostring(error)) os.exit() end 5if not server then print("server: " .. tostring(error)) os.exit() end
6ack = "\n"
6while 1 do 7while 1 do
7 print("server: waiting for client connection..."); 8 print("server: waiting for client connection...");
8 control = server:accept() 9 control = server:accept()
10 control:setoption("nodelay", true)
9 while 1 do 11 while 1 do
10 command, error = control:receive() 12 command, error = control:receive()
11 if error then 13 if error then
@@ -13,13 +15,12 @@ while 1 do
13 print("server: closing connection...") 15 print("server: closing connection...")
14 break 16 break
15 end 17 end
16 sent, error = control:send("\n") 18 sent, error = control:send(ack)
17 if error then 19 if error then
18 control:close() 20 control:close()
19 print("server: closing connection...") 21 print("server: closing connection...")
20 break 22 break
21 end 23 end
22 print(command);
23 (loadstring(command))() 24 (loadstring(command))()
24 end 25 end
25end 26end