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.
This commit is contained in:
parent
fd729b32a8
commit
be67f63f4e
7 changed files with 64 additions and 62 deletions
58
src/udp.c
58
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) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue