Make the recv() and send() family of functions use WSARecvFrom() and

WSASendTo().
oldstable
Martin Wilck 2002-04-05 21:22:55 +00:00 committed by Alexandre Julliard
parent 63963b8ddf
commit 58854430fa
2 changed files with 223 additions and 187 deletions

View File

@ -1797,34 +1797,13 @@ INT16 WINAPI WINSOCK_listen16(SOCKET16 s, INT16 backlog)
*/
int WINAPI WS_recv(SOCKET s, char *buf, int len, int flags)
{
int fd = _get_sock_fd(s);
DWORD n, dwFlags = flags;
WSABUF wsabuf = { len, buf };
TRACE("socket %04x, buf %8x, len %d, flags %d\n", s, (unsigned)buf, len, flags);
if (fd != -1)
{
INT length;
if (_is_blocking(s))
{
/* block here */
/* FIXME: OOB and exceptfds? */
do_block(fd, 1);
}
if ((length = recv(fd, buf, len, flags)) >= 0)
{
TRACE(" -> %i bytes\n", length);
close(fd);
_enable_event(s, FD_READ, 0, 0);
return length;
}
SetLastError(wsaErrno());
close(fd);
}
else SetLastError(WSAENOTSOCK);
WARN(" -> ERROR\n");
return SOCKET_ERROR;
if ( WSARecvFrom (s, &wsabuf, 1, &n, &dwFlags, NULL, NULL, NULL, NULL) == SOCKET_ERROR )
return SOCKET_ERROR;
else
return n;
}
/***********************************************************************
@ -1842,60 +1821,13 @@ INT16 WINAPI WINSOCK_recv16(SOCKET16 s, char *buf, INT16 len, INT16 flags)
int WINAPI WS_recvfrom(SOCKET s, char *buf, INT len, int flags,
struct WS_sockaddr *from, int *fromlen)
{
int fd = _get_sock_fd(s);
int res;
DWORD n, dwFlags = flags;
WSABUF wsabuf = { len, buf };
TRACE("socket %04x, ptr %08x, len %d, flags %d\n", s, (unsigned)buf, len, flags);
#if DEBUG_SOCKADDR
if (from)
dump_sockaddr(from);
if ( WSARecvFrom (s, &wsabuf, 1, &n, &dwFlags, from, fromlen, NULL, NULL) == SOCKET_ERROR )
return SOCKET_ERROR;
else
DPRINTF("from = NULL\n");
#endif
res=SOCKET_ERROR;
if (fd != -1)
{
struct sockaddr* uaddr;
int uaddrlen;
int length;
if (_is_blocking(s))
{
/* block here */
/* FIXME: OOB and exceptfds */
do_block(fd, 1);
}
uaddr=ws_sockaddr_alloc(from,fromlen,&uaddrlen);
length=recvfrom(fd, buf, len, flags, uaddr, &uaddrlen);
if (length < 0)
{
SetLastError(wsaErrno());
WARN(" -> ERROR\n");
}
else if (ws_sockaddr_u2ws(uaddr,uaddrlen,from,fromlen) != 0)
{
/* The from buffer was too small, but we read the data
* anyway. Is that really bad?
*/
SetLastError(WSAEFAULT);
WARN(" -> WSAEFAULT\n");
}
else
{
TRACE(" -> %i bytes\n", length);
_enable_event(s, FD_READ, 0, 0);
res=length;
}
close(fd);
}
else
{
SetLastError(WSAENOTSOCK);
WARN(" -> WSAENOTSOCK\n");
}
return res;
return n;
}
/***********************************************************************
@ -2012,34 +1944,13 @@ int WINAPI WS_select(int nfds, WS_fd_set *ws_readfds,
*/
int WINAPI WS_send(SOCKET s, const char *buf, int len, int flags)
{
int fd = _get_sock_fd(s);
DWORD n;
WSABUF wsabuf = { len, (char*) buf };
TRACE("socket %04x, ptr %p, length %d, flags %d\n", s, buf, len, flags);
if (fd != -1)
{
int length;
if (_is_blocking(s))
{
/* block here */
/* FIXME: exceptfds */
do_block(fd, 2);
}
if ((length = send(fd, buf, len, flags)) < 0 )
{
SetLastError(wsaErrno());
if( GetLastError() == WSAEWOULDBLOCK )
_enable_event(s, FD_WRITE, 0, 0);
}
else
{
close(fd);
return length;
}
close(fd);
}
else SetLastError(WSAENOTSOCK);
return SOCKET_ERROR;
if ( WSASendTo ( s, &wsabuf, 1, &n, flags, NULL, 0, NULL, NULL) == SOCKET_ERROR )
return SOCKET_ERROR;
else
return n;
}
/***********************************************************************
@ -2050,43 +1961,106 @@ INT WINAPI WSASend( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
LPWSAOVERLAPPED lpOverlapped,
LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine )
{
INT iFlags = 0;
INT rc = 0;
DWORD dwCount;
return WSASendTo ( s, lpBuffers, dwBufferCount, lpNumberOfBytesSent, dwFlags,
NULL, 0, lpOverlapped, lpCompletionRoutine );
}
/* Overlapped is not supported or checked for */
FIXME( "(%u,%p,0x%lx,%p,0x%lx,%p,%p): semi stub\n",
s, lpBuffers, dwBufferCount, lpNumberOfBytesSent,
dwFlags, lpOverlapped, lpCompletionRoutine );
/***********************************************************************
* WSASendTo (WS2_32.74)
*/
INT WINAPI WSASendTo( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
LPDWORD lpNumberOfBytesSent, DWORD dwFlags,
const struct WS_sockaddr *to, int tolen,
LPWSAOVERLAPPED lpOverlapped,
LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine )
{
int i, n, fd, err = WSAENOTSOCK;
struct iovec* iovec;
struct msghdr msghdr;
/* Convert setup flags */
if( dwFlags & MSG_DONTROUTE )
{
iFlags |= MSG_DONTROUTE;
}
TRACE ("socket %04x, wsabuf %p, nbufs %ld, flags %ld, to %p, tolen %d, ovl %p, func %p\n",
s, lpBuffers, dwBufferCount, dwFlags,
to, tolen, lpOverlapped, lpCompletionRoutine);
if( dwFlags & MSG_OOB )
{
iFlags |= MSG_OOB;
}
fd = _get_sock_fd(s);
/* Indicate nothing yet sent */
*lpNumberOfBytesSent = 0;
if ( fd == -1 )
goto error;
/* Send all buffers with the same flags */
for(dwCount = 0; dwCount < dwBufferCount; dwCount++ )
{
if( ( rc = WS_send( s, lpBuffers[ dwCount ].buf,
lpBuffers[ dwCount ].len, iFlags ) ) != 0 )
iovec = WS_ALLOC ( dwBufferCount * sizeof (struct iovec) );
if ( !iovec )
{
break;
err = WSAENOBUFS;
goto err_close;
}
/* Indicate that we've sent something */
*lpNumberOfBytesSent += lpBuffers[ dwCount ].len;
}
for ( i = 0; i < dwBufferCount; i++ )
{
iovec[i].iov_base = lpBuffers[i].buf;
iovec[i].iov_len = lpBuffers[i].len;
}
return rc;
msghdr.msg_name = NULL;
if (to)
{
#if DEBUG_SOCKADDR
dump_sockaddr (to);
#endif
msghdr.msg_name = (void*) ws_sockaddr_ws2u (to, tolen, &msghdr.msg_namelen);
if ( !msghdr.msg_name )
{
err = WSAEFAULT;
goto err_free;
}
}
else
msghdr.msg_namelen = 0;
msghdr.msg_iov = iovec;
msghdr.msg_iovlen = dwBufferCount;
msghdr.msg_control = NULL;
msghdr.msg_controllen = 0;
msghdr.msg_flags = 0;
/* FIXME: Treat overlapped IO here */
if (_is_blocking(s))
{
/* FIXME: exceptfds? */
do_block(fd, 2);
}
/* FIXME: can we support MSG_PARTIAL ? How does it relate to sendmsg()'s msg_flags ? */
if ((n = sendmsg (fd, &msghdr, dwFlags)) == -1)
{
err = wsaErrno();
if ( err == WSAEWOULDBLOCK )
_enable_event (s, FD_WRITE, 0, 0);
goto err_free;
}
*lpNumberOfBytesSent = n;
ws_sockaddr_free ( msghdr.msg_name, to );
WS_FREE ( iovec );
close ( fd );
return 0;
err_free:
ws_sockaddr_free ( msghdr.msg_name, to );
WS_FREE ( iovec );
err_close:
close ( fd );
error:
WARN (" -> ERROR %d\n", err);
SetLastError (err);
return SOCKET_ERROR;
}
/***********************************************************************
@ -2103,46 +2077,13 @@ INT16 WINAPI WINSOCK_send16(SOCKET16 s, char *buf, INT16 len, INT16 flags)
int WINAPI WS_sendto(SOCKET s, const char *buf, int len, int flags,
const struct WS_sockaddr *to, int tolen)
{
int fd = _get_sock_fd(s);
int res;
DWORD n;
WSABUF wsabuf = { len, (char*) buf };
TRACE("socket %04x, ptr %p, length %d, flags %d\n", s, buf, len, flags);
res=SOCKET_ERROR;
if (fd != -1)
{
const struct sockaddr* uaddr;
int uaddrlen;
uaddr=ws_sockaddr_ws2u(to,tolen,&uaddrlen);
if (uaddr == NULL)
{
SetLastError(WSAEFAULT);
}
else
{
if (_is_blocking(s))
{
/* block here */
/* FIXME: exceptfds */
do_block(fd, 2);
}
res=sendto(fd, buf, len, flags, uaddr, uaddrlen);
if (res < 0 )
{
SetLastError(wsaErrno());
if( GetLastError() == WSAEWOULDBLOCK )
_enable_event(s, FD_WRITE, 0, 0);
}
ws_sockaddr_free(uaddr,to);
}
close(fd);
}
if ( WSASendTo (s, &wsabuf, 1, &n, flags, to, tolen, NULL, NULL) == SOCKET_ERROR )
return SOCKET_ERROR;
else
{
SetLastError(WSAENOTSOCK);
}
return res;
return n;
}
/***********************************************************************
@ -3301,6 +3242,18 @@ UINT16 wsaHerrno(int loc_errno)
}
/***********************************************************************
* WSARecv (WS2_32.67)
*/
int WINAPI WSARecv (SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
LPDWORD NumberOfBytesReceived, LPDWORD lpFlags,
LPWSAOVERLAPPED lpOverlapped,
LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
{
return WSARecvFrom (s, lpBuffers, dwBufferCount, NumberOfBytesReceived, lpFlags,
NULL, NULL, lpOverlapped, lpCompletionRoutine);
}
/***********************************************************************
* WSARecvFrom (WS2_32.69)
*/
@ -3308,29 +3261,112 @@ INT WINAPI WSARecvFrom( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
LPDWORD lpNumberOfBytesRecvd, LPDWORD lpFlags, struct WS_sockaddr *lpFrom,
LPINT lpFromlen, LPWSAOVERLAPPED lpOverlapped,
LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine )
{
DWORD dwCount;
INT rc;
/* Uses recvmsg() in order to provide scatter-gather I/O */
FIXME( "(%i,%p,%lu,%p,%p,%p,%p,%p,%p: stub\n",
s, lpBuffers, dwBufferCount, lpNumberOfBytesRecvd, lpFlags,
lpFrom, lpFromlen, lpOverlapped, lpCompletionRoutine );
struct iovec* iovec;
struct msghdr msghdr;
int fd, i, length, err = WSAENOTSOCK;
for( dwCount = 0, rc = 0; dwCount < dwBufferCount; dwCount++ )
{
TRACE("socket %04x, wsabuf %p, nbufs %ld, flags %ld, from %p, fromlen %ld, ovl %p, func %p\n",
s, lpBuffers, dwBufferCount, *lpFlags, lpFrom,
(lpFromlen ? *lpFromlen : -1L),
lpOverlapped, lpCompletionRoutine);
if( ( rc = WS_recvfrom(s, lpBuffers[ dwCount ].buf, (INT)lpBuffers[ dwCount ].len,
(INT)*lpFlags, lpFrom, lpFromlen ) ) != 0 )
fd = _get_sock_fd(s);
if (fd == -1)
{
break;
err = WSAENOTSOCK;
goto error;
}
}
/* FIXME: should this be HeapAlloc() or WS_ALLOC ? */
iovec = WS_ALLOC ( dwBufferCount * sizeof (struct iovec) );
if ( !iovec )
{
err = WSAENOBUFS;
goto err_close;
}
return rc;
for (i = 0; i < dwBufferCount; i++)
{
iovec[i].iov_base = lpBuffers[i].buf;
iovec[i].iov_len = lpBuffers[i].len;
}
msghdr.msg_name = NULL;
if ( lpFrom )
{
#if DEBUG_SOCKADDR
dump_sockaddr (lpFrom);
#endif
msghdr.msg_namelen = *lpFromlen;
msghdr.msg_name = ws_sockaddr_alloc (lpFrom, lpFromlen, &msghdr.msg_namelen);
}
else
msghdr.msg_namelen = 0;
msghdr.msg_iov = iovec;
msghdr.msg_iovlen = dwBufferCount;
msghdr.msg_control = NULL;
msghdr.msg_controllen = 0;
msghdr.msg_flags = 0;
/* FIXME: Treat overlapped IO here */
if (_is_blocking(s))
{
/* block here */
/* FIXME: OOB and exceptfds? */
do_block(fd, 1);
}
/* FIXME: can we support MSG_PARTIAL ?
How does it relate to recvmsg()'s msg_flags ? */
if ((length = recvmsg (fd, &msghdr, *lpFlags)) == -1)
{
err = wsaErrno();
goto err_free;
}
TRACE(" -> %i bytes\n", length);
if ( lpFrom && ws_sockaddr_u2ws (msghdr.msg_name, msghdr.msg_namelen, lpFrom, lpFromlen) != 0 )
{
/* The from buffer was too small, but we read the data
* anyway. Is that really bad?
*/
SetLastError ( WSAEFAULT );
WARN ( " -> Address buffer too small\n" );
}
*lpNumberOfBytesRecvd = length;
WS_FREE (iovec);
ws_sockaddr_free ( msghdr.msg_name, lpFrom );
close(fd);
_enable_event(s, FD_READ, 0, 0);
return 0;
err_free:
WS_FREE (iovec);
ws_sockaddr_free ( msghdr.msg_name, lpFrom );
err_close:
close (fd);
error:
WARN(" -> ERROR %d\n", err);
SetLastError ( err );
return SOCKET_ERROR;
}
/***********************************************************************
* WSCInstallProvider (WS2_32.88)
*/

View File

@ -79,14 +79,14 @@ debug_channels (winsock)
64 stub WSANtohl
65 stub WSANtohs
66 stub WSAProviderConfigChange
67 stub WSARecv
67 stdcall WSARecv(long ptr long ptr ptr ptr ptr) WSARecv
68 stub WSARecvDisconnect
69 stdcall WSARecvFrom(long ptr long ptr ptr ptr ptr ptr ptr ) WSARecvFrom
70 stub WSARemoveServiceClass
71 forward WSAResetEvent KERNEL32.ResetEvent
72 stdcall WSASend(long ptr long ptr long ptr ptr) WSASend
73 stub WSASendDisconnect
74 stub WSASendTo
74 stdcall WSASendTo(long ptr long ptr long ptr long ptr ptr) WSASendTo
75 stub WSASetEvent
76 stub WSASetServiceA
77 stub WSASetServiceW