int uv_pipe_listen(uv_pipe_t* handle, int backlog, uv_connection_cb cb) { int saved_errno; int status; saved_errno = errno; status = -1; if (handle->fd == -1) { uv_err_new_artificial(handle->loop, UV_EINVAL); goto out; } assert(handle->fd >= 0); if ((status = listen(handle->fd, backlog)) == -1) { uv_err_new(handle->loop, errno); } else { handle->connection_cb = cb; ev_io_init(&handle->read_watcher, uv__pipe_accept, handle->fd, EV_READ); ev_io_start(handle->loop->ev, &handle->read_watcher); } out: errno = saved_errno; return status; }
/* TODO: share this with windows? */ int uv_ares_init_options(ares_channel *channelptr, struct ares_options *options, int optmask) { int rc; /* only allow single init at a time */ if (ares_data.channel != NULL) { uv_err_new_artificial(NULL, UV_EALREADY); return -1; } /* set our callback as an option */ options->sock_state_cb = uv__ares_sockstate_cb; options->sock_state_cb_data = &ares_data; optmask |= ARES_OPT_SOCK_STATE_CB; /* We do the call to ares_init_option for caller. */ rc = ares_init_options(channelptr, options, optmask); /* if success, save channel */ if (rc == ARES_SUCCESS) { ares_data.channel = *channelptr; } /* * Initialize the timeout timer. The timer won't be started until the * first socket is opened. */ ev_init(&ares_data.timer, uv__ares_timeout); ares_data.timer.repeat = 1.0; return rc; }
static void uv__read(uv_stream_t* stream) { uv_buf_t buf; ssize_t nread; struct ev_loop* ev = stream->loop->ev; /* XXX: Maybe instead of having UV_READING we just test if * tcp->read_cb is NULL or not? */ while (stream->read_cb && ((uv_handle_t*)stream)->flags & UV_READING) { assert(stream->alloc_cb); buf = stream->alloc_cb((uv_handle_t*)stream, 64 * 1024); assert(buf.len > 0); assert(buf.base); assert(stream->fd >= 0); do { nread = read(stream->fd, buf.base, buf.len); } while (nread < 0 && errno == EINTR); if (nread < 0) { /* Error */ if (errno == EAGAIN) { /* Wait for the next one. */ if (stream->flags & UV_READING) { ev_io_start(ev, &stream->read_watcher); } uv_err_new(stream->loop, EAGAIN); stream->read_cb(stream, 0, buf); return; } else { /* Error. User should call uv_close(). */ uv_err_new(stream->loop, errno); stream->read_cb(stream, -1, buf); assert(!ev_is_active(&stream->read_watcher)); return; } } else if (nread == 0) { /* EOF */ uv_err_new_artificial(stream->loop, UV_EOF); ev_io_stop(ev, &stream->read_watcher); stream->read_cb(stream, -1, buf); return; } else { /* Successful read */ stream->read_cb(stream, nread, buf); } } }
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); } } }
/* stub implementation of uv_getaddrinfo */ int uv_getaddrinfo(uv_loop_t* loop, uv_getaddrinfo_t* handle, uv_getaddrinfo_cb cb, const char* hostname, const char* service, const struct addrinfo* hints) { eio_req* req; uv_eio_init(loop); if (handle == NULL || cb == NULL || (hostname == NULL && service == NULL)) { uv_err_new_artificial(loop, UV_EINVAL); return -1; } uv__req_init((uv_req_t*)handle); handle->type = UV_GETADDRINFO; handle->loop = loop; handle->cb = cb; /* TODO don't alloc so much. */ if (hints) { handle->hints = malloc(sizeof(struct addrinfo)); memcpy(&handle->hints, hints, sizeof(struct addrinfo)); } /* TODO security! check lengths, check return values. */ handle->hostname = hostname ? strdup(hostname) : NULL; handle->service = service ? strdup(service) : NULL; handle->res = NULL; handle->retcode = 0; /* TODO check handle->hostname == NULL */ /* TODO check handle->service == NULL */ uv_ref(loop); req = eio_custom(getaddrinfo_thread_proc, EIO_PRI_DEFAULT, uv_getaddrinfo_done, handle); assert(req); assert(req->data == handle); return 0; }
int uv_pipe_bind(uv_pipe_t* handle, const char* name) { struct sockaddr_un sun; const char* pipe_fname; int saved_errno; int sockfd; int status; int bound; saved_errno = errno; pipe_fname = NULL; sockfd = -1; status = -1; bound = 0; /* Already bound? */ if (handle->fd >= 0) { uv_err_new_artificial(handle->loop, UV_EINVAL); goto out; } /* Make a copy of the file name, it outlives this function's scope. */ if ((pipe_fname = strdup(name)) == NULL) { uv_err_new(handle->loop, ENOMEM); goto out; } /* We've got a copy, don't touch the original any more. */ name = NULL; if ((sockfd = uv__socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { uv_err_new(handle->loop, errno); goto out; } memset(&sun, 0, sizeof sun); uv__strlcpy(sun.sun_path, pipe_fname, sizeof(sun.sun_path)); sun.sun_family = AF_UNIX; if (bind(sockfd, (struct sockaddr*)&sun, sizeof sun) == -1) { /* On EADDRINUSE: * * We hold the file lock so there is no other process listening * on the socket. Ergo, it's stale - remove it. * * This assumes that the other process uses locking too * but that's a good enough assumption for now. */ if (errno != EADDRINUSE || unlink(pipe_fname) == -1 || bind(sockfd, (struct sockaddr*)&sun, sizeof sun) == -1) { /* Convert ENOENT to EACCES for compatibility with Windows. */ uv_err_new(handle->loop, (errno == ENOENT) ? EACCES : errno); goto out; } } bound = 1; /* Success. */ handle->pipe_fname = pipe_fname; /* Is a strdup'ed copy. */ handle->fd = sockfd; status = 0; out: /* Clean up on error. */ if (status) { if (bound) { /* unlink() before close() to avoid races. */ assert(pipe_fname != NULL); unlink(pipe_fname); } uv__close(sockfd); free((void*)pipe_fname); } errno = saved_errno; return status; }