From be67f63f4e11e53690bf1431a236f86b484c9bf0 Mon Sep 17 00:00:00 2001 From: Diego Nehab Date: Tue, 6 Oct 2015 11:33:50 +0800 Subject: Changed buffer-per-socket to buffer-per-operation. This is a difficult tradeoff to measure. I think large datagrams won't be used very frequently. So it is better to not lock a large buffer to each socket object and instead allocate and deallocate for each operation receiving a datagram larger than UDP_DATAGRAMSIZE. --- src/select.c | 5 ++++- src/udp.c | 58 +++++++++++++++++++++++++++------------------------------- src/udp.h | 2 -- 3 files changed, 31 insertions(+), 34 deletions(-) (limited to 'src') 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[] = { \*-------------------------------------------------------------------------*/ int select_open(lua_State *L) { lua_pushstring(L, "_SETSIZE"); - lua_pushnumber(L, FD_SETSIZE); + lua_pushinteger(L, FD_SETSIZE); + lua_rawset(L, -3); + lua_pushstring(L, "_SOCKETINVALID"); + lua_pushinteger(L, SOCKET_INVALID); lua_rawset(L, -3); luaL_setfuncs(L, func, 0); return 0; diff --git a/src/udp.c b/src/udp.c index 9c27b60..968dca8 100644 --- a/src/udp.c +++ b/src/udp.c @@ -41,7 +41,6 @@ static int meth_setpeername(lua_State *L); static int meth_close(lua_State *L); static int meth_setoption(lua_State *L); static int meth_getoption(lua_State *L); -static int meth_getbufferlength(lua_State *L); static int meth_settimeout(lua_State *L); static int meth_getfd(lua_State *L); static int meth_setfd(lua_State *L); @@ -64,7 +63,6 @@ static luaL_Reg udp_methods[] = { {"setfd", meth_setfd}, {"setoption", meth_setoption}, {"getoption", meth_getoption}, - {"getoption", meth_getbufferlength}, {"setpeername", meth_setpeername}, {"setsockname", meth_setsockname}, {"settimeout", meth_settimeout}, @@ -118,8 +116,7 @@ static luaL_Reg func[] = { /*-------------------------------------------------------------------------*\ * Initializes module \*-------------------------------------------------------------------------*/ -int udp_open(lua_State *L) -{ +int udp_open(lua_State *L) { /* create classes */ auxiliar_newclass(L, "udp{connected}", udp_methods); auxiliar_newclass(L, "udp{unconnected}", udp_methods); @@ -130,6 +127,10 @@ int udp_open(lua_State *L) auxiliar_add2group(L, "udp{unconnected}", "select{able}"); /* define library functions */ luaL_setfuncs(L, func, 0); + /* export default UDP size */ + lua_pushliteral(L, "_DATAGRAMSIZE"); + lua_pushinteger(L, UDP_DATAGRAMSIZE); + lua_rawset(L, -3); return 0; } @@ -205,30 +206,26 @@ static int meth_sendto(lua_State *L) { static int meth_receive(lua_State *L) { p_udp udp = (p_udp) auxiliar_checkgroup(L, "udp{any}", 1); char buf[UDP_DATAGRAMSIZE]; - size_t len = MAX(udp->len, UDP_DATAGRAMSIZE); - char *dgram = len > sizeof(buf)? udp->buf: buf; - size_t got, wanted = (size_t) luaL_optnumber(L, 2, len); + size_t got, wanted = (size_t) luaL_optnumber(L, 2, sizeof(buf)); + char *dgram = wanted > sizeof(buf)? (char *) malloc(wanted): buf; int err; p_timeout tm = &udp->tm; timeout_markstart(tm); - wanted = MIN(wanted, len); + if (!dgram) { + lua_pushnil(L); + lua_pushliteral(L, "out of memory"); + return 2; + } err = socket_recv(&udp->sock, dgram, wanted, &got, tm); /* Unlike TCP, recv() of zero is not closed, but a zero-length packet. */ - if (err != IO_DONE && err != IO_CLOSED ) { + if (err != IO_DONE && err != IO_CLOSED) { lua_pushnil(L); lua_pushstring(L, udp_strerror(err)); + if (wanted > sizeof(buf)) free(dgram); return 2; } lua_pushlstring(L, dgram, got); - return 1; -} - -/*-------------------------------------------------------------------------*\ -* Receives data from a UDP socket -\*-------------------------------------------------------------------------*/ -static int meth_getbufferlength(lua_State *L) { - p_udp udp = (p_udp) auxiliar_checkgroup(L, "udp{any}", 1); - lua_pushinteger(L, MAX(UDP_DATAGRAMSIZE, udp->len)); + if (wanted > sizeof(buf)) free(dgram); return 1; } @@ -238,9 +235,8 @@ static int meth_getbufferlength(lua_State *L) { static int meth_receivefrom(lua_State *L) { p_udp udp = (p_udp) auxiliar_checkclass(L, "udp{unconnected}", 1); char buf[UDP_DATAGRAMSIZE]; - size_t len = MAX(udp->len, UDP_DATAGRAMSIZE); - char *dgram = len > sizeof(buf)? udp->buf: buf; - size_t got, wanted = (size_t) luaL_optnumber(L, 2, len); + size_t got, wanted = (size_t) luaL_optnumber(L, 2, sizeof(buf)); + char *dgram = wanted > sizeof(buf)? (char *) malloc(wanted): buf; struct sockaddr_storage addr; socklen_t addr_len = sizeof(addr); char addrstr[INET6_ADDRSTRLEN]; @@ -248,13 +244,18 @@ static int meth_receivefrom(lua_State *L) { int err; p_timeout tm = &udp->tm; timeout_markstart(tm); - wanted = MIN(wanted, len); + if (!dgram) { + lua_pushnil(L); + lua_pushliteral(L, "out of memory"); + return 2; + } err = socket_recvfrom(&udp->sock, dgram, wanted, &got, (SA *) &addr, &addr_len, tm); /* Unlike TCP, recv() of zero is not closed, but a zero-length packet. */ if (err != IO_DONE && err != IO_CLOSED) { lua_pushnil(L); lua_pushstring(L, udp_strerror(err)); + if (wanted > sizeof(buf)) free(dgram); return 2; } err = getnameinfo((struct sockaddr *)&addr, addr_len, addrstr, @@ -262,19 +263,20 @@ static int meth_receivefrom(lua_State *L) { if (err) { lua_pushnil(L); lua_pushstring(L, gai_strerror(err)); + if (wanted > sizeof(buf)) free(dgram); return 2; } lua_pushlstring(L, dgram, got); lua_pushstring(L, addrstr); lua_pushinteger(L, (int) strtol(portstr, (char **) NULL, 10)); + if (wanted > sizeof(buf)) free(dgram); return 3; } /*-------------------------------------------------------------------------*\ * Returns family as string \*-------------------------------------------------------------------------*/ -static int meth_getfamily(lua_State *L) -{ +static int meth_getfamily(lua_State *L) { p_udp udp = (p_udp) auxiliar_checkgroup(L, "udp{any}", 1); if (udp->family == AF_INET6) { lua_pushliteral(L, "inet6"); @@ -419,19 +421,13 @@ static int meth_setsockname(lua_State *L) { * Creates a master udp object \*-------------------------------------------------------------------------*/ static int udp_create(lua_State *L, int family) { - p_udp udp = NULL; - /* optional length for private datagram buffer. this is useful when - * you need larger datagrams than UDP_DATAGRAMSIZE */ - size_t len = (size_t) luaL_optinteger(L, 1, 0); - if (len <= UDP_DATAGRAMSIZE) len = 0; /* allocate udp object */ - udp = (p_udp) lua_newuserdata(L, sizeof(t_udp) + len - 1); + p_udp udp = (p_udp) lua_newuserdata(L, sizeof(t_udp)); auxiliar_setclass(L, "udp{unconnected}", -1); /* if family is AF_UNSPEC, we leave the socket invalid and * store AF_UNSPEC into family. This will allow it to later be * replaced with an AF_INET6 or AF_INET socket upon first use. */ udp->sock = SOCKET_INVALID; - udp->len = len; timeout_init(&udp->tm, -1, -1); udp->family = family; if (family != AF_UNSPEC) { diff --git a/src/udp.h b/src/udp.h index da27a7a..be9b6a5 100644 --- a/src/udp.h +++ b/src/udp.h @@ -23,8 +23,6 @@ typedef struct t_udp_ { t_socket sock; t_timeout tm; int family; - size_t len; /* length of datagram buffer below */ - char buf[1]; /* allocate larger structure to hold actual buffer */ } t_udp; typedef t_udp *p_udp; -- cgit v1.2.3-55-g6feb