diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/makefile | 66 | ||||
-rw-r--r-- | src/mime.lua | 1 | ||||
-rw-r--r-- | src/options.c | 60 | ||||
-rw-r--r-- | src/options.h | 10 | ||||
-rw-r--r-- | src/serial.c | 183 | ||||
-rw-r--r-- | src/socket.h | 3 | ||||
-rw-r--r-- | src/tcp.c | 16 | ||||
-rw-r--r-- | src/udp.c | 6 | ||||
-rw-r--r-- | src/unix.c | 8 | ||||
-rw-r--r-- | src/unix.h | 2 | ||||
-rw-r--r-- | src/usocket.c | 76 |
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 @@ | |||
1 | PLAT?=macosx | 1 | PLAT?=macosx |
2 | LUAV?=5.1 | ||
3 | prefix=/usr/local | ||
4 | #prefix=/opt/local | ||
5 | #prefix=. | ||
2 | 6 | ||
3 | INSTALL_DATA=cp | 7 | LUAINC_macosx=/usr/local/include |
4 | INSTALL_EXEC=cp | ||
5 | #INSTALL_TOP=/opt/local | ||
6 | INSTALL_TOP=./ | ||
7 | |||
8 | #LUAINC_macosx=/opt/local/include | 8 | #LUAINC_macosx=/opt/local/include |
9 | LUAINC_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 | ||
12 | LUAINC_linux=/usr/include/lua5.1 | 12 | #LUAINC_linux=/usr/local/include/lua$(LUAV) |
13 | LUAINC_linux=/usr/include/lua$(LUAV) | ||
14 | #LUAINC_linux=/usr/local/include | ||
15 | |||
13 | LUAINC_win32="../../lua-5.1.3/src" | 16 | LUAINC_win32="../../lua-5.1.3/src" |
14 | LUALIB_win32="../../lua-5.1.3" | 17 | LUALIB_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 | 23 | INSTALL_DATA=cp |
21 | INSTALL_TOP_SHARE=$(INSTALL_TOP)/share/lua/5.2 | 24 | INSTALL_EXEC=cp |
22 | INSTALL_TOP_LIB=$(INSTALL_TOP)/lib/lua/5.2 | 25 | INSTALL_TOP=$(DESTDIR)$(prefix) |
26 | |||
27 | INSTALL_TOP_SHARE=$(INSTALL_TOP)/share/lua/$(LUAV) | ||
28 | INSTALL_TOP_LIB=$(INSTALL_TOP)/lib/lua/$(LUAV) | ||
23 | 29 | ||
24 | INSTALL_SOCKET_SHARE=$(INSTALL_TOP_SHARE)/socket | 30 | INSTALL_SOCKET_SHARE=$(INSTALL_TOP_SHARE)/socket |
25 | INSTALL_SOCKET_LIB=$(INSTALL_TOP_LIB)/socket | 31 | INSTALL_SOCKET_LIB=$(INSTALL_TOP_LIB)/socket |
26 | #INSTALL_MIME_SHARE=$(INSTALL_TOP_SHARE)/mime | 32 | INSTALL_MIME_SHARE=$(INSTALL_TOP_SHARE)/mime |
27 | INSTALL_MIME_SHARE=$(INSTALL_TOP_SHARE)/foo/mime | ||
28 | INSTALL_MIME_LIB=$(INSTALL_TOP_LIB)/mime | 33 | INSTALL_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: |
82 | LD_win32=cl | 87 | LD_win32=cl |
83 | SOCKET_win32=wsocket.obj | 88 | SOCKET_win32=wsocket.obj |
84 | 89 | ||
@@ -97,6 +102,7 @@ MIME_V=1.0.3 | |||
97 | SOCKET_SO=socket.$(SO).$(SOCKET_V) | 102 | SOCKET_SO=socket.$(SO).$(SOCKET_V) |
98 | MIME_SO=mime.$(SO).$(MIME_V) | 103 | MIME_SO=mime.$(SO).$(MIME_V) |
99 | UNIX_SO=unix.$(SO) | 104 | UNIX_SO=unix.$(SO) |
105 | SERIAL_SO=serial.$(SO) | ||
100 | SOCKET=$(SOCKET_$(PLAT)) | 106 | SOCKET=$(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 | # | ||
159 | SERIAL_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 | # |
153 | TO_SOCKET_SHARE= \ | 172 | TO_SOCKET_SHARE= \ |
@@ -169,13 +188,13 @@ TO_TOP_SHARE= \ | |||
169 | default: $(PLAT) | 188 | default: $(PLAT) |
170 | 189 | ||
171 | macosx: | 190 | macosx: |
172 | $(MAKE) all PLAT=macosx | 191 | $(MAKE) all-unix PLAT=macosx |
173 | 192 | ||
174 | win32: | 193 | win32: |
175 | $(MAKE) all PLAT=win32 | 194 | $(MAKE) all PLAT=win32 |
176 | 195 | ||
177 | linux: | 196 | linux: |
178 | $(MAKE) all PLAT=linux | 197 | $(MAKE) all-unix PLAT=linux |
179 | 198 | ||
180 | none: | 199 | none: |
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 | ||
213 | all-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 | |||
197 | install: | 221 | install: |
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 | ||
231 | install-unix: install | ||
232 | $(INSTALL_EXEC) $(UNIX_SO) $(INSTALL_SOCKET_LIB)/$(UNIX_SO) | ||
233 | $(INSTALL_EXEC) $(SERIAL_SO) $(INSTALL_SOCKET_LIB)/$(SERIAL_SO) | ||
234 | |||
207 | local: | 235 | local: |
208 | $(MAKE) install INSTALL_TOP_LIB=.. INSTALL_TOP_SHARE=.. | 236 | $(MAKE) install INSTALL_TOP_LIB=.. INSTALL_TOP_SHARE=.. |
209 | 237 | ||
210 | clean: | 238 | clean: |
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 | |||
228 | options.$(O): options.c auxiliar.h options.h socket.h io.h \ | 256 | options.$(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 |
230 | select.$(O): select.c socket.h io.h timeout.h usocket.h select.h | 258 | select.$(O): select.c socket.h io.h timeout.h usocket.h select.h |
259 | serial.$(O): serial.c auxiliar.h socket.h io.h timeout.h usocket.h \ | ||
260 | options.h unix.h buffer.h | ||
231 | tcp.$(O): tcp.c auxiliar.h socket.h io.h timeout.h usocket.h \ | 261 | tcp.$(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 |
233 | timeout.$(O): timeout.c auxiliar.h timeout.h | 263 | timeout.$(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 @@ | |||
11 | local base = _G | 11 | local base = _G |
12 | local ltn12 = require("ltn12") | 12 | local ltn12 = require("ltn12") |
13 | local mime = require("mime.core") | 13 | local mime = require("mime.core") |
14 | local io = require("io") | ||
15 | local string = require("string") | 14 | local string = require("string") |
16 | module("mime") | 15 | module("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); | |||
21 | static int opt_getboolean(lua_State *L, p_socket ps, int level, int name); | 21 | static int opt_getboolean(lua_State *L, p_socket ps, int level, int name); |
22 | static int opt_set(lua_State *L, p_socket ps, int level, int name, | 22 | static int opt_set(lua_State *L, p_socket ps, int level, int name, |
23 | void *val, int len); | 23 | void *val, int len); |
24 | static 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 | ||
65 | int 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 */ |
64 | int opt_set_reuseport(lua_State *L, p_socket ps) | 71 | int 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 | ||
76 | int 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 */ |
70 | int opt_set_tcp_nodelay(lua_State *L, p_socket ps) | 82 | int 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 | ||
87 | int opt_get_tcp_nodelay(lua_State *L, p_socket ps) | ||
88 | { | ||
89 | return opt_getboolean(L, ps, IPPROTO_TCP, TCP_NODELAY); | ||
90 | } | ||
91 | |||
75 | int opt_set_keepalive(lua_State *L, p_socket ps) | 92 | int 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 | ||
97 | int opt_get_keepalive(lua_State *L, p_socket ps) | ||
98 | { | ||
99 | return opt_getboolean(L, ps, SOL_SOCKET, SO_KEEPALIVE); | ||
100 | } | ||
101 | |||
80 | int opt_set_dontroute(lua_State *L, p_socket ps) | 102 | int 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 | ||
139 | int 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 | |||
117 | int opt_set_ip_multicast_ttl(lua_State *L, p_socket ps) | 154 | int 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 | ||
187 | static | 224 | static |
225 | int 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 | |||
237 | static | ||
188 | int opt_set(lua_State *L, p_socket ps, int level, int name, void *val, int len) | 238 | int 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) | |||
199 | static int opt_getboolean(lua_State *L, p_socket ps, int level, int name) | 249 | static 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); | |||
33 | int opt_set_ip_add_membership(lua_State *L, p_socket ps); | 33 | int opt_set_ip_add_membership(lua_State *L, p_socket ps); |
34 | int opt_set_ip_drop_membersip(lua_State *L, p_socket ps); | 34 | int opt_set_ip_drop_membersip(lua_State *L, p_socket ps); |
35 | int opt_set_ip6_v6only(lua_State *L, p_socket ps); | 35 | int opt_set_ip6_v6only(lua_State *L, p_socket ps); |
36 | /* invokes the appropriate option handler */ | ||
37 | int opt_meth_setoption(lua_State *L, p_opt opt, p_socket ps); | ||
38 | 36 | ||
39 | /* supported options for getoption */ | 37 | /* supported options for getoption */ |
38 | int opt_get_reuseaddr(lua_State *L, p_socket ps); | ||
39 | int opt_get_tcp_nodelay(lua_State *L, p_socket ps); | ||
40 | int opt_get_keepalive(lua_State *L, p_socket ps); | ||
41 | int opt_get_linger(lua_State *L, p_socket ps); | ||
42 | int opt_get_reuseaddr(lua_State *L, p_socket ps); | ||
40 | int opt_get_ip_multicast_loop(lua_State *L, p_socket ps); | 43 | int opt_get_ip_multicast_loop(lua_State *L, p_socket ps); |
41 | int opt_get_ip_multicast_if(lua_State *L, p_socket ps); | 44 | int opt_get_ip_multicast_if(lua_State *L, p_socket ps); |
45 | |||
42 | /* invokes the appropriate option handler */ | 46 | /* invokes the appropriate option handler */ |
47 | int opt_meth_setoption(lua_State *L, p_opt opt, p_socket ps); | ||
43 | int opt_meth_getoption(lua_State *L, p_opt opt, p_socket ps); | 48 | int 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 | /* | ||
17 | Reuses userdata definition from unix.h, since it is useful for all | ||
18 | stream-like objects. | ||
19 | |||
20 | If we stored the serial path for use in error messages or userdata | ||
21 | printing, we might need our own userdata definition. | ||
22 | |||
23 | Group usage is semi-inherited from unix.c, but unnecessary since we | ||
24 | have only one object type. | ||
25 | */ | ||
26 | |||
27 | /*=========================================================================*\ | ||
28 | * Internal function prototypes | ||
29 | \*=========================================================================*/ | ||
30 | static int global_create(lua_State *L); | ||
31 | static int meth_send(lua_State *L); | ||
32 | static int meth_receive(lua_State *L); | ||
33 | static int meth_close(lua_State *L); | ||
34 | static int meth_settimeout(lua_State *L); | ||
35 | static int meth_getfd(lua_State *L); | ||
36 | static int meth_setfd(lua_State *L); | ||
37 | static int meth_dirty(lua_State *L); | ||
38 | static int meth_getstats(lua_State *L); | ||
39 | static int meth_setstats(lua_State *L); | ||
40 | |||
41 | /* serial object methods */ | ||
42 | static 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 */ | ||
58 | static luaL_Reg func[] = { | ||
59 | {"serial", global_create}, | ||
60 | {NULL, NULL} | ||
61 | }; | ||
62 | |||
63 | |||
64 | /*-------------------------------------------------------------------------*\ | ||
65 | * Initializes module | ||
66 | \*-------------------------------------------------------------------------*/ | ||
67 | LUASOCKET_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 | \*-------------------------------------------------------------------------*/ | ||
86 | static 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 | |||
91 | static 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 | |||
96 | static 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 | |||
101 | static 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 | \*-------------------------------------------------------------------------*/ | ||
109 | static 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 */ | ||
116 | static 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 | |||
122 | static 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 | \*-------------------------------------------------------------------------*/ | ||
131 | static 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 | \*-------------------------------------------------------------------------*/ | ||
143 | static 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 | \*-------------------------------------------------------------------------*/ | ||
156 | static 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); | |||
67 | int socket_send(p_socket ps, const char *data, size_t count, | 67 | int 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); |
69 | int socket_recv(p_socket ps, char *data, size_t count, size_t *got, p_timeout tm); | 69 | int socket_recv(p_socket ps, char *data, size_t count, size_t *got, p_timeout tm); |
70 | int socket_write(p_socket ps, const char *data, size_t count, | ||
71 | size_t *sent, p_timeout tm); | ||
72 | int socket_read(p_socket ps, char *data, size_t count, size_t *got, p_timeout tm); | ||
70 | const char *socket_ioerror(p_socket ps, int err); | 73 | const char *socket_ioerror(p_socket ps, int err); |
71 | 74 | ||
72 | int socket_gethostbyaddr(const char *addr, socklen_t len, struct hostent **hp); | 75 | int socket_gethostbyaddr(const char *addr, socklen_t len, struct hostent **hp); |
@@ -33,6 +33,7 @@ static int meth_shutdown(lua_State *L); | |||
33 | static int meth_receive(lua_State *L); | 33 | static int meth_receive(lua_State *L); |
34 | static int meth_accept(lua_State *L); | 34 | static int meth_accept(lua_State *L); |
35 | static int meth_close(lua_State *L); | 35 | static int meth_close(lua_State *L); |
36 | static int meth_getoption(lua_State *L); | ||
36 | static int meth_setoption(lua_State *L); | 37 | static int meth_setoption(lua_State *L); |
37 | static int meth_settimeout(lua_State *L); | 38 | static int meth_settimeout(lua_State *L); |
38 | static int meth_getfd(lua_State *L); | 39 | static 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 */ |
71 | static 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 | |||
69 | static t_opt optset[] = { | 79 | static 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 | \*-------------------------------------------------------------------------*/ |
143 | static 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 | |||
133 | static int meth_setoption(lua_State *L) | 149 | static 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); |
@@ -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)); |
@@ -39,7 +39,7 @@ static const char *unix_tryconnect(p_unix un, const char *path); | |||
39 | static const char *unix_trybind(p_unix un, const char *path); | 39 | static const char *unix_trybind(p_unix un, const char *path); |
40 | 40 | ||
41 | /* unix object methods */ | 41 | /* unix object methods */ |
42 | static luaL_Reg un[] = { | 42 | static 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 | \*-------------------------------------------------------------------------*/ |
83 | int luaopen_socket_unix(lua_State *L) { | 83 | int 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}"); |
@@ -21,6 +21,6 @@ typedef struct t_unix_ { | |||
21 | } t_unix; | 21 | } t_unix; |
22 | typedef t_unix *p_unix; | 22 | typedef t_unix *p_unix; |
23 | 23 | ||
24 | int luaopen_socket_unix(lua_State *L); | 24 | LUASOCKET_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 | \*-------------------------------------------------------------------------*/ | ||
312 | int 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 | \*-------------------------------------------------------------------------*/ | ||
345 | int 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 | ||