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 cs130_ryutaro 1.3
|
50 cs130_ryutaro 1.1 /* struct def */
51 typedef struct
52 {
53 DWORD id;
54 HANDLE handle;
55 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 cs130_ryutaro 1.1
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 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 cs130_ryutaro 1.1 static int WSAStartup_w( WORD wVersionRequired, LPWSADATA lpWSAData )
93 {
94 int errCode = 0;
95
96 // WSAVERNOTSUPPORTED test
97 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.3 trace( "WSAVERNOTSUPPORTED test failed with error code: %d\n", 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.3 trace( "WSAFAULT test failed with error code: %d\n", 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.3 trace( "WSAStartup() failed with error code: %d\n", 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.3 trace( "WSAEAFNOSUPPORT test failed: %d %d\n", 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.3 trace( "WSAEPROTONOSUPPORT test failed: %d %d\n", 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.3 trace( "WSAEPROTONOSUPPORT test failed: %d %d\n", 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.3 trace( "Error at socket(): %d\n", 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.3 trace( "accept error %d\n", 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.3 printf( "%c", buf[i] );
|
248 cs130_ryutaro 1.1 i++;
249 }
|
250 cs130_ryutaro 1.3 printf( "\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.3 printf( "%c", buf[j] );
|
274 cs130_ryutaro 1.1 j++;
275 }
|
276 cs130_ryutaro 1.3 printf( "\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 ExitThread( 0 );
288 }
289 }
290 break;
291
292 case FD_WRITE:
293
294 // don't do anything here for server
295 if( GetCurrentThreadId() == ServerThread.id )
296 break;
297
298 // enter an infinite loop
299 BOOL notDone = TRUE;
300 while( notDone ){
301
302 // determine how many bytes to send
303 int bytesToSend = 0;
304 if( sizeof( FileBuf ) - ClientThread.bytesSent < PACKET_SZ ){
305
306 cs130_ryutaro 1.1 // the bytes remaining to send is smaller than packet size
307 bytesToSend = (int) ( sizeof( FileBuf ) - ClientThread.bytesSent );
308 notDone = FALSE;
309
310 }
311 else{
312
313 // the bytes remaining is greater than or equal to PACKET_SZ
314 bytesToSend = PACKET_SZ;
315
316 }
317
318 memcpy( buf, FileBuf + ClientThread.bytesSent, bytesToSend );
319 ClientThread.bytesSent += bytesToSend;
320
321 // send the packet off to the Server if it is filled
322 if( send( socket, buf, bytesToSend, 0 ) == SOCKET_ERROR ){
323
324 // check if the network buffer is full and can send no more
325 // data. If so then break from the loop
326 if( WSAGetLastError() == WSAEWOULDBLOCK ){
|
327 cs130_ryutaro 1.2 // break from the loop buffer is full
|
328 cs130_ryutaro 1.1 break;
329 }
330 else{ // another error
331 return 0;
332 }
333 }
334
|
335 cs130_ryutaro 1.2 trace( "%ld sent: ", GetCurrentThreadId() );
|
336 cs130_ryutaro 1.1 j = 0;
337 while( j < PACKET_SZ && buf[j] != (char)EOF ){
|
338 cs130_ryutaro 1.3 printf( "%c", buf[j] );
|
339 cs130_ryutaro 1.1 j++;
340 }
|
341 cs130_ryutaro 1.3 printf( "\n" );
|
342 cs130_ryutaro 1.1 }
343 break;
344 }
345 }
346 return DefWindowProc( hWnd, msg, wParam, lParam );
347 }
348
349 /*
350 Creates a hidden window object.
351
352 input:
353 none
354 output:
355 window handle
356 */
357 static HWND WineCreateWindow( HINSTANCE hInstance )
358 {
359 // initialize the window class attributes.
|
360 cs130_ryutaro 1.2 WNDCLASS windowClass;
361 //windowClass = new WNDCLASS;
362 windowClass.lpszClassName = "Hidden_Winsock_Window";
363 windowClass.style = CS_HREDRAW | CS_VREDRAW;
364 windowClass.lpfnWndProc = WndProcedure;
365 windowClass.cbClsExtra = 0;
366 windowClass.cbWndExtra = 0;
367 windowClass.hInstance = hInstance;
368 windowClass.hIcon = NULL;
369 windowClass.hCursor = NULL;
370 windowClass.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
371 windowClass.lpszMenuName = NULL;
372 RegisterClass(&windowClass);
|
373 cs130_ryutaro 1.1
374 // create window
375 return CreateWindow(
376 "Hidden_Winsock_Window",
377 "Winsock Window",
378 WS_OVERLAPPEDWINDOW,
379 CW_USEDEFAULT,
380 CW_USEDEFAULT,
381 CW_USEDEFAULT,
382 CW_USEDEFAULT,
383 NULL,
384 NULL,
385 hInstance,
386 NULL
387 );
388 }
389
390 /* server */
391 static DWORD WINAPI WineRunServer()
392 {
393 // Retrieve an instance
394 cs130_ryutaro 1.1 HINSTANCE hInstance = GetModuleHandle( NULL );
395
396 // Create a window
397 HWND hwnd = WineCreateWindow( hInstance );
398 if( hwnd == NULL ){
|
399 cs130_ryutaro 1.3 trace( "Window could not be created %ld\n", GetLastError() );
|
400 cs130_ryutaro 1.1 ExitThread( TH_WINDOW_ERROR );
401 }
402
403 // start winsock
404 WSADATA wsaData;
405 if( WSAStartup_w( MAKEWORD( 2, 2 ), &wsaData ) != 0 ){
406
407 // print out the Error Code to be thorough
|
408 cs130_ryutaro 1.3 trace( "WSAStartup() failed with error code: %d\n", WSAGetLastError() );
|
409 cs130_ryutaro 1.1 ExitThread( TH_START_ERROR );
410 }
411
412 // Create a socket.
413 SOCKET sock = socket_w( AF_INET, SOCK_STREAM, IPPROTO_TCP );
if( sock == INVALID_SOCKET ){
|
414 cs130_ryutaro 1.3 trace( "socket error: %d\n", WSAGetLastError() );
|
415 cs130_ryutaro 1.1 ExitThread( TH_SOCKET_ERROR );
416 }
417
418 // Bind the socket.
|
419 cs130_ryutaro 1.2 SOCKADDR_IN sockAddr;
|
420 cs130_ryutaro 1.1 sockAddr.sin_family = AF_INET;
421 sockAddr.sin_addr.s_addr = inet_addr( "127.0.0.1" );
422 sockAddr.sin_port = htons( PORT_NUM );
423 if( bind( sock, (SOCKADDR*) &sockAddr, sizeof( sockAddr ) ) == SOCKET_ERROR ){
|
424 cs130_ryutaro 1.3 trace( "bind failed weith error code %d\n", WSAGetLastError() );
|
425 cs130_ryutaro 1.1 closesocket( sock );
426 ExitThread( TH_BIND_ERROR );
427
428 }
429
430 // Listen on the socket.
431 if ( listen( sock, 1 ) == SOCKET_ERROR ){
|
432 cs130_ryutaro 1.3 trace( "listen error with error code %d.\n", WSAGetLastError() );
|
433 cs130_ryutaro 1.1 closesocket( sock );
ExitThread( TH_LISTEN_ERROR );
}
434
435 // make the socket asynchronous and notify of read, write, connect and close events
436 if( WSAAsyncSelect( sock, hwnd, ASYNC_EVENT, FD_WRITE | FD_ACCEPT |FD_READ | FD_CLOSE ) == SOCKET_ERROR ){
437
|
438 cs130_ryutaro 1.3 trace( "WSAAsyncSelect Failed %d\n", WSAGetLastError() );
|
439 cs130_ryutaro 1.1 closesocket( sock );
440 ExitThread( TH_SELECT_ERROR );
441
442 }
443
|
444 cs130_ryutaro 1.2 trace( "listening and going to loop %ld\n", GetCurrentThreadId() );
|
445 cs130_ryutaro 1.1
446 BOOL retVal;
447 MSG msg;
448 while( ( retVal = GetMessage( &msg, NULL, 0, 0 ) ) != 0 ){
449
450 if( retVal == -1 ){
451
452 // handle the error and possibly exit
|
453 cs130_ryutaro 1.3 trace( "GetMessage error %ld\n", GetLastError() );
|
454 cs130_ryutaro 1.1 closesocket( sock );
455 ExitThread( TH_MSG_ERROR );
456 }
|
457 cs130_ryutaro 1.3
|
458 cs130_ryutaro 1.1 // Translate and dispatch the message
459 TranslateMessage( &msg );
460 DispatchMessage( &msg );
461
462 }
463
464 return 0;
465 }
466
467 /* client */
468 static DWORD WINAPI WineRunClient()
469 {
470 // Retrieve an instance
471 HINSTANCE hInstance = GetModuleHandle( NULL );
472
473 // Create a window
474 HWND hwnd = WineCreateWindow( hInstance );
475 if( hwnd == NULL ){
|
476 cs130_ryutaro 1.3 trace( "Window could not be created %ld\n", GetLastError() );
|
477 cs130_ryutaro 1.1 ExitThread( TH_WINDOW_ERROR );
478 }
479
480 // start winsock
481 WSADATA wsaData;
482 if( WSAStartup_w( MAKEWORD( 2, 2 ), &wsaData ) != 0 ){
483
484 // print out the Error Code to be thorough
|
485 cs130_ryutaro 1.3 trace( "WSAStartup() failed with error code: %d\n", WSAGetLastError() );
|
486 cs130_ryutaro 1.1 ExitThread( TH_START_ERROR );
487 }
488
489 // Create a socket. -- This is a TCP test
490 SOCKET sock = socket_w( AF_INET, SOCK_STREAM, IPPROTO_TCP );
491 if ( sock == INVALID_SOCKET ) {
|
492 cs130_ryutaro 1.3 trace( "socket returned with error code: %d\n", WSAGetLastError() );
|
493 cs130_ryutaro 1.1 ExitThread( TH_SOCKET_ERROR );
494 }
495
496 // make the socket asynchronous and notify of read, write, connect and close events
497 // this is the client socket
498 if( WSAAsyncSelect( sock, hwnd, ASYNC_EVENT, FD_WRITE | FD_CONNECT | FD_READ | FD_CLOSE ) == SOCKET_ERROR ){
|
499 cs130_ryutaro 1.3 trace( "WSAAsyncSelect Failed %d\n", WSAGetLastError() );
|
500 cs130_ryutaro 1.1 closesocket( sock );
501 ExitThread( TH_SELECT_ERROR );
502 }
503
504 /* connect */
|
505 cs130_ryutaro 1.2 SOCKADDR_IN sockAddr;
|
506 cs130_ryutaro 1.1 sockAddr.sin_family = AF_INET;
507 sockAddr.sin_addr.s_addr = inet_addr( "127.0.0.1" );
508 sockAddr.sin_port = htons( PORT_NUM );
509 if( connect( sock, (SOCKADDR*) &sockAddr, sizeof( sockAddr ) ) == SOCKET_ERROR ){
510 if( WSAGetLastError() != WSAEWOULDBLOCK ){
|
511 cs130_ryutaro 1.3 trace( "Failed to connect.: %d\n", WSAGetLastError() );
|
512 cs130_ryutaro 1.1 closesocket( sock );
513 ExitThread( TH_CONNECT_ERROR );
514 }
515 }
516
517 BOOL retVal;
518 MSG msg;
519 while( ( retVal = GetMessage( &msg, NULL, 0, 0 ) ) != 0 ){
520
521 if( retVal == -1 ){
522
523 // handle the error and possibly exit
|
524 cs130_ryutaro 1.3 trace( "GetMessage error %ld\n", GetLastError() );
|
525 cs130_ryutaro 1.1 closesocket( sock );
526 ExitThread( TH_MSG_ERROR );
527 }
528
529 // Translate and dispatch the message
530 TranslateMessage( &msg );
531 DispatchMessage( &msg );
|
532 cs130_ryutaro 1.3
|
533 cs130_ryutaro 1.1 }
534 return 0;
535 }
536
537 /* close thread handles and finish up winsock dll */
538 static void WineThreadCleanUp()
539 {
540 if( ServerThread.handle )
541 CloseHandle( ServerThread.handle );
542
543 if( ClientThread.handle )
544 CloseHandle( ClientThread.handle );
545 }
546
547 /* creates the buffer that the client sends */
548 static void WineCreateFile()
549 {
550 /* initialize just in case */
551 memset( FileBuf, 0, sizeof( FileBuf ) );
552
553 /* just customize this any way you want */
554 cs130_ryutaro 1.1 memset( FileBuf, 'W', PACKET_SZ );
555 memset( FileBuf + PACKET_SZ, 'I', PACKET_SZ );
556 memset( FileBuf + ( 2 * PACKET_SZ ), 'N', PACKET_SZ );
557 memset( FileBuf + ( 3 * PACKET_SZ ), 'E', 3 );
558 FileBuf[FILE_SZ - 1] = (char) EOF;
559 }
560
|
561 cs130_ryutaro 1.2 START_TEST( WineWinsockAsyncTest )
|
562 cs130_ryutaro 1.1 {
563 // Create the file that we are going to send.
564 WineCreateFile();
565
566 // Initialize server and client threads
567 memset( &ServerThread, 0, sizeof( ServerThread ) );
568 memset( &ClientThread, 0, sizeof( ClientThread ) );
569
570 // create server thread
571 ServerThread.handle = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)WineRunServer,
572 NULL, 0, &ServerThread.id );
573
574 if( ServerThread.handle == NULL ){
575
|
576 cs130_ryutaro 1.3 trace( "CreateThread failed %ld\n", GetLastError() );
|
577 cs130_ryutaro 1.1 WineThreadCleanUp();
578 return;
579 }
580
|
581 cs130_ryutaro 1.2 trace( "%ld: server thread %ld created\n", GetCurrentThreadId(), ServerThread.id );
|
582 cs130_ryutaro 1.1
583 // Wait for three seconds to let server start
584 DWORD waitRet = WaitForSingleObject( ServerThread.handle, SERVER_START_TIME );
585 if( waitRet == WAIT_FAILED ){
586
587 // WaitForSingleObject failed for whatever reason
|
588 cs130_ryutaro 1.3 trace( "WaitForSingleObject failed with error code %ld\n", GetLastError() );
|
589 cs130_ryutaro 1.1 WineThreadCleanUp();
590 return;
591
592 }
593
594 // get the exit code of the server - error if not STILL_ACTIVE
595 DWORD threadStatus = 0;
596 if( GetExitCodeThread( ServerThread.handle, &threadStatus ) == 0 ){
597
|
598 cs130_ryutaro 1.3 trace( "GetExitCodeThread failed with error code %ld\n",GetLastError() );
|
599 cs130_ryutaro 1.1 WineThreadCleanUp();
600 return;
601
602 }
603
|
604 cs130_ryutaro 1.2 trace( "%ld: server started successfully now creating client thread\n", GetCurrentThreadId() );
|
605 cs130_ryutaro 1.1
606 // Create client thread in suspended state
607 ClientThread.handle = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)WineRunClient,
608 NULL, 0, &ClientThread.id );
609
610 if( ClientThread.handle == NULL ){
611
|
612 cs130_ryutaro 1.3 trace( "CreateThread failed %ld\n", GetLastError() );
|
613 cs130_ryutaro 1.1 WineThreadCleanUp();
614 return;
615 }
616
|
617 cs130_ryutaro 1.2 trace( "%ld: client thread %ld created. Now wait.\n", GetCurrentThreadId(), ClientThread.id );
|
618 cs130_ryutaro 1.1
619 // Wait for this server to suspsend itself
620 HANDLE threadHandles[NUM_THREADS_TO_WAIT] = { ServerThread.handle, ClientThread.handle };
621 waitRet = WaitForMultipleObjects( NUM_THREADS_TO_WAIT, threadHandles, TRUE, MAX_WAIT_TIME );
622 if( waitRet == WAIT_FAILED ){
623
624 // WaitForSingleObject failed for whatever reason
|
625 cs130_ryutaro 1.3 trace( "WaitForMultipleObjects failed with error code %ld\n", GetLastError() );
|
626 cs130_ryutaro 1.1 WineThreadCleanUp();
627 return;
628
629 }
630 else if( waitRet == WAIT_TIMEOUT ){
631
|
632 cs130_ryutaro 1.3 trace( "Timed out while waiting for threads to finish\n" );
|
633 cs130_ryutaro 1.1 WineThreadCleanUp();
634 return;
635
636 }
637
638 // clean up the threads
639 WineThreadCleanUp();
640
|
641 cs130_ryutaro 1.2 trace( "%ld: main thread exiting...\n", GetCurrentThreadId() );
642 }
|