1 cs130_ryutaro 1.1 #include <stdio.h>
2 #include "winsock2.h"
3 #include "windows.h"
4
|
5 cs130_ryutaro 1.2 #include <wine/test.h>
6 #include <winbase.h>
7
|
8 cs130_ryutaro 1.1 /* The #pragma directives offer a way for each compiler to offer machine-
9 and operating-system-specific features while retaining overall
10 compatibility with the C and C++ languages.
11 The next line places a library-search record, ws2_32, in the object file. */
|
12 cs130_ryutaro 1.2 // #pragma comment ( lib, "ws2_32" )
|
13 cs130_ryutaro 1.1
14 /* constants */
15 #define ASYNC_EVENT (WM_USER +5) // the message we'll use for our async notification
16 #define PORT_NUM 27015
17 #define PACKET_SZ 32
18 #define FILE_SZ 100
19 #define SERVER_START_TIME 3000
20 #define MAX_WAIT_TIME 30000 // 30 seconds expressed in milliseconds
21 #define NUM_THREADS_TO_WAIT 2
22
23 enum // define all the exit codes for a thread
24 {
25 TH_START_ERROR = 1001,
26 TH_SOCKET_ERROR,
27 TH_SOCKADDR_ERROR,
28 TH_BIND_ERROR,
29 TH_CONNECT_ERROR,
30 TH_LISTEN_ERROR,
31 TH_ACCEPT_ERROR,
32 TH_SELECT_ERROR,
33 TH_RECV_ERROR,
34 cs130_ryutaro 1.1 TH_SEND_ERROR,
35 TH_WINDOW_ERROR,
36 TH_MSG_ERROR
37
38 } ThreadExitCodes;
39
40 /* static func prototypes */
41 static int WSAStartup_w( WORD wVersionRequired, LPWSADATA lpWSAData );
42 static SOCKET socket_w( int af, int type, int protocol );
43 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
50 /* struct def */
51 typedef struct
52 {
53 DWORD id;
54 HANDLE handle;
55 cs130_ryutaro 1.1 int bytesRecvd;
56 int bytesSent;
57 char packet[PACKET_SZ];
58 } thread_t;
59
60 /* global vars */
61 static char FileBuf[FILE_SZ];
62 static thread_t ServerThread;
63 static thread_t ClientThread;
64
65 /*
66 Wrapper for WSAStartup().
67 The WSAStartup function must be the first Windows Sockets function
68 called by an application or DLL. It allows an application or DLL to
69 specify the version of Windows Sockets required and retrieve details
70 of the specific Windows Sockets implementation.
71
72 Paremeters:
73 wVersionRequested
74 [in] Highest version of Windows Sockets support that the caller can use.
75 The high-order byte specifies the minor version (revision) number;
76 cs130_ryutaro 1.1 the low-order byte specifies the major version number.
77 lpWSAData
78 [out] Pointer to the WSADATA data structure that is to receive details of
79 the Windows Sockets implementation.
80
81 Error code | Meaning
82 WSASYSNOTREADY | Indicates that the underlying network subsystem is
83 not ready for network communication.
84 WSAVERNOTSUPPORTED | The version of Windows Sockets support requested is
85 not provided by this particular Windows Sockets
86 implementation.
87 WSAEINPROGRESS | A blocking Windows Sockets 1.1 operation is in progress.
88 WSAEPROCLIM | Limit on the number of tasks supported by the Windows
89 Sockets implementation has been reached.
90 WSAEFAULT | The lpWSAData is not a valid pointer.
91 */
92 static int WSAStartup_w( WORD wVersionRequired, LPWSADATA lpWSAData )
93 {
94 int errCode = 0;
95
96 // WSAVERNOTSUPPORTED test
97 cs130_ryutaro 1.1 WSADATA tmpLpWSAData;
98 errCode = WSAStartup( MAKEWORD( 0, 0 ), &tmpLpWSAData );
99 if( errCode != WSAVERNOTSUPPORTED ) {
100
101 // print out the Error Code to be thorough
|
102 cs130_ryutaro 1.2 trace( "%d: WSAVERNOTSUPPORTED test failed with error code: %d\n", __LINE__, errCode );
|
103 cs130_ryutaro 1.1 errCode = 0;
104 }
105
106 // WSEFAULT test
107 errCode = WSAStartup( wVersionRequired, ( LPWSADATA ) 0 );
108 if( errCode != WSAEFAULT ) {
109
110 // print out the Error Code to be thorough
|
111 cs130_ryutaro 1.2 trace( "%d: WSAFAULT test failed with error code: %d\n", __LINE__, errCode );
|
112 cs130_ryutaro 1.1 errCode = 0;
113 }
114
115 // lastly regular case - should succeed
116 errCode = WSAStartup( wVersionRequired, lpWSAData );
117 if( errCode != 0 ) {
118
119 // print out the Error Code to be thorough
120 errCode = WSAGetLastError();
|
121 cs130_ryutaro 1.2 trace( "%d: WSAStartup() failed with error code: %d\n", __LINE__, errCode );
|
122 cs130_ryutaro 1.1 }
123
124 return errCode;
125 }
126
127 /*
128 Wrapper for socket().
129 socket() function creates a socket that is bound to a specific service provider.
130
131 Parameters:
132 af
133 [in] Address family specification.
134 type
135 [in] Type specification for the new socket. Types are:
136 SOCK_STREAM - Uses TCP
137 SOCK_DGRAM - Uses UDP
138 protocol
139 [in] Protocol to be used with the socket that is specific to the indicated address
140 family.
141
142 If no error occurs, socket returns a descriptor referencing the new socket. Otherwise,
143 cs130_ryutaro 1.1 a value of INVALID_SOCKET is returned, and a specific error code can be retrieved by
144 calling WSAGetLastError.
145
146 Error code | Meaning
147 WSANOTINITIALISED | A successful WSAStartup call must occur before using this function.
148 WSAENETDOWN | The network subsystem or the associated service provider has failed.
149 WSAEAFNOSUPPORT | The specified address family is not supported.
150 WSAEINPROGRESS | A blocking Windows Sockets 1.1 call is in progress, or the service
151 provider is still processing a callback function.
152 WSAEMFILE | No more socket descriptors are available.
153 WSAENOBUFS | No buffer space is available. The socket cannot be created.
154 WSAEPROTONOSUPPORT | The specified protocol is not supported.
155 WSAEPROTOTYPE | The specified protocol is the wrong type for this socket.
156 WSAESOCKTNOSUPPORT | The specified socket type is not supported in this address family.
157
158 NOTE: WSAEPROTOTYPE tried to do test for this error by specifying type=SOCK_DGRAM and
159 protocol=IPPROTO_TCP but the return error code was WSEPROTONOSUPPORT
160 */
161 static SOCKET socket_w( int af, int type, int protocol )
162 {
163 // Create a socket.
164 cs130_ryutaro 1.1 SOCKET m_socket;
165
166 // WSAEAFNOSUPPORT test
167 m_socket = socket( -999, SOCK_STREAM, IPPROTO_TCP );
168 if( m_socket != INVALID_SOCKET || WSAGetLastError() != WSAEAFNOSUPPORT ){
|
169 cs130_ryutaro 1.2 trace( "%d: WSAEAFNOSUPPORT test failed: %d %d\n", __LINE__, m_socket, WSAGetLastError() );
|
170 cs130_ryutaro 1.1 }
171
172 // WSAEPROTONOSUPPORT test
173 m_socket = socket( AF_INET, SOCK_STREAM, -999 );
174 if( m_socket != INVALID_SOCKET || WSAGetLastError() != WSAEPROTONOSUPPORT ){
|
175 cs130_ryutaro 1.2 trace( "%d: WSAEPROTONOSUPPORT test failed: %d %d\n", __LINE__, m_socket, WSAGetLastError() );
|
176 cs130_ryutaro 1.1 }
177
178 // WSAESOCKTNOSUPPORT test
179 m_socket = socket( AF_INET, -999, IPPROTO_TCP );
180 if( m_socket != INVALID_SOCKET || WSAGetLastError() != WSAESOCKTNOSUPPORT ){
|
181 cs130_ryutaro 1.2 trace( "%d: WSAEPROTONOSUPPORT test failed: %d %d\n", __LINE__, m_socket, WSAGetLastError() );
|
182 cs130_ryutaro 1.1 }
183
184 m_socket = socket( af, type, protocol );
185 if( m_socket == INVALID_SOCKET ){
|
186 cs130_ryutaro 1.2 trace( "%d: Error at socket(): %d\n", __LINE__, WSAGetLastError() );
|
187 cs130_ryutaro 1.1 }
188
189 return m_socket;
190 }
191
192 /*
193 Call back event handler for asynchronous client
194 */
195 static LRESULT CALLBACK WndProcedure( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
196 {
|
197 cs130_ryutaro 1.2 int eventCode = 0;
|
198 cs130_ryutaro 1.1 switch( msg )
199 {
200 case ASYNC_EVENT:
|
201 cs130_ryutaro 1.2 eventCode = WSAGETSELECTEVENT( lParam );
|
202 cs130_ryutaro 1.1 SOCKET socket = (SOCKET) wParam;
203 SOCKET acceptSock;
204 int bytesRecv = 0;
205 int i = 0, j = 0;
206 char* buf;
207 if( GetCurrentThreadId() == ServerThread.id )
208 buf = ServerThread.packet;
209 else
210 buf = ClientThread.packet;
211
212 switch( eventCode )
213 {
214 case FD_ACCEPT:
|
215 cs130_ryutaro 1.2 trace( "%ld accept called\n", GetCurrentThreadId() );
|
216 cs130_ryutaro 1.1 acceptSock = accept( socket, NULL, NULL );
217 if( acceptSock == INVALID_SOCKET ){
|
218 cs130_ryutaro 1.2 trace( "%d: accept error %d\n", __LINE__, WSAGetLastError() );
|
219 cs130_ryutaro 1.1 closesocket( socket );
220 ExitThread( TH_ACCEPT_ERROR );
221 }
|
222 cs130_ryutaro 1.2 trace( "%ld: connection accepted\n", GetCurrentThreadId() );
|
223 cs130_ryutaro 1.1 break;
224
225 case FD_CONNECT:
226
227 // a call to connect() has completed
|
228 cs130_ryutaro 1.2 trace("%ld CONNECTED!\n", GetCurrentThreadId() );
|
229 cs130_ryutaro 1.1 break;
230
231 case FD_CLOSE:
232
233 // a connection has been closed
234 closesocket( socket );
|
235 cs130_ryutaro 1.2 trace( "%ld: Closed socket\n", GetCurrentThreadId());
|
236 cs130_ryutaro 1.1 WSACleanup();
237 ExitThread( 0 );
238 break;
239
240 case FD_READ:
241
242 // WinSock has data waiting to be read
243 bytesRecv = recv( socket, buf, PACKET_SZ, 0 );
244
|
245 cs130_ryutaro 1.2 trace( "%ld received %d bytes: ", GetCurrentThreadId(), bytesRecv );
|
246 cs130_ryutaro 1.1 while( i < PACKET_SZ && buf[i] != (char)EOF ){
|
247 cs130_ryutaro 1.2 trace( "%c", buf[i] );
|
248 cs130_ryutaro 1.1 i++;
249 }
|
250 cs130_ryutaro 1.2 trace( "\n" );
|
251 cs130_ryutaro 1.1
252 // Now send it back if you're the server
253 if( GetCurrentThreadId() == ServerThread.id ){
254
255 if( send( socket, buf, bytesRecv, 0 ) == SOCKET_ERROR ){
256
257 // check if the network buffer is full and can send no more
258 // data. If so then break from the loop
259 if( WSAGetLastError() == WSAEWOULDBLOCK ){
|
260 cs130_ryutaro 1.2 // break from the loop buffer is full
261 trace( "woud block send!\n" );
|
262 cs130_ryutaro 1.1 break;
263 }
264 else{ // another error
|
265 cs130_ryutaro 1.2 trace(" some send error\n" );
|
266 cs130_ryutaro 1.1 return 0;
267 }
268 }
269
|
270 cs130_ryutaro 1.2 trace( "%ld sent back %d bytes: ", GetCurrentThreadId(), bytesRecv );
|
271 cs130_ryutaro 1.1 j = 0;
272 while( j < bytesRecv ){
|
273 cs130_ryutaro 1.2 trace( "%c", buf[j] );
|
274 cs130_ryutaro 1.1 j++;
275 }
|
276 cs130_ryutaro 1.2 trace( "\n" );
|
277 cs130_ryutaro 1.1
278 }
279 else{
280
281 // Client: close the connection when it received back FILE_SZ
282 ClientThread.bytesRecvd += bytesRecv;
283 if( ClientThread.bytesRecvd >= FILE_SZ ){
|
284 cs130_ryutaro 1.2 trace( "%ld closing socket\n", GetCurrentThreadId() );
|
285 cs130_ryutaro 1.1 closesocket( socket );
286 WSACleanup();
287 ResumeThread( ServerThread.handle );
288 ExitThread( 0 );
289 }
290 }
291 break;
292
293 case FD_WRITE:
294
295 // don't do anything here for server
296 if( GetCurrentThreadId() == ServerThread.id )
297 break;
298
299 // enter an infinite loop
300 BOOL notDone = TRUE;
301 while( notDone ){
302
303 // determine how many bytes to send
304 int bytesToSend = 0;
305 if( sizeof( FileBuf ) - ClientThread.bytesSent < PACKET_SZ ){
306 cs130_ryutaro 1.1
307 // the bytes remaining to send is smaller than packet size
308 bytesToSend = (int) ( sizeof( FileBuf ) - ClientThread.bytesSent );
309 notDone = FALSE;
310
311 }
312 else{
313
314 // the bytes remaining is greater than or equal to PACKET_SZ
315 bytesToSend = PACKET_SZ;
316
317 }
318
319 memcpy( buf, FileBuf + ClientThread.bytesSent, bytesToSend );
320 ClientThread.bytesSent += bytesToSend;
321
322 // send the packet off to the Server if it is filled
323 if( send( socket, buf, bytesToSend, 0 ) == SOCKET_ERROR ){
324
325 // check if the network buffer is full and can send no more
326 // data. If so then break from the loop
327 cs130_ryutaro 1.1 if( WSAGetLastError() == WSAEWOULDBLOCK ){
|
328 cs130_ryutaro 1.2 // break from the loop buffer is full
|
329 cs130_ryutaro 1.1 break;
330 }
331 else{ // another error
332 return 0;
333 }
334 }
335
|
336 cs130_ryutaro 1.2 trace( "%ld sent: ", GetCurrentThreadId() );
|
337 cs130_ryutaro 1.1 j = 0;
338 while( j < PACKET_SZ && buf[j] != (char)EOF ){
|
339 cs130_ryutaro 1.2 trace( "%c", buf[j] );
|
340 cs130_ryutaro 1.1 j++;
341 }
|
342 cs130_ryutaro 1.2 trace( "\n" );
|
343 cs130_ryutaro 1.1 }
344 break;
345 }
346 }
347 return DefWindowProc( hWnd, msg, wParam, lParam );
348 }
349
350 /*
351 Creates a hidden window object.
352
353 input:
354 none
355 output:
356 window handle
357 */
358 static HWND WineCreateWindow( HINSTANCE hInstance )
359 {
360 // initialize the window class attributes.
|
361 cs130_ryutaro 1.2 WNDCLASS windowClass;
362 //windowClass = new WNDCLASS;
363 windowClass.lpszClassName = "Hidden_Winsock_Window";
364 windowClass.style = CS_HREDRAW | CS_VREDRAW;
365 windowClass.lpfnWndProc = WndProcedure;
366 windowClass.cbClsExtra = 0;
367 windowClass.cbWndExtra = 0;
368 windowClass.hInstance = hInstance;
369 windowClass.hIcon = NULL;
370 windowClass.hCursor = NULL;
371 windowClass.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
372 windowClass.lpszMenuName = NULL;
373 RegisterClass(&windowClass);
|
374 cs130_ryutaro 1.1
375 // create window
376 return CreateWindow(
377 "Hidden_Winsock_Window",
378 "Winsock Window",
379 WS_OVERLAPPEDWINDOW,
380 CW_USEDEFAULT,
381 CW_USEDEFAULT,
382 CW_USEDEFAULT,
383 CW_USEDEFAULT,
384 NULL,
385 NULL,
386 hInstance,
387 NULL
388 );
389 }
390
391 /* server */
392 static DWORD WINAPI WineRunServer()
393 {
394 // Retrieve an instance
395 cs130_ryutaro 1.1 HINSTANCE hInstance = GetModuleHandle( NULL );
396
397 // Create a window
398 HWND hwnd = WineCreateWindow( hInstance );
399 if( hwnd == NULL ){
|
400 cs130_ryutaro 1.2 trace( "%d: Window could not be created %ld\n", __LINE__, GetLastError() );
|
401 cs130_ryutaro 1.1 ExitThread( TH_WINDOW_ERROR );
402 }
403
404 // start winsock
405 WSADATA wsaData;
406 if( WSAStartup_w( MAKEWORD( 2, 2 ), &wsaData ) != 0 ){
407
408 // print out the Error Code to be thorough
|
409 cs130_ryutaro 1.2 trace( "%d: WSAStartup() failed with error code: %d\n", __LINE__, WSAGetLastError() );
|
410 cs130_ryutaro 1.1 ExitThread( TH_START_ERROR );
411 }
412
413 // Create a socket.
414 SOCKET sock = socket_w( AF_INET, SOCK_STREAM, IPPROTO_TCP );
if( sock == INVALID_SOCKET ){
|
415 cs130_ryutaro 1.2 trace( "%d: socket error: %d\n", __LINE__, WSAGetLastError() );
|
416 cs130_ryutaro 1.1 ExitThread( TH_SOCKET_ERROR );
417 }
418
419 // Bind the socket.
|
420 cs130_ryutaro 1.2 SOCKADDR_IN sockAddr;
|
421 cs130_ryutaro 1.1 sockAddr.sin_family = AF_INET;
422 sockAddr.sin_addr.s_addr = inet_addr( "127.0.0.1" );
423 sockAddr.sin_port = htons( PORT_NUM );
424 if( bind( sock, (SOCKADDR*) &sockAddr, sizeof( sockAddr ) ) == SOCKET_ERROR ){
|
425 cs130_ryutaro 1.2 trace( "%d: bind failed weith error code %d\n", __LINE__, WSAGetLastError() );
|
426 cs130_ryutaro 1.1 closesocket( sock );
427 ExitThread( TH_BIND_ERROR );
428
429 }
430
431 // Listen on the socket.
432 if ( listen( sock, 1 ) == SOCKET_ERROR ){
|
433 cs130_ryutaro 1.2 trace( "%d: listen error with error code %d.\n", __LINE__, WSAGetLastError() );
|
434 cs130_ryutaro 1.1 closesocket( sock );
ExitThread( TH_LISTEN_ERROR );
}
435
436 // make the socket asynchronous and notify of read, write, connect and close events
437 if( WSAAsyncSelect( sock, hwnd, ASYNC_EVENT, FD_WRITE | FD_ACCEPT |FD_READ | FD_CLOSE ) == SOCKET_ERROR ){
438
|
439 cs130_ryutaro 1.2 trace( "%d: WSAAsyncSelect Failed %d\n", __LINE__, WSAGetLastError() );
|
440 cs130_ryutaro 1.1 closesocket( sock );
441 ExitThread( TH_SELECT_ERROR );
442
443 }
444
|
445 cs130_ryutaro 1.2 trace( "listening and going to loop %ld\n", GetCurrentThreadId() );
|
446 cs130_ryutaro 1.1
447 BOOL retVal;
448 MSG msg;
449 while( ( retVal = GetMessage( &msg, NULL, 0, 0 ) ) != 0 ){
450
451 if( retVal == -1 ){
452
453 // handle the error and possibly exit
|
454 cs130_ryutaro 1.2 trace( "%d: GetMessage error %ld\n", __LINE__, GetLastError() );
|
455 cs130_ryutaro 1.1 closesocket( sock );
456 ExitThread( TH_MSG_ERROR );
457 }
458
459 // suspend the other thread
460 SuspendThread( ClientThread.handle );
461
462 // Translate and dispatch the message
463 TranslateMessage( &msg );
464 DispatchMessage( &msg );
465
|
466 cs130_ryutaro 1.2 trace( "%ld still here?\n", GetCurrentThreadId() );
|
467 cs130_ryutaro 1.1
468 ResumeThread( ClientThread.handle );
469
470 }
471
472 return 0;
473 }
474
475 /* client */
476 static DWORD WINAPI WineRunClient()
477 {
478 // Retrieve an instance
479 HINSTANCE hInstance = GetModuleHandle( NULL );
480
481 // Create a window
482 HWND hwnd = WineCreateWindow( hInstance );
483 if( hwnd == NULL ){
|
484 cs130_ryutaro 1.2 trace( "%d: Window could not be created %ld\n", __LINE__, GetLastError() );
|
485 cs130_ryutaro 1.1 ExitThread( TH_WINDOW_ERROR );
486 }
487
488 // start winsock
489 WSADATA wsaData;
490 if( WSAStartup_w( MAKEWORD( 2, 2 ), &wsaData ) != 0 ){
491
492 // print out the Error Code to be thorough
|
493 cs130_ryutaro 1.2 trace( "%d: WSAStartup() failed with error code: %d\n", __LINE__, WSAGetLastError() );
|
494 cs130_ryutaro 1.1 ExitThread( TH_START_ERROR );
495 }
496
497 // Create a socket. -- This is a TCP test
498 SOCKET sock = socket_w( AF_INET, SOCK_STREAM, IPPROTO_TCP );
499 if ( sock == INVALID_SOCKET ) {
|
500 cs130_ryutaro 1.2 trace( "%d: socket returned with error code: %d\n", __LINE__, WSAGetLastError() );
|
501 cs130_ryutaro 1.1 ExitThread( TH_SOCKET_ERROR );
502 }
503
504 // make the socket asynchronous and notify of read, write, connect and close events
505 // this is the client socket
506 if( WSAAsyncSelect( sock, hwnd, ASYNC_EVENT, FD_WRITE | FD_CONNECT | FD_READ | FD_CLOSE ) == SOCKET_ERROR ){
|
507 cs130_ryutaro 1.2 trace( "%d: WSAAsyncSelect Failed %d\n", __LINE__, WSAGetLastError() );
|
508 cs130_ryutaro 1.1 closesocket( sock );
509 ExitThread( TH_SELECT_ERROR );
510 }
511
512 /* connect */
|
513 cs130_ryutaro 1.2 SOCKADDR_IN sockAddr;
|
514 cs130_ryutaro 1.1 sockAddr.sin_family = AF_INET;
515 sockAddr.sin_addr.s_addr = inet_addr( "127.0.0.1" );
516 sockAddr.sin_port = htons( PORT_NUM );
517 if( connect( sock, (SOCKADDR*) &sockAddr, sizeof( sockAddr ) ) == SOCKET_ERROR ){
518 if( WSAGetLastError() != WSAEWOULDBLOCK ){
|
519 cs130_ryutaro 1.2 trace( "%d: Failed to connect.: %d\n", __LINE__, WSAGetLastError() );
|
520 cs130_ryutaro 1.1 closesocket( sock );
521 ExitThread( TH_CONNECT_ERROR );
522 }
523 }
524
525 BOOL retVal;
526 MSG msg;
527 while( ( retVal = GetMessage( &msg, NULL, 0, 0 ) ) != 0 ){
528
529 if( retVal == -1 ){
530
531 // handle the error and possibly exit
|
532 cs130_ryutaro 1.2 trace( "%d: GetMessage error %ld\n", __LINE__, GetLastError() );
|
533 cs130_ryutaro 1.1 closesocket( sock );
534 ExitThread( TH_MSG_ERROR );
535 }
536
537 SuspendThread( ServerThread.handle );
538
539 // Translate and dispatch the message
540 TranslateMessage( &msg );
541 DispatchMessage( &msg );
542
|
543 cs130_ryutaro 1.2 //trace( "%ld still here?\n", GetCurrentThreadId() );
|
544 cs130_ryutaro 1.1 ResumeThread( ServerThread.handle );
545 }
546 return 0;
547 }
548
549 /* close thread handles and finish up winsock dll */
550 static void WineThreadCleanUp()
551 {
552 if( ServerThread.handle )
553 CloseHandle( ServerThread.handle );
554
555 if( ClientThread.handle )
556 CloseHandle( ClientThread.handle );
557 }
558
559 /* creates the buffer that the client sends */
560 static void WineCreateFile()
561 {
562 /* initialize just in case */
563 memset( FileBuf, 0, sizeof( FileBuf ) );
564
565 cs130_ryutaro 1.1 /* just customize this any way you want */
566 memset( FileBuf, 'W', PACKET_SZ );
567 memset( FileBuf + PACKET_SZ, 'I', PACKET_SZ );
568 memset( FileBuf + ( 2 * PACKET_SZ ), 'N', PACKET_SZ );
569 memset( FileBuf + ( 3 * PACKET_SZ ), 'E', 3 );
570 FileBuf[FILE_SZ - 1] = (char) EOF;
571 }
572
|
573 cs130_ryutaro 1.2 START_TEST( WineWinsockAsyncTest )
|
574 cs130_ryutaro 1.1 {
575 // Create the file that we are going to send.
576 WineCreateFile();
577
578 // Initialize server and client threads
579 memset( &ServerThread, 0, sizeof( ServerThread ) );
580 memset( &ClientThread, 0, sizeof( ClientThread ) );
581
582 // create server thread
583 ServerThread.handle = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)WineRunServer,
584 NULL, 0, &ServerThread.id );
585
586 if( ServerThread.handle == NULL ){
587
|
588 cs130_ryutaro 1.2 trace( "%d: CreateThread failed %ld\n", __LINE__, GetLastError() );
|
589 cs130_ryutaro 1.1 WineThreadCleanUp();
590 return;
591 }
592
|
593 cs130_ryutaro 1.2 trace( "%ld: server thread %ld created\n", GetCurrentThreadId(), ServerThread.id );
|
594 cs130_ryutaro 1.1
595 // Wait for three seconds to let server start
596 DWORD waitRet = WaitForSingleObject( ServerThread.handle, SERVER_START_TIME );
597 if( waitRet == WAIT_FAILED ){
598
599 // WaitForSingleObject failed for whatever reason
|
600 cs130_ryutaro 1.2 trace( "%d: WaitForSingleObject failed with error code %ld\n", __LINE__, GetLastError() );
|
601 cs130_ryutaro 1.1 WineThreadCleanUp();
602 return;
603
604 }
605
606 // get the exit code of the server - error if not STILL_ACTIVE
607 DWORD threadStatus = 0;
608 if( GetExitCodeThread( ServerThread.handle, &threadStatus ) == 0 ){
609
|
610 cs130_ryutaro 1.2 trace( "%d: GetExitCodeThread failed with error code %ld\n", __LINE__, GetLastError() );
|
611 cs130_ryutaro 1.1 WineThreadCleanUp();
612 return;
613
614 }
615
|
616 cs130_ryutaro 1.2 trace( "%ld: server started successfully now creating client thread\n", GetCurrentThreadId() );
|
617 cs130_ryutaro 1.1
618 // Create client thread in suspended state
619 ClientThread.handle = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)WineRunClient,
620 NULL, 0, &ClientThread.id );
621
622 if( ClientThread.handle == NULL ){
623
|
624 cs130_ryutaro 1.2 trace( "%d: CreateThread failed %ld\n", __LINE__, GetLastError() );
|
625 cs130_ryutaro 1.1 WineThreadCleanUp();
626 return;
627 }
628
|
629 cs130_ryutaro 1.2 trace( "%ld: client thread %ld created. Now wait.\n", GetCurrentThreadId(), ClientThread.id );
|
630 cs130_ryutaro 1.1
631 // Wait for this server to suspsend itself
632 HANDLE threadHandles[NUM_THREADS_TO_WAIT] = { ServerThread.handle, ClientThread.handle };
633 waitRet = WaitForMultipleObjects( NUM_THREADS_TO_WAIT, threadHandles, TRUE, MAX_WAIT_TIME );
634 if( waitRet == WAIT_FAILED ){
635
636 // WaitForSingleObject failed for whatever reason
|
637 cs130_ryutaro 1.2 trace( "%d: WaitForMultipleObjects failed with error code %ld\n", __LINE__, GetLastError() );
|
638 cs130_ryutaro 1.1 WineThreadCleanUp();
639 return;
640
641 }
642 else if( waitRet == WAIT_TIMEOUT ){
643
|
644 cs130_ryutaro 1.2 trace( "%d: Timed out while waiting for threads to finish\n", __LINE__ );
|
645 cs130_ryutaro 1.1 WineThreadCleanUp();
646 return;
647
648 }
649
650 // clean up the threads
651 WineThreadCleanUp();
652
|
653 cs130_ryutaro 1.2 trace( "%ld: main thread exiting...\n", GetCurrentThreadId() );
|
654 cs130_ryutaro 1.1 while(1);
|
655 cs130_ryutaro 1.2 }
|