rpcrt4: Always use winsock for networking.

Signed-off-by: Jacek Caban <jacek@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Jacek Caban 2017-05-16 17:47:50 +02:00 committed by Alexandre Julliard
parent efdb722c17
commit e6215938b7
2 changed files with 18 additions and 283 deletions

View File

@ -2,8 +2,7 @@ EXTRADEFS = -D_RPCRT4_ -DMSWMSG
MODULE = rpcrt4.dll MODULE = rpcrt4.dll
IMPORTLIB = rpcrt4 IMPORTLIB = rpcrt4
IMPORTS = uuid advapi32 IMPORTS = uuid advapi32
DELAYIMPORTS = iphlpapi wininet secur32 user32 DELAYIMPORTS = iphlpapi wininet secur32 user32 ws2_32
EXTRALIBS = $(SOCKET_LIBS)
C_SRCS = \ C_SRCS = \
cproxy.c \ cproxy.c \

View File

@ -23,62 +23,14 @@
* *
*/ */
#include "config.h" #include "ntstatus.h"
#define WIN32_NO_STATUS
#include "ws2tcpip.h"
#include <stdarg.h> #include <stdarg.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <assert.h> #include <assert.h>
#include <errno.h>
#include <stdlib.h>
#include <sys/types.h>
#include "ntstatus.h"
#define WIN32_NO_STATUS
#if defined(__MINGW32__) || defined (_MSC_VER)
# include <ws2tcpip.h>
# ifndef EADDRINUSE
# define EADDRINUSE WSAEADDRINUSE
# endif
# ifndef EAGAIN
# define EAGAIN WSAEWOULDBLOCK
# endif
# undef errno
# define errno WSAGetLastError()
#else
# include <errno.h>
# ifdef HAVE_UNISTD_H
# include <unistd.h>
# endif
# include <fcntl.h>
# ifdef HAVE_SYS_SOCKET_H
# include <sys/socket.h>
# endif
# ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
# endif
# ifdef HAVE_NETINET_TCP_H
# include <netinet/tcp.h>
# endif
# ifdef HAVE_ARPA_INET_H
# include <arpa/inet.h>
# endif
# ifdef HAVE_NETDB_H
# include <netdb.h>
# endif
# ifdef HAVE_SYS_POLL_H
# include <sys/poll.h>
# endif
# ifdef HAVE_SYS_FILIO_H
# include <sys/filio.h>
# endif
# ifdef HAVE_SYS_IOCTL_H
# include <sys/ioctl.h>
# endif
# define closesocket close
# define ioctlsocket ioctl
#endif /* defined(__MINGW32__) || defined (_MSC_VER) */
#include "windef.h" #include "windef.h"
#include "winbase.h" #include "winbase.h"
@ -99,10 +51,6 @@
#include "rpc_server.h" #include "rpc_server.h"
#include "epm_towers.h" #include "epm_towers.h"
#ifndef SOL_TCP
# define SOL_TCP IPPROTO_TCP
#endif
#define DEFAULT_NCACN_HTTP_TIMEOUT (60 * 1000) #define DEFAULT_NCACN_HTTP_TIMEOUT (60 * 1000)
#define ARRAYSIZE(a) (sizeof((a)) / sizeof((a)[0])) #define ARRAYSIZE(a) (sizeof((a)) / sizeof((a)[0]))
@ -1057,7 +1005,7 @@ static RPC_STATUS rpcrt4_ip_tcp_parse_top_of_tower(const unsigned char *tower_da
in_addr.s_addr = ipv4_floor->ipv4addr; in_addr.s_addr = ipv4_floor->ipv4addr;
if (!inet_ntop(AF_INET, &in_addr, *networkaddr, INET_ADDRSTRLEN)) if (!inet_ntop(AF_INET, &in_addr, *networkaddr, INET_ADDRSTRLEN))
{ {
ERR("inet_ntop: %s\n", strerror(errno)); ERR("inet_ntop: %u\n", WSAGetLastError());
I_RpcFree(*networkaddr); I_RpcFree(*networkaddr);
*networkaddr = NULL; *networkaddr = NULL;
if (endpoint) if (endpoint)
@ -1076,75 +1024,10 @@ typedef struct _RpcConnection_tcp
{ {
RpcConnection common; RpcConnection common;
int sock; int sock;
#ifdef HAVE_SOCKETPAIR
int cancel_fds[2];
#else
HANDLE sock_event; HANDLE sock_event;
HANDLE cancel_event; HANDLE cancel_event;
#endif
} RpcConnection_tcp; } RpcConnection_tcp;
#ifdef HAVE_SOCKETPAIR
static BOOL rpcrt4_sock_wait_init(RpcConnection_tcp *tcpc)
{
if (socketpair(PF_UNIX, SOCK_STREAM, 0, tcpc->cancel_fds) < 0)
{
ERR("socketpair() failed: %s\n", strerror(errno));
return FALSE;
}
return TRUE;
}
static BOOL rpcrt4_sock_wait_for_recv(RpcConnection_tcp *tcpc)
{
struct pollfd pfds[2];
pfds[0].fd = tcpc->sock;
pfds[0].events = POLLIN;
pfds[1].fd = tcpc->cancel_fds[0];
pfds[1].events = POLLIN;
if (poll(pfds, 2, -1 /* infinite */) == -1 && errno != EINTR)
{
ERR("poll() failed: %s\n", strerror(errno));
return FALSE;
}
if (pfds[1].revents & POLLIN) /* canceled */
{
char dummy;
read(pfds[1].fd, &dummy, sizeof(dummy));
return FALSE;
}
return TRUE;
}
static BOOL rpcrt4_sock_wait_for_send(RpcConnection_tcp *tcpc)
{
struct pollfd pfd;
pfd.fd = tcpc->sock;
pfd.events = POLLOUT;
if (poll(&pfd, 1, -1 /* infinite */) == -1 && errno != EINTR)
{
ERR("poll() failed: %s\n", strerror(errno));
return FALSE;
}
return TRUE;
}
static void rpcrt4_sock_wait_cancel(RpcConnection_tcp *tcpc)
{
char dummy = 1;
write(tcpc->cancel_fds[1], &dummy, 1);
}
static void rpcrt4_sock_wait_destroy(RpcConnection_tcp *tcpc)
{
close(tcpc->cancel_fds[0]);
close(tcpc->cancel_fds[1]);
}
#else /* HAVE_SOCKETPAIR */
static BOOL rpcrt4_sock_wait_init(RpcConnection_tcp *tcpc) static BOOL rpcrt4_sock_wait_init(RpcConnection_tcp *tcpc)
{ {
static BOOL wsa_inited; static BOOL wsa_inited;
@ -1221,8 +1104,6 @@ static void rpcrt4_sock_wait_destroy(RpcConnection_tcp *tcpc)
CloseHandle(tcpc->cancel_event); CloseHandle(tcpc->cancel_event);
} }
#endif
static RpcConnection *rpcrt4_conn_tcp_alloc(void) static RpcConnection *rpcrt4_conn_tcp_alloc(void)
{ {
RpcConnection_tcp *tcpc; RpcConnection_tcp *tcpc;
@ -1293,20 +1174,20 @@ static RPC_STATUS rpcrt4_ncacn_ip_tcp_open(RpcConnection* Connection)
sock = socket(ai_cur->ai_family, ai_cur->ai_socktype, ai_cur->ai_protocol); sock = socket(ai_cur->ai_family, ai_cur->ai_socktype, ai_cur->ai_protocol);
if (sock == -1) if (sock == -1)
{ {
WARN("socket() failed: %s\n", strerror(errno)); WARN("socket() failed: %u\n", WSAGetLastError());
continue; continue;
} }
if (0>connect(sock, ai_cur->ai_addr, ai_cur->ai_addrlen)) if (0>connect(sock, ai_cur->ai_addr, ai_cur->ai_addrlen))
{ {
WARN("connect() failed: %s\n", strerror(errno)); WARN("connect() failed: %u\n", WSAGetLastError());
closesocket(sock); closesocket(sock);
continue; continue;
} }
/* RPC depends on having minimal latency so disable the Nagle algorithm */ /* RPC depends on having minimal latency so disable the Nagle algorithm */
val = 1; val = 1;
setsockopt(sock, SOL_TCP, TCP_NODELAY, (char *)&val, sizeof(val)); setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char *)&val, sizeof(val));
nonblocking = 1; nonblocking = 1;
ioctlsocket(sock, FIONBIO, &nonblocking); ioctlsocket(sock, FIONBIO, &nonblocking);
@ -1380,7 +1261,7 @@ static RPC_STATUS rpcrt4_protseq_ncacn_ip_tcp_open_endpoint(RpcServerProtseq *pr
sock = socket(ai_cur->ai_family, ai_cur->ai_socktype, ai_cur->ai_protocol); sock = socket(ai_cur->ai_family, ai_cur->ai_socktype, ai_cur->ai_protocol);
if (sock == -1) if (sock == -1)
{ {
WARN("socket() failed: %s\n", strerror(errno)); WARN("socket() failed: %u\n", WSAGetLastError());
status = RPC_S_CANT_CREATE_ENDPOINT; status = RPC_S_CANT_CREATE_ENDPOINT;
continue; continue;
} }
@ -1388,9 +1269,9 @@ static RPC_STATUS rpcrt4_protseq_ncacn_ip_tcp_open_endpoint(RpcServerProtseq *pr
ret = bind(sock, ai_cur->ai_addr, ai_cur->ai_addrlen); ret = bind(sock, ai_cur->ai_addr, ai_cur->ai_addrlen);
if (ret < 0) if (ret < 0)
{ {
WARN("bind failed: %s\n", strerror(errno)); WARN("bind failed: %u\n", WSAGetLastError());
closesocket(sock); closesocket(sock);
if (errno == EADDRINUSE) if (WSAGetLastError() == WSAEADDRINUSE)
status = RPC_S_DUPLICATE_ENDPOINT; status = RPC_S_DUPLICATE_ENDPOINT;
else else
status = RPC_S_CANT_CREATE_ENDPOINT; status = RPC_S_CANT_CREATE_ENDPOINT;
@ -1400,7 +1281,7 @@ static RPC_STATUS rpcrt4_protseq_ncacn_ip_tcp_open_endpoint(RpcServerProtseq *pr
sa_len = sizeof(sa); sa_len = sizeof(sa);
if (getsockname(sock, (struct sockaddr *)&sa, &sa_len)) if (getsockname(sock, (struct sockaddr *)&sa, &sa_len))
{ {
WARN("getsockname() failed: %s\n", strerror(errno)); WARN("getsockname() failed: %u\n", WSAGetLastError());
closesocket(sock); closesocket(sock);
status = RPC_S_CANT_CREATE_ENDPOINT; status = RPC_S_CANT_CREATE_ENDPOINT;
continue; continue;
@ -1431,7 +1312,7 @@ static RPC_STATUS rpcrt4_protseq_ncacn_ip_tcp_open_endpoint(RpcServerProtseq *pr
ret = listen(sock, protseq->MaxCalls); ret = listen(sock, protseq->MaxCalls);
if (ret < 0) if (ret < 0)
{ {
WARN("listen failed: %s\n", strerror(errno)); WARN("listen failed: %u\n", WSAGetLastError());
RPCRT4_ReleaseConnection(&tcpc->common); RPCRT4_ReleaseConnection(&tcpc->common);
status = RPC_S_OUT_OF_RESOURCES; status = RPC_S_OUT_OF_RESOURCES;
continue; continue;
@ -1528,11 +1409,11 @@ static int rpcrt4_conn_tcp_read(RpcConnection *Connection,
return -1; return -1;
else if (r > 0) else if (r > 0)
bytes_read += r; bytes_read += r;
else if (errno == EINTR) else if (WSAGetLastError() == WSAEINTR)
continue; continue;
else if (errno != EAGAIN) else if (WSAGetLastError() != WSAEWOULDBLOCK)
{ {
WARN("recv() failed: %s\n", strerror(errno)); WARN("recv() failed: %u\n", WSAGetLastError());
return -1; return -1;
} }
else else
@ -1555,9 +1436,9 @@ static int rpcrt4_conn_tcp_write(RpcConnection *Connection,
int r = send(tcpc->sock, (const char *)buffer + bytes_written, count - bytes_written, 0); int r = send(tcpc->sock, (const char *)buffer + bytes_written, count - bytes_written, 0);
if (r >= 0) if (r >= 0)
bytes_written += r; bytes_written += r;
else if (errno == EINTR) else if (WSAGetLastError() == WSAEINTR)
continue; continue;
else if (errno != EAGAIN) else if (WSAGetLastError() != WSAEWOULDBLOCK)
return -1; return -1;
else else
{ {
@ -1614,149 +1495,6 @@ static size_t rpcrt4_ncacn_ip_tcp_get_top_of_tower(unsigned char *tower_data,
EPM_PROTOCOL_TCP, endpoint); EPM_PROTOCOL_TCP, endpoint);
} }
#ifdef HAVE_SOCKETPAIR
typedef struct _RpcServerProtseq_sock
{
RpcServerProtseq common;
int mgr_event_rcv;
int mgr_event_snd;
} RpcServerProtseq_sock;
static RpcServerProtseq *rpcrt4_protseq_sock_alloc(void)
{
RpcServerProtseq_sock *ps = HeapAlloc(GetProcessHeap(), 0, sizeof(*ps));
if (ps)
{
int fds[2];
if (!socketpair(PF_UNIX, SOCK_DGRAM, 0, fds))
{
fcntl(fds[0], F_SETFL, O_NONBLOCK);
fcntl(fds[1], F_SETFL, O_NONBLOCK);
ps->mgr_event_rcv = fds[0];
ps->mgr_event_snd = fds[1];
}
else
{
ERR("socketpair failed with error %s\n", strerror(errno));
HeapFree(GetProcessHeap(), 0, ps);
return NULL;
}
}
return &ps->common;
}
static void rpcrt4_protseq_sock_signal_state_changed(RpcServerProtseq *protseq)
{
RpcServerProtseq_sock *sockps = CONTAINING_RECORD(protseq, RpcServerProtseq_sock, common);
char dummy = 1;
write(sockps->mgr_event_snd, &dummy, sizeof(dummy));
}
static void *rpcrt4_protseq_sock_get_wait_array(RpcServerProtseq *protseq, void *prev_array, unsigned int *count)
{
struct pollfd *poll_info = prev_array;
RpcConnection_tcp *conn;
RpcServerProtseq_sock *sockps = CONTAINING_RECORD(protseq, RpcServerProtseq_sock, common);
EnterCriticalSection(&protseq->cs);
/* open and count connections */
*count = 1;
conn = (RpcConnection_tcp *)protseq->conn;
while (conn) {
if (conn->sock != -1)
(*count)++;
conn = (RpcConnection_tcp *)conn->common.Next;
}
/* make array of connections */
if (poll_info)
poll_info = HeapReAlloc(GetProcessHeap(), 0, poll_info, *count*sizeof(*poll_info));
else
poll_info = HeapAlloc(GetProcessHeap(), 0, *count*sizeof(*poll_info));
if (!poll_info)
{
ERR("couldn't allocate poll_info\n");
LeaveCriticalSection(&protseq->cs);
return NULL;
}
poll_info[0].fd = sockps->mgr_event_rcv;
poll_info[0].events = POLLIN;
*count = 1;
conn = CONTAINING_RECORD(protseq->conn, RpcConnection_tcp, common);
while (conn) {
if (conn->sock != -1)
{
poll_info[*count].fd = conn->sock;
poll_info[*count].events = POLLIN;
(*count)++;
}
conn = CONTAINING_RECORD(conn->common.Next, RpcConnection_tcp, common);
}
LeaveCriticalSection(&protseq->cs);
return poll_info;
}
static void rpcrt4_protseq_sock_free_wait_array(RpcServerProtseq *protseq, void *array)
{
HeapFree(GetProcessHeap(), 0, array);
}
static int rpcrt4_protseq_sock_wait_for_new_connection(RpcServerProtseq *protseq, unsigned int count, void *wait_array)
{
struct pollfd *poll_info = wait_array;
int ret;
unsigned int i;
RpcConnection *cconn;
RpcConnection_tcp *conn;
if (!poll_info)
return -1;
ret = poll(poll_info, count, -1);
if (ret < 0)
{
ERR("poll failed with error %d\n", ret);
return -1;
}
for (i = 0; i < count; i++)
if (poll_info[i].revents & POLLIN)
{
/* RPC server event */
if (i == 0)
{
char dummy;
read(poll_info[0].fd, &dummy, sizeof(dummy));
return 0;
}
/* find which connection got a RPC */
EnterCriticalSection(&protseq->cs);
conn = CONTAINING_RECORD(protseq->conn, RpcConnection_tcp, common);
while (conn) {
if (poll_info[i].fd == conn->sock) break;
conn = CONTAINING_RECORD(conn->common.Next, RpcConnection_tcp, common);
}
cconn = NULL;
if (conn)
RPCRT4_SpawnConnection(&cconn, &conn->common);
else
ERR("failed to locate connection for fd %d\n", poll_info[i].fd);
LeaveCriticalSection(&protseq->cs);
if (cconn)
RPCRT4_new_client(cconn);
else
return -1;
}
return 1;
}
#else /* HAVE_SOCKETPAIR */
typedef struct _RpcServerProtseq_sock typedef struct _RpcServerProtseq_sock
{ {
RpcServerProtseq common; RpcServerProtseq common;
@ -1898,8 +1636,6 @@ static int rpcrt4_protseq_sock_wait_for_new_connection(RpcServerProtseq *protseq
} }
} }
#endif /* HAVE_SOCKETPAIR */
static RPC_STATUS rpcrt4_ncacn_ip_tcp_parse_top_of_tower(const unsigned char *tower_data, static RPC_STATUS rpcrt4_ncacn_ip_tcp_parse_top_of_tower(const unsigned char *tower_data,
size_t tower_size, size_t tower_size,
char **networkaddr, char **networkaddr,