diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/select.c | 5 | ||||
-rw-r--r-- | src/udp.c | 58 | ||||
-rw-r--r-- | src/udp.h | 2 |
3 files changed, 31 insertions, 34 deletions
diff --git a/src/select.c b/src/select.c index d14c40a..9d133b7 100644 --- a/src/select.c +++ b/src/select.c | |||
@@ -39,7 +39,10 @@ static luaL_Reg func[] = { | |||
39 | \*-------------------------------------------------------------------------*/ | 39 | \*-------------------------------------------------------------------------*/ |
40 | int select_open(lua_State *L) { | 40 | int select_open(lua_State *L) { |
41 | lua_pushstring(L, "_SETSIZE"); | 41 | lua_pushstring(L, "_SETSIZE"); |
42 | lua_pushnumber(L, FD_SETSIZE); | 42 | lua_pushinteger(L, FD_SETSIZE); |
43 | lua_rawset(L, -3); | ||
44 | lua_pushstring(L, "_SOCKETINVALID"); | ||
45 | lua_pushinteger(L, SOCKET_INVALID); | ||
43 | lua_rawset(L, -3); | 46 | lua_rawset(L, -3); |
44 | luaL_setfuncs(L, func, 0); | 47 | luaL_setfuncs(L, func, 0); |
45 | return 0; | 48 | return 0; |
@@ -41,7 +41,6 @@ static int meth_setpeername(lua_State *L); | |||
41 | static int meth_close(lua_State *L); | 41 | static int meth_close(lua_State *L); |
42 | static int meth_setoption(lua_State *L); | 42 | static int meth_setoption(lua_State *L); |
43 | static int meth_getoption(lua_State *L); | 43 | static int meth_getoption(lua_State *L); |
44 | static int meth_getbufferlength(lua_State *L); | ||
45 | static int meth_settimeout(lua_State *L); | 44 | static int meth_settimeout(lua_State *L); |
46 | static int meth_getfd(lua_State *L); | 45 | static int meth_getfd(lua_State *L); |
47 | static int meth_setfd(lua_State *L); | 46 | static int meth_setfd(lua_State *L); |
@@ -64,7 +63,6 @@ static luaL_Reg udp_methods[] = { | |||
64 | {"setfd", meth_setfd}, | 63 | {"setfd", meth_setfd}, |
65 | {"setoption", meth_setoption}, | 64 | {"setoption", meth_setoption}, |
66 | {"getoption", meth_getoption}, | 65 | {"getoption", meth_getoption}, |
67 | {"getoption", meth_getbufferlength}, | ||
68 | {"setpeername", meth_setpeername}, | 66 | {"setpeername", meth_setpeername}, |
69 | {"setsockname", meth_setsockname}, | 67 | {"setsockname", meth_setsockname}, |
70 | {"settimeout", meth_settimeout}, | 68 | {"settimeout", meth_settimeout}, |
@@ -118,8 +116,7 @@ static luaL_Reg func[] = { | |||
118 | /*-------------------------------------------------------------------------*\ | 116 | /*-------------------------------------------------------------------------*\ |
119 | * Initializes module | 117 | * Initializes module |
120 | \*-------------------------------------------------------------------------*/ | 118 | \*-------------------------------------------------------------------------*/ |
121 | int udp_open(lua_State *L) | 119 | int udp_open(lua_State *L) { |
122 | { | ||
123 | /* create classes */ | 120 | /* create classes */ |
124 | auxiliar_newclass(L, "udp{connected}", udp_methods); | 121 | auxiliar_newclass(L, "udp{connected}", udp_methods); |
125 | auxiliar_newclass(L, "udp{unconnected}", udp_methods); | 122 | auxiliar_newclass(L, "udp{unconnected}", udp_methods); |
@@ -130,6 +127,10 @@ int udp_open(lua_State *L) | |||
130 | auxiliar_add2group(L, "udp{unconnected}", "select{able}"); | 127 | auxiliar_add2group(L, "udp{unconnected}", "select{able}"); |
131 | /* define library functions */ | 128 | /* define library functions */ |
132 | luaL_setfuncs(L, func, 0); | 129 | luaL_setfuncs(L, func, 0); |
130 | /* export default UDP size */ | ||
131 | lua_pushliteral(L, "_DATAGRAMSIZE"); | ||
132 | lua_pushinteger(L, UDP_DATAGRAMSIZE); | ||
133 | lua_rawset(L, -3); | ||
133 | return 0; | 134 | return 0; |
134 | } | 135 | } |
135 | 136 | ||
@@ -205,30 +206,26 @@ static int meth_sendto(lua_State *L) { | |||
205 | static int meth_receive(lua_State *L) { | 206 | static int meth_receive(lua_State *L) { |
206 | p_udp udp = (p_udp) auxiliar_checkgroup(L, "udp{any}", 1); | 207 | p_udp udp = (p_udp) auxiliar_checkgroup(L, "udp{any}", 1); |
207 | char buf[UDP_DATAGRAMSIZE]; | 208 | char buf[UDP_DATAGRAMSIZE]; |
208 | size_t len = MAX(udp->len, UDP_DATAGRAMSIZE); | 209 | size_t got, wanted = (size_t) luaL_optnumber(L, 2, sizeof(buf)); |
209 | char *dgram = len > sizeof(buf)? udp->buf: buf; | 210 | char *dgram = wanted > sizeof(buf)? (char *) malloc(wanted): buf; |
210 | size_t got, wanted = (size_t) luaL_optnumber(L, 2, len); | ||
211 | int err; | 211 | int err; |
212 | p_timeout tm = &udp->tm; | 212 | p_timeout tm = &udp->tm; |
213 | timeout_markstart(tm); | 213 | timeout_markstart(tm); |
214 | wanted = MIN(wanted, len); | 214 | if (!dgram) { |
215 | lua_pushnil(L); | ||
216 | lua_pushliteral(L, "out of memory"); | ||
217 | return 2; | ||
218 | } | ||
215 | err = socket_recv(&udp->sock, dgram, wanted, &got, tm); | 219 | err = socket_recv(&udp->sock, dgram, wanted, &got, tm); |
216 | /* Unlike TCP, recv() of zero is not closed, but a zero-length packet. */ | 220 | /* Unlike TCP, recv() of zero is not closed, but a zero-length packet. */ |
217 | if (err != IO_DONE && err != IO_CLOSED ) { | 221 | if (err != IO_DONE && err != IO_CLOSED) { |
218 | lua_pushnil(L); | 222 | lua_pushnil(L); |
219 | lua_pushstring(L, udp_strerror(err)); | 223 | lua_pushstring(L, udp_strerror(err)); |
224 | if (wanted > sizeof(buf)) free(dgram); | ||
220 | return 2; | 225 | return 2; |
221 | } | 226 | } |
222 | lua_pushlstring(L, dgram, got); | 227 | lua_pushlstring(L, dgram, got); |
223 | return 1; | 228 | if (wanted > sizeof(buf)) free(dgram); |
224 | } | ||
225 | |||
226 | /*-------------------------------------------------------------------------*\ | ||
227 | * Receives data from a UDP socket | ||
228 | \*-------------------------------------------------------------------------*/ | ||
229 | static int meth_getbufferlength(lua_State *L) { | ||
230 | p_udp udp = (p_udp) auxiliar_checkgroup(L, "udp{any}", 1); | ||
231 | lua_pushinteger(L, MAX(UDP_DATAGRAMSIZE, udp->len)); | ||
232 | return 1; | 229 | return 1; |
233 | } | 230 | } |
234 | 231 | ||
@@ -238,9 +235,8 @@ static int meth_getbufferlength(lua_State *L) { | |||
238 | static int meth_receivefrom(lua_State *L) { | 235 | static int meth_receivefrom(lua_State *L) { |
239 | p_udp udp = (p_udp) auxiliar_checkclass(L, "udp{unconnected}", 1); | 236 | p_udp udp = (p_udp) auxiliar_checkclass(L, "udp{unconnected}", 1); |
240 | char buf[UDP_DATAGRAMSIZE]; | 237 | char buf[UDP_DATAGRAMSIZE]; |
241 | size_t len = MAX(udp->len, UDP_DATAGRAMSIZE); | 238 | size_t got, wanted = (size_t) luaL_optnumber(L, 2, sizeof(buf)); |
242 | char *dgram = len > sizeof(buf)? udp->buf: buf; | 239 | char *dgram = wanted > sizeof(buf)? (char *) malloc(wanted): buf; |
243 | size_t got, wanted = (size_t) luaL_optnumber(L, 2, len); | ||
244 | struct sockaddr_storage addr; | 240 | struct sockaddr_storage addr; |
245 | socklen_t addr_len = sizeof(addr); | 241 | socklen_t addr_len = sizeof(addr); |
246 | char addrstr[INET6_ADDRSTRLEN]; | 242 | char addrstr[INET6_ADDRSTRLEN]; |
@@ -248,13 +244,18 @@ static int meth_receivefrom(lua_State *L) { | |||
248 | int err; | 244 | int err; |
249 | p_timeout tm = &udp->tm; | 245 | p_timeout tm = &udp->tm; |
250 | timeout_markstart(tm); | 246 | timeout_markstart(tm); |
251 | wanted = MIN(wanted, len); | 247 | if (!dgram) { |
248 | lua_pushnil(L); | ||
249 | lua_pushliteral(L, "out of memory"); | ||
250 | return 2; | ||
251 | } | ||
252 | err = socket_recvfrom(&udp->sock, dgram, wanted, &got, (SA *) &addr, | 252 | err = socket_recvfrom(&udp->sock, dgram, wanted, &got, (SA *) &addr, |
253 | &addr_len, tm); | 253 | &addr_len, tm); |
254 | /* Unlike TCP, recv() of zero is not closed, but a zero-length packet. */ | 254 | /* Unlike TCP, recv() of zero is not closed, but a zero-length packet. */ |
255 | if (err != IO_DONE && err != IO_CLOSED) { | 255 | if (err != IO_DONE && err != IO_CLOSED) { |
256 | lua_pushnil(L); | 256 | lua_pushnil(L); |
257 | lua_pushstring(L, udp_strerror(err)); | 257 | lua_pushstring(L, udp_strerror(err)); |
258 | if (wanted > sizeof(buf)) free(dgram); | ||
258 | return 2; | 259 | return 2; |
259 | } | 260 | } |
260 | err = getnameinfo((struct sockaddr *)&addr, addr_len, addrstr, | 261 | err = getnameinfo((struct sockaddr *)&addr, addr_len, addrstr, |
@@ -262,19 +263,20 @@ static int meth_receivefrom(lua_State *L) { | |||
262 | if (err) { | 263 | if (err) { |
263 | lua_pushnil(L); | 264 | lua_pushnil(L); |
264 | lua_pushstring(L, gai_strerror(err)); | 265 | lua_pushstring(L, gai_strerror(err)); |
266 | if (wanted > sizeof(buf)) free(dgram); | ||
265 | return 2; | 267 | return 2; |
266 | } | 268 | } |
267 | lua_pushlstring(L, dgram, got); | 269 | lua_pushlstring(L, dgram, got); |
268 | lua_pushstring(L, addrstr); | 270 | lua_pushstring(L, addrstr); |
269 | lua_pushinteger(L, (int) strtol(portstr, (char **) NULL, 10)); | 271 | lua_pushinteger(L, (int) strtol(portstr, (char **) NULL, 10)); |
272 | if (wanted > sizeof(buf)) free(dgram); | ||
270 | return 3; | 273 | return 3; |
271 | } | 274 | } |
272 | 275 | ||
273 | /*-------------------------------------------------------------------------*\ | 276 | /*-------------------------------------------------------------------------*\ |
274 | * Returns family as string | 277 | * Returns family as string |
275 | \*-------------------------------------------------------------------------*/ | 278 | \*-------------------------------------------------------------------------*/ |
276 | static int meth_getfamily(lua_State *L) | 279 | static int meth_getfamily(lua_State *L) { |
277 | { | ||
278 | p_udp udp = (p_udp) auxiliar_checkgroup(L, "udp{any}", 1); | 280 | p_udp udp = (p_udp) auxiliar_checkgroup(L, "udp{any}", 1); |
279 | if (udp->family == AF_INET6) { | 281 | if (udp->family == AF_INET6) { |
280 | lua_pushliteral(L, "inet6"); | 282 | lua_pushliteral(L, "inet6"); |
@@ -419,19 +421,13 @@ static int meth_setsockname(lua_State *L) { | |||
419 | * Creates a master udp object | 421 | * Creates a master udp object |
420 | \*-------------------------------------------------------------------------*/ | 422 | \*-------------------------------------------------------------------------*/ |
421 | static int udp_create(lua_State *L, int family) { | 423 | static int udp_create(lua_State *L, int family) { |
422 | p_udp udp = NULL; | ||
423 | /* optional length for private datagram buffer. this is useful when | ||
424 | * you need larger datagrams than UDP_DATAGRAMSIZE */ | ||
425 | size_t len = (size_t) luaL_optinteger(L, 1, 0); | ||
426 | if (len <= UDP_DATAGRAMSIZE) len = 0; | ||
427 | /* allocate udp object */ | 424 | /* allocate udp object */ |
428 | udp = (p_udp) lua_newuserdata(L, sizeof(t_udp) + len - 1); | 425 | p_udp udp = (p_udp) lua_newuserdata(L, sizeof(t_udp)); |
429 | auxiliar_setclass(L, "udp{unconnected}", -1); | 426 | auxiliar_setclass(L, "udp{unconnected}", -1); |
430 | /* if family is AF_UNSPEC, we leave the socket invalid and | 427 | /* if family is AF_UNSPEC, we leave the socket invalid and |
431 | * store AF_UNSPEC into family. This will allow it to later be | 428 | * store AF_UNSPEC into family. This will allow it to later be |
432 | * replaced with an AF_INET6 or AF_INET socket upon first use. */ | 429 | * replaced with an AF_INET6 or AF_INET socket upon first use. */ |
433 | udp->sock = SOCKET_INVALID; | 430 | udp->sock = SOCKET_INVALID; |
434 | udp->len = len; | ||
435 | timeout_init(&udp->tm, -1, -1); | 431 | timeout_init(&udp->tm, -1, -1); |
436 | udp->family = family; | 432 | udp->family = family; |
437 | if (family != AF_UNSPEC) { | 433 | if (family != AF_UNSPEC) { |
@@ -23,8 +23,6 @@ typedef struct t_udp_ { | |||
23 | t_socket sock; | 23 | t_socket sock; |
24 | t_timeout tm; | 24 | t_timeout tm; |
25 | int family; | 25 | int family; |
26 | size_t len; /* length of datagram buffer below */ | ||
27 | char buf[1]; /* allocate larger structure to hold actual buffer */ | ||
28 | } t_udp; | 26 | } t_udp; |
29 | typedef t_udp *p_udp; | 27 | typedef t_udp *p_udp; |
30 | 28 | ||