static int luv_udp_send(lua_State* L) { uv_udp_t* handle = luv_check_udp(L, 1); uv_udp_send_t* req; uv_buf_t buf; int ret, port, ref; const char* host; struct sockaddr_storage addr; luv_check_buf(L, 2, &buf); host = luaL_checkstring(L, 3); port = luaL_checkinteger(L, 4); if (uv_ip4_addr(host, port, (struct sockaddr_in*)&addr) && uv_ip6_addr(host, port, (struct sockaddr_in6*)&addr)) { return luaL_error(L, "Invalid IP address or port [%s:%d]", host, port); } ref = luv_check_continuation(L, 5); req = (uv_udp_send_t*)lua_newuserdata(L, sizeof(*req)); req->data = luv_setup_req(L, ref); ret = uv_udp_send(req, handle, &buf, 1, (struct sockaddr*)&addr, luv_udp_send_cb); if (ret < 0) { luv_cleanup_req(L, (luv_req_t*)req->data); lua_pop(L, 1); return luv_error(L, ret); } return 1; }
static int luv_fs_scandir_next(lua_State* L) { uv_fs_t* req = luv_check_fs(L, 1); uv_dirent_t ent; int ret = uv_fs_scandir_next(req, &ent); const char* type; if (ret == UV_EOF) { luv_cleanup_req(L, req->data); req->data = NULL; uv_fs_req_cleanup(req); return 0; } if (ret < 0) return luv_error(L, ret); lua_createtable(L, 0, 2); lua_pushstring(L, ent.name); lua_setfield(L, -2, "name"); switch (ent.type) { case UV_DIRENT_UNKNOWN: type = NULL; break; case UV_DIRENT_FILE: type = "file"; break; case UV_DIRENT_DIR: type = "directory"; break; case UV_DIRENT_LINK: type = "link"; break; case UV_DIRENT_FIFO: type = "fifo"; break; case UV_DIRENT_SOCKET: type = "socket"; break; case UV_DIRENT_CHAR: type = "char"; break; case UV_DIRENT_BLOCK: type = "block"; break; } if (type) { lua_pushstring(L, type); lua_setfield(L, -2, "type"); } return 1; }
static void luv_udp_send_cb(uv_udp_send_t* req, int status) { lua_State* L = luv_state(req->handle->loop); luv_status(L, status); luv_fulfill_req(L, (luv_req_t*)req->data, 1); luv_cleanup_req(L, (luv_req_t*)req->data); req->data = NULL; }
static void luv_connect_cb(uv_connect_t* req, int status) { lua_State* L = luv_state(req->handle->loop); luv_status(L, status); luv_fulfill_req(L, req->data, 1); luv_cleanup_req(L, req->data); req->data = NULL; }
// Metamethod to allow storing anything in the userdata's environment static int luv_cancel(lua_State* L) { uv_req_t* req = (uv_req_t*)luv_check_req(L, 1); int ret = uv_cancel(req); if (ret < 0) return luv_error(L, ret); luv_cleanup_req(L, (luv_req_t*)req->data); req->data = NULL; lua_pushinteger(L, ret); return 1; }
static void luv_getaddrinfo_cb(uv_getaddrinfo_t* req, int status, struct addrinfo* res) { lua_State* L = luv_state(req->loop); int nargs; if (status < 0) { luv_status(L, status); nargs = 1; } else { lua_pushnil(L); luv_pushaddrinfo(L, res); nargs = 2; } luv_fulfill_req(L, (luv_req_t*)req->data, nargs); luv_cleanup_req(L, (luv_req_t*)req->data); req->data = NULL; if (res) uv_freeaddrinfo(res); }
static void luv_getnameinfo_cb(uv_getnameinfo_t* req, int status, const char* hostname, const char* service) { lua_State* L = luv_state(req->loop); int nargs; if (status < 0) { luv_status(L, status); nargs = 1; } else { lua_pushnil(L); lua_pushstring(L, hostname); lua_pushstring(L, service); nargs = 3; } luv_fulfill_req(L, (luv_req_t*)req->data, nargs); luv_cleanup_req(L, (luv_req_t*)req->data); req->data = NULL; }
static void luv_fs_cb(uv_fs_t* req) { lua_State* L = luv_state(req->loop); int nargs = push_fs_result(L, req); if (nargs == 2 && lua_isnil(L, -nargs)) { // If it was an error, convert to (err, value) format. lua_remove(L, -nargs); nargs--; } else { // Otherwise insert a nil in front to convert to (err, value) format. lua_pushnil(L); lua_insert(L, -nargs - 1); nargs++; } luv_fulfill_req(L, req->data, nargs); if (req->fs_type != UV_FS_SCANDIR) { luv_cleanup_req(L, req->data); req->data = NULL; uv_fs_req_cleanup(req); } }
static int luv_getaddrinfo(lua_State* L) { uv_getaddrinfo_t* req; const char* node; const char* service; struct addrinfo hints_s; struct addrinfo* hints = &hints_s; int ret, ref; if (lua_isnoneornil(L, 1)) node = NULL; else node = luaL_checkstring(L, 1); if (lua_isnoneornil(L, 2)) service = NULL; else service = luaL_checkstring(L, 2); if (!lua_isnoneornil(L, 3)) luaL_checktype(L, 3, LUA_TTABLE); else hints = NULL; if (hints) { // Initialize the hints memset(hints, 0, sizeof(*hints)); // Process the `family` hint. lua_getfield(L, 3, "family"); if (lua_isnumber(L, -1)) { hints->ai_family = lua_tointeger(L, -1); } else if (lua_isstring(L, -1)) { hints->ai_family = luv_af_string_to_num(lua_tostring(L, -1)); } else if (lua_isnil(L, -1)) { hints->ai_family = AF_UNSPEC; } else { luaL_argerror(L, 3, "family hint must be string if set"); } lua_pop(L, 1); // Process `socktype` hint lua_getfield(L, 3, "socktype"); if (lua_isnumber(L, -1)) { hints->ai_socktype = lua_tointeger(L, -1); } else if (lua_isstring(L, -1)) { hints->ai_socktype = luv_sock_string_to_num(lua_tostring(L, -1)); } else if (!lua_isnil(L, -1)) { return luaL_argerror(L, 3, "socktype hint must be string if set"); } lua_pop(L, 1); // Process the `protocol` hint lua_getfield(L, 3, "protocol"); if (lua_isnumber(L, -1)) { hints->ai_protocol = lua_tointeger(L, -1); } else if (lua_isstring(L, -1)) { int protocol = luv_af_string_to_num(lua_tostring(L, -1)); if (protocol) { hints->ai_protocol = protocol; } else { return luaL_argerror(L, 3, "Invalid protocol hint"); } } else if (!lua_isnil(L, -1)) { return luaL_argerror(L, 3, "protocol hint must be string if set"); } lua_pop(L, 1); lua_getfield(L, 3, "addrconfig"); if (lua_toboolean(L, -1)) hints->ai_flags |= AI_ADDRCONFIG; lua_pop(L, 1); #ifdef AI_V4MAPPED lua_getfield(L, 3, "v4mapped"); if (lua_toboolean(L, -1)) hints->ai_flags |= AI_V4MAPPED; lua_pop(L, 1); #endif #ifdef AI_ALL lua_getfield(L, 3, "all"); if (lua_toboolean(L, -1)) hints->ai_flags |= AI_ALL; lua_pop(L, 1); #endif lua_getfield(L, 3, "numerichost"); if (lua_toboolean(L, -1)) hints->ai_flags |= AI_NUMERICHOST; lua_pop(L, 1); lua_getfield(L, 3, "passive"); if (lua_toboolean(L, -1)) hints->ai_flags |= AI_PASSIVE; lua_pop(L, 1); lua_getfield(L, 3, "numericserv"); if (lua_toboolean(L, -1)) { hints->ai_flags |= AI_NUMERICSERV; /* On OS X upto at least OSX 10.9, getaddrinfo crashes * if AI_NUMERICSERV is set and the servname is NULL or "0". * This workaround avoids a segfault in libsystem. */ if (NULL == service) service = "00"; } lua_pop(L, 1); lua_getfield(L, 3, "canonname"); if (lua_toboolean(L, -1)) hints->ai_flags |= AI_CANONNAME; lua_pop(L, 1); } ref = luv_check_continuation(L, 4); req = (uv_getaddrinfo_t*)lua_newuserdata(L, sizeof(*req)); req->data = luv_setup_req(L, ref); ret = uv_getaddrinfo(luv_loop(L), req, ref == LUA_NOREF ? NULL : luv_getaddrinfo_cb, node, service, hints); if (ret < 0) { luv_cleanup_req(L, (luv_req_t*)req->data); lua_pop(L, 1); return luv_error(L, ret); } if (ref == LUA_NOREF) { lua_pop(L, 1); luv_pushaddrinfo(L, req->addrinfo); uv_freeaddrinfo(req->addrinfo); luv_cleanup_req(L, (luv_req_t*)req->data); } return 1; }
static int luv_getnameinfo(lua_State* L) { uv_getnameinfo_t* req; struct sockaddr_storage addr; const char* ip = NULL; int flags = 0; int ret, ref, port = 0; luaL_checktype(L, 1, LUA_TTABLE); memset(&addr, 0, sizeof(addr)); lua_getfield(L, 1, "ip"); if (lua_isstring(L, -1)) { ip = lua_tostring(L, -1); } else if (!lua_isnil(L, -1)) { luaL_argerror(L, 1, "ip property must be string if set"); } lua_pop(L, 1); lua_getfield(L, 1, "port"); if (lua_isnumber(L, -1)) { port = lua_tointeger(L, -1); } else if (!lua_isnil(L, -1)) { luaL_argerror(L, 1, "port property must be integer if set"); } lua_pop(L, 1); if (ip || port) { if (!ip) ip = "0.0.0.0"; if (!uv_ip4_addr(ip, port, (struct sockaddr_in*)&addr)) { addr.ss_family = AF_INET; } else if (!uv_ip6_addr(ip, port, (struct sockaddr_in6*)&addr)) { addr.ss_family = AF_INET6; } else { return luaL_argerror(L, 1, "Invalid ip address or port"); } } lua_getfield(L, 1, "family"); if (lua_isnumber(L, -1)) { addr.ss_family = lua_tointeger(L, -1); } else if (lua_isstring(L, -1)) { addr.ss_family = luv_af_string_to_num(lua_tostring(L, -1)); } else if (!lua_isnil(L, -1)) { luaL_argerror(L, 1, "family must be string if set"); } lua_pop(L, 1); ref = luv_check_continuation(L, 2); req = (uv_getnameinfo_t*)lua_newuserdata(L, sizeof(*req)); req->data = luv_setup_req(L, ref); ret = uv_getnameinfo(luv_loop(L), req, ref == LUA_NOREF ? NULL : luv_getnameinfo_cb, (struct sockaddr*)&addr, flags); if (ret < 0) { luv_cleanup_req(L, (luv_req_t*)req->data); lua_pop(L, 1); return luv_error(L, ret); } if (ref == LUA_NOREF) { lua_pop(L, 1); lua_pushstring(L, req->host); lua_pushstring(L, req->service); luv_cleanup_req(L, (luv_req_t*)req->data); return 2; } return 1; }