1 cs130_ryutaro 1.1 /*
2 * Unit test suite for winsock functions
3 *
4 * Copyright 2002 Martin Wilck
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21 #include <stdarg.h>
22 cs130_ryutaro 1.1
23 #include <windef.h>
24 #include <winbase.h>
25 #include <winsock2.h>
26 #include <mswsock.h>
27 #include "wine/test.h"
28 #include <winnt.h>
29 #include <winerror.h>
30
31 #define MAX_CLIENTS 4 /* Max number of clients */
32 #define NUM_TESTS 3 /* Number of tests performed */
33 #define FIRST_CHAR 'A' /* First character in transferred pattern */
34 #define BIND_SLEEP 10 /* seconds to wait between attempts to bind() */
35 #define BIND_TRIES 6 /* Number of bind() attempts */
36 #define TEST_TIMEOUT 30 /* seconds to wait before killing child threads
37 after server initialization, if something hangs */
38 #define ASYNC_EVENT (WM_USER +5) /* the message we'll use for our async notification */
39
40 #define wsa_ok(op, cond, msg) \
41 do { \
42 int tmp, err = 0; \
43 cs130_ryutaro 1.1 tmp = op; \
44 if ( !(cond tmp) ) err = WSAGetLastError(); \
45 ok ( cond tmp, msg, GetCurrentThreadId(), err); \
46 } while (0);
47
48
49 /**************** Structs and typedefs ***************/
50
51 typedef struct thread_info
52 {
53 HANDLE thread;
54 DWORD id;
55 } thread_info;
56
57 /* Information in the server about open client connections */
58 typedef struct sock_info
59 {
60 SOCKET s;
61 struct sockaddr_in addr;
62 struct sockaddr_in peer;
63 char *buf;
64 cs130_ryutaro 1.1 int nread;
65 } sock_info;
66
67 /* Test parameters for both server & client */
68 typedef struct test_params
69 {
70 int sock_type;
71 int sock_prot;
72 const char *inet_addr;
73 short inet_port;
74 int chunk_size;
75 int n_chunks;
76 int n_clients;
77 } test_params;
78
79 /* server-specific test parameters */
80 typedef struct server_params
81 {
82 test_params *general;
83 DWORD sock_flags;
84 int buflen;
85 cs130_ryutaro 1.1 } server_params;
86
87 /* client-specific test parameters */
88 typedef struct client_params
89 {
90 test_params *general;
91 DWORD sock_flags;
92 int buflen;
93 } client_params;
94
95 /* This type combines all information for setting up a test scenario */
96 typedef struct test_setup
97 {
98 test_params general;
99 LPVOID srv;
100 server_params srv_params;
101 LPVOID clt;
102 client_params clt_params;
103 } test_setup;
104
105 /* Thread local storage for server */
106 cs130_ryutaro 1.1 typedef struct server_memory
107 {
108 SOCKET s;
109 struct sockaddr_in addr;
110 sock_info sock[MAX_CLIENTS];
111 } server_memory;
112
113 /* Thread local storage for client */
114 typedef struct client_memory
115 {
116 SOCKET s;
117 struct sockaddr_in addr;
118 char *send_buf;
119 char *recv_buf;
120 } client_memory;
121
122 /* Things specific to async tests */
123 typedef struct async_param_t
124 {
125 server_params *svc_params;
126 int numClients;
127 cs130_ryutaro 1.1 char *fileBuf;
128 } async_param_t;
129
130 /**************** Static variables ***************/
131
132 static DWORD tls; /* Thread local storage index */
133 static HANDLE thread[1+MAX_CLIENTS];
134 static DWORD thread_id[1+MAX_CLIENTS];
135 static HANDLE server_ready;
136 static HANDLE client_ready[MAX_CLIENTS];
137 static int client_id;
138 static async_param_t async_params; /* async structure */
139
140 /**************** General utility functions ***************/
141
142 static void set_so_opentype ( BOOL overlapped )
143 {
144 int optval = !overlapped, newval, len = sizeof (int);
145
146 ok ( setsockopt ( INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE,
147 (LPVOID) &optval, sizeof (optval) ) == 0,
148 cs130_ryutaro 1.1 "setting SO_OPENTYPE failed\n" );
149 ok ( getsockopt ( INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE,
150 (LPVOID) &newval, &len ) == 0,
151 "getting SO_OPENTYPE failed\n" );
152 ok ( optval == newval, "failed to set SO_OPENTYPE\n" );
153 }
154
155 static int set_blocking ( SOCKET s, BOOL blocking )
156 {
157 u_long val = !blocking;
158 return ioctlsocket ( s, FIONBIO, &val );
159 }
160
161 static void fill_buffer ( char *buf, int chunk_size, int n_chunks )
162 {
163 char c, *p;
164 for ( c = FIRST_CHAR, p = buf; c < FIRST_CHAR + n_chunks; c++, p += chunk_size )
165 memset ( p, c, chunk_size );
166 }
167
168 static char* test_buffer ( char *buf, int chunk_size, int n_chunks )
169 cs130_ryutaro 1.1 {
170 char c, *p;
171 int i;
172 for ( c = FIRST_CHAR, p = buf; c < FIRST_CHAR + n_chunks; c++, p += chunk_size )
173 {
174 for ( i = 0; i < chunk_size; i++ )
175 if ( p[i] != c ) return p + i;
176 }
177 return NULL;
178 }
179
180 /*
181 * This routine is called when a client / server does not expect any more data,
182 * but needs to acknowedge the closing of the connection (by reasing 0 bytes).
183 */
184 static void read_zero_bytes ( SOCKET s )
185 {
186 char buf[256];
187 int tmp, n = 0;
188 while ( ( tmp = recv ( s, buf, 256, 0 ) ) > 0 )
189 n += tmp;
190 cs130_ryutaro 1.1 ok ( n <= 0, "garbage data received: %d bytes\n", n );
191 }
192
193 static int do_synchronous_send ( SOCKET s, char *buf, int buflen, int sendlen )
194 {
195 char* last = buf + buflen, *p;
196 int n = 1;
197 for ( p = buf; n > 0 && p < last; p += n )
198 n = send ( s, p, min ( sendlen, last - p ), 0 );
199 wsa_ok ( n, 0 <=, "do_synchronous_send (%lx): error %d\n" );
200 return p - buf;
201 }
202
203 static int do_synchronous_recv ( SOCKET s, char *buf, int buflen, int recvlen )
204 {
205 char* last = buf + buflen, *p;
206 int n = 1;
207 for ( p = buf; n > 0 && p < last; p += n )
208 n = recv ( s, p, min ( recvlen, last - p ), 0 );
209 wsa_ok ( n, 0 <=, "do_synchronous_recv (%lx): error %d:\n" );
210 return p - buf;
211 cs130_ryutaro 1.1 }
212
213 /*
214 * Call this routine right after thread startup.
215 * SO_OPENTYPE must by 0, regardless what the server did.
216 */
217 static void check_so_opentype (void)
218 {
219 int tmp = 1, len;
220 len = sizeof (tmp);
221 getsockopt ( INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE, (LPVOID) &tmp, &len );
222 ok ( tmp == 0, "check_so_opentype: wrong startup value of SO_OPENTYPE: %d\n", tmp );
223 }
224
225 /**************** Server utility functions ***************/
226
227 /*
228 * Even if we have closed our server socket cleanly,
229 * the OS may mark the address "in use" for some time -
230 * this happens with native Linux apps, too.
231 */
232 cs130_ryutaro 1.1 static void do_bind ( SOCKET s, struct sockaddr* addr, int addrlen )
233 {
234 int err, wsaerr = 0, n_try = BIND_TRIES;
235
236 while ( ( err = bind ( s, addr, addrlen ) ) != 0 &&
237 ( wsaerr = WSAGetLastError () ) == WSAEADDRINUSE &&
238 n_try-- >= 0)
239 {
240 trace ( "address in use, waiting ...\n" );
241 Sleep ( 1000 * BIND_SLEEP );
242 }
243 ok ( err == 0, "failed to bind: %d\n", wsaerr );
244 }
245
246 static void server_start ( server_params *par )
247 {
248 int i;
249 test_params *gen = par->general;
250 server_memory *mem = (LPVOID) LocalAlloc ( LPTR, sizeof (server_memory));
251
252 TlsSetValue ( tls, mem );
253 cs130_ryutaro 1.1 mem->s = WSASocketA ( AF_INET, gen->sock_type, gen->sock_prot,
254 NULL, 0, par->sock_flags );
255 ok ( mem->s != INVALID_SOCKET, "Server: WSASocket failed\n" );
256
257 mem->addr.sin_family = AF_INET;
258 mem->addr.sin_addr.s_addr = inet_addr ( gen->inet_addr );
259 mem->addr.sin_port = htons ( gen->inet_port );
260
261 for (i = 0; i < MAX_CLIENTS; i++)
262 {
263 mem->sock[i].s = INVALID_SOCKET;
264 mem->sock[i].buf = (LPVOID) LocalAlloc ( LPTR, gen->n_chunks * gen->chunk_size );
265 mem->sock[i].nread = 0;
266 }
267
268 if ( gen->sock_type == SOCK_STREAM )
269 do_bind ( mem->s, (struct sockaddr*) &mem->addr, sizeof (mem->addr) );
270 }
271
272 static void server_stop (void)
273 {
274 cs130_ryutaro 1.1 int i;
275 server_memory *mem = TlsGetValue ( tls );
276 for (i = 0; i < MAX_CLIENTS; i++ )
277 {
278 LocalFree ( (HANDLE) mem->sock[i].buf );
279 if ( mem->sock[i].s != INVALID_SOCKET )
280 closesocket ( mem->sock[i].s );
281 }
282 ok ( closesocket ( mem->s ) == 0, "closesocket failed\n" );
283 LocalFree ( (HANDLE) mem );
284 ExitThread ( GetCurrentThreadId () );
285 }
286
287 /**************** Client utilitiy functions ***************/
288
289 static void client_start ( client_params *par )
290 {
291 test_params *gen = par->general;
292 client_memory *mem = (LPVOID) LocalAlloc (LPTR, sizeof (client_memory));
293
294 TlsSetValue ( tls, mem );
295 cs130_ryutaro 1.1
296 WaitForSingleObject ( server_ready, INFINITE );
297
298 mem->s = WSASocketA ( AF_INET, gen->sock_type, gen->sock_prot,
299 NULL, 0, par->sock_flags );
300
301 mem->addr.sin_family = AF_INET;
302 mem->addr.sin_addr.s_addr = inet_addr ( gen->inet_addr );
303 mem->addr.sin_port = htons ( gen->inet_port );
304
305 ok ( mem->s != INVALID_SOCKET, "Client: WSASocket failed\n" );
306
307 mem->send_buf = (LPVOID) LocalAlloc ( LPTR, 2 * gen->n_chunks * gen->chunk_size );
308 mem->recv_buf = mem->send_buf + gen->n_chunks * gen->chunk_size;
309 fill_buffer ( mem->send_buf, gen->chunk_size, gen->n_chunks );
310
311 SetEvent ( client_ready[client_id] );
312 /* Wait for the other clients to come up */
313 WaitForMultipleObjects ( min ( gen->n_clients, MAX_CLIENTS ), client_ready, TRUE, INFINITE );
314 }
315
316 cs130_ryutaro 1.1 static void client_stop (void)
317 {
318 client_memory *mem = TlsGetValue ( tls );
319 wsa_ok ( closesocket ( mem->s ), 0 ==, "closesocket error (%lx): %d\n" );
320 LocalFree ( (HANDLE) mem->send_buf );
321 LocalFree ( (HANDLE) mem );
322 ExitThread(0);
323 }
324
325 /**************** Servers ***************/
326
327 /*
328 * simple_server: A very basic server doing synchronous IO.
329 */
330 static VOID WINAPI simple_server ( server_params *par )
331 {
332 test_params *gen = par->general;
333 server_memory *mem;
334 int n_recvd, n_sent, n_expected = gen->n_chunks * gen->chunk_size, tmp, i,
335 id = GetCurrentThreadId();
336 char *p;
337 cs130_ryutaro 1.1
338 trace ( "simple_server (%x) starting\n", id );
339
340 set_so_opentype ( FALSE ); /* non-overlapped */
341 server_start ( par );
342 mem = TlsGetValue ( tls );
343
344 wsa_ok ( set_blocking ( mem->s, TRUE ), 0 ==, "simple_server (%lx): failed to set blocking mode: %d\n");
345 wsa_ok ( listen ( mem->s, SOMAXCONN ), 0 ==, "simple_server (%lx): listen failed: %d\n");
346
347 trace ( "simple_server (%x) ready\n", id );
348 SetEvent ( server_ready ); /* notify clients */
349
350 for ( i = 0; i < min ( gen->n_clients, MAX_CLIENTS ); i++ )
351 {
352 trace ( "simple_server (%x): waiting for client\n", id );
353
354 /* accept a single connection */
355 tmp = sizeof ( mem->sock[0].peer );
356 mem->sock[0].s = accept ( mem->s, (struct sockaddr*) &mem->sock[0].peer, &tmp );
357 wsa_ok ( mem->sock[0].s, INVALID_SOCKET !=, "simple_server (%lx): accept failed: %d\n" );
358 cs130_ryutaro 1.1
359 ok ( mem->sock[0].peer.sin_addr.s_addr == inet_addr ( gen->inet_addr ),
360 "simple_server (%x): strange peer address\n", id );
361
362 /* Receive data & check it */
363 n_recvd = do_synchronous_recv ( mem->sock[0].s, mem->sock[0].buf, n_expected, par->buflen );
364 ok ( n_recvd == n_expected,
365 "simple_server (%x): received less data than expected: %d of %d\n", id, n_recvd, n_expected );
366 p = test_buffer ( mem->sock[0].buf, gen->chunk_size, gen->n_chunks );
367 ok ( p == NULL, "simple_server (%x): test pattern error: %d\n", id, p - mem->sock[0].buf);
368
369 /* Echo data back */
370 n_sent = do_synchronous_send ( mem->sock[0].s, mem->sock[0].buf, n_expected, par->buflen );
371 ok ( n_sent == n_expected,
372 "simple_server (%x): sent less data than expected: %d of %d\n", id, n_sent, n_expected );
373
374 /* cleanup */
375 read_zero_bytes ( mem->sock[0].s );
376 wsa_ok ( closesocket ( mem->sock[0].s ), 0 ==, "simple_server (%lx): closesocket error: %d\n" );
377 mem->sock[0].s = INVALID_SOCKET;
378 }
379 cs130_ryutaro 1.1
380 trace ( "simple_server (%x) exiting\n", id );
381 server_stop ();
382 }
383
384 /*
385 Call back event handler for asynchronous server
386 */
387 static LRESULT CALLBACK async_server_proc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
388 {
389 SOCKET socket = (SOCKET) wParam;
390 server_memory* mem = TlsGetValue( tls );
391 struct sockaddr_in peer;
392 char *file_buf = async_params.fileBuf;
393 char *inetAddr = (char*)((async_params.svc_params)->general)->inet_addr;
394 int n_recvd, n_sent, addrLen, id = GetCurrentThreadId();
395 int eventCode, packet_len = (async_params.svc_params)->buflen;;
396
397 switch( msg ){
398
399 case ASYNC_EVENT:
400 cs130_ryutaro 1.1
401 eventCode = WSAGETSELECTEVENT( lParam );
402 switch( eventCode ){
403
404 case FD_ACCEPT:
405
406 // accept connection
407 trace( "async_server (%x): accept event\n", id );
408 addrLen = sizeof ( peer );
409 socket = accept( mem->s, (struct sockaddr*) &peer, &addrLen );
410 wsa_ok( socket, INVALID_SOCKET !=, "async_server (%lx): accept failed: %d\n" );
411
412 if( socket == INVALID_SOCKET ){
413
414 trace( "async_server (%x): exiting\n", id );
415 server_stop();
416
417 }
418
419 ok( peer.sin_addr.s_addr == inet_addr ( inetAddr ),
420 "async_server (%x): strange peer address\n", id );
421 cs130_ryutaro 1.1 break;
422
423 case FD_READ:
424
425 // server has data waiting to be read
426 n_recvd = recv( socket, file_buf, packet_len, 0 );
427 wsa_ok( n_recvd, SOCKET_ERROR !=, "recv (%lx): error %d:\n" );
428
429 if( n_recvd == SOCKET_ERROR ){
430
431 trace( "async_server (%x) exiting\n", id );
432 server_stop();
433
434 }
435
436 // Send the packet back
437 n_sent = send( socket, file_buf, n_recvd, 0 );
438 wsa_ok( n_sent, SOCKET_ERROR !=, "send (%lx): error %d:\n" );
439
440 if( n_sent == SOCKET_ERROR ){
441
442 cs130_ryutaro 1.1 trace( "async_server (%x) exiting\n", id );
443 server_stop();
444
445 }
446 break;
447
448 case FD_CLOSE:
449
450 // Close the client socket and then close the server
451 // when all clients are done.
452 trace( "async_server (%x): close event\n", id );
453 closesocket( socket );
454
455 if( --async_params.numClients == 0 ){
456
457 trace( "async_server (%x) exiting\n", id );
458 server_stop();
459
460 }
461 }
462 }
463 cs130_ryutaro 1.1
464 return DefWindowProc( hWnd, msg, wParam, lParam );
465 }
466
467 /*
468 * async_server: An event-driven server
469 */
470 static void WINAPI async_server( server_params *par )
471 {
472 int id = GetCurrentThreadId(), err;
473 test_params* gen = par->general;
474
475 // set up async_params structure
476 memset( &async_params, 0, sizeof( async_params ) );
477 async_params.svc_params = par;
478 async_params.numClients = gen->n_clients;
479 async_params.fileBuf = (LPVOID) LocalAlloc( LPTR, gen->n_chunks * gen->chunk_size );
480
481 trace( "async_server (%x) starting\n", id );
482 set_so_opentype( FALSE ); /* non-overlapped */
483 server_start( par );
484 cs130_ryutaro 1.1 server_memory *mem = TlsGetValue( tls );
485
486 wsa_ok( listen ( mem->s, SOMAXCONN ), 0 ==, "async_server (%lx): listen failed: %d\n");
487
488 // Get the current instance
489 HINSTANCE instance = GetModuleHandle( NULL );
490 ok( instance != NULL, "async_server (%x):GetModuleHandle error %ld\n", id, GetLastError() );
491 if( instance == NULL ){
492
493 trace( "async_server (%x) exiting\n", id );
494 server_stop();
495
496 }
497
498 // Create a hiddent window to handle async events
499 WNDCLASS windowClass;
500 windowClass.lpszClassName = "Hidden_Winsock_Window";
501 windowClass.style = CS_HREDRAW | CS_VREDRAW;
502 windowClass.lpfnWndProc = async_server_proc;
503 windowClass.cbClsExtra = 0;
504 windowClass.cbWndExtra = 0;
505 cs130_ryutaro 1.1 windowClass.hInstance = instance;
506 windowClass.hIcon = NULL;
507 windowClass.hCursor = NULL;
508 windowClass.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
509 windowClass.lpszMenuName = NULL;
510 ATOM classAtom = RegisterClass( &windowClass );
511 ok( classAtom != 0, "async_server (%x): RegisterClass error %ld\n", id, GetLastError() );
512 if( classAtom == 0 ){
513
514 trace( "async_server (%x) exiting\n", id );
515 server_stop();
516
517 }
518
519 HWND hwnd = CreateWindow( "Hidden_Winsock_Window",
520 "Winsock Window",
521 WS_OVERLAPPEDWINDOW,
522 CW_USEDEFAULT,
523 CW_USEDEFAULT,
524 CW_USEDEFAULT,
525 CW_USEDEFAULT,
526 cs130_ryutaro 1.1 NULL,
527 NULL,
528 instance,
529 NULL );
530
531 ok( hwnd != NULL, "async_server (%x): CreateWindowd error %ld\n", id, GetLastError() );
532 if( hwnd == NULL ){
533
534 trace ( "async_server (%x) exiting\n", id );
535 server_stop();
536
537 }
538
539 /* make the socket asynchronous */
540 err = WSAAsyncSelect( mem->s, hwnd, ASYNC_EVENT, FD_ACCEPT | FD_READ | FD_CLOSE );
541 wsa_ok( err, SOCKET_ERROR !=, "async_server (%lx): WSAAsyncSelect failed: %d\n" );
542 if( err == SOCKET_ERROR ){
543
544 trace( "async_server (%x) exiting\n", id );
545 server_stop();
546
547 cs130_ryutaro 1.1 }
548
549 trace( "async_server (%x) ready\n", id );
550 SetEvent( server_ready ); /* notify clients */
551
552 /* Wait for any event and process it when it occurs */
553 BOOL retVal;
554 MSG msg;
555 while( ( retVal = GetMessage( &msg, NULL, 0, 0 ) ) != 0 ){
556
557 ok( retVal != -1, "async_server (%x): GetMessage error %ld\n", id, GetLastError() );
558 if( retVal == -1 ){
559
560 // error: exit
561 trace( "async_server (%x) exiting\n", id );
562 server_stop();
563
564 }
565
566 // Translate and dispatch the message
567 TranslateMessage( &msg );
568 cs130_ryutaro 1.1 DispatchMessage( &msg );
569
570 }
571 }
572
573 /**************** Clients ***************/
574
575 /*
576 * simple_client: A very basic client doing synchronous IO.
577 */
578 static VOID WINAPI simple_client ( client_params *par )
579 {
580 test_params *gen = par->general;
581 client_memory *mem;
582 int n_sent, n_recvd, n_expected = gen->n_chunks * gen->chunk_size, id;
583 char *p;
584
585 id = GetCurrentThreadId();
586 trace ( "simple_client (%x): starting\n", id );
587 /* wait here because we want to call set_so_opentype before creating a socket */
588 WaitForSingleObject ( server_ready, INFINITE );
589 cs130_ryutaro 1.1 trace ( "simple_client (%x): server ready\n", id );
590
591 check_so_opentype ();
592 set_so_opentype ( FALSE ); /* non-overlapped */
593 client_start ( par );
594 mem = TlsGetValue ( tls );
595
596 /* Connect */
597 wsa_ok ( connect ( mem->s, (struct sockaddr*) &mem->addr, sizeof ( mem->addr ) ),
598 0 ==, "simple_client (%lx): connect error: %d\n" );
599 ok ( set_blocking ( mem->s, TRUE ) == 0,
600 "simple_client (%x): failed to set blocking mode\n", id );
601 trace ( "simple_client (%x) connected\n", id );
602
603 /* send data to server */
604 n_sent = do_synchronous_send ( mem->s, mem->send_buf, n_expected, par->buflen );
605 ok ( n_sent == n_expected,
606 "simple_client (%x): sent less data than expected: %d of %d\n", id, n_sent, n_expected );
607
608 /* shutdown send direction */
609 wsa_ok ( shutdown ( mem->s, SD_SEND ), 0 ==, "simple_client (%lx): shutdown failed: %d\n" );
610 cs130_ryutaro 1.1
611 /* Receive data echoed back & check it */
612 n_recvd = do_synchronous_recv ( mem->s, mem->recv_buf, n_expected, par->buflen );
613 ok ( n_recvd == n_expected,
614 "simple_client (%x): received less data than expected: %d of %d\n", id, n_recvd, n_expected );
615
616 /* check data */
617 p = test_buffer ( mem->recv_buf, gen->chunk_size, gen->n_chunks );
618 ok ( p == NULL, "simple_client (%x): test pattern error: %d\n", id, p - mem->recv_buf);
619
620 /* cleanup */
621 read_zero_bytes ( mem->s );
622 trace ( "simple_client (%x) exiting\n", id );
623 client_stop ();
624 }
625
626 /*
627 * event_client: An event-driven client
628 */
629 static void WINAPI event_client ( client_params *par )
630 {
631 cs130_ryutaro 1.1 test_params *gen = par->general;
632 client_memory *mem;
633 int id = GetCurrentThreadId(), n_expected = gen->n_chunks * gen->chunk_size,
634 tmp, err, n;
635 HANDLE event;
636 WSANETWORKEVENTS wsa_events;
637 char *send_last, *recv_last, *send_p, *recv_p;
638 long mask = FD_READ | FD_WRITE | FD_CLOSE;
639
640 trace ( "event_client (%x): starting\n", id );
641 client_start ( par );
642 trace ( "event_client (%x): server ready\n", id );
643
644 mem = TlsGetValue ( tls );
645
646 /* Prepare event notification for connect, makes socket nonblocking */
647 event = WSACreateEvent ();
648 WSAEventSelect ( mem->s, event, FD_CONNECT );
649 tmp = connect ( mem->s, (struct sockaddr*) &mem->addr, sizeof ( mem->addr ) );
650 if ( tmp != 0 && ( err = WSAGetLastError () ) != WSAEWOULDBLOCK )
651 ok ( 0, "event_client (%x): connect error: %d\n", id, err );
652 cs130_ryutaro 1.1
653 tmp = WaitForSingleObject ( event, INFINITE );
654 ok ( tmp == WAIT_OBJECT_0, "event_client (%x): wait for connect event failed: %d\n", id, tmp );
655 err = WSAEnumNetworkEvents ( mem->s, event, &wsa_events );
656 wsa_ok ( err, 0 ==, "event_client (%lx): WSAEnumNetworkEvents error: %d\n" );
657
658 err = wsa_events.iErrorCode[ FD_CONNECT_BIT ];
659 ok ( err == 0, "event_client (%x): connect error: %d\n", id, err );
660 if ( err ) goto out;
661
662 trace ( "event_client (%x) connected\n", id );
663
664 WSAEventSelect ( mem->s, event, mask );
665
666 recv_p = mem->recv_buf;
667 recv_last = mem->recv_buf + n_expected;
668 send_p = mem->send_buf;
669 send_last = mem->send_buf + n_expected;
670
671 while ( TRUE )
672 {
673 cs130_ryutaro 1.1 err = WaitForSingleObject ( event, INFINITE );
674 ok ( err == WAIT_OBJECT_0, "event_client (%x): wait failed\n", id );
675
676 err = WSAEnumNetworkEvents ( mem->s, event, &wsa_events );
677 wsa_ok ( err, 0 ==, "event_client (%lx): WSAEnumNetworkEvents error: %d\n" );
678
679 if ( wsa_events.lNetworkEvents & FD_WRITE )
680 {
681 err = wsa_events.iErrorCode[ FD_WRITE_BIT ];
682 ok ( err == 0, "event_client (%x): FD_WRITE error code: %d\n", id, err );
683
684 if ( err== 0 )
685 do
686 {
687 n = send ( mem->s, send_p, min ( send_last - send_p, par->buflen ), 0 );
688 if ( n < 0 )
689 {
690 err = WSAGetLastError ();
691 ok ( err == WSAEWOULDBLOCK, "event_client (%x): send error: %d\n", id, err );
692 }
693 else
694 cs130_ryutaro 1.1 send_p += n;
695 }
696 while ( n >= 0 && send_p < send_last );
697
698 if ( send_p == send_last )
699 {
700 trace ( "event_client (%x): all data sent - shutdown\n", id );
701 shutdown ( mem->s, SD_SEND );
702 mask &= ~FD_WRITE;
703 WSAEventSelect ( mem->s, event, mask );
704 }
705 }
706 if ( wsa_events.lNetworkEvents & FD_READ )
707 {
708 err = wsa_events.iErrorCode[ FD_READ_BIT ];
709 ok ( err == 0, "event_client (%x): FD_READ error code: %d\n", id, err );
710 if ( err != 0 ) break;
711
712 /* First read must succeed */
713 n = recv ( mem->s, recv_p, min ( recv_last - recv_p, par->buflen ), 0 );
714 wsa_ok ( n, 0 <=, "event_client (%lx): recv error: %d\n" );
715 cs130_ryutaro 1.1
716 while ( n >= 0 ) {
717 recv_p += n;
718 if ( recv_p == recv_last )
719 {
720 mask &= ~FD_READ;
721 trace ( "event_client (%x): all data received\n", id );
722 WSAEventSelect ( mem->s, event, mask );
723 break;
724 }
725 n = recv ( mem->s, recv_p, min ( recv_last - recv_p, par->buflen ), 0 );
726 if ( n < 0 && ( err = WSAGetLastError()) != WSAEWOULDBLOCK )
727 ok ( 0, "event_client (%x): read error: %d\n", id, err );
728
729 }
730 }
731 if ( wsa_events.lNetworkEvents & FD_CLOSE )
732 {
733 trace ( "event_client (%x): close event\n", id );
734 err = wsa_events.iErrorCode[ FD_CLOSE_BIT ];
735 ok ( err == 0, "event_client (%x): FD_CLOSE error code: %d\n", id, err );
736 cs130_ryutaro 1.1 break;
737 }
738 }
739
740 ok ( send_p == send_last,
741 "simple_client (%x): sent less data than expected: %d of %d\n",
742 id, send_p - mem->send_buf, n_expected );
743 ok ( recv_p == recv_last,
744 "simple_client (%x): received less data than expected: %d of %d\n",
745 id, recv_p - mem->recv_buf, n_expected );
746 recv_p = test_buffer ( mem->recv_buf, gen->chunk_size, gen->n_chunks );
747 ok ( recv_p == NULL, "event_client (%x): test pattern error: %d\n", id, recv_p - mem->recv_buf);
748
749 out:
750 WSACloseEvent ( event );
751 trace ( "event_client (%x) exiting\n", id );
752 client_stop ();
753 }
754
755 /**************** Main program utility functions ***************/
756
757 cs130_ryutaro 1.1 static void Init (void)
758 {
759 WORD ver = MAKEWORD (2, 2);
760 WSADATA data;
761
762 ok ( WSAStartup ( ver, &data ) == 0, "WSAStartup failed\n" );
763 tls = TlsAlloc();
764 }
765
766 static void Exit (void)
767 {
768 TlsFree ( tls );
769 ok ( WSACleanup() == 0, "WSACleanup failed\n" );
770 }
771
772 static void StartServer (LPTHREAD_START_ROUTINE routine,
773 test_params *general, server_params *par)
774 {
775 par->general = general;
776 thread[0] = CreateThread ( NULL, 0, routine, par, 0, &thread_id[0] );
777 ok ( thread[0] != NULL, "Failed to create server thread\n" );
778 cs130_ryutaro 1.1 }
779
780 static void StartClients (LPTHREAD_START_ROUTINE routine,
781 test_params *general, client_params *par)
782 {
783 int i;
784 par->general = general;
785 for ( i = 1; i <= min ( general->n_clients, MAX_CLIENTS ); i++ )
786 {
787 client_id = i - 1;
788 thread[i] = CreateThread ( NULL, 0, routine, par, 0, &thread_id[i] );
789 ok ( thread[i] != NULL, "Failed to create client thread\n" );
790 /* Make sure the client is up and running */
791 WaitForSingleObject ( client_ready[client_id], INFINITE );
792 };
793 }
794
795 static void do_test( test_setup *test )
796 {
797 DWORD i, n = min (test->general.n_clients, MAX_CLIENTS);
798 DWORD wait;
799 cs130_ryutaro 1.1
800 server_ready = CreateEventW ( NULL, TRUE, FALSE, NULL );
801 for (i = 0; i <= n; i++)
802 client_ready[i] = CreateEventW ( NULL, TRUE, FALSE, NULL );
803
804 StartServer ( test->srv, &test->general, &test->srv_params );
805 StartClients ( test->clt, &test->general, &test->clt_params );
806 WaitForSingleObject ( server_ready, INFINITE );
807
808 wait = WaitForMultipleObjects ( 1 + n, thread, TRUE, 1000 * TEST_TIMEOUT );
809 ok ( wait >= WAIT_OBJECT_0 && wait <= WAIT_OBJECT_0 + n ,
810 "some threads have not completed: %lx\n", wait );
811
812 if ( ! ( wait >= WAIT_OBJECT_0 && wait <= WAIT_OBJECT_0 + n ) )
813 {
814 for (i = 0; i <= n; i++)
815 {
816 trace ("terminating thread %08lx\n", thread_id[i]);
817 if ( WaitForSingleObject ( thread[i], 0 ) != WAIT_OBJECT_0 )
818 TerminateThread ( thread [i], 0 );
819 }
820 cs130_ryutaro 1.1 }
821 CloseHandle ( server_ready );
822 for (i = 0; i <= n; i++)
823 CloseHandle ( client_ready[i] );
824 }
825
826 /********* some tests for getsockopt(setsockopt(X)) == X ***********/
827 /* optname = SO_LINGER */
828 LINGER linger_testvals[] = {
829 {0,0},
830 {0,73},
831 {1,0},
832 {5,189}
833 };
834
835 /* optname = SO_RCVTIMEO, SOSNDTIMEO */
836 #define SOCKTIMEOUT1 63000 /* 63 seconds. Do not test fractional part because of a
837 bug in the linux kernel (fixed in 2.6.8) */
838 #define SOCKTIMEOUT2 997000 /* 997 seconds */
839
840 static void test_set_getsockopt()
841 cs130_ryutaro 1.1 {
842 SOCKET s;
843 int i, err;
844 int timeout;
845 LINGER lingval;
846 int size;
847
848 s = socket(AF_INET, SOCK_STREAM, 0);
849 ok(s!=INVALID_SOCKET, "socket() failed error: %d\n", WSAGetLastError());
850 if( s == INVALID_SOCKET) return;
851 /* SO_RCVTIMEO */
852 timeout = SOCKTIMEOUT1;
853 size = sizeof(timeout);
854 err = setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, (char *) &timeout, size);
855 if( !err)
856 err = getsockopt(s, SOL_SOCKET, SO_RCVTIMEO, (char *) &timeout, &size);
857 ok( !err, "get/setsockopt(SO_RCVTIMEO) failed error: %d\n", WSAGetLastError());
858 ok( timeout == SOCKTIMEOUT1, "getsockopt(SO_RCVTIMEO) returned wrong value %d\n", timeout);
859 /* SO_SNDTIMEO */
860 timeout = SOCKTIMEOUT2; /* 54 seconds. See remark above */
861 size = sizeof(timeout);
862 cs130_ryutaro 1.1 err = setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, (char *) &timeout, size);
863 if( !err)
864 err = getsockopt(s, SOL_SOCKET, SO_SNDTIMEO, (char *) &timeout, &size);
865 ok( !err, "get/setsockopt(SO_SNDTIMEO) failed error: %d\n", WSAGetLastError());
866 ok( timeout == SOCKTIMEOUT2, "getsockopt(SO_SNDTIMEO) returned wrong value %d\n", timeout);
867 /* SO_LINGER */
868 for( i = 0; i < sizeof(linger_testvals)/sizeof(LINGER);i++) {
869 size = sizeof(lingval);
870 lingval = linger_testvals[i];
871 err = setsockopt(s, SOL_SOCKET, SO_LINGER, (char *) &lingval, size);
872 if( !err)
873 err = getsockopt(s, SOL_SOCKET, SO_LINGER, (char *) &lingval, &size);
874 ok( !err, "get/setsockopt(SO_LINGER) failed error: %d\n", WSAGetLastError());
875 ok( !lingval.l_onoff == !linger_testvals[i].l_onoff &&
876 (lingval.l_linger == linger_testvals[i].l_linger ||
877 (!lingval.l_linger && !linger_testvals[i].l_onoff))
878 , "getsockopt(SO_LINGER #%d) returned wrong value %d,%d not %d,%d \n", i,
879 lingval.l_onoff, lingval.l_linger,
880 linger_testvals[i].l_onoff, linger_testvals[i].l_linger);
881 }
882 closesocket(s);
883 cs130_ryutaro 1.1 }
884
885 static void test_so_reuseaddr()
886 {
887 struct sockaddr_in saddr;
888 SOCKET s1,s2;
889 unsigned int rc,reuse,size;
890
891 saddr.sin_family = AF_INET;
892 saddr.sin_port = htons(9375);
893 saddr.sin_addr.s_addr = inet_addr("127.0.0.1");
894
895 s1=socket(AF_INET, SOCK_STREAM, 0);
896 ok(s1!=INVALID_SOCKET, "socket() failed error: %d\n", WSAGetLastError());
897 rc = bind(s1, (struct sockaddr*)&saddr, sizeof(saddr));
898 ok(rc!=SOCKET_ERROR, "bind(s1) failed error: %d\n", WSAGetLastError());
899
900 s2=socket(AF_INET, SOCK_STREAM, 0);
901 ok(s2!=INVALID_SOCKET, "socket() failed error: %d\n", WSAGetLastError());
902
903 reuse=0x1234;
904 cs130_ryutaro 1.1 size=sizeof(reuse);
905 rc=getsockopt(s2, SOL_SOCKET, SO_REUSEADDR, (char*)&reuse, &size );
906 ok(rc==0 && reuse==0,"wrong result in getsockopt(SO_REUSEADDR): rc=%d reuse=%d\n",rc,reuse);
907
908 rc = bind(s2, (struct sockaddr*)&saddr, sizeof(saddr));
909 ok(rc==SOCKET_ERROR, "bind() succeeded\n");
910
911 reuse = 1;
912 rc = setsockopt(s2, SOL_SOCKET, SO_REUSEADDR, (char*)&reuse, sizeof(reuse));
913 ok(rc==0, "setsockopt() failed error: %d\n", WSAGetLastError());
914
915 todo_wine {
916 rc = bind(s2, (struct sockaddr*)&saddr, sizeof(saddr));
917 ok(rc==0, "bind() failed error: %d\n", WSAGetLastError());
918 }
919
920 closesocket(s2);
921 closesocket(s1);
922 }
923
924 /************* Array containing the tests to run **********/
925 cs130_ryutaro 1.1
926 #define STD_STREAM_SOCKET \
927 SOCK_STREAM, \
928 0, \
929 "127.0.0.1", \
930 9374
931
932 static test_setup tests [NUM_TESTS] =
933 {
934 /* Test 0: synchronous client and server */
935 {
936 {
937 STD_STREAM_SOCKET,
938 2048,
939 16,
940 2
941 },
942 simple_server,
943 {
944 NULL,
945 0,
946 cs130_ryutaro 1.1 64
947 },
948 simple_client,
949 {
950 NULL,
951 0,
952 128
953 }
954 },
955 /* Test 1: event-driven client, synchronous server */
956 {
957 {
958 STD_STREAM_SOCKET,
959 2048,
960 16,
961 2
962 },
963 simple_server,
964 {
965 NULL,
966 0,
967 cs130_ryutaro 1.1 64
968 },
969 event_client,
970 {
971 NULL,
972 WSA_FLAG_OVERLAPPED,
973 128
974 }
975 },
976
977 /* Test 2: synchronous client and asynchronous server */
978 {
979 {
980 STD_STREAM_SOCKET,
981 2048,
982 16,
983 2
984 },
985 async_server,
986 {
987 NULL,
988 cs130_ryutaro 1.1 0,
989 64
990 },
991 simple_client,
992 {
993 NULL,
994 0,
995 128
996 }
997 }
998 };
999
1000 static void test_WSAAddressToStringA()
1001 {
1002 INT ret;
1003 DWORD len;
1004 SOCKADDR_IN sockaddr;
1005 CHAR address[22]; /* 12 digits + 3 dots + ':' + 5 digits + '\0' */
1006
1007 CHAR expect1[] = "0.0.0.0";
1008 CHAR expect2[] = "255.255.255.255";
1009 cs130_ryutaro 1.1 CHAR expect3[] = "0.0.0.0:65535";
1010 CHAR expect4[] = "255.255.255.255:65535";
1011
1012 len = 0;
1013
1014 sockaddr.sin_family = AF_INET;
1015 sockaddr.sin_port = 0;
1016 sockaddr.sin_addr.s_addr = 0;
1017
1018 ret = WSAAddressToStringA( (SOCKADDR*)&sockaddr, sizeof(sockaddr), NULL, address, &len );
1019 ok( ret == SOCKET_ERROR, "WSAAddressToStringA() succeeded unexpectedly: %d\n", WSAGetLastError() );
1020
1021 len = sizeof(address);
1022
1023 sockaddr.sin_family = AF_INET;
1024 sockaddr.sin_port = 0;
1025 sockaddr.sin_addr.s_addr = 0;
1026
1027 ret = WSAAddressToStringA( (SOCKADDR*)&sockaddr, sizeof(sockaddr), NULL, address, &len );
1028 ok( !ret, "WSAAddressToStringA() failed unexpectedly: %d\n", WSAGetLastError() );
1029
1030 cs130_ryutaro 1.1 ok( !strcmp( address, expect1 ), "Expected: %s, got: %s\n", expect1, address );
1031
1032 len = sizeof(address);
1033
1034 sockaddr.sin_family = AF_INET;
1035 sockaddr.sin_port = 0;
1036 sockaddr.sin_addr.s_addr = 0xffffffff;
1037
1038 ret = WSAAddressToStringA( (SOCKADDR*)&sockaddr, sizeof(sockaddr), NULL, address, &len );
1039 ok( !ret, "WSAAddressToStringA() failed unexpectedly: %d\n", WSAGetLastError() );
1040
1041 ok( !strcmp( address, expect2 ), "Expected: %s, got: %s\n", expect2, address );
1042
1043 len = sizeof(address);
1044
1045 sockaddr.sin_family = AF_INET;
1046 sockaddr.sin_port = 0xffff;
1047 sockaddr.sin_addr.s_addr = 0;
1048
1049 ret = WSAAddressToStringA( (SOCKADDR*)&sockaddr, sizeof(sockaddr), NULL, address, &len );
1050 ok( !ret, "WSAAddressToStringA() failed unexpectedly: %d\n", WSAGetLastError() );
1051 cs130_ryutaro 1.1
1052 ok( !strcmp( address, expect3 ), "Expected: %s, got: %s\n", expect3, address );
1053
1054 len = sizeof(address);
1055
1056 sockaddr.sin_family = AF_INET;
1057 sockaddr.sin_port = 0xffff;
1058 sockaddr.sin_addr.s_addr = 0xffffffff;
1059
1060 ret = WSAAddressToStringA( (SOCKADDR*)&sockaddr, sizeof(sockaddr), NULL, address, &len );
1061 ok( !ret, "WSAAddressToStringA() failed unexpectedly: %d\n", WSAGetLastError() );
1062
1063 ok( !strcmp( address, expect4 ), "Expected: %s, got: %s\n", expect4, address );
1064 }
1065
1066 static void test_WSAAddressToStringW()
1067 {
1068 INT ret;
1069 DWORD len;
1070 SOCKADDR_IN sockaddr;
1071 WCHAR address[22]; /* 12 digits + 3 dots + ':' + 5 digits + '\0' */
1072 cs130_ryutaro 1.1
1073 WCHAR expect1[] = { '0','.','0','.','0','.','0', 0 };
1074 WCHAR expect2[] = { '2','5','5','.','2','5','5','.','2','5','5','.','2','5','5', 0 };
1075 WCHAR expect3[] = { '0','.','0','.','0','.','0', ':', '6', '5', '5', '3', '5', 0 };
1076 WCHAR expect4[] = { '2','5','5','.','2','5','5','.','2','5','5','.','2','5','5', ':',
1077 '6', '5', '5', '3', '5', 0 };
1078
1079 len = 0;
1080
1081 sockaddr.sin_family = AF_INET;
1082 sockaddr.sin_port = 0;
1083 sockaddr.sin_addr.s_addr = 0;
1084
1085 ret = WSAAddressToStringW( (SOCKADDR*)&sockaddr, sizeof(sockaddr), NULL, address, &len );
1086 ok( ret == SOCKET_ERROR, "WSAAddressToStringW() succeeded unexpectedly: %x\n", WSAGetLastError() );
1087
1088 len = sizeof(address);
1089
1090 sockaddr.sin_family = AF_INET;
1091 sockaddr.sin_port = 0;
1092 sockaddr.sin_addr.s_addr = 0;
1093 cs130_ryutaro 1.1
1094 ret = WSAAddressToStringW( (SOCKADDR*)&sockaddr, sizeof(sockaddr), NULL, address, &len );
1095 ok( !ret, "WSAAddressToStringW() failed unexpectedly: %x\n", WSAGetLastError() );
1096
1097 ok( !lstrcmpW( address, expect1 ), "Expected different address string\n" );
1098
1099 len = sizeof(address);
1100
1101 sockaddr.sin_family = AF_INET;
1102 sockaddr.sin_port = 0;
1103 sockaddr.sin_addr.s_addr = 0xffffffff;
1104
1105 ret = WSAAddressToStringW( (SOCKADDR*)&sockaddr, sizeof(sockaddr), NULL, address, &len );
1106 ok( !ret, "WSAAddressToStringW() failed unexpectedly: %x\n", WSAGetLastError() );
1107
1108 ok( !lstrcmpW( address, expect2 ), "Expected different address string\n" );
1109
1110 len = sizeof(address);
1111
1112 sockaddr.sin_family = AF_INET;
1113 sockaddr.sin_port = 0xffff;
1114 cs130_ryutaro 1.1 sockaddr.sin_addr.s_addr = 0;
1115
1116 ret = WSAAddressToStringW( (SOCKADDR*)&sockaddr, sizeof(sockaddr), NULL, address, &len );
1117 ok( !ret, "WSAAddressToStringW() failed unexpectedly: %x\n", WSAGetLastError() );
1118
1119 ok( !lstrcmpW( address, expect3 ), "Expected different address string\n" );
1120
1121 len = sizeof(address);
1122
1123 sockaddr.sin_family = AF_INET;
1124 sockaddr.sin_port = 0xffff;
1125 sockaddr.sin_addr.s_addr = 0xffffffff;
1126
1127 ret = WSAAddressToStringW( (SOCKADDR*)&sockaddr, sizeof(sockaddr), NULL, address, &len );
1128 ok( !ret, "WSAAddressToStringW() failed unexpectedly: %x\n", WSAGetLastError() );
1129
1130 ok( !lstrcmpW( address, expect4 ), "Expected different address string\n" );
1131 }
1132
1133 static void test_WSAStringToAddressA()
1134 {
1135 cs130_ryutaro 1.1 INT ret, len;
1136 SOCKADDR_IN sockaddr;
1137
1138 CHAR address1[] = "0.0.0.0";
1139 CHAR address2[] = "127.127.127.127";
1140 CHAR address3[] = "255.255.255.255";
1141 CHAR address4[] = "127.127.127.127:65535";
1142 CHAR address5[] = "255.255.255.255:65535";
1143
1144 len = 0;
1145 sockaddr.sin_family = AF_INET;
1146
1147 ret = WSAStringToAddressA( address1, AF_INET, NULL, (SOCKADDR*)&sockaddr, &len );
1148 ok( ret == SOCKET_ERROR, "WSAStringToAddressA() succeeded unexpectedly: %x\n",
1149 WSAGetLastError() );
1150
1151 len = sizeof(sockaddr);
1152 sockaddr.sin_port = 0;
1153 sockaddr.sin_addr.s_addr = 0;
1154
1155 ret = WSAStringToAddressA( address1, AF_INET, NULL, (SOCKADDR*)&sockaddr, &len );
1156 cs130_ryutaro 1.1 ok( !ret && sockaddr.sin_addr.s_addr == 0,
1157 "WSAStringToAddressA() failed unexpectedly: %d\n", WSAGetLastError() );
1158
1159 len = sizeof(sockaddr);
1160 sockaddr.sin_port = 0;
1161 sockaddr.sin_addr.s_addr = 0;
1162
1163 ret = WSAStringToAddressA( address2, AF_INET, NULL, (SOCKADDR*)&sockaddr, &len );
1164 ok( !ret && sockaddr.sin_addr.s_addr == 0x7f7f7f7f,
1165 "WSAStringToAddressA() failed unexpectedly: %d\n", WSAGetLastError() );
1166
1167 len = sizeof(sockaddr);
1168
1169 ret = WSAStringToAddressA( address3, AF_INET, NULL, (SOCKADDR*)&sockaddr, &len );
1170 ok( ret, "WSAStringToAddressA() succeeded unexpectedly: %d\n", WSAGetLastError() );
1171
1172 len = sizeof(sockaddr);
1173 sockaddr.sin_port = 0;
1174 sockaddr.sin_addr.s_addr = 0;
1175
1176 ret = WSAStringToAddressA( address4, AF_INET, NULL, (SOCKADDR*)&sockaddr, &len );
1177 cs130_ryutaro 1.1 ok( !ret && sockaddr.sin_addr.s_addr == 0x7f7f7f7f && sockaddr.sin_port == 0xffff,
1178 "WSAStringToAddressA() failed unexpectedly: %d\n", WSAGetLastError() );
1179
1180 len = sizeof(sockaddr);
1181
1182 ret = WSAStringToAddressA( address5, AF_INET, NULL, (SOCKADDR*)&sockaddr, &len );
1183 ok( ret, "WSAStringToAddressA() succeeded unexpectedly: %d\n", WSAGetLastError() );
1184 }
1185
1186 static void test_WSAStringToAddressW()
1187 {
1188 INT ret, len;
1189 SOCKADDR_IN sockaddr;
1190
1191 WCHAR address1[] = { '0','.','0','.','0','.','0', 0 };
1192 WCHAR address2[] = { '1','2','7','.','1','2','7','.','1','2','7','.','1','2','7', 0 };
1193 WCHAR address3[] = { '2','5','5','.','2','5','5','.','2','5','5','.','2','5','5', 0 };
1194 WCHAR address4[] = { '1','2','7','.','1','2','7','.','1','2','7','.','1','2','7',
1195 ':', '6', '5', '5', '3', '5', 0 };
1196 WCHAR address5[] = { '2','5','5','.','2','5','5','.','2','5','5','.','2','5','5', ':',
1197 '6', '5', '5', '3', '5', 0 };
1198 cs130_ryutaro 1.1
1199 len = 0;
1200 sockaddr.sin_family = AF_INET;
1201
1202 ret = WSAStringToAddressW( address1, AF_INET, NULL, (SOCKADDR*)&sockaddr, &len );
1203 ok( ret == SOCKET_ERROR, "WSAStringToAddressW() failed unexpectedly: %d\n",
1204 WSAGetLastError() );
1205
1206 len = sizeof(sockaddr);
1207 sockaddr.sin_port = 0;
1208 sockaddr.sin_addr.s_addr = 0;
1209
1210 ret = WSAStringToAddressW( address1, AF_INET, NULL, (SOCKADDR*)&sockaddr, &len );
1211 ok( !ret && sockaddr.sin_addr.s_addr == 0,
1212 "WSAStringToAddressW() failed unexpectedly: %d\n", WSAGetLastError() );
1213
1214 len = sizeof(sockaddr);
1215
1216 sockaddr.sin_port = 0;
1217 sockaddr.sin_addr.s_addr = 0;
1218
1219 cs130_ryutaro 1.1 ret = WSAStringToAddressW( address2, AF_INET, NULL, (SOCKADDR*)&sockaddr, &len );
1220 ok( !ret && sockaddr.sin_addr.s_addr == 0x7f7f7f7f,
1221 "WSAStringToAddressW() failed unexpectedly: %d\n", WSAGetLastError() );
1222
1223 len = sizeof(sockaddr);
1224
1225 ret = WSAStringToAddressW( address3, AF_INET, NULL, (SOCKADDR*)&sockaddr, &len );
1226 ok( ret, "WSAStringToAddressW() failed unexpectedly: %d\n", WSAGetLastError() );
1227
1228 len = sizeof(sockaddr);
1229 sockaddr.sin_port = 0;
1230 sockaddr.sin_addr.s_addr = 0;
1231
1232 ret = WSAStringToAddressW( address4, AF_INET, NULL, (SOCKADDR*)&sockaddr, &len );
1233 ok( !ret && sockaddr.sin_addr.s_addr == 0x7f7f7f7f && sockaddr.sin_port == 0xffff,
1234 "WSAStringToAddressW() failed unexpectedly: %d\n", WSAGetLastError() );
1235
1236 len = sizeof(sockaddr);
1237
1238 ret = WSAStringToAddressW( address5, AF_INET, NULL, (SOCKADDR*)&sockaddr, &len );
1239 ok( ret, "WSAStringToAddressW() succeeded unexpectedly: %d\n", WSAGetLastError() );
1240 cs130_ryutaro 1.1 }
1241
1242 /**************** Main program ***************/
1243
1244 START_TEST( sock )
1245 {
1246 int i;
1247 Init();
1248
1249 test_set_getsockopt();
1250 test_so_reuseaddr();
1251
1252 for (i = 0; i < NUM_TESTS; i++)
1253 {
1254 trace ( " **** STARTING TEST %d **** \n", i );
1255 do_test ( &tests[i] );
1256 trace ( " **** TEST %d COMPLETE **** \n", i );
1257 }
1258
1259 test_WSAAddressToStringA();
1260 test_WSAAddressToStringW();
1261 cs130_ryutaro 1.1
1262 test_WSAStringToAddressA();
1263 test_WSAStringToAddressW();
1264
1265 Exit();
1266 }
|