Add Udp::ReceiveMultiple method
This commit is contained in:
parent
2ca844be63
commit
b4732d8c17
|
|
@ -39,6 +39,7 @@ namespace Nz
|
||||||
std::size_t QueryMaxDatagramSize();
|
std::size_t QueryMaxDatagramSize();
|
||||||
|
|
||||||
bool Receive(void* buffer, std::size_t size, IpAddress* from, std::size_t* received);
|
bool Receive(void* buffer, std::size_t size, IpAddress* from, std::size_t* received);
|
||||||
|
bool ReceiveMultiple(NetBuffer* buffers, std::size_t bufferCount, IpAddress* from, std::size_t* received);
|
||||||
bool ReceivePacket(NetPacket* packet, IpAddress* from);
|
bool ReceivePacket(NetPacket* packet, IpAddress* from);
|
||||||
|
|
||||||
bool Send(const IpAddress& to, const void* buffer, std::size_t size, std::size_t* sent);
|
bool Send(const IpAddress& to, const void* buffer, std::size_t size, std::size_t* sent);
|
||||||
|
|
|
||||||
|
|
@ -549,6 +549,90 @@ namespace Nz
|
||||||
else // else we received something
|
else // else we received something
|
||||||
senderIp = IpAddressImpl::FromSockAddr(reinterpret_cast<const sockaddr*>(&nameBuffer));
|
senderIp = IpAddressImpl::FromSockAddr(reinterpret_cast<const sockaddr*>(&nameBuffer));
|
||||||
|
|
||||||
|
if (from)
|
||||||
|
*from = IpAddressImpl::FromSockAddr(reinterpret_cast<const sockaddr*>(&nameBuffer));
|
||||||
|
|
||||||
|
if (read)
|
||||||
|
*read = byteRead;
|
||||||
|
|
||||||
|
if (error)
|
||||||
|
*error = SocketError_NoError;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SocketImpl::ReceiveMultiple(SocketHandle handle, NetBuffer* buffers, std::size_t bufferCount, IpAddress* from, int* read, SocketError* error)
|
||||||
|
{
|
||||||
|
NazaraAssert(handle != InvalidHandle, "Invalid handle");
|
||||||
|
NazaraAssert(buffers && bufferCount > 0, "Invalid buffers");
|
||||||
|
|
||||||
|
StackAllocation memory = NazaraStackAllocation(bufferCount * sizeof(iovec));
|
||||||
|
struct iovec* sysBuffers = static_cast<struct iovec*>(memory.GetPtr());
|
||||||
|
for (std::size_t i = 0; i < bufferCount; ++i)
|
||||||
|
{
|
||||||
|
sysBuffers[i].iov_base = buffers[i].data;
|
||||||
|
sysBuffers[i].iov_len = buffers[i].dataLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct msghdr msgHdr;
|
||||||
|
std::memset(&msgHdr, 0, sizeof(msgHdr));
|
||||||
|
|
||||||
|
msgHdr.msg_iov = sysBuffers;
|
||||||
|
msgHdr.msg_iovlen = static_cast<int>(bufferCount);
|
||||||
|
|
||||||
|
IpAddressImpl::SockAddrBuffer nameBuffer;
|
||||||
|
if (from)
|
||||||
|
{
|
||||||
|
msgHdr.msg_name = nameBuffer.data();
|
||||||
|
msgHdr.msg_namelen = static_cast<socklen_t>(nameBuffer.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
int byteRead = recvmsg(handle, &msgHdr, MSG_NOSIGNAL);
|
||||||
|
if (byteRead == -1)
|
||||||
|
{
|
||||||
|
int errorCode = GetLastErrorCode();
|
||||||
|
if (errorCode == EAGAIN)
|
||||||
|
errorCode = EWOULDBLOCK;
|
||||||
|
|
||||||
|
switch (errorCode)
|
||||||
|
{
|
||||||
|
case EWOULDBLOCK:
|
||||||
|
{
|
||||||
|
// If we have no data and are not blocking, return true with 0 byte read
|
||||||
|
recvLength = 0;
|
||||||
|
senderIp = IpAddress::Invalid;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
if (error)
|
||||||
|
*error = TranslateErrnoToResolveError(errorCode);
|
||||||
|
|
||||||
|
return false; //< Error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (byteRead == 0)
|
||||||
|
{
|
||||||
|
if (error)
|
||||||
|
*error = SocketError_ConnectionClosed;
|
||||||
|
|
||||||
|
return false; //< Connection closed
|
||||||
|
}
|
||||||
|
else // else we received something
|
||||||
|
senderIp = IpAddressImpl::FromSockAddr(reinterpret_cast<const sockaddr*>(nameBuffer.data()));
|
||||||
|
|
||||||
|
#ifdef HAS_MSGHDR_FLAGS
|
||||||
|
if (msgHdr.msg_flags & MSG_TRUNC)
|
||||||
|
{
|
||||||
|
if (error)
|
||||||
|
*error = SocketError_DatagramSize;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (from)
|
if (from)
|
||||||
*from = senderIp;
|
*from = senderIp;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -63,6 +63,7 @@ namespace Nz
|
||||||
|
|
||||||
static bool Receive(SocketHandle handle, void* buffer, int length, int* read, SocketError* error);
|
static bool Receive(SocketHandle handle, void* buffer, int length, int* read, SocketError* error);
|
||||||
static bool ReceiveFrom(SocketHandle handle, void* buffer, int length, IpAddress* from, int* read, SocketError* error);
|
static bool ReceiveFrom(SocketHandle handle, void* buffer, int length, IpAddress* from, int* read, SocketError* error);
|
||||||
|
static bool ReceiveMultiple(SocketHandle handle, NetBuffer* buffers, std::size_t bufferCount, IpAddress* from, int* read, SocketError* error);
|
||||||
|
|
||||||
static bool Send(SocketHandle handle, const void* buffer, int length, int* sent, SocketError* error);
|
static bool Send(SocketHandle handle, const void* buffer, int length, int* sent, SocketError* error);
|
||||||
static bool SendMultiple(SocketHandle handle, const NetBuffer* buffers, std::size_t bufferCount, const IpAddress& to, int* sent, SocketError* error);
|
static bool SendMultiple(SocketHandle handle, const NetBuffer* buffers, std::size_t bufferCount, const IpAddress& to, int* sent, SocketError* error);
|
||||||
|
|
|
||||||
|
|
@ -118,6 +118,42 @@ namespace Nz
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Receive multiple datagram from one peer
|
||||||
|
* \return true If data were sent
|
||||||
|
*
|
||||||
|
* \param to Destination IpAddress (must match socket protocol)
|
||||||
|
* \param buffers A pointer to an array of NetBuffer containing buffers and size data
|
||||||
|
* \param bufferCount Number of buffers available
|
||||||
|
* \param from IpAddress of the peer
|
||||||
|
* \param received Optional argument to get the number of bytes received
|
||||||
|
*/
|
||||||
|
bool UdpSocket::ReceiveMultiple(NetBuffer* buffers, std::size_t bufferCount, IpAddress* from, std::size_t* received)
|
||||||
|
{
|
||||||
|
NazaraAssert(m_handle != SocketImpl::InvalidHandle, "Socket hasn't been created");
|
||||||
|
NazaraAssert(buffers && bufferCount > 0, "Invalid buffer");
|
||||||
|
|
||||||
|
int read;
|
||||||
|
if (!SocketImpl::ReceiveMultiple(m_handle, buffers, bufferCount, from, &read, &m_lastError))
|
||||||
|
{
|
||||||
|
switch (m_lastError)
|
||||||
|
{
|
||||||
|
case SocketError_ConnectionClosed:
|
||||||
|
m_lastError = SocketError_NoError;
|
||||||
|
read = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (received)
|
||||||
|
*received = read;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Receives the packet available
|
* \brief Receives the packet available
|
||||||
* \return true If packet received
|
* \return true If packet received
|
||||||
|
|
|
||||||
|
|
@ -586,6 +586,72 @@ namespace Nz
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SocketImpl::ReceiveMultiple(SocketHandle handle, NetBuffer* buffers, std::size_t bufferCount, IpAddress* from, int* read, SocketError* error)
|
||||||
|
{
|
||||||
|
NazaraAssert(handle != InvalidHandle, "Invalid handle");
|
||||||
|
NazaraAssert(buffers && bufferCount > 0, "Invalid buffers");
|
||||||
|
|
||||||
|
IpAddressImpl::SockAddrBuffer nameBuffer;
|
||||||
|
int bufferLength = static_cast<int>(nameBuffer.size());
|
||||||
|
|
||||||
|
IpAddress senderIp;
|
||||||
|
|
||||||
|
StackAllocation memory = NazaraStackAllocation(bufferCount * sizeof(WSABUF));
|
||||||
|
WSABUF* winBuffers = static_cast<WSABUF*>(memory.GetPtr());
|
||||||
|
for (std::size_t i = 0; i < bufferCount; ++i)
|
||||||
|
{
|
||||||
|
winBuffers[i].buf = static_cast<CHAR*>(buffers[i].data);
|
||||||
|
winBuffers[i].len = static_cast<ULONG>(buffers[i].dataLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
DWORD flags = 0;
|
||||||
|
DWORD byteRead;
|
||||||
|
if (WSARecvFrom(handle, winBuffers, static_cast<DWORD>(bufferCount), &byteRead, &flags, reinterpret_cast<sockaddr*>(nameBuffer.data()), &bufferLength, nullptr, nullptr) == SOCKET_ERROR)
|
||||||
|
{
|
||||||
|
int errorCode = WSAGetLastError();
|
||||||
|
switch (errorCode)
|
||||||
|
{
|
||||||
|
case WSAECONNRESET:
|
||||||
|
case WSAEWOULDBLOCK:
|
||||||
|
{
|
||||||
|
// If we have no data and are not blocking, return true with 0 byte read
|
||||||
|
byteRead = 0;
|
||||||
|
senderIp = IpAddress::Invalid;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
if (error)
|
||||||
|
*error = TranslateWSAErrorToSocketError(errorCode);
|
||||||
|
|
||||||
|
return false; //< Error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
senderIp = IpAddressImpl::FromSockAddr(reinterpret_cast<const sockaddr*>(&nameBuffer));
|
||||||
|
|
||||||
|
if (flags & MSG_PARTIAL)
|
||||||
|
{
|
||||||
|
if (error)
|
||||||
|
*error = SocketError_DatagramSize;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (from)
|
||||||
|
*from = senderIp;
|
||||||
|
|
||||||
|
if (read)
|
||||||
|
*read = byteRead;
|
||||||
|
|
||||||
|
if (error)
|
||||||
|
*error = SocketError_NoError;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool SocketImpl::Send(SocketHandle handle, const void* buffer, int length, int* sent, SocketError* error)
|
bool SocketImpl::Send(SocketHandle handle, const void* buffer, int length, int* sent, SocketError* error)
|
||||||
{
|
{
|
||||||
NazaraAssert(handle != InvalidHandle, "Invalid handle");
|
NazaraAssert(handle != InvalidHandle, "Invalid handle");
|
||||||
|
|
|
||||||
|
|
@ -64,6 +64,7 @@ namespace Nz
|
||||||
|
|
||||||
static bool Receive(SocketHandle handle, void* buffer, int length, int* read, SocketError* error);
|
static bool Receive(SocketHandle handle, void* buffer, int length, int* read, SocketError* error);
|
||||||
static bool ReceiveFrom(SocketHandle handle, void* buffer, int length, IpAddress* from, int* read, SocketError* error);
|
static bool ReceiveFrom(SocketHandle handle, void* buffer, int length, IpAddress* from, int* read, SocketError* error);
|
||||||
|
static bool ReceiveMultiple(SocketHandle handle, NetBuffer* buffers, std::size_t bufferCount, IpAddress* from, int* read, SocketError* error);
|
||||||
|
|
||||||
static bool Send(SocketHandle handle, const void* buffer, int length, int* sent, SocketError* error);
|
static bool Send(SocketHandle handle, const void* buffer, int length, int* sent, SocketError* error);
|
||||||
static bool SendMultiple(SocketHandle handle, const NetBuffer* buffers, std::size_t bufferCount, const IpAddress& to, int* sent, SocketError* error);
|
static bool SendMultiple(SocketHandle handle, const NetBuffer* buffers, std::size_t bufferCount, const IpAddress& to, int* sent, SocketError* error);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue