Beispiel #1
0
int uv_pipe_read_start(uv_pipe_t* handle, uv_alloc_cb alloc_cb, uv_read_cb read_cb) {
  if (!(handle->flags & UV_HANDLE_CONNECTION)) {
    uv_set_error(UV_EINVAL, 0);
    return -1;
  }

  if (handle->flags & UV_HANDLE_READING) {
    uv_set_error(UV_EALREADY, 0);
    return -1;
  }

  if (handle->flags & UV_HANDLE_EOF) {
    uv_set_error(UV_EOF, 0);
    return -1;
  }

  handle->flags |= UV_HANDLE_READING;
  handle->read_cb = read_cb;
  handle->alloc_cb = alloc_cb;

  /* If reading was stopped and then started again, there could stell be a */
  /* read request pending. */
  if (!(handle->flags & UV_HANDLE_READ_PENDING))
    uv_pipe_queue_read(handle);

  return 0;
}
Beispiel #2
0
/* Starts listening for connections for the given pipe. */
int uv_pipe_listen(uv_pipe_t* handle, int backlog, uv_connection_cb cb) {
  int i, errno;
  uv_pipe_accept_t* req;
  HANDLE pipeHandle;

  if (handle->flags & UV_HANDLE_BIND_ERROR) {
    uv_set_error(UV_EINVAL, 0);
    return -1;
  }

  if (!(handle->flags & UV_HANDLE_BOUND) && 
      !(handle->flags & UV_HANDLE_GIVEN_OS_HANDLE)) {
    uv_set_error(UV_EINVAL, 0);
    return -1;
  }

  if (handle->flags & UV_HANDLE_LISTENING ||
      handle->flags & UV_HANDLE_READING) {
    uv_set_error(UV_EALREADY, 0);
    return -1;
  }

  if (!(handle->flags & UV_HANDLE_PIPESERVER) && 
      !(handle->flags & UV_HANDLE_GIVEN_OS_HANDLE)) {
    uv_set_error(UV_ENOTSUP, 0);
    return -1;
  }

  handle->flags |= UV_HANDLE_LISTENING;
  handle->connection_cb = cb;

  if (handle->flags & UV_HANDLE_GIVEN_OS_HANDLE) {
    handle->flags |= UV_HANDLE_PIPESERVER;
    pipeHandle = handle->handle;
    assert(pipeHandle != INVALID_HANDLE_VALUE);
    req = &handle->accept_reqs[0];
    uv_req_init((uv_req_t*) req);
    req->pipeHandle = pipeHandle;
    req->type = UV_ACCEPT;
    req->data = handle;
    req->next_pending = NULL;

    if (uv_set_pipe_handle(handle, pipeHandle)) {
      uv_set_sys_error(GetLastError());
      return -1;
    }

    uv_pipe_queue_accept(handle, req, TRUE);
  } else {
    /* First pipe handle should have already been created in uv_pipe_bind */
    assert(handle->accept_reqs[0].pipeHandle != INVALID_HANDLE_VALUE);

    for (i = 0; i < COUNTOF(handle->accept_reqs); i++) {
      uv_pipe_queue_accept(handle, &handle->accept_reqs[i], i == 0);
    }
  }

  return 0;
}
Beispiel #3
0
int uv_pipe_write(uv_write_t* req, uv_pipe_t* handle, uv_buf_t bufs[], int bufcnt,
    uv_write_cb cb) {
  int result;

  if (bufcnt != 1) {
    uv_set_error(UV_ENOTSUP, 0);
    return -1;
  }

  assert(handle->handle != INVALID_HANDLE_VALUE);

  if (!(handle->flags & UV_HANDLE_CONNECTION)) {
    uv_set_error(UV_EINVAL, 0);
    return -1;
  }

  if (handle->flags & UV_HANDLE_SHUTTING) {
    uv_set_error(UV_EOF, 0);
    return -1;
  }

  uv_req_init((uv_req_t*) req);
  req->type = UV_WRITE;
  req->handle = (uv_stream_t*) handle;
  req->cb = cb;
  memset(&req->overlapped, 0, sizeof(req->overlapped));

  result = WriteFile(handle->handle,
                     bufs[0].base,
                     bufs[0].len,
                     NULL,
                     &req->overlapped);

  if (!result && GetLastError() != ERROR_IO_PENDING) {
    uv_set_sys_error(GetLastError());
    return -1;
  }

  if (result) {
    /* Request completed immediately. */
    req->queued_bytes = 0;
  } else {
    /* Request queued by the kernel. */
    req->queued_bytes = uv_count_bufs(bufs, bufcnt);
    handle->write_queue_size += req->queued_bytes;
  }

  handle->reqs_pending++;
  handle->write_reqs_pending++;

  return 0;
}
Beispiel #4
0
uv_stream_t* uv_std_handle(uv_loop_t* loop, uv_std_type type) {
  HANDLE handle;

  switch (type) {
    case UV_STDIN:
      handle = GetStdHandle(STD_INPUT_HANDLE);
      if (handle == INVALID_HANDLE_VALUE) {
        return NULL;
      }

      /* Assume only named pipes for now. */
      return (uv_stream_t*)uv_make_pipe_for_std_handle(loop, handle);
      break;

    case UV_STDOUT:
      return NULL;
      break;

    case UV_STDERR:
      return NULL;
      break;

    default:
      assert(0);
      uv_set_error(loop, UV_EINVAL, 0);
      return NULL;
  }
}
Beispiel #5
0
static void uv_pipe_read_eof(uv_pipe_t* handle, uv_buf_t buf) {
  /* If there is an eof timer running, we don't need it any more, */
  /* so discard it. */
  eof_timer_destroy(handle);

  handle->flags |= UV_HANDLE_EOF;
  uv_read_stop((uv_stream_t*) handle);

  uv_set_error(UV_EOF, 0);
  handle->read_cb((uv_stream_t*) handle, -1, uv_null_buf_);
}
Beispiel #6
0
/* Starts listening for connections for the given pipe. */
int uv_pipe_listen(uv_pipe_t* handle, uv_connection_cb cb) {
  int i, errno;

  if (handle->flags & UV_HANDLE_BIND_ERROR) {
    LOOP->last_error = handle->error;
    return -1;
  }

  if (!(handle->flags & UV_HANDLE_BOUND)) {
    uv_set_error(UV_ENOTCONN, 0);
    return -1;
  }

  if (handle->flags & UV_HANDLE_LISTENING ||
      handle->flags & UV_HANDLE_READING) {
    uv_set_error(UV_EALREADY, 0);
    return -1;
  }

  if (!(handle->flags & UV_HANDLE_PIPESERVER)) {
    uv_set_error(UV_ENOTSUP, 0);
    return -1;
  }

  handle->flags |= UV_HANDLE_LISTENING;
  handle->connection_cb = cb;

  /* First pipe handle should have already been created in uv_pipe_bind */
  assert(handle->accept_reqs[0].pipeHandle != INVALID_HANDLE_VALUE);

  for (i = 0; i < COUNTOF(handle->accept_reqs); i++) {
    uv_pipe_queue_accept(handle, &handle->accept_reqs[i], i == 0);
  }

  return 0;
}
Beispiel #7
0
/* Creates a pipe server. */
int uv_pipe_bind(uv_pipe_t* handle, const char* name) {
  int i, errno, nameSize;
  uv_pipe_accept_t* req;

  if (handle->flags & UV_HANDLE_BOUND) {
    uv_set_sys_error(WSAEINVAL);
    return -1;
  }

  if (!name) {
    uv_set_sys_error(WSAEINVAL);
    return -1;
  }

  for (i = 0; i < COUNTOF(handle->accept_reqs); i++) {
    req = &handle->accept_reqs[i];
    uv_req_init((uv_req_t*) req);
    req->type = UV_ACCEPT;
    req->data = handle;
    req->pipeHandle = INVALID_HANDLE_VALUE;
    req->next_pending = NULL;
  }

  /* Convert name to UTF16. */
  nameSize = uv_utf8_to_utf16(name, NULL, 0) * sizeof(wchar_t);
  handle->name = (wchar_t*)malloc(nameSize);
  if (!handle->name) {
    uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
  }

  if (!uv_utf8_to_utf16(name, handle->name, nameSize / sizeof(wchar_t))) {
    uv_set_sys_error(GetLastError());
    return -1;
  }

  /*
   * Attempt to create the first pipe with FILE_FLAG_FIRST_PIPE_INSTANCE.
   * If this fails then there's already a pipe server for the given pipe name.
   */
  handle->accept_reqs[0].pipeHandle = CreateNamedPipeW(handle->name,
                                                       PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED | FILE_FLAG_FIRST_PIPE_INSTANCE,
                                                       PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,
                                                       PIPE_UNLIMITED_INSTANCES,
                                                       65536,
                                                       65536,
                                                       0,
                                                       NULL);

  if (handle->accept_reqs[0].pipeHandle == INVALID_HANDLE_VALUE) {
    errno = GetLastError();
    if (errno == ERROR_ACCESS_DENIED) {
      uv_set_error(UV_EADDRINUSE, errno);
      handle->error = LOOP->last_error;
      handle->flags |= UV_HANDLE_BIND_ERROR;
    } else if (errno == ERROR_PATH_NOT_FOUND || errno == ERROR_INVALID_NAME) {
      uv_set_error(UV_EACCESS, errno);
    } else {
      uv_set_sys_error(errno);
    }
    goto error;
  }

  if (uv_set_pipe_handle(handle, handle->accept_reqs[0].pipeHandle)) {
    uv_set_sys_error(GetLastError());
    goto error;
  }

  handle->flags |= UV_HANDLE_PIPESERVER;
  handle->flags |= UV_HANDLE_BOUND;

  return 0;

error:
  if (handle->name) {
    free(handle->name);
    handle->name = NULL;
  }

  if (handle->accept_reqs[0].pipeHandle != INVALID_HANDLE_VALUE) {
    CloseHandle(handle->accept_reqs[0].pipeHandle);
    handle->accept_reqs[0].pipeHandle = INVALID_HANDLE_VALUE;
  }

  return -1;
}
Beispiel #8
0
static int uv_create_stdio_pipe_pair(uv_pipe_t* server_pipe, HANDLE* child_pipe,  DWORD server_access, DWORD child_access) {
  int err;
  SECURITY_ATTRIBUTES sa = { sizeof(SECURITY_ATTRIBUTES), NULL, TRUE };
  char pipe_name[64];
  DWORD mode = PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT;

  if (server_pipe->type != UV_NAMED_PIPE) {
    uv_set_error(UV_EINVAL, 0);
    err = -1;
    goto done;
  }

  /* Create server pipe handle. */
  err = uv_stdio_pipe_server(server_pipe, server_access, pipe_name, sizeof(pipe_name));
  if (err) {
    goto done;
  }

  /* Create child pipe handle. */
  *child_pipe = CreateFileA(pipe_name,
                            child_access,
                            0,
                            &sa,
                            OPEN_EXISTING,
                            0,
                            NULL);

  if (*child_pipe == INVALID_HANDLE_VALUE) {
    uv_set_sys_error(GetLastError());
    err = -1;
    goto done;
  }

  if (!SetNamedPipeHandleState(*child_pipe, &mode, NULL, NULL)) {
    uv_set_sys_error(GetLastError());
    err = -1;
    goto done;
  }

  /* Do a blocking ConnectNamedPipe.  This should not block because
   * we have both ends of the pipe created.
   */
  if (!ConnectNamedPipe(server_pipe->handle, NULL)) {
    if (GetLastError() != ERROR_PIPE_CONNECTED) {
      uv_set_sys_error(GetLastError());
      err = -1;
      goto done;
    }
  }

  err = 0;

done:
  if (err) {
    if (server_pipe->handle != INVALID_HANDLE_VALUE) {
      close_pipe(server_pipe, NULL, NULL);
    }

    if (*child_pipe != INVALID_HANDLE_VALUE) {
      CloseHandle(*child_pipe);
      *child_pipe = INVALID_HANDLE_VALUE;
    }
  }

  return err;
}