int uv_pipe_init(uv_loop_t* loop, uv_pipe_t* handle, int ipc) { uv_stream_init(loop, (uv_stream_t*)handle); handle->type = UV_NAMED_PIPE; handle->reqs_pending = 0; handle->handle = INVALID_HANDLE_VALUE; handle->name = NULL; handle->ipc_pid = 0; handle->remaining_ipc_rawdata_bytes = 0; handle->pending_socket_info = NULL; handle->ipc = ipc; handle->non_overlapped_writes_tail = NULL; uv_req_init(loop, (uv_req_t*) &handle->ipc_header_write_req); loop->counters.pipe_init++; return 0; }
int uv_udp_init(uv_loop_t* loop, uv_udp_t* handle) { handle->type = UV_UDP; handle->socket = INVALID_SOCKET; handle->reqs_pending = 0; handle->loop = loop; handle->flags = 0; handle->func_wsarecv = WSARecv; handle->func_wsarecvfrom = WSARecvFrom; uv_req_init(loop, (uv_req_t*) &(handle->recv_req)); handle->recv_req.type = UV_UDP_RECV; handle->recv_req.data = handle; uv_ref(loop); loop->counters.handle_init++; loop->counters.udp_init++; return 0; }
int uv_shutdown(uv_shutdown_t* req, uv_stream_t* handle, uv_shutdown_cb cb) { uv_loop_t* loop = handle->loop; if (!(handle->flags & UV_HANDLE_WRITABLE)) { return UV_EPIPE; } uv_req_init(loop, (uv_req_t*) req); req->type = UV_SHUTDOWN; req->handle = handle; req->cb = cb; handle->flags &= ~UV_HANDLE_WRITABLE; handle->stream.conn.shutdown_req = req; handle->reqs_pending++; REGISTER_HANDLE_REQ(loop, handle, req); uv_want_endgame(loop, (uv_handle_t*)handle); return 0; }
static void pipe_pinger_new() { int r; pinger_t *pinger; pinger = (pinger_t*)malloc(sizeof(*pinger)); pinger->state = 0; pinger->pongs = 0; /* Try to connec to the server and do NUM_PINGS ping-pongs. */ r = uv_pipe_init(&pinger->pipe); pinger->pipe.data = pinger; ASSERT(!r); /* We are never doing multiple reads/connects at a time anyway. */ /* so these handles can be pre-initialized. */ uv_req_init(&pinger->connect_req, (uv_handle_t*)(&pinger->pipe), (void *(*)(void *))pinger_on_connect); r = uv_pipe_connect(&pinger->connect_req, TEST_PIPENAME); ASSERT(!r); }
static void read_cb(uv_stream_t* tcp, ssize_t nread, uv_buf_t buf) { ASSERT(nested == 0 && "read_cb must be called from a fresh stack"); printf("Read. nread == %d\n", (int)nread); free(buf.base); if (nread == 0) { ASSERT(uv_last_error().code == UV_EAGAIN); return; } else if (nread == -1) { ASSERT(uv_last_error().code == UV_EOF); nested++; if (uv_close((uv_handle_t*)tcp, close_cb)) { FATAL("uv_close failed"); } nested--; return; } bytes_received += nread; /* We call shutdown here because when bytes_received == sizeof MESSAGE */ /* there will be no more data sent nor received, so here it would be */ /* possible for a backend to to call shutdown_cb immediately and *not* */ /* from a fresh stack. */ if (bytes_received == sizeof MESSAGE) { nested++; uv_req_init(&shutdown_req, (uv_handle_t*)tcp, (void *(*)(void *))shutdown_cb); puts("Shutdown"); if (uv_shutdown(&shutdown_req)) { FATAL("uv_shutdown failed"); } nested--; } }
static int uv__udp_send(uv_udp_send_t* req, uv_udp_t* handle, uv_buf_t bufs[], int bufcnt, struct sockaddr* addr, int addr_len, uv_udp_send_cb cb) { uv_loop_t* loop = handle->loop; DWORD result, bytes; uv_req_init(loop, (uv_req_t*) req); req->type = UV_UDP_SEND; req->handle = handle; req->cb = cb; memset(&req->overlapped, 0, sizeof(req->overlapped)); result = WSASendTo(handle->socket, (WSABUF*)bufs, bufcnt, &bytes, 0, addr, addr_len, &req->overlapped, NULL); if (UV_SUCCEEDED_WITHOUT_IOCP(result == 0)) { /* Request completed immediately. */ req->queued_bytes = 0; handle->reqs_pending++; REGISTER_HANDLE_REQ(loop, handle, req); uv_insert_pending_req(loop, (uv_req_t*)req); } else if (UV_SUCCEEDED_WITH_IOCP(result == 0)) { /* Request queued by the kernel. */ req->queued_bytes = uv_count_bufs(bufs, bufcnt); handle->reqs_pending++; REGISTER_HANDLE_REQ(loop, handle, req); } else { /* Send failed due to an error. */ uv__set_sys_error(loop, WSAGetLastError()); return -1; } return 0; }
static void tcp_pinger_new() { int r; struct sockaddr_in server_addr = uv_ip4_addr("127.0.0.1", TEST_PORT); pinger_t *pinger; pinger = (pinger_t*)malloc(sizeof(*pinger)); pinger->state = 0; pinger->pongs = 0; /* Try to connec to the server and do NUM_PINGS ping-pongs. */ r = uv_tcp_init(&pinger->tcp); pinger->tcp.data = pinger; ASSERT(!r); /* We are never doing multiple reads/connects at a time anyway. */ /* so these handles can be pre-initialized. */ uv_req_init(&pinger->connect_req, (uv_handle_t*)(&pinger->tcp), (void *(*)(void *))pinger_on_connect); r = uv_tcp_connect(&pinger->connect_req, server_addr); ASSERT(!r); }
static void pinger_new() { int r; struct sockaddr_in client_addr = uv_ip4_addr("0.0.0.0", 0); struct sockaddr_in server_addr = uv_ip4_addr("127.0.0.1", TEST_PORT); pinger_t *pinger; pinger = (pinger_t*)malloc(sizeof(*pinger)); pinger->state = 0; pinger->pongs = 0; /* Try to connec to the server and do NUM_PINGS ping-pongs. */ r = uv_tcp_init(&pinger->handle, pinger_close_cb, (void*)pinger); ASSERT(!r); /* We are never doing multiple reads/connects at a time anyway. */ /* so these handles can be pre-initialized. */ uv_req_init(&pinger->connect_req, &pinger->handle, pinger_connect_cb); uv_bind(&pinger->handle, (struct sockaddr*)&client_addr); r = uv_connect(&pinger->connect_req, (struct sockaddr*)&server_addr); ASSERT(!r); }
/* * Entry point for getnameinfo * return 0 if a callback will be made * return error code if validation fails */ int uv_getnameinfo(uv_loop_t* loop, uv_getnameinfo_t* req, uv_getnameinfo_cb getnameinfo_cb, const struct sockaddr* addr, int flags) { if (req == NULL || getnameinfo_cb == NULL || addr == NULL) return UV_EINVAL; if (addr->sa_family == AF_INET) { memcpy(&req->storage, addr, sizeof(struct sockaddr_in)); } else if (addr->sa_family == AF_INET6) { memcpy(&req->storage, addr, sizeof(struct sockaddr_in6)); } else { return UV_EINVAL; } uv_req_init(loop, (uv_req_t*)req); req->getnameinfo_cb = getnameinfo_cb; req->flags = flags; req->type = UV_GETNAMEINFO; req->loop = loop; /* Ask thread to run. Treat this as a long operation. */ if (QueueUserWorkItem(&getnameinfo_thread_proc, req, WT_EXECUTELONGFUNCTION) == 0) { return uv_translate_sys_error(GetLastError()); } uv__req_register(loop, req); return 0; }
static void connect_cb(uv_req_t* req, int status) { uv_buf_t buf; puts("Connected. Write some data to echo server..."); ASSERT(status == 0); ASSERT(nested == 0 && "connect_cb must be called from a fresh stack"); nested++; buf.base = (char*) &MESSAGE; buf.len = sizeof MESSAGE; uv_req_init(&write_req, req->handle, (void *(*)(void *))write_cb); if (uv_write(&write_req, &buf, 1)) { FATAL("uv_write failed"); } nested--; connect_cb_called++; }
static void pinger_read_cb(uv_tcp_t* tcp, int nread, uv_buf_t buf) { unsigned int i; pinger_t* pinger; pinger = (pinger_t*)tcp->data; if (nread < 0) { ASSERT(uv_last_error().code == UV_EOF); if (buf.base) { buf_free(buf); } ASSERT(pinger_shutdown_cb_called == 1); uv_close((uv_handle_t*)tcp); return; } /* Now we count the pings */ for (i = 0; i < nread; i++) { ASSERT(buf.base[i] == PING[pinger->state]); pinger->state = (pinger->state + 1) % (sizeof(PING) - 1); if (pinger->state == 0) { pinger->pongs++; if (uv_now() - start_time > TIME) { uv_req_init(&pinger->shutdown_req, (uv_handle_t*)tcp, pinger_shutdown_cb); uv_shutdown(&pinger->shutdown_req); break; } else { pinger_write_ping(pinger); } } } buf_free(buf); }
int uv_shutdown(uv_shutdown_t* req, uv_stream_t* handle, uv_shutdown_cb cb) { if (!(handle->flags & UV_HANDLE_CONNECTION)) { uv_set_sys_error(WSAEINVAL); return -1; } if (handle->flags & UV_HANDLE_SHUTTING) { uv_set_sys_error(WSAESHUTDOWN); return -1; } uv_req_init((uv_req_t*) req); req->type = UV_SHUTDOWN; req->handle = handle; req->cb = cb; handle->flags |= UV_HANDLE_SHUTTING; handle->shutdown_req = req; handle->reqs_pending++; uv_want_endgame((uv_handle_t*)handle); return 0; }
int uv_tcp_listen(uv_tcp_t* handle, int backlog, uv_connection_cb cb) { uv_loop_t* loop = handle->loop; unsigned int i, simultaneous_accepts; uv_tcp_accept_t* req; int err; assert(backlog > 0); if (handle->flags & UV_HANDLE_LISTENING) { handle->connection_cb = cb; } if (handle->flags & UV_HANDLE_READING) { return WSAEISCONN; } if (handle->flags & UV_HANDLE_BIND_ERROR) { return handle->bind_error; } if (!(handle->flags & UV_HANDLE_BOUND)) { err = uv_tcp_try_bind(handle, (const struct sockaddr*) &uv_addr_ip4_any_, sizeof(uv_addr_ip4_any_), 0); if (err) return err; } if (!handle->func_acceptex) { if (!uv_get_acceptex_function(handle->socket, &handle->func_acceptex)) { return WSAEAFNOSUPPORT; } } if (!(handle->flags & UV_HANDLE_SHARED_TCP_SOCKET) && listen(handle->socket, backlog) == SOCKET_ERROR) { return WSAGetLastError(); } handle->flags |= UV_HANDLE_LISTENING; handle->connection_cb = cb; INCREASE_ACTIVE_COUNT(loop, handle); simultaneous_accepts = handle->flags & UV_HANDLE_TCP_SINGLE_ACCEPT ? 1 : uv_simultaneous_server_accepts; if(!handle->accept_reqs) { handle->accept_reqs = (uv_tcp_accept_t*) malloc(uv_simultaneous_server_accepts * sizeof(uv_tcp_accept_t)); if (!handle->accept_reqs) { uv_fatal_error(ERROR_OUTOFMEMORY, "malloc"); } for (i = 0; i < simultaneous_accepts; i++) { req = &handle->accept_reqs[i]; uv_req_init(loop, (uv_req_t*)req); req->type = UV_ACCEPT; req->accept_socket = INVALID_SOCKET; req->data = handle; req->wait_handle = INVALID_HANDLE_VALUE; if (handle->flags & UV_HANDLE_EMULATE_IOCP) { req->event_handle = CreateEvent(NULL, 0, 0, NULL); if (!req->event_handle) { uv_fatal_error(GetLastError(), "CreateEvent"); } } else { req->event_handle = NULL; } uv_tcp_queue_accept(handle, req); } /* Initialize other unused requests too, because uv_tcp_endgame */ /* doesn't know how how many requests were intialized, so it will */ /* try to clean up {uv_simultaneous_server_accepts} requests. */ for (i = simultaneous_accepts; i < uv_simultaneous_server_accepts; i++) { req = &handle->accept_reqs[i]; uv_req_init(loop, (uv_req_t*) req); req->type = UV_ACCEPT; req->accept_socket = INVALID_SOCKET; req->data = handle; req->wait_handle = INVALID_HANDLE_VALUE; req->event_handle = NULL; } } return 0; }
int uv_tcp_listen(uv_tcp_t* handle, int backlog, uv_connection_cb cb) { uv_loop_t* loop = handle->loop; unsigned int i, simultaneous_accepts; uv_tcp_accept_t* req; assert(backlog > 0); if (handle->flags & UV_HANDLE_BIND_ERROR) { uv__set_sys_error(loop, handle->bind_error); return -1; } if (!(handle->flags & UV_HANDLE_BOUND) && uv_tcp_bind(handle, uv_addr_ip4_any_) < 0) return -1; if (!handle->func_acceptex) { if(!uv_get_acceptex_function(handle->socket, &handle->func_acceptex)) { uv__set_sys_error(loop, WSAEAFNOSUPPORT); return -1; } } if (!(handle->flags & UV_HANDLE_SHARED_TCP_SERVER) && listen(handle->socket, backlog) == SOCKET_ERROR) { uv__set_sys_error(loop, WSAGetLastError()); return -1; } handle->flags |= UV_HANDLE_LISTENING; handle->connection_cb = cb; simultaneous_accepts = handle->flags & UV_HANDLE_TCP_SINGLE_ACCEPT ? 1 : uv_simultaneous_server_accepts; if(!handle->accept_reqs) { handle->accept_reqs = (uv_tcp_accept_t*) malloc(simultaneous_accepts * sizeof(uv_tcp_accept_t)); if (!handle->accept_reqs) { uv_fatal_error(ERROR_OUTOFMEMORY, "malloc"); } for (i = 0; i < simultaneous_accepts; i++) { req = &handle->accept_reqs[i]; uv_req_init(loop, (uv_req_t*)req); req->type = UV_ACCEPT; req->accept_socket = INVALID_SOCKET; req->data = handle; req->wait_handle = INVALID_HANDLE_VALUE; if (handle->flags & UV_HANDLE_EMULATE_IOCP) { req->event_handle = CreateEvent(NULL, 0, 0, NULL); if (!req->event_handle) { uv_fatal_error(GetLastError(), "CreateEvent"); } } else { req->event_handle = NULL; } uv_tcp_queue_accept(handle, req); } } return 0; }
/* * Entry point for getaddrinfo * we convert the UTF-8 strings to UNICODE * and save the UNICODE string pointers in the handle * We also copy hints so that caller does not need to keep memory until the * callback. * return UV_OK if a callback will be made * return error code if validation fails * * To minimize allocation we calculate total size required, * and copy all structs and referenced strings into the one block. * Each size calculation is adjusted to avoid unaligned pointers. */ int uv_getaddrinfo(uv_loop_t* loop, uv_getaddrinfo_t* handle, uv_getaddrinfo_cb getaddrinfo_cb, const char* node, const char* service, const struct addrinfo* hints) { int nodesize = 0; int servicesize = 0; int hintssize = 0; char* alloc_ptr = NULL; if (handle == NULL || getaddrinfo_cb == NULL || (node == NULL && service == NULL)) { uv__set_sys_error(loop, WSAEINVAL); goto error; } uv_req_init(loop, (uv_req_t*)handle); handle->getaddrinfo_cb = getaddrinfo_cb; handle->res = NULL; handle->type = UV_GETADDRINFO; handle->loop = loop; /* calculate required memory size for all input values */ if (node != NULL) { nodesize = ALIGNED_SIZE(uv_utf8_to_utf16(node, NULL, 0) * sizeof(wchar_t)); if (nodesize == 0) { uv__set_sys_error(loop, GetLastError()); goto error; } } if (service != NULL) { servicesize = ALIGNED_SIZE(uv_utf8_to_utf16(service, NULL, 0) * sizeof(wchar_t)); if (servicesize == 0) { uv__set_sys_error(loop, GetLastError()); goto error; } } if (hints != NULL) { hintssize = ALIGNED_SIZE(sizeof(struct addrinfoW)); } /* allocate memory for inputs, and partition it as needed */ alloc_ptr = (char*)malloc(nodesize + servicesize + hintssize); if (!alloc_ptr) { uv__set_sys_error(loop, WSAENOBUFS); goto error; } /* save alloc_ptr now so we can free if error */ handle->alloc = (void*)alloc_ptr; /* convert node string to UTF16 into allocated memory and save pointer in */ /* handle */ if (node != NULL) { handle->node = (wchar_t*)alloc_ptr; if (uv_utf8_to_utf16(node, (wchar_t*) alloc_ptr, nodesize / sizeof(wchar_t)) == 0) { uv__set_sys_error(loop, GetLastError()); goto error; } alloc_ptr += nodesize; } else { handle->node = NULL; } /* convert service string to UTF16 into allocated memory and save pointer */ /* in handle */ if (service != NULL) { handle->service = (wchar_t*)alloc_ptr; if (uv_utf8_to_utf16(service, (wchar_t*) alloc_ptr, servicesize / sizeof(wchar_t)) == 0) { uv__set_sys_error(loop, GetLastError()); goto error; } alloc_ptr += servicesize; } else { handle->service = NULL; } /* copy hints to allocated memory and save pointer in handle */ if (hints != NULL) { handle->hints = (struct addrinfoW*)alloc_ptr; handle->hints->ai_family = hints->ai_family; handle->hints->ai_socktype = hints->ai_socktype; handle->hints->ai_protocol = hints->ai_protocol; handle->hints->ai_flags = hints->ai_flags; handle->hints->ai_addrlen = 0; handle->hints->ai_canonname = NULL; handle->hints->ai_addr = NULL; handle->hints->ai_next = NULL; } else { handle->hints = NULL; } /* init request for Post handling */ uv_req_init(loop, &handle->getadddrinfo_req); handle->getadddrinfo_req.data = handle; handle->getadddrinfo_req.type = UV_GETADDRINFO_REQ; /* Ask thread to run. Treat this as a long operation */ if (QueueUserWorkItem(&getaddrinfo_thread_proc, handle, WT_EXECUTELONGFUNCTION) == 0) { uv__set_sys_error(loop, GetLastError()); goto error; } uv_ref(loop); return 0; error: if (handle != NULL && handle->alloc != NULL) { free(handle->alloc); } return -1; }
int uv_poll_init_socket(uv_loop_t* loop, uv_poll_t* handle, uv_os_sock_t socket) { WSAPROTOCOL_INFOW protocol_info; int len; SOCKET peer_socket, base_socket; DWORD bytes; /* Try to obtain a base handle for the socket. This increases this chances */ /* that we find an AFD handle and are able to use the fast poll mechanism. */ /* This will always fail on windows XP/2k3, since they don't support the */ /* SIO_BASE_HANDLE ioctl. */ #ifndef NDEBUG base_socket = INVALID_SOCKET; #endif if (WSAIoctl(socket, SIO_BASE_HANDLE, NULL, 0, &base_socket, sizeof base_socket, &bytes, NULL, NULL) == 0) { assert(base_socket != 0 && base_socket != INVALID_SOCKET); socket = base_socket; } uv__handle_init(loop, (uv_handle_t*) handle, UV_POLL); handle->socket = socket; handle->events = 0; /* Obtain protocol information about the socket. */ len = sizeof protocol_info; if (getsockopt(socket, SOL_SOCKET, SO_PROTOCOL_INFOW, (char*) &protocol_info, &len) != 0) { uv__set_sys_error(loop, WSAGetLastError()); return -1; } /* Get the peer socket that is needed to enable fast poll. If the returned */ /* value is NULL, the protocol is not implemented by MSAFD and we'll have */ /* to use slow mode. */ peer_socket = uv__fast_poll_get_peer_socket(loop, &protocol_info); if (peer_socket != INVALID_SOCKET) { /* Initialize fast poll specific fields. */ handle->peer_socket = peer_socket; } else { /* Initialize slow poll specific fields. */ handle->flags |= UV_HANDLE_POLL_SLOW; } /* Intialize 2 poll reqs. */ handle->submitted_events_1 = 0; uv_req_init(loop, (uv_req_t*) &(handle->poll_req_1)); handle->poll_req_1.type = UV_POLL_REQ; handle->poll_req_1.data = handle; handle->submitted_events_2 = 0; uv_req_init(loop, (uv_req_t*) &(handle->poll_req_2)); handle->poll_req_2.type = UV_POLL_REQ; handle->poll_req_2.data = handle; return 0; }
static void process_req(uv_tcp_t* handle, ssize_t nread, uv_buf_t buf) { write_req_t *wr; dnshandle* dns = (dnshandle*)handle; char hdrbuf[DNSREC_LEN]; int hdrbuf_remaining = DNSREC_LEN; int rec_remaining = 0; int readbuf_remaining; char* dnsreq; char* hdrstart; int usingprev = 0; wr = (write_req_t*) malloc(sizeof *wr); uv_req_init(&wr->req, (uv_handle_t*)handle, after_write); wr->buf.base = (char*)malloc(WRITE_BUF_LEN); wr->buf.len = 0; if (dns->state.prevbuf_ptr != NULL) { dnsreq = dns->state.prevbuf_ptr + dns->state.prevbuf_pos; readbuf_remaining = dns->state.prevbuf_rem; usingprev = 1; } else { dnsreq = buf.base; readbuf_remaining = nread; } hdrstart = dnsreq; while (dnsreq != NULL) { /* something to process */ while (readbuf_remaining > 0) { /* something to process in current buffer */ if (hdrbuf_remaining > 0) { /* process len and id */ if (readbuf_remaining < hdrbuf_remaining) { /* too little to get request header. save for next buffer */ memcpy(&hdrbuf[DNSREC_LEN - hdrbuf_remaining], dnsreq, readbuf_remaining); hdrbuf_remaining = DNSREC_LEN - readbuf_remaining; break; } else { short int reclen_n; /* save header */ memcpy(&hdrbuf[DNSREC_LEN - hdrbuf_remaining], dnsreq, hdrbuf_remaining); dnsreq += hdrbuf_remaining; readbuf_remaining -= hdrbuf_remaining; hdrbuf_remaining = 0; /* get record length */ reclen_n = *((short int*)hdrbuf); rec_remaining = ntohs(reclen_n) - (DNSREC_LEN - 2); } } if (rec_remaining <= readbuf_remaining) { /* prepare reply */ addrsp(wr, hdrbuf); /* move to next record */ dnsreq += rec_remaining; hdrstart = dnsreq; readbuf_remaining -= rec_remaining; rec_remaining = 0; hdrbuf_remaining = DNSREC_LEN; } else { /* otherwise this buffer is done. */ rec_remaining -= readbuf_remaining; break; } } /* if we had to use bytes from prev buffer, start processing the current one */ if (usingprev == 1) { /* free previous buffer */ free(dns->state.prevbuf_ptr); dnsreq = buf.base; readbuf_remaining = nread; usingprev = 0; } else { dnsreq = NULL; } } /* send write buffer */ if (wr->buf.len > 0) { if (uv_write(&wr->req, &wr->buf, 1)) { FATAL("uv_write failed"); } } if (readbuf_remaining > 0) { /* save start of record position, so we can continue on next read */ dns->state.prevbuf_ptr = buf.base; dns->state.prevbuf_pos = hdrstart - buf.base; dns->state.prevbuf_rem = nread - dns->state.prevbuf_pos; } else { /* nothing left in this buffer */ dns->state.prevbuf_ptr = NULL; dns->state.prevbuf_pos = 0; dns->state.prevbuf_rem = 0; free(buf.base); } }
/* * Entry point for getaddrinfo * we convert the UTF-8 strings to UNICODE * and save the UNICODE string pointers in the req * We also copy hints so that caller does not need to keep memory until the * callback. * return 0 if a callback will be made * return error code if validation fails * * To minimize allocation we calculate total size required, * and copy all structs and referenced strings into the one block. * Each size calculation is adjusted to avoid unaligned pointers. */ int uv_getaddrinfo(uv_loop_t* loop, uv_getaddrinfo_t* req, uv_getaddrinfo_cb getaddrinfo_cb, const char* node, const char* service, const struct addrinfo* hints) { int nodesize = 0; int servicesize = 0; int hintssize = 0; char* alloc_ptr = NULL; int err; if (req == NULL || getaddrinfo_cb == NULL || (node == NULL && service == NULL)) { err = WSAEINVAL; goto error; } uv_req_init(loop, (uv_req_t*)req); req->getaddrinfo_cb = getaddrinfo_cb; req->res = NULL; req->type = UV_GETADDRINFO; req->loop = loop; req->retcode = 0; /* calculate required memory size for all input values */ if (node != NULL) { nodesize = ALIGNED_SIZE(uv_utf8_to_utf16(node, NULL, 0) * sizeof(WCHAR)); if (nodesize == 0) { err = GetLastError(); goto error; } } if (service != NULL) { servicesize = ALIGNED_SIZE(uv_utf8_to_utf16(service, NULL, 0) * sizeof(WCHAR)); if (servicesize == 0) { err = GetLastError(); goto error; } } if (hints != NULL) { hintssize = ALIGNED_SIZE(sizeof(struct addrinfoW)); } /* allocate memory for inputs, and partition it as needed */ alloc_ptr = (char*)malloc(nodesize + servicesize + hintssize); if (!alloc_ptr) { err = WSAENOBUFS; goto error; } /* save alloc_ptr now so we can free if error */ req->alloc = (void*)alloc_ptr; /* convert node string to UTF16 into allocated memory and save pointer in */ /* the reques. */ if (node != NULL) { req->node = (WCHAR*)alloc_ptr; if (uv_utf8_to_utf16(node, (WCHAR*) alloc_ptr, nodesize / sizeof(WCHAR)) == 0) { err = GetLastError(); goto error; } alloc_ptr += nodesize; } else { req->node = NULL; } /* convert service string to UTF16 into allocated memory and save pointer */ /* in the req. */ if (service != NULL) { req->service = (WCHAR*)alloc_ptr; if (uv_utf8_to_utf16(service, (WCHAR*) alloc_ptr, servicesize / sizeof(WCHAR)) == 0) { err = GetLastError(); goto error; } alloc_ptr += servicesize; } else { req->service = NULL; } /* copy hints to allocated memory and save pointer in req */ if (hints != NULL) { req->hints = (struct addrinfoW*)alloc_ptr; req->hints->ai_family = hints->ai_family; req->hints->ai_socktype = hints->ai_socktype; req->hints->ai_protocol = hints->ai_protocol; req->hints->ai_flags = hints->ai_flags; req->hints->ai_addrlen = 0; req->hints->ai_canonname = NULL; req->hints->ai_addr = NULL; req->hints->ai_next = NULL; } else { req->hints = NULL; } uv__work_submit(loop, &req->work_req, uv__getaddrinfo_work, uv__getaddrinfo_done); uv__req_register(loop, req); return 0; error: if (req != NULL && req->alloc != NULL) { free(req->alloc); } return uv_translate_sys_error(err); }
void uv_pipe_connect(uv_connect_t* req, uv_pipe_t* handle, const char* name, uv_connect_cb cb) { uv_loop_t* loop = handle->loop; int errorno, nameSize; HANDLE pipeHandle = INVALID_HANDLE_VALUE; DWORD duplex_flags; uv_req_init(loop, (uv_req_t*) req); req->type = UV_CONNECT; req->handle = (uv_stream_t*) handle; req->cb = cb; /* Convert name to UTF16. */ nameSize = uv_utf8_to_utf16(name, NULL, 0) * sizeof(WCHAR); handle->name = (WCHAR*)malloc(nameSize); if (!handle->name) { uv_fatal_error(ERROR_OUTOFMEMORY, "malloc"); } if (!uv_utf8_to_utf16(name, handle->name, nameSize / sizeof(WCHAR))) { errorno = GetLastError(); goto error; } pipeHandle = open_named_pipe(handle->name, &duplex_flags); if (pipeHandle == INVALID_HANDLE_VALUE) { if (GetLastError() == ERROR_PIPE_BUSY) { /* Wait for the server to make a pipe instance available. */ if (!QueueUserWorkItem(&pipe_connect_thread_proc, req, WT_EXECUTELONGFUNCTION)) { errorno = GetLastError(); goto error; } REGISTER_HANDLE_REQ(loop, handle, req); handle->reqs_pending++; return; } errorno = GetLastError(); goto error; } assert(pipeHandle != INVALID_HANDLE_VALUE); if (uv_set_pipe_handle(loop, (uv_pipe_t*) req->handle, pipeHandle, duplex_flags)) { errorno = GetLastError(); goto error; } SET_REQ_SUCCESS(req); uv_insert_pending_req(loop, (uv_req_t*) req); handle->reqs_pending++; REGISTER_HANDLE_REQ(loop, handle, req); return; error: if (handle->name) { free(handle->name); handle->name = NULL; } if (pipeHandle != INVALID_HANDLE_VALUE) { CloseHandle(pipeHandle); } /* Make this req pending reporting an error. */ SET_REQ_ERROR(req, errorno); uv_insert_pending_req(loop, (uv_req_t*) req); handle->reqs_pending++; REGISTER_HANDLE_REQ(loop, handle, req); return; }
/* callback from ares when socket operation is started */ static void uv_ares_sockstate_cb(void *data, ares_socket_t sock, int read, int write) { /* look to see if we have a handle for this socket in our list */ uv_loop_t* loop = (uv_loop_t*) data; uv_ares_task_t* uv_handle_ares = uv_find_ares_handle(loop, sock); if (read == 0 && write == 0) { /* if read and write are 0, cleanup existing data */ /* The code assumes that c-ares does a callback with read = 0 and */ /* write = 0 when the socket is closed. After we receive this we stop */ /* monitoring the socket. */ if (uv_handle_ares != NULL) { uv_req_t* uv_ares_req; uv_handle_ares->h_close_event = CreateEvent(NULL, FALSE, FALSE, NULL); /* remove Wait */ if (uv_handle_ares->h_wait) { UnregisterWaitEx(uv_handle_ares->h_wait, uv_handle_ares->h_close_event); uv_handle_ares->h_wait = NULL; } /* detach socket from the event */ WSAEventSelect(sock, NULL, 0); if (uv_handle_ares->h_event != WSA_INVALID_EVENT) { WSACloseEvent(uv_handle_ares->h_event); uv_handle_ares->h_event = WSA_INVALID_EVENT; } /* remove handle from list */ uv_remove_ares_handle(uv_handle_ares); /* Post request to cleanup the Task */ uv_ares_req = &uv_handle_ares->ares_req; uv_req_init(loop, uv_ares_req); uv_ares_req->type = UV_ARES_CLEANUP_REQ; uv_ares_req->data = uv_handle_ares; /* post ares done with socket - finish cleanup when all threads done. */ POST_COMPLETION_FOR_REQ(loop, uv_ares_req); } else { assert(0); uv_fatal_error(ERROR_INVALID_DATA, "ares_SockStateCB"); } } else { if (uv_handle_ares == NULL) { /* setup new handle */ /* The code assumes that c-ares will call us when it has an open socket. We need to call into c-ares when there is something to read, or when it becomes writable. */ uv_handle_ares = (uv_ares_task_t*)malloc(sizeof(uv_ares_task_t)); if (uv_handle_ares == NULL) { uv_fatal_error(ERROR_OUTOFMEMORY, "malloc"); } uv_handle_ares->type = UV_ARES_TASK; uv_handle_ares->close_cb = NULL; uv_handle_ares->loop = loop; uv_handle_ares->data = loop; uv_handle_ares->sock = sock; uv_handle_ares->h_wait = NULL; uv_handle_ares->flags = 0; /* create an event to wait on socket signal */ uv_handle_ares->h_event = WSACreateEvent(); if (uv_handle_ares->h_event == WSA_INVALID_EVENT) { uv_fatal_error(WSAGetLastError(), "WSACreateEvent"); } /* tie event to socket */ if (SOCKET_ERROR == WSAEventSelect(sock, uv_handle_ares->h_event, FD_READ | FD_WRITE | FD_CONNECT)) { uv_fatal_error(WSAGetLastError(), "WSAEventSelect"); } /* add handle to list */ uv_add_ares_handle(loop, uv_handle_ares); uv_ref(loop); /* * we have a single polling timer for all ares sockets. * This is preferred to using ares_timeout. See ares_timeout.c warning. * if timer is not running start it, and keep socket count */ if (loop->ares_active_sockets == 0) { uv_timer_init(loop, &loop->ares_polling_timer); uv_timer_start(&loop->ares_polling_timer, uv_ares_poll, 1000L, 1000L); } loop->ares_active_sockets++; /* specify thread pool function to call when event is signaled */ if (RegisterWaitForSingleObject(&uv_handle_ares->h_wait, uv_handle_ares->h_event, uv_ares_socksignal_tp, (void*)uv_handle_ares, INFINITE, WT_EXECUTEINWAITTHREAD) == 0) { uv_fatal_error(GetLastError(), "RegisterWaitForSingleObject"); } } else { /* found existing handle. */ assert(uv_handle_ares->type == UV_ARES_TASK); assert(uv_handle_ares->data != NULL); assert(uv_handle_ares->h_event != WSA_INVALID_EVENT); } } }
static int uv_tcp_try_connect(uv_connect_t* req, uv_tcp_t* handle, const struct sockaddr* addr, unsigned int addrlen, uv_connect_cb cb) { uv_loop_t* loop = handle->loop; const struct sockaddr* bind_addr; BOOL success; DWORD bytes; int err; if (handle->flags & UV_HANDLE_BIND_ERROR) { return handle->bind_error; } if (!(handle->flags & UV_HANDLE_BOUND)) { if (addrlen == sizeof(uv_addr_ip4_any_)) { bind_addr = (const struct sockaddr*) &uv_addr_ip4_any_; } else if (addrlen == sizeof(uv_addr_ip6_any_)) { bind_addr = (const struct sockaddr*) &uv_addr_ip6_any_; } else { abort(); } err = uv_tcp_try_bind(handle, bind_addr, addrlen, 0); if (err) return err; } if (!handle->func_connectex) { if (!uv_get_connectex_function(handle->socket, &handle->func_connectex)) { return WSAEAFNOSUPPORT; } } uv_req_init(loop, (uv_req_t*) req); req->type = UV_CONNECT; req->handle = (uv_stream_t*) handle; req->cb = cb; memset(&req->overlapped, 0, sizeof(req->overlapped)); success = handle->func_connectex(handle->socket, addr, addrlen, NULL, 0, &bytes, &req->overlapped); if (UV_SUCCEEDED_WITHOUT_IOCP(success)) { /* Process the req without IOCP. */ handle->reqs_pending++; REGISTER_HANDLE_REQ(loop, handle, req); uv_insert_pending_req(loop, (uv_req_t*)req); } else if (UV_SUCCEEDED_WITH_IOCP(success)) { /* The req will be processed with IOCP. */ handle->reqs_pending++; REGISTER_HANDLE_REQ(loop, handle, req); } else { return WSAGetLastError(); } return 0; }
int uv_pipe_connect(uv_connect_t* req, uv_pipe_t* handle, const char* name, uv_connect_cb cb) { int errno, nameSize; HANDLE pipeHandle; handle->handle = INVALID_HANDLE_VALUE; uv_req_init((uv_req_t*) req); req->type = UV_CONNECT; req->handle = (uv_stream_t*) handle; req->cb = cb; /* 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))) { errno = GetLastError(); goto error; } pipeHandle = CreateFileW(handle->name, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); if (pipeHandle == INVALID_HANDLE_VALUE) { if (GetLastError() == ERROR_PIPE_BUSY) { /* Wait for the server to make a pipe instance available. */ if (!QueueUserWorkItem(&pipe_connect_thread_proc, req, WT_EXECUTELONGFUNCTION)) { errno = GetLastError(); goto error; } return 0; } errno = GetLastError(); goto error; } if (uv_set_pipe_handle((uv_pipe_t*)req->handle, pipeHandle)) { errno = GetLastError(); goto error; } handle->handle = pipeHandle; req->error = uv_ok_; uv_insert_pending_req((uv_req_t*) req); handle->reqs_pending++; return 0; error: if (handle->name) { free(handle->name); handle->name = NULL; } if (pipeHandle != INVALID_HANDLE_VALUE) { CloseHandle(pipeHandle); } uv_set_sys_error(errno); return -1; }
int uv_tcp_write(uv_loop_t* loop, uv_write_t* req, uv_tcp_t* handle, uv_buf_t bufs[], int bufcnt, uv_write_cb cb) { int result; DWORD bytes; if (!(handle->flags & UV_HANDLE_CONNECTION)) { uv__set_sys_error(loop, WSAEINVAL); return -1; } if (handle->flags & UV_HANDLE_SHUTTING) { uv__set_sys_error(loop, WSAESHUTDOWN); return -1; } uv_req_init(loop, (uv_req_t*) req); req->type = UV_WRITE; req->handle = (uv_stream_t*) handle; req->cb = cb; memset(&req->overlapped, 0, sizeof(req->overlapped)); /* Prepare the overlapped structure. */ memset(&(req->overlapped), 0, sizeof(req->overlapped)); if (handle->flags & UV_HANDLE_EMULATE_IOCP) { req->event_handle = CreateEvent(NULL, 0, 0, NULL); if (!req->event_handle) { uv_fatal_error(GetLastError(), "CreateEvent"); } req->overlapped.hEvent = (HANDLE) ((ULONG_PTR) req->event_handle | 1); } result = WSASend(handle->socket, (WSABUF*)bufs, bufcnt, &bytes, 0, &req->overlapped, NULL); if (UV_SUCCEEDED_WITHOUT_IOCP(result == 0)) { /* Request completed immediately. */ req->queued_bytes = 0; handle->reqs_pending++; handle->write_reqs_pending++; uv_insert_pending_req(loop, (uv_req_t*) req); uv_ref(loop); } else if (UV_SUCCEEDED_WITH_IOCP(result == 0)) { /* Request queued by the kernel. */ req->queued_bytes = uv_count_bufs(bufs, bufcnt); handle->reqs_pending++; handle->write_reqs_pending++; handle->write_queue_size += req->queued_bytes; uv_ref(loop); if (handle->flags & UV_HANDLE_EMULATE_IOCP && req->wait_handle == INVALID_HANDLE_VALUE && !RegisterWaitForSingleObject(&req->wait_handle, req->overlapped.hEvent, post_completion, (void*) req, INFINITE, WT_EXECUTEINWAITTHREAD)) { SET_REQ_ERROR(req, GetLastError()); uv_insert_pending_req(loop, (uv_req_t*)req); } } else { /* Send failed due to an error. */ uv__set_sys_error(loop, WSAGetLastError()); return -1; } return 0; }
int uv_tcp_write(uv_loop_t* loop, uv_write_t* req, uv_tcp_t* handle, const uv_buf_t bufs[], unsigned int nbufs, uv_write_cb cb) { int result; DWORD bytes; uv_req_init(loop, (uv_req_t*) req); req->type = UV_WRITE; req->handle = (uv_stream_t*) handle; req->cb = cb; /* Prepare the overlapped structure. */ memset(&(req->overlapped), 0, sizeof(req->overlapped)); if (handle->flags & UV_HANDLE_EMULATE_IOCP) { req->event_handle = CreateEvent(NULL, 0, 0, NULL); if (!req->event_handle) { uv_fatal_error(GetLastError(), "CreateEvent"); } req->overlapped.hEvent = (HANDLE) ((DWORD) req->event_handle | 1); req->wait_handle = INVALID_HANDLE_VALUE; } result = WSASend(handle->socket, (WSABUF*) bufs, nbufs, &bytes, 0, &req->overlapped, NULL); if (UV_SUCCEEDED_WITHOUT_IOCP(result == 0)) { /* Request completed immediately. */ req->queued_bytes = 0; handle->reqs_pending++; handle->write_reqs_pending++; REGISTER_HANDLE_REQ(loop, handle, req); uv_insert_pending_req(loop, (uv_req_t*) req); } else if (UV_SUCCEEDED_WITH_IOCP(result == 0)) { /* Request queued by the kernel. */ req->queued_bytes = uv__count_bufs(bufs, nbufs); handle->reqs_pending++; handle->write_reqs_pending++; REGISTER_HANDLE_REQ(loop, handle, req); handle->write_queue_size += req->queued_bytes; if (handle->flags & UV_HANDLE_EMULATE_IOCP && !pRegisterWaitForSingleObject(&req->wait_handle, req->event_handle, post_write_completion, (void*) req, INFINITE, WT_EXECUTEINWAITTHREAD | 0x00000008/*WT_EXECUTEONLYONCE*/)) { SET_REQ_ERROR(req, GetLastError()); uv_insert_pending_req(loop, (uv_req_t*)req); } } else { /* Send failed due to an error. */ return WSAGetLastError(); } return 0; }
static int uv_pipe_write_impl(uv_loop_t* loop, uv_write_t* req, uv_pipe_t* handle, uv_buf_t bufs[], int bufcnt, uv_stream_t* send_handle, uv_write_cb cb) { int result; uv_tcp_t* tcp_send_handle; uv_write_t* ipc_header_req; uv_ipc_frame_uv_stream ipc_frame; if (bufcnt != 1 && (bufcnt != 0 || !send_handle)) { uv__set_artificial_error(loop, UV_ENOTSUP); return -1; } /* Only TCP handles are supported for sharing. */ if (send_handle && ((send_handle->type != UV_TCP) || (!(send_handle->flags & UV_HANDLE_BOUND) && !(send_handle->flags & UV_HANDLE_CONNECTION)))) { uv__set_artificial_error(loop, UV_ENOTSUP); return -1; } assert(handle->handle != INVALID_HANDLE_VALUE); uv_req_init(loop, (uv_req_t*) req); req->type = UV_WRITE; req->handle = (uv_stream_t*) handle; req->cb = cb; req->ipc_header = 0; req->event_handle = NULL; req->wait_handle = INVALID_HANDLE_VALUE; memset(&req->overlapped, 0, sizeof(req->overlapped)); if (handle->ipc) { assert(!(handle->flags & UV_HANDLE_NON_OVERLAPPED_PIPE)); ipc_frame.header.flags = 0; /* Use the IPC framing protocol. */ if (send_handle) { tcp_send_handle = (uv_tcp_t*)send_handle; if (uv_tcp_duplicate_socket(tcp_send_handle, handle->ipc_pid, &ipc_frame.socket_info)) { return -1; } ipc_frame.header.flags |= UV_IPC_TCP_SERVER; if (tcp_send_handle->flags & UV_HANDLE_CONNECTION) { ipc_frame.header.flags |= UV_IPC_TCP_CONNECTION; } } if (bufcnt == 1) { ipc_frame.header.flags |= UV_IPC_RAW_DATA; ipc_frame.header.raw_data_length = bufs[0].len; } /* * Use the provided req if we're only doing a single write. * If we're doing multiple writes, use ipc_header_write_req to do * the first write, and then use the provided req for the second write. */ if (!(ipc_frame.header.flags & UV_IPC_RAW_DATA)) { ipc_header_req = req; } else { /* * Try to use the preallocated write req if it's available. * Otherwise allocate a new one. */ if (handle->ipc_header_write_req.type != UV_WRITE) { ipc_header_req = (uv_write_t*)&handle->ipc_header_write_req; } else { ipc_header_req = (uv_write_t*)malloc(sizeof(uv_write_t)); if (!ipc_header_req) { uv_fatal_error(ERROR_OUTOFMEMORY, "malloc"); } } uv_req_init(loop, (uv_req_t*) ipc_header_req); ipc_header_req->type = UV_WRITE; ipc_header_req->handle = (uv_stream_t*) handle; ipc_header_req->cb = NULL; ipc_header_req->ipc_header = 1; } /* Write the header or the whole frame. */ memset(&ipc_header_req->overlapped, 0, sizeof(ipc_header_req->overlapped)); result = WriteFile(handle->handle, &ipc_frame, ipc_frame.header.flags & UV_IPC_TCP_SERVER ? sizeof(ipc_frame) : sizeof(ipc_frame.header), NULL, &ipc_header_req->overlapped); if (!result && GetLastError() != ERROR_IO_PENDING) { uv__set_sys_error(loop, GetLastError()); return -1; } if (result) { /* Request completed immediately. */ ipc_header_req->queued_bytes = 0; } else { /* Request queued by the kernel. */ ipc_header_req->queued_bytes = ipc_frame.header.flags & UV_IPC_TCP_SERVER ? sizeof(ipc_frame) : sizeof(ipc_frame.header); handle->write_queue_size += ipc_header_req->queued_bytes; } REGISTER_HANDLE_REQ(loop, handle, ipc_header_req); handle->reqs_pending++; handle->write_reqs_pending++; /* If we don't have any raw data to write - we're done. */ if (!(ipc_frame.header.flags & UV_IPC_RAW_DATA)) { return 0; } } if (handle->flags & UV_HANDLE_NON_OVERLAPPED_PIPE) { req->write_buffer = bufs[0]; uv_insert_non_overlapped_write_req(handle, req); if (handle->write_reqs_pending == 0) { uv_queue_non_overlapped_write(handle); } /* Request queued by the kernel. */ req->queued_bytes = uv_count_bufs(bufs, bufcnt); handle->write_queue_size += req->queued_bytes; } else { result = WriteFile(handle->handle, bufs[0].base, bufs[0].len, NULL, &req->overlapped); if (!result && GetLastError() != ERROR_IO_PENDING) { uv__set_sys_error(loop, 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; } if (handle->flags & UV_HANDLE_EMULATE_IOCP) { req->event_handle = CreateEvent(NULL, 0, 0, NULL); if (!req->event_handle) { uv_fatal_error(GetLastError(), "CreateEvent"); } if (!RegisterWaitForSingleObject(&req->wait_handle, req->overlapped.hEvent, post_completion_write_wait, (void*) req, INFINITE, WT_EXECUTEINWAITTHREAD)) { uv__set_sys_error(loop, GetLastError()); return -1; } } } REGISTER_HANDLE_REQ(loop, handle, req); handle->reqs_pending++; handle->write_reqs_pending++; return 0; }
/* Creates a pipe server. */ int uv_pipe_bind(uv_pipe_t* handle, const char* name) { uv_loop_t* loop = handle->loop; int i, errorno, nameSize; uv_pipe_accept_t* req; if (handle->flags & UV_HANDLE_BOUND) { uv__set_sys_error(loop, WSAEINVAL); return -1; } if (!name) { uv__set_sys_error(loop, WSAEINVAL); return -1; } if (!(handle->flags & UV_HANDLE_PIPESERVER)) { handle->pending_instances = default_pending_pipe_instances; } handle->accept_reqs = (uv_pipe_accept_t*) malloc(sizeof(uv_pipe_accept_t) * handle->pending_instances); if (!handle->accept_reqs) { uv_fatal_error(ERROR_OUTOFMEMORY, "malloc"); } for (i = 0; i < handle->pending_instances; i++) { req = &handle->accept_reqs[i]; uv_req_init(loop, (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); handle->name = (WCHAR*)malloc(nameSize); if (!handle->name) { uv_fatal_error(ERROR_OUTOFMEMORY, "malloc"); } if (!uv_utf8_to_utf16(name, handle->name, nameSize / sizeof(WCHAR))) { uv__set_sys_error(loop, 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) { errorno = GetLastError(); if (errorno == ERROR_ACCESS_DENIED) { uv__set_error(loop, UV_EADDRINUSE, errorno); } else if (errorno == ERROR_PATH_NOT_FOUND || errorno == ERROR_INVALID_NAME) { uv__set_error(loop, UV_EACCES, errorno); } else { uv__set_sys_error(loop, errorno); } goto error; } if (uv_set_pipe_handle(loop, handle, handle->accept_reqs[0].pipeHandle, 0)) { uv__set_sys_error(loop, GetLastError()); goto error; } handle->pending_accepts = NULL; 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; }
void uv_pipe_connect(uv_connect_t* req, uv_pipe_t* handle, const char* name, uv_connect_cb cb) { uv_loop_t* loop = handle->loop; int errno, nameSize; handle->handle = INVALID_HANDLE_VALUE; uv_req_init(loop, (uv_req_t*) req); req->type = UV_CONNECT; req->handle = (uv_stream_t*) handle; req->cb = cb; /* 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))) { errno = GetLastError(); goto error; } if (open_named_pipe(handle) != 0) { if (GetLastError() == ERROR_PIPE_BUSY) { /* Wait for the server to make a pipe instance available. */ if (!QueueUserWorkItem(&pipe_connect_thread_proc, req, WT_EXECUTELONGFUNCTION)) { errno = GetLastError(); goto error; } handle->reqs_pending++; return; } errno = GetLastError(); goto error; } assert(handle->handle != INVALID_HANDLE_VALUE); /* Ensure that what we just opened is actually a pipe */ if (!GetNamedPipeInfo(handle->handle, NULL, NULL, NULL, NULL)) { errno = WSAENOTSOCK; goto error; } if (uv_set_pipe_handle(loop, (uv_pipe_t*)req->handle, handle->handle)) { errno = GetLastError(); goto error; } SET_REQ_SUCCESS(req); uv_insert_pending_req(loop, (uv_req_t*) req); handle->reqs_pending++; return; error: if (handle->name) { free(handle->name); handle->name = NULL; } if (handle->handle != INVALID_HANDLE_VALUE) { CloseHandle(handle->handle); handle->handle = INVALID_HANDLE_VALUE; } /* Make this req pending reporting an error. */ SET_REQ_ERROR(req, errno); uv_insert_pending_req(loop, (uv_req_t*) req); handle->reqs_pending++; return; }