[Libreoffice-commits] online.git: net/Socket.cpp net/Socket.hpp wsd/LOOLWSD.cpp
Michael Meeks
michael.meeks at collabora.com
Tue May 1 15:30:58 UTC 2018
net/Socket.cpp | 66 +++++++++++++++++++++++++++++++++++++
net/Socket.hpp | 19 +++++++++-
wsd/LOOLWSD.cpp | 98 +++++++-------------------------------------------------
3 files changed, 96 insertions(+), 87 deletions(-)
New commits:
commit b5a1af763cf0e2295286f3e27c767ec51551cf2f
Author: Michael Meeks <michael.meeks at collabora.com>
Date: Tue May 1 14:57:17 2018 +0100
Share HTTP header parsing inside the StreamSocket.
Change-Id: Id98e895a939d931ac10b7cd7403da4cbe822ee82
diff --git a/net/Socket.cpp b/net/Socket.cpp
index 1bf847cba..9a07986c9 100644
--- a/net/Socket.cpp
+++ b/net/Socket.cpp
@@ -17,6 +17,8 @@
#include <Poco/DateTime.h>
#include <Poco/DateTimeFormat.h>
#include <Poco/DateTimeFormatter.h>
+#include <Poco/MemoryStream.h>
+#include <Poco/Net/HTTPRequest.h>
#include <Poco/Net/HTTPResponse.h>
#include <SigUtil.hpp>
@@ -241,6 +243,70 @@ bool ServerSocket::bind(Type type, int port)
return rc == 0;
}
+bool StreamSocket::parseHeader(const char *clientName,
+ Poco::MemoryInputStream &message,
+ Poco::Net::HTTPRequest &request,
+ size_t *requestSize)
+{
+ LOG_TRC("#" << getFD() << " handling incoming " << _inBuffer.size() << " bytes.");
+
+ assert(!requestSize || *requestSize == 0);
+
+ // Find the end of the header, if any.
+ static const std::string marker("\r\n\r\n");
+ auto itBody = std::search(_inBuffer.begin(), _inBuffer.end(),
+ marker.begin(), marker.end());
+ if (itBody == _inBuffer.end())
+ {
+ LOG_TRC("#" << getFD() << " doesn't have enough data yet.");
+ return false;
+ }
+
+ // Skip the marker.
+ itBody += marker.size();
+ if (requestSize)
+ *requestSize = static_cast<size_t>(itBody - _inBuffer.begin());
+
+ try
+ {
+ request.read(message);
+
+ Log::StreamLogger logger = Log::info();
+ if (logger.enabled())
+ {
+ logger << "#" << getFD() << ": " << clientName << " HTTP Request: "
+ << request.getMethod() << ' '
+ << request.getURI() << ' '
+ << request.getVersion();
+
+ for (const auto& it : request)
+ {
+ logger << " / " << it.first << ": " << it.second;
+ }
+
+ LOG_END(logger);
+ }
+
+ const std::streamsize contentLength = request.getContentLength();
+ const auto offset = itBody - _inBuffer.begin();
+ const std::streamsize available = _inBuffer.size() - offset;
+
+ if (contentLength != Poco::Net::HTTPMessage::UNKNOWN_CONTENT_LENGTH && available < contentLength)
+ {
+ LOG_DBG("Not enough content yet: ContentLength: " << contentLength << ", available: " << available);
+ return false;
+ }
+ }
+ catch (const std::exception& exc)
+ {
+ // Probably don't have enough data just yet.
+ // TODO: timeout if we never get enough.
+ return false;
+ }
+
+ return true;
+}
+
namespace HttpHelper
{
diff --git a/net/Socket.hpp b/net/Socket.hpp
index d3d48128f..84632a4f2 100644
--- a/net/Socket.hpp
+++ b/net/Socket.hpp
@@ -40,8 +40,10 @@
namespace Poco
{
+ class MemoryInputStream;
namespace Net
{
+ class HTTPRequest;
class HTTPResponse;
}
}
@@ -833,6 +835,20 @@ public:
return socket;
}
+ /// Remove the first @count bytes from input buffer
+ void eraseFirstInputBytes(size_t count)
+ {
+ _inBuffer.erase(_inBuffer.begin(), _inBuffer.begin() + count);
+ }
+
+ /// Detects if we have an HTTP header in the provided message and
+ /// populates a request for that.
+ bool parseHeader(const char *clientLoggingName,
+ Poco::MemoryInputStream &message,
+ Poco::Net::HTTPRequest &request,
+ size_t *requestSize = nullptr);
+
+ /// Get input/output statistics on this stream
void getIOStats(uint64_t &sent, uint64_t &recv)
{
sent = _bytesSent;
@@ -1021,8 +1037,7 @@ namespace HttpHelper
void sendFile(const std::shared_ptr<StreamSocket>& socket, const std::string& path, const std::string& mediaType,
Poco::Net::HTTPResponse& response, bool noCache = false, bool deflate = false,
const bool headerOnly = false);
-};
-
+}
#endif
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/wsd/LOOLWSD.cpp b/wsd/LOOLWSD.cpp
index 9d39ba2ce..668916500 100644
--- a/wsd/LOOLWSD.cpp
+++ b/wsd/LOOLWSD.cpp
@@ -1608,42 +1608,16 @@ private:
}
std::shared_ptr<StreamSocket> socket = _socket.lock();
- std::vector<char>& in = socket->_inBuffer;
- // Find the end of the header, if any.
- static const std::string marker("\r\n\r\n");
- auto itBody = std::search(in.begin(), in.end(),
- marker.begin(), marker.end());
- if (itBody == in.end())
- {
- LOG_TRC("#" << socket->getFD() << " doesn't have enough data yet.");
- return;
- }
-
- // Skip the marker.
- itBody += marker.size();
-
- Poco::MemoryInputStream message(&in[0], in.size());
+ Poco::MemoryInputStream message(&socket->_inBuffer[0],
+ socket->_inBuffer.size());;
Poco::Net::HTTPRequest request;
+ size_t requestSize = 0;
+
try
{
- request.read(message);
-
- Log::StreamLogger logger = Log::info();
- if (logger.enabled())
- {
- logger << "#" << socket->getFD() << ": Prisoner HTTP Request: "
- << request.getMethod() << ' '
- << request.getURI() << ' '
- << request.getVersion();
-
- for (const auto& it : request)
- {
- logger << " / " << it.first << ": " << it.second;
- }
-
- LOG_END(logger);
- }
+ if (!socket->parseHeader("Prisoner", message, request, &requestSize))
+ return;
LOG_TRC("Child connection with URI [" << request.getURI() << "].");
if (request.getURI().find(NEW_CHILD_URI) != 0)
@@ -1684,7 +1658,7 @@ private:
return;
}
- in.clear();
+ socket->_inBuffer.clear();
LOG_INF("New child [" << pid << "], jailId: " << jailId << ".");
@@ -1768,60 +1742,14 @@ private:
void handleIncomingMessage(SocketDisposition &disposition) override
{
std::shared_ptr<StreamSocket> socket = _socket.lock();
- std::vector<char>& in = socket->_inBuffer;
- LOG_TRC("#" << socket->getFD() << " handling incoming " << in.size() << " bytes.");
-
- // Find the end of the header, if any.
- static const std::string marker("\r\n\r\n");
- auto itBody = std::search(in.begin(), in.end(),
- marker.begin(), marker.end());
- if (itBody == in.end())
- {
- LOG_DBG("#" << socket->getFD() << " doesn't have enough data yet.");
- return;
- }
- // Skip the marker.
- itBody += marker.size();
-
- Poco::MemoryInputStream message(&in[0], in.size());
+ Poco::MemoryInputStream message(&socket->_inBuffer[0],
+ socket->_inBuffer.size());;
Poco::Net::HTTPRequest request;
- try
- {
- request.read(message);
-
- Log::StreamLogger logger = Log::info();
- if (logger.enabled())
- {
- logger << "#" << socket->getFD() << ": Client HTTP Request: "
- << request.getMethod() << ' '
- << request.getURI() << ' '
- << request.getVersion();
-
- for (const auto& it : request)
- {
- logger << " / " << it.first << ": " << it.second;
- }
-
- LOG_END(logger);
- }
-
- const std::streamsize contentLength = request.getContentLength();
- const auto offset = itBody - in.begin();
- const std::streamsize available = in.size() - offset;
+ size_t requestSize = 0;
- if (contentLength != Poco::Net::HTTPMessage::UNKNOWN_CONTENT_LENGTH && available < contentLength)
- {
- LOG_DBG("Not enough content yet: ContentLength: " << contentLength << ", available: " << available);
- return;
- }
- }
- catch (const std::exception& exc)
- {
- // Probably don't have enough data just yet.
- // TODO: timeout if we never get enough.
+ if (!socket->parseHeader("Client", message, request, &requestSize))
return;
- }
try
{
@@ -1949,12 +1877,12 @@ private:
// NOTE: Check _wsState to choose between HTTP response or WebSocket (app-level) error.
LOG_INF("#" << socket->getFD() << " Exception while processing incoming request: [" <<
- LOOLProtocol::getAbbreviatedMessage(in) << "]: " << exc.what());
+ LOOLProtocol::getAbbreviatedMessage(socket->_inBuffer) << "]: " << exc.what());
}
// if we succeeded - remove the request from our input buffer
// we expect one request per socket
- in.erase(in.begin(), itBody);
+ socket->eraseFirstInputBytes(requestSize);
}
int getPollEvents(std::chrono::steady_clock::time_point /* now */,
More information about the Libreoffice-commits
mailing list