|
|
@@ -62,17 +62,25 @@ namespace SocketHelpers |
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool resetSocketOptions (const SocketHandle handle, const bool isDatagram, const bool allowBroadcast) noexcept
|
|
|
|
template <typename Type>
|
|
|
|
static bool setOption (const SocketHandle handle, int mode, int property, Type value) noexcept
|
|
|
|
{
|
|
|
|
return setsockopt (handle, mode, property, reinterpret_cast<const char*> (&value), sizeof (value)) == 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename Type>
|
|
|
|
static bool setOption (const SocketHandle handle, int property, Type value) noexcept
|
|
|
|
{
|
|
|
|
const int sndBufSize = 65536;
|
|
|
|
const int rcvBufSize = 65536;
|
|
|
|
const int one = 1;
|
|
|
|
return setOption (handle, SOL_SOCKET, property, value);
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool resetSocketOptions (const SocketHandle handle, const bool isDatagram, const bool allowBroadcast) noexcept
|
|
|
|
{
|
|
|
|
return handle > 0
|
|
|
|
&& setsockopt (handle, SOL_SOCKET, SO_RCVBUF, (const char*) &rcvBufSize, sizeof (rcvBufSize)) == 0
|
|
|
|
&& setsockopt (handle, SOL_SOCKET, SO_SNDBUF, (const char*) &sndBufSize, sizeof (sndBufSize)) == 0
|
|
|
|
&& (isDatagram ? ((! allowBroadcast) || setsockopt (handle, SOL_SOCKET, SO_BROADCAST, (const char*) &one, sizeof (one)) == 0)
|
|
|
|
: (setsockopt (handle, IPPROTO_TCP, TCP_NODELAY, (const char*) &one, sizeof (one)) == 0));
|
|
|
|
&& setOption (handle, SO_RCVBUF, (int) 65536)
|
|
|
|
&& setOption (handle, SO_SNDBUF, (int) 65536)
|
|
|
|
&& (isDatagram ? ((! allowBroadcast) || setOption (handle, SO_BROADCAST, (int) 1))
|
|
|
|
: setOption (handle, IPPROTO_TCP, TCP_NODELAY, (int) 1));
|
|
|
|
}
|
|
|
|
|
|
|
|
static void closeSocket (volatile int& handle, CriticalSection& readLock,
|
|
|
@@ -308,8 +316,7 @@ namespace SocketHelpers |
|
|
|
hints.ai_flags = AI_NUMERICSERV;
|
|
|
|
|
|
|
|
struct addrinfo* info = nullptr;
|
|
|
|
if (getaddrinfo (hostName.toUTF8(), String (portNumber).toUTF8(), &hints, &info) == 0
|
|
|
|
&& info != nullptr)
|
|
|
|
if (getaddrinfo (hostName.toUTF8(), String (portNumber).toUTF8(), &hints, &info) == 0)
|
|
|
|
return info;
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
@@ -364,8 +371,7 @@ namespace SocketHelpers |
|
|
|
|
|
|
|
static void makeReusable (int handle) noexcept
|
|
|
|
{
|
|
|
|
const int reuse = 1;
|
|
|
|
setsockopt (handle, SOL_SOCKET, SO_REUSEADDR, (const char*) &reuse, sizeof (reuse));
|
|
|
|
setOption (handle, SO_REUSEADDR, (int) 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool multicast (int handle, const String& multicastIPAddress,
|
|
|
@@ -380,9 +386,10 @@ namespace SocketHelpers |
|
|
|
if (interfaceIPAddress.isNotEmpty())
|
|
|
|
mreq.imr_interface.s_addr = inet_addr (interfaceIPAddress.toUTF8());
|
|
|
|
|
|
|
|
int joinCmd = join ? IP_ADD_MEMBERSHIP : IP_DROP_MEMBERSHIP;
|
|
|
|
|
|
|
|
return setsockopt (handle, IPPROTO_IP, joinCmd, (const char*) &mreq, sizeof (mreq)) == 0;
|
|
|
|
return setsockopt (handle, IPPROTO_IP,
|
|
|
|
join ? IP_ADD_MEMBERSHIP
|
|
|
|
: IP_DROP_MEMBERSHIP,
|
|
|
|
(const char*) &mreq, sizeof (mreq)) == 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
@@ -569,6 +576,7 @@ DatagramSocket::DatagramSocket (const bool canBroadcast) |
|
|
|
SocketHelpers::initSockets();
|
|
|
|
|
|
|
|
handle = (int) socket (AF_INET, SOCK_DGRAM, 0);
|
|
|
|
|
|
|
|
if (handle >= 0)
|
|
|
|
{
|
|
|
|
SocketHelpers::resetSocketOptions (handle, true, canBroadcast);
|
|
|
@@ -579,7 +587,7 @@ DatagramSocket::DatagramSocket (const bool canBroadcast) |
|
|
|
DatagramSocket::~DatagramSocket()
|
|
|
|
{
|
|
|
|
if (lastServerAddress != nullptr)
|
|
|
|
freeaddrinfo (static_cast <struct addrinfo*> (lastServerAddress));
|
|
|
|
freeaddrinfo (static_cast<struct addrinfo*> (lastServerAddress));
|
|
|
|
|
|
|
|
shutdown();
|
|
|
|
}
|
|
|
@@ -660,7 +668,7 @@ int DatagramSocket::write (const String& remoteHostname, int remotePortNumber, |
|
|
|
if (handle < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
struct addrinfo*& info = reinterpret_cast <struct addrinfo*&> (lastServerAddress);
|
|
|
|
struct addrinfo*& info = reinterpret_cast<struct addrinfo*&> (lastServerAddress);
|
|
|
|
|
|
|
|
// getaddrinfo can be quite slow so cache the result of the address lookup
|
|
|
|
if (info == nullptr || remoteHostname != lastServerHost || remotePortNumber != lastServerPort)
|
|
|
@@ -698,25 +706,18 @@ bool DatagramSocket::leaveMulticast (const String& multicastIPAddress) |
|
|
|
|
|
|
|
bool DatagramSocket::setEnablePortReuse (bool enabled)
|
|
|
|
{
|
|
|
|
#if JUCE_ANDROID
|
|
|
|
return false;
|
|
|
|
#else
|
|
|
|
const int reuse = enabled ? 1 : 0;
|
|
|
|
|
|
|
|
#if JUCE_WINDOWS
|
|
|
|
// port re-use is implied by addr re-use on windows
|
|
|
|
const int optname = SO_REUSEADDR;
|
|
|
|
#else
|
|
|
|
const int optname = SO_REUSEPORT;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
#if ! JUCE_ANDROID
|
|
|
|
if (handle >= 0)
|
|
|
|
return (setsockopt (handle, SOL_SOCKET, optname,
|
|
|
|
(const char*) &reuse, sizeof (reuse)) == 0);
|
|
|
|
return SocketHelpers::setOption (handle,
|
|
|
|
#if JUCE_WINDOWS || JUCE_LINUX
|
|
|
|
SO_REUSEADDR, // port re-use is implied by addr re-use on these platforms
|
|
|
|
#else
|
|
|
|
SO_REUSEPORT,
|
|
|
|
#endif
|
|
|
|
(int) (enabled ? 1 : 0));
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return false;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
#if JUCE_MSVC
|
|
|
|