22#ifdef JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED
23 #include <juce_core/juce_core.h>
24 #include <juce_events/juce_events.h>
26 #include <JuceHeader.h>
49 template <
typename Fn>
52 const juce::ScopedLock lock(mutex);
60 const juce::ScopedLock lock(mutex);
66 const juce::ScopedLock lock(mutex);
71 juce::CriticalSection mutex;
83 : useMessageThread(callbacksOnMessageThread),
84 safeAction(std::make_shared<
SafeAction>(*this)), m_threadPriority(threadPriority)
96 jassert(!safeAction->isSafe());
98 callbackConnectionState =
false;
105 int portNumber,
int timeOutMillisecs)
109 auto s = std::make_unique<juce::StreamingSocket>();
111 if (s->connect(hostName, portNumber, timeOutMillisecs))
113 const juce::ScopedWriteLock sl(socketLock);
114 initialiseWithSocket(std::move(s));
125 thread->stopThread(timeoutMs);
128 const juce::ScopedReadLock sl(socketLock);
129 if (socket !=
nullptr) socket->close();
137 callbackConnectionState =
false;
138 safeAction->setSafe(
false);
141void Ocp1Connection::deleteSocket()
143 const juce::ScopedWriteLock sl(socketLock);
149 const juce::ScopedReadLock sl(socketLock);
151 return (socket !=
nullptr && socket->isConnected())
158 const juce::ScopedReadLock sl(socketLock);
160 if (socket ==
nullptr)
163 if (socket !=
nullptr && !socket->isLocal())
164 return socket->getHostName();
167 return juce::IPAddress::local().toString();
173 return writeData(
const_cast<std::uint8_t*
>(message.data()),
static_cast<int>(message.size())) ==
static_cast<int>(message.size());
176int Ocp1Connection::writeData(
void* data,
int dataSize)
178 const juce::ScopedReadLock sl(socketLock);
180 if (socket !=
nullptr)
181 return socket->write(data, dataSize);
187void Ocp1Connection::initialise()
189 safeAction->setSafe(
true);
190 threadIsRunning =
true;
192 thread->startThread(m_threadPriority);
195void Ocp1Connection::initialiseWithSocket(std::unique_ptr<juce::StreamingSocket> newSocket)
197 jassert(socket ==
nullptr);
198 socket = std::move(newSocket);
226void Ocp1Connection::connectionMadeInt()
228 if (!callbackConnectionState)
230 callbackConnectionState =
true;
232 if (useMessageThread)
239void Ocp1Connection::connectionLostInt()
241 if (callbackConnectionState)
243 callbackConnectionState =
false;
245 if (useMessageThread)
246 (
new ConnectionStateMessage(safeAction,
false))->post();
270void Ocp1Connection::deliverDataInt(
const ByteVector& data)
272 jassert(callbackConnectionState);
274 if (useMessageThread)
281int Ocp1Connection::readData(
void* data,
int num)
283 const juce::ScopedReadLock sl(socketLock);
285 if (socket !=
nullptr)
286 return socket->read(data, num,
true);
292bool Ocp1Connection::readNextMessage()
301 Ocp1Header tmpHeader(messageData);
305 messageData.resize(
static_cast<size_t>(tmpHeader.GetMessageSize()) + 1);
309 while (bytesLeft > 0)
311 if (thread->threadShouldExit())
314 auto numThisTime = juce::jmin(bytesLeft, 65536);
315 auto bytesIn = readData(messageData.data() + readPosition, numThisTime);
320 readPosition += bytesIn;
321 bytesLeft -= bytesIn;
324 deliverDataInt(messageData);
331 if (socket !=
nullptr)
340void Ocp1Connection::runThread()
342 while (!thread->threadShouldExit())
344 if (socket !=
nullptr)
346 auto ready = socket->waitUntilReady(
true, 100);
366 if (thread->threadShouldExit() || !readNextMessage())
370 threadIsRunning =
false;
Low-level TCP socket manager for a single OCP.1 connection.
virtual ~Ocp1Connection()
virtual void connectionLost()=0
Called when the TCP connection is dropped or closed. Override to react.
Notify
Controls whether connectionLost() is called when disconnect() is invoked. Use Notify::no when shuttin...
bool connectToSocket(const juce::String &hostName, int portNumber, int timeOutMillisecs)
Attempts a TCP connection to the given host and port. Spawns the read thread on success.
void disconnect(int timeoutMs=0, Notify notify=Notify::yes)
Closes the TCP socket and stops the read thread.
juce::String getConnectedHostName() const
Returns the hostname of the currently connected remote peer, or an empty string.
Ocp1Connection(bool callbacksOnMessageThread=true, const juce::Thread::Priority threadPriority=juce::Thread::Priority::normal)
Constructs the connection object.
virtual void messageReceived(const ByteVector &message)=0
Called with each complete OCP.1 frame received from the remote device. Pass message to Ocp1Message::U...
bool isConnected() const
Returns true if the TCP socket is currently open.
virtual void connectionMade()=0
Called when the TCP connection is successfully established. Override to react.
bool sendMessage(const ByteVector &message)
Sends a complete OCP.1 frame over the TCP socket. Acquires the write lock, then writes all bytes in o...
SafeActionImpl(Ocp1Connection &p)
Minimal AES70 / OCP.1 TCP client/server library built on JUCE.
std::vector< std::uint8_t > ByteVector
Binary buffer type used throughout NanoOcp for all serialized OCP.1 data.
ConnectionStateMessage(std::shared_ptr< SafeActionImpl > ipc, bool connected) noexcept
std::shared_ptr< SafeActionImpl > safeAction
void messageCallback() override
DataDeliveryMessage(std::shared_ptr< SafeActionImpl > ipc, const ByteVector &d)
std::shared_ptr< SafeActionImpl > safeAction
void messageCallback() override
ConnectionThread(Ocp1Connection &c)