static void lluv_on_fs(uv_fs_t *arg){ lluv_fs_request_t *req = arg->data; lua_State *L = LLUV_FCALLBACK_L(req); lluv_loop_t *loop = lluv_loop_byptr(req->req.loop); int argc; LLUV_CHECK_LOOP_CB_INVARIANT(L); lua_rawgeti(L, LLUV_LUA_REGISTRY, req->cb); argc = lluv_push_fs_result_object(L, req); if(arg->result < 0){ lluv_error_create(L, LLUV_ERR_UV, arg->result, arg->path); ++argc; } else{ lua_pushnil(L); argc += 1 + lluv_push_fs_result(L, req); } uv_fs_req_cleanup(&req->req); lluv_fs_request_free(L, req); LLUV_LOOP_CALL_CB(L, loop, argc); LLUV_CHECK_LOOP_CB_INVARIANT(L); }
static int lluv_udp_send(lua_State *L){ lluv_handle_t *handle = lluv_check_udp(L, 1, LLUV_FLAG_OPEN); struct sockaddr_storage sa; int err = lluv_check_addr(L, 2, &sa); if(err < 0){ int top = lua_gettop(L); if(top > 4) lua_settop(L, top = 5); if(lua_isfunction(L, top)){ lua_pushvalue(L, 1); /*self*/ /*host:port*/ lua_pushvalue(L, 2); lua_pushliteral(L, ":"); lua_pushvalue(L, 3); lua_concat(L, 3); lluv_error_create(L, LLUV_ERR_UV, err, lua_tostring(L, -1)); lua_remove(L, -2); lluv_loop_defer_call(L, lluv_loop_by_handle(&handle->handle), 2); lua_settop(L, 1); return 1; } lua_settop(L, 3); lua_pushliteral(L, ":");lua_insert(L, -2);lua_concat(L, 3); return lluv_fail(L, handle->flags, LLUV_ERR_UV, err, lua_tostring(L, -1)); } if(lua_type(L, 4) == LUA_TTABLE){ return lluv_udp_send_t(L, handle, (struct sockaddr*)&sa); } else{ size_t len; const char *str = luaL_checklstring(L, 4, &len); uv_buf_t buf = uv_buf_init((char*)str, len); return lluv_udp_send_(L, handle, (struct sockaddr*)&sa, &buf, 1); } }
static void lluv_on_udp_recv_cb(uv_udp_t *arg, ssize_t nread, const uv_buf_t* buf, const struct sockaddr* addr, unsigned flags){ lluv_handle_t *handle = lluv_handle_byptr((uv_handle_t*)arg); lua_State *L = LLUV_HCALLBACK_L(handle); LLUV_CHECK_LOOP_CB_INVARIANT(L); if((nread == 0) && (addr == NULL)){ /* ** The receive callback will be called with ** nread == 0 and addr == NULL when there is ** nothing to read */ lluv_free_buffer((uv_handle_t*)arg, buf); return; } lua_rawgeti(L, LLUV_LUA_REGISTRY, LLUV_READ_CB(handle)); assert(!lua_isnil(L, -1)); lluv_handle_pushself(L, handle); if(nread >= 0){ assert(addr); lua_pushnil(L); lua_pushlstring(L, buf->base, nread); lluv_free_buffer((uv_handle_t*)arg, buf); } else{ lluv_free_buffer((uv_handle_t*)arg, buf); /* The callee is responsible for stopping closing the stream * when an error happens by calling uv_read_stop() or uv_close(). * Trying to read from the stream again is undefined. */ uv_udp_recv_stop(arg); luaL_unref(L, LLUV_LUA_REGISTRY, LLUV_READ_CB(handle)); LLUV_READ_CB(handle) = LUA_NOREF; lluv_error_create(L, LLUV_ERR_UV, (uv_errno_t)nread, NULL); lua_pushnil(L); lluv_handle_unlock(L, handle, LLUV_LOCK_READ); } lua_pushinteger(L, flags); LLUV_HANDLE_CALL_CB(L, handle, 4 + lluv_push_addr(L, (const struct sockaddr_storage*)addr)); LLUV_CHECK_LOOP_CB_INVARIANT(L); }
static int lluv_tcp_bind(lua_State *L){ static const lluv_uv_const_t FLAGS[] = { { UV_TCP_IPV6ONLY , "ipv6only" }, { 0, NULL } }; lluv_handle_t *handle = lluv_check_tcp(L, 1, LLUV_FLAG_OPEN); struct sockaddr_storage sa; int err = lluv_check_addr(L, 2, &sa); unsigned int flags = 0; int top = lua_gettop(L); if(top > 5)lua_settop(L, top = 5); if((top > 4) || (!lua_isfunction(L, 4))){ flags = lluv_opt_flags_ui(L, 4, flags, FLAGS); } if(err < 0){ lua_checkstack(L, 3); lua_pushvalue(L, 2); lua_pushliteral(L, ":"); lua_pushvalue(L, 3); lua_concat(L, 3); if(!lua_isfunction(L, top)){ return lluv_fail(L, handle->flags, LLUV_ERR_UV, err, lua_tostring(L, -1)); } lluv_error_create(L, LLUV_ERR_UV, err, lua_tostring(L, -1)); lua_remove(L, -2); lua_pushvalue(L, 1); lua_insert(L, -2); lluv_loop_defer_call(L, lluv_loop_by_handle(&handle->handle), 2); lua_settop(L, 1); return 1; } err = uv_tcp_bind(LLUV_H(handle, uv_tcp_t), (struct sockaddr *)&sa, flags); if(err < 0){ lua_checkstack(L, 3); lua_pushvalue(L, 2); lua_pushliteral(L, ":"); lua_pushvalue(L, 3); lua_concat(L, 3); if(!lua_isfunction(L, top)){ return lluv_fail(L, handle->flags, LLUV_ERR_UV, err, lua_tostring(L, -1)); } lluv_error_create(L, LLUV_ERR_UV, err, lua_tostring(L, -1)); lua_remove(L, -2); lua_pushvalue(L, 1); lua_insert(L, -2); lluv_loop_defer_call(L, lluv_loop_by_handle(&handle->handle), 2); lua_settop(L, 1); return 1; } if(lua_isfunction(L, top)){ lua_pushvalue(L, 1); lua_pushnil(L); lluv_loop_defer_call(L, lluv_loop_by_handle(&handle->handle), lluv_push_addr(L, &sa) + 2 ); } lua_settop(L, 1); return 1; }
static void lluv_on_getaddrinfo(uv_getaddrinfo_t* arg, int status, struct addrinfo* res){ lluv_req_t *req = lluv_req_byptr((uv_req_t*)arg); lluv_loop_t *loop = lluv_loop_byptr(arg->loop); lua_State *L = loop->L; struct addrinfo* a = res; int i = 0; LLUV_CHECK_LOOP_CB_INVARIANT(L); lua_rawgeti(L, LLUV_LUA_REGISTRY, req->cb); lluv_req_free(L, req); assert(!lua_isnil(L, -1)); lluv_loop_pushself(L, loop); if(status < 0){ uv_freeaddrinfo(res); lluv_error_create(L, LLUV_ERR_UV, (uv_errno_t)status, NULL); LLUV_LOOP_CALL_CB(L, loop, 2); LLUV_CHECK_LOOP_CB_INVARIANT(L); return; } lua_pushnil(L); lua_newtable(L); for(a = res; a; a = a->ai_next){ char buf[INET6_ADDRSTRLEN + 1]; int port; lua_newtable(L); switch (a->ai_family){ case AF_INET:{ struct sockaddr_in *sa = (struct sockaddr_in*)a->ai_addr; uv_ip4_name(sa, buf, sizeof(buf)); lua_pushstring(L, buf); lua_setfield(L, -2, "address"); if((port = ntohs(sa->sin_port))){ lua_pushinteger(L, port); lua_setfield(L, -2, "port"); } break; } case AF_INET6:{ struct sockaddr_in6 *sa = (struct sockaddr_in6*)a->ai_addr; uv_ip6_name(sa, buf, sizeof(buf)); lua_pushstring(L, buf); lua_setfield(L, -2, "address"); if((port = ntohs(sa->sin6_port))){ lua_pushinteger(L, port); lua_setfield(L, -2, "port"); } break; } } if(a->ai_canonname){ lua_pushstring(L, a->ai_canonname); lua_setfield(L, -2, "canonname"); } lluv_push_ai_family(L, a->ai_family); lua_setfield(L, -2, "family"); lluv_push_ai_stype(L, a->ai_socktype); lua_setfield(L, -2, "socktype"); lluv_push_ai_proto(L, a->ai_protocol); lua_setfield(L, -2, "protocol"); lua_rawseti(L, -2, ++i); } uv_freeaddrinfo(res); LLUV_LOOP_CALL_CB(L, loop, 3); LLUV_CHECK_LOOP_CB_INVARIANT(L); }