aboutsummaryrefslogtreecommitdiff
path: root/src/udp.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rwxr-xr-x[-rw-r--r--]src/udp.c111
1 files changed, 78 insertions, 33 deletions
diff --git a/src/udp.c b/src/udp.c
index 17d932a..712ad50 100644..100755
--- a/src/udp.c
+++ b/src/udp.c
@@ -2,12 +2,7 @@
2* UDP object 2* UDP object
3* LuaSocket toolkit 3* LuaSocket toolkit
4\*=========================================================================*/ 4\*=========================================================================*/
5#include <string.h> 5#include "luasocket.h"
6#include <stdlib.h>
7
8#include "lua.h"
9#include "lauxlib.h"
10#include "compat.h"
11 6
12#include "auxiliar.h" 7#include "auxiliar.h"
13#include "socket.h" 8#include "socket.h"
@@ -15,6 +10,9 @@
15#include "options.h" 10#include "options.h"
16#include "udp.h" 11#include "udp.h"
17 12
13#include <string.h>
14#include <stdlib.h>
15
18/* min and max macros */ 16/* min and max macros */
19#ifndef MIN 17#ifndef MIN
20#define MIN(x, y) ((x) < (y) ? x : y) 18#define MIN(x, y) ((x) < (y) ? x : y)
@@ -36,6 +34,7 @@ static int meth_receivefrom(lua_State *L);
36static int meth_getfamily(lua_State *L); 34static int meth_getfamily(lua_State *L);
37static int meth_getsockname(lua_State *L); 35static int meth_getsockname(lua_State *L);
38static int meth_getpeername(lua_State *L); 36static int meth_getpeername(lua_State *L);
37static int meth_gettimeout(lua_State *L);
39static int meth_setsockname(lua_State *L); 38static int meth_setsockname(lua_State *L);
40static int meth_setpeername(lua_State *L); 39static int meth_setpeername(lua_State *L);
41static int meth_close(lua_State *L); 40static int meth_close(lua_State *L);
@@ -66,6 +65,7 @@ static luaL_Reg udp_methods[] = {
66 {"setpeername", meth_setpeername}, 65 {"setpeername", meth_setpeername},
67 {"setsockname", meth_setsockname}, 66 {"setsockname", meth_setsockname},
68 {"settimeout", meth_settimeout}, 67 {"settimeout", meth_settimeout},
68 {"gettimeout", meth_gettimeout},
69 {NULL, NULL} 69 {NULL, NULL}
70}; 70};
71 71
@@ -86,6 +86,8 @@ static t_opt optset[] = {
86 {"ipv6-add-membership", opt_set_ip6_add_membership}, 86 {"ipv6-add-membership", opt_set_ip6_add_membership},
87 {"ipv6-drop-membership", opt_set_ip6_drop_membersip}, 87 {"ipv6-drop-membership", opt_set_ip6_drop_membersip},
88 {"ipv6-v6only", opt_set_ip6_v6only}, 88 {"ipv6-v6only", opt_set_ip6_v6only},
89 {"recv-buffer-size", opt_set_recv_buf_size},
90 {"send-buffer-size", opt_set_send_buf_size},
89 {NULL, NULL} 91 {NULL, NULL}
90}; 92};
91 93
@@ -102,6 +104,8 @@ static t_opt optget[] = {
102 {"ipv6-multicast-hops", opt_get_ip6_unicast_hops}, 104 {"ipv6-multicast-hops", opt_get_ip6_unicast_hops},
103 {"ipv6-multicast-loop", opt_get_ip6_multicast_loop}, 105 {"ipv6-multicast-loop", opt_get_ip6_multicast_loop},
104 {"ipv6-v6only", opt_get_ip6_v6only}, 106 {"ipv6-v6only", opt_get_ip6_v6only},
107 {"recv-buffer-size", opt_get_recv_buf_size},
108 {"send-buffer-size", opt_get_send_buf_size},
105 {NULL, NULL} 109 {NULL, NULL}
106}; 110};
107 111
@@ -116,8 +120,7 @@ static luaL_Reg func[] = {
116/*-------------------------------------------------------------------------*\ 120/*-------------------------------------------------------------------------*\
117* Initializes module 121* Initializes module
118\*-------------------------------------------------------------------------*/ 122\*-------------------------------------------------------------------------*/
119int udp_open(lua_State *L) 123int udp_open(lua_State *L) {
120{
121 /* create classes */ 124 /* create classes */
122 auxiliar_newclass(L, "udp{connected}", udp_methods); 125 auxiliar_newclass(L, "udp{connected}", udp_methods);
123 auxiliar_newclass(L, "udp{unconnected}", udp_methods); 126 auxiliar_newclass(L, "udp{unconnected}", udp_methods);
@@ -128,6 +131,10 @@ int udp_open(lua_State *L)
128 auxiliar_add2group(L, "udp{unconnected}", "select{able}"); 131 auxiliar_add2group(L, "udp{unconnected}", "select{able}");
129 /* define library functions */ 132 /* define library functions */
130 luaL_setfuncs(L, func, 0); 133 luaL_setfuncs(L, func, 0);
134 /* export default UDP size */
135 lua_pushliteral(L, "_DATAGRAMSIZE");
136 lua_pushinteger(L, UDP_DATAGRAMSIZE);
137 lua_rawset(L, -3);
131 return 0; 138 return 0;
132} 139}
133 140
@@ -177,13 +184,37 @@ static int meth_sendto(lua_State *L) {
177 memset(&aihint, 0, sizeof(aihint)); 184 memset(&aihint, 0, sizeof(aihint));
178 aihint.ai_family = udp->family; 185 aihint.ai_family = udp->family;
179 aihint.ai_socktype = SOCK_DGRAM; 186 aihint.ai_socktype = SOCK_DGRAM;
180 aihint.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV; 187 aihint.ai_flags = AI_NUMERICHOST;
188#ifdef AI_NUMERICSERV
189 aihint.ai_flags |= AI_NUMERICSERV;
190#endif
181 err = getaddrinfo(ip, port, &aihint, &ai); 191 err = getaddrinfo(ip, port, &aihint, &ai);
182 if (err) { 192 if (err) {
183 lua_pushnil(L); 193 lua_pushnil(L);
184 lua_pushstring(L, gai_strerror(err)); 194 lua_pushstring(L, LUA_GAI_STRERROR(err));
185 return 2; 195 return 2;
186 } 196 }
197
198 /* create socket if on first sendto if AF_UNSPEC was set */
199 if (udp->family == AF_UNSPEC && udp->sock == SOCKET_INVALID) {
200 struct addrinfo *ap;
201 const char *errstr = NULL;
202 for (ap = ai; ap != NULL; ap = ap->ai_next) {
203 errstr = inet_trycreate(&udp->sock, ap->ai_family, SOCK_DGRAM, 0);
204 if (errstr == NULL) {
205 socket_setnonblocking(&udp->sock);
206 udp->family = ap->ai_family;
207 break;
208 }
209 }
210 if (errstr != NULL) {
211 lua_pushnil(L);
212 lua_pushstring(L, errstr);
213 freeaddrinfo(ai);
214 return 2;
215 }
216 }
217
187 timeout_markstart(tm); 218 timeout_markstart(tm);
188 err = socket_sendto(&udp->sock, data, count, &sent, ai->ai_addr, 219 err = socket_sendto(&udp->sock, data, count, &sent, ai->ai_addr,
189 (socklen_t) ai->ai_addrlen, tm); 220 (socklen_t) ai->ai_addrlen, tm);
@@ -202,69 +233,78 @@ static int meth_sendto(lua_State *L) {
202\*-------------------------------------------------------------------------*/ 233\*-------------------------------------------------------------------------*/
203static int meth_receive(lua_State *L) { 234static int meth_receive(lua_State *L) {
204 p_udp udp = (p_udp) auxiliar_checkgroup(L, "udp{any}", 1); 235 p_udp udp = (p_udp) auxiliar_checkgroup(L, "udp{any}", 1);
205 char buffer[UDP_DATAGRAMSIZE]; 236 char buf[UDP_DATAGRAMSIZE];
206 size_t got, count = (size_t) luaL_optnumber(L, 2, sizeof(buffer)); 237 size_t got, wanted = (size_t) luaL_optnumber(L, 2, sizeof(buf));
238 char *dgram = wanted > sizeof(buf)? (char *) malloc(wanted): buf;
207 int err; 239 int err;
208 p_timeout tm = &udp->tm; 240 p_timeout tm = &udp->tm;
209 count = MIN(count, sizeof(buffer));
210 timeout_markstart(tm); 241 timeout_markstart(tm);
211 err = socket_recv(&udp->sock, buffer, count, &got, tm); 242 if (!dgram) {
243 lua_pushnil(L);
244 lua_pushliteral(L, "out of memory");
245 return 2;
246 }
247 err = socket_recv(&udp->sock, dgram, wanted, &got, tm);
212 /* Unlike TCP, recv() of zero is not closed, but a zero-length packet. */ 248 /* Unlike TCP, recv() of zero is not closed, but a zero-length packet. */
213 if (err == IO_CLOSED) 249 if (err != IO_DONE && err != IO_CLOSED) {
214 err = IO_DONE;
215 if (err != IO_DONE) {
216 lua_pushnil(L); 250 lua_pushnil(L);
217 lua_pushstring(L, udp_strerror(err)); 251 lua_pushstring(L, udp_strerror(err));
252 if (wanted > sizeof(buf)) free(dgram);
218 return 2; 253 return 2;
219 } 254 }
220 lua_pushlstring(L, buffer, got); 255 lua_pushlstring(L, dgram, got);
256 if (wanted > sizeof(buf)) free(dgram);
221 return 1; 257 return 1;
222} 258}
223 259
224/*-------------------------------------------------------------------------*\ 260/*-------------------------------------------------------------------------*\
225* Receives data and sender from a UDP socket 261* Receives data and sender from a UDP socket
226\*-------------------------------------------------------------------------*/ 262\*-------------------------------------------------------------------------*/
227static int meth_receivefrom(lua_State *L) 263static int meth_receivefrom(lua_State *L) {
228{
229 p_udp udp = (p_udp) auxiliar_checkclass(L, "udp{unconnected}", 1); 264 p_udp udp = (p_udp) auxiliar_checkclass(L, "udp{unconnected}", 1);
230 char buffer[UDP_DATAGRAMSIZE]; 265 char buf[UDP_DATAGRAMSIZE];
231 size_t got, count = (size_t) luaL_optnumber(L, 2, sizeof(buffer)); 266 size_t got, wanted = (size_t) luaL_optnumber(L, 2, sizeof(buf));
232 int err; 267 char *dgram = wanted > sizeof(buf)? (char *) malloc(wanted): buf;
233 p_timeout tm = &udp->tm;
234 struct sockaddr_storage addr; 268 struct sockaddr_storage addr;
235 socklen_t addr_len = sizeof(addr); 269 socklen_t addr_len = sizeof(addr);
236 char addrstr[INET6_ADDRSTRLEN]; 270 char addrstr[INET6_ADDRSTRLEN];
237 char portstr[6]; 271 char portstr[6];
272 int err;
273 p_timeout tm = &udp->tm;
238 timeout_markstart(tm); 274 timeout_markstart(tm);
239 count = MIN(count, sizeof(buffer)); 275 if (!dgram) {
240 err = socket_recvfrom(&udp->sock, buffer, count, &got, (SA *) &addr, 276 lua_pushnil(L);
277 lua_pushliteral(L, "out of memory");
278 return 2;
279 }
280 err = socket_recvfrom(&udp->sock, dgram, wanted, &got, (SA *) &addr,
241 &addr_len, tm); 281 &addr_len, tm);
242 /* Unlike TCP, recv() of zero is not closed, but a zero-length packet. */ 282 /* Unlike TCP, recv() of zero is not closed, but a zero-length packet. */
243 if (err == IO_CLOSED) 283 if (err != IO_DONE && err != IO_CLOSED) {
244 err = IO_DONE;
245 if (err != IO_DONE) {
246 lua_pushnil(L); 284 lua_pushnil(L);
247 lua_pushstring(L, udp_strerror(err)); 285 lua_pushstring(L, udp_strerror(err));
286 if (wanted > sizeof(buf)) free(dgram);
248 return 2; 287 return 2;
249 } 288 }
250 err = getnameinfo((struct sockaddr *)&addr, addr_len, addrstr, 289 err = getnameinfo((struct sockaddr *)&addr, addr_len, addrstr,
251 INET6_ADDRSTRLEN, portstr, 6, NI_NUMERICHOST | NI_NUMERICSERV); 290 INET6_ADDRSTRLEN, portstr, 6, NI_NUMERICHOST | NI_NUMERICSERV);
252 if (err) { 291 if (err) {
253 lua_pushnil(L); 292 lua_pushnil(L);
254 lua_pushstring(L, gai_strerror(err)); 293 lua_pushstring(L, LUA_GAI_STRERROR(err));
294 if (wanted > sizeof(buf)) free(dgram);
255 return 2; 295 return 2;
256 } 296 }
257 lua_pushlstring(L, buffer, got); 297 lua_pushlstring(L, dgram, got);
258 lua_pushstring(L, addrstr); 298 lua_pushstring(L, addrstr);
259 lua_pushinteger(L, (int) strtol(portstr, (char **) NULL, 10)); 299 lua_pushinteger(L, (int) strtol(portstr, (char **) NULL, 10));
300 if (wanted > sizeof(buf)) free(dgram);
260 return 3; 301 return 3;
261} 302}
262 303
263/*-------------------------------------------------------------------------*\ 304/*-------------------------------------------------------------------------*\
264* Returns family as string 305* Returns family as string
265\*-------------------------------------------------------------------------*/ 306\*-------------------------------------------------------------------------*/
266static int meth_getfamily(lua_State *L) 307static int meth_getfamily(lua_State *L) {
267{
268 p_udp udp = (p_udp) auxiliar_checkgroup(L, "udp{any}", 1); 308 p_udp udp = (p_udp) auxiliar_checkgroup(L, "udp{any}", 1);
269 if (udp->family == AF_INET6) { 309 if (udp->family == AF_INET6) {
270 lua_pushliteral(L, "inet6"); 310 lua_pushliteral(L, "inet6");
@@ -335,6 +375,11 @@ static int meth_settimeout(lua_State *L) {
335 return timeout_meth_settimeout(L, &udp->tm); 375 return timeout_meth_settimeout(L, &udp->tm);
336} 376}
337 377
378static int meth_gettimeout(lua_State *L) {
379 p_udp udp = (p_udp) auxiliar_checkgroup(L, "udp{any}", 1);
380 return timeout_meth_gettimeout(L, &udp->tm);
381}
382
338/*-------------------------------------------------------------------------*\ 383/*-------------------------------------------------------------------------*\
339* Turns a master udp object into a client object. 384* Turns a master udp object into a client object.
340\*-------------------------------------------------------------------------*/ 385\*-------------------------------------------------------------------------*/