diff options
author | Diego Nehab <diego@impa.br> | 2013-05-30 16:20:34 +0800 |
---|---|---|
committer | Diego Nehab <diego@impa.br> | 2013-05-30 16:20:34 +0800 |
commit | a233e27865d96566a6cb13960d08605ce34d9f0d (patch) | |
tree | 6ef3219bec0c29bbb14ce92b5c2f4dc46b42dbc6 | |
parent | 5341131cd07bf4f66ce242980b5f3cfbbf45ea12 (diff) | |
download | luasocket-a233e27865d96566a6cb13960d08605ce34d9f0d.tar.gz luasocket-a233e27865d96566a6cb13960d08605ce34d9f0d.tar.bz2 luasocket-a233e27865d96566a6cb13960d08605ce34d9f0d.zip |
Leaving if in src/ but out of build for now.
-rw-r--r-- | README | 11 | ||||
-rw-r--r-- | src/inet.c | 131 | ||||
-rw-r--r-- | src/makefile | 16 | ||||
-rw-r--r-- | src/options.c | 135 | ||||
-rw-r--r-- | src/options.h | 9 | ||||
-rw-r--r-- | src/serial.c | 1 | ||||
-rw-r--r-- | src/udp.c | 157 | ||||
-rw-r--r-- | src/unix.c | 1 |
8 files changed, 265 insertions, 196 deletions
@@ -1,6 +1,11 @@ | |||
1 | This is the LuaSocket 2.1. It has been tested on --[[WinXP--]], Mac OS X, | 1 | This is the LuaSocket 2.1. It has been tested on Windows 7, Mac OS X, |
2 | and --[[Linux--]]. Please use the Lua mailing list to report any bugs | 2 | and Linux. |
3 | (or "features") you encounter. | 3 | |
4 | Please use the project page at GitHub | ||
5 | |||
6 | https://github.com/diegonehab/luasocket | ||
7 | |||
8 | to file bug reports or propose changes. | ||
4 | 9 | ||
5 | Have fun, | 10 | Have fun, |
6 | Diego Nehab. | 11 | Diego Nehab. |
@@ -3,6 +3,7 @@ | |||
3 | * LuaSocket toolkit | 3 | * LuaSocket toolkit |
4 | \*=========================================================================*/ | 4 | \*=========================================================================*/ |
5 | #include <stdio.h> | 5 | #include <stdio.h> |
6 | #include <stdlib.h> | ||
6 | #include <string.h> | 7 | #include <string.h> |
7 | 8 | ||
8 | #include "lua.h" | 9 | #include "lua.h" |
@@ -227,7 +228,6 @@ static int inet_global_gethostname(lua_State *L) | |||
227 | } | 228 | } |
228 | } | 229 | } |
229 | 230 | ||
230 | |||
231 | /*=========================================================================*\ | 231 | /*=========================================================================*\ |
232 | * Lua methods | 232 | * Lua methods |
233 | \*=========================================================================*/ | 233 | \*=========================================================================*/ |
@@ -236,44 +236,33 @@ static int inet_global_gethostname(lua_State *L) | |||
236 | \*-------------------------------------------------------------------------*/ | 236 | \*-------------------------------------------------------------------------*/ |
237 | int inet_meth_getpeername(lua_State *L, p_socket ps, int family) | 237 | int inet_meth_getpeername(lua_State *L, p_socket ps, int family) |
238 | { | 238 | { |
239 | switch (family) { | 239 | int err; |
240 | case PF_INET: { | 240 | struct sockaddr_storage peer; |
241 | struct sockaddr_in peer; | 241 | socklen_t peer_len = sizeof(peer); |
242 | socklen_t peer_len = sizeof(peer); | 242 | char name[INET6_ADDRSTRLEN]; |
243 | char name[INET_ADDRSTRLEN]; | 243 | char port[6]; /* 65535 = 5 bytes + 0 to terminate it */ |
244 | if (getpeername(*ps, (SA *) &peer, &peer_len) < 0) { | 244 | if (getpeername(*ps, (SA *) &peer, &peer_len) < 0) { |
245 | lua_pushnil(L); | 245 | lua_pushnil(L); |
246 | lua_pushstring(L, socket_strerror(errno)); | 246 | lua_pushstring(L, socket_strerror(errno)); |
247 | return 2; | 247 | return 2; |
248 | } else { | 248 | } |
249 | inet_ntop(family, &peer.sin_addr, name, sizeof(name)); | 249 | if ((err = getnameinfo((struct sockaddr *) &peer, peer_len, |
250 | lua_pushstring(L, name); | 250 | name, INET6_ADDRSTRLEN, |
251 | lua_pushnumber(L, ntohs(peer.sin_port)); | 251 | port, sizeof(port), NI_NUMERICHOST | NI_NUMERICSERV))) { |
252 | lua_pushliteral(L, "inet"); | 252 | lua_pushnil(L); |
253 | return 3; | 253 | lua_pushstring(L, gai_strerror(err)); |
254 | } | 254 | return 2; |
255 | } | 255 | } |
256 | case PF_INET6: { | 256 | lua_pushstring(L, name); |
257 | struct sockaddr_in6 peer; | 257 | lua_pushinteger(L, (int) strtol(port, (char **) NULL, 10)); |
258 | socklen_t peer_len = sizeof(peer); | 258 | if (family == PF_INET) { |
259 | char name[INET6_ADDRSTRLEN]; | 259 | lua_pushliteral(L, "inet"); |
260 | if (getpeername(*ps, (SA *) &peer, &peer_len) < 0) { | 260 | } else if (family == PF_INET6) { |
261 | lua_pushnil(L); | 261 | lua_pushliteral(L, "inet6"); |
262 | lua_pushstring(L, socket_strerror(errno)); | 262 | } else { |
263 | return 2; | 263 | lua_pushliteral(L, "uknown family"); |
264 | } else { | ||
265 | inet_ntop(family, &peer.sin6_addr, name, sizeof(name)); | ||
266 | lua_pushstring(L, name); | ||
267 | lua_pushnumber(L, ntohs(peer.sin6_port)); | ||
268 | lua_pushliteral(L, "inet6"); | ||
269 | return 3; | ||
270 | } | ||
271 | } | ||
272 | default: | ||
273 | lua_pushnil(L); | ||
274 | lua_pushfstring(L, "unknown family %d", family); | ||
275 | return 2; | ||
276 | } | 264 | } |
265 | return 3; | ||
277 | } | 266 | } |
278 | 267 | ||
279 | /*-------------------------------------------------------------------------*\ | 268 | /*-------------------------------------------------------------------------*\ |
@@ -281,44 +270,33 @@ int inet_meth_getpeername(lua_State *L, p_socket ps, int family) | |||
281 | \*-------------------------------------------------------------------------*/ | 270 | \*-------------------------------------------------------------------------*/ |
282 | int inet_meth_getsockname(lua_State *L, p_socket ps, int family) | 271 | int inet_meth_getsockname(lua_State *L, p_socket ps, int family) |
283 | { | 272 | { |
284 | switch (family) { | 273 | int err; |
285 | case PF_INET: { | 274 | struct sockaddr_storage peer; |
286 | struct sockaddr_in local; | 275 | socklen_t peer_len = sizeof(peer); |
287 | socklen_t local_len = sizeof(local); | 276 | char name[INET6_ADDRSTRLEN]; |
288 | char name[INET_ADDRSTRLEN]; | 277 | char port[6]; /* 65535 = 5 bytes + 0 to terminate it */ |
289 | if (getsockname(*ps, (SA *) &local, &local_len) < 0) { | 278 | if (getsockname(*ps, (SA *) &peer, &peer_len) < 0) { |
290 | lua_pushnil(L); | 279 | lua_pushnil(L); |
291 | lua_pushstring(L, socket_strerror(errno)); | 280 | lua_pushstring(L, socket_strerror(errno)); |
292 | return 2; | 281 | return 2; |
293 | } else { | 282 | } |
294 | inet_ntop(family, &local.sin_addr, name, sizeof(name)); | 283 | if ((err=getnameinfo((struct sockaddr *)&peer, peer_len, |
295 | lua_pushstring(L, name); | 284 | name, INET6_ADDRSTRLEN, |
296 | lua_pushnumber(L, ntohs(local.sin_port)); | 285 | port, 6, NI_NUMERICHOST | NI_NUMERICSERV))) { |
297 | lua_pushliteral(L, "inet"); | 286 | lua_pushnil(L); |
298 | return 3; | 287 | lua_pushstring(L, gai_strerror(err)); |
299 | } | 288 | return 2; |
300 | } | 289 | } |
301 | case PF_INET6: { | 290 | lua_pushstring(L, name); |
302 | struct sockaddr_in6 local; | 291 | lua_pushstring(L, port); |
303 | socklen_t local_len = sizeof(local); | 292 | if (family == PF_INET) { |
304 | char name[INET6_ADDRSTRLEN]; | 293 | lua_pushliteral(L, "inet"); |
305 | if (getsockname(*ps, (SA *) &local, &local_len) < 0) { | 294 | } else if (family == PF_INET6) { |
306 | lua_pushnil(L); | 295 | lua_pushliteral(L, "inet6"); |
307 | lua_pushstring(L, socket_strerror(errno)); | 296 | } else { |
308 | return 2; | 297 | lua_pushliteral(L, "uknown family"); |
309 | } else { | ||
310 | inet_ntop(family, &local.sin6_addr, name, sizeof(name)); | ||
311 | lua_pushstring(L, name); | ||
312 | lua_pushnumber(L, ntohs(local.sin6_port)); | ||
313 | lua_pushliteral(L, "inet6"); | ||
314 | return 3; | ||
315 | } | ||
316 | } | ||
317 | default: | ||
318 | lua_pushnil(L); | ||
319 | lua_pushfstring(L, "unknown family %d", family); | ||
320 | return 2; | ||
321 | } | 298 | } |
299 | return 3; | ||
322 | } | 300 | } |
323 | 301 | ||
324 | /*=========================================================================*\ | 302 | /*=========================================================================*\ |
@@ -456,7 +434,8 @@ const char *inet_tryaccept(p_socket server, int family, p_socket client, | |||
456 | } else { | 434 | } else { |
457 | len = sizeof(struct sockaddr_in); | 435 | len = sizeof(struct sockaddr_in); |
458 | } | 436 | } |
459 | return socket_strerror(socket_accept(server, client, (SA *) &addr, &len, tm)); | 437 | return socket_strerror(socket_accept(server, client, (SA *) &addr, |
438 | &len, tm)); | ||
460 | } | 439 | } |
461 | 440 | ||
462 | /*-------------------------------------------------------------------------*\ | 441 | /*-------------------------------------------------------------------------*\ |
diff --git a/src/makefile b/src/makefile index 42589f6..f7b0401 100644 --- a/src/makefile +++ b/src/makefile | |||
@@ -30,7 +30,7 @@ DEBUG?=NODEBUG | |||
30 | COMPAT?=NOCOMPAT | 30 | COMPAT?=NOCOMPAT |
31 | 31 | ||
32 | # where lua headers are found for macosx builds | 32 | # where lua headers are found for macosx builds |
33 | # LUAINC_macosx: | 33 | # LUAINC_macosx: |
34 | # /opt/local/include | 34 | # /opt/local/include |
35 | LUAINC_macosx_base?=/opt/local/include | 35 | LUAINC_macosx_base?=/opt/local/include |
36 | LUAINC_macosx?=$(LUAINC_macosx_base)/lua/$(LUAV) | 36 | LUAINC_macosx?=$(LUAINC_macosx_base)/lua/$(LUAV) |
@@ -41,9 +41,9 @@ CDIR_macosx?=lib/lua/$(LUAV) | |||
41 | LDIR_macosx?=share/lua/$(LUAV) | 41 | LDIR_macosx?=share/lua/$(LUAV) |
42 | 42 | ||
43 | 43 | ||
44 | # LUAINC_linux: | 44 | # LUAINC_linux: |
45 | # /usr/include/lua$(LUAV) | 45 | # /usr/include/lua$(LUAV) |
46 | # /usr/local/include | 46 | # /usr/local/include |
47 | # /usr/local/include/lua$(LUAV) | 47 | # /usr/local/include/lua$(LUAV) |
48 | # where lua headers are found for linux builds | 48 | # where lua headers are found for linux builds |
49 | LUAINC_linux_base?=/usr/include | 49 | LUAINC_linux_base?=/usr/include |
@@ -134,7 +134,7 @@ DEF_macosx= -DLUASOCKET_$(DEBUG) -DUNIX_HAS_SUN_LEN -DLUA_$(COMPAT)_MODULE \ | |||
134 | -DMIME_API='__attribute__((visibility("default")))' | 134 | -DMIME_API='__attribute__((visibility("default")))' |
135 | CFLAGS_macosx= -I$(LUAINC) $(DEF) -pedantic -Wall -O2 -fno-common \ | 135 | CFLAGS_macosx= -I$(LUAINC) $(DEF) -pedantic -Wall -O2 -fno-common \ |
136 | -fvisibility=hidden | 136 | -fvisibility=hidden |
137 | LDFLAGS_macosx= -bundle -undefined dynamic_lookup -o | 137 | LDFLAGS_macosx= -bundle -undefined dynamic_lookup -o |
138 | LD_macosx= export MACOSX_DEPLOYMENT_TARGET="10.3"; gcc | 138 | LD_macosx= export MACOSX_DEPLOYMENT_TARGET="10.3"; gcc |
139 | SOCKET_macosx=usocket.o | 139 | SOCKET_macosx=usocket.o |
140 | 140 | ||
@@ -308,15 +308,15 @@ none: | |||
308 | all: $(SOCKET_SO) $(MIME_SO) | 308 | all: $(SOCKET_SO) $(MIME_SO) |
309 | 309 | ||
310 | $(SOCKET_SO): $(SOCKET_OBJS) | 310 | $(SOCKET_SO): $(SOCKET_OBJS) |
311 | $(LD) $(SOCKET_OBJS) $(LDFLAGS)$@ | 311 | $(LD) $(SOCKET_OBJS) $(LDFLAGS)$@ |
312 | 312 | ||
313 | $(MIME_SO): $(MIME_OBJS) | 313 | $(MIME_SO): $(MIME_OBJS) |
314 | $(LD) $(MIME_OBJS) $(LDFLAGS)$@ | 314 | $(LD) $(MIME_OBJS) $(LDFLAGS)$@ |
315 | 315 | ||
316 | all-unix: all $(UNIX_SO) $(SERIAL_SO) | 316 | all-unix: all $(UNIX_SO) $(SERIAL_SO) |
317 | 317 | ||
318 | $(UNIX_SO): $(UNIX_OBJS) | 318 | $(UNIX_SO): $(UNIX_OBJS) |
319 | $(LD) $(UNIX_OBJS) $(LDFLAGS)$@ | 319 | $(LD) $(UNIX_OBJS) $(LDFLAGS)$@ |
320 | 320 | ||
321 | $(SERIAL_SO): $(SERIAL_OBJS) | 321 | $(SERIAL_SO): $(SERIAL_OBJS) |
322 | $(LD) $(SERIAL_OBJS) $(LDFLAGS)$@ | 322 | $(LD) $(SERIAL_OBJS) $(LDFLAGS)$@ |
diff --git a/src/options.c b/src/options.c index 6f36ba4..8737d9c 100644 --- a/src/options.c +++ b/src/options.c | |||
@@ -3,6 +3,9 @@ | |||
3 | * LuaSocket toolkit | 3 | * LuaSocket toolkit |
4 | \*=========================================================================*/ | 4 | \*=========================================================================*/ |
5 | #include <string.h> | 5 | #include <string.h> |
6 | #include <sys/types.h> | ||
7 | #include <sys/socket.h> | ||
8 | #include <net/if.h> | ||
6 | 9 | ||
7 | #include "lauxlib.h" | 10 | #include "lauxlib.h" |
8 | 11 | ||
@@ -10,12 +13,30 @@ | |||
10 | #include "options.h" | 13 | #include "options.h" |
11 | #include "inet.h" | 14 | #include "inet.h" |
12 | 15 | ||
16 | /* Some platforms use IPV6_JOIN_GROUP instead if | ||
17 | * IPV6_ADD_MEMBERSHIP. The semantics are same, though. */ | ||
18 | #ifndef IPV6_ADD_MEMBERSHIP | ||
19 | #ifdef IPV6_JOIN_GROUP | ||
20 | #define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP | ||
21 | #endif /* IPV6_JOIN_GROUP */ | ||
22 | #endif /* !IPV6_ADD_MEMBERSHIP */ | ||
23 | |||
24 | /* Same with IPV6_DROP_MEMBERSHIP / IPV6_LEAVE_GROUP. */ | ||
25 | #ifndef IPV6_DROP_MEMBERSHIP | ||
26 | #ifdef IPV6_LEAVE_GROUP | ||
27 | #define IPV6_DROP_MEMBERSHIP IPV6_LEAVE_GROUP | ||
28 | #endif /* IPV6_LEAVE_GROUP */ | ||
29 | #endif /* !IPV6_DROP_MEMBERSHIP */ | ||
30 | |||
13 | /*=========================================================================*\ | 31 | /*=========================================================================*\ |
14 | * Internal functions prototypes | 32 | * Internal functions prototypes |
15 | \*=========================================================================*/ | 33 | \*=========================================================================*/ |
16 | static int opt_setmembership(lua_State *L, p_socket ps, int level, int name); | 34 | static int opt_setmembership(lua_State *L, p_socket ps, int level, int name); |
35 | static int opt_ip6_setmembership(lua_State *L, p_socket ps, int level, int name); | ||
17 | static int opt_setboolean(lua_State *L, p_socket ps, int level, int name); | 36 | static int opt_setboolean(lua_State *L, p_socket ps, int level, int name); |
18 | static int opt_getboolean(lua_State *L, p_socket ps, int level, int name); | 37 | static int opt_getboolean(lua_State *L, p_socket ps, int level, int name); |
38 | static int opt_setint(lua_State *L, p_socket ps, int level, int name); | ||
39 | static int opt_getint(lua_State *L, p_socket ps, int level, int name); | ||
19 | static int opt_set(lua_State *L, p_socket ps, int level, int name, | 40 | static int opt_set(lua_State *L, p_socket ps, int level, int name, |
20 | void *val, int len); | 41 | void *val, int len); |
21 | static int opt_get(lua_State *L, p_socket ps, int level, int name, | 42 | static int opt_get(lua_State *L, p_socket ps, int level, int name, |
@@ -106,6 +127,26 @@ int opt_set_broadcast(lua_State *L, p_socket ps) | |||
106 | return opt_setboolean(L, ps, SOL_SOCKET, SO_BROADCAST); | 127 | return opt_setboolean(L, ps, SOL_SOCKET, SO_BROADCAST); |
107 | } | 128 | } |
108 | 129 | ||
130 | int opt_set_ip6_unicast_hops(lua_State *L, p_socket ps) | ||
131 | { | ||
132 | return opt_setint(L, ps, IPPROTO_IPV6, IPV6_UNICAST_HOPS); | ||
133 | } | ||
134 | |||
135 | int opt_get_ip6_unicast_hops(lua_State *L, p_socket ps) | ||
136 | { | ||
137 | return opt_getint(L, ps, IPPROTO_IPV6, IPV6_UNICAST_HOPS); | ||
138 | } | ||
139 | |||
140 | int opt_set_ip6_multicast_hops(lua_State *L, p_socket ps) | ||
141 | { | ||
142 | return opt_setint(L, ps, IPPROTO_IPV6, IPV6_MULTICAST_HOPS); | ||
143 | } | ||
144 | |||
145 | int opt_get_ip6_multicast_hops(lua_State *L, p_socket ps) | ||
146 | { | ||
147 | return opt_getint(L, ps, IPPROTO_IPV6, IPV6_MULTICAST_HOPS); | ||
148 | } | ||
149 | |||
109 | int opt_set_ip_multicast_loop(lua_State *L, p_socket ps) | 150 | int opt_set_ip_multicast_loop(lua_State *L, p_socket ps) |
110 | { | 151 | { |
111 | return opt_setboolean(L, ps, IPPROTO_IP, IP_MULTICAST_LOOP); | 152 | return opt_setboolean(L, ps, IPPROTO_IP, IP_MULTICAST_LOOP); |
@@ -116,6 +157,16 @@ int opt_get_ip_multicast_loop(lua_State *L, p_socket ps) | |||
116 | return opt_getboolean(L, ps, IPPROTO_IP, IP_MULTICAST_LOOP); | 157 | return opt_getboolean(L, ps, IPPROTO_IP, IP_MULTICAST_LOOP); |
117 | } | 158 | } |
118 | 159 | ||
160 | int opt_set_ip6_multicast_loop(lua_State *L, p_socket ps) | ||
161 | { | ||
162 | return opt_setboolean(L, ps, IPPROTO_IPV6, IPV6_MULTICAST_LOOP); | ||
163 | } | ||
164 | |||
165 | int opt_get_ip6_multicast_loop(lua_State *L, p_socket ps) | ||
166 | { | ||
167 | return opt_getboolean(L, ps, IPPROTO_IPV6, IPV6_MULTICAST_LOOP); | ||
168 | } | ||
169 | |||
119 | int opt_set_linger(lua_State *L, p_socket ps) | 170 | int opt_set_linger(lua_State *L, p_socket ps) |
120 | { | 171 | { |
121 | struct linger li; /* obj, name, table */ | 172 | struct linger li; /* obj, name, table */ |
@@ -150,9 +201,7 @@ int opt_get_linger(lua_State *L, p_socket ps) | |||
150 | 201 | ||
151 | int opt_set_ip_multicast_ttl(lua_State *L, p_socket ps) | 202 | int opt_set_ip_multicast_ttl(lua_State *L, p_socket ps) |
152 | { | 203 | { |
153 | int val = (int) luaL_checknumber(L, 3); /* obj, name, int */ | 204 | return opt_setint(L, ps, IPPROTO_IP, IP_MULTICAST_TTL); |
154 | return opt_set(L, ps, IPPROTO_IP, IP_MULTICAST_TTL, | ||
155 | (char *) &val, sizeof(val)); | ||
156 | } | 205 | } |
157 | 206 | ||
158 | int opt_set_ip_multicast_if(lua_State *L, p_socket ps) | 207 | int opt_set_ip_multicast_if(lua_State *L, p_socket ps) |
@@ -189,6 +238,21 @@ int opt_set_ip_drop_membersip(lua_State *L, p_socket ps) | |||
189 | return opt_setmembership(L, ps, IPPROTO_IP, IP_DROP_MEMBERSHIP); | 238 | return opt_setmembership(L, ps, IPPROTO_IP, IP_DROP_MEMBERSHIP); |
190 | } | 239 | } |
191 | 240 | ||
241 | int opt_set_ip6_add_membership(lua_State *L, p_socket ps) | ||
242 | { | ||
243 | return opt_ip6_setmembership(L, ps, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP); | ||
244 | } | ||
245 | |||
246 | int opt_set_ip6_drop_membersip(lua_State *L, p_socket ps) | ||
247 | { | ||
248 | return opt_ip6_setmembership(L, ps, IPPROTO_IPV6, IPV6_DROP_MEMBERSHIP); | ||
249 | } | ||
250 | |||
251 | int opt_get_ip6_v6only(lua_State *L, p_socket ps) | ||
252 | { | ||
253 | return opt_getboolean(L, ps, IPPROTO_IPV6, IPV6_V6ONLY); | ||
254 | } | ||
255 | |||
192 | int opt_set_ip6_v6only(lua_State *L, p_socket ps) | 256 | int opt_set_ip6_v6only(lua_State *L, p_socket ps) |
193 | { | 257 | { |
194 | return opt_setboolean(L, ps, IPPROTO_IPV6, IPV6_V6ONLY); | 258 | return opt_setboolean(L, ps, IPPROTO_IPV6, IPV6_V6ONLY); |
@@ -218,6 +282,37 @@ static int opt_setmembership(lua_State *L, p_socket ps, int level, int name) | |||
218 | return opt_set(L, ps, level, name, (char *) &val, sizeof(val)); | 282 | return opt_set(L, ps, level, name, (char *) &val, sizeof(val)); |
219 | } | 283 | } |
220 | 284 | ||
285 | static int opt_ip6_setmembership(lua_State *L, p_socket ps, int level, int name) | ||
286 | { | ||
287 | struct ipv6_mreq val; /* obj, opt-name, table */ | ||
288 | memset(&val, 0, sizeof(val)); | ||
289 | if (!lua_istable(L, 3)) auxiliar_typeerror(L,3,lua_typename(L, LUA_TTABLE)); | ||
290 | lua_pushstring(L, "multiaddr"); | ||
291 | lua_gettable(L, 3); | ||
292 | if (!lua_isstring(L, -1)) | ||
293 | luaL_argerror(L, 3, "string 'multiaddr' field expected"); | ||
294 | if (!inet_pton(AF_INET6, lua_tostring(L, -1), &val.ipv6mr_multiaddr)) | ||
295 | luaL_argerror(L, 3, "invalid 'multiaddr' ip address"); | ||
296 | lua_pushstring(L, "interface"); | ||
297 | lua_gettable(L, 3); | ||
298 | /* By default we listen to interface on default route | ||
299 | * (sigh). However, interface= can override it. We support either | ||
300 | * number, or name for it. */ | ||
301 | if (!lua_isnil(L, -1)) { | ||
302 | if (lua_isnumber(L, -1)) { | ||
303 | val.ipv6mr_interface = lua_tonumber(L, -1); | ||
304 | } else if (lua_isstring(L, -1)) { | ||
305 | if (!(val.ipv6mr_interface = if_nametoindex(lua_tostring(L, -1)))) { | ||
306 | lua_pushnil(L); | ||
307 | lua_pushstring(L, "nonexistent interface"); | ||
308 | return 2; | ||
309 | } | ||
310 | } else | ||
311 | luaL_argerror(L, -1, "number/string 'interface' field expected"); | ||
312 | } | ||
313 | return opt_set(L, ps, level, name, (char *) &val, sizeof(val)); | ||
314 | } | ||
315 | |||
221 | static | 316 | static |
222 | int opt_get(lua_State *L, p_socket ps, int level, int name, void *val, int* len) | 317 | int opt_get(lua_State *L, p_socket ps, int level, int name, void *val, int* len) |
223 | { | 318 | { |
@@ -256,15 +351,15 @@ static int opt_getboolean(lua_State *L, p_socket ps, int level, int name) | |||
256 | 351 | ||
257 | int opt_get_error(lua_State *L, p_socket ps) | 352 | int opt_get_error(lua_State *L, p_socket ps) |
258 | { | 353 | { |
259 | int val = 0; | 354 | int val = 0; |
260 | socklen_t len = sizeof(val); | 355 | socklen_t len = sizeof(val); |
261 | if (getsockopt(*ps, SOL_SOCKET, SO_ERROR, (char *) &val, &len) < 0) { | 356 | if (getsockopt(*ps, SOL_SOCKET, SO_ERROR, (char *) &val, &len) < 0) { |
262 | lua_pushnil(L); | 357 | lua_pushnil(L); |
263 | lua_pushstring(L, "getsockopt failed"); | 358 | lua_pushstring(L, "getsockopt failed"); |
264 | return 2; | 359 | return 2; |
265 | } | 360 | } |
266 | lua_pushstring(L, socket_strerror(val)); | 361 | lua_pushstring(L, socket_strerror(val)); |
267 | return 1; | 362 | return 1; |
268 | } | 363 | } |
269 | 364 | ||
270 | static int opt_setboolean(lua_State *L, p_socket ps, int level, int name) | 365 | static int opt_setboolean(lua_State *L, p_socket ps, int level, int name) |
@@ -273,3 +368,19 @@ static int opt_setboolean(lua_State *L, p_socket ps, int level, int name) | |||
273 | return opt_set(L, ps, level, name, (char *) &val, sizeof(val)); | 368 | return opt_set(L, ps, level, name, (char *) &val, sizeof(val)); |
274 | } | 369 | } |
275 | 370 | ||
371 | static int opt_getint(lua_State *L, p_socket ps, int level, int name) | ||
372 | { | ||
373 | int val = 0; | ||
374 | int len = sizeof(val); | ||
375 | int err = opt_get(L, ps, level, name, (char *) &val, &len); | ||
376 | if (err) | ||
377 | return err; | ||
378 | lua_pushnumber(L, val); | ||
379 | return 1; | ||
380 | } | ||
381 | |||
382 | static int opt_setint(lua_State *L, p_socket ps, int level, int name) | ||
383 | { | ||
384 | int val = (int) lua_tonumber(L, 3); /* obj, name, int */ | ||
385 | return opt_set(L, ps, level, name, (char *) &val, sizeof(val)); | ||
386 | } | ||
diff --git a/src/options.h b/src/options.h index 1cabd7d..5657a06 100644 --- a/src/options.h +++ b/src/options.h | |||
@@ -32,6 +32,11 @@ int opt_set_ip_multicast_ttl(lua_State *L, p_socket ps); | |||
32 | int opt_set_ip_multicast_loop(lua_State *L, p_socket ps); | 32 | 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_unicast_hops(lua_State *L, p_socket ps); | ||
36 | int opt_set_ip6_multicast_hops(lua_State *L, p_socket ps); | ||
37 | int opt_set_ip6_multicast_loop(lua_State *L, p_socket ps); | ||
38 | int opt_set_ip6_add_membership(lua_State *L, p_socket ps); | ||
39 | int opt_set_ip6_drop_membersip(lua_State *L, p_socket ps); | ||
35 | int opt_set_ip6_v6only(lua_State *L, p_socket ps); | 40 | int opt_set_ip6_v6only(lua_State *L, p_socket ps); |
36 | 41 | ||
37 | /* supported options for getoption */ | 42 | /* supported options for getoption */ |
@@ -43,6 +48,10 @@ int opt_get_reuseaddr(lua_State *L, p_socket ps); | |||
43 | int opt_get_ip_multicast_loop(lua_State *L, p_socket ps); | 48 | int opt_get_ip_multicast_loop(lua_State *L, p_socket ps); |
44 | int opt_get_ip_multicast_if(lua_State *L, p_socket ps); | 49 | int opt_get_ip_multicast_if(lua_State *L, p_socket ps); |
45 | int opt_get_error(lua_State *L, p_socket ps); | 50 | int opt_get_error(lua_State *L, p_socket ps); |
51 | int opt_get_ip6_multicast_loop(lua_State *L, p_socket ps); | ||
52 | int opt_get_ip6_multicast_hops(lua_State *L, p_socket ps); | ||
53 | int opt_get_ip6_unicast_hops(lua_State *L, p_socket ps); | ||
54 | int opt_get_ip6_v6only(lua_State *L, p_socket ps); | ||
46 | 55 | ||
47 | /* invokes the appropriate option handler */ | 56 | /* invokes the appropriate option handler */ |
48 | int opt_meth_setoption(lua_State *L, p_opt opt, p_socket ps); | 57 | int opt_meth_setoption(lua_State *L, p_opt opt, p_socket ps); |
diff --git a/src/serial.c b/src/serial.c index 66e8da6..583d4e5 100644 --- a/src/serial.c +++ b/src/serial.c | |||
@@ -73,6 +73,7 @@ LUASOCKET_API int luaopen_socket_serial(lua_State *L) { | |||
73 | auxiliar_add2group(L, "serial{client}", "serial{any}"); | 73 | auxiliar_add2group(L, "serial{client}", "serial{any}"); |
74 | #if LUA_VERSION_NUM > 501 && !defined(LUA_COMPAT_MODULE) | 74 | #if LUA_VERSION_NUM > 501 && !defined(LUA_COMPAT_MODULE) |
75 | lua_pushcfunction(L, global_create); | 75 | lua_pushcfunction(L, global_create); |
76 | (void) func; | ||
76 | #else | 77 | #else |
77 | /* set function into socket namespace */ | 78 | /* set function into socket namespace */ |
78 | luaL_openlib(L, "socket", func, 0); | 79 | luaL_openlib(L, "socket", func, 0); |
@@ -3,6 +3,7 @@ | |||
3 | * LuaSocket toolkit | 3 | * LuaSocket toolkit |
4 | \*=========================================================================*/ | 4 | \*=========================================================================*/ |
5 | #include <string.h> | 5 | #include <string.h> |
6 | #include <stdlib.h> | ||
6 | 7 | ||
7 | #include "lua.h" | 8 | #include "lua.h" |
8 | #include "lauxlib.h" | 9 | #include "lauxlib.h" |
@@ -68,25 +69,34 @@ static luaL_Reg udp_methods[] = { | |||
68 | 69 | ||
69 | /* socket options for setoption */ | 70 | /* socket options for setoption */ |
70 | static t_opt optset[] = { | 71 | static t_opt optset[] = { |
71 | {"dontroute", opt_set_dontroute}, | 72 | {"dontroute", opt_set_dontroute}, |
72 | {"broadcast", opt_set_broadcast}, | 73 | {"broadcast", opt_set_broadcast}, |
73 | {"reuseaddr", opt_set_reuseaddr}, | 74 | {"reuseaddr", opt_set_reuseaddr}, |
74 | {"reuseport", opt_set_reuseport}, | 75 | {"reuseport", opt_set_reuseport}, |
75 | {"ip-multicast-if", opt_set_ip_multicast_if}, | 76 | {"ip-multicast-if", opt_set_ip_multicast_if}, |
76 | {"ip-multicast-ttl", opt_set_ip_multicast_ttl}, | 77 | {"ip-multicast-ttl", opt_set_ip_multicast_ttl}, |
77 | {"ip-multicast-loop", opt_set_ip_multicast_loop}, | 78 | {"ip-multicast-loop", opt_set_ip_multicast_loop}, |
78 | {"ip-add-membership", opt_set_ip_add_membership}, | 79 | {"ip-add-membership", opt_set_ip_add_membership}, |
79 | {"ip-drop-membership", opt_set_ip_drop_membersip}, | 80 | {"ip-drop-membership", opt_set_ip_drop_membersip}, |
80 | {"ipv6-v6only", opt_set_ip6_v6only}, | 81 | {"ipv6-unicast-hops", opt_set_ip6_unicast_hops}, |
81 | {NULL, NULL} | 82 | {"ipv6-multicast-hops", opt_set_ip6_unicast_hops}, |
83 | {"ipv6-multicast-loop", opt_set_ip6_multicast_loop}, | ||
84 | {"ipv6-add-membership", opt_set_ip6_add_membership}, | ||
85 | {"ipv6-drop-membership", opt_set_ip6_drop_membersip}, | ||
86 | {"ipv6-v6only", opt_set_ip6_v6only}, | ||
87 | {NULL, NULL} | ||
82 | }; | 88 | }; |
83 | 89 | ||
84 | /* socket options for getoption */ | 90 | /* socket options for getoption */ |
85 | static t_opt optget[] = { | 91 | static t_opt optget[] = { |
86 | {"ip-multicast-if", opt_get_ip_multicast_if}, | 92 | {"ip-multicast-if", opt_get_ip_multicast_if}, |
87 | {"ip-multicast-loop", opt_get_ip_multicast_loop}, | 93 | {"ip-multicast-loop", opt_get_ip_multicast_loop}, |
88 | {"error", opt_get_error}, | 94 | {"error", opt_get_error}, |
89 | {NULL, NULL} | 95 | {"ipv6-unicast-hops", opt_get_ip6_unicast_hops}, |
96 | {"ipv6-multicast-hops", opt_get_ip6_unicast_hops}, | ||
97 | {"ipv6-multicast-loop", opt_get_ip6_multicast_loop}, | ||
98 | {"ipv6-v6only", opt_get_ip6_v6only}, | ||
99 | {NULL, NULL} | ||
90 | }; | 100 | }; |
91 | 101 | ||
92 | /* functions in library namespace */ | 102 | /* functions in library namespace */ |
@@ -156,39 +166,24 @@ static int meth_sendto(lua_State *L) { | |||
156 | size_t count, sent = 0; | 166 | size_t count, sent = 0; |
157 | const char *data = luaL_checklstring(L, 2, &count); | 167 | const char *data = luaL_checklstring(L, 2, &count); |
158 | const char *ip = luaL_checkstring(L, 3); | 168 | const char *ip = luaL_checkstring(L, 3); |
159 | unsigned short port = (unsigned short) luaL_checknumber(L, 4); | 169 | const char *port = luaL_checkstring(L, 4); |
160 | p_timeout tm = &udp->tm; | 170 | p_timeout tm = &udp->tm; |
161 | int err; | 171 | int err; |
162 | switch (udp->family) { | 172 | struct addrinfo aihint; |
163 | case PF_INET: { | 173 | struct addrinfo *ai; |
164 | struct sockaddr_in addr; | 174 | memset(&aihint, 0, sizeof(aihint)); |
165 | memset(&addr, 0, sizeof(addr)); | 175 | aihint.ai_family = udp->family; |
166 | if (inet_pton(AF_INET, ip, &addr.sin_addr) != 1) | 176 | aihint.ai_socktype = SOCK_DGRAM; |
167 | luaL_argerror(L, 3, "invalid ip address"); | 177 | aihint.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV; |
168 | addr.sin_family = AF_INET; | 178 | if ((err = getaddrinfo(ip, port, &aihint, &ai))) { |
169 | addr.sin_port = htons(port); | ||
170 | timeout_markstart(tm); | ||
171 | err = socket_sendto(&udp->sock, data, count, &sent, | ||
172 | (SA *) &addr, sizeof(addr), tm); | ||
173 | break; | ||
174 | } | ||
175 | case PF_INET6: { | ||
176 | struct sockaddr_in6 addr; | ||
177 | memset(&addr, 0, sizeof(addr)); | ||
178 | if (inet_pton(AF_INET6, ip, &addr.sin6_addr) != 1) | ||
179 | luaL_argerror(L, 3, "invalid ip address"); | ||
180 | addr.sin6_family = AF_INET6; | ||
181 | addr.sin6_port = htons(port); | ||
182 | timeout_markstart(tm); | ||
183 | err = socket_sendto(&udp->sock, data, count, &sent, | ||
184 | (SA *) &addr, sizeof(addr), tm); | ||
185 | break; | ||
186 | } | ||
187 | default: | ||
188 | lua_pushnil(L); | 179 | lua_pushnil(L); |
189 | lua_pushfstring(L, "unknown family %d", udp->family); | 180 | lua_pushstring(L, udp_strerror(err)); |
190 | return 2; | 181 | return 2; |
191 | } | 182 | } |
183 | timeout_markstart(tm); | ||
184 | err = socket_sendto(&udp->sock, data, count, &sent, ai->ai_addr, | ||
185 | ai->ai_addrlen, tm); | ||
186 | freeaddrinfo(ai); | ||
192 | if (err != IO_DONE) { | 187 | if (err != IO_DONE) { |
193 | lua_pushnil(L); | 188 | lua_pushnil(L); |
194 | lua_pushstring(L, udp_strerror(err)); | 189 | lua_pushstring(L, udp_strerror(err)); |
@@ -225,71 +220,39 @@ static int meth_receive(lua_State *L) { | |||
225 | /*-------------------------------------------------------------------------*\ | 220 | /*-------------------------------------------------------------------------*\ |
226 | * Receives data and sender from a UDP socket | 221 | * Receives data and sender from a UDP socket |
227 | \*-------------------------------------------------------------------------*/ | 222 | \*-------------------------------------------------------------------------*/ |
228 | static int meth_receivefrom(lua_State *L) { | 223 | static int meth_receivefrom(lua_State *L) |
224 | { | ||
229 | p_udp udp = (p_udp) auxiliar_checkclass(L, "udp{unconnected}", 1); | 225 | p_udp udp = (p_udp) auxiliar_checkclass(L, "udp{unconnected}", 1); |
230 | char buffer[UDP_DATAGRAMSIZE]; | 226 | char buffer[UDP_DATAGRAMSIZE]; |
231 | size_t got, count = (size_t) luaL_optnumber(L, 2, sizeof(buffer)); | 227 | size_t got, count = (size_t) luaL_optnumber(L, 2, sizeof(buffer)); |
232 | int err; | 228 | int err; |
233 | p_timeout tm = &udp->tm; | 229 | p_timeout tm = &udp->tm; |
230 | struct sockaddr_storage addr; | ||
231 | socklen_t addr_len = sizeof(addr); | ||
232 | char addrstr[INET6_ADDRSTRLEN]; | ||
233 | char portstr[6]; | ||
234 | timeout_markstart(tm); | 234 | timeout_markstart(tm); |
235 | count = MIN(count, sizeof(buffer)); | 235 | count = MIN(count, sizeof(buffer)); |
236 | switch (udp->family) { | 236 | err = socket_recvfrom(&udp->sock, buffer, count, &got, (SA *) &addr, |
237 | case PF_INET: { | 237 | &addr_len, tm); |
238 | struct sockaddr_in addr; | 238 | /* Unlike TCP, recv() of zero is not closed, but a zero-length packet. */ |
239 | socklen_t addr_len = sizeof(addr); | 239 | if (err == IO_CLOSED) |
240 | err = socket_recvfrom(&udp->sock, buffer, count, &got, | 240 | err = IO_DONE; |
241 | (SA *) &addr, &addr_len, tm); | 241 | if (err != IO_DONE) { |
242 | /* Unlike TCP, recv() of zero is not closed, | 242 | lua_pushnil(L); |
243 | * but a zero-length packet. */ | 243 | lua_pushstring(L, udp_strerror(err)); |
244 | if (err == IO_CLOSED) | 244 | return 2; |
245 | err = IO_DONE; | ||
246 | if (err == IO_DONE) { | ||
247 | char addrstr[INET_ADDRSTRLEN]; | ||
248 | lua_pushlstring(L, buffer, got); | ||
249 | if (!inet_ntop(AF_INET, &addr.sin_addr, | ||
250 | addrstr, sizeof(addrstr))) { | ||
251 | lua_pushnil(L); | ||
252 | lua_pushstring(L, "invalid source address"); | ||
253 | return 2; | ||
254 | } | ||
255 | lua_pushstring(L, addrstr); | ||
256 | lua_pushnumber(L, ntohs(addr.sin_port)); | ||
257 | return 3; | ||
258 | } | ||
259 | break; | ||
260 | } | ||
261 | case PF_INET6: { | ||
262 | struct sockaddr_in6 addr; | ||
263 | socklen_t addr_len = sizeof(addr); | ||
264 | err = socket_recvfrom(&udp->sock, buffer, count, &got, | ||
265 | (SA *) &addr, &addr_len, tm); | ||
266 | /* Unlike TCP, recv() of zero is not closed, | ||
267 | * but a zero-length packet. */ | ||
268 | if (err == IO_CLOSED) | ||
269 | err = IO_DONE; | ||
270 | if (err == IO_DONE) { | ||
271 | char addrstr[INET6_ADDRSTRLEN]; | ||
272 | lua_pushlstring(L, buffer, got); | ||
273 | if (!inet_ntop(AF_INET6, &addr.sin6_addr, | ||
274 | addrstr, sizeof(addrstr))) { | ||
275 | lua_pushnil(L); | ||
276 | lua_pushstring(L, "invalid source address"); | ||
277 | return 2; | ||
278 | } | ||
279 | lua_pushstring(L, addrstr); | ||
280 | lua_pushnumber(L, ntohs(addr.sin6_port)); | ||
281 | return 3; | ||
282 | } | ||
283 | break; | ||
284 | } | 245 | } |
285 | default: | 246 | if ((err = getnameinfo((struct sockaddr *)&addr, addr_len, addrstr, |
247 | INET6_ADDRSTRLEN, portstr, 6, NI_NUMERICHOST | NI_NUMERICSERV))) { | ||
286 | lua_pushnil(L); | 248 | lua_pushnil(L); |
287 | lua_pushfstring(L, "unknown family %d", udp->family); | 249 | lua_pushstring(L, gai_strerror(err)); |
288 | return 2; | 250 | return 2; |
289 | } | 251 | } |
290 | lua_pushnil(L); | 252 | lua_pushlstring(L, buffer, got); |
291 | lua_pushstring(L, udp_strerror(err)); | 253 | lua_pushstring(L, addrstr); |
292 | return 2; | 254 | lua_pushinteger(L, (int) strtol(portstr, (char **) NULL, 10)); |
255 | return 3; | ||
293 | } | 256 | } |
294 | 257 | ||
295 | /*-------------------------------------------------------------------------*\ | 258 | /*-------------------------------------------------------------------------*\ |
@@ -91,6 +91,7 @@ int luaopen_socket_unix(lua_State *L) { | |||
91 | auxiliar_add2group(L, "unix{server}", "unix{any}"); | 91 | auxiliar_add2group(L, "unix{server}", "unix{any}"); |
92 | #if LUA_VERSION_NUM > 501 && !defined(LUA_COMPAT_MODULE) | 92 | #if LUA_VERSION_NUM > 501 && !defined(LUA_COMPAT_MODULE) |
93 | lua_pushcfunction(L, global_create); | 93 | lua_pushcfunction(L, global_create); |
94 | (void) func; | ||
94 | #else | 95 | #else |
95 | /* set function into socket namespace */ | 96 | /* set function into socket namespace */ |
96 | luaL_openlib(L, "socket", func, 0); | 97 | luaL_openlib(L, "socket", func, 0); |