mirror of
https://github.com/reactos/reactos.git
synced 2024-11-02 04:37:32 +00:00
9393fc320e
Excluded: 3rd-party code (incl. wine) and most of the win32ss.
329 lines
12 KiB
C
329 lines
12 KiB
C
/*
|
|
* PROJECT: ReactOS api tests
|
|
* LICENSE: GPL - See COPYING in the top level directory
|
|
* PURPOSE: Test for WSAAsync
|
|
* PROGRAMMERS: Miroslav Mastny
|
|
*/
|
|
|
|
#include "ws2_32.h"
|
|
|
|
#define SVR_PORT 5000
|
|
#define WAIT_TIMEOUT_ 10000
|
|
#define EXIT_FLAGS (FD_ACCEPT|FD_CONNECT)
|
|
#define MAX_LOOPCOUNT 9u
|
|
|
|
START_TEST(WSAAsync)
|
|
{
|
|
WSADATA WsaData;
|
|
SOCKET ServerSocket = INVALID_SOCKET,
|
|
ClientSocket = INVALID_SOCKET;
|
|
WSAEVENT ServerEvent = WSA_INVALID_EVENT,
|
|
ClientEvent = WSA_INVALID_EVENT;
|
|
struct hostent *ent = NULL;
|
|
struct sockaddr_in server_addr_in;
|
|
struct sockaddr_in addr_remote;
|
|
struct sockaddr_in addr_con_loc;
|
|
int nConRes, nSockNameRes;
|
|
int addrsize, len;
|
|
WSAEVENT fEvents[2];
|
|
SOCKET fSockets[2];
|
|
SOCKET sockaccept;
|
|
WSANETWORKEVENTS WsaNetworkEvents;
|
|
ULONG ulValue = 1;
|
|
DWORD dwWait;
|
|
DWORD dwFlags = 0;
|
|
struct fd_set select_rfds;
|
|
struct fd_set select_wfds;
|
|
struct fd_set select_efds;
|
|
struct timeval timeval;
|
|
BOOL ConnectSent = FALSE;
|
|
unsigned int Addr_con_locLoopCount = 0,
|
|
ServerSocketLoopCount = 0;
|
|
|
|
if (WSAStartup(MAKEWORD(2, 2), &WsaData) != 0)
|
|
{
|
|
skip("WSAStartup failed\n");
|
|
return;
|
|
}
|
|
|
|
ServerSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
|
ClientSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
|
ServerEvent = WSACreateEvent();
|
|
ClientEvent = WSACreateEvent();
|
|
|
|
if (ServerSocket == INVALID_SOCKET)
|
|
{
|
|
skip("ERROR: Server socket creation failed\n");
|
|
return;
|
|
}
|
|
if (ClientSocket == INVALID_SOCKET)
|
|
{
|
|
skip("ERROR: Client socket creation failed\n");
|
|
closesocket(ServerSocket);
|
|
return;
|
|
}
|
|
if (ServerEvent == WSA_INVALID_EVENT)
|
|
{
|
|
skip("ERROR: Server WSAEvent creation failed\n");
|
|
closesocket(ClientSocket);
|
|
closesocket(ServerSocket);
|
|
return;
|
|
}
|
|
if (ClientEvent == WSA_INVALID_EVENT)
|
|
{
|
|
skip("ERROR: Client WSAEvent creation failed\n");
|
|
WSACloseEvent(ServerEvent);
|
|
closesocket(ClientSocket);
|
|
closesocket(ServerSocket);
|
|
return;
|
|
}
|
|
ent = gethostbyname("127.0.0.1");
|
|
if (ent == NULL)
|
|
{
|
|
ok(ent != NULL, "ERROR: gethostbyname '127.0.0.1' failed, trying 'localhost'\n");
|
|
ent = gethostbyname("localhost");
|
|
|
|
if (ent == NULL)
|
|
{
|
|
skip("ERROR: gethostbyname 'localhost' failed\n");
|
|
goto done;
|
|
}
|
|
}
|
|
|
|
server_addr_in.sin_family = AF_INET;
|
|
server_addr_in.sin_port = htons(SVR_PORT);
|
|
memcpy(&server_addr_in.sin_addr.S_un.S_addr, ent->h_addr_list[0], 4);
|
|
|
|
// Server initialization.
|
|
trace("Initializing server and client connections ...\n");
|
|
ok(bind(ServerSocket, (struct sockaddr*)&server_addr_in, sizeof(server_addr_in)) == 0, "ERROR: server bind failed\n");
|
|
ok(ioctlsocket(ServerSocket, FIONBIO, &ulValue) == 0, "ERROR: server ioctlsocket FIONBIO failed\n");
|
|
ok(WSAEventSelect(ServerSocket, ServerEvent, FD_ACCEPT | FD_CLOSE) == 0, "ERROR: server accept EventSelect failed\n");
|
|
|
|
// Client initialization.
|
|
ok(WSAEventSelect(ClientSocket, ClientEvent, FD_CONNECT | FD_CLOSE) == 0, "ERROR: client EventSelect failed\n");
|
|
ok(ioctlsocket(ClientSocket, FIONBIO, &ulValue) == 0, "ERROR: client ioctlsocket FIONBIO failed\n");
|
|
|
|
// listen
|
|
trace("Starting server listening mode ...\n");
|
|
ok(listen(ServerSocket, SOMAXCONN) == 0, "ERROR: cannot initialize server listen\n");
|
|
|
|
trace("Starting client to server connection ...\n");
|
|
// connect
|
|
nConRes = connect(ClientSocket, (struct sockaddr*)&server_addr_in, sizeof(server_addr_in));
|
|
ok(nConRes == SOCKET_ERROR, "ERROR: client connect() result is not SOCKET_ERROR\n");
|
|
ok(WSAGetLastError() == WSAEWOULDBLOCK, "ERROR: client connect() last error is not WSAEWOULDBLOCK\n");
|
|
|
|
fSockets[0] = ServerSocket;
|
|
fSockets[1] = ClientSocket;
|
|
|
|
fEvents[0] = ServerEvent;
|
|
fEvents[1] = ClientEvent;
|
|
|
|
while (dwFlags != EXIT_FLAGS)
|
|
{
|
|
dwWait = WaitForMultipleObjects(2, fEvents, FALSE, WAIT_TIMEOUT_);
|
|
|
|
if (dwWait != WAIT_OBJECT_0 && // server socket event
|
|
dwWait != WAIT_OBJECT_0+1) // client socket event
|
|
{
|
|
ok(FALSE, "Unknown event received %lu\n", dwWait);
|
|
skip("ERROR: Connection timeout\n");
|
|
break;
|
|
}
|
|
|
|
WSAEnumNetworkEvents(fSockets[dwWait-WAIT_OBJECT_0], fEvents[dwWait-WAIT_OBJECT_0], &WsaNetworkEvents);
|
|
|
|
if ((WsaNetworkEvents.lNetworkEvents & FD_ACCEPT) != 0)
|
|
{// connection accepted
|
|
trace("Event FD_ACCEPT...\n");
|
|
ok(WsaNetworkEvents.iErrorCode[FD_ACCEPT_BIT] == 0, "Error on accept %d\n", WsaNetworkEvents.iErrorCode[FD_ACCEPT_BIT]);
|
|
if (WsaNetworkEvents.iErrorCode[FD_ACCEPT_BIT] == 0)
|
|
{
|
|
addrsize = sizeof(addr_remote);
|
|
sockaccept = accept(fSockets[dwWait - WAIT_OBJECT_0], (struct sockaddr*)&addr_remote, &addrsize);
|
|
ok(sockaccept != INVALID_SOCKET, "ERROR: Connection accept function failed, error %d\n", WSAGetLastError());
|
|
dwFlags |= FD_ACCEPT;
|
|
}
|
|
}
|
|
|
|
if ((WsaNetworkEvents.lNetworkEvents & FD_CONNECT) != 0)
|
|
{// client connected
|
|
trace("Event FD_CONNECT...\n");
|
|
ok(WsaNetworkEvents.iErrorCode[FD_CONNECT_BIT] == 0, "Error on connect %d\n", WsaNetworkEvents.iErrorCode[FD_CONNECT_BIT]);
|
|
if (WsaNetworkEvents.iErrorCode[FD_CONNECT_BIT] == 0)
|
|
{
|
|
len = sizeof(addr_con_loc);
|
|
ok(getsockname(fSockets[dwWait - WAIT_OBJECT_0], (struct sockaddr*)&addr_con_loc, &len) == 0, "\n");
|
|
dwFlags |= FD_CONNECT;
|
|
}
|
|
}
|
|
}
|
|
closesocket(sockaccept);
|
|
closesocket(ServerSocket);
|
|
closesocket(ClientSocket);
|
|
|
|
/* same test but with waiting select and getsockname to return proper values */
|
|
ServerSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
|
ClientSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
|
|
|
if (ServerSocket == INVALID_SOCKET)
|
|
{
|
|
skip("ERROR: Server socket creation failed\n");
|
|
return;
|
|
}
|
|
if (ClientSocket == INVALID_SOCKET)
|
|
{
|
|
skip("ERROR: Client socket creation failed\n");
|
|
closesocket(ServerSocket);
|
|
return;
|
|
}
|
|
ent = gethostbyname("127.0.0.1");
|
|
if (ent == NULL)
|
|
{
|
|
ok(ent != NULL, "ERROR: gethostbyname '127.0.0.1' failed, trying 'localhost'\n");
|
|
ent = gethostbyname("localhost");
|
|
|
|
if (ent == NULL)
|
|
{
|
|
skip("ERROR: gethostbyname 'localhost' failed\n");
|
|
goto done;
|
|
}
|
|
}
|
|
|
|
server_addr_in.sin_family = AF_INET;
|
|
server_addr_in.sin_port = htons(SVR_PORT);
|
|
memcpy(&server_addr_in.sin_addr.S_un.S_addr, ent->h_addr_list[0], 4);
|
|
|
|
// Server initialization.
|
|
trace("Initializing server and client connections ...\n");
|
|
ok(bind(ServerSocket, (struct sockaddr*)&server_addr_in, sizeof(server_addr_in)) == 0, "ERROR: server bind failed\n");
|
|
ok(ioctlsocket(ServerSocket, FIONBIO, &ulValue) == 0, "ERROR: server ioctlsocket FIONBIO failed\n");
|
|
|
|
// Client initialization.
|
|
ok(ioctlsocket(ClientSocket, FIONBIO, &ulValue) == 0, "ERROR: client ioctlsocket FIONBIO failed\n");
|
|
|
|
// listen
|
|
trace("Starting server listening mode ...\n");
|
|
ok(listen(ServerSocket, SOMAXCONN) == 0, "ERROR: cannot initialize server listen\n");
|
|
|
|
memset(&timeval, 0, sizeof(timeval));
|
|
timeval.tv_usec = WAIT_TIMEOUT_;
|
|
dwFlags = 0;
|
|
|
|
while (dwFlags != EXIT_FLAGS)
|
|
{
|
|
len = sizeof(addr_con_loc);
|
|
nSockNameRes = getsockname(ClientSocket, (struct sockaddr*)&addr_con_loc, &len);
|
|
if (dwFlags == 0 && !ConnectSent)
|
|
{
|
|
ok(nSockNameRes == SOCKET_ERROR, "ERROR: getsockname function failed, expected %d error %d\n", SOCKET_ERROR, nSockNameRes);
|
|
ok(WSAGetLastError() == WSAEINVAL, "ERROR: getsockname function failed, expected %ld error %d\n", WSAEINVAL, WSAGetLastError());
|
|
trace("Starting client to server connection ...\n");
|
|
// connect
|
|
nConRes = connect(ClientSocket, (struct sockaddr*)&server_addr_in, sizeof(server_addr_in));
|
|
ok(nConRes == SOCKET_ERROR, "ERROR: client connect() result is not SOCKET_ERROR\n");
|
|
ok(WSAGetLastError() == WSAEWOULDBLOCK, "ERROR: client connect() last error is not WSAEWOULDBLOCK\n");
|
|
ConnectSent = TRUE;
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
if (nSockNameRes != 0)
|
|
ok(FALSE, "ERROR: getsockname function failed, expected 0 error %d\n", nSockNameRes);
|
|
if (len != sizeof(addr_con_loc))
|
|
ok(FALSE, "ERROR: getsockname function wrong size, expected %Iu returned %d\n", sizeof(addr_con_loc), len);
|
|
|
|
if (addr_con_loc.sin_addr.s_addr == 0ul)
|
|
{
|
|
if (++Addr_con_locLoopCount >= MAX_LOOPCOUNT)
|
|
{
|
|
ok(FALSE, "Giving up, on getsockname() (%u/%u), as addr_con_loc is not set yet\n",
|
|
Addr_con_locLoopCount, MAX_LOOPCOUNT);
|
|
goto done;
|
|
}
|
|
|
|
trace("Looping, for getsockname() (%u/%u), as addr_con_loc is not set yet\n",
|
|
Addr_con_locLoopCount, MAX_LOOPCOUNT);
|
|
Sleep(1);
|
|
continue;
|
|
}
|
|
|
|
if (addr_con_loc.sin_addr.s_addr != server_addr_in.sin_addr.s_addr)
|
|
ok(FALSE, "ERROR: getsockname function wrong addr, expected %08lx returned %08lx\n", server_addr_in.sin_addr.s_addr, addr_con_loc.sin_addr.s_addr);
|
|
}
|
|
if ((dwFlags & FD_ACCEPT) != 0)
|
|
{// client connected
|
|
trace("Select CONNECT...\n");
|
|
dwFlags |= FD_CONNECT;
|
|
}
|
|
|
|
FD_ZERO(&select_rfds);
|
|
FD_ZERO(&select_wfds);
|
|
FD_ZERO(&select_efds);
|
|
FD_SET(ServerSocket, &select_rfds);
|
|
FD_SET(ClientSocket, &select_rfds);
|
|
FD_SET(ServerSocket, &select_wfds);
|
|
FD_SET(ClientSocket, &select_wfds);
|
|
FD_SET(ServerSocket, &select_efds);
|
|
FD_SET(ClientSocket, &select_efds);
|
|
if ((dwFlags & FD_ACCEPT) != 0)
|
|
{
|
|
FD_SET(sockaccept, &select_rfds);
|
|
FD_SET(sockaccept, &select_wfds);
|
|
FD_SET(sockaccept, &select_efds);
|
|
}
|
|
if (select(0, &select_rfds, &select_wfds, &select_efds, &timeval) != 0)
|
|
{// connection accepted
|
|
if (dwFlags == (FD_ACCEPT | FD_CONNECT))
|
|
{
|
|
trace("Select ACCEPT&CONNECT...\n");
|
|
ok(FD_ISSET(ClientSocket, &select_wfds), "ClientSocket is not writable\n");
|
|
ok(FD_ISSET(sockaccept, &select_wfds), "sockaccept is not writable\n");
|
|
ok(!FD_ISSET(ServerSocket, &select_rfds), "ServerSocket is readable\n");
|
|
}
|
|
if (dwFlags == FD_ACCEPT)
|
|
{
|
|
trace("Select ACCEPT...\n");
|
|
ok(!FD_ISSET(ClientSocket, &select_wfds), "ClientSocket is writable\n");
|
|
ok(FD_ISSET(sockaccept, &select_wfds), "sockaccept is not writable\n");
|
|
ok(FD_ISSET(ServerSocket, &select_rfds), "ServerSocket is not readable\n");
|
|
}
|
|
if (dwFlags == 0)
|
|
{
|
|
if (FD_ISSET(ServerSocket, &select_rfds))
|
|
{
|
|
trace("Select ACCEPT...\n");
|
|
addrsize = sizeof(addr_remote);
|
|
sockaccept = accept(ServerSocket, (struct sockaddr*)&addr_remote, &addrsize);
|
|
ok(sockaccept != INVALID_SOCKET, "ERROR: Connection accept function failed, error %d\n", WSAGetLastError());
|
|
dwFlags |= FD_ACCEPT;
|
|
}
|
|
else
|
|
{
|
|
if (++ServerSocketLoopCount >= MAX_LOOPCOUNT)
|
|
{
|
|
ok(FALSE, "Giving up, on select() (%u/%u), as ServerSocket is not readable yet\n",
|
|
ServerSocketLoopCount, MAX_LOOPCOUNT);
|
|
goto done;
|
|
}
|
|
|
|
trace("Looping, for select() (%u/%u), as ServerSocket is not readable yet\n",
|
|
ServerSocketLoopCount, MAX_LOOPCOUNT);
|
|
Sleep(1);
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
done:
|
|
WSACloseEvent(ServerEvent);
|
|
WSACloseEvent(ClientEvent);
|
|
closesocket(sockaccept);
|
|
closesocket(ServerSocket);
|
|
closesocket(ClientSocket);
|
|
|
|
WSACleanup();
|
|
}
|