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); } } }
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; }
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); } } } }
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); }
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); } } }
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); } } }
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); } } } }
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; }
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); }
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; }
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; } } } }
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; } } } }
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); } } }