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 }
|