version 1.2, 2005/03/05 00:30:41
|
version 1.5, 2005/03/07 10:59:18
|
|
|
#include <stdio.h> | #include <stdio.h> |
#include "winsock2.h" | #include "winsock2.h" |
#include "windows.h" | #include "windows.h" |
|
|
#include <wine/test.h> | #include <wine/test.h> |
#include <winbase.h> | #include <winbase.h> |
| |
/* The #pragma directives offer a way for each compiler to offer machine- |
|
and operating-system-specific features while retaining overall |
|
compatibility with the C and C++ languages. |
|
The next line places a library-search record, ws2_32, in the object file. */ |
|
// #pragma comment ( lib, "ws2_32" ) |
|
|
|
/* constants */ | /* constants */ |
#define ASYNC_EVENT (WM_USER +5) // the message we'll use for our async notification | #define ASYNC_EVENT (WM_USER +5) // the message we'll use for our async notification |
#define PORT_NUM 27015 | #define PORT_NUM 27015 |
|
|
#define MAX_WAIT_TIME 30000 // 30 seconds expressed in milliseconds | #define MAX_WAIT_TIME 30000 // 30 seconds expressed in milliseconds |
#define NUM_THREADS_TO_WAIT 2 | #define NUM_THREADS_TO_WAIT 2 |
| |
|
// macros |
|
#define eq(received, expected, label, type) \ |
|
ok((received) == (expected), "%s: got " type " instead of " type "\n", (label),(received),(expected)) |
|
|
enum // define all the exit codes for a thread | enum // define all the exit codes for a thread |
{ | { |
TH_START_ERROR = 1001, | TH_START_ERROR = 1001, |
|
|
| |
/* static func prototypes */ | /* static func prototypes */ |
static int WSAStartup_w( WORD wVersionRequired, LPWSADATA lpWSAData ); | static int WSAStartup_w( WORD wVersionRequired, LPWSADATA lpWSAData ); |
|
static int WSAAsyncSelect_w( SOCKET s, HWND hWnd, unsigned int wMsg, long lEvent ); |
static SOCKET socket_w( int af, int type, int protocol ); | static SOCKET socket_w( int af, int type, int protocol ); |
|
static int bind_w( SOCKET sock, const struct sockaddr* name, int namelen ); |
|
static int listen_w( SOCKET sock, int backlog ); |
static LRESULT CALLBACK WndProcedure(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); | static LRESULT CALLBACK WndProcedure(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); |
static HWND WineCreateWindow( HINSTANCE hInstance); | static HWND WineCreateWindow( HINSTANCE hInstance); |
static void WineThreadCleanUp(); | static void WineThreadCleanUp(); |
static void WineCreateFile(); | static void WineCreateFile(); |
static DWORD WINAPI WineRunServer(); | static DWORD WINAPI WineRunServer(); |
static DWORD WINAPI WineRunClient(); | static DWORD WINAPI WineRunClient(); |
|
static void print_buf( BOOL sent, char* buf, int max ); |
| |
/* struct def */ | /* struct def */ |
typedef struct | typedef struct |
|
|
*/ | */ |
static int WSAStartup_w( WORD wVersionRequired, LPWSADATA lpWSAData ) | static int WSAStartup_w( WORD wVersionRequired, LPWSADATA lpWSAData ) |
{ | { |
|
|
int errCode = 0; | int errCode = 0; |
| |
// WSAVERNOTSUPPORTED test | // WSAVERNOTSUPPORTED test |
WSADATA tmpLpWSAData; | WSADATA tmpLpWSAData; |
errCode = WSAStartup( MAKEWORD( 0, 0 ), &tmpLpWSAData ); | errCode = WSAStartup( MAKEWORD( 0, 0 ), &tmpLpWSAData ); |
if( errCode != WSAVERNOTSUPPORTED ) { |
|
| |
// print out the Error Code to be thorough |
// check the output |
trace( "%d: WSAVERNOTSUPPORTED test failed with error code: %d\n", __LINE__, errCode ); |
eq( errCode, WSAVERNOTSUPPORTED, "WSAStartup", "%d" ); |
errCode = 0; | errCode = 0; |
} |
|
| |
// WSEFAULT test | // WSEFAULT test |
errCode = WSAStartup( wVersionRequired, ( LPWSADATA ) 0 ); | errCode = WSAStartup( wVersionRequired, ( LPWSADATA ) 0 ); |
if( errCode != WSAEFAULT ) { |
eq( errCode, WSAEFAULT, "WSAStartup", "%d" ); |
|
|
// print out the Error Code to be thorough |
|
trace( "%d: WSAFAULT test failed with error code: %d\n", __LINE__, errCode ); |
|
errCode = 0; | errCode = 0; |
} |
|
| |
// lastly regular case - should succeed | // lastly regular case - should succeed |
errCode = WSAStartup( wVersionRequired, lpWSAData ); | errCode = WSAStartup( wVersionRequired, lpWSAData ); |
if( errCode != 0 ) { |
eq( errCode, 0, "WSAStartup", "%d" ); |
|
return errCode; |
| |
// print out the Error Code to be thorough |
|
errCode = WSAGetLastError(); |
|
trace( "%d: WSAStartup() failed with error code: %d\n", __LINE__, errCode ); |
|
} | } |
| |
return errCode; |
|
|
/* |
|
Parameters: |
|
sock |
|
[in] A descriptor that identifies the socket for which event notification is required. |
|
hwnd |
|
[in] A handle that identifies the window that will receive a message when a network event occurs. |
|
msg |
|
[in] A message to be received when a network event occurs. |
|
event |
|
[in] A bitmask that specifies a combination of network events in which the application is interested. |
|
|
|
Return Values: |
|
0 - success |
|
SOCKET_ERROR - Failure |
|
|
|
Error Code | Meaning |
|
WSANOTINITIALISED | A successful WSAStartup call must occur before using this function. |
|
WSAENETDOWN | The network subsystem failed. |
|
WSAEINVAL | One of the specified parameters was invalid, such as the window handle not referring to an |
|
| existing window, or the specified socket is in an invalid state. |
|
WSAEINPROGRESS | A blocking Windows Sockets 1.1 call is in progress, or the service provider is still processing |
|
| a callback function. |
|
WSAENOTSOCK | The descriptor is not a socket. |
|
*/ |
|
static int WSAAsyncSelect_w( SOCKET sock, HWND hwnd, unsigned int msg, long event ) |
|
{ |
|
|
|
BOOL unblocked = FALSE; |
|
|
|
// Test invalid socket |
|
int retVal = WSAAsyncSelect( -999, hwnd, msg, event ); |
|
ok( retVal == SOCKET_ERROR && WSAGetLastError() == WSAENOTSOCK, |
|
"WSAAsyncSelect: Got retVal=%d WSAGetLastError()=%d Expected retVal=%d WSAGetLastError()=%d\n", |
|
retVal, WSAGetLastError(), SOCKET_ERROR, WSAENOTSOCK ); |
|
|
|
if( retVal == 0 ) |
|
unblocked = TRUE; |
|
retVal = 0; |
|
|
|
// Test invalid window handler |
|
retVal = WSAAsyncSelect( sock, 0, msg, event ); |
|
ok( retVal == SOCKET_ERROR && WSAGetLastError() == WSAEINVAL, |
|
"WSAAsyncSelect: Got retVal=%d WSAGetLastError()=%d Expected retVal=%d WSAGetLastError()=%d\n", |
|
retVal, WSAGetLastError(), SOCKET_ERROR, WSAEINVAL ); |
|
|
|
if( retVal == 0 ) |
|
unblocked = TRUE; |
|
retVal = 0; |
|
|
|
// Test invalid event |
|
retVal = WSAAsyncSelect( sock, hwnd, msg, -999 ); |
|
ok( retVal == SOCKET_ERROR && WSAGetLastError() == WSAEINVAL, |
|
"WSAAsyncSelect: Got retVal=%d WSAGetLastError()=%d Expected retVal=%d WSAGetLastError()=%d\n", |
|
retVal, WSAGetLastError(), SOCKET_ERROR, WSAEINVAL ); |
|
|
|
if( retVal == 0 ) |
|
unblocked = TRUE; |
|
retVal = 0; |
|
|
|
// If blocked, make the socket unblocking again |
|
if( unblocked ){ |
|
|
|
trace( "Making socket blocking again\n" ); |
|
if( WSAAsyncSelect( sock, hwnd, msg, 0 ) == SOCKET_ERROR ){ |
|
trace( "WSAAsyncSelect failed to disable events %d\n", WSAGetLastError() ); |
|
return SOCKET_ERROR; |
|
} |
|
|
|
int mode = 0; |
|
if( ioctlsocket( sock, FIONBIO, (u_long FAR*) &mode ) != 0 ){ |
|
trace( "ioctlsocket failed with error code %d\n", WSAGetLastError() ); |
|
return SOCKET_ERROR; |
|
} |
|
|
|
} |
|
|
|
// normal case |
|
retVal = WSAAsyncSelect( sock, hwnd, msg, event ); |
|
eq( retVal, 0, "WSSAsyncSelect", "%d" ); |
|
return retVal; |
|
|
} | } |
| |
/* | /* |
|
Parameters: |
|
sock |
|
[in] Descriptor identifying an unbound socket. |
|
name |
|
[in] Address to assign to the socket from the sockaddr structure. |
|
namelen |
|
[in] Length of the value in the name parameter, in bytes. |
|
|
|
Return Values: |
|
0 - SUCCESS |
|
SOCKET_ERROR - FAILED |
|
|
|
Error code | Meaning |
|
WSANOTINITIALISED | A successful WSAStartup call must occur before using this function. |
|
WSAENETDOWN | The network subsystem has failed. |
|
WSAEACCES | Attempt to connect datagram socket to broadcast address failed because |
|
setsockopt option SO_BROADCAST is not enabled. |
|
WSAEADDRINUSE | A process on the computer is already bound to the same fully-qualified |
|
address and the socket has not been marked to allow address reuse with |
|
SO_REUSEADDR. For example, the IP address and port are bound in the |
|
af_inet case). (See the SO_REUSEADDR socket option under setsockopt.) |
|
WSAEADDRNOTAVAIL | The specified address is not a valid address for this computer. |
|
WSAEFAULT | The name or namelen parameter is not a valid part of the user address space, |
|
the namelen parameter is too small, the name parameter contains an incorrect |
|
address format for the associated address family, or the first two bytes of |
|
the memory block specified by name does not match the address family associated |
|
with the socket descriptor s. |
|
WSAEINPROGRESS | A blocking Windows Sockets 1.1 call is in progress, or the service provider is |
|
still processing a callback function. |
|
WSAEINVAL | The socket is already bound to an address. |
|
WSAENOBUFS | Not enough buffers available, too many connections. |
|
WSAENOTSOCK | The descriptor is not a socket. |
|
*/ |
|
static int bind_w( SOCKET sock, const struct sockaddr* name, int namelen ) |
|
{ |
|
int retVal = 0; |
|
|
|
// invalid socket |
|
retVal = bind( -999, name, namelen ); |
|
ok( retVal == SOCKET_ERROR && WSAGetLastError() == WSAENOTSOCK, |
|
"bind: Got retVal=%d WSAGetLastError()=%d Expected retVal=%d WSAGetLastError()=%d\n", |
|
retVal, WSAGetLastError(), SOCKET_ERROR, WSAENOTSOCK ); |
|
retVal = 0; |
|
|
|
// invalid address |
|
retVal = bind( sock, 0, namelen ); |
|
ok( retVal == SOCKET_ERROR && WSAGetLastError() == WSAEFAULT, |
|
"bind: Got retVal=%d WSAGetLastError()=%d Expected retVal=%d WSAGetLastError()=%d\n", |
|
retVal, WSAGetLastError(), SOCKET_ERROR, WSAEFAULT ); |
|
retVal = 0; |
|
|
|
// invalid arg |
|
retVal = bind( sock, name, -999 ); |
|
ok( retVal == SOCKET_ERROR && WSAGetLastError() == WSAEFAULT, |
|
"bind: Got retVal=%d WSAGetLastError()=%d Expected retVal=%d WSAGetLastError()=%d\n", |
|
retVal, WSAGetLastError(), SOCKET_ERROR, WSAEFAULT ); |
|
retVal = 0; |
|
|
|
// normal case |
|
retVal = bind( sock, name, namelen ); |
|
eq( retVal, 0, "bind", "%d" ); |
|
|
|
return retVal; |
|
} |
|
|
|
|
|
/* |
Wrapper for socket(). | Wrapper for socket(). |
socket() function creates a socket that is bound to a specific service provider. | socket() function creates a socket that is bound to a specific service provider. |
| |
|
|
*/ | */ |
static SOCKET socket_w( int af, int type, int protocol ) | static SOCKET socket_w( int af, int type, int protocol ) |
{ | { |
// Create a socket. |
|
SOCKET m_socket; |
SOCKET sock; |
| |
// WSAEAFNOSUPPORT test | // WSAEAFNOSUPPORT test |
m_socket = socket( -999, SOCK_STREAM, IPPROTO_TCP ); |
sock = socket( -999, SOCK_STREAM, IPPROTO_TCP ); |
if( m_socket != INVALID_SOCKET || WSAGetLastError() != WSAEAFNOSUPPORT ){ |
ok( sock == INVALID_SOCKET && WSAGetLastError() == WSAEAFNOSUPPORT, |
trace( "%d: WSAEAFNOSUPPORT test failed: %d %d\n", __LINE__, m_socket, WSAGetLastError() ); |
"socket: Got sock=%d WSAGetLastError()=%d Expected sock=%d WSAGetLastError()=%d\n", |
} |
sock, WSAGetLastError(), INVALID_SOCKET, WSAEAFNOSUPPORT ); |
| |
// WSAEPROTONOSUPPORT test | // WSAEPROTONOSUPPORT test |
m_socket = socket( AF_INET, SOCK_STREAM, -999 ); |
sock = socket( AF_INET, SOCK_STREAM, -999 ); |
if( m_socket != INVALID_SOCKET || WSAGetLastError() != WSAEPROTONOSUPPORT ){ |
ok( sock == INVALID_SOCKET && WSAGetLastError() == WSAEPROTONOSUPPORT, |
trace( "%d: WSAEPROTONOSUPPORT test failed: %d %d\n", __LINE__, m_socket, WSAGetLastError() ); |
"socket: Got sock=%d WSAGetLastError()=%d Expected sock=%d WSAGetLastError()=%d\n", |
} |
sock, WSAGetLastError(), INVALID_SOCKET, WSAEPROTONOSUPPORT ); |
| |
// WSAESOCKTNOSUPPORT test | // WSAESOCKTNOSUPPORT test |
m_socket = socket( AF_INET, -999, IPPROTO_TCP ); |
sock = socket( AF_INET, -999, IPPROTO_TCP ); |
if( m_socket != INVALID_SOCKET || WSAGetLastError() != WSAESOCKTNOSUPPORT ){ |
ok( sock == INVALID_SOCKET && WSAGetLastError() == WSAESOCKTNOSUPPORT, |
trace( "%d: WSAEPROTONOSUPPORT test failed: %d %d\n", __LINE__, m_socket, WSAGetLastError() ); |
"socket: Got sock=%d WSAGetLastError()=%d Expected sock=%d WSAGetLastError()=%d\n", |
} |
sock, WSAGetLastError(), INVALID_SOCKET, WSAESOCKTNOSUPPORT ); |
|
|
|
// check the normal case |
|
sock = socket( af, type, protocol ); |
|
ok( sock != INVALID_SOCKET, "socket: Got sock=%d\n", sock ); |
|
return sock; |
| |
m_socket = socket( af, type, protocol ); |
|
if( m_socket == INVALID_SOCKET ){ |
|
trace( "%d: Error at socket(): %d\n", __LINE__, WSAGetLastError() ); |
|
} | } |
| |
return m_socket; |
/* |
|
Test routine for listen(), a function that places a socket in a state in which it is listening for an |
|
incoming connection. |
|
Parameters: |
|
sock |
|
[in] Descriptor identifying a bound, unconnected socket. |
|
backlog |
|
[in] Maximum length of the queue of pending connections. If set to SOMAXCONN, the underlying service |
|
provider responsible for socket s will set the backlog to a maximum reasonable value. There is no standard |
|
provision to obtain the actual backlog value. |
|
|
|
Return Values: |
|
0 - success |
|
SOCKET_ERROR - failed |
|
|
|
Error code | Meaning |
|
WSANOTINITIALISED | A successful WSAStartup call must occur before using this function. |
|
WSAENETDOWN | The network subsystem has failed. |
|
WSAEADDRINUSE | The socket's local address is already in use and the socket was not marked to |
|
allow address reuse with SO_REUSEADDR. This error usually occurs during execution |
|
of the bind function, but could be delayed until this function if the bind was to a |
|
partially wildcard address (involving ADDR_ANY) and if a specific address needs to be |
|
committed at the time of this function. |
|
WSAEINPROGRESS | A blocking Windows Sockets 1.1 call is in progress, or the service provider is still |
|
processing a callback function. |
|
WSAEINVAL | The socket has not been bound with bind. |
|
WSAEISCONN | The socket is already connected. |
|
WSAEMFILE | No more socket descriptors are available. |
|
WSAENOBUFS | No buffer space is available. |
|
WSAENOTSOCK | The descriptor is not a socket. |
|
WSAEOPNOTSUPP | The referenced socket is not of a type that supports the listen operation. |
|
|
|
*/ |
|
static int listen_w( SOCKET sock, int backlog ) |
|
{ |
|
int retVal = 0; |
|
|
|
// WSAENOTSOCK test |
|
retVal = listen( -999, backlog ); |
|
ok( retVal == SOCKET_ERROR && WSAGetLastError() == WSAENOTSOCK, |
|
"listen: Got retVal=%d WSAGetLastError()=%d Expected retVal=%d WSAGetLastError()=%d\n", |
|
retVal, WSAGetLastError(), SOCKET_ERROR, WSAENOTSOCK ); |
|
retVal = 0; |
|
|
|
// normal case |
|
retVal = listen( sock, backlog ); |
|
eq( retVal, 0, "listen", "%d" ); |
|
|
|
return retVal; |
} | } |
| |
/* | /* |
|
|
eventCode = WSAGETSELECTEVENT( lParam ); | eventCode = WSAGETSELECTEVENT( lParam ); |
SOCKET socket = (SOCKET) wParam; | SOCKET socket = (SOCKET) wParam; |
SOCKET acceptSock; | SOCKET acceptSock; |
int bytesRecv = 0; |
int bytesRecv = 0, bytesTestCli = 0, bytesTestServ = 0; |
int i = 0, j = 0; |
|
char* buf; | char* buf; |
if( GetCurrentThreadId() == ServerThread.id ) | if( GetCurrentThreadId() == ServerThread.id ) |
buf = ServerThread.packet; | buf = ServerThread.packet; |
|
|
switch( eventCode ) | switch( eventCode ) |
{ | { |
case FD_ACCEPT: | case FD_ACCEPT: |
trace( "%ld accept called\n", GetCurrentThreadId() ); |
|
acceptSock = accept( socket, NULL, NULL ); | acceptSock = accept( socket, NULL, NULL ); |
if( acceptSock == INVALID_SOCKET ){ | if( acceptSock == INVALID_SOCKET ){ |
trace( "%d: accept error %d\n", __LINE__, WSAGetLastError() ); |
trace( "accept error %d\n", WSAGetLastError() ); |
closesocket( socket ); | closesocket( socket ); |
ExitThread( TH_ACCEPT_ERROR ); | ExitThread( TH_ACCEPT_ERROR ); |
} | } |
|
|
|
eq( GetCurrentThreadId(), ServerThread.id, "FD_ACCEPT", "%ld" ); |
trace( "%ld: connection accepted\n", GetCurrentThreadId() ); | trace( "%ld: connection accepted\n", GetCurrentThreadId() ); |
break; | break; |
| |
case FD_CONNECT: | case FD_CONNECT: |
| |
// a call to connect() has completed | // a call to connect() has completed |
trace("%ld CONNECTED!\n", GetCurrentThreadId() ); |
eq( GetCurrentThreadId(), ClientThread.id, "FD_CONNECT", "%ld" ); |
|
trace("%ld: connection established\n", GetCurrentThreadId() ); |
break; | break; |
| |
case FD_CLOSE: | case FD_CLOSE: |
| |
// a connection has been closed | // a connection has been closed |
closesocket( socket ); | closesocket( socket ); |
trace( "%ld: Closed socket\n", GetCurrentThreadId()); |
eq( GetCurrentThreadId(), ServerThread.id, "FD_CLOSE", "%ld" ); |
|
trace( "%ld: closed socket and exiting...\n", GetCurrentThreadId()); |
WSACleanup(); | WSACleanup(); |
ExitThread( 0 ); | ExitThread( 0 ); |
break; | break; |
|
|
// WinSock has data waiting to be read | // WinSock has data waiting to be read |
bytesRecv = recv( socket, buf, PACKET_SZ, 0 ); | bytesRecv = recv( socket, buf, PACKET_SZ, 0 ); |
| |
trace( "%ld received %d bytes: ", GetCurrentThreadId(), bytesRecv ); |
ok( bytesRecv == PACKET_SZ || bytesRecv == FILE_SZ%PACKET_SZ, |
while( i < PACKET_SZ && buf[i] != (char)EOF ){ |
"recv: Got bytesRecv=%d Expected bytesRecv=%d or %d\n", |
trace( "%c", buf[i] ); |
bytesRecv, PACKET_SZ, FILE_SZ%PACKET_SZ ); |
i++; |
trace( "Thread %ld received %d bytes\n", GetCurrentThreadId(), bytesRecv ); |
} |
|
trace( "\n" ); |
// print the bytes |
|
print_buf( FALSE, buf, PACKET_SZ ); |
|
|
| |
// Now send it back if you're the server | // Now send it back if you're the server |
if( GetCurrentThreadId() == ServerThread.id ){ | if( GetCurrentThreadId() == ServerThread.id ){ |
| |
if( send( socket, buf, bytesRecv, 0 ) == SOCKET_ERROR ){ |
// Test the bytes sent. Since we are sending small size packets |
|
// the entire packet shoudl be successfully sent. |
// check if the network buffer is full and can send no more |
// For this test, don't send any big file. |
// data. If so then break from the loop |
bytesTestServ = send( socket, buf, bytesRecv, 0 ); |
if( WSAGetLastError() == WSAEWOULDBLOCK ){ |
eq( bytesTestServ, bytesRecv, "send", "%d" ); |
// break from the loop – buffer is full |
if( bytesTestServ == SOCKET_ERROR ) |
trace( "woud block send!\n" ); |
|
break; | break; |
} |
|
else{ // another error |
|
trace(" some send error\n" ); |
|
return 0; |
|
} |
|
} |
|
| |
trace( "%ld sent back %d bytes: ", GetCurrentThreadId(), bytesRecv ); |
trace( "Thread %ld sent %d bytes\n", GetCurrentThreadId(), bytesTestServ ); |
j = 0; |
|
while( j < bytesRecv ){ |
// print the bytes |
trace( "%c", buf[j] ); |
print_buf( TRUE, buf, PACKET_SZ ); |
j++; |
|
} |
|
trace( "\n" ); |
|
| |
} | } |
else{ | else{ |
|
|
// Client: close the connection when it received back FILE_SZ | // Client: close the connection when it received back FILE_SZ |
ClientThread.bytesRecvd += bytesRecv; | ClientThread.bytesRecvd += bytesRecv; |
if( ClientThread.bytesRecvd >= FILE_SZ ){ | if( ClientThread.bytesRecvd >= FILE_SZ ){ |
trace( "%ld closing socket\n", GetCurrentThreadId() ); |
|
closesocket( socket ); | closesocket( socket ); |
|
trace( "%ld closed socket and exiting..\n", GetCurrentThreadId() ); |
WSACleanup(); | WSACleanup(); |
ResumeThread( ServerThread.handle ); |
|
ExitThread( 0 ); | ExitThread( 0 ); |
} | } |
} | } |
|
|
if( GetCurrentThreadId() == ServerThread.id ) | if( GetCurrentThreadId() == ServerThread.id ) |
break; | break; |
| |
// enter an infinite loop |
// loop until the entire file is sent |
BOOL notDone = TRUE; | BOOL notDone = TRUE; |
while( notDone ){ | while( notDone ){ |
| |
|
|
ClientThread.bytesSent += bytesToSend; | ClientThread.bytesSent += bytesToSend; |
| |
// send the packet off to the Server if it is filled | // send the packet off to the Server if it is filled |
if( send( socket, buf, bytesToSend, 0 ) == SOCKET_ERROR ){ |
// Since it will always send a small packet, the entire packet |
|
// should be sent successfully. |
|
bytesTestCli = send( socket, buf, bytesToSend, 0 ); |
| |
// check if the network buffer is full and can send no more |
eq( bytesTestCli, bytesToSend, "send", "%d" ); |
// data. If so then break from the loop |
if( bytesTestCli == SOCKET_ERROR ) |
if( WSAGetLastError() == WSAEWOULDBLOCK ){ |
|
// break from the loop – buffer is full |
|
break; | break; |
} |
|
else{ // another error |
|
return 0; |
|
} |
|
} |
|
| |
trace( "%ld sent: ", GetCurrentThreadId() ); |
trace( "Thread %ld sent %d bytes\n", GetCurrentThreadId(), bytesTestCli ); |
j = 0; |
|
while( j < PACKET_SZ && buf[j] != (char)EOF ){ |
// print the bytes |
trace( "%c", buf[j] ); |
print_buf( TRUE, buf, PACKET_SZ ); |
j++; |
|
} |
|
trace( "\n" ); |
|
} | } |
break; | break; |
} | } |
} | } |
|
|
return DefWindowProc( hWnd, msg, wParam, lParam ); | return DefWindowProc( hWnd, msg, wParam, lParam ); |
} | } |
| |
|
/* debugging function to print out the buffer */ |
|
static void print_buf( BOOL sent, char* buf, int max ) |
|
{ |
|
if( sent ) |
|
printf( "%s(%d): %ld sent: ", __FILE__, __LINE__, GetCurrentThreadId() ); |
|
else |
|
printf( "%s(%d): %ld recv: ", __FILE__, __LINE__, GetCurrentThreadId() ); |
|
|
|
int i = 0; |
|
while( i < max && buf[i] != (char)EOF ){ |
|
printf( "%c", buf[i] ); |
|
i++; |
|
} |
|
printf( "\n" ); |
|
|
|
} |
|
|
/* | /* |
Creates a hidden window object. | Creates a hidden window object. |
| |
|
|
// Create a window | // Create a window |
HWND hwnd = WineCreateWindow( hInstance ); | HWND hwnd = WineCreateWindow( hInstance ); |
if( hwnd == NULL ){ | if( hwnd == NULL ){ |
trace( "%d: Window could not be created %ld\n", __LINE__, GetLastError() ); |
trace( "Window could not be created %ld\n", GetLastError() ); |
ExitThread( TH_WINDOW_ERROR ); | ExitThread( TH_WINDOW_ERROR ); |
} | } |
| |
|
|
if( WSAStartup_w( MAKEWORD( 2, 2 ), &wsaData ) != 0 ){ | if( WSAStartup_w( MAKEWORD( 2, 2 ), &wsaData ) != 0 ){ |
| |
// print out the Error Code to be thorough | // print out the Error Code to be thorough |
trace( "%d: WSAStartup() failed with error code: %d\n", __LINE__, WSAGetLastError() ); |
trace( "WSAStartup() failed with error code: %d\n", WSAGetLastError() ); |
ExitThread( TH_START_ERROR ); | ExitThread( TH_START_ERROR ); |
} | } |
| |
// Create a socket. | // Create a socket. |
SOCKET sock = socket_w( AF_INET, SOCK_STREAM, IPPROTO_TCP );
if( sock == INVALID_SOCKET ){ |
SOCKET sock = socket_w( AF_INET, SOCK_STREAM, IPPROTO_TCP ); |
trace( "%d: socket error: %d\n", __LINE__, WSAGetLastError() ); |
if( sock == INVALID_SOCKET ){ |
|
trace( "socket error: %d\n", WSAGetLastError() ); |
ExitThread( TH_SOCKET_ERROR ); | ExitThread( TH_SOCKET_ERROR ); |
} | } |
| |
|
|
sockAddr.sin_family = AF_INET; | sockAddr.sin_family = AF_INET; |
sockAddr.sin_addr.s_addr = inet_addr( "127.0.0.1" ); | sockAddr.sin_addr.s_addr = inet_addr( "127.0.0.1" ); |
sockAddr.sin_port = htons( PORT_NUM ); | sockAddr.sin_port = htons( PORT_NUM ); |
if( bind( sock, (SOCKADDR*) &sockAddr, sizeof( sockAddr ) ) == SOCKET_ERROR ){ |
if( bind_w( sock, (SOCKADDR*) &sockAddr, sizeof( sockAddr ) ) == SOCKET_ERROR ){ |
trace( "%d: bind failed weith error code %d\n", __LINE__, WSAGetLastError() ); |
trace( "bind failed weith error code %d\n", WSAGetLastError() ); |
closesocket( sock ); | closesocket( sock ); |
ExitThread( TH_BIND_ERROR ); | ExitThread( TH_BIND_ERROR ); |
| |
} | } |
| |
// Listen on the socket. | // Listen on the socket. |
if ( listen( sock, 1 ) == SOCKET_ERROR ){ |
if( listen_w( sock, 1 ) == SOCKET_ERROR ){ |
trace( "%d: listen error with error code %d.\n", __LINE__, WSAGetLastError() ); |
trace( "listen error with error code %d.\n", WSAGetLastError() ); |
closesocket( sock );
ExitThread( TH_LISTEN_ERROR );
} |
closesocket( sock ); |
|
ExitThread( TH_LISTEN_ERROR ); |
|
} |
| |
// make the socket asynchronous and notify of read, write, connect and close events | // make the socket asynchronous and notify of read, write, connect and close events |
if( WSAAsyncSelect( sock, hwnd, ASYNC_EVENT, FD_WRITE | FD_ACCEPT |FD_READ | FD_CLOSE ) == SOCKET_ERROR ){ |
if( WSAAsyncSelect_w( sock, hwnd, ASYNC_EVENT, FD_WRITE | FD_ACCEPT |FD_READ | FD_CLOSE ) == SOCKET_ERROR ){ |
| |
trace( "%d: WSAAsyncSelect Failed %d\n", __LINE__, WSAGetLastError() ); |
trace( "WSAAsyncSelect Failed %d\n", WSAGetLastError() ); |
closesocket( sock ); | closesocket( sock ); |
ExitThread( TH_SELECT_ERROR ); | ExitThread( TH_SELECT_ERROR ); |
| |
} | } |
| |
trace( "listening and going to loop %ld\n", GetCurrentThreadId() ); |
trace( "Server socket has disabled blocking\n" ); |
| |
BOOL retVal; | BOOL retVal; |
MSG msg; | MSG msg; |
|
|
if( retVal == -1 ){ | if( retVal == -1 ){ |
| |
// handle the error and possibly exit | // handle the error and possibly exit |
trace( "%d: GetMessage error %ld\n", __LINE__, GetLastError() ); |
trace( "GetMessage error %ld\n", GetLastError() ); |
closesocket( sock ); | closesocket( sock ); |
ExitThread( TH_MSG_ERROR ); | ExitThread( TH_MSG_ERROR ); |
} | } |
| |
// suspend the other thread |
|
SuspendThread( ClientThread.handle ); |
|
|
|
// Translate and dispatch the message | // Translate and dispatch the message |
TranslateMessage( &msg ); | TranslateMessage( &msg ); |
DispatchMessage( &msg ); | DispatchMessage( &msg ); |
| |
trace( "%ld still here?\n", GetCurrentThreadId() ); |
|
|
|
ResumeThread( ClientThread.handle ); |
|
|
|
} | } |
| |
return 0; | return 0; |
|
|
// Create a window | // Create a window |
HWND hwnd = WineCreateWindow( hInstance ); | HWND hwnd = WineCreateWindow( hInstance ); |
if( hwnd == NULL ){ | if( hwnd == NULL ){ |
trace( "%d: Window could not be created %ld\n", __LINE__, GetLastError() ); |
trace( "Window could not be created %ld\n", GetLastError() ); |
ExitThread( TH_WINDOW_ERROR ); | ExitThread( TH_WINDOW_ERROR ); |
} | } |
| |
|
|
if( WSAStartup_w( MAKEWORD( 2, 2 ), &wsaData ) != 0 ){ | if( WSAStartup_w( MAKEWORD( 2, 2 ), &wsaData ) != 0 ){ |
| |
// print out the Error Code to be thorough | // print out the Error Code to be thorough |
trace( "%d: WSAStartup() failed with error code: %d\n", __LINE__, WSAGetLastError() ); |
trace( "WSAStartup() failed with error code: %d\n", WSAGetLastError() ); |
ExitThread( TH_START_ERROR ); | ExitThread( TH_START_ERROR ); |
} | } |
| |
// Create a socket. -- This is a TCP test | // Create a socket. -- This is a TCP test |
SOCKET sock = socket_w( AF_INET, SOCK_STREAM, IPPROTO_TCP ); | SOCKET sock = socket_w( AF_INET, SOCK_STREAM, IPPROTO_TCP ); |
if ( sock == INVALID_SOCKET ) { | if ( sock == INVALID_SOCKET ) { |
trace( "%d: socket returned with error code: %d\n", __LINE__, WSAGetLastError() ); |
trace( "socket returned with error code: %d\n", WSAGetLastError() ); |
ExitThread( TH_SOCKET_ERROR ); | ExitThread( TH_SOCKET_ERROR ); |
} | } |
| |
// make the socket asynchronous and notify of read, write, connect and close events | // make the socket asynchronous and notify of read, write, connect and close events |
// this is the client socket | // this is the client socket |
if( WSAAsyncSelect( sock, hwnd, ASYNC_EVENT, FD_WRITE | FD_CONNECT | FD_READ | FD_CLOSE ) == SOCKET_ERROR ){ |
if( WSAAsyncSelect_w( sock, hwnd, ASYNC_EVENT, FD_WRITE | FD_CONNECT | FD_READ | FD_CLOSE ) == SOCKET_ERROR ){ |
trace( "%d: WSAAsyncSelect Failed %d\n", __LINE__, WSAGetLastError() ); |
|
|
trace( "WSAAsyncSelect Failed %d\n", WSAGetLastError() ); |
closesocket( sock ); | closesocket( sock ); |
ExitThread( TH_SELECT_ERROR ); | ExitThread( TH_SELECT_ERROR ); |
|
|
} | } |
| |
|
trace( "Client socket has disabled blocking\n" ); |
|
|
/* connect */ | /* connect */ |
SOCKADDR_IN sockAddr; | SOCKADDR_IN sockAddr; |
sockAddr.sin_family = AF_INET; | sockAddr.sin_family = AF_INET; |
|
|
sockAddr.sin_port = htons( PORT_NUM ); | sockAddr.sin_port = htons( PORT_NUM ); |
if( connect( sock, (SOCKADDR*) &sockAddr, sizeof( sockAddr ) ) == SOCKET_ERROR ){ | if( connect( sock, (SOCKADDR*) &sockAddr, sizeof( sockAddr ) ) == SOCKET_ERROR ){ |
if( WSAGetLastError() != WSAEWOULDBLOCK ){ | if( WSAGetLastError() != WSAEWOULDBLOCK ){ |
trace( "%d: Failed to connect.: %d\n", __LINE__, WSAGetLastError() ); |
trace( "Failed to connect.: %d\n", WSAGetLastError() ); |
closesocket( sock ); | closesocket( sock ); |
ExitThread( TH_CONNECT_ERROR ); | ExitThread( TH_CONNECT_ERROR ); |
} | } |
|
|
if( retVal == -1 ){ | if( retVal == -1 ){ |
| |
// handle the error and possibly exit | // handle the error and possibly exit |
trace( "%d: GetMessage error %ld\n", __LINE__, GetLastError() ); |
trace( "GetMessage error %ld\n", GetLastError() ); |
closesocket( sock ); | closesocket( sock ); |
ExitThread( TH_MSG_ERROR ); | ExitThread( TH_MSG_ERROR ); |
} | } |
| |
SuspendThread( ServerThread.handle ); |
|
|
|
// Translate and dispatch the message | // Translate and dispatch the message |
TranslateMessage( &msg ); | TranslateMessage( &msg ); |
DispatchMessage( &msg ); | DispatchMessage( &msg ); |
| |
//trace( "%ld still here?\n", GetCurrentThreadId() ); |
|
ResumeThread( ServerThread.handle ); |
|
} | } |
return 0; | return 0; |
} | } |
|
|
| |
if( ServerThread.handle == NULL ){ | if( ServerThread.handle == NULL ){ |
| |
trace( "%d: CreateThread failed %ld\n", __LINE__, GetLastError() ); |
trace( "CreateThread failed %ld\n", GetLastError() ); |
WineThreadCleanUp(); | WineThreadCleanUp(); |
return; | return; |
} | } |
| |
trace( "%ld: server thread %ld created\n", GetCurrentThreadId(), ServerThread.id ); |
trace( "server thread %ld created. Wait %d seconds\n", ServerThread.id, SERVER_START_TIME ); |
| |
// Wait for three seconds to let server start | // Wait for three seconds to let server start |
DWORD waitRet = WaitForSingleObject( ServerThread.handle, SERVER_START_TIME ); | DWORD waitRet = WaitForSingleObject( ServerThread.handle, SERVER_START_TIME ); |
if( waitRet == WAIT_FAILED ){ | if( waitRet == WAIT_FAILED ){ |
| |
// WaitForSingleObject failed for whatever reason | // WaitForSingleObject failed for whatever reason |
trace( "%d: WaitForSingleObject failed with error code %ld\n", __LINE__, GetLastError() ); |
trace( "WaitForSingleObject failed with error code %ld\n", GetLastError() ); |
WineThreadCleanUp(); | WineThreadCleanUp(); |
return; | return; |
| |
|
|
DWORD threadStatus = 0; | DWORD threadStatus = 0; |
if( GetExitCodeThread( ServerThread.handle, &threadStatus ) == 0 ){ | if( GetExitCodeThread( ServerThread.handle, &threadStatus ) == 0 ){ |
| |
trace( "%d: GetExitCodeThread failed with error code %ld\n", __LINE__, GetLastError() ); |
trace( "GetExitCodeThread failed with error code %ld\n",GetLastError() ); |
WineThreadCleanUp(); | WineThreadCleanUp(); |
return; | return; |
| |
} | } |
| |
trace( "%ld: server started successfully now creating client thread\n", GetCurrentThreadId() ); |
if( threadStatus != STILL_ACTIVE ){ |
|
|
|
trace( "Server thread in invalid status - %ld\n", threadStatus ); |
|
WineThreadCleanUp(); |
|
return; |
|
|
|
} |
| |
// Create client thread in suspended state | // Create client thread in suspended state |
ClientThread.handle = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)WineRunClient, | ClientThread.handle = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)WineRunClient, |
|
|
| |
if( ClientThread.handle == NULL ){ | if( ClientThread.handle == NULL ){ |
| |
trace( "%d: CreateThread failed %ld\n", __LINE__, GetLastError() ); |
trace( "CreateThread failed %ld\n", GetLastError() ); |
WineThreadCleanUp(); | WineThreadCleanUp(); |
return; | return; |
} | } |
| |
trace( "%ld: client thread %ld created. Now wait.\n", GetCurrentThreadId(), ClientThread.id ); |
trace( "client thread %ld created.\n", ClientThread.id ); |
| |
// Wait for this server to suspsend itself | // Wait for this server to suspsend itself |
HANDLE threadHandles[NUM_THREADS_TO_WAIT] = { ServerThread.handle, ClientThread.handle }; | HANDLE threadHandles[NUM_THREADS_TO_WAIT] = { ServerThread.handle, ClientThread.handle }; |
|
|
if( waitRet == WAIT_FAILED ){ | if( waitRet == WAIT_FAILED ){ |
| |
// WaitForSingleObject failed for whatever reason | // WaitForSingleObject failed for whatever reason |
trace( "%d: WaitForMultipleObjects failed with error code %ld\n", __LINE__, GetLastError() ); |
trace( "WaitForMultipleObjects failed with error code %ld\n", GetLastError() ); |
WineThreadCleanUp(); | WineThreadCleanUp(); |
return; | return; |
| |
} | } |
else if( waitRet == WAIT_TIMEOUT ){ | else if( waitRet == WAIT_TIMEOUT ){ |
| |
trace( "%d: Timed out while waiting for threads to finish\n", __LINE__ ); |
trace( "Timed out while waiting for threads to finish\n" ); |
WineThreadCleanUp(); | WineThreadCleanUp(); |
return; | return; |
| |
|
|
// clean up the threads | // clean up the threads |
WineThreadCleanUp(); | WineThreadCleanUp(); |
| |
trace( "%ld: main thread exiting...\n", GetCurrentThreadId() ); |
trace( "Test completed. Main thread exiting\n" ); |
while(1); |
|
} | } |