mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-19 01:04:20 +00:00
DatagramSocket: Added shutdown method to cleanly exit from Datagram Read/Write loop without destroying the object (useful to resolve race conditions).
This commit is contained in:
parent
35424d137f
commit
eafa657f3b
2 changed files with 50 additions and 5 deletions
|
|
@ -569,8 +569,11 @@ DatagramSocket::DatagramSocket (const bool canBroadcast)
|
|||
SocketHelpers::initSockets();
|
||||
|
||||
handle = (int) socket (AF_INET, SOCK_DGRAM, 0);
|
||||
SocketHelpers::resetSocketOptions (handle, true, canBroadcast);
|
||||
SocketHelpers::makeReusable (handle);
|
||||
if (handle >= 0)
|
||||
{
|
||||
SocketHelpers::resetSocketOptions (handle, true, canBroadcast);
|
||||
SocketHelpers::makeReusable (handle);
|
||||
}
|
||||
}
|
||||
|
||||
DatagramSocket::~DatagramSocket()
|
||||
|
|
@ -578,8 +581,18 @@ DatagramSocket::~DatagramSocket()
|
|||
if (lastServerAddress != nullptr)
|
||||
freeaddrinfo (static_cast <struct addrinfo*> (lastServerAddress));
|
||||
|
||||
shutdown();
|
||||
}
|
||||
|
||||
void DatagramSocket::shutdown()
|
||||
{
|
||||
if (handle < 0)
|
||||
return;
|
||||
|
||||
int copyOfHandle = handle;
|
||||
handle = -1;
|
||||
bool connected = false;
|
||||
SocketHelpers::closeSocket (handle, readLock, false, 0, connected);
|
||||
SocketHelpers::closeSocket (copyOfHandle, readLock, false, 0, connected);
|
||||
}
|
||||
|
||||
bool DatagramSocket::bindToPort (const int port)
|
||||
|
|
@ -589,6 +602,9 @@ bool DatagramSocket::bindToPort (const int port)
|
|||
|
||||
bool DatagramSocket::bindToPort (const int port, const String& addr)
|
||||
{
|
||||
if (handle < 0)
|
||||
return false;
|
||||
|
||||
if (SocketHelpers::bindSocket (handle, port, addr))
|
||||
{
|
||||
isBound = true;
|
||||
|
|
@ -602,6 +618,9 @@ bool DatagramSocket::bindToPort (const int port, const String& addr)
|
|||
|
||||
int DatagramSocket::getBoundPort() const noexcept
|
||||
{
|
||||
if (handle < 0)
|
||||
return -1;
|
||||
|
||||
return isBound ? SocketHelpers::getBoundPort (handle) : -1;
|
||||
}
|
||||
|
||||
|
|
@ -609,11 +628,17 @@ int DatagramSocket::getBoundPort() const noexcept
|
|||
int DatagramSocket::waitUntilReady (const bool readyForReading,
|
||||
const int timeoutMsecs) const
|
||||
{
|
||||
if (handle < 0)
|
||||
return -1;
|
||||
|
||||
return SocketHelpers::waitForReadiness (handle, readLock, readyForReading, timeoutMsecs);
|
||||
}
|
||||
|
||||
int DatagramSocket::read (void* destBuffer, int maxBytesToRead, bool shouldBlock)
|
||||
{
|
||||
if (handle < 0)
|
||||
return -1;
|
||||
|
||||
bool connected = true;
|
||||
return isBound ? SocketHelpers::readSocket (handle, destBuffer, maxBytesToRead,
|
||||
connected, shouldBlock, readLock) : -1;
|
||||
|
|
@ -621,6 +646,9 @@ int DatagramSocket::read (void* destBuffer, int maxBytesToRead, bool shouldBlock
|
|||
|
||||
int DatagramSocket::read (void* destBuffer, int maxBytesToRead, bool shouldBlock, String& senderIPAddress, int& senderPort)
|
||||
{
|
||||
if (handle < 0)
|
||||
return -1;
|
||||
|
||||
bool connected = true;
|
||||
return isBound ? SocketHelpers::readSocket (handle, destBuffer, maxBytesToRead, connected,
|
||||
shouldBlock, readLock, &senderIPAddress, &senderPort) : -1;
|
||||
|
|
@ -629,6 +657,9 @@ int DatagramSocket::read (void* destBuffer, int maxBytesToRead, bool shouldBlock
|
|||
int DatagramSocket::write (const String& remoteHostname, int remotePortNumber,
|
||||
const void* sourceBuffer, int numBytesToWrite)
|
||||
{
|
||||
if (handle < 0)
|
||||
return -1;
|
||||
|
||||
struct addrinfo*& info = reinterpret_cast <struct addrinfo*&> (lastServerAddress);
|
||||
|
||||
// getaddrinfo can be quite slow so cache the result of the address lookup
|
||||
|
|
@ -651,7 +682,7 @@ int DatagramSocket::write (const String& remoteHostname, int remotePortNumber,
|
|||
|
||||
bool DatagramSocket::joinMulticast (const String& multicastIPAddress)
|
||||
{
|
||||
if (! isBound)
|
||||
if (! isBound || handle < 0)
|
||||
return false;
|
||||
|
||||
return SocketHelpers::multicast (handle, multicastIPAddress, lastBindAddress, true);
|
||||
|
|
@ -659,7 +690,7 @@ bool DatagramSocket::joinMulticast (const String& multicastIPAddress)
|
|||
|
||||
bool DatagramSocket::leaveMulticast (const String& multicastIPAddress)
|
||||
{
|
||||
if (! isBound)
|
||||
if (! isBound || handle < 0)
|
||||
return false;
|
||||
|
||||
return SocketHelpers::multicast (handle, multicastIPAddress, lastBindAddress, false);
|
||||
|
|
|
|||
|
|
@ -306,6 +306,20 @@ public:
|
|||
int write (const String& remoteHostname, int remotePortNumber,
|
||||
const void* sourceBuffer, int numBytesToWrite);
|
||||
|
||||
/** Closes the underlying socket object.
|
||||
|
||||
Closes the underlying socket object and aborts any read or write operations.
|
||||
Note that all other methods will return an error after this call. This
|
||||
method is useful if another thread is blocking in a read/write call and you
|
||||
woould like to abort the read/write thread. Simply deleting the socket
|
||||
object without calling shutdown may cause a race-condition where the read/write
|
||||
returns just before the socket is deleted and the subsequent read/write would
|
||||
try to read from an invalid pointer. By calling shutdown first, the socket
|
||||
object remains valid but all current and subsequent calls to read/write will
|
||||
return immediately.
|
||||
*/
|
||||
void shutdown();
|
||||
|
||||
//==============================================================================
|
||||
/** Join a multicast group
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue