windows: implement uv_tcp_nodelay and uv_tcp_keepalive
This commit is contained in:
parent
0cb2213db0
commit
d15b88a935
@ -69,6 +69,8 @@ void uv_process_timers(uv_loop_t* loop);
|
||||
#define UV_HANDLE_TTY_SAVED_POSITION 0x0400000
|
||||
#define UV_HANDLE_TTY_SAVED_ATTRIBUTES 0x0800000
|
||||
#define UV_HANDLE_SHARED_TCP_SERVER 0x1000000
|
||||
#define UV_HANDLE_TCP_NODELAY 0x2000000
|
||||
#define UV_HANDLE_TCP_KEEPALIVE 0x4000000
|
||||
|
||||
void uv_want_endgame(uv_loop_t* loop, uv_handle_t* handle);
|
||||
void uv_process_endgames(uv_loop_t* loop);
|
||||
|
||||
@ -956,7 +956,9 @@ static int uv_pipe_write_impl(uv_loop_t* loop, uv_write_t* req,
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (send_handle && send_handle->type != UV_TCP) {
|
||||
/* Only TCP server handles are supported for sharing. */
|
||||
if (send_handle && (send_handle->type != UV_TCP ||
|
||||
send_handle->flags & UV_HANDLE_CONNECTION)) {
|
||||
uv__set_artificial_error(loop, UV_ENOTSUP);
|
||||
return -1;
|
||||
}
|
||||
|
||||
114
src/win/tcp.c
114
src/win/tcp.c
@ -46,6 +46,42 @@ static char uv_zero_[] = "";
|
||||
static unsigned int active_tcp_streams = 0;
|
||||
|
||||
|
||||
static int uv__tcp_nodelay(uv_tcp_t* handle, SOCKET socket, int enable) {
|
||||
if (setsockopt(socket,
|
||||
IPPROTO_TCP,
|
||||
TCP_NODELAY,
|
||||
(const char*)&enable,
|
||||
sizeof enable) == -1) {
|
||||
uv__set_sys_error(handle->loop, errno);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int uv__tcp_keepalive(uv_tcp_t* handle, SOCKET socket, int enable, unsigned int delay) {
|
||||
if (setsockopt(socket,
|
||||
SOL_SOCKET,
|
||||
SO_KEEPALIVE,
|
||||
(const char*)&enable,
|
||||
sizeof enable) == -1) {
|
||||
uv__set_sys_error(handle->loop, errno);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (enable && setsockopt(socket,
|
||||
IPPROTO_TCP,
|
||||
TCP_KEEPALIVE,
|
||||
(const char*)&delay,
|
||||
sizeof delay) == -1) {
|
||||
uv__set_sys_error(handle->loop, errno);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int uv_tcp_set_socket(uv_loop_t* loop, uv_tcp_t* handle,
|
||||
SOCKET socket, int imported) {
|
||||
DWORD yes = 1;
|
||||
@ -89,6 +125,17 @@ static int uv_tcp_set_socket(uv_loop_t* loop, uv_tcp_t* handle,
|
||||
}
|
||||
}
|
||||
|
||||
if ((handle->flags & UV_HANDLE_TCP_NODELAY) &&
|
||||
uv__tcp_nodelay(handle, socket, 1)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* TODO: Use stored delay. */
|
||||
if ((handle->flags & UV_HANDLE_TCP_KEEPALIVE) &&
|
||||
uv__tcp_keepalive(handle, socket, 1, 60)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
handle->socket = socket;
|
||||
|
||||
return 0;
|
||||
@ -961,38 +1008,61 @@ int uv_tcp_import(uv_tcp_t* tcp, WSAPROTOCOL_INFOW* socket_protocol_info) {
|
||||
|
||||
|
||||
int uv_tcp_nodelay(uv_tcp_t* handle, int enable) {
|
||||
uv__set_artificial_error(handle->loop, UV_ENOSYS);
|
||||
return -1;
|
||||
if (handle->socket != INVALID_SOCKET &&
|
||||
uv__tcp_nodelay(handle, handle->socket, enable)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (enable) {
|
||||
handle->flags |= UV_HANDLE_TCP_NODELAY;
|
||||
} else {
|
||||
handle->flags &= ~UV_HANDLE_TCP_NODELAY;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int uv_tcp_keepalive(uv_tcp_t* handle, int enable, unsigned int delay) {
|
||||
uv__set_artificial_error(handle->loop, UV_ENOSYS);
|
||||
return -1;
|
||||
if (handle->socket != INVALID_SOCKET &&
|
||||
uv__tcp_keepalive(handle, handle->socket, enable, delay)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (enable) {
|
||||
handle->flags |= UV_HANDLE_TCP_KEEPALIVE;
|
||||
} else {
|
||||
handle->flags &= ~UV_HANDLE_TCP_KEEPALIVE;
|
||||
}
|
||||
|
||||
/* TODO: Store delay if handle->socket isn't created yet. */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int uv_tcp_duplicate_socket(uv_tcp_t* handle, int pid,
|
||||
LPWSAPROTOCOL_INFOW protocol_info) {
|
||||
if (!(handle->flags & UV_HANDLE_CONNECTION)) {
|
||||
/*
|
||||
* We're about to share the socket with another process. Because
|
||||
* this is a server socket, we assume that the other process will
|
||||
* be accepting conections on this socket. So, before sharing the
|
||||
* socket with another process, we call listen here in the parent
|
||||
* process. This needs to be modified if the socket is shared with
|
||||
* another process for anything other than accepting connections.
|
||||
*/
|
||||
assert(!(handle->flags & UV_HANDLE_CONNECTION));
|
||||
|
||||
if (!(handle->flags & UV_HANDLE_LISTENING)) {
|
||||
if (!(handle->flags & UV_HANDLE_BOUND)) {
|
||||
uv__set_artificial_error(handle->loop, UV_EINVAL);
|
||||
return -1;
|
||||
}
|
||||
if (listen(handle->socket, SOMAXCONN) == SOCKET_ERROR) {
|
||||
uv__set_sys_error(handle->loop, WSAGetLastError());
|
||||
return -1;
|
||||
}
|
||||
/*
|
||||
* We're about to share the socket with another process. Because
|
||||
* this is a listening socket, we assume that the other process will
|
||||
* be accepting conections on it. So, before sharing the socket
|
||||
* with another process, we call listen here in the parent process.
|
||||
* This needs to be modified if the socket is shared with
|
||||
* another process for anything other than accepting connections.
|
||||
*/
|
||||
|
||||
if (!(handle->flags & UV_HANDLE_LISTENING)) {
|
||||
if (!(handle->flags & UV_HANDLE_BOUND)) {
|
||||
uv__set_artificial_error(handle->loop, UV_EINVAL);
|
||||
return -1;
|
||||
}
|
||||
if (listen(handle->socket, SOMAXCONN) == SOCKET_ERROR) {
|
||||
uv__set_sys_error(handle->loop, WSAGetLastError());
|
||||
return -1;
|
||||
}
|
||||
|
||||
handle->flags |= UV_HANDLE_SHARED_TCP_SERVER;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user