| version 1.3, 2005/03/05 01:32:48 | 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( "WSAVERNOTSUPPORTED test failed with error code: %d\n", 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( "WSAFAULT test failed with error code: %d\n", 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( "WSAStartup() failed with error code: %d\n", 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( "WSAEAFNOSUPPORT test failed: %d %d\n", 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( "WSAEPROTONOSUPPORT test failed: %d %d\n", 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( "WSAEPROTONOSUPPORT test failed: %d %d\n", 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( "Error at socket(): %d\n", 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( "accept error %d\n", 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", | 
| printf( "%c", buf[i] ); | bytesRecv, PACKET_SZ, FILE_SZ%PACKET_SZ ); | 
| i++; | trace( "Thread %ld received %d bytes\n", GetCurrentThreadId(), bytesRecv ); | 
| } |  | 
| printf( "\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 | 
| printf( "%c", buf[j] ); | print_buf( TRUE, buf, PACKET_SZ ); | 
| j++; |  | 
| } |  | 
| printf( "\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(); | 
| 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 | 
| printf( "%c", buf[j] ); | print_buf( TRUE, buf, PACKET_SZ ); | 
| j++; |  | 
| } |  | 
| printf( "\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 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 ); | 
|  | if( sock == INVALID_SOCKET ){ | 
| trace( "socket error: %d\n", WSAGetLastError() ); | 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( "bind failed weith error code %d\n", 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( "listen error with error code %d.\n", 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( "WSAAsyncSelect Failed %d\n", WSAGetLastError() ); | trace( "WSAAsyncSelect Failed %d\n", WSAGetLastError() ); | 
| closesocket( sock ); | closesocket( sock ); | 
|  |  | 
|  |  | 
| } | } | 
|  |  | 
| trace( "listening and going to loop %ld\n", GetCurrentThreadId() ); | trace( "Server socket has disabled blocking\n" ); | 
|  |  | 
| BOOL retVal; | BOOL retVal; | 
| MSG msg; | MSG msg; | 
|  |  | 
|  |  | 
| // 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( "WSAAsyncSelect Failed %d\n", 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; | 
|  |  | 
| 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 ); | 
|  |  | 
|  |  | 
| } | } | 
|  |  | 
| 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, | 
|  |  | 
| 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 }; | 
|  |  | 
| // clean up the threads | // clean up the threads | 
| WineThreadCleanUp(); | WineThreadCleanUp(); | 
|  |  | 
| trace( "%ld: main thread exiting...\n", GetCurrentThreadId() ); | trace( "Test completed.  Main thread exiting\n" ); | 
| } | } |