diff --git a/source/backend/plugin/CarlaPluginLV2.cpp b/source/backend/plugin/CarlaPluginLV2.cpp index 7c8ad9558..689eb5ffd 100644 --- a/source/backend/plugin/CarlaPluginLV2.cpp +++ b/source/backend/plugin/CarlaPluginLV2.cpp @@ -1561,8 +1561,8 @@ public: // manually write messages so we can take the lock for ourselves { - char tmpBuf[0xff+1]; - tmpBuf[0xff] = '\0'; + char tmpBuf[0xff]; + tmpBuf[0xfe] = '\0'; const CarlaMutexLocker cml(fPipeServer.getPipeLock()); const CarlaScopedLocale csl; @@ -1575,12 +1575,17 @@ public: continue; const std::string& uri(*it); - std::snprintf(tmpBuf, 0xff, "%u\n", u); if (! fPipeServer.writeMessage("urid\n", 5)) return; + std::snprintf(tmpBuf, 0xfe, "%u\n", u); if (! fPipeServer.writeMessage(tmpBuf)) return; + + std::snprintf(tmpBuf, 0xfe, "%lu\n", static_cast(uri.length())); + if (! fPipeServer.writeMessage(tmpBuf)) + return; + if (! fPipeServer.writeAndFixMessage(uri.c_str())) return; } @@ -7252,15 +7257,16 @@ bool CarlaPipeServerLV2::msgReceived(const char* const msg) noexcept if (std::strcmp(msg, "atom") == 0) { - uint32_t index, size; + uint32_t index, atomTotalSize, base64Size; const char* base64atom; CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(index), true); - CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(size), true); - CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(base64atom, false), true); + CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(atomTotalSize), true); + CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(base64Size), true); + CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(base64atom, false, base64Size), true); std::vector chunk(carla_getChunkFromBase64String(base64atom)); - CARLA_SAFE_ASSERT_RETURN(chunk.size() >= sizeof(LV2_Atom), true); + CARLA_SAFE_ASSERT_UINT2_RETURN(chunk.size() >= sizeof(LV2_Atom), chunk.size(), sizeof(LV2_Atom), true); #ifdef CARLA_PROPER_CPP11_SUPPORT const LV2_Atom* const atom((const LV2_Atom*)chunk.data()); @@ -7291,11 +7297,12 @@ bool CarlaPipeServerLV2::msgReceived(const char* const msg) noexcept if (std::strcmp(msg, "urid") == 0) { - uint32_t urid; + uint32_t urid, size; const char* uri; CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(urid), true); - CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(uri, false), true); + CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(size), true); + CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(uri, false, size), true); if (urid != 0) { diff --git a/source/backend/utils/PipeClient.cpp b/source/backend/utils/PipeClient.cpp index 619553d86..ce37c811f 100644 --- a/source/backend/utils/PipeClient.cpp +++ b/source/backend/utils/PipeClient.cpp @@ -88,7 +88,7 @@ public: #endif delete[] fLastReadLine; - fLastReadLine = CarlaPipeClient::_readlineblock(true, timeout); + fLastReadLine = CarlaPipeClient::_readlineblock(true, 0, timeout); return fLastReadLine; } @@ -103,7 +103,7 @@ public: } #endif - if (const char* const line = CarlaPipeClient::_readlineblock(false, timeout)) + if (const char* const line = CarlaPipeClient::_readlineblock(false, 0, timeout)) return std::strcmp(line, "true") == 0; return false; @@ -120,7 +120,7 @@ public: } #endif - if (const char* const line = CarlaPipeClient::_readlineblock(false, timeout)) + if (const char* const line = CarlaPipeClient::_readlineblock(false, 0, timeout)) return std::atoi(line); return 0; @@ -137,7 +137,7 @@ public: } #endif - if (const char* const line = CarlaPipeClient::_readlineblock(false, timeout)) + if (const char* const line = CarlaPipeClient::_readlineblock(false, 0, timeout)) return std::atof(line); return 0.0; diff --git a/source/bridges-ui/CarlaBridgeFormat.cpp b/source/bridges-ui/CarlaBridgeFormat.cpp index af01270a7..22828e353 100644 --- a/source/bridges-ui/CarlaBridgeFormat.cpp +++ b/source/bridges-ui/CarlaBridgeFormat.cpp @@ -42,7 +42,8 @@ CarlaBridgeFormat::CarlaBridgeFormat() noexcept fLastMsgTimer(-1), fToolkit(nullptr), fLib(nullptr), - fLibFilename() + fLibFilename(), + fBase64ReservedChunk() { carla_debug("CarlaBridgeFormat::CarlaBridgeFormat()"); @@ -120,6 +121,50 @@ bool CarlaBridgeFormat::msgReceived(const char* const msg) noexcept if (fLastMsgTimer > 0) --fLastMsgTimer; + if (std::strcmp(msg, "atom") == 0) + { + uint32_t index, atomTotalSize, base64Size; + const char* base64atom; + + CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(index), true); + CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(atomTotalSize), true); + CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(base64Size), true); + CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(base64atom, false, base64Size), true); + + carla_getChunkFromBase64String_impl(fBase64ReservedChunk, base64atom); + CARLA_SAFE_ASSERT_UINT2_RETURN(fBase64ReservedChunk.size() >= sizeof(LV2_Atom), + fBase64ReservedChunk.size(), sizeof(LV2_Atom), true); + +#ifdef CARLA_PROPER_CPP11_SUPPORT + const LV2_Atom* const atom((const LV2_Atom*)fBase64ReservedChunk.data()); +#else + const LV2_Atom* const atom((const LV2_Atom*)&fBase64ReservedChunk.front()); +#endif + const uint32_t atomTotalSizeCheck(lv2_atom_total_size(atom)); + + CARLA_SAFE_ASSERT_UINT2_RETURN(atomTotalSizeCheck == atomTotalSize, atomTotalSizeCheck, atomTotalSize, true); + CARLA_SAFE_ASSERT_UINT2_RETURN(atomTotalSizeCheck == fBase64ReservedChunk.size(), + atomTotalSizeCheck, fBase64ReservedChunk.size(), true); + + dspAtomReceived(index, atom); + return true; + } + + if (std::strcmp(msg, "urid") == 0) + { + uint32_t urid, size; + const char* uri; + + CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(urid), true); + CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(size), true); + CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(uri, false, size), true); + + if (urid != 0) + dspURIDReceived(urid, uri); + + return true; + } + if (std::strcmp(msg, "control") == 0) { uint32_t index; @@ -181,46 +226,6 @@ bool CarlaBridgeFormat::msgReceived(const char* const msg) noexcept return true; } - if (std::strcmp(msg, "atom") == 0) - { - uint32_t index, atomTotalSize; - const char* base64atom; - - CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(index), true); - CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(atomTotalSize), true); - CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(base64atom, false), true); - - std::vector chunk(carla_getChunkFromBase64String(base64atom)); - CARLA_SAFE_ASSERT_RETURN(chunk.size() >= sizeof(LV2_Atom), true); - -#ifdef CARLA_PROPER_CPP11_SUPPORT - const LV2_Atom* const atom((const LV2_Atom*)chunk.data()); -#else - const LV2_Atom* const atom((const LV2_Atom*)&chunk.front()); -#endif - const uint32_t atomTotalSizeCheck(lv2_atom_total_size(atom)); - - CARLA_SAFE_ASSERT_RETURN(atomTotalSizeCheck == atomTotalSize, true); - CARLA_SAFE_ASSERT_RETURN(atomTotalSizeCheck == chunk.size(), true); - - dspAtomReceived(index, atom); - return true; - } - - if (std::strcmp(msg, "urid") == 0) - { - uint32_t urid; - const char* uri; - - CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(urid), true); - CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(uri, false), true); - - if (urid != 0) - dspURIDReceived(urid, uri); - - return true; - } - if (std::strcmp(msg, "uiOptions") == 0) { BridgeFormatOptions opts; diff --git a/source/bridges-ui/CarlaBridgeFormat.hpp b/source/bridges-ui/CarlaBridgeFormat.hpp index 35205aa6e..606155559 100644 --- a/source/bridges-ui/CarlaBridgeFormat.hpp +++ b/source/bridges-ui/CarlaBridgeFormat.hpp @@ -27,6 +27,8 @@ #include "lv2/atom.h" #include "lv2/urid.h" +#include + CARLA_BRIDGE_UI_START_NAMESPACE /*! @@ -161,6 +163,7 @@ protected: lib_t fLib; CarlaString fLibFilename; + std::vector fBase64ReservedChunk; /*! @internal */ bool msgReceived(const char* const msg) noexcept override; diff --git a/source/bridges-ui/CarlaBridgeToolkitNative.cpp b/source/bridges-ui/CarlaBridgeToolkitNative.cpp index 82957c002..7e7c0ccbb 100644 --- a/source/bridges-ui/CarlaBridgeToolkitNative.cpp +++ b/source/bridges-ui/CarlaBridgeToolkitNative.cpp @@ -108,7 +108,7 @@ public: // MacOS and Win32 have event-loops to run, so minimize sleep time carla_msleep(1); #else - carla_msleep(20); + carla_msleep(33); #endif } } diff --git a/source/utils/CarlaBase64Utils.hpp b/source/utils/CarlaBase64Utils.hpp index 56ced8b24..afb365740 100644 --- a/source/utils/CarlaBase64Utils.hpp +++ b/source/utils/CarlaBase64Utils.hpp @@ -60,15 +60,15 @@ bool isBase64Char(const char c) // ----------------------------------------------------------------------- static inline -std::vector carla_getChunkFromBase64String(const char* const base64string) +void carla_getChunkFromBase64String_impl(std::vector& vector, const char* const base64string) { - CARLA_SAFE_ASSERT_RETURN(base64string != nullptr, std::vector()); + CARLA_SAFE_ASSERT_RETURN(base64string != nullptr,); uint i=0, j=0; uint charArray3[3], charArray4[4]; - std::vector ret; - ret.reserve(std::strlen(base64string)*3/4 + 4); + vector.clear(); + vector.reserve(std::strlen(base64string)*3/4 + 4); for (std::size_t l=0, len=std::strlen(base64string); l carla_getChunkFromBase64String(const char* const base64stri charArray3[2] = ((charArray4[2] & 0x3) << 6) + charArray4[3]; for (i=0; i<3; ++i) - ret.push_back(static_cast(charArray3[i])); + vector.push_back(static_cast(charArray3[i])); i = 0; } @@ -112,9 +112,16 @@ std::vector carla_getChunkFromBase64String(const char* const base64stri charArray3[2] = ((charArray4[2] & 0x3) << 6) + charArray4[3]; for (j=0; i>0 && j(charArray3[j])); + vector.push_back(static_cast(charArray3[j])); } +} + +static inline +std::vector carla_getChunkFromBase64String(const char* const base64string) +{ + std::vector ret; + carla_getChunkFromBase64String_impl(ret, base64string); return ret; } diff --git a/source/utils/CarlaPipeUtils.cpp b/source/utils/CarlaPipeUtils.cpp index 493dbac4e..1e4e9a5cf 100644 --- a/source/utils/CarlaPipeUtils.cpp +++ b/source/utils/CarlaPipeUtils.cpp @@ -660,10 +660,12 @@ void CarlaPipeCommon::idlePipe(const bool onlyOnce) noexcept for (;;) { readSucess = false; - const char* const msg = _readline(true, readSucess); + const char* const msg = _readline(true, 0, readSucess); - if (msg == nullptr || ! readSucess) + if (! readSucess) break; + if (msg == nullptr) + continue; pData->isReading = true; @@ -836,11 +838,14 @@ bool CarlaPipeCommon::readNextLineAsDouble(double& value) const noexcept return false; } -bool CarlaPipeCommon::readNextLineAsString(const char*& value, const bool allocateString) const noexcept +bool CarlaPipeCommon::readNextLineAsString(const char*& value, const bool allocateString, uint32_t size) const noexcept { CARLA_SAFE_ASSERT_RETURN(pData->isReading, false); - if (const char* const msg = _readlineblock(allocateString)) + if (size >= 0xffff) + size = 0; + + if (const char* const msg = _readlineblock(allocateString, static_cast(size))) { value = msg; return true; @@ -1141,6 +1146,10 @@ void CarlaPipeCommon::writeLv2AtomMessage(const uint32_t index, const LV2_Atom* if (! _writeMsgBuffer(tmpBuf, std::strlen(tmpBuf))) return; + std::snprintf(tmpBuf, 0xfe, "%lu\n", static_cast(base64atom.length())); + if (! _writeMsgBuffer(tmpBuf, std::strlen(tmpBuf))) + return; + if (! writeAndFixMessage(base64atom.buffer())) return; @@ -1164,6 +1173,10 @@ void CarlaPipeCommon::writeLv2UridMessage(const uint32_t urid, const char* const if (! _writeMsgBuffer(tmpBuf, std::strlen(tmpBuf))) return; + std::snprintf(tmpBuf, 0xfe, "%lu\n", static_cast(std::strlen(uri))); + if (! _writeMsgBuffer(tmpBuf, std::strlen(tmpBuf))) + return; + if (! writeAndFixMessage(uri)) return; @@ -1173,7 +1186,7 @@ void CarlaPipeCommon::writeLv2UridMessage(const uint32_t urid, const char* const // ------------------------------------------------------------------- // internal -const char* CarlaPipeCommon::_readline(const bool allocReturn, bool& readSucess) const noexcept +const char* CarlaPipeCommon::_readline(const bool allocReturn, const uint16_t size, bool& readSucess) const noexcept { CARLA_SAFE_ASSERT_RETURN(pData->pipeRecv != INVALID_PIPE_VALUE, nullptr); @@ -1184,31 +1197,79 @@ const char* CarlaPipeCommon::_readline(const bool allocReturn, bool& readSucess) pData->tmpStr.clear(); - for (int i=0; i<0xfffe; ++i) + if (size == 0 || size == 1) { - try { -#ifdef CARLA_OS_WIN - ret = ReadFileWin32(pData->pipeRecv, pData->ovRecv, &c, 1); -#else - ret = ::read(pData->pipeRecv, &c, 1); -#endif - } CARLA_SAFE_EXCEPTION_BREAK("CarlaPipeCommon::readline() - read"); + for (int i=0; i<0xfffe; ++i) + { + try { + #ifdef CARLA_OS_WIN + ret = ReadFileWin32(pData->pipeRecv, pData->ovRecv, &c, 1); + #else + ret = ::read(pData->pipeRecv, &c, 1); + #endif + } CARLA_SAFE_EXCEPTION_BREAK("CarlaPipeCommon::readline() - read"); + + if (ret != 1 || c == '\n') + break; - if (ret != 1 || c == '\n') - break; + if (c == '\r') + c = '\n'; - if (c == '\r') - c = '\n'; + *ptr++ = c; - *ptr++ = c; + if (i+1 == 0xfffe) + { + i = 0; + *ptr = '\0'; + tooBig = true; + pData->tmpStr += pData->tmpBuf; + ptr = pData->tmpBuf; + } + } + } + else + { + uint16_t remaining = size; + readSucess = false; - if (i+1 == 0xfffe) + for (;;) { - i = 0; + try { + #ifdef CARLA_OS_WIN + ret = ReadFileWin32(pData->pipeRecv, pData->ovRecv, ptr, remaining); + #else + ret = ::read(pData->pipeRecv, ptr, remaining); + #endif + } CARLA_SAFE_EXCEPTION_RETURN("CarlaPipeCommon::readline() - read", nullptr); + + if (ret == -1 && errno == EAGAIN) + continue; + + CARLA_SAFE_ASSERT_INT2_RETURN(ret > 0, ret, remaining, nullptr); + CARLA_SAFE_ASSERT_INT2_RETURN(ret <= (ssize_t)remaining, ret, remaining, nullptr); + + for (ssize_t i=0; itmpStr += pData->tmpBuf; - ptr = pData->tmpBuf; + remaining = static_cast(remaining - ret); + + if (remaining != 0) + continue; + + readSucess = true; + + if (allocReturn) + { + pData->tmpStr = pData->tmpBuf; + return pData->tmpStr.releaseBufferPointer(); + } + + return pData->tmpBuf; } } @@ -1230,14 +1291,17 @@ const char* CarlaPipeCommon::_readline(const bool allocReturn, bool& readSucess) return nullptr; } + readSucess = true; + if (! allocReturn && ! tooBig) return pData->tmpBuf; - readSucess = true; return allocReturn ? pData->tmpStr.releaseBufferPointer() : pData->tmpStr.buffer(); } -const char* CarlaPipeCommon::_readlineblock(const bool allocReturn, const uint32_t timeOutMilliseconds) const noexcept +const char* CarlaPipeCommon::_readlineblock(const bool allocReturn, + const uint16_t size, + const uint32_t timeOutMilliseconds) const noexcept { const uint32_t timeoutEnd = water::Time::getMillisecondCounter() + timeOutMilliseconds; bool readSucess; @@ -1245,7 +1309,7 @@ const char* CarlaPipeCommon::_readlineblock(const bool allocReturn, const uint32 for (;;) { readSucess = false; - const char* const msg = _readline(allocReturn, readSucess); + const char* const msg = _readline(allocReturn, size, readSucess); if (readSucess) return msg; @@ -1265,7 +1329,7 @@ const char* CarlaPipeCommon::_readlineblock(const bool allocReturn, const uint32 for (;;) { readSucess = false; - const char* const msg = _readline(allocReturn, readSucess); + const char* const msg = _readline(allocReturn, size, readSucess); if (readSucess) return msg; diff --git a/source/utils/CarlaPipeUtils.hpp b/source/utils/CarlaPipeUtils.hpp index 49327a76a..38095ba03 100644 --- a/source/utils/CarlaPipeUtils.hpp +++ b/source/utils/CarlaPipeUtils.hpp @@ -142,7 +142,7 @@ public: * Read the next line as a string. * @note: @a value must be deleted if valid. */ - bool readNextLineAsString(const char*& value, bool allocateString) const noexcept; + bool readNextLineAsString(const char*& value, bool allocateString, uint32_t size = 0) const noexcept; // ------------------------------------------------------------------- // write messages, must be locked before calling @@ -236,10 +236,10 @@ protected: // ------------------------------------------------------------------- /*! @internal */ - const char* _readline(bool allocReturn, bool& readSucess) const noexcept; + const char* _readline(bool allocReturn, uint16_t size, bool& readSucess) const noexcept; /*! @internal */ - const char* _readlineblock(bool allocReturn, uint32_t timeOutMilliseconds = 50) const noexcept; + const char* _readlineblock(bool allocReturn, uint16_t size = 0, uint32_t timeOutMilliseconds = 50) const noexcept; /*! @internal */ bool _writeMsgBuffer(const char* msg, std::size_t size) const noexcept;