Network: Add support for dual-stack sockets
This commit is contained in:
parent
600bfc3ee6
commit
715729fc02
|
|
@ -77,6 +77,7 @@ Nazara Engine:
|
||||||
- ⚠️ Added a type tag parameter to Serialize and Unserialize functions, to prevent implicit conversions with overloads
|
- ⚠️ Added a type tag parameter to Serialize and Unserialize functions, to prevent implicit conversions with overloads
|
||||||
- Added Collider3D::ForEachPolygon method, allowing construction of a debug mesh based on the physics collider
|
- Added Collider3D::ForEachPolygon method, allowing construction of a debug mesh based on the physics collider
|
||||||
- Fixed ConvexCollider3D::GetType returning Compound instead of ConvexHull.
|
- Fixed ConvexCollider3D::GetType returning Compound instead of ConvexHull.
|
||||||
|
- Dual-stack sockets are now supported (by using NetProtocol_Any at creation/opening)
|
||||||
|
|
||||||
Nazara Development Kit:
|
Nazara Development Kit:
|
||||||
- Added ImageWidget (#139)
|
- Added ImageWidget (#139)
|
||||||
|
|
|
||||||
|
|
@ -156,6 +156,7 @@ namespace Nz
|
||||||
UInt64 m_totalReceivedData;
|
UInt64 m_totalReceivedData;
|
||||||
bool m_allowsIncomingConnections;
|
bool m_allowsIncomingConnections;
|
||||||
bool m_continueSending;
|
bool m_continueSending;
|
||||||
|
bool m_isUsingDualStack;
|
||||||
bool m_isSimulationEnabled;
|
bool m_isSimulationEnabled;
|
||||||
bool m_recalculateBandwidthLimits;
|
bool m_recalculateBandwidthLimits;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ namespace Nz
|
||||||
{
|
{
|
||||||
inline ENetHost::ENetHost() :
|
inline ENetHost::ENetHost() :
|
||||||
m_packetPool(sizeof(ENetPacket)),
|
m_packetPool(sizeof(ENetPacket)),
|
||||||
|
m_isUsingDualStack(false),
|
||||||
m_isSimulationEnabled(false)
|
m_isSimulationEnabled(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
@ -20,21 +21,22 @@ namespace Nz
|
||||||
|
|
||||||
inline bool ENetHost::Create(NetProtocol protocol, UInt16 port, std::size_t peerCount, std::size_t channelCount)
|
inline bool ENetHost::Create(NetProtocol protocol, UInt16 port, std::size_t peerCount, std::size_t channelCount)
|
||||||
{
|
{
|
||||||
NazaraAssert(protocol != NetProtocol_Any, "Any protocol not supported for Listen"); //< TODO
|
|
||||||
NazaraAssert(protocol != NetProtocol_Unknown, "Invalid protocol");
|
NazaraAssert(protocol != NetProtocol_Unknown, "Invalid protocol");
|
||||||
|
|
||||||
IpAddress any;
|
IpAddress any;
|
||||||
switch (protocol)
|
switch (protocol)
|
||||||
{
|
{
|
||||||
case NetProtocol_Any:
|
|
||||||
case NetProtocol_Unknown:
|
case NetProtocol_Unknown:
|
||||||
NazaraInternalError("Invalid protocol Any at this point");
|
NazaraInternalError("Invalid protocol");
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
case NetProtocol_IPv4:
|
case NetProtocol_IPv4:
|
||||||
any = IpAddress::AnyIpV4;
|
any = IpAddress::AnyIpV4;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case NetProtocol_Any:
|
||||||
|
m_isUsingDualStack = true;
|
||||||
|
// fallthrough
|
||||||
case NetProtocol_IPv6:
|
case NetProtocol_IPv6:
|
||||||
any = IpAddress::AnyIpV6;
|
any = IpAddress::AnyIpV6;
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -51,15 +51,15 @@ namespace Nz
|
||||||
IpAddress any;
|
IpAddress any;
|
||||||
switch (m_protocol)
|
switch (m_protocol)
|
||||||
{
|
{
|
||||||
case NetProtocol_Any:
|
|
||||||
case NetProtocol_Unknown:
|
case NetProtocol_Unknown:
|
||||||
NazaraInternalError("Invalid protocol Any at this point");
|
NazaraInternalError("Invalid protocol");
|
||||||
return SocketState_NotConnected;
|
return SocketState_NotConnected;
|
||||||
|
|
||||||
case NetProtocol_IPv4:
|
case NetProtocol_IPv4:
|
||||||
any = IpAddress::AnyIpV4;
|
any = IpAddress::AnyIpV4;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case NetProtocol_Any:
|
||||||
case NetProtocol_IPv6:
|
case NetProtocol_IPv6:
|
||||||
any = IpAddress::AnyIpV6;
|
any = IpAddress::AnyIpV6;
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
#include <Nazara/Network/AbstractSocket.hpp>
|
#include <Nazara/Network/AbstractSocket.hpp>
|
||||||
#include <Nazara/Core/Error.hpp>
|
#include <Nazara/Core/Error.hpp>
|
||||||
#include <Nazara/Network/Debug.hpp>
|
#include <Nazara/Network/Algorithm.hpp>
|
||||||
|
|
||||||
#if defined(NAZARA_PLATFORM_WINDOWS)
|
#if defined(NAZARA_PLATFORM_WINDOWS)
|
||||||
#include <Nazara/Network/Win32/SocketImpl.hpp>
|
#include <Nazara/Network/Win32/SocketImpl.hpp>
|
||||||
|
|
@ -14,6 +14,8 @@
|
||||||
#error Missing implementation: Socket
|
#error Missing implementation: Socket
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <Nazara/Network/Debug.hpp>
|
||||||
|
|
||||||
namespace Nz
|
namespace Nz
|
||||||
{
|
{
|
||||||
/*!
|
/*!
|
||||||
|
|
@ -187,10 +189,21 @@ namespace Nz
|
||||||
{
|
{
|
||||||
if (m_handle == SocketImpl::InvalidHandle || m_protocol != protocol)
|
if (m_handle == SocketImpl::InvalidHandle || m_protocol != protocol)
|
||||||
{
|
{
|
||||||
SocketHandle handle = SocketImpl::Create(protocol, m_type, &m_lastError);
|
SocketHandle handle = SocketImpl::Create((protocol == NetProtocol_Any) ? NetProtocol_IPv6 : protocol, m_type, &m_lastError);
|
||||||
if (handle == SocketImpl::InvalidHandle)
|
if (handle == SocketImpl::InvalidHandle)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
if (protocol == NetProtocol_Any)
|
||||||
|
{
|
||||||
|
if (!SocketImpl::SetIPv6Only(handle, false, &m_lastError))
|
||||||
|
{
|
||||||
|
SocketImpl::Close(handle);
|
||||||
|
|
||||||
|
NazaraError("Failed to open a dual-stack socket: " + Nz::String(ErrorToString(m_lastError)));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
m_protocol = protocol;
|
m_protocol = protocol;
|
||||||
Open(handle);
|
Open(handle);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -320,7 +320,7 @@ namespace Nz
|
||||||
|
|
||||||
bool ENetHost::InitSocket(const IpAddress& address)
|
bool ENetHost::InitSocket(const IpAddress& address)
|
||||||
{
|
{
|
||||||
if (!m_socket.Create(address.GetProtocol()))
|
if (!m_socket.Create((m_isUsingDualStack) ? NetProtocol_Any : address.GetProtocol()))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
m_socket.EnableBlocking(false);
|
m_socket.EnableBlocking(false);
|
||||||
|
|
|
||||||
|
|
@ -809,8 +809,27 @@ namespace Nz
|
||||||
{
|
{
|
||||||
NazaraAssert(handle != InvalidHandle, "Invalid handle");
|
NazaraAssert(handle != InvalidHandle, "Invalid handle");
|
||||||
|
|
||||||
bool option = broadcasting;
|
int option = broadcasting;
|
||||||
if (setsockopt(handle, SOL_SOCKET, SO_BROADCAST, reinterpret_cast<const char*>(&option), sizeof(option)) == SOCKET_ERROR)
|
if (setsockopt(handle, IPPROTO_IPV6, SO_BROADCAST, reinterpret_cast<const char*>(&option), sizeof(option)) == SOCKET_ERROR)
|
||||||
|
{
|
||||||
|
if (error)
|
||||||
|
*error = TranslateErrnoToResolveError(GetLastErrorCode());
|
||||||
|
|
||||||
|
return false; //< Error
|
||||||
|
}
|
||||||
|
|
||||||
|
if (error)
|
||||||
|
*error = SocketError_NoError;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SocketImpl::SetIPv6Only(SocketHandle handle, bool ipv6Only, SocketError* error)
|
||||||
|
{
|
||||||
|
NazaraAssert(handle != InvalidHandle, "Invalid handle");
|
||||||
|
|
||||||
|
int option = broadcasting;
|
||||||
|
if (setsockopt(handle, SOL_SOCKET, IPV6_V6ONLY, reinterpret_cast<const char*>(&option), sizeof(option)) == SOCKET_ERROR)
|
||||||
{
|
{
|
||||||
if (error)
|
if (error)
|
||||||
*error = TranslateErrnoToResolveError(GetLastErrorCode());
|
*error = TranslateErrnoToResolveError(GetLastErrorCode());
|
||||||
|
|
|
||||||
|
|
@ -72,6 +72,7 @@ namespace Nz
|
||||||
|
|
||||||
static bool SetBlocking(SocketHandle handle, bool blocking, SocketError* error = nullptr);
|
static bool SetBlocking(SocketHandle handle, bool blocking, SocketError* error = nullptr);
|
||||||
static bool SetBroadcasting(SocketHandle handle, bool broadcasting, SocketError* error = nullptr);
|
static bool SetBroadcasting(SocketHandle handle, bool broadcasting, SocketError* error = nullptr);
|
||||||
|
static bool SetIPv6Only(SocketHandle handle, bool ipv6only, SocketError* error = nullptr);
|
||||||
static bool SetKeepAlive(SocketHandle handle, bool enabled, UInt64 msTime, UInt64 msInterval, 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 SetNoDelay(SocketHandle handle, bool nodelay, SocketError* error = nullptr);
|
||||||
static bool SetReceiveBufferSize(SocketHandle handle, std::size_t size, SocketError* error = nullptr);
|
static bool SetReceiveBufferSize(SocketHandle handle, std::size_t size, SocketError* error = nullptr);
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright (C) 2017 Jérôme Leclercq
|
// Copyright (C) 2018 Jérôme Leclercq
|
||||||
// This file is part of the "Nazara Engine - Network module"
|
// This file is part of the "Nazara Engine - Network module"
|
||||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||||
|
|
||||||
|
|
@ -827,6 +827,32 @@ namespace Nz
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SocketImpl::SetIPv6Only(SocketHandle handle, bool ipv6Only, SocketError* error)
|
||||||
|
{
|
||||||
|
#if NAZARA_CORE_WINDOWS_NT6
|
||||||
|
NazaraAssert(handle != InvalidHandle, "Invalid handle");
|
||||||
|
|
||||||
|
DWORD option = ipv6Only;
|
||||||
|
if (setsockopt(handle, IPPROTO_IPV6, IPV6_V6ONLY, reinterpret_cast<const char*>(&option), sizeof(option)) == SOCKET_ERROR)
|
||||||
|
{
|
||||||
|
if (error)
|
||||||
|
*error = TranslateWSAErrorToSocketError(WSAGetLastError());
|
||||||
|
|
||||||
|
return false; //< Error
|
||||||
|
}
|
||||||
|
|
||||||
|
if (error)
|
||||||
|
*error = SocketError_NoError;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
#else
|
||||||
|
if (error)
|
||||||
|
*error = SocketError_NotSupported;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
bool SocketImpl::SetKeepAlive(SocketHandle handle, bool enabled, UInt64 msTime, UInt64 msInterval, SocketError* error)
|
bool SocketImpl::SetKeepAlive(SocketHandle handle, bool enabled, UInt64 msTime, UInt64 msInterval, SocketError* error)
|
||||||
{
|
{
|
||||||
NazaraAssert(handle != InvalidHandle, "Invalid handle");
|
NazaraAssert(handle != InvalidHandle, "Invalid handle");
|
||||||
|
|
|
||||||
|
|
@ -72,6 +72,7 @@ namespace Nz
|
||||||
|
|
||||||
static bool SetBlocking(SocketHandle handle, bool blocking, SocketError* error = nullptr);
|
static bool SetBlocking(SocketHandle handle, bool blocking, SocketError* error = nullptr);
|
||||||
static bool SetBroadcasting(SocketHandle handle, bool broadcasting, SocketError* error = nullptr);
|
static bool SetBroadcasting(SocketHandle handle, bool broadcasting, SocketError* error = nullptr);
|
||||||
|
static bool SetIPv6Only(SocketHandle handle, bool ipv6Only, SocketError* error = nullptr);
|
||||||
static bool SetKeepAlive(SocketHandle handle, bool enabled, UInt64 msTime, UInt64 msInterval, 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 SetNoDelay(SocketHandle handle, bool nodelay, SocketError* error = nullptr);
|
||||||
static bool SetReceiveBufferSize(SocketHandle handle, std::size_t size, SocketError* error = nullptr);
|
static bool SetReceiveBufferSize(SocketHandle handle, std::size_t size, SocketError* error = nullptr);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue