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 | |
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.
-rw-r--r-- | doc/udp.html | 34 | ||||
-rw-r--r-- | src/udp.c | 58 | ||||
-rw-r--r-- | src/udp.h | 5 |
3 files changed, 68 insertions, 29 deletions
diff --git a/doc/udp.html b/doc/udp.html index a300f2f..22d7c72 100644 --- a/doc/udp.html +++ b/doc/udp.html | |||
@@ -42,7 +42,7 @@ | |||
42 | <!-- socket.udp ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> | 42 | <!-- socket.udp ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> |
43 | 43 | ||
44 | <p class="name" id="socket.udp"> | 44 | <p class="name" id="socket.udp"> |
45 | socket.<b>udp()</b> | 45 | socket.<b>udp(</b>[buffersize]<b>)</b> |
46 | </p> | 46 | </p> |
47 | 47 | ||
48 | <p class="description"> | 48 | <p class="description"> |
@@ -62,6 +62,13 @@ The <a href="#setpeername"><tt>setpeername</tt></a> | |||
62 | is used to connect the object. | 62 | is used to connect the object. |
63 | </p> | 63 | </p> |
64 | 64 | ||
65 | <p class="parameters"> | ||
66 | The optional <tt>buffersize</tt> parameter | ||
67 | specifies the size of the largest datagram that will | ||
68 | ever be received by the UDP object. The default value is | ||
69 | 8192. | ||
70 | </p> | ||
71 | |||
65 | <p class="return"> | 72 | <p class="return"> |
66 | In case of success, a new unconnected UDP object | 73 | In case of success, a new unconnected UDP object |
67 | returned. In case of error, <b><tt>nil</tt></b> is returned, followed by | 74 | returned. In case of error, <b><tt>nil</tt></b> is returned, followed by |
@@ -85,7 +92,7 @@ href=#setoption><tt>setoption</tt></a> will fail. | |||
85 | <!-- socket.udp4 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> | 92 | <!-- socket.udp4 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> |
86 | 93 | ||
87 | <p class="name" id="socket.udp"> | 94 | <p class="name" id="socket.udp"> |
88 | socket.<b>udp4()</b> | 95 | socket.<b>udp4(</b>[buffersize]<b>)</b> |
89 | </p> | 96 | </p> |
90 | 97 | ||
91 | <p class="description"> | 98 | <p class="description"> |
@@ -105,6 +112,13 @@ The <a href="#setpeername"><tt>setpeername</tt></a> | |||
105 | is used to connect the object. | 112 | is used to connect the object. |
106 | </p> | 113 | </p> |
107 | 114 | ||
115 | <p class="parameters"> | ||
116 | The optional <tt>buffersize</tt> parameter | ||
117 | specifies the size of the largest datagram that will | ||
118 | ever be received by the UDP object. The default value is | ||
119 | 8192. | ||
120 | </p> | ||
121 | |||
108 | <p class="return"> | 122 | <p class="return"> |
109 | In case of success, a new unconnected UDP object | 123 | In case of success, a new unconnected UDP object |
110 | returned. In case of error, <b><tt>nil</tt></b> is returned, followed by | 124 | returned. In case of error, <b><tt>nil</tt></b> is returned, followed by |
@@ -114,7 +128,7 @@ an error message. | |||
114 | <!-- socket.udp ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> | 128 | <!-- socket.udp ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> |
115 | 129 | ||
116 | <p class="name" id="socket.udp6"> | 130 | <p class="name" id="socket.udp6"> |
117 | socket.<b>udp6()</b> | 131 | socket.<b>udp6(</b>[buffersize]<b>)</b> |
118 | </p> | 132 | </p> |
119 | 133 | ||
120 | <p class="description"> | 134 | <p class="description"> |
@@ -134,6 +148,13 @@ The <a href="#setpeername"><tt>setpeername</tt></a> | |||
134 | is used to connect the object. | 148 | is used to connect the object. |
135 | </p> | 149 | </p> |
136 | 150 | ||
151 | <p class="parameters"> | ||
152 | The optional <tt>buffersize</tt> parameter | ||
153 | specifies the size of the largest datagram that will | ||
154 | ever be received by the UDP object. The default value is | ||
155 | 8192. | ||
156 | </p> | ||
157 | |||
137 | <p class="return"> | 158 | <p class="return"> |
138 | In case of success, a new unconnected UDP object | 159 | In case of success, a new unconnected UDP object |
139 | returned. In case of error, <b><tt>nil</tt></b> is returned, followed by | 160 | returned. In case of error, <b><tt>nil</tt></b> is returned, followed by |
@@ -238,9 +259,10 @@ specifies the maximum size of the datagram to be retrieved. If | |||
238 | there are more than <tt>size</tt> bytes available in the datagram, | 259 | there are more than <tt>size</tt> bytes available in the datagram, |
239 | the excess bytes are discarded. If there are less then | 260 | the excess bytes are discarded. If there are less then |
240 | <tt>size</tt> bytes available in the current datagram, the | 261 | <tt>size</tt> bytes available in the current datagram, the |
241 | available bytes are returned. If <tt>size</tt> is omitted, the | 262 | available bytes are returned. |
242 | maximum datagram size is used (which is currently limited by the | 263 | If <tt>size</tt> is omitted, the |
243 | implementation to 8192 bytes). | 264 | <tt>buffersize</tt> argument at creation time is used |
265 | (which defaults to 8192 bytes). | ||
244 | </p> | 266 | </p> |
245 | 267 | ||
246 | <p class="return"> | 268 | <p class="return"> |
@@ -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 | ||