Ejemplo n.º 1
0
void uv__stream_io(EV_P_ ev_io* watcher, int revents) {
  uv_stream_t* stream = watcher->data;

  assert(stream->type == UV_TCP || stream->type == UV_NAMED_PIPE ||
      stream->type == UV_TTY);
  assert(watcher == &stream->read_watcher ||
         watcher == &stream->write_watcher);
  assert(!(stream->flags & UV_CLOSING));

  if (stream->connect_req) {
    uv__stream_connect(stream);
  } else {
    assert(revents & (EV_READ | EV_WRITE));
    assert(stream->fd >= 0);

    if (revents & EV_READ) {
      uv__read((uv_stream_t*)stream);
    }

    if (revents & EV_WRITE) {
      uv__write(stream);
      uv__write_callbacks(stream);
    }
  }
}
Ejemplo n.º 2
0
static void uv__stream_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
  uv_stream_t* stream;

  stream = container_of(w, uv_stream_t, io_watcher);

  assert(stream->type == UV_TCP ||
         stream->type == UV_NAMED_PIPE ||
         stream->type == UV_TTY);
  assert(!(stream->flags & UV_CLOSING));

  if (stream->connect_req) {
    uv__stream_connect(stream);
    return;
  }

  if (events & UV__POLLIN) {
    assert(uv__stream_fd(stream) >= 0);

    uv__read(stream);

    if (uv__stream_fd(stream) == -1)
      return; /* read_cb closed stream. */
  }

  if (events & UV__POLLOUT) {
    assert(uv__stream_fd(stream) >= 0);
    uv__write(stream);
    uv__write_callbacks(stream);
  }
}
Ejemplo n.º 3
0
void uv__tcp_io(EV_P_ ev_io* watcher, int revents) {
  uv_tcp_t* tcp = watcher->data;

  assert(tcp->type == UV_TCP);
  assert(watcher == &tcp->read_watcher ||
         watcher == &tcp->write_watcher);
  assert(tcp->fd >= 0);
  assert(!uv_flag_is_set((uv_handle_t*)tcp, UV_CLOSING));

  if (tcp->connect_req) {
    uv__tcp_connect(tcp);
  } else {
    if (revents & EV_READ) {
      uv__read(tcp);
    }

    if (revents & EV_WRITE) {
      uv_write_t* req = uv__write(tcp);
      if (req) {
        /* Error. Notify the user. */
        if (req->cb) {
          req->cb(req, -1);
        }
      } else {
        uv__write_callbacks(tcp);
      }
    }
  }
}
Ejemplo n.º 4
0
void uv__stream_destroy(uv_stream_t* stream) {
  assert(!uv__io_active(&stream->io_watcher, UV__POLLIN | UV__POLLOUT));
  assert(stream->flags & UV_CLOSED);

  if (stream->connect_req) {
    uv__req_unregister(stream->loop, stream->connect_req);
    stream->connect_req->cb(stream->connect_req, -ECANCELED);
    stream->connect_req = NULL;
  }

  uv__stream_flush_write_queue(stream, -ECANCELED);
  uv__write_callbacks(stream);

  if (stream->shutdown_req) {
    /* The ECANCELED error code is a lie, the shutdown(2) syscall is a
     * fait accompli at this point. Maybe we should revisit this in v0.11.
     * A possible reason for leaving it unchanged is that it informs the
     * callee that the handle has been destroyed.
     */
    uv__req_unregister(stream->loop, stream->shutdown_req);
    stream->shutdown_req->cb(stream->shutdown_req, -ECANCELED);
    stream->shutdown_req = NULL;
  }

  assert(stream->write_queue_size == 0);
}
Ejemplo n.º 5
0
static void uv__stream_io(uv_loop_t* loop, uv__io_t* w, int events) {
  uv_stream_t* stream;

  /* either UV__IO_READ or UV__IO_WRITE but not both */
  assert(!!(events & UV__IO_READ) ^ !!(events & UV__IO_WRITE));

  if (events & UV__IO_READ)
    stream = container_of(w, uv_stream_t, read_watcher);
  else
    stream = container_of(w, uv_stream_t, write_watcher);

  assert(stream->type == UV_TCP ||
         stream->type == UV_NAMED_PIPE ||
         stream->type == UV_TTY);
  assert(!(stream->flags & UV_CLOSING));

  if (stream->connect_req)
    uv__stream_connect(stream);
  else if (events & UV__IO_READ) {
    assert(stream->fd >= 0);
    uv__read(stream);
  }
  else {
    assert(stream->fd >= 0);
    uv__write(stream);
    uv__write_callbacks(stream);
  }
}
Ejemplo n.º 6
0
static void uv__stream_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
  uv_stream_t* stream;

  stream = container_of(w, uv_stream_t, io_watcher);

  assert(stream->type == UV_TCP ||
         stream->type == UV_NAMED_PIPE ||
         stream->type == UV_TTY);
  assert(!(stream->flags & UV_CLOSING));

  if (stream->connect_req) {
    uv__stream_connect(stream);
    return;
  }

  assert(uv__stream_fd(stream) >= 0);

  /* Ignore POLLHUP here. Even it it's set, there may still be data to read. */
  if (events & (UV__POLLIN | UV__POLLERR | UV__POLLHUP))
    uv__read(stream);

  if (uv__stream_fd(stream) == -1)
    return;  /* read_cb closed stream. */

  /* Short-circuit iff POLLHUP is set, the user is still interested in read
   * events and uv__read() reported a partial read but not EOF. If the EOF
   * flag is set, uv__read() called read_cb with err=UV_EOF and we don't
   * have to do anything. If the partial read flag is not set, we can't
   * report the EOF yet because there is still data to read.
   */
  if ((events & UV__POLLHUP) &&
      (stream->flags & UV_STREAM_READING) &&
      (stream->flags & UV_STREAM_READ_PARTIAL) &&
      !(stream->flags & UV_STREAM_READ_EOF)) {
    uv_buf_t buf = { NULL, 0 };
    uv__stream_eof(stream, &buf);
  }

  if (uv__stream_fd(stream) == -1)
    return;  /* read_cb closed stream. */

  if (events & (UV__POLLOUT | UV__POLLERR | UV__POLLHUP)) {
    uv__write(stream);
    uv__write_callbacks(stream);

    /* Write queue drained. */
    if (QUEUE_EMPTY(&stream->write_queue))
      uv__drain(stream);
  }
}
Ejemplo n.º 7
0
/**
 * We get called here from directly following a call to connect(2).
 * In order to determine if we've errored out or succeeded must call
 * getsockopt.
 */
static void uv__stream_connect(uv_stream_t* stream) {
  int error;
  uv_connect_t* req = stream->connect_req;
  socklen_t errorsize = sizeof(int);

  assert(stream->type == UV_TCP || stream->type == UV_NAMED_PIPE);
  assert(req);

  if (stream->delayed_error) {
    /* To smooth over the differences between unixes errors that
     * were reported synchronously on the first connect can be delayed
     * until the next tick--which is now.
     */
    error = stream->delayed_error;
    stream->delayed_error = 0;
  } else {
    /* Normal situation: we need to get the socket error from the kernel. */
    assert(uv__stream_fd(stream) >= 0);
    tuvp_getsockopt(uv__stream_fd(stream),
                    SOL_SOCKET,
                    SO_ERROR,
                    &error,
                    &errorsize);
    error = -error;
  }

  if (error == -EINPROGRESS)
    return;

  stream->connect_req = NULL;
  uv__req_unregister(stream->loop, req);

  if (error < 0 || QUEUE_EMPTY(&stream->write_queue)) {
    uv__io_stop(stream->loop, &stream->io_watcher, UV__POLLOUT);
  }

  if (req->cb)
    req->cb(req, error);

  if (uv__stream_fd(stream) == -1)
    return;

  if (error < 0) {
    uv__stream_flush_write_queue(stream, -ECANCELED);
    uv__write_callbacks(stream);
  }
}