aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/makefile66
-rw-r--r--src/mime.lua1
-rw-r--r--src/options.c60
-rw-r--r--src/options.h10
-rw-r--r--src/serial.c183
-rw-r--r--src/socket.h3
-rw-r--r--src/tcp.c16
-rw-r--r--src/udp.c6
-rw-r--r--src/unix.c8
-rw-r--r--src/unix.h2
-rw-r--r--src/usocket.c76
11 files changed, 390 insertions, 41 deletions
diff --git a/src/makefile b/src/makefile
index b7c22da..a38ff98 100644
--- a/src/makefile
+++ b/src/makefile
@@ -1,30 +1,35 @@
1PLAT?=macosx 1PLAT?=macosx
2LUAV?=5.1
3prefix=/usr/local
4#prefix=/opt/local
5#prefix=.
2 6
3INSTALL_DATA=cp 7LUAINC_macosx=/usr/local/include
4INSTALL_EXEC=cp
5#INSTALL_TOP=/opt/local
6INSTALL_TOP=./
7
8#LUAINC_macosx=/opt/local/include 8#LUAINC_macosx=/opt/local/include
9LUAINC_macosx=../../../../projects/lua_env/luaenv/lua_versions/lua-5.2.0-beta/src 9#LUAINC_macosx=../../../../projects/lua_env/luaenv/lua_versions/lua-5.2.0-beta/src
10#LUAINC_macosx=../../../../projects/lua_env/luaenv/lua_versions/lua-5.1.4/src 10#LUAINC_macosx=../../../../projects/lua_env/luaenv/lua_versions/lua-5.1.4/src
11 11
12LUAINC_linux=/usr/include/lua5.1 12#LUAINC_linux=/usr/local/include/lua$(LUAV)
13LUAINC_linux=/usr/include/lua$(LUAV)
14#LUAINC_linux=/usr/local/include
15
13LUAINC_win32="../../lua-5.1.3/src" 16LUAINC_win32="../../lua-5.1.3/src"
14LUALIB_win32="../../lua-5.1.3" 17LUALIB_win32="../../lua-5.1.3"
15 18
16#------ 19#------
17# Install directories 20# Install directories
18# 21#
19#INSTALL_TOP_SHARE=$(INSTALL_TOP)/share/lua/5.1 22
20#INSTALL_TOP_LIB=$(INSTALL_TOP)/lib/lua/5.1 23INSTALL_DATA=cp
21INSTALL_TOP_SHARE=$(INSTALL_TOP)/share/lua/5.2 24INSTALL_EXEC=cp
22INSTALL_TOP_LIB=$(INSTALL_TOP)/lib/lua/5.2 25INSTALL_TOP=$(DESTDIR)$(prefix)
26
27INSTALL_TOP_SHARE=$(INSTALL_TOP)/share/lua/$(LUAV)
28INSTALL_TOP_LIB=$(INSTALL_TOP)/lib/lua/$(LUAV)
23 29
24INSTALL_SOCKET_SHARE=$(INSTALL_TOP_SHARE)/socket 30INSTALL_SOCKET_SHARE=$(INSTALL_TOP_SHARE)/socket
25INSTALL_SOCKET_LIB=$(INSTALL_TOP_LIB)/socket 31INSTALL_SOCKET_LIB=$(INSTALL_TOP_LIB)/socket
26#INSTALL_MIME_SHARE=$(INSTALL_TOP_SHARE)/mime 32INSTALL_MIME_SHARE=$(INSTALL_TOP_SHARE)/mime
27INSTALL_MIME_SHARE=$(INSTALL_TOP_SHARE)/foo/mime
28INSTALL_MIME_LIB=$(INSTALL_TOP_LIB)/mime 33INSTALL_MIME_LIB=$(INSTALL_TOP_LIB)/mime
29 34
30#------ 35#------
@@ -78,7 +83,7 @@ LDFLAGS_win32= /nologo /link /NOLOGO /DLL /INCREMENTAL:NO \
78 /MANIFESTFILE:"intermediate.manifest" \ 83 /MANIFESTFILE:"intermediate.manifest" \
79 /MANIFESTUAC:"level='asInvoker' uiAccess='false'" \ 84 /MANIFESTUAC:"level='asInvoker' uiAccess='false'" \
80 /SUBSYSTEM:WINDOWS /OPT:REF /OPT:ICF /DYNAMICBASE:NO \ 85 /SUBSYSTEM:WINDOWS /OPT:REF /OPT:ICF /DYNAMICBASE:NO \
81 /MACHINE:X86 ws2_32.lib lua5.1.lib /OUT: 86 /MACHINE:X86 ws2_32.lib lua$(LUAV).lib /OUT:
82LD_win32=cl 87LD_win32=cl
83SOCKET_win32=wsocket.obj 88SOCKET_win32=wsocket.obj
84 89
@@ -97,6 +102,7 @@ MIME_V=1.0.3
97SOCKET_SO=socket.$(SO).$(SOCKET_V) 102SOCKET_SO=socket.$(SO).$(SOCKET_V)
98MIME_SO=mime.$(SO).$(MIME_V) 103MIME_SO=mime.$(SO).$(MIME_V)
99UNIX_SO=unix.$(SO) 104UNIX_SO=unix.$(SO)
105SERIAL_SO=serial.$(SO)
100SOCKET=$(SOCKET_$(PLAT)) 106SOCKET=$(SOCKET_$(PLAT))
101 107
102#------ 108#------
@@ -118,7 +124,7 @@ SOCKET_OBJS= \
118 timeout.$(O) \ 124 timeout.$(O) \
119 buffer.$(O) \ 125 buffer.$(O) \
120 io.$(O) \ 126 io.$(O) \
121 auxiliar.$(O) \ 127 auxiliar.$(O) \
122 options.$(O) \ 128 options.$(O) \
123 inet.$(O) \ 129 inet.$(O) \
124 $(SOCKET) \ 130 $(SOCKET) \
@@ -148,6 +154,19 @@ UNIX_OBJS=\
148 lua_typeerror.$(O) 154 lua_typeerror.$(O)
149 155
150#------ 156#------
157# Modules belonging to serial (device streams)
158#
159SERIAL_OBJS:=\
160 buffer.$(O) \
161 auxiliar.$(O) \
162 options.$(O) \
163 timeout.$(O) \
164 io.$(O) \
165 usocket.$(O) \
166 serial.$(O) \
167 lua_typeerror.$(O)
168
169#------
151# Files to install 170# Files to install
152# 171#
153TO_SOCKET_SHARE= \ 172TO_SOCKET_SHARE= \
@@ -169,13 +188,13 @@ TO_TOP_SHARE= \
169default: $(PLAT) 188default: $(PLAT)
170 189
171macosx: 190macosx:
172 $(MAKE) all PLAT=macosx 191 $(MAKE) all-unix PLAT=macosx
173 192
174win32: 193win32:
175 $(MAKE) all PLAT=win32 194 $(MAKE) all PLAT=win32
176 195
177linux: 196linux:
178 $(MAKE) all PLAT=linux 197 $(MAKE) all-unix PLAT=linux
179 198
180none: 199none:
181 @echo "Please run" 200 @echo "Please run"
@@ -191,9 +210,14 @@ $(SOCKET_SO): $(SOCKET_OBJS)
191$(MIME_SO): $(MIME_OBJS) 210$(MIME_SO): $(MIME_OBJS)
192 $(LD) $(MIME_OBJS) $(LDFLAGS)$@ 211 $(LD) $(MIME_OBJS) $(LDFLAGS)$@
193 212
213all-unix: all $(UNIX_SO) $(SERIAL_SO)
214
194$(UNIX_SO): $(UNIX_OBJS) 215$(UNIX_SO): $(UNIX_OBJS)
195 $(LD) $(UNIX_OBJS) $(LDFLAGS)$@ 216 $(LD) $(UNIX_OBJS) $(LDFLAGS)$@
196 217
218$(SERIAL_SO): $(SERIAL_OBJS)
219 $(LD) $(SERIAL_OBJS) $(LDFLAGS)$@
220
197install: 221install:
198 mkdir -p $(INSTALL_TOP_SHARE) 222 mkdir -p $(INSTALL_TOP_SHARE)
199 $(INSTALL_DATA) $(TO_TOP_SHARE) $(INSTALL_TOP_SHARE) 223 $(INSTALL_DATA) $(TO_TOP_SHARE) $(INSTALL_TOP_SHARE)
@@ -204,12 +228,16 @@ install:
204 mkdir -p $(INSTALL_MIME_LIB) 228 mkdir -p $(INSTALL_MIME_LIB)
205 $(INSTALL_EXEC) $(MIME_SO) $(INSTALL_MIME_LIB)/core.$(SO) 229 $(INSTALL_EXEC) $(MIME_SO) $(INSTALL_MIME_LIB)/core.$(SO)
206 230
231install-unix: install
232 $(INSTALL_EXEC) $(UNIX_SO) $(INSTALL_SOCKET_LIB)/$(UNIX_SO)
233 $(INSTALL_EXEC) $(SERIAL_SO) $(INSTALL_SOCKET_LIB)/$(SERIAL_SO)
234
207local: 235local:
208 $(MAKE) install INSTALL_TOP_LIB=.. INSTALL_TOP_SHARE=.. 236 $(MAKE) install INSTALL_TOP_LIB=.. INSTALL_TOP_SHARE=..
209 237
210clean: 238clean:
211 rm -f $(SOCKET_SO) $(SOCKET_OBJS) 239 rm -f $(SOCKET_SO) $(SOCKET_OBJS)
212 rm -f $(MIME_SO) $(UNIX_SO) $(MIME_OBJS) $(UNIX_OBJS) 240 rm -f $(MIME_SO) $(UNIX_SO) $(SERIAL_SO) $(MIME_OBJS) $(UNIX_OBJS)
213 241
214.PHONY: all $(PLATS) default clean echo none 242.PHONY: all $(PLATS) default clean echo none
215 243
@@ -228,6 +256,8 @@ mime.$(O): mime.c mime.h
228options.$(O): options.c auxiliar.h options.h socket.h io.h \ 256options.$(O): options.c auxiliar.h options.h socket.h io.h \
229 timeout.h usocket.h inet.h 257 timeout.h usocket.h inet.h
230select.$(O): select.c socket.h io.h timeout.h usocket.h select.h 258select.$(O): select.c socket.h io.h timeout.h usocket.h select.h
259serial.$(O): serial.c auxiliar.h socket.h io.h timeout.h usocket.h \
260 options.h unix.h buffer.h
231tcp.$(O): tcp.c auxiliar.h socket.h io.h timeout.h usocket.h \ 261tcp.$(O): tcp.c auxiliar.h socket.h io.h timeout.h usocket.h \
232 inet.h options.h tcp.h buffer.h 262 inet.h options.h tcp.h buffer.h
233timeout.$(O): timeout.c auxiliar.h timeout.h 263timeout.$(O): timeout.c auxiliar.h timeout.h
diff --git a/src/mime.lua b/src/mime.lua
index 169eda2..218b38a 100644
--- a/src/mime.lua
+++ b/src/mime.lua
@@ -11,7 +11,6 @@
11local base = _G 11local base = _G
12local ltn12 = require("ltn12") 12local ltn12 = require("ltn12")
13local mime = require("mime.core") 13local mime = require("mime.core")
14local io = require("io")
15local string = require("string") 14local string = require("string")
16module("mime") 15module("mime")
17 16
diff --git a/src/options.c b/src/options.c
index 801adf9..ab9e621 100644
--- a/src/options.c
+++ b/src/options.c
@@ -21,6 +21,8 @@ static int opt_setboolean(lua_State *L, p_socket ps, int level, int name);
21static int opt_getboolean(lua_State *L, p_socket ps, int level, int name); 21static int opt_getboolean(lua_State *L, p_socket ps, int level, int name);
22static int opt_set(lua_State *L, p_socket ps, int level, int name, 22static int opt_set(lua_State *L, p_socket ps, int level, int name,
23 void *val, int len); 23 void *val, int len);
24static int opt_get(lua_State *L, p_socket ps, int level, int name,
25 void *val, int* len);
24 26
25/*=========================================================================*\ 27/*=========================================================================*\
26* Exported functions 28* Exported functions
@@ -60,23 +62,43 @@ int opt_set_reuseaddr(lua_State *L, p_socket ps)
60 return opt_setboolean(L, ps, SOL_SOCKET, SO_REUSEADDR); 62 return opt_setboolean(L, ps, SOL_SOCKET, SO_REUSEADDR);
61} 63}
62 64
65int opt_get_reuseaddr(lua_State *L, p_socket ps)
66{
67 return opt_getboolean(L, ps, SOL_SOCKET, SO_REUSEADDR);
68}
69
63/* enables reuse of local port */ 70/* enables reuse of local port */
64int opt_set_reuseport(lua_State *L, p_socket ps) 71int opt_set_reuseport(lua_State *L, p_socket ps)
65{ 72{
66 return opt_setboolean(L, ps, SOL_SOCKET, SO_REUSEPORT); 73 return opt_setboolean(L, ps, SOL_SOCKET, SO_REUSEPORT);
67} 74}
68 75
76int opt_get_reuseport(lua_State *L, p_socket ps)
77{
78 return opt_getboolean(L, ps, SOL_SOCKET, SO_REUSEPORT);
79}
80
69/* disables the Naggle algorithm */ 81/* disables the Naggle algorithm */
70int opt_set_tcp_nodelay(lua_State *L, p_socket ps) 82int opt_set_tcp_nodelay(lua_State *L, p_socket ps)
71{ 83{
72 return opt_setboolean(L, ps, IPPROTO_TCP, TCP_NODELAY); 84 return opt_setboolean(L, ps, IPPROTO_TCP, TCP_NODELAY);
73} 85}
74 86
87int opt_get_tcp_nodelay(lua_State *L, p_socket ps)
88{
89 return opt_getboolean(L, ps, IPPROTO_TCP, TCP_NODELAY);
90}
91
75int opt_set_keepalive(lua_State *L, p_socket ps) 92int opt_set_keepalive(lua_State *L, p_socket ps)
76{ 93{
77 return opt_setboolean(L, ps, SOL_SOCKET, SO_KEEPALIVE); 94 return opt_setboolean(L, ps, SOL_SOCKET, SO_KEEPALIVE);
78} 95}
79 96
97int opt_get_keepalive(lua_State *L, p_socket ps)
98{
99 return opt_getboolean(L, ps, SOL_SOCKET, SO_KEEPALIVE);
100}
101
80int opt_set_dontroute(lua_State *L, p_socket ps) 102int opt_set_dontroute(lua_State *L, p_socket ps)
81{ 103{
82 return opt_setboolean(L, ps, SOL_SOCKET, SO_DONTROUTE); 104 return opt_setboolean(L, ps, SOL_SOCKET, SO_DONTROUTE);
@@ -114,6 +136,21 @@ int opt_set_linger(lua_State *L, p_socket ps)
114 return opt_set(L, ps, SOL_SOCKET, SO_LINGER, (char *) &li, sizeof(li)); 136 return opt_set(L, ps, SOL_SOCKET, SO_LINGER, (char *) &li, sizeof(li));
115} 137}
116 138
139int opt_get_linger(lua_State *L, p_socket ps)
140{
141 struct linger li; /* obj, name */
142 int len = sizeof(li);
143 int err = opt_get(L, ps, SOL_SOCKET, SO_LINGER, (char *) &li, &len);
144 if (err)
145 return err;
146 lua_newtable(L);
147 lua_pushboolean(L, li.l_onoff);
148 lua_setfield(L, -2, "on");
149 lua_pushinteger(L, li.l_linger);
150 lua_setfield(L, -2, "timeout");
151 return 1;
152}
153
117int opt_set_ip_multicast_ttl(lua_State *L, p_socket ps) 154int opt_set_ip_multicast_ttl(lua_State *L, p_socket ps)
118{ 155{
119 int val = (int) luaL_checknumber(L, 3); /* obj, name, int */ 156 int val = (int) luaL_checknumber(L, 3); /* obj, name, int */
@@ -185,6 +222,19 @@ static int opt_setmembership(lua_State *L, p_socket ps, int level, int name)
185} 222}
186 223
187static 224static
225int opt_get(lua_State *L, p_socket ps, int level, int name, void *val, int* len)
226{
227 socklen_t socklen = *len;
228 if (getsockopt(*ps, level, name, (char *) val, &socklen) < 0) {
229 lua_pushnil(L);
230 lua_pushstring(L, "getsockopt failed");
231 return 2;
232 }
233 *len = socklen;
234 return 0;
235}
236
237static
188int opt_set(lua_State *L, p_socket ps, int level, int name, void *val, int len) 238int opt_set(lua_State *L, p_socket ps, int level, int name, void *val, int len)
189{ 239{
190 if (setsockopt(*ps, level, name, (char *) val, len) < 0) { 240 if (setsockopt(*ps, level, name, (char *) val, len) < 0) {
@@ -199,12 +249,10 @@ int opt_set(lua_State *L, p_socket ps, int level, int name, void *val, int len)
199static int opt_getboolean(lua_State *L, p_socket ps, int level, int name) 249static int opt_getboolean(lua_State *L, p_socket ps, int level, int name)
200{ 250{
201 int val = 0; 251 int val = 0;
202 socklen_t len = sizeof(val); 252 int len = sizeof(val);
203 if (getsockopt(*ps, level, name, (char *) &val, &len) < 0) { 253 int err = opt_get(L, ps, level, name, (char *) &val, &len);
204 lua_pushnil(L); 254 if (err)
205 lua_pushstring(L, "getsockopt failed"); 255 return err;
206 return 2;
207 }
208 lua_pushboolean(L, val); 256 lua_pushboolean(L, val);
209 return 1; 257 return 1;
210} 258}
diff --git a/src/options.h b/src/options.h
index 70364fc..55447f7 100644
--- a/src/options.h
+++ b/src/options.h
@@ -33,14 +33,18 @@ int opt_set_ip_multicast_loop(lua_State *L, p_socket ps);
33int opt_set_ip_add_membership(lua_State *L, p_socket ps); 33int opt_set_ip_add_membership(lua_State *L, p_socket ps);
34int opt_set_ip_drop_membersip(lua_State *L, p_socket ps); 34int opt_set_ip_drop_membersip(lua_State *L, p_socket ps);
35int opt_set_ip6_v6only(lua_State *L, p_socket ps); 35int opt_set_ip6_v6only(lua_State *L, p_socket ps);
36/* invokes the appropriate option handler */
37int opt_meth_setoption(lua_State *L, p_opt opt, p_socket ps);
38 36
39/* supported options for getoption */ 37/* supported options for getoption */
38int opt_get_reuseaddr(lua_State *L, p_socket ps);
39int opt_get_tcp_nodelay(lua_State *L, p_socket ps);
40int opt_get_keepalive(lua_State *L, p_socket ps);
41int opt_get_linger(lua_State *L, p_socket ps);
42int opt_get_reuseaddr(lua_State *L, p_socket ps);
40int opt_get_ip_multicast_loop(lua_State *L, p_socket ps); 43int opt_get_ip_multicast_loop(lua_State *L, p_socket ps);
41int opt_get_ip_multicast_if(lua_State *L, p_socket ps); 44int opt_get_ip_multicast_if(lua_State *L, p_socket ps);
45
42/* invokes the appropriate option handler */ 46/* invokes the appropriate option handler */
47int opt_meth_setoption(lua_State *L, p_opt opt, p_socket ps);
43int opt_meth_getoption(lua_State *L, p_opt opt, p_socket ps); 48int opt_meth_getoption(lua_State *L, p_opt opt, p_socket ps);
44 49
45
46#endif 50#endif
diff --git a/src/serial.c b/src/serial.c
new file mode 100644
index 0000000..5b09e76
--- /dev/null
+++ b/src/serial.c
@@ -0,0 +1,183 @@
1/*=========================================================================*\
2* Serial stream
3* LuaSocket toolkit
4\*=========================================================================*/
5#include <string.h>
6
7#include "lua.h"
8#include "lauxlib.h"
9
10#include "auxiliar.h"
11#include "socket.h"
12#include "options.h"
13#include "unix.h"
14#include <sys/un.h>
15
16/*
17Reuses userdata definition from unix.h, since it is useful for all
18stream-like objects.
19
20If we stored the serial path for use in error messages or userdata
21printing, we might need our own userdata definition.
22
23Group usage is semi-inherited from unix.c, but unnecessary since we
24have only one object type.
25*/
26
27/*=========================================================================*\
28* Internal function prototypes
29\*=========================================================================*/
30static int global_create(lua_State *L);
31static int meth_send(lua_State *L);
32static int meth_receive(lua_State *L);
33static int meth_close(lua_State *L);
34static int meth_settimeout(lua_State *L);
35static int meth_getfd(lua_State *L);
36static int meth_setfd(lua_State *L);
37static int meth_dirty(lua_State *L);
38static int meth_getstats(lua_State *L);
39static int meth_setstats(lua_State *L);
40
41/* serial object methods */
42static luaL_Reg serial_methods[] = {
43 {"__gc", meth_close},
44 {"__tostring", auxiliar_tostring},
45 {"close", meth_close},
46 {"dirty", meth_dirty},
47 {"getfd", meth_getfd},
48 {"getstats", meth_getstats},
49 {"setstats", meth_setstats},
50 {"receive", meth_receive},
51 {"send", meth_send},
52 {"setfd", meth_setfd},
53 {"settimeout", meth_settimeout},
54 {NULL, NULL}
55};
56
57/* our socket creation function */
58static luaL_Reg func[] = {
59 {"serial", global_create},
60 {NULL, NULL}
61};
62
63
64/*-------------------------------------------------------------------------*\
65* Initializes module
66\*-------------------------------------------------------------------------*/
67LUASOCKET_API int luaopen_socket_serial(lua_State *L) {
68 /* create classes */
69 auxiliar_newclass(L, "serial{client}", serial_methods);
70 /* create class groups */
71 auxiliar_add2group(L, "serial{client}", "serial{any}");
72 /* make sure the function ends up in the package table */
73 luaL_openlib(L, "socket", func, 0);
74 /* return the function instead of the 'socket' table */
75 lua_pushstring(L, "serial");
76 lua_gettable(L, -2);
77 return 1;
78}
79
80/*=========================================================================*\
81* Lua methods
82\*=========================================================================*/
83/*-------------------------------------------------------------------------*\
84* Just call buffered IO methods
85\*-------------------------------------------------------------------------*/
86static int meth_send(lua_State *L) {
87 p_unix un = (p_unix) auxiliar_checkclass(L, "serial{client}", 1);
88 return buffer_meth_send(L, &un->buf);
89}
90
91static int meth_receive(lua_State *L) {
92 p_unix un = (p_unix) auxiliar_checkclass(L, "serial{client}", 1);
93 return buffer_meth_receive(L, &un->buf);
94}
95
96static int meth_getstats(lua_State *L) {
97 p_unix un = (p_unix) auxiliar_checkclass(L, "serial{client}", 1);
98 return buffer_meth_getstats(L, &un->buf);
99}
100
101static int meth_setstats(lua_State *L) {
102 p_unix un = (p_unix) auxiliar_checkclass(L, "serial{client}", 1);
103 return buffer_meth_setstats(L, &un->buf);
104}
105
106/*-------------------------------------------------------------------------*\
107* Select support methods
108\*-------------------------------------------------------------------------*/
109static int meth_getfd(lua_State *L) {
110 p_unix un = (p_unix) auxiliar_checkgroup(L, "serial{any}", 1);
111 lua_pushnumber(L, (int) un->sock);
112 return 1;
113}
114
115/* this is very dangerous, but can be handy for those that are brave enough */
116static int meth_setfd(lua_State *L) {
117 p_unix un = (p_unix) auxiliar_checkgroup(L, "serial{any}", 1);
118 un->sock = (t_socket) luaL_checknumber(L, 2);
119 return 0;
120}
121
122static int meth_dirty(lua_State *L) {
123 p_unix un = (p_unix) auxiliar_checkgroup(L, "serial{any}", 1);
124 lua_pushboolean(L, !buffer_isempty(&un->buf));
125 return 1;
126}
127
128/*-------------------------------------------------------------------------*\
129* Closes socket used by object
130\*-------------------------------------------------------------------------*/
131static int meth_close(lua_State *L)
132{
133 p_unix un = (p_unix) auxiliar_checkgroup(L, "serial{any}", 1);
134 socket_destroy(&un->sock);
135 lua_pushnumber(L, 1);
136 return 1;
137}
138
139
140/*-------------------------------------------------------------------------*\
141* Just call tm methods
142\*-------------------------------------------------------------------------*/
143static int meth_settimeout(lua_State *L) {
144 p_unix un = (p_unix) auxiliar_checkgroup(L, "serial{any}", 1);
145 return timeout_meth_settimeout(L, &un->tm);
146}
147
148/*=========================================================================*\
149* Library functions
150\*=========================================================================*/
151
152
153/*-------------------------------------------------------------------------*\
154* Creates a serial object
155\*-------------------------------------------------------------------------*/
156static int global_create(lua_State *L) {
157 const char* path = luaL_checkstring(L, 1);
158
159 /* allocate unix object */
160 p_unix un = (p_unix) lua_newuserdata(L, sizeof(t_unix));
161
162 /* open serial device */
163 t_socket sock = open(path, O_NOCTTY|O_RDWR);
164
165 /*printf("open %s on %d\n", path, sock);*/
166
167 if (sock < 0) {
168 lua_pushnil(L);
169 lua_pushstring(L, socket_strerror(errno));
170 lua_pushnumber(L, errno);
171 return 3;
172 }
173 /* set its type as client object */
174 auxiliar_setclass(L, "serial{client}", -1);
175 /* initialize remaining structure fields */
176 socket_setnonblocking(&sock);
177 un->sock = sock;
178 io_init(&un->io, (p_send) socket_write, (p_recv) socket_read,
179 (p_error) socket_ioerror, &un->sock);
180 timeout_init(&un->tm, -1, -1);
181 buffer_init(&un->buf, &un->io, &un->tm);
182 return 1;
183}
diff --git a/src/socket.h b/src/socket.h
index e325952..63573de 100644
--- a/src/socket.h
+++ b/src/socket.h
@@ -67,6 +67,9 @@ const char *socket_strerror(int err);
67int socket_send(p_socket ps, const char *data, size_t count, 67int socket_send(p_socket ps, const char *data, size_t count,
68 size_t *sent, p_timeout tm); 68 size_t *sent, p_timeout tm);
69int socket_recv(p_socket ps, char *data, size_t count, size_t *got, p_timeout tm); 69int socket_recv(p_socket ps, char *data, size_t count, size_t *got, p_timeout tm);
70int socket_write(p_socket ps, const char *data, size_t count,
71 size_t *sent, p_timeout tm);
72int socket_read(p_socket ps, char *data, size_t count, size_t *got, p_timeout tm);
70const char *socket_ioerror(p_socket ps, int err); 73const char *socket_ioerror(p_socket ps, int err);
71 74
72int socket_gethostbyaddr(const char *addr, socklen_t len, struct hostent **hp); 75int socket_gethostbyaddr(const char *addr, socklen_t len, struct hostent **hp);
diff --git a/src/tcp.c b/src/tcp.c
index 19ee73c..3146467 100644
--- a/src/tcp.c
+++ b/src/tcp.c
@@ -33,6 +33,7 @@ static int meth_shutdown(lua_State *L);
33static int meth_receive(lua_State *L); 33static int meth_receive(lua_State *L);
34static int meth_accept(lua_State *L); 34static int meth_accept(lua_State *L);
35static int meth_close(lua_State *L); 35static int meth_close(lua_State *L);
36static int meth_getoption(lua_State *L);
36static int meth_setoption(lua_State *L); 37static int meth_setoption(lua_State *L);
37static int meth_settimeout(lua_State *L); 38static int meth_settimeout(lua_State *L);
38static int meth_getfd(lua_State *L); 39static int meth_getfd(lua_State *L);
@@ -49,6 +50,7 @@ static luaL_Reg tcp_methods[] = {
49 {"connect", meth_connect}, 50 {"connect", meth_connect},
50 {"dirty", meth_dirty}, 51 {"dirty", meth_dirty},
51 {"getfd", meth_getfd}, 52 {"getfd", meth_getfd},
53 {"getoption", meth_getoption},
52 {"getpeername", meth_getpeername}, 54 {"getpeername", meth_getpeername},
53 {"getsockname", meth_getsockname}, 55 {"getsockname", meth_getsockname},
54 {"getstats", meth_getstats}, 56 {"getstats", meth_getstats},
@@ -66,6 +68,14 @@ static luaL_Reg tcp_methods[] = {
66}; 68};
67 69
68/* socket option handlers */ 70/* socket option handlers */
71static t_opt optget[] = {
72 {"keepalive", opt_get_keepalive},
73 {"reuseaddr", opt_get_reuseaddr},
74 {"tcp-nodelay", opt_get_tcp_nodelay},
75 {"linger", opt_get_linger},
76 {NULL, NULL}
77};
78
69static t_opt optset[] = { 79static t_opt optset[] = {
70 {"keepalive", opt_set_keepalive}, 80 {"keepalive", opt_set_keepalive},
71 {"reuseaddr", opt_set_reuseaddr}, 81 {"reuseaddr", opt_set_reuseaddr},
@@ -130,6 +140,12 @@ static int meth_setstats(lua_State *L) {
130/*-------------------------------------------------------------------------*\ 140/*-------------------------------------------------------------------------*\
131* Just call option handler 141* Just call option handler
132\*-------------------------------------------------------------------------*/ 142\*-------------------------------------------------------------------------*/
143static int meth_getoption(lua_State *L)
144{
145 p_tcp tcp = (p_tcp) auxiliar_checkgroup(L, "tcp{any}", 1);
146 return opt_meth_getoption(L, optget, &tcp->sock);
147}
148
133static int meth_setoption(lua_State *L) 149static int meth_setoption(lua_State *L)
134{ 150{
135 p_tcp tcp = (p_tcp) auxiliar_checkgroup(L, "tcp{any}", 1); 151 p_tcp tcp = (p_tcp) auxiliar_checkgroup(L, "tcp{any}", 1);
diff --git a/src/udp.c b/src/udp.c
index 13007fb..386051a 100644
--- a/src/udp.c
+++ b/src/udp.c
@@ -184,6 +184,9 @@ static int meth_receive(lua_State *L) {
184 count = MIN(count, sizeof(buffer)); 184 count = MIN(count, sizeof(buffer));
185 timeout_markstart(tm); 185 timeout_markstart(tm);
186 err = socket_recv(&udp->sock, buffer, count, &got, tm); 186 err = socket_recv(&udp->sock, buffer, count, &got, tm);
187 /* Unlike TCP, recv() of zero is not closed, but a zero-length packet. */
188 if (err == IO_CLOSED)
189 err = IO_DONE;
187 if (err != IO_DONE) { 190 if (err != IO_DONE) {
188 lua_pushnil(L); 191 lua_pushnil(L);
189 lua_pushstring(L, udp_strerror(err)); 192 lua_pushstring(L, udp_strerror(err));
@@ -208,6 +211,9 @@ static int meth_receivefrom(lua_State *L) {
208 count = MIN(count, sizeof(buffer)); 211 count = MIN(count, sizeof(buffer));
209 err = socket_recvfrom(&udp->sock, buffer, count, &got, 212 err = socket_recvfrom(&udp->sock, buffer, count, &got,
210 (SA *) &addr, &addr_len, tm); 213 (SA *) &addr, &addr_len, tm);
214 /* Unlike TCP, recv() of zero is not closed, but a zero-length packet. */
215 if (err == IO_CLOSED)
216 err = IO_DONE;
211 if (err == IO_DONE) { 217 if (err == IO_DONE) {
212 lua_pushlstring(L, buffer, got); 218 lua_pushlstring(L, buffer, got);
213 lua_pushstring(L, inet_ntoa(addr.sin_addr)); 219 lua_pushstring(L, inet_ntoa(addr.sin_addr));
diff --git a/src/unix.c b/src/unix.c
index b08d325..935d4c3 100644
--- a/src/unix.c
+++ b/src/unix.c
@@ -39,7 +39,7 @@ static const char *unix_tryconnect(p_unix un, const char *path);
39static const char *unix_trybind(p_unix un, const char *path); 39static const char *unix_trybind(p_unix un, const char *path);
40 40
41/* unix object methods */ 41/* unix object methods */
42static luaL_Reg un[] = { 42static luaL_Reg unix_methods[] = {
43 {"__gc", meth_close}, 43 {"__gc", meth_close},
44 {"__tostring", auxiliar_tostring}, 44 {"__tostring", auxiliar_tostring},
45 {"accept", meth_accept}, 45 {"accept", meth_accept},
@@ -82,9 +82,9 @@ static luaL_Reg func[] = {
82\*-------------------------------------------------------------------------*/ 82\*-------------------------------------------------------------------------*/
83int luaopen_socket_unix(lua_State *L) { 83int luaopen_socket_unix(lua_State *L) {
84 /* create classes */ 84 /* create classes */
85 auxiliar_newclass(L, "unix{master}", un); 85 auxiliar_newclass(L, "unix{master}", unix_methods);
86 auxiliar_newclass(L, "unix{client}", un); 86 auxiliar_newclass(L, "unix{client}", unix_methods);
87 auxiliar_newclass(L, "unix{server}", un); 87 auxiliar_newclass(L, "unix{server}", unix_methods);
88 /* create class groups */ 88 /* create class groups */
89 auxiliar_add2group(L, "unix{master}", "unix{any}"); 89 auxiliar_add2group(L, "unix{master}", "unix{any}");
90 auxiliar_add2group(L, "unix{client}", "unix{any}"); 90 auxiliar_add2group(L, "unix{client}", "unix{any}");
diff --git a/src/unix.h b/src/unix.h
index 39fa719..3a7e1e6 100644
--- a/src/unix.h
+++ b/src/unix.h
@@ -21,6 +21,6 @@ typedef struct t_unix_ {
21} t_unix; 21} t_unix;
22typedef t_unix *p_unix; 22typedef t_unix *p_unix;
23 23
24int luaopen_socket_unix(lua_State *L); 24LUASOCKET_API int luaopen_socket_unix(lua_State *L);
25 25
26#endif /* UNIX_H */ 26#endif /* UNIX_H */
diff --git a/src/usocket.c b/src/usocket.c
index fdab123..bf2d19c 100644
--- a/src/usocket.c
+++ b/src/usocket.c
@@ -16,7 +16,7 @@
16/*-------------------------------------------------------------------------*\ 16/*-------------------------------------------------------------------------*\
17* Wait for readable/writable/connected socket with timeout 17* Wait for readable/writable/connected socket with timeout
18\*-------------------------------------------------------------------------*/ 18\*-------------------------------------------------------------------------*/
19#ifdef SOCKET_POLL 19#ifndef SOCKET_SELECT
20#include <sys/poll.h> 20#include <sys/poll.h>
21 21
22#define WAITFD_R POLLIN 22#define WAITFD_R POLLIN
@@ -49,6 +49,7 @@ int socket_waitfd(p_socket ps, int sw, p_timeout tm) {
49 fd_set rfds, wfds, *rp, *wp; 49 fd_set rfds, wfds, *rp, *wp;
50 struct timeval tv, *tp; 50 struct timeval tv, *tp;
51 double t; 51 double t;
52 if (*ps >= FD_SETSIZE) return EINVAL;
52 if (timeout_iszero(tm)) return IO_TIMEOUT; /* optimize timeout == 0 case */ 53 if (timeout_iszero(tm)) return IO_TIMEOUT; /* optimize timeout == 0 case */
53 do { 54 do {
54 /* must set bits within loop, because select may have modifed them */ 55 /* must set bits within loop, because select may have modifed them */
@@ -213,14 +214,13 @@ int socket_send(p_socket ps, const char *data, size_t count,
213 for ( ;; ) { 214 for ( ;; ) {
214 long put = (long) send(*ps, data, count, 0); 215 long put = (long) send(*ps, data, count, 0);
215 /* if we sent anything, we are done */ 216 /* if we sent anything, we are done */
216 if (put > 0) { 217 if (put >= 0) {
217 *sent = put; 218 *sent = put;
218 return IO_DONE; 219 return IO_DONE;
219 } 220 }
220 err = errno; 221 err = errno;
221 /* send can't really return 0, but EPIPE means the connection was 222 /* EPIPE means the connection was closed */
222 closed */ 223 if (err == EPIPE) return IO_CLOSED;
223 if (put == 0 || err == EPIPE) return IO_CLOSED;
224 /* we call was interrupted, just try again */ 224 /* we call was interrupted, just try again */
225 if (err == EINTR) continue; 225 if (err == EINTR) continue;
226 /* if failed fatal reason, report error */ 226 /* if failed fatal reason, report error */
@@ -243,12 +243,12 @@ int socket_sendto(p_socket ps, const char *data, size_t count, size_t *sent,
243 if (*ps == SOCKET_INVALID) return IO_CLOSED; 243 if (*ps == SOCKET_INVALID) return IO_CLOSED;
244 for ( ;; ) { 244 for ( ;; ) {
245 long put = (long) sendto(*ps, data, count, 0, addr, len); 245 long put = (long) sendto(*ps, data, count, 0, addr, len);
246 if (put > 0) { 246 if (put >= 0) {
247 *sent = put; 247 *sent = put;
248 return IO_DONE; 248 return IO_DONE;
249 } 249 }
250 err = errno; 250 err = errno;
251 if (put == 0 || err == EPIPE) return IO_CLOSED; 251 if (err == EPIPE) return IO_CLOSED;
252 if (err == EINTR) continue; 252 if (err == EINTR) continue;
253 if (err != EAGAIN) return err; 253 if (err != EAGAIN) return err;
254 if ((err = socket_waitfd(ps, WAITFD_W, tm)) != IO_DONE) return err; 254 if ((err = socket_waitfd(ps, WAITFD_W, tm)) != IO_DONE) return err;
@@ -301,6 +301,66 @@ int socket_recvfrom(p_socket ps, char *data, size_t count, size_t *got,
301 return IO_UNKNOWN; 301 return IO_UNKNOWN;
302} 302}
303 303
304
305/*-------------------------------------------------------------------------*\
306* Write with timeout
307*
308* socket_read and socket_write are cut-n-paste of socket_send and socket_recv,
309* with send/recv replaced with write/read. We can't just use write/read
310* in the socket version, because behaviour when size is zero is different.
311\*-------------------------------------------------------------------------*/
312int socket_write(p_socket ps, const char *data, size_t count,
313 size_t *sent, p_timeout tm)
314{
315 int err;
316 *sent = 0;
317 /* avoid making system calls on closed sockets */
318 if (*ps == SOCKET_INVALID) return IO_CLOSED;
319 /* loop until we send something or we give up on error */
320 for ( ;; ) {
321 long put = (long) write(*ps, data, count);
322 /* if we sent anything, we are done */
323 if (put >= 0) {
324 *sent = put;
325 return IO_DONE;
326 }
327 err = errno;
328 /* EPIPE means the connection was closed */
329 if (err == EPIPE) return IO_CLOSED;
330 /* we call was interrupted, just try again */
331 if (err == EINTR) continue;
332 /* if failed fatal reason, report error */
333 if (err != EAGAIN) return err;
334 /* wait until we can send something or we timeout */
335 if ((err = socket_waitfd(ps, WAITFD_W, tm)) != IO_DONE) return err;
336 }
337 /* can't reach here */
338 return IO_UNKNOWN;
339}
340
341/*-------------------------------------------------------------------------*\
342* Read with timeout
343* See note for socket_write
344\*-------------------------------------------------------------------------*/
345int socket_read(p_socket ps, char *data, size_t count, size_t *got, p_timeout tm) {
346 int err;
347 *got = 0;
348 if (*ps == SOCKET_INVALID) return IO_CLOSED;
349 for ( ;; ) {
350 long taken = (long) read(*ps, data, count);
351 if (taken > 0) {
352 *got = taken;
353 return IO_DONE;
354 }
355 err = errno;
356 if (taken == 0) return IO_CLOSED;
357 if (err == EINTR) continue;
358 if (err != EAGAIN) return err;
359 if ((err = socket_waitfd(ps, WAITFD_R, tm)) != IO_DONE) return err;
360 }
361 return IO_UNKNOWN;
362}
363
304/*-------------------------------------------------------------------------*\ 364/*-------------------------------------------------------------------------*\
305* Put socket into blocking mode 365* Put socket into blocking mode
306\*-------------------------------------------------------------------------*/ 366\*-------------------------------------------------------------------------*/
@@ -360,7 +420,7 @@ const char *socket_strerror(int err) {
360 case ECONNABORTED: return "closed"; 420 case ECONNABORTED: return "closed";
361 case ECONNRESET: return "closed"; 421 case ECONNRESET: return "closed";
362 case ETIMEDOUT: return "timeout"; 422 case ETIMEDOUT: return "timeout";
363 default: return strerror(errno); 423 default: return strerror(err);
364 } 424 }
365} 425}
366 426