From 85f02086901bbe0ef6ad6f7a1b5f243d3dd8362c Mon Sep 17 00:00:00 2001 From: DrLynix Date: Fri, 20 Jan 2017 14:33:05 +0100 Subject: [PATCH] Newtork/AbstractSocket: Allow to specify receive and send buffer size per socket --- include/Nazara/Network/AbstractSocket.hpp | 7 +- src/Nazara/Network/AbstractSocket.cpp | 48 ++++++++++++- src/Nazara/Network/Posix/SocketImpl.cpp | 86 +++++++++++++++++++++-- src/Nazara/Network/Posix/SocketImpl.hpp | 4 ++ src/Nazara/Network/Win32/SocketImpl.cpp | 82 ++++++++++++++++++++- src/Nazara/Network/Win32/SocketImpl.hpp | 6 +- 6 files changed, 222 insertions(+), 11 deletions(-) diff --git a/include/Nazara/Network/AbstractSocket.hpp b/include/Nazara/Network/AbstractSocket.hpp index d137c9050..8a2e55e25 100644 --- a/include/Nazara/Network/AbstractSocket.hpp +++ b/include/Nazara/Network/AbstractSocket.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2017 Jérôme Leclercq +// Copyright (C) 2017 Jérôme Leclercq // This file is part of the "Nazara Engine - Network module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -34,6 +34,11 @@ namespace Nz inline bool IsBlockingEnabled() const; std::size_t QueryAvailableBytes() const; + std::size_t QueryReceiveBufferSize() const; + std::size_t QuerySendBufferSize() const; + + void SetReceiveBufferSize(std::size_t size); + void SetSendBufferSize(std::size_t size); AbstractSocket& operator=(const AbstractSocket&) = delete; AbstractSocket& operator=(AbstractSocket&& abstractSocket); diff --git a/src/Nazara/Network/AbstractSocket.cpp b/src/Nazara/Network/AbstractSocket.cpp index 03b27c57f..f562900d2 100644 --- a/src/Nazara/Network/AbstractSocket.cpp +++ b/src/Nazara/Network/AbstractSocket.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2017 Jérôme Leclercq +// Copyright (C) 2017 Jérôme Leclercq // This file is part of the "Nazara Engine - Utility module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -111,6 +111,52 @@ namespace Nz return SocketImpl::QueryAvailableBytes(m_handle); } + /*! + * \brief Queries the maximum socket receive buffer size + * \return The size of the receive buffer in bytes. + */ + std::size_t AbstractSocket::QueryReceiveBufferSize() const + { + if (m_handle == SocketImpl::InvalidHandle) + return 0; + + return SocketImpl::QueryReceiveBufferSize(m_handle); + } + + /*! + * \brief Queries the maximum socket send buffer size + * \return The size of the send buffer in bytes. + */ + std::size_t AbstractSocket::QuerySendBufferSize() const + { + if (m_handle == SocketImpl::InvalidHandle) + return 0; + + return SocketImpl::QuerySendBufferSize(m_handle); + } + + /*! + * \brief Sets the maximum receive buffer size + * + * \param size The new maximum receive buffer size in bytes + */ + void AbstractSocket::SetReceiveBufferSize(std::size_t size) + { + if (m_handle != SocketImpl::InvalidHandle) + SocketImpl::SetReceiveBufferSize(m_handle, size); + } + + /*! + * \brief Sets the maximum send buffer size + * + * \param size The new maximum send buffer size in bytes + */ + void AbstractSocket::SetSendBufferSize(std::size_t size) + { + if (m_handle != SocketImpl::InvalidHandle) + SocketImpl::SetSendBufferSize(m_handle, size); + } + /*! * \brief Operation to do when closing socket */ diff --git a/src/Nazara/Network/Posix/SocketImpl.cpp b/src/Nazara/Network/Posix/SocketImpl.cpp index 954ac4f43..69f0d0bf3 100644 --- a/src/Nazara/Network/Posix/SocketImpl.cpp +++ b/src/Nazara/Network/Posix/SocketImpl.cpp @@ -277,7 +277,7 @@ namespace Nz bool SocketImpl::QueryBroadcasting(SocketHandle handle, SocketError* error) { bool code; - unsigned int codeLength = sizeof(code); + socklen_t codeLength = sizeof(code); if (getsockopt(handle, SOL_SOCKET, SO_BROADCAST, &code, &codeLength) == SOCKET_ERROR) { @@ -296,7 +296,7 @@ namespace Nz bool SocketImpl::QueryKeepAlive(SocketHandle handle, SocketError* error) { bool code; - unsigned int codeLength = sizeof(code); + socklen_t codeLength = sizeof(code); if (getsockopt(handle, SOL_SOCKET, SO_KEEPALIVE, &code, &codeLength) == SOCKET_ERROR) { @@ -315,14 +315,14 @@ namespace Nz std::size_t SocketImpl::QueryMaxDatagramSize(SocketHandle handle, SocketError* error) { unsigned int code; - unsigned int codeLength = sizeof(code); + socklen_t codeLength = sizeof(code); if (getsockopt(handle, IPPROTO_IP, IP_MTU, &code, &codeLength) == SOCKET_ERROR) { if (error) *error = TranslateErrnoToResolveError(GetLastErrorCode()); - return -1; + return 0; } if (error) @@ -334,7 +334,7 @@ namespace Nz bool SocketImpl::QueryNoDelay(SocketHandle handle, SocketError* error) { bool code; - unsigned int codeLength = sizeof(code); + socklen_t codeLength = sizeof(code); if (getsockopt(handle, IPPROTO_TCP, TCP_NODELAY, &code, &codeLength) == SOCKET_ERROR) { @@ -350,6 +350,25 @@ namespace Nz return code; } + std::size_t SocketImpl::QueryReceiveBufferSize(SocketHandle handle, SocketError* error) + { + unsigned int code; + socklen_t codeLength = sizeof(code); + + if (getsockopt(handle, SOL_SOCKET, SO_RCVBUF, reinterpret_cast(&code), &codeLength) == SOCKET_ERROR) + { + if (error) + *error = TranslateErrnoToResolveError(GetLastErrorCode()); + + return 0; + } + + if (error) + *error = SocketError_NoError; + + return code; + } + IpAddress SocketImpl::QueryPeerAddress(SocketHandle handle, SocketError* error) { NazaraAssert(handle != InvalidHandle, "Invalid handle"); @@ -371,6 +390,25 @@ namespace Nz return IpAddressImpl::FromSockAddr(reinterpret_cast(nameBuffer.data())); } + std::size_t SocketImpl::QuerySendBufferSize(SocketHandle handle, SocketError* error) + { + unsigned int code; + socklen_t codeLength = sizeof(code); + + if (getsockopt(handle, SOL_SOCKET, SO_SNDBUF, reinterpret_cast(&code), &codeLength) == SOCKET_ERROR) + { + if (error) + *error = TranslateErrnoToResolveError(GetLastErrorCode()); + + return 0; + } + + if (error) + *error = SocketError_NoError; + + return code; + } + IpAddress SocketImpl::QuerySocketAddress(SocketHandle handle, SocketError* error) { NazaraAssert(handle != InvalidHandle, "Invalid handle"); @@ -659,6 +697,44 @@ namespace Nz return true; } + bool SocketImpl::SetReceiveBufferSize(SocketHandle handle, std::size_t size, SocketError* error) + { + NazaraAssert(handle != InvalidHandle, "Invalid handle"); + + int option = static_cast(size); + if (setsockopt(handle, SOL_SOCKET, SO_RCVBUF, reinterpret_cast(&option), sizeof(option)) == SOCKET_ERROR) + { + if (error) + *error = TranslateErrnoToResolveError(GetLastErrorCode()); + + return false; //< Error + } + + if (error) + *error = SocketError_NoError; + + return true; + } + + bool SocketImpl::SetSendBufferSize(SocketHandle handle, std::size_t size, SocketError* error) + { + NazaraAssert(handle != InvalidHandle, "Invalid handle"); + + int option = static_cast(size); + if (setsockopt(handle, SOL_SOCKET, SO_SNDBUF, reinterpret_cast(&option), sizeof(option)) == SOCKET_ERROR) + { + if (error) + *error = TranslateErrnoToResolveError(GetLastErrorCode()); + + return false; //< Error + } + + if (error) + *error = SocketError_NoError; + + return true; + } + SocketError SocketImpl::TranslateErrnoToResolveError(int error) { switch (error) diff --git a/src/Nazara/Network/Posix/SocketImpl.hpp b/src/Nazara/Network/Posix/SocketImpl.hpp index c120bd19a..a543d8880 100644 --- a/src/Nazara/Network/Posix/SocketImpl.hpp +++ b/src/Nazara/Network/Posix/SocketImpl.hpp @@ -55,6 +55,8 @@ namespace Nz static bool QueryNoDelay(SocketHandle handle, SocketError* error = nullptr); static IpAddress QueryPeerAddress(SocketHandle handle, SocketError* error = nullptr); static IpAddress QuerySocketAddress(SocketHandle handle, SocketError* error = nullptr); + static std::size_t QueryReceiveBufferSize(SocketHandle handle, SocketError* error = nullptr); + static std::size_t QuerySendBufferSize(SocketHandle handle, SocketError* error = nullptr); static int Poll(PollSocket* fdarray, std::size_t nfds, int timeout, SocketError* error); @@ -68,6 +70,8 @@ namespace Nz static bool SetBroadcasting(SocketHandle handle, bool broadcasting, SocketError* error = nullptr); static bool SetKeepAlive(SocketHandle handle, bool enabled, UInt64 msTime, UInt64 msInterval, SocketError* error = nullptr); static bool SetNoDelay(SocketHandle handle, bool nodelay, SocketError* error = nullptr); + static bool SetReceiveBufferSize(SocketHandle handle, std::size_t size, SocketError* error = nullptr); + static bool SetSendBufferSize(SocketHandle handle, std::size_t size, SocketError* error = nullptr); static SocketError TranslateErrnoToResolveError(int error); static int TranslateNetProtocolToAF(NetProtocol protocol); diff --git a/src/Nazara/Network/Win32/SocketImpl.cpp b/src/Nazara/Network/Win32/SocketImpl.cpp index 9606da500..74550fe37 100644 --- a/src/Nazara/Network/Win32/SocketImpl.cpp +++ b/src/Nazara/Network/Win32/SocketImpl.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2017 Jérôme Leclercq +// Copyright (C) 2017 Jérôme Leclercq // This file is part of the "Nazara Engine - Network module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -331,7 +331,7 @@ namespace Nz std::size_t SocketImpl::QueryMaxDatagramSize(SocketHandle handle, SocketError* error) { - unsigned int code; + DWORD code; int codeLength = sizeof(code); if (getsockopt(handle, SOL_SOCKET, SO_MAX_MSG_SIZE, reinterpret_cast(&code), &codeLength) == SOCKET_ERROR) @@ -339,7 +339,7 @@ namespace Nz if (error) *error = TranslateWSAErrorToSocketError(WSAGetLastError()); - return -1; + return 0; } if (error) @@ -367,6 +367,25 @@ namespace Nz return code == TRUE; } + std::size_t SocketImpl::QueryReceiveBufferSize(SocketHandle handle, SocketError* error) + { + DWORD code; + int codeLength = sizeof(code); + + if (getsockopt(handle, SOL_SOCKET, SO_RCVBUF, reinterpret_cast(&code), &codeLength) == SOCKET_ERROR) + { + if (error) + *error = TranslateWSAErrorToSocketError(WSAGetLastError()); + + return 0; + } + + if (error) + *error = SocketError_NoError; + + return code; + } + IpAddress SocketImpl::QueryPeerAddress(SocketHandle handle, SocketError* error) { NazaraAssert(handle != InvalidHandle, "Invalid handle"); @@ -415,6 +434,25 @@ namespace Nz return IpAddressImpl::FromSockAddr(reinterpret_cast(nameBuffer.data())); } + std::size_t SocketImpl::QuerySendBufferSize(SocketHandle handle, SocketError* error) + { + DWORD code; + int codeLength = sizeof(code); + + if (getsockopt(handle, SOL_SOCKET, SO_SNDBUF, reinterpret_cast(&code), &codeLength) == SOCKET_ERROR) + { + if (error) + *error = TranslateWSAErrorToSocketError(WSAGetLastError()); + + return 0; + } + + if (error) + *error = SocketError_NoError; + + return code; + } + int SocketImpl::Poll(PollSocket* fdarray, std::size_t nfds, int timeout, SocketError* error) { NazaraAssert(fdarray && nfds > 0, "Invalid fdarray"); @@ -677,6 +715,44 @@ namespace Nz return true; } + bool SocketImpl::SetReceiveBufferSize(SocketHandle handle, std::size_t size, SocketError* error) + { + NazaraAssert(handle != InvalidHandle, "Invalid handle"); + + DWORD option = size; + if (setsockopt(handle, SOL_SOCKET, SO_RCVBUF, reinterpret_cast(&option), sizeof(option)) == SOCKET_ERROR) + { + if (error) + *error = TranslateWSAErrorToSocketError(WSAGetLastError()); + + return false; //< Error + } + + if (error) + *error = SocketError_NoError; + + return true; + } + + bool SocketImpl::SetSendBufferSize(SocketHandle handle, std::size_t size, SocketError* error) + { + NazaraAssert(handle != InvalidHandle, "Invalid handle"); + + DWORD option = size; + if (setsockopt(handle, SOL_SOCKET, SO_SNDBUF, reinterpret_cast(&option), sizeof(option)) == SOCKET_ERROR) + { + if (error) + *error = TranslateWSAErrorToSocketError(WSAGetLastError()); + + return false; //< Error + } + + if (error) + *error = SocketError_NoError; + + return true; + } + SocketError SocketImpl::TranslateWSAErrorToSocketError(int error) { switch (error) diff --git a/src/Nazara/Network/Win32/SocketImpl.hpp b/src/Nazara/Network/Win32/SocketImpl.hpp index f7c278a41..5af2b2534 100644 --- a/src/Nazara/Network/Win32/SocketImpl.hpp +++ b/src/Nazara/Network/Win32/SocketImpl.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2017 Jérôme Leclercq +// Copyright (C) 2017 Jérôme Leclercq // This file is part of the "Nazara Engine - Network module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -54,8 +54,10 @@ namespace Nz static bool QueryKeepAlive(SocketHandle handle, SocketError* error = nullptr); static std::size_t QueryMaxDatagramSize(SocketHandle handle, SocketError* error = nullptr); static bool QueryNoDelay(SocketHandle handle, SocketError* error = nullptr); + static std::size_t QueryReceiveBufferSize(SocketHandle handle, SocketError* error = nullptr); static IpAddress QueryPeerAddress(SocketHandle handle, SocketError* error = nullptr); static IpAddress QuerySocketAddress(SocketHandle handle, SocketError* error = nullptr); + static std::size_t QuerySendBufferSize(SocketHandle handle, SocketError* error = nullptr); static int Poll(PollSocket* fdarray, std::size_t nfds, int timeout, SocketError* error); @@ -69,6 +71,8 @@ namespace Nz static bool SetBroadcasting(SocketHandle handle, bool broadcasting, SocketError* error = nullptr); static bool SetKeepAlive(SocketHandle handle, bool enabled, UInt64 msTime, UInt64 msInterval, SocketError* error = nullptr); static bool SetNoDelay(SocketHandle handle, bool nodelay, SocketError* error = nullptr); + static bool SetReceiveBufferSize(SocketHandle handle, std::size_t size, SocketError* error = nullptr); + static bool SetSendBufferSize(SocketHandle handle, std::size_t size, SocketError* error = nullptr); static SocketError TranslateWSAErrorToSocketError(int error); static int TranslateNetProtocolToAF(NetProtocol protocol);