Example #1
0
File: udp.c Project: luvit/luv
static int luv_new_udp(lua_State* L) {
    uv_udp_t* handle = (uv_udp_t*)luv_newuserdata(L, sizeof(*handle));
    int ret;
    if (lua_isnoneornil(L, 1)) {
        ret = uv_udp_init(luv_loop(L), handle);
    }
    else {
        ret = uv_udp_init_ex(luv_loop(L), handle, lua_tointeger(L, 1));
    }
    if (ret < 0) {
        lua_pop(L, 1);
        return luv_error(L, ret);
    }
    handle->data = luv_setup_handle(L);
    return 1;
}
Example #2
0
static int luv_new_work(lua_State* L) {
  size_t len;
  const char* buff;
  luv_work_ctx_t* ctx;

  buff = luv_thread_dumped(L, 1, &len);
  luaL_checktype(L, 2, LUA_TFUNCTION);
  if(!lua_isnoneornil(L, 3))
    luaL_checktype(L, 3, LUA_TFUNCTION);

  ctx = lua_newuserdata(L, sizeof(*ctx));
  memset(ctx, 0, sizeof(*ctx));

  ctx->len = len;
  ctx->code = malloc(ctx->len);
  memcpy(ctx->code, buff, len);

  lua_pushvalue(L, 2);
  ctx->after_work_cb = luaL_ref(L, LUA_REGISTRYINDEX);
  if (lua_gettop(L) == 4) {
    lua_pushvalue(L, 3);
    ctx->async_cb = luaL_ref(L, LUA_REGISTRYINDEX);
    uv_async_init(luv_loop(L), &ctx->async, async_cb);
  } else
    ctx->async_cb = LUA_REFNIL;
  ctx->L = L;
  luaL_getmetatable(L, "luv_work_ctx");
  lua_setmetatable(L, -2);
  return 1;
}
Example #3
0
static int luv_queue_channel_new(lua_State* L)
{
	const char* name = luv_queue_lua_arg_string(L, 1, NULL, queue_usage_new);
	int limit = luv_queue_lua_arg_integer(L, 2, 1, 0, queue_usage_new);
	luv_queue_t* queue = luv_queue_create(name, limit);

	if (lua_gettop(L) >= 3) {
		lua_pushvalue(L, 3);
		queue->async_cb = luaL_ref(L, LUA_REGISTRYINDEX);

		uv_async_init(luv_loop(L), &queue->async, luv_queue_async_callback);
		queue->async.data = queue;

	} else {
		queue->async_cb = LUA_REFNIL;
		queue->async.data = NULL;
	}

	queue->L = L;

	if (!luv_queues_add(queue)) {
		luv_queue_destroy(queue);
		lua_pushnil(L);
		lua_pushstring(L, "chan name duplicated");
		return 2;
	}

	luv_queue_channel_push_queue(L, queue);
	return 1;
}
Example #4
0
static int luv_queue_work(lua_State* L) {
    luv_work_ctx_t* ctx;
    luv_work_t* work;
    int ret;
    int top = lua_gettop(L);
    ctx = luv_check_work_ctx(L, 1);   // ctx should ref up
    work = lua_newuserdata(L, sizeof(*work)); //work should ref up
    memset(work, 0, sizeof(*work));
    luv_thread_arg_set(L, &work->arg, 2, top);
    work->ctx = ctx;
    work->work.data = work;
    ret = uv_queue_work(luv_loop(L), &work->work, luv_work_cb, luv_after_work_cb);
    if (ret < 0) return luv_error(L, ret);

    lua_pushlightuserdata(L, work->ctx);
    lua_pushvalue(L, 1);
    lua_settable(L, LUA_REGISTRYINDEX);

    lua_pushlightuserdata(L, work);
    lua_pushvalue(L, -2);
    lua_settable(L, LUA_REGISTRYINDEX);

    lua_pushboolean(L, 1);
    return 1;
}
Example #5
0
static int luv_new_signal(lua_State* L) {
  uv_signal_t* handle = luv_newuserdata(L, sizeof(*handle));
  int ret = uv_signal_init(luv_loop(L), handle);
  if (ret < 0) {
    lua_pop(L, 1);
    return luv_error(L, ret);
  }
  handle->data = luv_setup_handle(L);
  return 1;
}
Example #6
0
static int loop_gc(lua_State *L) {
  uv_loop_t* loop = luv_loop(L);
  // Call uv_close on every active handle
  uv_walk(loop, walk_cb, NULL);
  // Run the event loop until all handles are successfully closed
  while (uv_loop_close(loop)) {
    uv_run(loop, UV_RUN_DEFAULT);
  }
  return 0;
}
Example #7
0
static int luv_new_socket_poll(lua_State* L) {
  int fd = luaL_checkinteger(L, 1);
  uv_poll_t* handle = (uv_poll_t*)luv_newuserdata(L, sizeof(*handle));
  int ret = uv_poll_init_socket(luv_loop(L), handle, fd);
  if (ret < 0) {
    lua_pop(L, 1);
    return luv_error(L, ret);
  }
  handle->data = luv_setup_handle(L);
  return 1;
}
Example #8
0
File: tty.c Project: luvit/luv
static int luv_new_tty(lua_State* L) {
    int readable, ret;
    uv_tty_t* handle;
    uv_file fd = luaL_checkinteger(L, 1);
    luaL_checktype(L, 2, LUA_TBOOLEAN);
    readable = lua_toboolean(L, 2);
    handle = (uv_tty_t*)luv_newuserdata(L, sizeof(*handle));
    ret = uv_tty_init(luv_loop(L), handle, fd, readable);
    if (ret < 0) {
        lua_pop(L, 1);
        return luv_error(L, ret);
    }
    handle->data = luv_setup_handle(L);
    return 1;
}
Example #9
0
static int luv_queue_work(lua_State* L) {
  int top = lua_gettop(L);
  luv_work_ctx_t* ctx = luv_check_work_ctx(L, 1);
  luv_work_t* work = malloc(sizeof(*work));
  int ret;

  luv_thread_arg_set(L, &work->arg, 2, top);
  work->ctx = ctx;
  work->work.data = work;
  ret = uv_queue_work(luv_loop(L), &work->work, luv_work_cb, luv_after_work_cb);
  if (ret < 0) {
    free(work);
    return luv_error(L, ret);
  }

  //ref up to ctx 
  lua_pushlightuserdata(L, work);
  lua_pushvalue(L, 1);
  lua_rawset(L, LUA_REGISTRYINDEX);

  lua_pushboolean(L, 1);
  return 1;
}
Example #10
0
File: process.c Project: kidaa/luv
static int luv_spawn(lua_State* L) {
  uv_process_t* handle;
  uv_process_options_t options;
  size_t i, len = 0;
  int ret;

  memset(&options, 0, sizeof(options));
  options.exit_cb = exit_cb;
  options.file = luaL_checkstring(L, 1);
  options.flags = 0;

  // Make sure the 2nd argument is a table
  luaL_checktype(L, 2, LUA_TTABLE);

  // get the args list
  lua_getfield(L, 2, "args");
  // +1 for inserted command at front
  if (lua_type(L, -1) == LUA_TTABLE) {
    len = 1 + lua_rawlen(L, -1);
  }
  else if (lua_type(L, -1) != LUA_TNIL) {
    luv_clean_options(&options);
    return luaL_argerror(L, 3, "args option must be table");
  }
  else {
    len = 1;
  }
  // +1 for null terminator at end
  options.args = malloc((len + 1) * sizeof(*options.args));
  if (!options.args) {
    luv_clean_options(&options);
    return luaL_error(L, "Problem allocating args");
  }
  options.args[0] = (char*)options.file;
  for (i = 1; i < len; ++i) {
    lua_rawgeti(L, -1, i);
    options.args[i] = (char*)lua_tostring(L, -1);
    lua_pop(L, 1);
  }
  options.args[len] = NULL;
  lua_pop(L, 1);

  // get the stdio list
  lua_getfield(L, 2, "stdio");
  if (lua_type(L, -1) == LUA_TTABLE) {
    options.stdio_count = len = lua_rawlen(L, -1);
    options.stdio = malloc(len * sizeof(*options.stdio));
    if (!options.stdio) {
      luv_clean_options(&options);
      return luaL_error(L, "Problem allocating stdio");
    }
    for (i = 0; i < len; ++i) {
      lua_rawgeti(L, -1, i + 1);
      // integers are assumed to be file descripters
      if (lua_type(L, -1) == LUA_TNUMBER) {
        options.stdio[i].flags = UV_INHERIT_FD;
        options.stdio[i].data.fd = lua_tointeger(L, -1);
      }
      // userdata is assumed to be a uv_stream_t instance
      else if (lua_type(L, -1) == LUA_TUSERDATA) {
        uv_os_fd_t fd;
        uv_stream_t* stream = luv_check_stream(L, -1);
        int err = uv_fileno((uv_handle_t*)stream, &fd);
        if (err == UV_EINVAL || err == UV_EBADF) {
          options.stdio[i].flags = UV_CREATE_PIPE | UV_READABLE_PIPE | UV_WRITABLE_PIPE;
        }
        else {
          options.stdio[i].flags = UV_INHERIT_STREAM;
        }
        options.stdio[i].data.stream = stream;
      }
      else if (lua_type(L, -1) == LUA_TNIL) {
        options.stdio[i].flags = UV_IGNORE;
      }
      else {
        luv_clean_options(&options);
        return luaL_argerror(L, 2, "stdio table entries must be nil, uv_stream_t, or integer");
      }
      lua_pop(L, 1);
    }
  }
  else if (lua_type(L, -1) != LUA_TNIL) {
    luv_clean_options(&options);
    return luaL_argerror(L, 2, "stdio option must be table");
  }
  lua_pop(L, 1);

  // Get the env
  lua_getfield(L, 2, "env");
  if (lua_type(L, -1) == LUA_TTABLE) {
    len = lua_rawlen(L, -1);
    options.env = malloc((len + 1) * sizeof(*options.env));
    if (!options.env) {
      luv_clean_options(&options);
      return luaL_error(L, "Problem allocating env");
    }
    for (i = 0; i < len; ++i) {
      lua_rawgeti(L, -1, i + 1);
      options.env[i] = (char*)lua_tostring(L, -1);
      lua_pop(L, 1);
    }
    options.env[len] = NULL;
  }
  else if (lua_type(L, -1) != LUA_TNIL) {
    luv_clean_options(&options);
    return luaL_argerror(L, 2, "env option must be table");
  }
  lua_pop(L, 1);

  // Get the cwd
  lua_getfield(L, 2, "cwd");
  if (lua_type(L, -1) == LUA_TSTRING) {
    options.cwd = (char*)lua_tostring(L, -1);
  }
  else if (lua_type(L, -1) != LUA_TNIL) {
    luv_clean_options(&options);
    return luaL_argerror(L, 2, "cwd option must be string");
  }
  lua_pop(L, 1);

  // Check for uid
  lua_getfield(L, 2, "uid");
  if (lua_type(L, -1) == LUA_TNUMBER) {
    options.uid = lua_tointeger(L, -1);
    options.flags |= UV_PROCESS_SETUID;
  }
  else if (lua_type(L, -1) != LUA_TNIL) {
    luv_clean_options(&options);
    return luaL_argerror(L, 2, "uid option must be number");
  }
  lua_pop(L, 1);

  // Check for gid
  lua_getfield(L, 2, "gid");
  if (lua_type(L, -1) == LUA_TNUMBER) {
    options.gid = lua_tointeger(L, -1);
    options.flags |= UV_PROCESS_SETGID;
  }
  else if (lua_type(L, -1) != LUA_TNIL) {
    luv_clean_options(&options);
    return luaL_argerror(L, 2, "gid option must be number");
  }
  lua_pop(L, 1);

  // Check for the boolean flags
  lua_getfield(L, 2, "verbatim");
  if (lua_toboolean(L, -1)) {
    options.flags |= UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS;
  }
  lua_pop(L, 1);
  lua_getfield(L, 2, "detached");
  if (lua_toboolean(L, -1)) {
    options.flags |= UV_PROCESS_DETACHED;
  }
  lua_pop(L, 1);
  lua_getfield(L, 2, "hide");
  if (lua_toboolean(L, -1)) {
    options.flags |= UV_PROCESS_WINDOWS_HIDE;
  }
  lua_pop(L, 1);

  handle = lua_newuserdata(L, sizeof(*handle));
  handle->type = UV_PROCESS;
  handle->data = luv_setup_handle(L);

  if (!lua_isnoneornil(L, 3)) {
    luv_check_callback(L, handle->data, LUV_EXIT, 3);
  }

  ret = uv_spawn(luv_loop(L), handle, &options);

  luv_clean_options(&options);
  if (ret < 0) {
    /* The async callback is required here because luajit GC may reclaim the
     * luv handle before libuv is done closing it down.
     */
    uv_close((uv_handle_t*)handle, luv_spawn_close_cb);
    return luv_error(L, ret);
  }
  lua_pushinteger(L, handle->pid);
  return 2;
}
Example #11
0
static int lua_SpawnServiceCtrlDispatcher(lua_State *L) {
  luaL_checktype(L, 1, LUA_TTABLE);
  luaL_checktype(L, 2, LUA_TFUNCTION);
  luaL_checktype(L, 3, LUA_TFUNCTION);
  if (gBatons) {
    return luaL_error(L, "ServiceCtrlDispatcher is already running");
  }

  /* structure allocation/setup */
  BOOL ret = FALSE;
  size_t len = 0;
  svc_dispatch_info *info = LocalAlloc(LPTR, sizeof(svc_dispatch_info));
  uv_async_init(luv_loop(L), &info->end_async_handle, svcdispatcher_end_cb);
  svc_baton** baton_pp = &gBatons;

  /* Convert the table to a service table and setup the baton table */
  lua_pushnil(L);  /* first key */
  while (lua_next(L, 1) != 0) {
    /* uses 'key' (at index -2) and 'value' (at index -1) */
    const char* name = luaL_checkstring(L, -2);

    luaL_checktype(L, -1, LUA_TTABLE);
    lua_pushvalue(L, -1);
    lua_pushnil(L);
    lua_next(L, -2);
    luaL_checktype(L, -1, LUA_TFUNCTION);
    lua_pushvalue(L, -1);
    int main_ref = luaL_ref(L, LUA_REGISTRYINDEX);
    lua_pop(L, 1);
    lua_next(L, -2);
    luaL_checktype(L, -1, LUA_TFUNCTION);
    lua_pushvalue(L, -1);
    int cb_ref = luaL_ref(L, LUA_REGISTRYINDEX);
    lua_pop(L, 3);

    *baton_pp = svc_create_baton(luv_loop(L), _strdup(name), main_ref, cb_ref);
    baton_pp = &(*baton_pp)->next;

    // count the entries
    ++len;

    /* removes 'value'; keeps 'key' for next iteration */
    lua_pop(L, 1);
  }

  if (len == 0) {
    return luaL_error(L, "Service Dispatch Table is empty");
  }

  lua_pushvalue(L, 2);
  info->lua_cb_ref = luaL_ref(L, LUA_REGISTRYINDEX);

  /* store the error cb in the registry */
  lua_pushstring(L, "winsvc_error_cb");
  lua_pushvalue(L, 3);
  lua_settable(L, LUA_REGISTRYINDEX);

  /* Create Windows Service Entry Table */
  info->svc_table = LocalAlloc(LPTR, sizeof(SERVICE_TABLE_ENTRY) * (len + 1));
  svc_baton* baton_it = gBatons;
  SERVICE_TABLE_ENTRY* entry_it = info->svc_table;
  while(baton_it) {
    entry_it->lpServiceName = baton_it->name;
    entry_it->lpServiceProc = ServiceMain;
    baton_it = baton_it->next;
    ++entry_it;
  }


  /* Start */
  HANDLE thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&StartServiceCtrlDispatcherThread, info, 0, NULL);
  ret = thread != NULL;

  lua_pushboolean(L, ret);
  if (ret) {
    lua_pushnil(L);
  }
  else {
    lua_pushinteger(L, GetLastError());
  }
  return 2;
}
Example #12
0
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;
}
Example #13
0
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;
}
Example #14
0
File: misc.c Project: luvit/luv
static int luv_print_active_handles(lua_State* L){
  uv_print_active_handles(luv_loop(L), stderr);
  return 0;
}