1 cs130_tom 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_tom 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 2 /* 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
39 #define wsa_ok(op, cond, msg) \
40 do { \
41 int tmp, err = 0; \
42 tmp = op; \
43 cs130_tom 1.1 if ( !(cond tmp) ) err = WSAGetLastError(); \
44 ok ( cond tmp, msg, GetCurrentThreadId(), err); \
45 } while (0);
46
47
48 /**************** Structs and typedefs ***************/
49
50 typedef struct thread_info
51 {
52 HANDLE thread;
53 DWORD id;
54 } thread_info;
55
56 /* Information in the server about open client connections */
57 typedef struct sock_info
58 {
59 SOCKET s;
60 struct sockaddr_in addr;
61 struct sockaddr_in peer;
62 char *buf;
63 int nread;
64 cs130_tom 1.1 } sock_info;
65
66 /* Test parameters for both server & client */
67 typedef struct test_params
68 {
69 int sock_type;
70 int sock_prot;
71 const char *inet_addr;
72 short inet_port;
73 int chunk_size;
74 int n_chunks;
75 int n_clients;
76 } test_params;
77
78 /* server-specific test parameters */
79 typedef struct server_params
80 {
81 test_params *general;
82 DWORD sock_flags;
83 int buflen;
84 } server_params;
85 cs130_tom 1.1
86 /* client-specific test parameters */
87 typedef struct client_params
88 {
89 test_params *general;
90 DWORD sock_flags;
91 int buflen;
92 } client_params;
93
94 /* This type combines all information for setting up a test scenario */
95 typedef struct test_setup
96 {
97 test_params general;
98 LPVOID srv;
99 server_params srv_params;
100 LPVOID clt;
101 client_params clt_params;
102 } test_setup;
103
104 /* Thread local storage for server */
105 typedef struct server_memory
106 cs130_tom 1.1 {
107 SOCKET s;
108 struct sockaddr_in addr;
109 sock_info sock[MAX_CLIENTS];
110 } server_memory;
111
112 /* Thread local storage for client */
113 typedef struct client_memory
114 {
115 SOCKET s;
116 struct sockaddr_in addr;
117 char *send_buf;
118 char *recv_buf;
119 } client_memory;
120
121 /**************** Static variables ***************/
122
123 static DWORD tls; /* Thread local storage index */
124 static HANDLE thread[1+MAX_CLIENTS];
125 static DWORD thread_id[1+MAX_CLIENTS];
126 static HANDLE server_ready;
127 cs130_tom 1.1 static HANDLE client_ready[MAX_CLIENTS];
128 static int client_id;
129
130 /**************** General utility functions ***************/
131
132 static void set_so_opentype ( BOOL overlapped )
133 {
134 int optval = !overlapped, newval, len = sizeof (int);
135
136 ok ( setsockopt ( INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE,
137 (LPVOID) &optval, sizeof (optval) ) == 0,
138 "setting SO_OPENTYPE failed\n" );
139 ok ( getsockopt ( INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE,
140 (LPVOID) &newval, &len ) == 0,
141 "getting SO_OPENTYPE failed\n" );
142 ok ( optval == newval, "failed to set SO_OPENTYPE\n" );
143 }
144
145 static int set_blocking ( SOCKET s, BOOL blocking )
146 {
147 u_long val = !blocking;
148 cs130_tom 1.1 return ioctlsocket ( s, FIONBIO, &val );
149 }
150
151 static void fill_buffer ( char *buf, int chunk_size, int n_chunks )
152 {
153 char c, *p;
154 for ( c = FIRST_CHAR, p = buf; c < FIRST_CHAR + n_chunks; c++, p += chunk_size )
155 memset ( p, c, chunk_size );
156 }
157
158 static char* test_buffer ( char *buf, int chunk_size, int n_chunks )
159 {
160 char c, *p;
161 int i;
162 for ( c = FIRST_CHAR, p = buf; c < FIRST_CHAR + n_chunks; c++, p += chunk_size )
163 {
164 for ( i = 0; i < chunk_size; i++ )
165 if ( p[i] != c ) return p + i;
166 }
167 return NULL;
168 }
169 cs130_tom 1.1
170 /*
171 * This routine is called when a client / server does not expect any more data,
172 * but needs to acknowedge the closing of the connection (by reasing 0 bytes).
173 */
174 static void read_zero_bytes ( SOCKET s )
175 {
176 char buf[256];
177 int tmp, n = 0;
178 while ( ( tmp = recv ( s, buf, 256, 0 ) ) > 0 )
179 n += tmp;
180 ok ( n <= 0, "garbage data received: %d bytes\n", n );
181 }
182
183 static int do_synchronous_send ( SOCKET s, char *buf, int buflen, int sendlen )
184 {
185 char* last = buf + buflen, *p;
186 int n = 1;
187 for ( p = buf; n > 0 && p < last; p += n )
188 n = send ( s, p, min ( sendlen, last - p ), 0 );
189 wsa_ok ( n, 0 <=, "do_synchronous_send (%lx): error %d\n" );
190 cs130_tom 1.1 return p - buf;
191 }
192
193 static int do_synchronous_recv ( SOCKET s, char *buf, int buflen, int recvlen )
194 {
195 char* last = buf + buflen, *p;
196 int n = 1;
197 for ( p = buf; n > 0 && p < last; p += n )
198 n = recv ( s, p, min ( recvlen, last - p ), 0 );
199 wsa_ok ( n, 0 <=, "do_synchronous_recv (%lx): error %d:\n" );
200 return p - buf;
201 }
202
203 /*
204 * Call this routine right after thread startup.
205 * SO_OPENTYPE must by 0, regardless what the server did.
206 */
207 static void check_so_opentype (void)
208 {
209 int tmp = 1, len;
210 len = sizeof (tmp);
211 cs130_tom 1.1 getsockopt ( INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE, (LPVOID) &tmp, &len );
212 ok ( tmp == 0, "check_so_opentype: wrong startup value of SO_OPENTYPE: %d\n", tmp );
213 }
214
215 /**************** Server utility functions ***************/
216
217 /*
218 * Even if we have closed our server socket cleanly,
219 * the OS may mark the address "in use" for some time -
220 * this happens with native Linux apps, too.
221 */
222 static void do_bind ( SOCKET s, struct sockaddr* addr, int addrlen )
223 {
224 int err, wsaerr = 0, n_try = BIND_TRIES;
225
226 while ( ( err = bind ( s, addr, addrlen ) ) != 0 &&
227 ( wsaerr = WSAGetLastError () ) == WSAEADDRINUSE &&
228 n_try-- >= 0)
229 {
230 trace ( "address in use, waiting ...\n" );
231 Sleep ( 1000 * BIND_SLEEP );
232 cs130_tom 1.1 }
233 ok ( err == 0, "failed to bind: %d\n", wsaerr );
234 }
235
236 static void server_start ( server_params *par )
237 {
238 int i;
239 test_params *gen = par->general;
240 server_memory *mem = (LPVOID) LocalAlloc ( LPTR, sizeof (server_memory));
241
242 TlsSetValue ( tls, mem );
243 mem->s = WSASocketA ( AF_INET, gen->sock_type, gen->sock_prot,
244 NULL, 0, par->sock_flags );
245 ok ( mem->s != INVALID_SOCKET, "Server: WSASocket failed\n" );
246
247 mem->addr.sin_family = AF_INET;
248 mem->addr.sin_addr.s_addr = inet_addr ( gen->inet_addr );
249 mem->addr.sin_port = htons ( gen->inet_port );
250
251 for (i = 0; i < MAX_CLIENTS; i++)
252 {
253 cs130_tom 1.1 mem->sock[i].s = INVALID_SOCKET;
254 mem->sock[i].buf = (LPVOID) LocalAlloc ( LPTR, gen->n_chunks * gen->chunk_size );
255 mem->sock[i].nread = 0;
256 }
257
258 if ( gen->sock_type == SOCK_STREAM )
259 do_bind ( mem->s, (struct sockaddr*) &mem->addr, sizeof (mem->addr) );
260 }
261
262 static void server_stop (void)
263 {
264 int i;
265 server_memory *mem = TlsGetValue ( tls );
266
267 for (i = 0; i < MAX_CLIENTS; i++ )
268 {
269 LocalFree ( (HANDLE) mem->sock[i].buf );
270 if ( mem->sock[i].s != INVALID_SOCKET )
271 closesocket ( mem->sock[i].s );
272 }
273 ok ( closesocket ( mem->s ) == 0, "closesocket failed\n" );
274 cs130_tom 1.1 LocalFree ( (HANDLE) mem );
275 ExitThread ( GetCurrentThreadId () );
276 }
277
278 /**************** Client utilitiy functions ***************/
279
280 static void client_start ( client_params *par )
281 {
282 test_params *gen = par->general;
283 client_memory *mem = (LPVOID) LocalAlloc (LPTR, sizeof (client_memory));
284
285 TlsSetValue ( tls, mem );
286
287 WaitForSingleObject ( server_ready, INFINITE );
288
289 mem->s = WSASocketA ( AF_INET, gen->sock_type, gen->sock_prot,
290 NULL, 0, par->sock_flags );
291
292 mem->addr.sin_family = AF_INET;
293 mem->addr.sin_addr.s_addr = inet_addr ( gen->inet_addr );
294 mem->addr.sin_port = htons ( gen->inet_port );
295 cs130_tom 1.1
296 ok ( mem->s != INVALID_SOCKET, "Client: WSASocket failed\n" );
297
298 mem->send_buf = (LPVOID) LocalAlloc ( LPTR, 2 * gen->n_chunks * gen->chunk_size );
299 mem->recv_buf = mem->send_buf + gen->n_chunks * gen->chunk_size;
300 fill_buffer ( mem->send_buf, gen->chunk_size, gen->n_chunks );
301
302 SetEvent ( client_ready[client_id] );
303 /* Wait for the other clients to come up */
304 WaitForMultipleObjects ( min ( gen->n_clients, MAX_CLIENTS ), client_ready, TRUE, INFINITE );
305 }
306
307 static void client_stop (void)
308 {
309 client_memory *mem = TlsGetValue ( tls );
310 wsa_ok ( closesocket ( mem->s ), 0 ==, "closesocket error (%lx): %d\n" );
311 LocalFree ( (HANDLE) mem->send_buf );
312 LocalFree ( (HANDLE) mem );
313 ExitThread(0);
314 }
315
316 cs130_tom 1.1 /**************** Servers ***************/
317
318 /*
319 * simple_server: A very basic server doing synchronous IO.
320 */
321 static VOID WINAPI simple_server ( server_params *par )
322 {
323 test_params *gen = par->general;
324 server_memory *mem;
325 int n_recvd, n_sent, n_expected = gen->n_chunks * gen->chunk_size, tmp, i,
326 id = GetCurrentThreadId();
327 char *p;
328
329 trace ( "simple_server (%x) starting\n", id );
330
331 set_so_opentype ( FALSE ); /* non-overlapped */
332 server_start ( par );
333 mem = TlsGetValue ( tls );
334
335 wsa_ok ( set_blocking ( mem->s, TRUE ), 0 ==, "simple_server (%lx): failed to set blocking mode: %d\n");
336 wsa_ok ( listen ( mem->s, SOMAXCONN ), 0 ==, "simple_server (%lx): listen failed: %d\n");
337 cs130_tom 1.1
338 trace ( "simple_server (%x) ready\n", id );
339 SetEvent ( server_ready ); /* notify clients */
340
341 for ( i = 0; i < min ( gen->n_clients, MAX_CLIENTS ); i++ )
342 {
343 trace ( "simple_server (%x): waiting for client\n", id );
344
345 /* accept a single connection */
346 tmp = sizeof ( mem->sock[0].peer );
347 mem->sock[0].s = accept ( mem->s, (struct sockaddr*) &mem->sock[0].peer, &tmp );
348 wsa_ok ( mem->sock[0].s, INVALID_SOCKET !=, "simple_server (%lx): accept failed: %d\n" );
349
350 ok ( mem->sock[0].peer.sin_addr.s_addr == inet_addr ( gen->inet_addr ),
351 "simple_server (%x): strange peer address\n", id );
352
353 /* Receive data & check it */
354 n_recvd = do_synchronous_recv ( mem->sock[0].s, mem->sock[0].buf, n_expected, par->buflen );
355 ok ( n_recvd == n_expected,
356 "simple_server (%x): received less data than expected: %d of %d\n", id, n_recvd, n_expected );
357 p = test_buffer ( mem->sock[0].buf, gen->chunk_size, gen->n_chunks );
358 cs130_tom 1.1 ok ( p == NULL, "simple_server (%x): test pattern error: %d\n", id, p - mem->sock[0].buf);
359
360 /* Echo data back */
361 n_sent = do_synchronous_send ( mem->sock[0].s, mem->sock[0].buf, n_expected, par->buflen );
362 ok ( n_sent == n_expected,
363 "simple_server (%x): sent less data than expected: %d of %d\n", id, n_sent, n_expected );
364
365 /* cleanup */
366 read_zero_bytes ( mem->sock[0].s );
367 wsa_ok ( closesocket ( mem->sock[0].s ), 0 ==, "simple_server (%lx): closesocket error: %d\n" );
368 mem->sock[0].s = INVALID_SOCKET;
369 }
370
371 trace ( "simple_server (%x) exiting\n", id );
372 server_stop ();
373 }
374
375 /**************** Clients ***************/
376
377 /*
378 * simple_client: A very basic client doing synchronous IO.
379 cs130_tom 1.1 */
380 static VOID WINAPI simple_client ( client_params *par )
381 {
382 test_params *gen = par->general;
383 client_memory *mem;
384 int n_sent, n_recvd, n_expected = gen->n_chunks * gen->chunk_size, id;
385 char *p;
386
387 id = GetCurrentThreadId();
388 trace ( "simple_client (%x): starting\n", id );
389 /* wait here because we want to call set_so_opentype before creating a socket */
390 WaitForSingleObject ( server_ready, INFINITE );
391 trace ( "simple_client (%x): server ready\n", id );
392
393 check_so_opentype ();
394 set_so_opentype ( FALSE ); /* non-overlapped */
395 client_start ( par );
396 mem = TlsGetValue ( tls );
397
398 /* Connect */
399 wsa_ok ( connect ( mem->s, (struct sockaddr*) &mem->addr, sizeof ( mem->addr ) ),
400 cs130_tom 1.1 0 ==, "simple_client (%lx): connect error: %d\n" );
401 ok ( set_blocking ( mem->s, TRUE ) == 0,
402 "simple_client (%x): failed to set blocking mode\n", id );
403 trace ( "simple_client (%x) connected\n", id );
404
405 /* send data to server */
406 n_sent = do_synchronous_send ( mem->s, mem->send_buf, n_expected, par->buflen );
407 ok ( n_sent == n_expected,
408 "simple_client (%x): sent less data than expected: %d of %d\n", id, n_sent, n_expected );
409
410 /* shutdown send direction */
411 wsa_ok ( shutdown ( mem->s, SD_SEND ), 0 ==, "simple_client (%lx): shutdown failed: %d\n" );
412
413 /* Receive data echoed back & check it */
414 n_recvd = do_synchronous_recv ( mem->s, mem->recv_buf, n_expected, par->buflen );
415 ok ( n_recvd == n_expected,
416 "simple_client (%x): received less data than expected: %d of %d\n", id, n_recvd, n_expected );
417
418 /* check data */
419 p = test_buffer ( mem->recv_buf, gen->chunk_size, gen->n_chunks );
420 ok ( p == NULL, "simple_client (%x): test pattern error: %d\n", id, p - mem->recv_buf);
421 cs130_tom 1.1
422 /* cleanup */
423 read_zero_bytes ( mem->s );
424 trace ( "simple_client (%x) exiting\n", id );
425 client_stop ();
426 }
427
428 /*
429 * event_client: An event-driven client
430 */
431 static void WINAPI event_client ( client_params *par )
432 {
433 test_params *gen = par->general;
434 client_memory *mem;
435 int id = GetCurrentThreadId(), n_expected = gen->n_chunks * gen->chunk_size,
436 tmp, err, n;
437 HANDLE event;
438 WSANETWORKEVENTS wsa_events;
439 char *send_last, *recv_last, *send_p, *recv_p;
440 long mask = FD_READ | FD_WRITE | FD_CLOSE;
441
442 cs130_tom 1.1 trace ( "event_client (%x): starting\n", id );
443 client_start ( par );
444 trace ( "event_client (%x): server ready\n", id );
445
446 mem = TlsGetValue ( tls );
447
448 /* Prepare event notification for connect, makes socket nonblocking */
449 event = WSACreateEvent ();
450 WSAEventSelect ( mem->s, event, FD_CONNECT );
451 tmp = connect ( mem->s, (struct sockaddr*) &mem->addr, sizeof ( mem->addr ) );
452 if ( tmp != 0 && ( err = WSAGetLastError () ) != WSAEWOULDBLOCK )
453 ok ( 0, "event_client (%x): connect error: %d\n", id, err );
454
455 tmp = WaitForSingleObject ( event, INFINITE );
456 ok ( tmp == WAIT_OBJECT_0, "event_client (%x): wait for connect event failed: %d\n", id, tmp );
457 err = WSAEnumNetworkEvents ( mem->s, event, &wsa_events );
458 wsa_ok ( err, 0 ==, "event_client (%lx): WSAEnumNetworkEvents error: %d\n" );
459
460 err = wsa_events.iErrorCode[ FD_CONNECT_BIT ];
461 ok ( err == 0, "event_client (%x): connect error: %d\n", id, err );
462 if ( err ) goto out;
463 cs130_tom 1.1
464 trace ( "event_client (%x) connected\n", id );
465
466 WSAEventSelect ( mem->s, event, mask );
467
468 recv_p = mem->recv_buf;
469 recv_last = mem->recv_buf + n_expected;
470 send_p = mem->send_buf;
471 send_last = mem->send_buf + n_expected;
472
473 while ( TRUE )
474 {
475 err = WaitForSingleObject ( event, INFINITE );
476 ok ( err == WAIT_OBJECT_0, "event_client (%x): wait failed\n", id );
477
478 err = WSAEnumNetworkEvents ( mem->s, event, &wsa_events );
479 wsa_ok ( err, 0 ==, "event_client (%lx): WSAEnumNetworkEvents error: %d\n" );
480
481 if ( wsa_events.lNetworkEvents & FD_WRITE )
482 {
483 err = wsa_events.iErrorCode[ FD_WRITE_BIT ];
484 cs130_tom 1.1 ok ( err == 0, "event_client (%x): FD_WRITE error code: %d\n", id, err );
485
486 if ( err== 0 )
487 do
488 {
489 n = send ( mem->s, send_p, min ( send_last - send_p, par->buflen ), 0 );
490 if ( n < 0 )
491 {
492 err = WSAGetLastError ();
493 ok ( err == WSAEWOULDBLOCK, "event_client (%x): send error: %d\n", id, err );
494 }
495 else
496 send_p += n;
497 }
498 while ( n >= 0 && send_p < send_last );
499
500 if ( send_p == send_last )
501 {
502 trace ( "event_client (%x): all data sent - shutdown\n", id );
503 shutdown ( mem->s, SD_SEND );
504 mask &= ~FD_WRITE;
505 cs130_tom 1.1 WSAEventSelect ( mem->s, event, mask );
506 }
507 }
508 if ( wsa_events.lNetworkEvents & FD_READ )
509 {
510 err = wsa_events.iErrorCode[ FD_READ_BIT ];
511 ok ( err == 0, "event_client (%x): FD_READ error code: %d\n", id, err );
512 if ( err != 0 ) break;
513
514 /* First read must succeed */
515 n = recv ( mem->s, recv_p, min ( recv_last - recv_p, par->buflen ), 0 );
516 wsa_ok ( n, 0 <=, "event_client (%lx): recv error: %d\n" );
517
518 while ( n >= 0 ) {
519 recv_p += n;
520 if ( recv_p == recv_last )
521 {
522 mask &= ~FD_READ;
523 trace ( "event_client (%x): all data received\n", id );
524 WSAEventSelect ( mem->s, event, mask );
525 break;
526 cs130_tom 1.1 }
527 n = recv ( mem->s, recv_p, min ( recv_last - recv_p, par->buflen ), 0 );
528 if ( n < 0 && ( err = WSAGetLastError()) != WSAEWOULDBLOCK )
529 ok ( 0, "event_client (%x): read error: %d\n", id, err );
530
531 }
532 }
533 if ( wsa_events.lNetworkEvents & FD_CLOSE )
534 {
535 trace ( "event_client (%x): close event\n", id );
536 err = wsa_events.iErrorCode[ FD_CLOSE_BIT ];
537 ok ( err == 0, "event_client (%x): FD_CLOSE error code: %d\n", id, err );
538 break;
539 }
540 }
541
542 ok ( send_p == send_last,
543 "simple_client (%x): sent less data than expected: %d of %d\n",
544 id, send_p - mem->send_buf, n_expected );
545 ok ( recv_p == recv_last,
546 "simple_client (%x): received less data than expected: %d of %d\n",
547 cs130_tom 1.1 id, recv_p - mem->recv_buf, n_expected );
548 recv_p = test_buffer ( mem->recv_buf, gen->chunk_size, gen->n_chunks );
549 ok ( recv_p == NULL, "event_client (%x): test pattern error: %d\n", id, recv_p - mem->recv_buf);
550
551 out:
552 WSACloseEvent ( event );
553 trace ( "event_client (%x) exiting\n", id );
554 client_stop ();
555 }
556
557 /**************** Main program utility functions ***************/
558
559 static void Init (void)
560 {
561 WORD ver = MAKEWORD (2, 2);
562 WSADATA data;
563
564 ok ( WSAStartup ( ver, &data ) == 0, "WSAStartup failed\n" );
565 tls = TlsAlloc();
566 }
567
568 cs130_tom 1.1 static void Exit (void)
569 {
570 TlsFree ( tls );
571 ok ( WSACleanup() == 0, "WSACleanup failed\n" );
572 }
573
574 static void StartServer (LPTHREAD_START_ROUTINE routine,
575 test_params *general, server_params *par)
576 {
577 par->general = general;
578 thread[0] = CreateThread ( NULL, 0, routine, par, 0, &thread_id[0] );
579 ok ( thread[0] != NULL, "Failed to create server thread\n" );
580 }
581
582 static void StartClients (LPTHREAD_START_ROUTINE routine,
583 test_params *general, client_params *par)
584 {
585 int i;
586 par->general = general;
587 for ( i = 1; i <= min ( general->n_clients, MAX_CLIENTS ); i++ )
588 {
589 cs130_tom 1.1 client_id = i - 1;
590 thread[i] = CreateThread ( NULL, 0, routine, par, 0, &thread_id[i] );
591 ok ( thread[i] != NULL, "Failed to create client thread\n" );
592 /* Make sure the client is up and running */
593 WaitForSingleObject ( client_ready[client_id], INFINITE );
594 };
595 }
596
597 static void do_test( test_setup *test )
598 {
599 DWORD i, n = min (test->general.n_clients, MAX_CLIENTS);
600 DWORD wait;
601
602 server_ready = CreateEventW ( NULL, TRUE, FALSE, NULL );
603 for (i = 0; i <= n; i++)
604 client_ready[i] = CreateEventW ( NULL, TRUE, FALSE, NULL );
605
606 StartServer ( test->srv, &test->general, &test->srv_params );
607 StartClients ( test->clt, &test->general, &test->clt_params );
608 WaitForSingleObject ( server_ready, INFINITE );
609
610 cs130_tom 1.1 wait = WaitForMultipleObjects ( 1 + n, thread, TRUE, 1000 * TEST_TIMEOUT );
611 ok ( wait >= WAIT_OBJECT_0 && wait <= WAIT_OBJECT_0 + n ,
612 "some threads have not completed: %lx\n", wait );
613
614 if ( ! ( wait >= WAIT_OBJECT_0 && wait <= WAIT_OBJECT_0 + n ) )
615 {
616 for (i = 0; i <= n; i++)
617 {
618 trace ("terminating thread %08lx\n", thread_id[i]);
619 if ( WaitForSingleObject ( thread[i], 0 ) != WAIT_OBJECT_0 )
620 TerminateThread ( thread [i], 0 );
621 }
622 }
623 CloseHandle ( server_ready );
624 for (i = 0; i <= n; i++)
625 CloseHandle ( client_ready[i] );
626 }
627
628 /********* some tests for getsockopt(setsockopt(X)) == X ***********/
629 /* optname = SO_LINGER */
630 LINGER linger_testvals[] = {
631 cs130_tom 1.1 {0,0},
632 {0,73},
633 {1,0},
634 {5,189}
635 };
636
637 /* optname = SO_RCVTIMEO, SOSNDTIMEO */
638 #define SOCKTIMEOUT1 63000 /* 63 seconds. Do not test fractional part because of a
639 bug in the linux kernel (fixed in 2.6.8) */
640 #define SOCKTIMEOUT2 997000 /* 997 seconds */
641
642 static void test_set_getsockopt()
643 {
644 SOCKET s;
645 int i, err;
646 int timeout;
647 LINGER lingval;
648 int size;
649
650 s = socket(AF_INET, SOCK_STREAM, 0);
651 ok(s!=INVALID_SOCKET, "socket() failed error: %d\n", WSAGetLastError());
652 cs130_tom 1.1 if( s == INVALID_SOCKET) return;
653 /* SO_RCVTIMEO */
654 timeout = SOCKTIMEOUT1;
655 size = sizeof(timeout);
656 err = setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, (char *) &timeout, size);
657 if( !err)
658 err = getsockopt(s, SOL_SOCKET, SO_RCVTIMEO, (char *) &timeout, &size);
659 ok( !err, "get/setsockopt(SO_RCVTIMEO) failed error: %d\n", WSAGetLastError());
660 ok( timeout == SOCKTIMEOUT1, "getsockopt(SO_RCVTIMEO) returned wrong value %d\n", timeout);
661 /* SO_SNDTIMEO */
662 timeout = SOCKTIMEOUT2; /* 54 seconds. See remark above */
663 size = sizeof(timeout);
664 err = setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, (char *) &timeout, size);
665 if( !err)
666 err = getsockopt(s, SOL_SOCKET, SO_SNDTIMEO, (char *) &timeout, &size);
667 ok( !err, "get/setsockopt(SO_SNDTIMEO) failed error: %d\n", WSAGetLastError());
668 ok( timeout == SOCKTIMEOUT2, "getsockopt(SO_SNDTIMEO) returned wrong value %d\n", timeout);
669 /* SO_LINGER */
670 for( i = 0; i < sizeof(linger_testvals)/sizeof(LINGER);i++) {
671 size = sizeof(lingval);
672 lingval = linger_testvals[i];
673 cs130_tom 1.1 err = setsockopt(s, SOL_SOCKET, SO_LINGER, (char *) &lingval, size);
674 if( !err)
675 err = getsockopt(s, SOL_SOCKET, SO_LINGER, (char *) &lingval, &size);
676 ok( !err, "get/setsockopt(SO_LINGER) failed error: %d\n", WSAGetLastError());
677 ok( !lingval.l_onoff == !linger_testvals[i].l_onoff &&
678 (lingval.l_linger == linger_testvals[i].l_linger ||
679 (!lingval.l_linger && !linger_testvals[i].l_onoff))
680 , "getsockopt(SO_LINGER #%d) returned wrong value %d,%d not %d,%d \n", i,
681 lingval.l_onoff, lingval.l_linger,
682 linger_testvals[i].l_onoff, linger_testvals[i].l_linger);
683 }
684 closesocket(s);
685 }
686
687 static void test_so_reuseaddr()
688 {
689 struct sockaddr_in saddr;
690 SOCKET s1,s2;
691 unsigned int rc,reuse,size;
692
693 saddr.sin_family = AF_INET;
694 cs130_tom 1.1 saddr.sin_port = htons(9375);
695 saddr.sin_addr.s_addr = inet_addr("127.0.0.1");
696
697 s1=socket(AF_INET, SOCK_STREAM, 0);
698 ok(s1!=INVALID_SOCKET, "socket() failed error: %d\n", WSAGetLastError());
699 rc = bind(s1, (struct sockaddr*)&saddr, sizeof(saddr));
700 ok(rc!=SOCKET_ERROR, "bind(s1) failed error: %d\n", WSAGetLastError());
701
702 s2=socket(AF_INET, SOCK_STREAM, 0);
703 ok(s2!=INVALID_SOCKET, "socket() failed error: %d\n", WSAGetLastError());
704
705 reuse=0x1234;
706 size=sizeof(reuse);
707 rc=getsockopt(s2, SOL_SOCKET, SO_REUSEADDR, (char*)&reuse, &size );
708 ok(rc==0 && reuse==0,"wrong result in getsockopt(SO_REUSEADDR): rc=%d reuse=%d\n",rc,reuse);
709
710 rc = bind(s2, (struct sockaddr*)&saddr, sizeof(saddr));
711 ok(rc==SOCKET_ERROR, "bind() succeeded\n");
712
713 reuse = 1;
714 rc = setsockopt(s2, SOL_SOCKET, SO_REUSEADDR, (char*)&reuse, sizeof(reuse));
715 cs130_tom 1.1 ok(rc==0, "setsockopt() failed error: %d\n", WSAGetLastError());
716
717 todo_wine {
718 rc = bind(s2, (struct sockaddr*)&saddr, sizeof(saddr));
719 ok(rc==0, "bind() failed error: %d\n", WSAGetLastError());
720 }
721
722 closesocket(s2);
723 closesocket(s1);
724 }
725
726 /************* Array containing the tests to run **********/
727
728 #define STD_STREAM_SOCKET \
729 SOCK_STREAM, \
730 0, \
731 "127.0.0.1", \
732 9374
733
734 static test_setup tests [NUM_TESTS] =
735 {
736 cs130_tom 1.1 /* Test 0: synchronous client and server */
737 {
738 {
739 STD_STREAM_SOCKET,
740 2048,
741 16,
742 2
743 },
744 simple_server,
745 {
746 NULL,
747 0,
748 64
749 },
750 simple_client,
751 {
752 NULL,
753 0,
754 128
755 }
756 },
757 cs130_tom 1.1 /* Test 1: event-driven client, synchronous server */
758 {
759 {
760 STD_STREAM_SOCKET,
761 2048,
762 16,
763 2
764 },
765 simple_server,
766 {
767 NULL,
768 0,
769 64
770 },
771 event_client,
772 {
773 NULL,
774 WSA_FLAG_OVERLAPPED,
775 128
776 }
777 }
778 cs130_tom 1.1 };
779
780 static void test_WSAAddressToStringA()
781 {
782 INT ret;
783 DWORD len;
784 SOCKADDR_IN sockaddr;
785 CHAR address[22]; /* 12 digits + 3 dots + ':' + 5 digits + '\0' */
786
787 CHAR expect1[] = "0.0.0.0";
788 CHAR expect2[] = "255.255.255.255";
789 CHAR expect3[] = "0.0.0.0:65535";
790 CHAR expect4[] = "255.255.255.255:65535";
791
792 len = 0;
793
794 sockaddr.sin_family = AF_INET;
795 sockaddr.sin_port = 0;
796 sockaddr.sin_addr.s_addr = 0;
797
798 ret = WSAAddressToStringA( (SOCKADDR*)&sockaddr, sizeof(sockaddr), NULL, address, &len );
799 cs130_tom 1.1 ok( ret == SOCKET_ERROR, "WSAAddressToStringA() succeeded unexpectedly: %d\n", WSAGetLastError() );
800
801 len = sizeof(address);
802
803 sockaddr.sin_family = AF_INET;
804 sockaddr.sin_port = 0;
805 sockaddr.sin_addr.s_addr = 0;
806
807 ret = WSAAddressToStringA( (SOCKADDR*)&sockaddr, sizeof(sockaddr), NULL, address, &len );
808 ok( !ret, "WSAAddressToStringA() failed unexpectedly: %d\n", WSAGetLastError() );
809
810 ok( !strcmp( address, expect1 ), "Expected: %s, got: %s\n", expect1, address );
811
812 len = sizeof(address);
813
814 sockaddr.sin_family = AF_INET;
815 sockaddr.sin_port = 0;
816 sockaddr.sin_addr.s_addr = 0xffffffff;
817
818 ret = WSAAddressToStringA( (SOCKADDR*)&sockaddr, sizeof(sockaddr), NULL, address, &len );
819 ok( !ret, "WSAAddressToStringA() failed unexpectedly: %d\n", WSAGetLastError() );
820 cs130_tom 1.1
821 ok( !strcmp( address, expect2 ), "Expected: %s, got: %s\n", expect2, address );
822
823 len = sizeof(address);
824
825 sockaddr.sin_family = AF_INET;
826 sockaddr.sin_port = 0xffff;
827 sockaddr.sin_addr.s_addr = 0;
828
829 ret = WSAAddressToStringA( (SOCKADDR*)&sockaddr, sizeof(sockaddr), NULL, address, &len );
830 ok( !ret, "WSAAddressToStringA() failed unexpectedly: %d\n", WSAGetLastError() );
831
832 ok( !strcmp( address, expect3 ), "Expected: %s, got: %s\n", expect3, address );
833
834 len = sizeof(address);
835
836 sockaddr.sin_family = AF_INET;
837 sockaddr.sin_port = 0xffff;
838 sockaddr.sin_addr.s_addr = 0xffffffff;
839
840 ret = WSAAddressToStringA( (SOCKADDR*)&sockaddr, sizeof(sockaddr), NULL, address, &len );
841 cs130_tom 1.1 ok( !ret, "WSAAddressToStringA() failed unexpectedly: %d\n", WSAGetLastError() );
842
843 ok( !strcmp( address, expect4 ), "Expected: %s, got: %s\n", expect4, address );
844 }
845
846 static void test_WSAAddressToStringW()
847 {
848 INT ret;
849 DWORD len;
850 SOCKADDR_IN sockaddr;
851 WCHAR address[22]; /* 12 digits + 3 dots + ':' + 5 digits + '\0' */
852
853 WCHAR expect1[] = { '0','.','0','.','0','.','0', 0 };
854 WCHAR expect2[] = { '2','5','5','.','2','5','5','.','2','5','5','.','2','5','5', 0 };
855 WCHAR expect3[] = { '0','.','0','.','0','.','0', ':', '6', '5', '5', '3', '5', 0 };
856 WCHAR expect4[] = { '2','5','5','.','2','5','5','.','2','5','5','.','2','5','5', ':',
857 '6', '5', '5', '3', '5', 0 };
858
859 len = 0;
860
861 sockaddr.sin_family = AF_INET;
862 cs130_tom 1.1 sockaddr.sin_port = 0;
863 sockaddr.sin_addr.s_addr = 0;
864
865 ret = WSAAddressToStringW( (SOCKADDR*)&sockaddr, sizeof(sockaddr), NULL, address, &len );
866 ok( ret == SOCKET_ERROR, "WSAAddressToStringW() succeeded unexpectedly: %x\n", WSAGetLastError() );
867
868 len = sizeof(address);
869
870 sockaddr.sin_family = AF_INET;
871 sockaddr.sin_port = 0;
872 sockaddr.sin_addr.s_addr = 0;
873
874 ret = WSAAddressToStringW( (SOCKADDR*)&sockaddr, sizeof(sockaddr), NULL, address, &len );
875 ok( !ret, "WSAAddressToStringW() failed unexpectedly: %x\n", WSAGetLastError() );
876
877 ok( !lstrcmpW( address, expect1 ), "Expected different address string\n" );
878
879 len = sizeof(address);
880
881 sockaddr.sin_family = AF_INET;
882 sockaddr.sin_port = 0;
883 cs130_tom 1.1 sockaddr.sin_addr.s_addr = 0xffffffff;
884
885 ret = WSAAddressToStringW( (SOCKADDR*)&sockaddr, sizeof(sockaddr), NULL, address, &len );
886 ok( !ret, "WSAAddressToStringW() failed unexpectedly: %x\n", WSAGetLastError() );
887
888 ok( !lstrcmpW( address, expect2 ), "Expected different address string\n" );
889
890 len = sizeof(address);
891
892 sockaddr.sin_family = AF_INET;
893 sockaddr.sin_port = 0xffff;
894 sockaddr.sin_addr.s_addr = 0;
895
896 ret = WSAAddressToStringW( (SOCKADDR*)&sockaddr, sizeof(sockaddr), NULL, address, &len );
897 ok( !ret, "WSAAddressToStringW() failed unexpectedly: %x\n", WSAGetLastError() );
898
899 ok( !lstrcmpW( address, expect3 ), "Expected different address string\n" );
900
901 len = sizeof(address);
902
903 sockaddr.sin_family = AF_INET;
904 cs130_tom 1.1 sockaddr.sin_port = 0xffff;
905 sockaddr.sin_addr.s_addr = 0xffffffff;
906
907 ret = WSAAddressToStringW( (SOCKADDR*)&sockaddr, sizeof(sockaddr), NULL, address, &len );
908 ok( !ret, "WSAAddressToStringW() failed unexpectedly: %x\n", WSAGetLastError() );
909
910 ok( !lstrcmpW( address, expect4 ), "Expected different address string\n" );
911 }
912
913 static void test_WSAStringToAddressA()
914 {
915 INT ret, len;
916 SOCKADDR_IN sockaddr;
917
918 CHAR address1[] = "0.0.0.0";
919 CHAR address2[] = "127.127.127.127";
920 CHAR address3[] = "255.255.255.255";
921 CHAR address4[] = "127.127.127.127:65535";
922 CHAR address5[] = "255.255.255.255:65535";
923
924 len = 0;
925 cs130_tom 1.1 sockaddr.sin_family = AF_INET;
926
927 ret = WSAStringToAddressA( address1, AF_INET, NULL, (SOCKADDR*)&sockaddr, &len );
928 ok( ret == SOCKET_ERROR, "WSAStringToAddressA() succeeded unexpectedly: %x\n",
929 WSAGetLastError() );
930
931 len = sizeof(sockaddr);
932 sockaddr.sin_port = 0;
933 sockaddr.sin_addr.s_addr = 0;
934
935 ret = WSAStringToAddressA( address1, AF_INET, NULL, (SOCKADDR*)&sockaddr, &len );
936 ok( !ret && sockaddr.sin_addr.s_addr == 0,
937 "WSAStringToAddressA() failed unexpectedly: %d\n", WSAGetLastError() );
938
939 len = sizeof(sockaddr);
940 sockaddr.sin_port = 0;
941 sockaddr.sin_addr.s_addr = 0;
942
943 ret = WSAStringToAddressA( address2, AF_INET, NULL, (SOCKADDR*)&sockaddr, &len );
944 ok( !ret && sockaddr.sin_addr.s_addr == 0x7f7f7f7f,
945 "WSAStringToAddressA() failed unexpectedly: %d\n", WSAGetLastError() );
946 cs130_tom 1.1
947 len = sizeof(sockaddr);
948
949 ret = WSAStringToAddressA( address3, AF_INET, NULL, (SOCKADDR*)&sockaddr, &len );
950 ok( ret, "WSAStringToAddressA() succeeded unexpectedly: %d\n", WSAGetLastError() );
951
952 len = sizeof(sockaddr);
953 sockaddr.sin_port = 0;
954 sockaddr.sin_addr.s_addr = 0;
955
956 ret = WSAStringToAddressA( address4, AF_INET, NULL, (SOCKADDR*)&sockaddr, &len );
957 ok( !ret && sockaddr.sin_addr.s_addr == 0x7f7f7f7f && sockaddr.sin_port == 0xffff,
958 "WSAStringToAddressA() failed unexpectedly: %d\n", WSAGetLastError() );
959
960 len = sizeof(sockaddr);
961
962 ret = WSAStringToAddressA( address5, AF_INET, NULL, (SOCKADDR*)&sockaddr, &len );
963 ok( ret, "WSAStringToAddressA() succeeded unexpectedly: %d\n", WSAGetLastError() );
964 }
965
966 static void test_WSAStringToAddressW()
967 cs130_tom 1.1 {
968 INT ret, len;
969 SOCKADDR_IN sockaddr;
970
971 WCHAR address1[] = { '0','.','0','.','0','.','0', 0 };
972 WCHAR address2[] = { '1','2','7','.','1','2','7','.','1','2','7','.','1','2','7', 0 };
973 WCHAR address3[] = { '2','5','5','.','2','5','5','.','2','5','5','.','2','5','5', 0 };
974 WCHAR address4[] = { '1','2','7','.','1','2','7','.','1','2','7','.','1','2','7',
975 ':', '6', '5', '5', '3', '5', 0 };
976 WCHAR address5[] = { '2','5','5','.','2','5','5','.','2','5','5','.','2','5','5', ':',
977 '6', '5', '5', '3', '5', 0 };
978
979 len = 0;
980 sockaddr.sin_family = AF_INET;
981
982 ret = WSAStringToAddressW( address1, AF_INET, NULL, (SOCKADDR*)&sockaddr, &len );
983 ok( ret == SOCKET_ERROR, "WSAStringToAddressW() failed unexpectedly: %d\n",
984 WSAGetLastError() );
985
986 len = sizeof(sockaddr);
987 sockaddr.sin_port = 0;
988 cs130_tom 1.1 sockaddr.sin_addr.s_addr = 0;
989
990 ret = WSAStringToAddressW( address1, AF_INET, NULL, (SOCKADDR*)&sockaddr, &len );
991 ok( !ret && sockaddr.sin_addr.s_addr == 0,
992 "WSAStringToAddressW() failed unexpectedly: %d\n", WSAGetLastError() );
993
994 len = sizeof(sockaddr);
995
996 sockaddr.sin_port = 0;
997 sockaddr.sin_addr.s_addr = 0;
998
999 ret = WSAStringToAddressW( address2, AF_INET, NULL, (SOCKADDR*)&sockaddr, &len );
1000 ok( !ret && sockaddr.sin_addr.s_addr == 0x7f7f7f7f,
1001 "WSAStringToAddressW() failed unexpectedly: %d\n", WSAGetLastError() );
1002
1003 len = sizeof(sockaddr);
1004
1005 ret = WSAStringToAddressW( address3, AF_INET, NULL, (SOCKADDR*)&sockaddr, &len );
1006 ok( ret, "WSAStringToAddressW() failed unexpectedly: %d\n", WSAGetLastError() );
1007
1008 len = sizeof(sockaddr);
1009 cs130_tom 1.1 sockaddr.sin_port = 0;
1010 sockaddr.sin_addr.s_addr = 0;
1011
1012 ret = WSAStringToAddressW( address4, AF_INET, NULL, (SOCKADDR*)&sockaddr, &len );
1013 ok( !ret && sockaddr.sin_addr.s_addr == 0x7f7f7f7f && sockaddr.sin_port == 0xffff,
1014 "WSAStringToAddressW() failed unexpectedly: %d\n", WSAGetLastError() );
1015
1016 len = sizeof(sockaddr);
1017
1018 ret = WSAStringToAddressW( address5, AF_INET, NULL, (SOCKADDR*)&sockaddr, &len );
1019 ok( ret, "WSAStringToAddressW() succeeded unexpectedly: %d\n", WSAGetLastError() );
1020 }
1021
1022 /**************** Main program ***************/
1023
1024 START_TEST( sock )
1025 {
1026 int i;
1027 Init();
1028
1029 test_set_getsockopt();
1030 cs130_tom 1.1 test_so_reuseaddr();
1031
1032 for (i = 0; i < NUM_TESTS; i++)
1033 {
1034 trace ( " **** STARTING TEST %d **** \n", i );
1035 do_test ( &tests[i] );
1036 trace ( " **** TEST %d COMPLETE **** \n", i );
1037 }
1038
1039 test_WSAAddressToStringA();
1040 test_WSAAddressToStringW();
1041
1042 test_WSAStringToAddressA();
1043 test_WSAStringToAddressW();
1044
1045 Exit();
1046 }
|