diff options
| author | Diego Nehab <diego.nehab@gmail.com> | 2015-10-05 11:47:51 +0800 |
|---|---|---|
| committer | Diego Nehab <diego.nehab@gmail.com> | 2015-10-05 11:47:51 +0800 |
| commit | fd729b32a8966291f007567f72f3dc0158bdab35 (patch) | |
| tree | 46737842ba3f9a5aaa2325a76724f12fbc53353e /src | |
| parent | d1ec29be7f982db75864155dd61a058902e1cae2 (diff) | |
| download | luasocket-fd729b32a8966291f007567f72f3dc0158bdab35.tar.gz luasocket-fd729b32a8966291f007567f72f3dc0158bdab35.tar.bz2 luasocket-fd729b32a8966291f007567f72f3dc0158bdab35.zip | |
Added support for arbitrary datagram sizes.
The maximum size is still constant per UDP object, but the
size can be speficied at creation time.
Diffstat (limited to 'src')
| -rw-r--r-- | src/udp.c | 58 | ||||
| -rw-r--r-- | src/udp.h | 5 |
2 files changed, 40 insertions, 23 deletions
| @@ -41,6 +41,7 @@ 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); | ||
| 44 | static int meth_settimeout(lua_State *L); | 45 | static int meth_settimeout(lua_State *L); |
| 45 | static int meth_getfd(lua_State *L); | 46 | static int meth_getfd(lua_State *L); |
| 46 | static int meth_setfd(lua_State *L); | 47 | static int meth_setfd(lua_State *L); |
| @@ -63,6 +64,7 @@ static luaL_Reg udp_methods[] = { | |||
| 63 | {"setfd", meth_setfd}, | 64 | {"setfd", meth_setfd}, |
| 64 | {"setoption", meth_setoption}, | 65 | {"setoption", meth_setoption}, |
| 65 | {"getoption", meth_getoption}, | 66 | {"getoption", meth_getoption}, |
| 67 | {"getoption", meth_getbufferlength}, | ||
| 66 | {"setpeername", meth_setpeername}, | 68 | {"setpeername", meth_setpeername}, |
| 67 | {"setsockname", meth_setsockname}, | 69 | {"setsockname", meth_setsockname}, |
| 68 | {"settimeout", meth_settimeout}, | 70 | {"settimeout", meth_settimeout}, |
| @@ -202,47 +204,55 @@ static int meth_sendto(lua_State *L) { | |||
| 202 | \*-------------------------------------------------------------------------*/ | 204 | \*-------------------------------------------------------------------------*/ |
| 203 | static int meth_receive(lua_State *L) { | 205 | static int meth_receive(lua_State *L) { |
| 204 | p_udp udp = (p_udp) auxiliar_checkgroup(L, "udp{any}", 1); | 206 | p_udp udp = (p_udp) auxiliar_checkgroup(L, "udp{any}", 1); |
| 205 | char buffer[UDP_DATAGRAMSIZE]; | 207 | char buf[UDP_DATAGRAMSIZE]; |
| 206 | size_t got, count = (size_t) luaL_optnumber(L, 2, sizeof(buffer)); | 208 | size_t len = MAX(udp->len, UDP_DATAGRAMSIZE); |
| 209 | char *dgram = len > sizeof(buf)? udp->buf: buf; | ||
| 210 | size_t got, wanted = (size_t) luaL_optnumber(L, 2, len); | ||
| 207 | int err; | 211 | int err; |
| 208 | p_timeout tm = &udp->tm; | 212 | p_timeout tm = &udp->tm; |
| 209 | count = MIN(count, sizeof(buffer)); | ||
| 210 | timeout_markstart(tm); | 213 | timeout_markstart(tm); |
| 211 | err = socket_recv(&udp->sock, buffer, count, &got, tm); | 214 | wanted = MIN(wanted, len); |
| 215 | err = socket_recv(&udp->sock, dgram, wanted, &got, tm); | ||
| 212 | /* Unlike TCP, recv() of zero is not closed, but a zero-length packet. */ | 216 | /* Unlike TCP, recv() of zero is not closed, but a zero-length packet. */ |
| 213 | if (err == IO_CLOSED) | 217 | if (err != IO_DONE && err != IO_CLOSED ) { |
| 214 | err = IO_DONE; | ||
| 215 | if (err != IO_DONE) { | ||
| 216 | lua_pushnil(L); | 218 | lua_pushnil(L); |
| 217 | lua_pushstring(L, udp_strerror(err)); | 219 | lua_pushstring(L, udp_strerror(err)); |
| 218 | return 2; | 220 | return 2; |
| 219 | } | 221 | } |
| 220 | lua_pushlstring(L, buffer, got); | 222 | lua_pushlstring(L, dgram, got); |
| 223 | return 1; | ||
| 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)); | ||
| 221 | return 1; | 232 | return 1; |
| 222 | } | 233 | } |
| 223 | 234 | ||
| 224 | /*-------------------------------------------------------------------------*\ | 235 | /*-------------------------------------------------------------------------*\ |
| 225 | * Receives data and sender from a UDP socket | 236 | * Receives data and sender from a UDP socket |
| 226 | \*-------------------------------------------------------------------------*/ | 237 | \*-------------------------------------------------------------------------*/ |
| 227 | static int meth_receivefrom(lua_State *L) | 238 | static int meth_receivefrom(lua_State *L) { |
| 228 | { | ||
| 229 | p_udp udp = (p_udp) auxiliar_checkclass(L, "udp{unconnected}", 1); | 239 | p_udp udp = (p_udp) auxiliar_checkclass(L, "udp{unconnected}", 1); |
| 230 | char buffer[UDP_DATAGRAMSIZE]; | 240 | char buf[UDP_DATAGRAMSIZE]; |
| 231 | size_t got, count = (size_t) luaL_optnumber(L, 2, sizeof(buffer)); | 241 | size_t len = MAX(udp->len, UDP_DATAGRAMSIZE); |
| 232 | int err; | 242 | char *dgram = len > sizeof(buf)? udp->buf: buf; |
| 233 | p_timeout tm = &udp->tm; | 243 | size_t got, wanted = (size_t) luaL_optnumber(L, 2, len); |
| 234 | struct sockaddr_storage addr; | 244 | struct sockaddr_storage addr; |
| 235 | socklen_t addr_len = sizeof(addr); | 245 | socklen_t addr_len = sizeof(addr); |
| 236 | char addrstr[INET6_ADDRSTRLEN]; | 246 | char addrstr[INET6_ADDRSTRLEN]; |
| 237 | char portstr[6]; | 247 | char portstr[6]; |
| 248 | int err; | ||
| 249 | p_timeout tm = &udp->tm; | ||
| 238 | timeout_markstart(tm); | 250 | timeout_markstart(tm); |
| 239 | count = MIN(count, sizeof(buffer)); | 251 | wanted = MIN(wanted, len); |
| 240 | err = socket_recvfrom(&udp->sock, buffer, count, &got, (SA *) &addr, | 252 | err = socket_recvfrom(&udp->sock, dgram, wanted, &got, (SA *) &addr, |
| 241 | &addr_len, tm); | 253 | &addr_len, tm); |
| 242 | /* 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. */ |
| 243 | if (err == IO_CLOSED) | 255 | if (err != IO_DONE && err != IO_CLOSED) { |
| 244 | err = IO_DONE; | ||
| 245 | if (err != IO_DONE) { | ||
| 246 | lua_pushnil(L); | 256 | lua_pushnil(L); |
| 247 | lua_pushstring(L, udp_strerror(err)); | 257 | lua_pushstring(L, udp_strerror(err)); |
| 248 | return 2; | 258 | return 2; |
| @@ -254,7 +264,7 @@ static int meth_receivefrom(lua_State *L) | |||
| 254 | lua_pushstring(L, gai_strerror(err)); | 264 | lua_pushstring(L, gai_strerror(err)); |
| 255 | return 2; | 265 | return 2; |
| 256 | } | 266 | } |
| 257 | lua_pushlstring(L, buffer, got); | 267 | lua_pushlstring(L, dgram, got); |
| 258 | lua_pushstring(L, addrstr); | 268 | lua_pushstring(L, addrstr); |
| 259 | lua_pushinteger(L, (int) strtol(portstr, (char **) NULL, 10)); | 269 | lua_pushinteger(L, (int) strtol(portstr, (char **) NULL, 10)); |
| 260 | return 3; | 270 | return 3; |
| @@ -409,13 +419,19 @@ static int meth_setsockname(lua_State *L) { | |||
| 409 | * Creates a master udp object | 419 | * Creates a master udp object |
| 410 | \*-------------------------------------------------------------------------*/ | 420 | \*-------------------------------------------------------------------------*/ |
| 411 | static int udp_create(lua_State *L, int family) { | 421 | 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; | ||
| 412 | /* allocate udp object */ | 427 | /* allocate udp object */ |
| 413 | p_udp udp = (p_udp) lua_newuserdata(L, sizeof(t_udp)); | 428 | udp = (p_udp) lua_newuserdata(L, sizeof(t_udp) + len - 1); |
| 414 | auxiliar_setclass(L, "udp{unconnected}", -1); | 429 | auxiliar_setclass(L, "udp{unconnected}", -1); |
| 415 | /* if family is AF_UNSPEC, we leave the socket invalid and | 430 | /* if family is AF_UNSPEC, we leave the socket invalid and |
| 416 | * store AF_UNSPEC into family. This will allow it to later be | 431 | * store AF_UNSPEC into family. This will allow it to later be |
| 417 | * replaced with an AF_INET6 or AF_INET socket upon first use. */ | 432 | * replaced with an AF_INET6 or AF_INET socket upon first use. */ |
| 418 | udp->sock = SOCKET_INVALID; | 433 | udp->sock = SOCKET_INVALID; |
| 434 | udp->len = len; | ||
| 419 | timeout_init(&udp->tm, -1, -1); | 435 | timeout_init(&udp->tm, -1, -1); |
| 420 | udp->family = family; | 436 | udp->family = family; |
| 421 | if (family != AF_UNSPEC) { | 437 | if (family != AF_UNSPEC) { |
| @@ -8,7 +8,7 @@ | |||
| 8 | * (AF_INET, SOCK_DGRAM). | 8 | * (AF_INET, SOCK_DGRAM). |
| 9 | * | 9 | * |
| 10 | * Two classes are defined: connected and unconnected. UDP objects are | 10 | * Two classes are defined: connected and unconnected. UDP objects are |
| 11 | * originally unconnected. They can be "connected" to a given address | 11 | * originally unconnected. They can be "connected" to a given address |
| 12 | * with a call to the setpeername function. The same function can be used to | 12 | * with a call to the setpeername function. The same function can be used to |
| 13 | * break the connection. | 13 | * break the connection. |
| 14 | \*=========================================================================*/ | 14 | \*=========================================================================*/ |
| @@ -17,13 +17,14 @@ | |||
| 17 | #include "timeout.h" | 17 | #include "timeout.h" |
| 18 | #include "socket.h" | 18 | #include "socket.h" |
| 19 | 19 | ||
| 20 | /* can't be larger than wsocket.c MAXCHUNK!!! */ | ||
| 21 | #define UDP_DATAGRAMSIZE 8192 | 20 | #define UDP_DATAGRAMSIZE 8192 |
| 22 | 21 | ||
| 23 | typedef struct t_udp_ { | 22 | typedef struct t_udp_ { |
| 24 | t_socket sock; | 23 | t_socket sock; |
| 25 | t_timeout tm; | 24 | t_timeout tm; |
| 26 | 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 */ | ||
| 27 | } t_udp; | 28 | } t_udp; |
| 28 | typedef t_udp *p_udp; | 29 | typedef t_udp *p_udp; |
| 29 | 30 | ||
