ws2_32: Ignore lpFrom for connected sockets.

If the the socket is connected and lpFrom is not NULL, Linux will set
msg_namelen to zero and ignore msg_name in recvfrom so don't try try
to update lpFrom.
This commit is contained in:
Jeff Zaroyko 2008-06-13 18:05:22 +10:00 committed by Alexandre Julliard
parent 5b7bec34c1
commit 30e6b81dd1
2 changed files with 113 additions and 2 deletions

View File

@ -1103,7 +1103,17 @@ static int WS2_recv( int fd, struct iovec* iov, int count,
if ( (n = recvmsg(fd, &hdr, *lpFlags)) == -1 ) if ( (n = recvmsg(fd, &hdr, *lpFlags)) == -1 )
return -1; return -1;
if ( lpFrom && /* if this socket is connected and lpFrom is not NULL, Linux doesn't give us
* msg_name and msg_namelen from recvmsg, but it does set msg_namelen to zero.
*
* quoting linux 2.6 net/ipv4/tcp.c:
* "According to UNIX98, msg_name/msg_namelen are ignored
* on connected socket. I was just happy when found this 8) --ANK"
*
* likewise MSDN says that lpFrom and lpFromlen are ignored for
* connection-oriented sockets, so don't try to update lpFrom.
*/
if ( lpFrom && hdr.msg_namelen &&
ws_sockaddr_u2ws( &unix_sockaddr.addr, lpFrom, lpFromlen ) != 0 ) ws_sockaddr_u2ws( &unix_sockaddr.addr, lpFrom, lpFromlen ) != 0 )
{ {
/* The from buffer was too small, but we read the data /* The from buffer was too small, but we read the data

View File

@ -31,7 +31,7 @@
#include <winerror.h> #include <winerror.h>
#define MAX_CLIENTS 4 /* Max number of clients */ #define MAX_CLIENTS 4 /* Max number of clients */
#define NUM_TESTS 3 /* Number of tests performed */ #define NUM_TESTS 4 /* Number of tests performed */
#define FIRST_CHAR 'A' /* First character in transferred pattern */ #define FIRST_CHAR 'A' /* First character in transferred pattern */
#define BIND_SLEEP 10 /* seconds to wait between attempts to bind() */ #define BIND_SLEEP 10 /* seconds to wait between attempts to bind() */
#define BIND_TRIES 6 /* Number of bind() attempts */ #define BIND_TRIES 6 /* Number of bind() attempts */
@ -269,6 +269,16 @@ static int do_synchronous_recv ( SOCKET s, char *buf, int buflen, int recvlen )
return p - buf; return p - buf;
} }
static int do_synchronous_recvfrom ( SOCKET s, char *buf, int buflen,int flags,struct sockaddr *from, socklen_t *fromlen, int recvlen )
{
char* last = buf + buflen, *p;
int n = 1;
for ( p = buf; n > 0 && p < last; p += n )
n = recvfrom ( s, p, min ( recvlen, last - p ), 0, from, fromlen );
wsa_ok ( n, 0 <=, "do_synchronous_recv (%x): error %d:\n" );
return p - buf;
}
/* /*
* Call this routine right after thread startup. * Call this routine right after thread startup.
* SO_OPENTYPE must by 0, regardless what the server did. * SO_OPENTYPE must by 0, regardless what the server did.
@ -626,6 +636,76 @@ static VOID WINAPI simple_client ( client_params *par )
client_stop (); client_stop ();
} }
/*
* simple_mixed_client: mixing send and recvfrom
*/
static VOID WINAPI simple_mixed_client ( client_params *par )
{
test_params *gen = par->general;
client_memory *mem;
int n_sent, n_recvd, n_expected = gen->n_chunks * gen->chunk_size, id;
char *p;
socklen_t fromLen = sizeof(mem->addr);
struct sockaddr test;
id = GetCurrentThreadId();
trace ( "simple_client (%x): starting\n", id );
/* wait here because we want to call set_so_opentype before creating a socket */
WaitForSingleObject ( server_ready, INFINITE );
trace ( "simple_client (%x): server ready\n", id );
check_so_opentype ();
set_so_opentype ( FALSE ); /* non-overlapped */
client_start ( par );
mem = TlsGetValue ( tls );
/* Connect */
wsa_ok ( connect ( mem->s, (struct sockaddr*) &mem->addr, sizeof ( mem->addr ) ),
0 ==, "simple_client (%x): connect error: %d\n" );
ok ( set_blocking ( mem->s, TRUE ) == 0,
"simple_client (%x): failed to set blocking mode\n", id );
trace ( "simple_client (%x) connected\n", id );
/* send data to server */
n_sent = do_synchronous_send ( mem->s, mem->send_buf, n_expected, par->buflen );
ok ( n_sent == n_expected,
"simple_client (%x): sent less data than expected: %d of %d\n", id, n_sent, n_expected );
/* shutdown send direction */
wsa_ok ( shutdown ( mem->s, SD_SEND ), 0 ==, "simple_client (%x): shutdown failed: %d\n" );
/* this shouldn't change, since lpFrom, is not updated on
connection oriented sockets - exposed by bug 11640
*/
((struct sockaddr_in*)&test)->sin_addr.s_addr = inet_addr("0.0.0.0");
/* Receive data echoed back & check it */
n_recvd = do_synchronous_recvfrom ( mem->s,
mem->recv_buf,
n_expected,
0,
(struct sockaddr *)&test,
&fromLen,
par->buflen );
ok ( n_recvd == n_expected,
"simple_client (%x): received less data than expected: %d of %d\n", id, n_recvd, n_expected );
/* check that lpFrom was not updated */
ok(0 ==
strcmp(
inet_ntoa(((struct sockaddr_in*)&test)->sin_addr),
"0.0.0.0"), "lpFrom shouldn't be updated on connection oriented sockets\n");
/* check data */
p = test_buffer ( mem->recv_buf, gen->chunk_size, gen->n_chunks );
ok ( p == NULL, "simple_client (%x): test pattern error: %d\n", id, p - mem->recv_buf);
/* cleanup */
read_zero_bytes ( mem->s );
trace ( "simple_client (%x) exiting\n", id );
client_stop ();
}
/* /*
* event_client: An event-driven client * event_client: An event-driven client
*/ */
@ -1013,6 +1093,27 @@ static test_setup tests [NUM_TESTS] =
0, 0,
128 128
} }
},
/* Test 3: synchronous mixed client and server */
{
{
STD_STREAM_SOCKET,
2048,
16,
2
},
simple_server,
{
NULL,
0,
64
},
simple_mixed_client,
{
NULL,
0,
128
}
} }
}; };