ws2_32: Use IOCTL_AFD_WINE_CONNECT in connect().

Signed-off-by: Zebediah Figura <z.figura12@gmail.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Zebediah Figura 2021-05-17 21:30:01 -05:00 committed by Alexandre Julliard
parent d3b6c772a5
commit a891713f48
2 changed files with 44 additions and 85 deletions

View File

@ -1145,13 +1145,6 @@ static void _get_sock_errors(SOCKET s, int *events)
SERVER_END_REQ;
}
static int get_sock_error(SOCKET s, unsigned int bit)
{
int events[FD_MAX_EVENTS];
_get_sock_errors(s, events);
return events[bit];
}
static int _get_fd_type(int fd)
{
int sock_type = -1;
@ -2976,82 +2969,65 @@ int WINAPI WS_closesocket(SOCKET s)
return res;
}
static int do_connect(int fd, const struct WS_sockaddr* name, int namelen)
/***********************************************************************
* connect (ws2_32.4)
*/
int WINAPI WS_connect( SOCKET s, const struct WS_sockaddr *addr, int len )
{
union generic_unix_sockaddr uaddr;
unsigned int uaddrlen = ws_sockaddr_ws2u(name, namelen, &uaddr);
unsigned int uaddrlen = ws_sockaddr_ws2u( addr, len, &uaddr );
struct afd_connect_params *params;
IO_STATUS_BLOCK io;
HANDLE sync_event;
NTSTATUS status;
TRACE( "socket %#lx, addr %s, len %d\n", s, debugstr_sockaddr(addr), len );
if (!uaddrlen)
return WSAEFAULT;
if (name->sa_family == WS_AF_INET)
{
struct sockaddr_in *in4 = (struct sockaddr_in*) &uaddr;
if (memcmp(&in4->sin_addr, magic_loopback_addr, 4) == 0)
SetLastError( WSAEFAULT );
return -1;
}
if (addr->sa_family == WS_AF_INET)
{
struct sockaddr_in *in4 = (struct sockaddr_in *)&uaddr;
if (!memcmp(&in4->sin_addr, magic_loopback_addr, sizeof(magic_loopback_addr)))
{
/* Trying to connect to magic replace-loopback address,
* assuming we really want to connect to localhost */
TRACE("Trying to connect to magic IP address, using "
"INADDR_LOOPBACK instead.\n");
TRACE("Replacing magic address 127.12.34.56 with INADDR_LOOPBACK.\n");
in4->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
}
}
if (connect(fd, &uaddr.addr, uaddrlen) == 0)
return 0;
if (!(sync_event = get_sync_event())) return -1;
return wsaErrno();
}
/***********************************************************************
* connect (WS2_32.4)
*/
int WINAPI WS_connect(SOCKET s, const struct WS_sockaddr* name, int namelen)
{
int fd = get_sock_fd( s, FILE_READ_DATA, NULL );
TRACE("socket %04lx, ptr %p %s, length %d\n", s, name, debugstr_sockaddr(name), namelen);
if (fd != -1)
if (!(params = HeapAlloc( GetProcessHeap(), 0, sizeof(*params) + uaddrlen )))
{
BOOL is_blocking;
int ret = do_connect(fd, name, namelen);
if (ret == 0)
goto connect_success;
if (ret == WSAEWOULDBLOCK)
{
/* tell wineserver that a connection is in progress */
_enable_event(SOCKET2HANDLE(s), FD_CONNECT|FD_READ|FD_WRITE,
FD_CONNECT,
FD_WINE_CONNECTED|FD_WINE_LISTENING);
ret = sock_is_blocking( s, &is_blocking );
if (!ret)
{
if (is_blocking)
{
do_block(fd, POLLIN | POLLOUT, -1);
_sync_sock_state(s); /* let wineserver notice connection */
/* retrieve any error codes from it */
if (!(ret = get_sock_error(s, FD_CONNECT_BIT))) goto connect_success;
}
else ret = WSAEWOULDBLOCK;
}
}
release_sock_fd( s, fd );
SetLastError(ret);
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
return -1;
}
return SOCKET_ERROR;
params->addr_len = uaddrlen;
params->synchronous = TRUE;
memcpy(params + 1, &uaddr, uaddrlen);
connect_success:
release_sock_fd( s, fd );
_enable_event(SOCKET2HANDLE(s), FD_CONNECT|FD_READ|FD_WRITE,
FD_WINE_CONNECTED|FD_READ|FD_WRITE,
FD_CONNECT|FD_WINE_LISTENING);
TRACE("\tconnected %04lx\n", s);
status = NtDeviceIoControlFile( (HANDLE)s, sync_event, NULL, NULL, &io, IOCTL_AFD_WINE_CONNECT,
params, sizeof(*params) + uaddrlen, NULL, 0);
HeapFree( GetProcessHeap(), 0, params );
if (status == STATUS_PENDING)
{
if (WaitForSingleObject( sync_event, INFINITE ) == WAIT_FAILED) return -1;
status = io.u.Status;
}
if (status)
{
SetLastError( NtStatusToWSAError( status ) );
return -1;
}
return 0;
}
/***********************************************************************
* WSAConnect (WS2_32.30)
*/

View File

@ -4159,7 +4159,7 @@ static void test_connect_events(struct event_test_ctx *ctx)
if (ctx->is_message)
check_events(ctx, FD_WRITE, 0, 200);
else
check_events_todo(ctx, FD_CONNECT, FD_WRITE, 200);
check_events(ctx, FD_CONNECT, FD_WRITE, 200);
closesocket(client);
closesocket(server);
@ -6117,25 +6117,8 @@ todo_wine
/* try to connect a socket that's being accepted into */
iret = connect(acceptor, (struct sockaddr*)&bindAddress, sizeof(bindAddress));
todo_wine ok(iret == SOCKET_ERROR && WSAGetLastError() == WSAEINVAL,
ok(iret == SOCKET_ERROR && WSAGetLastError() == WSAEINVAL,
"connecting to acceptex acceptor succeeded? return %d + errno %d\n", iret, WSAGetLastError());
if (!iret || (iret == SOCKET_ERROR && WSAGetLastError() == WSAEWOULDBLOCK)) {
/* We need to cancel this call, otherwise things fail */
closesocket(acceptor);
acceptor = socket(AF_INET, SOCK_STREAM, 0);
ok(acceptor != INVALID_SOCKET, "failed to create socket, error %u\n", GetLastError());
bret = CancelIo((HANDLE) listener);
ok(bret, "Failed to cancel failed test. Bailing...\n");
if (!bret) return;
overlapped.Internal = 0xdeadbeef;
bret = pAcceptEx(listener, acceptor, buffer, 0,
sizeof(struct sockaddr_in) + 16, sizeof(struct sockaddr_in) + 16,
&bytesReturned, &overlapped);
ok(bret == FALSE && WSAGetLastError() == ERROR_IO_PENDING, "AcceptEx returned %d + errno %d\n", bret, WSAGetLastError());
ok(overlapped.Internal == STATUS_PENDING, "got %08x\n", (ULONG)overlapped.Internal);
}
bret = pConnectEx(acceptor, (struct sockaddr *)&bindAddress, sizeof(bindAddress),
NULL, 0, &bytesReturned, &overlapped2);