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 /src | |
| 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.
Diffstat (limited to 'src')
| -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 |
7 files changed, 257 insertions, 193 deletions
| @@ -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); |
