예제 #1
0
파일: uv-unix.c 프로젝트: nekedos/node
static void uv__drain(uv_handle_t* handle) {
    assert(!uv_write_queue_head(handle));
    assert(handle->write_queue_size == 0);

    ev_io_stop(EV_DEFAULT_ &handle->write_watcher);

    /* Shutdown? */
    if (uv_flag_is_set(handle, UV_SHUTTING) &&
            !uv_flag_is_set(handle, UV_CLOSING) &&
            !uv_flag_is_set(handle, UV_SHUT)) {
        assert(handle->shutdown_req);

        uv_req_t* req = handle->shutdown_req;
        uv_shutdown_cb cb = req->cb;

        if (shutdown(handle->fd, SHUT_WR)) {
            /* Error. Nothing we can do, close the handle. */
            uv_err_new(handle, errno);
            uv_close(handle);
            if (cb) cb(req, -1);
        } else {
            uv_err_new(handle, 0);
            uv_flag_set(handle, UV_SHUT);
            if (cb) cb(req, 0);
        }
    }
}
예제 #2
0
파일: uv-unix.c 프로젝트: markuskopf/node
int uv_shutdown(uv_shutdown_t* req, uv_stream_t* handle, uv_shutdown_cb cb) {
  uv_tcp_t* tcp = (uv_tcp_t*)handle;
  assert(handle->type == UV_TCP &&
      "uv_shutdown (unix) only supports uv_tcp_t right now");
  assert(tcp->fd >= 0);

  /* Initialize request */
  uv__req_init((uv_req_t*)req);
  req->handle = handle;
  req->cb = cb;

  if (uv_flag_is_set((uv_handle_t*)tcp, UV_SHUT) ||
      uv_flag_is_set((uv_handle_t*)tcp, UV_CLOSED) ||
      uv_flag_is_set((uv_handle_t*)tcp, UV_CLOSING)) {
    return -1;
  }

  tcp->shutdown_req = req;
  req->type = UV_SHUTDOWN;

  uv_flag_set((uv_handle_t*)tcp, UV_SHUTTING);

  ev_io_start(EV_DEFAULT_UC_ &tcp->write_watcher);

  return 0;
}
예제 #3
0
파일: uv-unix.c 프로젝트: markuskopf/node
static void uv__drain(uv_tcp_t* tcp) {
  uv_shutdown_t* req;

  assert(!uv_write_queue_head(tcp));
  assert(tcp->write_queue_size == 0);

  ev_io_stop(EV_DEFAULT_ &tcp->write_watcher);

  /* Shutdown? */
  if (uv_flag_is_set((uv_handle_t*)tcp, UV_SHUTTING) &&
      !uv_flag_is_set((uv_handle_t*)tcp, UV_CLOSING) &&
      !uv_flag_is_set((uv_handle_t*)tcp, UV_SHUT)) {
    assert(tcp->shutdown_req);

    req = tcp->shutdown_req;

    if (shutdown(tcp->fd, SHUT_WR)) {
      /* Error. Report it. User should call uv_close(). */
      uv_err_new((uv_handle_t*)tcp, errno);
      if (req->cb) {
        req->cb(req, -1);
      }
    } else {
      uv_err_new((uv_handle_t*)tcp, 0);
      uv_flag_set((uv_handle_t*)tcp, UV_SHUT);
      if (req->cb) {
        req->cb(req, 0);
      }
    }
  }
}
예제 #4
0
파일: uv-unix.c 프로젝트: nekedos/node
void uv__finish_close(uv_handle_t* handle) {
    assert(uv_flag_is_set(handle, UV_CLOSING));
    assert(!uv_flag_is_set(handle, UV_CLOSED));
    uv_flag_set(handle, UV_CLOSED);

    switch (handle->type) {
    case UV_TCP:
        /* XXX Is it necessary to stop these watchers here? weren't they
         * supposed to be stopped in uv_close()?
         */
        ev_io_stop(EV_DEFAULT_ &handle->write_watcher);
        ev_io_stop(EV_DEFAULT_ &handle->read_watcher);

        assert(!ev_is_active(&handle->read_watcher));
        assert(!ev_is_active(&handle->write_watcher));

        close(handle->fd);
        handle->fd = -1;

        if (handle->accepted_fd >= 0) {
            close(handle->accepted_fd);
            handle->accepted_fd = -1;
        }
        break;

    case UV_PREPARE:
        assert(!ev_is_active(&handle->prepare_watcher));
        break;

    case UV_CHECK:
        assert(!ev_is_active(&handle->check_watcher));
        break;

    case UV_IDLE:
        assert(!ev_is_active(&handle->idle_watcher));
        break;

    case UV_ASYNC:
        assert(!ev_is_active(&handle->async_watcher));
        break;

    case UV_TIMER:
        assert(!ev_is_active(&handle->timer_watcher));
        break;

    default:
        assert(0);
        break;
    }

    ev_idle_stop(EV_DEFAULT_ &handle->next_watcher);

    if (handle->close_cb) {
        handle->close_cb(handle, 0);
    }

    ev_unref(EV_DEFAULT_UC);
}
예제 #5
0
파일: uv-unix.c 프로젝트: nekedos/node
void uv__read(uv_handle_t* handle) {
    /* XXX: Maybe instead of having UV_READING we just test if
     * handle->read_cb is NULL or not?
     */
    while (handle->read_cb && uv_flag_is_set(handle, UV_READING)) {
        assert(alloc_cb);
        uv_buf_t buf = alloc_cb(handle, 64 * 1024);

        assert(buf.len > 0);
        assert(buf.base);

        struct iovec* iov = (struct iovec*) &buf;

        ssize_t nread = readv(handle->fd, iov, 1);

        if (nread < 0) {
            /* Error */
            if (errno == EAGAIN) {
                /* Wait for the next one. */
                if (uv_flag_is_set(handle, UV_READING)) {
                    ev_io_start(EV_DEFAULT_UC_ &handle->read_watcher);
                }
                uv_err_new(handle, EAGAIN);
                handle->read_cb(handle, 0, buf);
                return;
            } else {
                uv_err_new(handle, errno);
                uv_close(handle);
                handle->read_cb(handle, -1, buf);
                assert(!ev_is_active(&handle->read_watcher));
                return;
            }
        } else if (nread == 0) {
            /* EOF */
            uv_err_new_artificial(handle, UV_EOF);
            ev_io_stop(EV_DEFAULT_UC_ &handle->read_watcher);
            handle->read_cb(handle, -1, buf);

            if (uv_flag_is_set(handle, UV_SHUT)) {
                uv_close(handle);
            }
            return;
        } else {
            /* Successful read */
            handle->read_cb(handle, nread, buf);
        }
    }
}
예제 #6
0
파일: uv-unix.c 프로젝트: markuskopf/node
void uv__read(uv_tcp_t* tcp) {
  uv_buf_t buf;
  struct iovec* iov;
  ssize_t nread;

  /* XXX: Maybe instead of having UV_READING we just test if
   * tcp->read_cb is NULL or not?
   */
  while (tcp->read_cb && uv_flag_is_set((uv_handle_t*)tcp, UV_READING)) {
    assert(tcp->alloc_cb);
    buf = tcp->alloc_cb((uv_stream_t*)tcp, 64 * 1024);

    assert(buf.len > 0);
    assert(buf.base);

    iov = (struct iovec*) &buf;

    nread = read(tcp->fd, buf.base, buf.len);

    if (nread < 0) {
      /* Error */
      if (errno == EAGAIN) {
        /* Wait for the next one. */
        if (uv_flag_is_set((uv_handle_t*)tcp, UV_READING)) {
          ev_io_start(EV_DEFAULT_UC_ &tcp->read_watcher);
        }
        uv_err_new((uv_handle_t*)tcp, EAGAIN);
        tcp->read_cb((uv_stream_t*)tcp, 0, buf);
        return;
      } else {
        /* Error. User should call uv_close(). */
        uv_err_new((uv_handle_t*)tcp, errno);
        tcp->read_cb((uv_stream_t*)tcp, -1, buf);
        assert(!ev_is_active(&tcp->read_watcher));
        return;
      }
    } else if (nread == 0) {
      /* EOF */
      uv_err_new_artificial((uv_handle_t*)tcp, UV_EOF);
      ev_io_stop(EV_DEFAULT_UC_ &tcp->read_watcher);
      tcp->read_cb((uv_stream_t*)tcp, -1, buf);
      return;
    } else {
      /* Successful read */
      tcp->read_cb((uv_stream_t*)tcp, nread, buf);
    }
  }
}
예제 #7
0
파일: uv-unix.c 프로젝트: markuskopf/node
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);
      }
    }
  }
}
예제 #8
0
파일: uv-unix.c 프로젝트: nekedos/node
int uv_shutdown(uv_req_t* req) {
    uv_handle_t* handle = req->handle;
    assert(handle->fd >= 0);

    if (uv_flag_is_set(handle, UV_SHUT) ||
            uv_flag_is_set(handle, UV_CLOSED) ||
            uv_flag_is_set(handle, UV_CLOSING)) {
        return -1;
    }

    handle->shutdown_req = req;
    req->type = UV_SHUTDOWN;

    uv_flag_set(handle, UV_SHUTTING);

    ev_io_start(EV_DEFAULT_UC_ &handle->write_watcher);

    return 0;
}
예제 #9
0
파일: uv-unix.c 프로젝트: nekedos/node
void uv__next(EV_P_ ev_idle* watcher, int revents) {
    uv_handle_t* handle = watcher->data;
    assert(watcher == &handle->next_watcher);
    assert(revents == EV_IDLE);

    /* For now this function is only to handle the closing event, but we might
     * put more stuff here later.
     */
    assert(uv_flag_is_set(handle, UV_CLOSING));
    uv__finish_close(handle);
}
예제 #10
0
파일: uv-unix.c 프로젝트: AMorgaut/node
int uv_shutdown(uv_req_t* req) {
  uv_tcp_t* tcp = (uv_tcp_t*)req->handle;
  assert(tcp->fd >= 0);
  assert(tcp->type == UV_TCP);

  if (uv_flag_is_set((uv_handle_t*)tcp, UV_SHUT) ||
      uv_flag_is_set((uv_handle_t*)tcp, UV_CLOSED) ||
      uv_flag_is_set((uv_handle_t*)tcp, UV_CLOSING)) {
    return -1;
  }

  tcp->shutdown_req = req;
  req->type = UV_SHUTDOWN;

  uv_flag_set((uv_handle_t*)tcp, UV_SHUTTING);

  ev_io_start(EV_DEFAULT_UC_ &tcp->write_watcher);

  return 0;
}
예제 #11
0
파일: uv-unix.c 프로젝트: markuskopf/node
void uv__server_io(EV_P_ ev_io* watcher, int revents) {
  int fd;
  struct sockaddr_storage addr;
  socklen_t addrlen = sizeof(struct sockaddr_storage);
  uv_tcp_t* tcp = watcher->data;

  assert(watcher == &tcp->read_watcher ||
         watcher == &tcp->write_watcher);
  assert(revents == EV_READ);

  assert(!uv_flag_is_set((uv_handle_t*)tcp, UV_CLOSING));

  if (tcp->accepted_fd >= 0) {
    ev_io_stop(EV_DEFAULT_ &tcp->read_watcher);
    return;
  }

  while (1) {
    assert(tcp->accepted_fd < 0);
    fd = accept(tcp->fd, (struct sockaddr*)&addr, &addrlen);

    if (fd < 0) {
      if (errno == EAGAIN) {
        /* No problem. */
        return;
      } else if (errno == EMFILE) {
        /* TODO special trick. unlock reserved socket, accept, close. */
        return;
      } else {
        uv_err_new((uv_handle_t*)tcp, errno);
        tcp->connection_cb((uv_handle_t*)tcp, -1);
      }

    } else {
      tcp->accepted_fd = fd;
      tcp->connection_cb((uv_handle_t*)tcp, 0);
      if (tcp->accepted_fd >= 0) {
        /* The user hasn't yet accepted called uv_accept() */
        ev_io_stop(EV_DEFAULT_ &tcp->read_watcher);
        return;
      }
    }
  }
}
예제 #12
0
파일: uv-unix.c 프로젝트: nekedos/node
void uv__server_io(EV_P_ ev_io* watcher, int revents) {
    uv_handle_t* handle = watcher->data;
    assert(watcher == &handle->read_watcher ||
           watcher == &handle->write_watcher);
    assert(revents == EV_READ);

    assert(!uv_flag_is_set(handle, UV_CLOSING));

    if (handle->accepted_fd >= 0) {
        ev_io_stop(EV_DEFAULT_ &handle->read_watcher);
        return;
    }

    while (1) {
        struct sockaddr addr = { 0 };
        socklen_t addrlen = 0;

        assert(handle->accepted_fd < 0);
        int fd = accept(handle->fd, &addr, &addrlen);

        if (fd < 0) {
            if (errno == EAGAIN) {
                /* No problem. */
                return;
            } else if (errno == EMFILE) {
                /* TODO special trick. unlock reserved socket, accept, close. */
                return;
            } else {
                uv_err_new(handle, errno);
                uv_close(handle);
            }

        } else {
            handle->accepted_fd = fd;
            handle->accept_cb(handle);
            if (handle->accepted_fd >= 0) {
                /* The user hasn't yet accepted called uv_accept() */
                ev_io_stop(EV_DEFAULT_ &handle->read_watcher);
                return;
            }
        }
    }
}
예제 #13
0
파일: uv-unix.c 프로젝트: nekedos/node
void uv__tcp_io(EV_P_ ev_io* watcher, int revents) {
    uv_handle_t* handle = watcher->data;
    assert(watcher == &handle->read_watcher ||
           watcher == &handle->write_watcher);

    assert(handle->fd >= 0);

    assert(!uv_flag_is_set(handle, UV_CLOSING));

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

        if (revents & EV_WRITE) {
            uv__write(handle);
        }
    }
}