int luv_udp_recv_start(lua_State* L) { uv_udp_t* handle = (uv_udp_t*)luv_checkudata(L, 1, "udp"); int rc = uv_udp_recv_start(handle, luv_on_alloc, luv_on_udp_recv); if (rc && uv_last_error(luv_get_loop(L)).code != UV_EALREADY) { uv_err_t err = uv_last_error(luv_get_loop(L)); return luaL_error(L, "udp_recv_start: %s", uv_strerror(err)); } luv_handle_ref(L, handle->data, 1); return 0; }
static int luv__udp_bind(lua_State *L, int family) { uv_udp_t* handle = (uv_udp_t*)luv_checkudata(L, 1, "udp"); const char* host = luaL_checkstring(L, 2); int port = luaL_checkint(L, 3); int flags = 0; int rc = 0; switch (family) { case AF_INET: rc = uv_udp_bind(handle, uv_ip4_addr(host, port), flags); break; case AF_INET6: rc = uv_udp_bind6(handle, uv_ip6_addr(host, port), flags); 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_bind: %s", uv_strerror(err)); } return 0; }
static void luv_on_udp_send(uv_udp_send_t* req, int status) { luv_udp_ref_t *ref; /* load the lua state and the userdata */ lua_State *L = luv_handle_get_lua(req->handle->data); lua_pop(L, 1); /* We don't need the userdata */ /* load the callback */ ref = req->data; lua_rawgeti(L, LUA_REGISTRYINDEX, ref->ref); luaL_unref(L, LUA_REGISTRYINDEX, ref->ref); free(ref); if (lua_isfunction(L, -1)) { if (status != 0) { luv_push_async_error(L, uv_last_error(luv_get_loop(L)), "on_udp_send", NULL); luv_acall(L, 1, 0, "on_udp_send"); } else { luv_acall(L, 0, 0, "on_udp_send"); } } else { lua_pop(L, 1); } luv_handle_unref(L, req->handle->data); free(req); }
int luv_tcp_connect6(lua_State* L) { int before = lua_gettop(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); luv_connect_ref_t* ref = (luv_connect_ref_t*)malloc(sizeof(luv_connect_ref_t)); /* Store a reference to the userdata */ ref->L = L; lua_pushvalue(L, 1); ref->r = luaL_ref(L, LUA_REGISTRYINDEX); /* Give the connect_req access to this */ ref->connect_req.data = ref; if (uv_tcp_connect6(&ref->connect_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)); } assert(lua_gettop(L) == before); return 0; }
void luv_on_fs_event(uv_fs_event_t* handle, const char* filename, int events, int status) { /* load the lua state and the userdata */ luv_ref_t* ref = handle->data; lua_State *L = ref->L; int before = lua_gettop(L); lua_rawgeti(L, LUA_REGISTRYINDEX, ref->r); if (status == -1) { luv_push_async_error(L, uv_last_error(luv_get_loop(L)), "on_fs_event", NULL); luv_emit_event(L, "error", 1); } else { switch (events) { case UV_RENAME: lua_pushstring(L, "rename"); break; case UV_CHANGE: lua_pushstring(L, "change"); break; default: lua_pushnil(L); break; } if (filename) { lua_pushstring(L, filename); } else { lua_pushnil(L); } luv_emit_event(L, "change", 2); } assert(lua_gettop(L) == before); }
int luv_new_fs_watcher (lua_State* L) { int before = lua_gettop(L); const char* filename = luaL_checkstring(L, 1); luv_ref_t* ref; uv_fs_event_t* handle = (uv_fs_event_t*)lua_newuserdata(L, sizeof(uv_fs_event_t)); uv_fs_event_init(luv_get_loop(L), handle, filename, luv_on_fs_event, 0); /* Set metatable for type */ luaL_getmetatable(L, "luv_fs_watcher"); 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 */ 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; }
int luv_tcp_getsockname(lua_State* 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_getsockname(handle, (struct sockaddr*)(&address), &addrlen)) { uv_err_t err = uv_last_error(luv_get_loop(L)); return luaL_error(L, "tcp_getsockname: %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"); return 1; }
int luv_new_udp (lua_State* L) { uv_udp_t* handle = luv_create_udp(L); /* uv_udp_init memset's the handle so we need to reset the data baton */ void *data = handle->data; uv_udp_init(luv_get_loop(L), handle); handle->data = data; return 1; }
int luv_udp_recv_stop(lua_State* L) { uv_udp_t* handle = (uv_udp_t*)luv_checkudata(L, 1, "udp"); if (uv_udp_recv_stop(handle)) { uv_err_t err = uv_last_error(luv_get_loop(L)); return luaL_error(L, "udp_recv_stop: %s", uv_strerror(err)); } luv_handle_unref(L, handle->data); return 0; }
int luv_execpath(lua_State* L) { size_t size = 2*PATH_MAX; char exec_path[2*PATH_MAX]; if (uv_exepath(exec_path, &size)) { uv_err_t err = uv_last_error(luv_get_loop(L)); return luaL_error(L, "uv_exepath: %s", uv_strerror(err)); } lua_pushlstring(L, exec_path, size); return 1; }
int luv_tcp_nodelay (lua_State* L) { uv_tcp_t* handle = (uv_tcp_t*)luv_checkudata(L, 1, "tcp"); int enable = lua_toboolean(L, 2); if (uv_tcp_nodelay(handle, enable)) { uv_err_t err = uv_last_error(luv_get_loop(L)); return luaL_error(L, "tcp_nodelay: %s", uv_strerror(err)); } 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; }
static void luv_on_udp_recv(uv_udp_t* handle, ssize_t nread, uv_buf_t buf, struct sockaddr* addr, unsigned flags) { int port; char ip[INET6_ADDRSTRLEN]; /* load the lua state and the userdata */ lua_State *L = luv_handle_get_lua(handle->data); /* perform some magic */ /* the base buffer is the offset of the slab block + sizeof(MemBlock) */ MemBlock *mb = (MemBlock *)(buf.base - sizeof(MemBlock)); printf("luv_on_read: %p pool=%p\n", mb, mb->pool); if (nread == 0) { return; } if (nread < 0) { uv_close((uv_handle_t *)handle, luv_on_close); luv_push_async_error(L, uv_last_error(luv_get_loop(L)), "on_recv", NULL); luv_emit_event(L, "error", 1); return; } lua_pushlstring(L, buf.base, nread); lua_newtable(L); if (addr->sa_family == AF_INET) { uv_inet_ntop(AF_INET, &(((struct sockaddr_in*)addr)->sin_addr), ip, INET6_ADDRSTRLEN); port = ntohs(((struct sockaddr_in*)addr)->sin_port); } else if (addr->sa_family == AF_INET6){ uv_inet_ntop(AF_INET6, &(((struct sockaddr_in6*)addr)->sin6_addr), ip, INET6_ADDRSTRLEN); port = ntohs(((struct sockaddr_in6*)addr)->sin6_port); } lua_pushstring(L, ip); lua_setfield(L, -2, "address"); lua_pushnumber(L, port); lua_setfield(L, -2, "port"); lua_pushboolean(L, flags == UV_UDP_PARTIAL); lua_setfield(L, -2, "partial"); lua_pushnumber(L, nread); lua_setfield(L, -2, "size"); luv_emit_event(L, "message", 2); lev_slab_decRef( mb ); /*free(buf.base);*/ }
/* 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; }
static void luv_on_udp_recv(uv_udp_t* handle, ssize_t nread, uv_buf_t buf, struct sockaddr* addr, unsigned flags) { int port; char ip[INET6_ADDRSTRLEN]; /* load the lua state and the userdata */ lua_State *L = luv_handle_get_lua(handle->data); if (nread == 0) { return; } if (nread < 0) { uv_close((uv_handle_t *)handle, luv_on_close); luv_push_async_error(L, uv_last_error(luv_get_loop(L)), "on_recv", NULL); luv_emit_event(L, "error", 1); return; } lua_pushlstring(L, buf.base, nread); lua_newtable(L); if (addr->sa_family == AF_INET) { uv_inet_ntop(AF_INET, &(((struct sockaddr_in*)addr)->sin_addr), ip, INET6_ADDRSTRLEN); port = ntohs(((struct sockaddr_in*)addr)->sin_port); } else if (addr->sa_family == AF_INET6){ uv_inet_ntop(AF_INET6, &(((struct sockaddr_in6*)addr)->sin6_addr), ip, INET6_ADDRSTRLEN); port = ntohs(((struct sockaddr_in6*)addr)->sin6_port); } lua_pushstring(L, ip); lua_setfield(L, -2, "address"); lua_pushnumber(L, port); lua_setfield(L, -2, "port"); lua_pushboolean(L, flags == UV_UDP_PARTIAL); lua_setfield(L, -2, "partial"); lua_pushnumber(L, nread); lua_setfield(L, -2, "size"); luv_emit_event(L, "message", 2); free(buf.base); buf.base = NULL; }
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; }
static int luv_run(lua_State* L) { int r = 0; int args = lua_gettop(L); uv_run_mode mode = UV_RUN_DEFAULT; assert(args >= 0 && args <= 1); if (args == 1) { const char* smode = luaL_checkstring(L, 1); if (strcmp(smode, "once") == 0) { mode = UV_RUN_ONCE; } else if (strcmp(smode, "nowait") == 0) { mode = UV_RUN_NOWAIT; } } r = uv_run(luv_get_loop(L), mode); lua_pushinteger(L, r); return 1; }
int luv_run(lua_State* L) { uv_run(luv_get_loop(L), UV_RUN_DEFAULT); return 0; }
int luvit_init(lua_State *L, uv_loop_t* loop, int argc, char *argv[]) { int index, rc; ares_channel channel; struct ares_options options; luvit__suck_in_symbols(); memset(&options, 0, sizeof(options)); rc = ares_library_init(ARES_LIB_INIT_ALL); assert(rc == ARES_SUCCESS); // Pull up the preload table lua_getglobal(L, "package"); lua_getfield(L, -1, "preload"); lua_remove(L, -2); // Register yajl lua_pushcfunction(L, luaopen_yajl); lua_setfield(L, -2, "yajl"); // Register os lua_pushcfunction(L, luaopen_os_binding); lua_setfield(L, -2, "os_binding"); // Register http_parser lua_pushcfunction(L, luaopen_http_parser); lua_setfield(L, -2, "http_parser"); // Register uv lua_pushcfunction(L, luaopen_uv); lua_setfield(L, -2, "uv"); // Register env lua_pushcfunction(L, luaopen_env); lua_setfield(L, -2, "env"); // Register constants lua_pushcfunction(L, luaopen_constants); lua_setfield(L, -2, "constants"); // We're done with preload, put it away lua_pop(L, 1); // Get argv lua_createtable (L, argc, 0); for (index = 0; index < argc; index++) { lua_pushstring (L, argv[index]); lua_rawseti(L, -2, index); } lua_setglobal(L, "argv"); lua_pushcfunction(L, luvit_exit); lua_setglobal(L, "exit_process"); lua_pushcfunction(L, luvit_print_stderr); lua_setglobal(L, "print_stderr"); lua_pushcfunction(L, luvit_getcwd); lua_setglobal(L, "getcwd"); lua_pushstring(L, LUVIT_VERSION); lua_setglobal(L, "VERSION"); lua_pushstring(L, UV_VERSION); lua_setglobal(L, "UV_VERSION"); lua_pushstring(L, LUAJIT_VERSION); lua_setglobal(L, "LUAJIT_VERSION"); lua_pushstring(L, HTTP_VERSION); lua_setglobal(L, "HTTP_VERSION"); lua_pushstring(L, YAJL_VERSIONISH); lua_setglobal(L, "YAJL_VERSION"); // Hold a reference to the main thread in the registry assert(lua_pushthread(L) == 1); lua_setfield(L, LUA_REGISTRYINDEX, "main_thread"); // Store the loop within the registry luv_set_loop(L, loop); // Store the ARES Channel uv_ares_init_options(luv_get_loop(L), &channel, &options, 0); luv_set_ares_channel(L, &channel); return 0; }
int luv_new_tcp (lua_State* L) { uv_tcp_t* handle = luv_create_tcp(L); uv_tcp_init(luv_get_loop(L), handle); return 1; }
int luv_now(lua_State* L) { double now = (double)uv_now(luv_get_loop(L)); lua_pushnumber(L, now); return 1; }
int luv_print_all_handles(lua_State* L) { uv_print_all_handles(luv_get_loop(L)); return 0; }
static int luv_now(lua_State* L) { uint64_t now = uv_now(luv_get_loop(L)); lua_pushnumber(L, (lua_Number)now); return 1; }
int luv_update_time(lua_State* L) { uv_update_time(luv_get_loop(L)); return 0; }
uv_loop_t* virgo_get_loop(virgo_t *v) { return luv_get_loop(v->L); }
// 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); size_t argc; char** args; int i; char* cwd; char** env; uv_process_options_t options; uv_process_t* handle; int r; luv_ref_t* ref; luaL_checktype(L, 5, LUA_TTABLE); // args luaL_checktype(L, 6, LUA_TTABLE); // options // Parse the args array argc = lua_objlen(L, 5) + 1; args = malloc((argc + 1) * sizeof(char*)); args[0] = (char*)command; 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"); cwd = (char*)lua_tostring(L, -1); lua_pop(L, 1); // Get the env lua_getfield(L, 6, "env"); env = NULL; if (lua_type(L, -1) == LUA_TTABLE) { argc = lua_objlen(L, -1); env = malloc((argc + 1) * sizeof(char*)); 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); options.exit_cb = luv_process_on_exit; options.file = command; options.args = args; options.env = env ? env : luv_os_environ(); options.cwd = cwd; options.stdin_stream = stdin_stream; options.stdout_stream = stdout_stream; options.stderr_stream = stderr_stream; // Create the userdata handle = (uv_process_t*)lua_newuserdata(L, sizeof(uv_process_t)); r = uv_spawn(luv_get_loop(L), handle, options); free(args); if (env) free(env); if (r) { uv_err_t err = uv_last_error(luv_get_loop(L)); 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 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; }