/*-------------------------------------------------------------------------*\ * Receives data and sender from a UDP socket \*-------------------------------------------------------------------------*/ static int meth_receivefrom(lua_State *L) { p_udp udp = (p_udp) auxiliar_checkclass(L, "udp{unconnected}", 1); char buffer[UDP_DATAGRAMSIZE]; size_t got, count = (size_t) luaL_optnumber(L, 2, sizeof(buffer)); int err; p_timeout tm = &udp->tm; struct sockaddr_storage addr; socklen_t addr_len = sizeof(addr); char addrstr[INET6_ADDRSTRLEN]; char portstr[6]; timeout_markstart(tm); count = MIN(count, sizeof(buffer)); err = socket_recvfrom(&udp->sock, buffer, count, &got, (SA *) &addr, &addr_len, tm); /* Unlike TCP, recv() of zero is not closed, but a zero-length packet. */ if (err == IO_CLOSED) err = IO_DONE; if (err != IO_DONE) { lua_pushnil(L); lua_pushstring(L, udp_strerror(err)); return 2; } err = getnameinfo((struct sockaddr *)&addr, addr_len, addrstr, INET6_ADDRSTRLEN, portstr, 6, NI_NUMERICHOST | NI_NUMERICSERV); if (err) { lua_pushnil(L); lua_pushstring(L, gai_strerror(err)); return 2; } lua_pushlstring(L, buffer, got); lua_pushstring(L, addrstr); lua_pushinteger(L, (int) strtol(portstr, (char **) NULL, 10)); return 3; }
/*-------------------------------------------------------------------------*\ * Send data through unconnected udp socket \*-------------------------------------------------------------------------*/ static int meth_sendto(lua_State *L) { p_udp udp = (p_udp) auxiliar_checkclass(L, "udp{unconnected}", 1); size_t count, sent = 0; const char *data = luaL_checklstring(L, 2, &count); const char *ip = luaL_checkstring(L, 3); unsigned short port = (unsigned short) luaL_checknumber(L, 4); p_timeout tm = &udp->tm; struct sockaddr_in addr; int err; memset(&addr, 0, sizeof(addr)); if (!inet_aton(ip, &addr.sin_addr)) luaL_argerror(L, 3, "invalid ip address"); addr.sin_family = AF_INET; addr.sin_port = htons(port); timeout_markstart(tm); err = socket_sendto(&udp->sock, data, count, &sent, (SA *) &addr, sizeof(addr), tm); if (err != IO_DONE) { lua_pushnil(L); lua_pushstring(L, udp_strerror(err)); return 2; } lua_pushnumber(L, sent); return 1; }
/*-------------------------------------------------------------------------*\ * Send data through unconnected udp socket \*-------------------------------------------------------------------------*/ static int meth_sendto(lua_State *L) { p_udp udp = (p_udp) auxiliar_checkclass(L, "udp{unconnected}", 1); size_t count, sent = 0; const char *data = luaL_checklstring(L, 2, &count); const char *ip = luaL_checkstring(L, 3); const char *port = luaL_checkstring(L, 4); p_timeout tm = &udp->tm; int err; struct addrinfo aihint; struct addrinfo *ai; memset(&aihint, 0, sizeof(aihint)); aihint.ai_family = udp->family; aihint.ai_socktype = SOCK_DGRAM; aihint.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV; err = getaddrinfo(ip, port, &aihint, &ai); if (err) { lua_pushnil(L); lua_pushstring(L, gai_strerror(err)); return 2; } timeout_markstart(tm); err = socket_sendto(&udp->sock, data, count, &sent, ai->ai_addr, (socklen_t) ai->ai_addrlen, tm); freeaddrinfo(ai); if (err != IO_DONE) { lua_pushnil(L); lua_pushstring(L, udp_strerror(err)); return 2; } lua_pushnumber(L, (lua_Number) sent); return 1; }
/*-------------------------------------------------------------------------*\ * Receives data from a UDP socket \*-------------------------------------------------------------------------*/ static int meth_receive(lua_State *L) { p_udp udp = (p_udp) auxiliar_checkgroup(L, "udp{any}", 1); char buf[UDP_DATAGRAMSIZE]; 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); 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) { lua_pushnil(L); lua_pushstring(L, udp_strerror(err)); if (wanted > sizeof(buf)) free(dgram); return 2; } lua_pushlstring(L, dgram, got); if (wanted > sizeof(buf)) free(dgram); return 1; }
/*-------------------------------------------------------------------------*\ * Send data through unconnected udp socket \*-------------------------------------------------------------------------*/ static int meth_sendto(lua_State *L) { p_udp udp = (p_udp) auxiliar_checkclass(L, "udp{unconnected}", 1); size_t count, sent = 0; const char *data = luaL_checklstring(L, 2, &count); const char *ip = luaL_checkstring(L, 3); const char *port = luaL_checkstring(L, 4); p_timeout tm = &udp->tm; int err; struct addrinfo aihint; struct addrinfo *ai; memset(&aihint, 0, sizeof(aihint)); aihint.ai_family = udp->family; aihint.ai_socktype = SOCK_DGRAM; aihint.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV; err = getaddrinfo(ip, port, &aihint, &ai); if (err) { lua_pushnil(L); lua_pushstring(L, gai_strerror(err)); return 2; } /* create socket if on first sendto if AF_UNSPEC was set */ if (udp->family == AF_UNSPEC && udp->sock == SOCKET_INVALID) { struct addrinfo *ap; const char *errstr = NULL; for (ap = ai; ap != NULL; ap = ap->ai_next) { errstr = inet_trycreate(&udp->sock, ap->ai_family, SOCK_DGRAM, 0); if (errstr == NULL) { socket_setnonblocking(&udp->sock); udp->family = ap->ai_family; break; } } if (errstr != NULL) { lua_pushnil(L); lua_pushstring(L, errstr); freeaddrinfo(ai); return 2; } } timeout_markstart(tm); err = socket_sendto(&udp->sock, data, count, &sent, ai->ai_addr, (socklen_t) ai->ai_addrlen, tm); freeaddrinfo(ai); if (err != IO_DONE) { lua_pushnil(L); lua_pushstring(L, udp_strerror(err)); return 2; } lua_pushnumber(L, (lua_Number) sent); return 1; }
/*-------------------------------------------------------------------------*\ * Send data through connected udp socket \*-------------------------------------------------------------------------*/ static int meth_send(lua_State *L) { p_udp udp = (p_udp) auxiliar_checkclass(L, "udp{connected}", 1); p_timeout tm = &udp->tm; size_t count, sent = 0; int err; const char *data = luaL_checklstring(L, 2, &count); timeout_markstart(tm); err = socket_send(&udp->sock, data, count, &sent, tm); if (err != IO_DONE) { lua_pushnil(L); lua_pushstring(L, udp_strerror(err)); return 2; } lua_pushnumber(L, (lua_Number) sent); return 1; }
/*-------------------------------------------------------------------------*\ * Receives data from a UDP socket \*-------------------------------------------------------------------------*/ static int meth_receive(lua_State *L) { p_udp udp = (p_udp) auxiliar_checkgroup(L, "udp{any}", 1); char buffer[UDP_DATAGRAMSIZE]; size_t got, count = (size_t) luaL_optnumber(L, 2, sizeof(buffer)); int err; p_timeout tm = &udp->tm; count = MIN(count, sizeof(buffer)); timeout_markstart(tm); err = socket_recv(&udp->sock, buffer, count, &got, tm); if (err != IO_DONE) { lua_pushnil(L); lua_pushstring(L, udp_strerror(err)); return 2; } lua_pushlstring(L, buffer, got); return 1; }
/*-------------------------------------------------------------------------*\ * Receives data and sender from a UDP socket \*-------------------------------------------------------------------------*/ static int meth_receivefrom(lua_State *L) { p_udp udp = (p_udp) auxiliar_checkclass(L, "udp{unconnected}", 1); struct sockaddr_in addr; socklen_t addr_len = sizeof(addr); char buffer[UDP_DATAGRAMSIZE]; size_t got, count = (size_t) luaL_optnumber(L, 2, sizeof(buffer)); int err; p_timeout tm = &udp->tm; timeout_markstart(tm); count = MIN(count, sizeof(buffer)); err = socket_recvfrom(&udp->sock, buffer, count, &got, (SA *) &addr, &addr_len, tm); if (err == IO_DONE) { lua_pushlstring(L, buffer, got); lua_pushstring(L, inet_ntoa(addr.sin_addr)); lua_pushnumber(L, ntohs(addr.sin_port)); return 3; } else { lua_pushnil(L); lua_pushstring(L, udp_strerror(err)); return 2; } }