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:
parent
5b7bec34c1
commit
30e6b81dd1
|
@ -1103,7 +1103,17 @@ static int WS2_recv( int fd, struct iovec* iov, int count,
|
|||
if ( (n = recvmsg(fd, &hdr, *lpFlags)) == -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 )
|
||||
{
|
||||
/* The from buffer was too small, but we read the data
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
#include <winerror.h>
|
||||
|
||||
#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 BIND_SLEEP 10 /* seconds to wait between attempts to bind() */
|
||||
#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;
|
||||
}
|
||||
|
||||
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.
|
||||
* SO_OPENTYPE must by 0, regardless what the server did.
|
||||
|
@ -626,6 +636,76 @@ static VOID WINAPI simple_client ( client_params *par )
|
|||
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
|
||||
*/
|
||||
|
@ -1013,6 +1093,27 @@ static test_setup tests [NUM_TESTS] =
|
|||
0,
|
||||
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
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue