(file) Return to WineWinsockAsyncTest.c CVS log (file) (dir) Up to [RizwankCVS] / wine1 / wine

  1 cs130_ryutaro 1.4 #include <stdio.h>
  2                   #include "winsock2.h"
  3                   #include "windows.h"
  4                   #include <wine/test.h>
  5                   #include <winbase.h>
  6                   
  7                   /* constants */
  8                   #define ASYNC_EVENT (WM_USER +5)     // the message we'll use for our async notification
  9                   #define PORT_NUM 27015
 10                   #define PACKET_SZ 32
 11                   #define FILE_SZ 100
 12                   #define SERVER_START_TIME 3000
 13                   #define MAX_WAIT_TIME 30000 // 30 seconds expressed in milliseconds
 14                   #define NUM_THREADS_TO_WAIT 2
 15                   
 16 cs130_ryutaro 1.5 // macros
 17                   #define eq(received, expected, label, type) \
 18                           ok((received) == (expected), "%s: got " type " instead of " type "\n", (label),(received),(expected))
 19                   
 20 cs130_ryutaro 1.4 enum  // define all the exit codes for a thread
 21                     {
 22                       TH_START_ERROR = 1001,
 23                       TH_SOCKET_ERROR,
 24                       TH_SOCKADDR_ERROR,
 25                       TH_BIND_ERROR,
 26                       TH_CONNECT_ERROR,
 27                       TH_LISTEN_ERROR,
 28                       TH_ACCEPT_ERROR,
 29                       TH_SELECT_ERROR,
 30                       TH_RECV_ERROR,
 31                       TH_SEND_ERROR,
 32                       TH_WINDOW_ERROR,
 33                       TH_MSG_ERROR
 34                   
 35                     } ThreadExitCodes;
 36                   
 37                   /* static func prototypes */
 38                   static int WSAStartup_w( WORD wVersionRequired, LPWSADATA lpWSAData );
 39 cs130_ryutaro 1.5 static int WSAAsyncSelect_w( SOCKET s, HWND hWnd, unsigned int wMsg, long lEvent );
 40 cs130_ryutaro 1.4 static SOCKET socket_w( int af, int type, int protocol );
 41 cs130_ryutaro 1.5 static int bind_w( SOCKET sock, const struct sockaddr* name, int namelen );
 42                   static int listen_w( SOCKET sock, int backlog );
 43 cs130_ryutaro 1.4 static LRESULT CALLBACK WndProcedure(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
 44                   static HWND WineCreateWindow( HINSTANCE hInstance);
 45                   static void WineThreadCleanUp();
 46                   static void WineCreateFile();
 47                   static DWORD WINAPI WineRunServer();
 48                   static DWORD WINAPI WineRunClient();
 49 cs130_ryutaro 1.5 static void print_buf( BOOL sent, char* buf, int max );
 50 cs130_ryutaro 1.4 
 51                   /* struct def */
 52                   typedef struct 
 53                   {
 54                     DWORD id;
 55                     HANDLE handle;
 56                     int bytesRecvd;
 57                     int bytesSent;
 58                     char packet[PACKET_SZ];
 59                   } thread_t;
 60                   
 61                   /* global vars */
 62                   static char FileBuf[FILE_SZ];
 63                   static thread_t ServerThread;
 64                   static thread_t ClientThread;
 65                   
 66                   /* 
 67                      Wrapper for WSAStartup(). 
 68                      The WSAStartup function must be the first Windows Sockets function 
 69                      called by an application or DLL. It allows an application or DLL to 
 70                      specify the version of Windows Sockets required and retrieve details 
 71 cs130_ryutaro 1.4    of the specific Windows Sockets implementation. 
 72                   
 73                      Paremeters:
 74                      wVersionRequested 
 75                      [in] Highest version of Windows Sockets support that the caller can use. 
 76                      The high-order byte specifies the minor version (revision) number; 
 77                      the low-order byte specifies the major version number. 
 78                      lpWSAData 
 79                      [out] Pointer to the WSADATA data structure that is to receive details of 
 80                      the Windows Sockets implementation. 
 81                   
 82                      Error code          |        Meaning 
 83                      WSASYSNOTREADY      | Indicates that the underlying network subsystem is 
 84                      not ready for network communication. 
 85                      WSAVERNOTSUPPORTED  | The version of Windows Sockets support requested is 
 86                      not provided by this particular Windows Sockets 
 87                      implementation. 
 88                      WSAEINPROGRESS      | A blocking Windows Sockets 1.1 operation is in progress. 
 89                      WSAEPROCLIM         | Limit on the number of tasks supported by the Windows 
 90                      Sockets implementation has been reached. 
 91                      WSAEFAULT           | The lpWSAData is not a valid pointer. 
 92 cs130_ryutaro 1.4 */
 93                   static int WSAStartup_w( WORD wVersionRequired, LPWSADATA lpWSAData )
 94                   {
 95 cs130_ryutaro 1.5 
 96 cs130_ryutaro 1.4   int errCode = 0;
 97                   	
 98                     // WSAVERNOTSUPPORTED test
 99                     WSADATA tmpLpWSAData;
100                     errCode = WSAStartup( MAKEWORD( 0, 0 ), &tmpLpWSAData );
101                   
102 cs130_ryutaro 1.5   // check the output
103                     eq( errCode, WSAVERNOTSUPPORTED, "WSAStartup", "%d" );
104                     errCode = 0;
105 cs130_ryutaro 1.4 
106                     // WSEFAULT test
107                     errCode = WSAStartup( wVersionRequired, ( LPWSADATA ) 0 );
108 cs130_ryutaro 1.5   eq( errCode, WSAEFAULT, "WSAStartup", "%d" );
109                     errCode = 0;
110 cs130_ryutaro 1.4 
111                     // lastly regular case - should succeed
112                     errCode = WSAStartup( wVersionRequired, lpWSAData );
113 cs130_ryutaro 1.5   eq( errCode, 0, "WSAStartup", "%d" );
114                     return errCode;
115                   
116                   }
117                   
118                   
119                   /*
120                   Parameters:
121                   sock 
122                   	[in] A descriptor that identifies the socket for which event notification is required. 
123                   hwnd 
124                   	[in] A handle that identifies the window that will receive a message when a network event occurs. 
125                   msg	
126                   	[in] A message to be received when a network event occurs. 
127                   event 
128                   	[in] A bitmask that specifies a combination of network events in which the application is interested. 
129                   
130                   Return Values:
131                   0 - success 
132                   SOCKET_ERROR - Failure 
133                   
134 cs130_ryutaro 1.5 Error Code        |   Meaning
135                   WSANOTINITIALISED | A successful WSAStartup call must occur before using this function. 
136                   WSAENETDOWN       | The network subsystem failed. 
137                   WSAEINVAL         | One of the specified parameters was invalid, such as the window handle not referring to an 
138                   		  | 	existing window, or the specified socket is in an invalid state. 
139                   WSAEINPROGRESS    | A blocking Windows Sockets 1.1 call is in progress, or the service provider is still processing 
140                   		  | 	a callback function. 
141                   WSAENOTSOCK       | The descriptor is not a socket. 
142                   */
143                   static int WSAAsyncSelect_w( SOCKET sock, HWND hwnd, unsigned int msg, long event )
144                   {
145                   
146                     BOOL unblocked = FALSE;
147                   
148                     // Test invalid socket
149                     int retVal = WSAAsyncSelect( -999, hwnd, msg, event );
150                     ok( retVal == SOCKET_ERROR && WSAGetLastError() == WSAENOTSOCK, 
151                         "WSAAsyncSelect: Got retVal=%d WSAGetLastError()=%d Expected retVal=%d WSAGetLastError()=%d\n",
152                         retVal, WSAGetLastError(), SOCKET_ERROR, WSAENOTSOCK );
153                   
154                     if( retVal == 0 )
155 cs130_ryutaro 1.5     unblocked = TRUE;
156                     retVal = 0;
157                   
158                     // Test invalid window handler
159                     retVal = WSAAsyncSelect( sock, 0, msg, event );
160                     ok( retVal == SOCKET_ERROR && WSAGetLastError() == WSAEINVAL, 
161                         "WSAAsyncSelect: Got retVal=%d WSAGetLastError()=%d Expected retVal=%d WSAGetLastError()=%d\n",
162                         retVal, WSAGetLastError(), SOCKET_ERROR, WSAEINVAL );
163                   
164                     if( retVal == 0 )
165                       unblocked = TRUE;
166                     retVal = 0;
167                   
168                     // Test invalid event
169                     retVal = WSAAsyncSelect( sock, hwnd, msg, -999 );
170                     ok( retVal == SOCKET_ERROR && WSAGetLastError() == WSAEINVAL, 
171                         "WSAAsyncSelect: Got retVal=%d WSAGetLastError()=%d Expected retVal=%d WSAGetLastError()=%d\n",
172                         retVal, WSAGetLastError(), SOCKET_ERROR, WSAEINVAL );
173                   
174                     if( retVal == 0 )
175                       unblocked = TRUE;
176 cs130_ryutaro 1.5   retVal = 0;
177                   
178                     // If blocked, make the socket unblocking again
179                     if( unblocked ){
180                       
181                       trace( "Making socket blocking again\n" );
182                       if( WSAAsyncSelect( sock, hwnd, msg, 0 ) == SOCKET_ERROR ){
183                         trace( "WSAAsyncSelect failed to disable events %d\n", WSAGetLastError() );
184                         return SOCKET_ERROR;
185                       }
186                   
187                       int mode = 0;
188                       if( ioctlsocket( sock, FIONBIO, (u_long FAR*) &mode ) != 0 ){
189                         trace( "ioctlsocket failed with error code %d\n", WSAGetLastError() );
190                         return SOCKET_ERROR;
191                       }
192 cs130_ryutaro 1.4 
193                     }
194                   
195 cs130_ryutaro 1.5   // normal case
196                     retVal = WSAAsyncSelect( sock, hwnd, msg, event );
197                     eq( retVal, 0, "WSSAsyncSelect", "%d" );  
198                     return retVal;
199                   
200                   }
201                   
202                   /*
203                   Parameters:
204                   sock
205                   	[in] Descriptor identifying an unbound socket. 
206                   name
207                   	[in] Address to assign to the socket from the sockaddr structure. 
208                   namelen 
209                   	[in] Length of the value in the name parameter, in bytes. 
210                   
211                   Return Values:
212                   0 - SUCCESS
213                   SOCKET_ERROR - FAILED
214                   
215                   Error code                  |      Meaning 
216 cs130_ryutaro 1.5 WSANOTINITIALISED           | A successful WSAStartup call must occur before using this function. 
217                   WSAENETDOWN                 | The network subsystem has failed. 
218                   WSAEACCES                   | Attempt to connect datagram socket to broadcast address failed because 
219                                                 setsockopt option SO_BROADCAST is not enabled. 
220                   WSAEADDRINUSE               | A process on the computer is already bound to the same fully-qualified 
221                   			      address and the socket has not been marked to allow address reuse with 
222                   			      SO_REUSEADDR. For example, the IP address and port are bound in the 
223                   			      af_inet case). (See the SO_REUSEADDR socket option under setsockopt.) 
224                   WSAEADDRNOTAVAIL            | The specified address is not a valid address for this computer. 
225                   WSAEFAULT                   | The name or namelen parameter is not a valid part of the user address space, 
226                   			      the namelen parameter is too small, the name parameter contains an incorrect 
227                   			      address format for the associated address family, or the first two bytes of 
228                   			      the memory block specified by name does not match the address family associated 
229                   			      with the socket descriptor s. 
230                   WSAEINPROGRESS              | A blocking Windows Sockets 1.1 call is in progress, or the service provider is 
231                   			      still processing a callback function. 
232                   WSAEINVAL                   | The socket is already bound to an address. 
233                   WSAENOBUFS                  | Not enough buffers available, too many connections. 
234                   WSAENOTSOCK                 | The descriptor is not a socket. 
235                   */
236                   static int bind_w( SOCKET sock, const struct sockaddr* name, int namelen )
237 cs130_ryutaro 1.5 {
238                     int retVal = 0;
239                   
240                     // invalid socket 
241                     retVal = bind( -999, name, namelen );
242                     ok( retVal == SOCKET_ERROR && WSAGetLastError() == WSAENOTSOCK, 
243                         "bind: Got retVal=%d WSAGetLastError()=%d Expected retVal=%d WSAGetLastError()=%d\n",
244                         retVal, WSAGetLastError(), SOCKET_ERROR, WSAENOTSOCK );
245                     retVal = 0;
246                   
247                     // invalid address
248                     retVal = bind( sock, 0, namelen );
249                     ok( retVal == SOCKET_ERROR && WSAGetLastError() ==  WSAEFAULT,
250                         "bind: Got retVal=%d WSAGetLastError()=%d Expected retVal=%d WSAGetLastError()=%d\n",
251                         retVal, WSAGetLastError(), SOCKET_ERROR, WSAEFAULT );
252                     retVal = 0;
253                   
254                     // invalid arg
255                     retVal = bind( sock, name, -999 );
256                     ok( retVal == SOCKET_ERROR && WSAGetLastError() == WSAEFAULT,
257                         "bind: Got retVal=%d WSAGetLastError()=%d Expected retVal=%d WSAGetLastError()=%d\n",
258 cs130_ryutaro 1.5       retVal, WSAGetLastError(), SOCKET_ERROR, WSAEFAULT );
259                     retVal = 0;         
260                   
261                     // normal case
262                     retVal = bind( sock, name, namelen );	
263                     eq( retVal, 0, "bind", "%d" );
264                   
265                     return retVal;
266 cs130_ryutaro 1.4 }
267                   
268 cs130_ryutaro 1.5 
269 cs130_ryutaro 1.4 /* 
270                      Wrapper for socket().
271                      socket() function creates a socket that is bound to a specific service provider.
272                   
273                      Parameters:
274                      af
275                      [in] Address family specification. 
276                      type 
277                      [in] Type specification for the new socket. Types are:
278                      SOCK_STREAM - Uses TCP
279                      SOCK_DGRAM  - Uses UDP 
280                      protocol 
281                      [in] Protocol to be used with the socket that is specific to the indicated address 
282                      family. 
283                   
284                      If no error occurs, socket returns a descriptor referencing the new socket. Otherwise, 
285                      a value of INVALID_SOCKET is returned, and a specific error code can be retrieved by 
286                      calling WSAGetLastError.
287                   
288                      Error code              |        Meaning 
289                      WSANOTINITIALISED       | A successful WSAStartup call must occur before using this function. 
290 cs130_ryutaro 1.4    WSAENETDOWN             | The network subsystem or the associated service provider has failed. 
291                      WSAEAFNOSUPPORT         | The specified address family is not supported. 
292                      WSAEINPROGRESS          | A blocking Windows Sockets 1.1 call is in progress, or the service 
293                      provider is still processing a callback function. 
294                      WSAEMFILE               | No more socket descriptors are available. 
295                      WSAENOBUFS              | No buffer space is available. The socket cannot be created. 
296                      WSAEPROTONOSUPPORT      | The specified protocol is not supported. 
297                      WSAEPROTOTYPE           | The specified protocol is the wrong type for this socket. 
298                      WSAESOCKTNOSUPPORT      | The specified socket type is not supported in this address family. 
299                   
300                      NOTE: WSAEPROTOTYPE  tried to do test for this error by specifying type=SOCK_DGRAM and
301                      protocol=IPPROTO_TCP but the return error code was WSEPROTONOSUPPORT
302                   */
303                   static SOCKET socket_w( int af, int type, int protocol )
304                   {
305 cs130_ryutaro 1.5 
306                     SOCKET sock;
307 cs130_ryutaro 1.4 
308                     // WSAEAFNOSUPPORT test	
309 cs130_ryutaro 1.5   sock = socket( -999, SOCK_STREAM, IPPROTO_TCP );
310                     ok( sock == INVALID_SOCKET && WSAGetLastError() == WSAEAFNOSUPPORT, 
311                         "socket: Got sock=%d WSAGetLastError()=%d Expected sock=%d WSAGetLastError()=%d\n", 
312                         sock, WSAGetLastError(), INVALID_SOCKET, WSAEAFNOSUPPORT );
313 cs130_ryutaro 1.4 
314                     // WSAEPROTONOSUPPORT test
315 cs130_ryutaro 1.5   sock = socket( AF_INET, SOCK_STREAM, -999 );
316                     ok( sock == INVALID_SOCKET && WSAGetLastError() == WSAEPROTONOSUPPORT, 
317                         "socket: Got sock=%d WSAGetLastError()=%d Expected sock=%d WSAGetLastError()=%d\n", 
318                         sock, WSAGetLastError(), INVALID_SOCKET, WSAEPROTONOSUPPORT );
319 cs130_ryutaro 1.4 
320                     // WSAESOCKTNOSUPPORT test
321 cs130_ryutaro 1.5   sock = socket( AF_INET, -999, IPPROTO_TCP );
322                     ok( sock == INVALID_SOCKET && WSAGetLastError() == WSAESOCKTNOSUPPORT, 
323                         "socket: Got sock=%d WSAGetLastError()=%d Expected sock=%d WSAGetLastError()=%d\n", 
324                         sock, WSAGetLastError(), INVALID_SOCKET, WSAESOCKTNOSUPPORT );
325                   
326                     // check the normal case
327                     sock = socket( af, type, protocol );    
328                     ok( sock != INVALID_SOCKET, "socket: Got sock=%d\n", sock );
329                     return sock;
330                   
331                   }
332                   
333                   /*
334                   Test routine for listen(), a function that places a socket in a state in which it is listening for an 
335                   incoming connection.
336                   Parameters:
337                   sock 
338                   	[in] Descriptor identifying a bound, unconnected socket. 
339                   backlog 
340                   	[in] Maximum length of the queue of pending connections. If set to SOMAXCONN, the underlying service 
341                   	provider responsible for socket s will set the backlog to a maximum reasonable value. There is no standard 
342 cs130_ryutaro 1.5 	provision to obtain the actual backlog value. 
343                   
344                   Return Values:
345                   0 - success
346                   SOCKET_ERROR - failed
347                   
348                   Error code              |   Meaning 
349                   WSANOTINITIALISED       | A successful WSAStartup call must occur before using this function. 
350                   WSAENETDOWN             | The network subsystem has failed. 
351                   WSAEADDRINUSE           | The socket's local address is already in use and the socket was not marked to 
352                   			  allow address reuse with SO_REUSEADDR. This error usually occurs during execution 
353                   			  of the bind function, but could be delayed until this function if the bind was to a 
354                   			  partially wildcard address (involving ADDR_ANY) and if a specific address needs to be 
355                   			  committed at the time of this function. 
356                   WSAEINPROGRESS          | A blocking Windows Sockets 1.1 call is in progress, or the service provider is still 
357                   			  processing a callback function. 
358                   WSAEINVAL               | The socket has not been bound with bind. 
359                   WSAEISCONN              | The socket is already connected. 
360                   WSAEMFILE               | No more socket descriptors are available. 
361                   WSAENOBUFS              | No buffer space is available. 
362                   WSAENOTSOCK             | The descriptor is not a socket. 
363 cs130_ryutaro 1.5 WSAEOPNOTSUPP           | The referenced socket is not of a type that supports the listen operation. 
364                   
365                   */
366                   static int listen_w( SOCKET sock, int backlog )
367                   {
368                     int retVal = 0;
369 cs130_ryutaro 1.4 
370 cs130_ryutaro 1.5   // WSAENOTSOCK test
371                     retVal = listen( -999, backlog );
372                     ok( retVal == SOCKET_ERROR && WSAGetLastError() == WSAENOTSOCK,
373                         "listen: Got retVal=%d WSAGetLastError()=%d Expected retVal=%d WSAGetLastError()=%d\n",
374                         retVal, WSAGetLastError(), SOCKET_ERROR, WSAENOTSOCK );
375                     retVal = 0;
376                   	
377                     // normal case
378                     retVal = listen( sock, backlog );
379                     eq( retVal, 0, "listen", "%d" );
380 cs130_ryutaro 1.4 
381 cs130_ryutaro 1.5   return retVal;	
382 cs130_ryutaro 1.4 }
383                   
384                   /* 
385                      Call back event handler for asynchronous client 
386                   */
387                   static LRESULT CALLBACK WndProcedure( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
388                   {
389                     int eventCode = 0; 
390                     switch( msg )
391                       {
392                       case ASYNC_EVENT: 
393                         eventCode = WSAGETSELECTEVENT( lParam );
394                         SOCKET socket = (SOCKET) wParam;
395                         SOCKET acceptSock;
396 cs130_ryutaro 1.5       int bytesRecv = 0, bytesTestCli = 0, bytesTestServ = 0;
397 cs130_ryutaro 1.4       char* buf;
398                         if( GetCurrentThreadId() == ServerThread.id )
399                   	buf = ServerThread.packet;
400                         else
401                   	buf = ClientThread.packet;
402                   
403                         switch( eventCode )
404                   	{
405                   	case FD_ACCEPT:					
406 cs130_ryutaro 1.5 
407 cs130_ryutaro 1.4 	  acceptSock = accept( socket, NULL, NULL );
408                   	  if( acceptSock == INVALID_SOCKET ){
409                   	    trace( "accept error %d\n", WSAGetLastError() );
410                   	    closesocket( socket );
411                   	    ExitThread( TH_ACCEPT_ERROR );
412                   	  }
413 cs130_ryutaro 1.5 	  
414                   	  eq( GetCurrentThreadId(), ServerThread.id, "FD_ACCEPT", "%ld" );
415 cs130_ryutaro 1.4 	  trace( "%ld: connection accepted\n", GetCurrentThreadId() );
416                   	  break;
417                   
418                   	case FD_CONNECT:
419                   
420                   	  // a call to connect() has completed
421 cs130_ryutaro 1.5 	  eq( GetCurrentThreadId(), ClientThread.id, "FD_CONNECT", "%ld" );
422                   	  trace("%ld: connection established\n", GetCurrentThreadId() );
423 cs130_ryutaro 1.4 	  break;
424                   
425                   	case FD_CLOSE:				
426                   
427 cs130_ryutaro 1.5 	  // a connection has been closed
428 cs130_ryutaro 1.4 	  closesocket( socket );
429 cs130_ryutaro 1.5 	  eq( GetCurrentThreadId(), ServerThread.id, "FD_CLOSE", "%ld" );
430                   	  trace( "%ld: closed socket and exiting...\n", GetCurrentThreadId());
431 cs130_ryutaro 1.4 	  WSACleanup();
432                   	  ExitThread( 0 );
433                   	  break;
434                   
435                   	case FD_READ:
436                   
437                   	  // WinSock has data waiting to be read									
438                   	  bytesRecv = recv( socket, buf, PACKET_SZ, 0 );
439                   
440 cs130_ryutaro 1.5 	  ok( bytesRecv == PACKET_SZ || bytesRecv == FILE_SZ%PACKET_SZ,
441                   	      "recv: Got bytesRecv=%d Expected bytesRecv=%d or %d\n",
442                   	      bytesRecv, PACKET_SZ, FILE_SZ%PACKET_SZ );
443                   	  trace( "Thread %ld received %d bytes\n", GetCurrentThreadId(), bytesRecv );
444                   	
445                   	  // print the bytes
446                   	  print_buf( FALSE, buf, PACKET_SZ );  
447                   
448 cs130_ryutaro 1.4 
449                   	  // Now send it back if you're the server
450                   	  if( GetCurrentThreadId() == ServerThread.id ){
451                   
452 cs130_ryutaro 1.5 	    // Test the bytes sent.  Since we are sending small size packets
453                   	    // the entire packet shoudl be successfully sent.
454                   	    // For this test, don't send any big file.
455                   	    bytesTestServ = send( socket, buf, bytesRecv, 0 );
456                   	    eq( bytesTestServ, bytesRecv, "send", "%d" );
457                   	    if( bytesTestServ == SOCKET_ERROR )
458                   	      break;
459                    
460                   	    trace( "Thread %ld sent %d bytes\n", GetCurrentThreadId(), bytesTestServ );
461 cs130_ryutaro 1.4 
462 cs130_ryutaro 1.5 	    // print the bytes
463                   	    print_buf( TRUE, buf, PACKET_SZ );
464 cs130_ryutaro 1.4 
465                   	  }
466                   	  else{
467                   
468                   	    // Client: close the connection when it received back FILE_SZ
469                   	    ClientThread.bytesRecvd += bytesRecv;
470                   	    if( ClientThread.bytesRecvd >= FILE_SZ ){
471                   	      closesocket( socket );
472 cs130_ryutaro 1.5 	      trace( "%ld closed socket and exiting..\n", GetCurrentThreadId() );
473 cs130_ryutaro 1.4 	      WSACleanup();
474                   	      ExitThread( 0 );
475                   	    }
476                   	  }
477                   	  break;
478                   
479                   	case FD_WRITE:
480                   
481                   	  // don't do anything here for server
482                   	  if( GetCurrentThreadId() == ServerThread.id )
483                   	    break;
484                   
485 cs130_ryutaro 1.5 	  // loop until the entire file is sent
486 cs130_ryutaro 1.4 	  BOOL notDone = TRUE;
487                   	  while( notDone ){
488                   
489                   	    // determine how many bytes to send
490                   	    int bytesToSend = 0;
491                   	    if( sizeof( FileBuf ) - ClientThread.bytesSent < PACKET_SZ ){
492                   
493                   	      // the bytes remaining to send is smaller than packet size
494                   	      bytesToSend = (int) ( sizeof( FileBuf ) - ClientThread.bytesSent );
495                   	      notDone = FALSE;
496                   
497                   	    }
498                   	    else{
499                   
500                   	      // the bytes remaining is greater than or equal to PACKET_SZ
501                   	      bytesToSend = PACKET_SZ;
502                   
503                   	    }
504                   							
505                   	    memcpy( buf, FileBuf + ClientThread.bytesSent, bytesToSend ); 
506                   	    ClientThread.bytesSent += bytesToSend;
507 cs130_ryutaro 1.4 						
508                   	    // send the packet off to the Server if it is filled
509 cs130_ryutaro 1.5 	    // Since it will always send a small packet, the entire packet
510                   	    // should be sent successfully.
511                   	    bytesTestCli = send( socket, buf, bytesToSend, 0 );
512                   
513                   	    eq( bytesTestCli, bytesToSend, "send", "%d" );
514                   	    if( bytesTestCli == SOCKET_ERROR )
515                   	      break;
516                    
517                   	    trace( "Thread %ld sent %d bytes\n", GetCurrentThreadId(), bytesTestCli  );
518                   
519                   	    // print the bytes
520                   	    print_buf( TRUE, buf, PACKET_SZ );
521 cs130_ryutaro 1.4 
522                   	  }
523                   	  break;
524                   	}
525                       }
526 cs130_ryutaro 1.5 
527 cs130_ryutaro 1.4   return DefWindowProc( hWnd, msg, wParam, lParam );
528                   }
529                   
530 cs130_ryutaro 1.5 /* debugging function to print out the buffer */
531                   static void print_buf( BOOL sent, char* buf, int max )
532                   {
533                     if( sent )
534                       printf( "%s(%d): %ld sent: ", __FILE__, __LINE__, GetCurrentThreadId() );
535                     else
536                       printf( "%s(%d): %ld recv: ", __FILE__, __LINE__, GetCurrentThreadId() );
537                   
538                     int i = 0;
539                     while( i < max &&  buf[i] != (char)EOF ){
540                       printf( "%c", buf[i] );
541                       i++;
542                     }
543                     printf( "\n" );
544                   
545                   }
546                   
547 cs130_ryutaro 1.4 /* 
548                      Creates a hidden window object.
549                   
550                      input:
551                      none
552                      output:
553                      window handle
554                   */
555                   static HWND WineCreateWindow( HINSTANCE hInstance )
556                   {
557                     // initialize the window class attributes.
558                     WNDCLASS windowClass;
559                     //windowClass = new WNDCLASS;
560                     windowClass.lpszClassName = "Hidden_Winsock_Window";
561                     windowClass.style = CS_HREDRAW | CS_VREDRAW;
562                     windowClass.lpfnWndProc = WndProcedure;
563                     windowClass.cbClsExtra = 0;
564                     windowClass.cbWndExtra = 0;
565                     windowClass.hInstance = hInstance;
566                     windowClass.hIcon = NULL;
567                     windowClass.hCursor = NULL;
568 cs130_ryutaro 1.4   windowClass.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
569                     windowClass.lpszMenuName = NULL;
570                     RegisterClass(&windowClass);
571                   
572                     // create window
573                     return CreateWindow( 
574                   		      "Hidden_Winsock_Window", 
575                   		      "Winsock Window", 
576                   		      WS_OVERLAPPEDWINDOW,
577                   		      CW_USEDEFAULT, 
578                   		      CW_USEDEFAULT,
579                   		      CW_USEDEFAULT,
580                   		      CW_USEDEFAULT,
581                   		      NULL,
582                   		      NULL,
583                   		      hInstance,
584                   		      NULL 
585                   		      );
586                   }
587                   
588                   /* server */
589 cs130_ryutaro 1.4 static DWORD WINAPI WineRunServer()
590                   {
591                     // Retrieve an instance
592                     HINSTANCE hInstance = GetModuleHandle( NULL );
593                   
594                     // Create a window
595                     HWND hwnd = WineCreateWindow( hInstance );
596                     if( hwnd == NULL ){
597                       trace( "Window could not be created %ld\n", GetLastError() );
598                       ExitThread( TH_WINDOW_ERROR );
599                     }
600                   	
601                     // start winsock	
602                     WSADATA wsaData;
603                     if( WSAStartup_w( MAKEWORD( 2, 2 ), &wsaData ) != 0 ){
604                   
605                       // print out the Error Code to be thorough
606                       trace( "WSAStartup() failed with error code: %d\n", WSAGetLastError() );		
607                       ExitThread( TH_START_ERROR );
608                     }
609                   
610 cs130_ryutaro 1.4   // Create a socket.
611 cs130_ryutaro 1.5   SOCKET sock = socket_w( AF_INET, SOCK_STREAM, IPPROTO_TCP );	
612                     if( sock == INVALID_SOCKET ){
613 cs130_ryutaro 1.4     trace( "socket error: %d\n", WSAGetLastError() ); 
614                       ExitThread( TH_SOCKET_ERROR );
615                     }
616                   
617                     // Bind the socket.
618                     SOCKADDR_IN sockAddr;
619                     sockAddr.sin_family = AF_INET;
620                     sockAddr.sin_addr.s_addr = inet_addr( "127.0.0.1" );
621                     sockAddr.sin_port = htons( PORT_NUM );
622 cs130_ryutaro 1.5   if( bind_w( sock, (SOCKADDR*) &sockAddr, sizeof( sockAddr ) ) == SOCKET_ERROR ){
623 cs130_ryutaro 1.4     trace( "bind failed weith error code %d\n", WSAGetLastError() );
624                       closesocket( sock );
625                       ExitThread( TH_BIND_ERROR );
626                   
627                     }
628                   
629                     // Listen on the socket.
630 cs130_ryutaro 1.5   if( listen_w( sock, 1 ) == SOCKET_ERROR ){
631 cs130_ryutaro 1.4     trace( "listen error with error code %d.\n", WSAGetLastError() );
632 cs130_ryutaro 1.5     closesocket( sock );	
633                       ExitThread( TH_LISTEN_ERROR );
634                     }
635                     
636 cs130_ryutaro 1.4   // make the socket asynchronous and notify of read, write, connect and close events
637 cs130_ryutaro 1.5   if( WSAAsyncSelect_w( sock, hwnd, ASYNC_EVENT, FD_WRITE | FD_ACCEPT |FD_READ | FD_CLOSE ) == SOCKET_ERROR ){
638 cs130_ryutaro 1.4 
639                       trace( "WSAAsyncSelect Failed %d\n", WSAGetLastError() );
640                       closesocket( sock );
641                       ExitThread( TH_SELECT_ERROR );
642                   
643                     }
644                   
645 cs130_ryutaro 1.5   trace( "Server socket has disabled blocking\n" );
646 cs130_ryutaro 1.4 	
647                     BOOL retVal;
648                     MSG msg;
649                     while( ( retVal = GetMessage( &msg, NULL, 0, 0 ) ) != 0 ){ 
650                   
651                       if( retVal == -1 ){
652                   
653                         // handle the error and possibly exit
654                         trace( "GetMessage error %ld\n", GetLastError() );
655                         closesocket( sock );
656                         ExitThread( TH_MSG_ERROR );
657                       }
658                   
659                       // Translate and dispatch the message
660                       TranslateMessage( &msg ); 
661                       DispatchMessage( &msg );
662                   
663                     }
664                   
665                     return 0;
666                   }
667 cs130_ryutaro 1.4 
668                   /* client */
669                   static DWORD WINAPI WineRunClient()
670                   {
671                     // Retrieve an instance
672                     HINSTANCE hInstance = GetModuleHandle( NULL );
673                   
674                     // Create a window
675                     HWND hwnd = WineCreateWindow( hInstance );
676                     if( hwnd == NULL ){
677                       trace( "Window could not be created %ld\n", GetLastError() );
678                       ExitThread( TH_WINDOW_ERROR );
679                     }
680                   
681                     // start winsock	
682                     WSADATA wsaData;
683                     if( WSAStartup_w( MAKEWORD( 2, 2 ), &wsaData ) != 0 ){
684                   
685                       // print out the Error Code to be thorough
686                       trace( "WSAStartup() failed with error code: %d\n", WSAGetLastError() );		
687                       ExitThread( TH_START_ERROR );
688 cs130_ryutaro 1.4   }
689                   
690                     // Create a socket.  -- This is a TCP test
691                     SOCKET sock = socket_w( AF_INET, SOCK_STREAM, IPPROTO_TCP );
692                     if ( sock == INVALID_SOCKET ) {
693                       trace( "socket returned with error code: %d\n", WSAGetLastError() );
694                       ExitThread( TH_SOCKET_ERROR );
695                     }
696                   
697                     // make the socket asynchronous and notify of read, write, connect and close events
698                     // this is the client socket
699 cs130_ryutaro 1.5   if( WSAAsyncSelect_w( sock, hwnd, ASYNC_EVENT, FD_WRITE | FD_CONNECT | FD_READ | FD_CLOSE ) == SOCKET_ERROR ){
700                   
701 cs130_ryutaro 1.4     trace( "WSAAsyncSelect Failed %d\n", WSAGetLastError() );
702                       closesocket( sock );
703                       ExitThread( TH_SELECT_ERROR );
704 cs130_ryutaro 1.5 
705 cs130_ryutaro 1.4   }
706                   
707 cs130_ryutaro 1.5   trace( "Client socket has disabled blocking\n" );
708                   
709 cs130_ryutaro 1.4   /* connect */
710                     SOCKADDR_IN sockAddr;
711                     sockAddr.sin_family = AF_INET;
712                     sockAddr.sin_addr.s_addr = inet_addr( "127.0.0.1" );
713                     sockAddr.sin_port = htons( PORT_NUM );
714                     if( connect( sock, (SOCKADDR*) &sockAddr, sizeof( sockAddr ) ) == SOCKET_ERROR ){
715                       if( WSAGetLastError() != WSAEWOULDBLOCK ){
716                         trace( "Failed to connect.: %d\n", WSAGetLastError() );
717                         closesocket( sock );
718                         ExitThread( TH_CONNECT_ERROR );
719                       }
720                     }
721                   
722                     BOOL retVal;
723                     MSG msg;
724                     while( ( retVal = GetMessage( &msg, NULL, 0, 0 ) ) != 0 ){ 
725                   
726                       if( retVal == -1 ){
727                   
728                         // handle the error and possibly exit
729                         trace( "GetMessage error %ld\n", GetLastError() );
730 cs130_ryutaro 1.4       closesocket( sock );
731                         ExitThread( TH_MSG_ERROR );
732                       }
733                   
734                       // Translate and dispatch the message
735                       TranslateMessage( &msg ); 
736                       DispatchMessage( &msg );
737                   
738                     }
739                     return 0;
740                   }
741                   
742                   /* close thread handles and finish up winsock dll */
743                   static void WineThreadCleanUp()
744                   {
745                     if( ServerThread.handle )
746                       CloseHandle( ServerThread.handle );
747                   
748                     if( ClientThread.handle )
749                       CloseHandle( ClientThread.handle );	
750                   }
751 cs130_ryutaro 1.4 
752                   /* creates the buffer that the client sends */
753                   static void WineCreateFile()
754                   {
755                     /* initialize just in case */
756                     memset( FileBuf, 0, sizeof( FileBuf ) );
757                   
758                     /* just customize this any way you want */
759                     memset( FileBuf, 'W', PACKET_SZ );
760                     memset( FileBuf + PACKET_SZ, 'I', PACKET_SZ );
761                     memset( FileBuf + ( 2 * PACKET_SZ ), 'N', PACKET_SZ );
762                     memset( FileBuf + ( 3 * PACKET_SZ ), 'E', 3 );
763                     FileBuf[FILE_SZ - 1] = (char) EOF;
764                   }
765                   
766                   START_TEST( WineWinsockAsyncTest )
767                   {
768                     // Create the file that we are going to send.
769                     WineCreateFile();
770                   
771                     // Initialize server and client threads
772 cs130_ryutaro 1.4   memset( &ServerThread, 0, sizeof( ServerThread ) );
773                     memset( &ClientThread, 0, sizeof( ClientThread ) );
774                   
775                     // create server thread	
776                     ServerThread.handle = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)WineRunServer, 
777                   				      NULL, 0, &ServerThread.id );
778                   
779                     if( ServerThread.handle == NULL ){
780                   
781                       trace( "CreateThread failed %ld\n", GetLastError() );
782                       WineThreadCleanUp();
783                       return;
784                     }
785                   
786 cs130_ryutaro 1.5   trace( "server thread %ld created. Wait %d seconds\n", ServerThread.id, SERVER_START_TIME );
787 cs130_ryutaro 1.4 
788                     // Wait for three seconds to let server start
789                     DWORD waitRet = WaitForSingleObject( ServerThread.handle, SERVER_START_TIME );
790                     if( waitRet == WAIT_FAILED ){
791                   		
792                       // WaitForSingleObject failed for whatever reason
793                       trace( "WaitForSingleObject failed with error code %ld\n", GetLastError() );	
794                       WineThreadCleanUp();
795                       return;
796                   
797                     }
798                   
799                     // get the exit code of the server - error if not STILL_ACTIVE
800                     DWORD threadStatus = 0;
801                     if( GetExitCodeThread( ServerThread.handle, &threadStatus ) == 0 ){
802                   		
803                       trace( "GetExitCodeThread failed with error code %ld\n",GetLastError() );
804                       WineThreadCleanUp();
805                       return;
806                   
807                     }
808 cs130_ryutaro 1.4 
809 cs130_ryutaro 1.5   if( threadStatus != STILL_ACTIVE ){
810                   
811                       trace( "Server thread in invalid status - %ld\n", threadStatus );
812                       WineThreadCleanUp();
813                       return;   
814                   
815                     }
816 cs130_ryutaro 1.4 
817                     // Create client thread in suspended state
818                     ClientThread.handle = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)WineRunClient, 
819                   				      NULL, 0, &ClientThread.id );
820                   
821                     if( ClientThread.handle == NULL ){
822                   
823                       trace( "CreateThread failed %ld\n", GetLastError() );
824                       WineThreadCleanUp();
825                       return;
826                     }	
827                   	
828 cs130_ryutaro 1.5   trace( "client thread %ld created.\n", ClientThread.id );
829 cs130_ryutaro 1.4 
830                     // Wait for this server to suspsend itself
831                     HANDLE threadHandles[NUM_THREADS_TO_WAIT] = { ServerThread.handle, ClientThread.handle };
832                     waitRet = WaitForMultipleObjects( NUM_THREADS_TO_WAIT, threadHandles, TRUE, MAX_WAIT_TIME );
833                     if( waitRet == WAIT_FAILED ){
834 cs130_ryutaro 1.5 
835 cs130_ryutaro 1.4     // WaitForSingleObject failed for whatever reason
836                       trace( "WaitForMultipleObjects failed with error code %ld\n", GetLastError() );	
837                       WineThreadCleanUp();
838                       return;
839                   
840                     }
841                     else if( waitRet == WAIT_TIMEOUT ){
842                   
843                       trace( "Timed out while waiting for threads to finish\n" );
844                       WineThreadCleanUp();
845                       return;
846                   
847                     }
848                   
849                     // clean up the threads
850                     WineThreadCleanUp();
851                   
852 cs130_ryutaro 1.5   trace( "Test completed.  Main thread exiting\n" );
853 cs130_ryutaro 1.4 }

Rizwan Kassim
Powered by
ViewCVS 0.9.2