diff --git a/modules/juce_gui_extra/native/juce_WebBrowserComponent_linux.cpp b/modules/juce_gui_extra/native/juce_WebBrowserComponent_linux.cpp index f2e8a95d1c..88849c2c9f 100644 --- a/modules/juce_gui_extra/native/juce_WebBrowserComponent_linux.cpp +++ b/modules/juce_gui_extra/native/juce_WebBrowserComponent_linux.cpp @@ -464,24 +464,39 @@ public: { for (;;) { - char lengthBytes[sizeof (size_t)]{}; - const auto numLengthBytes = readIntoBuffer (lengthBytes); + auto len = (receivingLength ? sizeof (size_t) : bufferLength.len); - if (numLengthBytes != std::size (lengthBytes)) + if (! receivingLength) + buffer.realloc (len); + + auto* dst = (receivingLength ? bufferLength.data : buffer.getData()); + + auto actual = read (inChannel, &dst[pos], static_cast (len - pos)); + + if (actual < 0) + { + if (errno == EINTR) + continue; + + // This isn't an abort condition. The transfer of the same file can continue after + // the next call to tryNextRead. break; + } - const auto numBytesExpected = readUnaligned (lengthBytes); - buffer.reserve (numBytesExpected + 1); - buffer.resize (numBytesExpected); + pos += static_cast (actual); - if (readIntoBuffer (buffer) != numBytesExpected) - break; + if (pos == len) + { + pos = 0; - buffer.push_back (0); - parseJSON (StringRef (buffer.data())); + if (! std::exchange (receivingLength, ! receivingLength)) + { + parseJSON (String (buffer.getData(), bufferLength.len)); - if (ret == ReturnAfterMessageReceived::yes) - return; + if (ret == ReturnAfterMessageReceived::yes) + return; + } + } } if (errno != EAGAIN && errno != EWOULDBLOCK && responder != nullptr) @@ -536,37 +551,15 @@ private: } } - /* Try to fill the target buffer by reading from the input channel. - Returns the number of bytes that were successfully read. - */ - size_t readIntoBuffer (Span target) const - { - size_t pos = 0; - - while (pos != target.size()) - { - const auto bytesThisTime = read (inChannel, target.data() + pos, target.size() - pos); - - if (bytesThisTime <= 0) - { - if (bytesThisTime != 0 && errno == EINTR) - continue; - - break; - } - - pos += static_cast (bytesThisTime); - } - - return pos; - } - static Identifier getCmdIdentifier() { static Identifier Id ("cmd"); return Id; } static Identifier getParamIdentifier() { static Identifier Id ("params"); return Id; } - std::vector buffer; Responder* responder = nullptr; int inChannel = 0; + size_t pos = 0; + bool receivingLength = true; + union { char data [sizeof (size_t)]; size_t len; } bufferLength; + HeapBlock buffer; }; #define juce_g_signal_connect(instance, detailed_signal, c_handler, data) \