int luv_set_handler(lua_State* L) { int before = lua_gettop(L); luv_checkudata(L, 1, "handle"); const char* name = luaL_checkstring(L, 2); luaL_checktype(L, 3, LUA_TFUNCTION); luv_register_event(L, 1, name, 3); assert(lua_gettop(L) == before); return 0; }
int luv_close (lua_State* L) { uv_handle_t* handle = luv_checkudata(L, 1, "handle"); /* printf("close \tlhandle=%p handle=%p\n", handle->data, handle);*/ if (uv_is_closing(handle)) { fprintf(stderr, "WARNING: Handle already closing \tlhandle=%p handle=%p\n", handle->data, handle); return 0; } uv_close(handle, luv_on_close); luv_handle_ref(L, handle->data, 1); return 0; }
int luv_timer_stop(lua_State* L) { uv_timer_t* handle = (uv_timer_t*)luv_checkudata(L, 1, "timer"); int err = uv_timer_stop(handle); if (err < 0) { return luaL_error(L, "timer_stop: %s", uv_strerror(err)); } luv_handle_unref(L, handle->data); return 0; }
// Kills the process with the specified signal. The user must still call close // on the process. int luv_process_kill(lua_State* L) { uv_process_t* handle = (uv_process_t*)luv_checkudata(L, 1, "process"); int signum = luaL_checkint(L, 2); if (uv_process_kill(handle, signum)) { uv_err_t err = uv_last_error(luv_get_loop(L)); return luaL_error(L, "process_kill: %s", uv_strerror(err)); } return 0; }
int luv_tcp_keepalive (lua_State* L) { uv_tcp_t* handle = (uv_tcp_t*)luv_checkudata(L, 1, "tcp"); int enable = lua_toboolean(L, 2); int delay = lua_tointeger(L, 3); if (uv_tcp_keepalive(handle, enable, delay)) { uv_err_t err = uv_last_error(luv_get_loop(L)); return luaL_error(L, "tcp_keepalive: %s", uv_strerror(err)); } return 0; }
int luv_tty_set_mode(lua_State* L) { int before = lua_gettop(L); uv_tty_t* handle = (uv_tty_t*)luv_checkudata(L, 1, "tty"); int mode = luaL_checkint(L, 2); if (uv_tty_set_mode(handle, mode)) { uv_err_t err = uv_last_error(uv_default_loop()); return luaL_error(L, "tcp_set_mode: %s", uv_strerror(err)); } assert(lua_gettop(L) == before); return 0; }
/* const char* interface_addr, uv_membership membership);*/ int luv_udp_set_membership(lua_State* L) { uv_udp_t* handle = (uv_udp_t*)luv_checkudata(L, 1, "udp"); const char* multicast_addr = luaL_checkstring(L, 2); const char* interface_addr = luaL_checkstring(L, 3); int option = luaL_checkoption (L, 4, "membership", luv_membership_options); uv_membership membership = option ? UV_LEAVE_GROUP : UV_JOIN_GROUP; if (uv_udp_set_membership(handle, multicast_addr, interface_addr, membership)) { uv_err_t err = uv_last_error(luv_get_loop(L)); return luaL_error(L, "udp_set_membership: %s", uv_strerror(err)); } return 0; }
int luv_tcp_bind6(lua_State* L) { uv_tcp_t* handle = (uv_tcp_t*)luv_checkudata(L, 1, "tcp"); const char* host = luaL_checkstring(L, 2); int port = luaL_checkint(L, 3); struct sockaddr_in6 address = uv_ip6_addr(host, port); if (uv_tcp_bind6(handle, address)) { uv_err_t err = uv_last_error(luv_get_loop(L)); return luaL_error(L, "tcp_bind6: %s", uv_strerror(err)); } return 0; }
static int luv_udp__send(lua_State* L, int family) { uv_buf_t buf; uv_udp_t* handle = (uv_udp_t*)luv_checkudata(L, 1, "udp"); size_t len; const char* chunk = luaL_checklstring(L, 2, &len); luv_udp_ref_t *ref; uv_udp_send_t* req = (uv_udp_send_t*)malloc(sizeof(uv_udp_send_t)); int port = luaL_checkint(L, 3); const char* host = luaL_checkstring(L, 4); struct sockaddr_in dest; struct sockaddr_in6 dest6; int rc; /* Store a reference to the callback */ lua_pushvalue(L, 5); ref = malloc(sizeof(*ref)); ref->ref = luaL_ref(L, LUA_REGISTRYINDEX); req->data = ref; luv_handle_ref(L, handle->data, 1); /* Store the chunk * TODO: this is probably unsafe, should investigate */ buf = uv_buf_init((char*)chunk, len); switch(family) { case AF_INET: dest = uv_ip4_addr(host, port); rc = uv_udp_send(req, handle, &buf, 1, dest, luv_on_udp_send); break; case AF_INET6: dest6 = uv_ip6_addr(host, port); rc = uv_udp_send6(req, handle, &buf, 1, dest6, luv_on_udp_send); break; default: assert(0 && "unexpected family type"); abort(); } if (rc) { uv_err_t err = uv_last_error(luv_get_loop(L)); return luaL_error(L, "udp_send: %s", uv_strerror(err)); } return 0; }
int luv_tcp_bind (lua_State* L) { int before = lua_gettop(L); uv_tcp_t* handle = (uv_tcp_t*)luv_checkudata(L, 1, "tcp"); const char* host = luaL_checkstring(L, 2); int port = luaL_checkint(L, 3); struct sockaddr_in address = uv_ip4_addr(host, port); if (uv_tcp_bind(handle, address)) { uv_err_t err = uv_last_error(luv_get_loop(L)); return luaL_error(L, "tcp_bind: %s", uv_strerror(err)); } assert(lua_gettop(L) == before); return 0; }
int luv_timer_start(lua_State* L) { uv_timer_t* handle = (uv_timer_t*)luv_checkudata(L, 1, "timer"); int64_t timeout = luaL_checklong(L, 2); int64_t repeat = luaL_checklong(L, 3); luaL_checktype(L, 4, LUA_TFUNCTION); luv_register_event(L, 1, "timeout", 4); int err = uv_timer_start(handle, luv_on_timer, timeout, repeat); if (err < 0) { return luaL_error(L, "timer_start: %s", uv_strerror(err)); } luv_handle_ref(L, handle->data, 1); return 0; }
int luv_tty_get_winsize(lua_State* L) { int before = lua_gettop(L); uv_tty_t* handle = (uv_tty_t*)luv_checkudata(L, 1, "tty"); int width, height; if (uv_tty_get_winsize(handle, &width, &height)) { uv_err_t err = uv_last_error(uv_default_loop()); return luaL_error(L, "tcp_get_winsize: %s", uv_strerror(err)); } lua_pushinteger(L, width); lua_pushinteger(L, height); assert(lua_gettop(L) == before + 2); return 2; }
int luv_tcp_connect6(lua_State* L) { uv_tcp_t* handle = (uv_tcp_t*)luv_checkudata(L, 1, "tcp"); const char* ip_address = luaL_checkstring(L, 2); int port = luaL_checkint(L, 3); struct sockaddr_in6 address = uv_ip6_addr(ip_address, port); uv_connect_t* req = (uv_connect_t*)malloc(sizeof(uv_connect_t)); if (uv_tcp_connect6(req, handle, address, luv_after_connect)) { uv_err_t err = uv_last_error(luv_get_loop(L)); return luaL_error(L, "tcp_connect6: %s", uv_strerror(err)); } luv_handle_ref(L, handle->data, 1); return 0; }
int luv_tcp_getpeername(lua_State* L) { int before = lua_gettop(L); uv_tcp_t* handle = (uv_tcp_t*)luv_checkudata(L, 1, "tcp"); int port = 0; char ip[INET6_ADDRSTRLEN]; int family; struct sockaddr_storage address; int addrlen = sizeof(address); if (uv_tcp_getpeername(handle, (struct sockaddr*)(&address), &addrlen)) { uv_err_t err = uv_last_error(luv_get_loop(L)); return luaL_error(L, "tcp_getpeername: %s", uv_strerror(err)); } family = address.ss_family; if (family == AF_INET) { struct sockaddr_in* addrin = (struct sockaddr_in*)&address; uv_inet_ntop(AF_INET, &(addrin->sin_addr), ip, INET6_ADDRSTRLEN); port = ntohs(addrin->sin_port); } else if (family == AF_INET6) { struct sockaddr_in6* addrin6 = (struct sockaddr_in6*)&address; uv_inet_ntop(AF_INET6, &(addrin6->sin6_addr), ip, INET6_ADDRSTRLEN); port = ntohs(addrin6->sin6_port); } lua_newtable(L); lua_pushnumber(L, port); lua_setfield(L, -2, "port"); lua_pushnumber(L, family); lua_setfield(L, -2, "family"); lua_pushstring(L, ip); lua_setfield(L, -2, "address"); assert(lua_gettop(L) == before + 1); return 1; }
static uv_idle_t* luv_check_idle(lua_State* L, int index) { uv_idle_t* handle = (uv_idle_t*)luv_checkudata(L, index, "uv_idle"); luaL_argcheck(L, handle->type == UV_IDLE && handle->data, index, "Expected uv_idle_t"); return handle; }
static uv_poll_t* luv_check_poll(lua_State* L, int index) { uv_poll_t* handle = (uv_poll_t*)luv_checkudata(L, index, "uv_poll"); luaL_argcheck(L, handle->type == UV_POLL && handle->data, index, "Expected uv_poll_t"); return handle; }
static uv_process_t* luv_check_process(lua_State* L, int index) { uv_process_t* handle = luv_checkudata(L, index, "uv_process"); luaL_argcheck(L, handle->type == UV_PROCESS && handle->data, index, "Expected uv_process_t"); return handle; }
// Initializes uv_process_t and starts the process. int luv_spawn(lua_State* L) { int before = lua_gettop(L); uv_pipe_t* stdin_stream = (uv_pipe_t*)luv_checkudata(L, 1, "pipe"); uv_pipe_t* stdout_stream = (uv_pipe_t*)luv_checkudata(L, 2, "pipe"); uv_pipe_t* stderr_stream = (uv_pipe_t*)luv_checkudata(L, 3, "pipe"); const char* command = luaL_checkstring(L, 4); luaL_checktype(L, 5, LUA_TTABLE); // args luaL_checktype(L, 6, LUA_TTABLE); // options // Parse the args array size_t argc = lua_objlen(L, 5) + 1; char** args = malloc(argc + 1); args[0] = (char*)command; int i; for (i = 1; i < argc; i++) { lua_rawgeti(L, 5, i); args[i] = (char*)lua_tostring(L, -1); lua_pop(L, 1); } args[argc] = NULL; // Get the cwd lua_getfield(L, 6, "cwd"); char* cwd = (char*)lua_tostring(L, -1); lua_pop(L, 1); // Get the env lua_getfield(L, 6, "env"); char** env = NULL; if (lua_type(L, -1) == LUA_TTABLE) { argc = lua_objlen(L, -1); env = malloc(argc + 1); for (i = 0; i < argc; i++) { lua_rawgeti(L, -1, i + 1); env[i] = (char*)lua_tostring(L, -1); lua_pop(L, 1); } env[argc] = NULL; } lua_pop(L, 1); uv_process_options_t options; options.exit_cb = luv_process_on_exit; options.file = command; options.args = args; options.env = env; options.cwd = cwd; options.stdin_stream = stdin_stream; options.stdout_stream = stdout_stream; options.stderr_stream = stderr_stream; // Create the userdata uv_process_t* handle = (uv_process_t*)lua_newuserdata(L, sizeof(uv_process_t)); int r = uv_spawn(uv_default_loop(), handle, options); free(args); if (env) free(env); if (r) { uv_err_t err = uv_last_error(uv_default_loop()); return luaL_error(L, "spawn: %s", uv_strerror(err)); } // Set metatable for type luaL_getmetatable(L, "luv_process"); lua_setmetatable(L, -2); // Create a local environment for storing stuff lua_newtable(L); lua_setfenv (L, -2); // Store a reference to the userdata in the handle luv_ref_t* ref = (luv_ref_t*)malloc(sizeof(luv_ref_t)); ref->L = L; lua_pushvalue(L, -1); // duplicate so we can _ref it ref->r = luaL_ref(L, LUA_REGISTRYINDEX); handle->data = ref; assert(lua_gettop(L) == before + 1); // return the userdata return 1; }
static uv_signal_t* luv_check_signal(lua_State* L, int index) { uv_signal_t* handle = luv_checkudata(L, index, "uv_signal"); luaL_argcheck(L, handle->type == UV_SIGNAL && handle->data, index, "Expected uv_signal_t"); return handle; }
static uv_tty_t* luv_check_tty(lua_State* L, int index) { uv_tty_t* handle = (uv_tty_t*)luv_checkudata(L, index, "uv_tty"); luaL_argcheck(L, handle->type == UV_TTY && handle->data, index, "Expected uv_tty_t"); return handle; }
int luv_ref(lua_State* L) { uv_handle_t* handle = luv_checkudata(L, 1, "handle"); uv_ref(handle); return 0; }
static uv_tcp_t* luv_check_tcp(lua_State* L, int index) { uv_tcp_t* handle = luv_checkudata(L, index, "uv_tcp"); luaL_argcheck(L, handle->type == UV_TCP && handle->data, index, "Expected uv_tcp_t"); return handle; }
static uv_udp_t* luv_check_udp(lua_State* L, int index) { uv_udp_t* handle = (uv_udp_t*)luv_checkudata(L, index, "uv_udp"); luaL_argcheck(L, handle->type == UV_UDP && handle->data, index, "Expected uv_udp_t"); return handle; }
static uv_prepare_t* luv_check_prepare(lua_State* L, int index) { uv_prepare_t* handle = (uv_prepare_t*)luv_checkudata(L, index, "uv_prepare"); luaL_argcheck(L, handle->type == UV_PREPARE && handle->data, index, "Expected uv_prepare_t"); return handle; }