|
|
|
@@ -62,76 +62,62 @@ BEGIN_JUCE_NAMESPACE |
|
|
|
#include "../../threads/juce_Thread.h"
|
|
|
|
|
|
|
|
|
|
|
|
//==============================================================================
|
|
|
|
#if JUCE_WIN32
|
|
|
|
static CriticalSection socketInitLock;
|
|
|
|
static int numActiveSockets = 0;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
//==============================================================================
|
|
|
|
Socket::Socket()
|
|
|
|
: portNumber (0),
|
|
|
|
handle (-1),
|
|
|
|
connected (false),
|
|
|
|
isListener (false)
|
|
|
|
typedef int (__stdcall juce_CloseWin32SocketLibCall) (void);
|
|
|
|
juce_CloseWin32SocketLibCall* juce_CloseWin32SocketLib = 0;
|
|
|
|
|
|
|
|
static void initWin32Sockets()
|
|
|
|
{
|
|
|
|
#if JUCE_WIN32
|
|
|
|
const ScopedLock sl (socketInitLock);
|
|
|
|
static CriticalSection lock;
|
|
|
|
const ScopedLock sl (lock);
|
|
|
|
|
|
|
|
if (numActiveSockets++ == 0)
|
|
|
|
if (juce_CloseWin32SocketLib == 0)
|
|
|
|
{
|
|
|
|
WSADATA wsaData;
|
|
|
|
WORD wVersionRequested = MAKEWORD (1, 1);
|
|
|
|
const WORD wVersionRequested = MAKEWORD (1, 1);
|
|
|
|
WSAStartup (wVersionRequested, &wsaData);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
Socket::Socket (const String& hostName_, const int portNumber_, const int handle_)
|
|
|
|
: hostName (hostName_),
|
|
|
|
portNumber (portNumber_),
|
|
|
|
handle (handle_),
|
|
|
|
connected (true),
|
|
|
|
isListener (false)
|
|
|
|
{
|
|
|
|
#if JUCE_WIN32
|
|
|
|
socketInitLock.enter();
|
|
|
|
++numActiveSockets;
|
|
|
|
socketInitLock.exit();
|
|
|
|
#endif
|
|
|
|
|
|
|
|
resetSocketOptions();
|
|
|
|
juce_CloseWin32SocketLib = &WSACleanup;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Socket::~Socket()
|
|
|
|
{
|
|
|
|
close();
|
|
|
|
|
|
|
|
#if JUCE_WIN32
|
|
|
|
const ScopedLock sl (socketInitLock);
|
|
|
|
|
|
|
|
if (--numActiveSockets == 0)
|
|
|
|
WSACleanup();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
//==============================================================================
|
|
|
|
bool Socket::resetSocketOptions()
|
|
|
|
static bool resetSocketOptions (const int handle, const bool isDatagram) throw()
|
|
|
|
{
|
|
|
|
if (handle <= 0)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
const int sndBufSize = 65536;
|
|
|
|
const int rcvBufSize = 65536;
|
|
|
|
const int one = 1;
|
|
|
|
|
|
|
|
return setsockopt (handle, SOL_SOCKET, SO_RCVBUF, (const char*) &rcvBufSize, sizeof (int)) == 0
|
|
|
|
&& setsockopt (handle, SOL_SOCKET, SO_SNDBUF, (const char*) &sndBufSize, sizeof (int)) == 0
|
|
|
|
&& setsockopt (handle, IPPROTO_TCP, TCP_NODELAY, (const char*) &one, sizeof (int)) == 0;
|
|
|
|
&& (isDatagram || (setsockopt (handle, IPPROTO_TCP, TCP_NODELAY, (const char*) &one, sizeof (int)) == 0));
|
|
|
|
}
|
|
|
|
|
|
|
|
//==============================================================================
|
|
|
|
int Socket::read (void* destBuffer, const int maxBytesToRead)
|
|
|
|
static bool bindSocketToPort (const int handle, const int port) throw()
|
|
|
|
{
|
|
|
|
if (isListener || ! connected)
|
|
|
|
return -1;
|
|
|
|
if (handle == 0 || port <= 0)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
struct sockaddr_in servTmpAddr;
|
|
|
|
zerostruct (servTmpAddr);
|
|
|
|
servTmpAddr.sin_family = PF_INET;
|
|
|
|
servTmpAddr.sin_addr.s_addr = htonl (INADDR_ANY);
|
|
|
|
servTmpAddr.sin_port = htons ((uint16) port);
|
|
|
|
|
|
|
|
return bind (handle, (struct sockaddr*) &servTmpAddr, sizeof (struct sockaddr_in)) >= 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int readSocket (const int handle,
|
|
|
|
void* const destBuffer, const int maxBytesToRead,
|
|
|
|
bool volatile& connected) throw()
|
|
|
|
{
|
|
|
|
int bytesRead = 0;
|
|
|
|
|
|
|
|
while (bytesRead < maxBytesToRead)
|
|
|
|
@@ -162,31 +148,9 @@ int Socket::read (void* destBuffer, const int maxBytesToRead) |
|
|
|
return bytesRead;
|
|
|
|
}
|
|
|
|
|
|
|
|
int Socket::write (const void* sourceBuffer, int numBytesToWrite)
|
|
|
|
{
|
|
|
|
if (isListener || ! connected)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
#if JUCE_WIN32
|
|
|
|
return send (handle, (const char*) sourceBuffer, numBytesToWrite, 0);
|
|
|
|
#else
|
|
|
|
int result;
|
|
|
|
|
|
|
|
while ((result = ::write (handle, sourceBuffer, numBytesToWrite)) < 0
|
|
|
|
&& errno == EINTR)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
//==============================================================================
|
|
|
|
int Socket::isReady (int timeoutMsecs)
|
|
|
|
static int waitForReadiness (const int handle, const bool forReading,
|
|
|
|
const int timeoutMsecs) throw()
|
|
|
|
{
|
|
|
|
if (! connected)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
struct timeval timeout;
|
|
|
|
struct timeval* timeoutp;
|
|
|
|
|
|
|
|
@@ -201,16 +165,21 @@ int Socket::isReady (int timeoutMsecs) |
|
|
|
timeoutp = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
fd_set readbits;
|
|
|
|
FD_ZERO (&readbits);
|
|
|
|
FD_SET (handle, &readbits);
|
|
|
|
fd_set rset, wset;
|
|
|
|
FD_ZERO (&rset);
|
|
|
|
FD_SET (handle, &rset);
|
|
|
|
FD_ZERO (&wset);
|
|
|
|
FD_SET (handle, &wset);
|
|
|
|
|
|
|
|
fd_set* const prset = forReading ? &rset : 0;
|
|
|
|
fd_set* const pwset = forReading ? 0 : &wset;
|
|
|
|
|
|
|
|
#if JUCE_WIN32
|
|
|
|
if (select (handle + 1, &readbits, 0, 0, timeoutp) < 0)
|
|
|
|
if (select (handle + 1, prset, pwset, 0, timeoutp) < 0)
|
|
|
|
return -1;
|
|
|
|
#else
|
|
|
|
int result;
|
|
|
|
while ((result = select (handle + 1, &readbits, 0, 0, timeoutp)) < 0
|
|
|
|
while ((result = select (handle + 1, prset, pwset, 0, timeoutp)) < 0
|
|
|
|
&& errno == EINTR)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
@@ -219,33 +188,48 @@ int Socket::isReady (int timeoutMsecs) |
|
|
|
return -1;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (FD_ISSET (handle, &readbits))
|
|
|
|
if ((forReading && FD_ISSET (handle, &rset))
|
|
|
|
|| ((! forReading) && FD_ISSET (handle, &wset)))
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
//==============================================================================
|
|
|
|
bool Socket::connect (const String& newHostName,
|
|
|
|
int newPortNumber,
|
|
|
|
int timeOutMillisecs)
|
|
|
|
static bool setSocketBlockingState (const int handle, const bool shouldBlock) throw()
|
|
|
|
{
|
|
|
|
if (isListener)
|
|
|
|
{
|
|
|
|
jassertfalse // a listener socket can't connect to another one!
|
|
|
|
#if JUCE_WIN32
|
|
|
|
u_long nonBlocking = shouldBlock ? 0 : 1;
|
|
|
|
|
|
|
|
if (ioctlsocket (handle, FIONBIO, &nonBlocking) != 0)
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
int socketFlags = fcntl (handle, F_GETFL, 0);
|
|
|
|
|
|
|
|
if (connected)
|
|
|
|
close();
|
|
|
|
if (socketFlags == -1)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
hostName = newHostName;
|
|
|
|
portNumber = newPortNumber;
|
|
|
|
isListener = false;
|
|
|
|
if (shouldBlock)
|
|
|
|
socketFlags &= ~O_NONBLOCK;
|
|
|
|
else
|
|
|
|
socketFlags |= O_NONBLOCK;
|
|
|
|
|
|
|
|
if (fcntl (handle, F_SETFL, socketFlags) != 0)
|
|
|
|
return false;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct hostent* hostEnt = gethostbyname (hostName);
|
|
|
|
static bool connectSocket (int volatile& handle,
|
|
|
|
const bool isDatagram,
|
|
|
|
void** serverAddress,
|
|
|
|
const String& hostName,
|
|
|
|
const int portNumber,
|
|
|
|
const int timeOutMillisecs) throw()
|
|
|
|
{
|
|
|
|
struct hostent* const hostEnt = gethostbyname (hostName);
|
|
|
|
|
|
|
|
if (! hostEnt)
|
|
|
|
if (hostEnt == 0)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
struct in_addr targetAddress;
|
|
|
|
@@ -259,31 +243,136 @@ bool Socket::connect (const String& newHostName, |
|
|
|
servTmpAddr.sin_addr = targetAddress;
|
|
|
|
servTmpAddr.sin_port = htons ((uint16) portNumber);
|
|
|
|
|
|
|
|
handle = (int) socket (AF_INET, SOCK_STREAM, 0);
|
|
|
|
handle = (int) socket (AF_INET, isDatagram ? SOCK_DGRAM : SOCK_STREAM, 0);
|
|
|
|
|
|
|
|
if (handle < 0)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
while (timeOutMillisecs > 0 || timeOutMillisecs < 0)
|
|
|
|
if (isDatagram)
|
|
|
|
{
|
|
|
|
if (handle < 0)
|
|
|
|
return false;
|
|
|
|
*serverAddress = new struct sockaddr_in();
|
|
|
|
*((struct sockaddr_in*) *serverAddress) = servTmpAddr;
|
|
|
|
|
|
|
|
if (::connect (handle, (struct sockaddr*) &servTmpAddr, sizeof (struct sockaddr_in)) >= 0)
|
|
|
|
{
|
|
|
|
connected = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
setSocketBlockingState (handle, false);
|
|
|
|
|
|
|
|
const int result = ::connect (handle, (struct sockaddr*) &servTmpAddr, sizeof (struct sockaddr_in));
|
|
|
|
|
|
|
|
if (timeOutMillisecs > 0)
|
|
|
|
if (result < 0)
|
|
|
|
{
|
|
|
|
#if JUCE_WIN32
|
|
|
|
if (result == SOCKET_ERROR && WSAGetLastError() == WSAEWOULDBLOCK)
|
|
|
|
#else
|
|
|
|
if (result == EINPROGRESS)
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
const int timeToSleep = jmin (timeOutMillisecs, 1000);
|
|
|
|
timeOutMillisecs -= timeToSleep;
|
|
|
|
Thread::sleep (timeToSleep);
|
|
|
|
if (waitForReadiness (handle, false, timeOutMillisecs) != 1)
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
setSocketBlockingState (handle, true);
|
|
|
|
resetSocketOptions (handle, false);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
//==============================================================================
|
|
|
|
StreamingSocket::StreamingSocket()
|
|
|
|
: portNumber (0),
|
|
|
|
handle (-1),
|
|
|
|
connected (false),
|
|
|
|
isListener (false)
|
|
|
|
{
|
|
|
|
#if JUCE_WIN32
|
|
|
|
initWin32Sockets();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
StreamingSocket::StreamingSocket (const String& hostName_,
|
|
|
|
const int portNumber_,
|
|
|
|
const int handle_)
|
|
|
|
: hostName (hostName_),
|
|
|
|
portNumber (portNumber_),
|
|
|
|
handle (handle_),
|
|
|
|
connected (true),
|
|
|
|
isListener (false)
|
|
|
|
{
|
|
|
|
#if JUCE_WIN32
|
|
|
|
initWin32Sockets();
|
|
|
|
#endif
|
|
|
|
|
|
|
|
resetSocketOptions (handle_, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
StreamingSocket::~StreamingSocket()
|
|
|
|
{
|
|
|
|
close();
|
|
|
|
}
|
|
|
|
|
|
|
|
//==============================================================================
|
|
|
|
int StreamingSocket::read (void* destBuffer, const int maxBytesToRead)
|
|
|
|
{
|
|
|
|
return (connected && ! isListener) ? readSocket (handle, destBuffer, maxBytesToRead, connected)
|
|
|
|
: -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int StreamingSocket::write (const void* sourceBuffer, const int numBytesToWrite)
|
|
|
|
{
|
|
|
|
if (isListener || ! connected)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
#if JUCE_WIN32
|
|
|
|
return send (handle, (const char*) sourceBuffer, numBytesToWrite, 0);
|
|
|
|
#else
|
|
|
|
int result;
|
|
|
|
|
|
|
|
while ((result = ::write (handle, sourceBuffer, numBytesToWrite)) < 0
|
|
|
|
&& errno == EINTR)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
//==============================================================================
|
|
|
|
int StreamingSocket::waitUntilReady (const bool readyForReading,
|
|
|
|
const int timeoutMsecs) const
|
|
|
|
{
|
|
|
|
return connected ? waitForReadiness (handle, readyForReading, timeoutMsecs)
|
|
|
|
: -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
//==============================================================================
|
|
|
|
bool StreamingSocket::bindToPort (const int port)
|
|
|
|
{
|
|
|
|
return bindSocketToPort (handle, port);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool StreamingSocket::connect (const String& remoteHostName,
|
|
|
|
const int remotePortNumber,
|
|
|
|
const int timeOutMillisecs)
|
|
|
|
{
|
|
|
|
if (isListener)
|
|
|
|
{
|
|
|
|
jassertfalse // a listener socket can't connect to another one!
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (connected)
|
|
|
|
close();
|
|
|
|
|
|
|
|
hostName = remoteHostName;
|
|
|
|
portNumber = remotePortNumber;
|
|
|
|
isListener = false;
|
|
|
|
|
|
|
|
connected = connectSocket (handle, false, 0, remoteHostName,
|
|
|
|
remotePortNumber, timeOutMillisecs);
|
|
|
|
|
|
|
|
if (! (connected && resetSocketOptions()))
|
|
|
|
if (! (connected && resetSocketOptions (handle, false)))
|
|
|
|
{
|
|
|
|
close();
|
|
|
|
return false;
|
|
|
|
@@ -292,10 +381,11 @@ bool Socket::connect (const String& newHostName, |
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Socket::close()
|
|
|
|
void StreamingSocket::close()
|
|
|
|
{
|
|
|
|
#if JUCE_WIN32
|
|
|
|
closesocket (handle);
|
|
|
|
connected = false;
|
|
|
|
#else
|
|
|
|
if (connected)
|
|
|
|
{
|
|
|
|
@@ -304,7 +394,7 @@ void Socket::close() |
|
|
|
if (isListener)
|
|
|
|
{
|
|
|
|
// need to do this to interrupt the accept() function..
|
|
|
|
Socket temp;
|
|
|
|
StreamingSocket temp;
|
|
|
|
temp.connect ("localhost", portNumber, 1000);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@@ -315,12 +405,11 @@ void Socket::close() |
|
|
|
hostName = String::empty;
|
|
|
|
portNumber = 0;
|
|
|
|
handle = -1;
|
|
|
|
connected = false;
|
|
|
|
isListener = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
//==============================================================================
|
|
|
|
bool Socket::createListener (int newPortNumber)
|
|
|
|
bool StreamingSocket::createListener (const int newPortNumber)
|
|
|
|
{
|
|
|
|
if (connected)
|
|
|
|
close();
|
|
|
|
@@ -354,7 +443,7 @@ bool Socket::createListener (int newPortNumber) |
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
Socket* Socket::waitForNextConnection()
|
|
|
|
StreamingSocket* StreamingSocket::waitForNextConnection() const
|
|
|
|
{
|
|
|
|
jassert (isListener || ! connected); // to call this method, you first have to use createListener() to
|
|
|
|
// prepare this socket as a listener.
|
|
|
|
@@ -371,15 +460,153 @@ Socket* Socket::waitForNextConnection() |
|
|
|
const int newSocket = (int) accept (handle, &address, &len);
|
|
|
|
|
|
|
|
if (newSocket >= 0 && connected)
|
|
|
|
return new Socket (inet_ntoa (((struct sockaddr_in*) &address)->sin_addr),
|
|
|
|
portNumber, newSocket);
|
|
|
|
return new StreamingSocket (inet_ntoa (((struct sockaddr_in*) &address)->sin_addr),
|
|
|
|
portNumber, newSocket);
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool StreamingSocket::isLocal() const throw()
|
|
|
|
{
|
|
|
|
return hostName == T("127.0.0.1");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//==============================================================================
|
|
|
|
//==============================================================================
|
|
|
|
DatagramSocket::DatagramSocket (const int localPortNumber)
|
|
|
|
: portNumber (0),
|
|
|
|
handle (-1),
|
|
|
|
connected (false),
|
|
|
|
serverAddress (0)
|
|
|
|
{
|
|
|
|
#if JUCE_WIN32
|
|
|
|
initWin32Sockets();
|
|
|
|
#endif
|
|
|
|
|
|
|
|
bindToPort (localPortNumber);
|
|
|
|
}
|
|
|
|
|
|
|
|
DatagramSocket::DatagramSocket (const String& hostName_, const int portNumber_,
|
|
|
|
const int handle_, const int localPortNumber)
|
|
|
|
: hostName (hostName_),
|
|
|
|
portNumber (portNumber_),
|
|
|
|
handle (handle_),
|
|
|
|
connected (true),
|
|
|
|
serverAddress (0)
|
|
|
|
{
|
|
|
|
#if JUCE_WIN32
|
|
|
|
initWin32Sockets();
|
|
|
|
#endif
|
|
|
|
|
|
|
|
resetSocketOptions (handle_, true);
|
|
|
|
bindToPort (localPortNumber);
|
|
|
|
}
|
|
|
|
|
|
|
|
DatagramSocket::~DatagramSocket()
|
|
|
|
{
|
|
|
|
close();
|
|
|
|
|
|
|
|
delete ((struct sockaddr_in*) serverAddress);
|
|
|
|
serverAddress = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void DatagramSocket::close()
|
|
|
|
{
|
|
|
|
#if JUCE_WIN32
|
|
|
|
closesocket (handle);
|
|
|
|
connected = false;
|
|
|
|
#else
|
|
|
|
connected = false;
|
|
|
|
::close (handle);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
hostName = String::empty;
|
|
|
|
portNumber = 0;
|
|
|
|
handle = -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool DatagramSocket::bindToPort (const int port)
|
|
|
|
{
|
|
|
|
return bindSocketToPort (handle, port);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool DatagramSocket::connect (const String& remoteHostName,
|
|
|
|
const int remotePortNumber,
|
|
|
|
const int timeOutMillisecs)
|
|
|
|
{
|
|
|
|
if (connected)
|
|
|
|
close();
|
|
|
|
|
|
|
|
hostName = remoteHostName;
|
|
|
|
portNumber = remotePortNumber;
|
|
|
|
|
|
|
|
connected = connectSocket (handle, true, &serverAddress,
|
|
|
|
remoteHostName, remotePortNumber,
|
|
|
|
timeOutMillisecs);
|
|
|
|
|
|
|
|
if (! (connected && resetSocketOptions (handle, true)))
|
|
|
|
{
|
|
|
|
close();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
DatagramSocket* DatagramSocket::waitForNextConnection() const
|
|
|
|
{
|
|
|
|
struct sockaddr address;
|
|
|
|
|
|
|
|
#if defined (JUCE_LINUX) || (defined (JUCE_MAC) && ! MACOS_10_2_OR_EARLIER)
|
|
|
|
socklen_t len = sizeof (sockaddr);
|
|
|
|
#else
|
|
|
|
int len = sizeof (sockaddr);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
while (waitUntilReady (true, -1) == 1)
|
|
|
|
{
|
|
|
|
char buf[1];
|
|
|
|
|
|
|
|
if (recvfrom (handle, buf, 0, 0, &address, &len) > 0)
|
|
|
|
{
|
|
|
|
return new DatagramSocket (inet_ntoa (((struct sockaddr_in*) &address)->sin_addr),
|
|
|
|
ntohs (((struct sockaddr_in*) &address)->sin_port),
|
|
|
|
-1, -1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
//==============================================================================
|
|
|
|
bool Socket::isLocal() const throw()
|
|
|
|
int DatagramSocket::waitUntilReady (const bool readyForReading,
|
|
|
|
const int timeoutMsecs) const
|
|
|
|
{
|
|
|
|
return connected ? waitForReadiness (handle, readyForReading, timeoutMsecs)
|
|
|
|
: -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int DatagramSocket::read (void* destBuffer, const int maxBytesToRead)
|
|
|
|
{
|
|
|
|
return connected ? readSocket (handle, destBuffer, maxBytesToRead, connected)
|
|
|
|
: -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int DatagramSocket::write (const void* sourceBuffer, const int numBytesToWrite)
|
|
|
|
{
|
|
|
|
// You need to call connect() first to set the server address..
|
|
|
|
jassert (serverAddress != 0 && connected);
|
|
|
|
|
|
|
|
return connected ? sendto (handle, (const char*) sourceBuffer,
|
|
|
|
numBytesToWrite, 0,
|
|
|
|
(const struct sockaddr*) serverAddress,
|
|
|
|
sizeof (struct sockaddr_in))
|
|
|
|
: -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool DatagramSocket::isLocal() const throw()
|
|
|
|
{
|
|
|
|
return hostName == T("127.0.0.1");
|
|
|
|
}
|
|
|
|
|