diff --git a/src/AsyncSocket.h b/src/AsyncSocket.h index 04ad5f1..e3e2771 100644 --- a/src/AsyncSocket.h +++ b/src/AsyncSocket.h @@ -176,7 +176,7 @@ protected: if ((unsigned int) written < asyncSocketData->buffer.length()) { /* Update buffering (todo: we can do better here if we keep track of what happens to this guy later on) */ - asyncSocketData->buffer = asyncSocketData->buffer.substr((size_t) written); + asyncSocketData->buffer.erase((unsigned int) written); if (optionally) { /* Thankfully we can exit early here */ diff --git a/src/AsyncSocketData.h b/src/AsyncSocketData.h index db43a62..16dd997 100644 --- a/src/AsyncSocketData.h +++ b/src/AsyncSocketData.h @@ -1,5 +1,5 @@ /* - * Authored by Alex Hultman, 2018-2019. + * Authored by Alex Hultman, 2018-2021. * Intellectual property of third-party. * Licensed under the Apache License, Version 2.0 (the "License"); @@ -22,15 +22,51 @@ namespace uWS { +struct BackPressure { + std::string buffer; + unsigned int pendingRemoval = 0; + BackPressure(BackPressure &&other) { + buffer = std::move(other.buffer); + pendingRemoval = other.pendingRemoval; + } + BackPressure() = default; + void append(const char *data, size_t length) { + buffer.append(data, length); + } + void erase(unsigned int length) { + pendingRemoval += length; + if (pendingRemoval > 1024 * 1024 || !(buffer.length() - pendingRemoval)) { + buffer.erase(0, pendingRemoval); + pendingRemoval = 0; + } + } + size_t length() { + return buffer.length() - pendingRemoval; + } + void clear() { + pendingRemoval = 0; + buffer.clear(); + } + void reserve(size_t length) { + buffer.reserve(length + pendingRemoval); + } + const char *data() { + return buffer.data() + pendingRemoval; + } + size_t size() { + return length(); + } +}; + /* Depending on how we want AsyncSocket to function, this will need to change */ template struct AsyncSocketData { /* This will do for now */ - std::string buffer; + BackPressure buffer; /* Allow move constructing us */ - AsyncSocketData(std::string &&backpressure) : buffer(std::move(backpressure)) { + AsyncSocketData(BackPressure &&backpressure) : buffer(std::move(backpressure)) { } diff --git a/src/HttpResponse.h b/src/HttpResponse.h index ba1bd2f..2ce13ee 100644 --- a/src/HttpResponse.h +++ b/src/HttpResponse.h @@ -273,7 +273,7 @@ public: HttpContext *httpContext = (HttpContext *) us_socket_context(SSL, (struct us_socket_t *) this); /* Move any backpressure out of HttpResponse */ - std::string backpressure(std::move(((AsyncSocketData *) getHttpResponseData())->buffer)); + BackPressure backpressure(std::move(((AsyncSocketData *) getHttpResponseData())->buffer)); /* Destroy HttpResponseData */ getHttpResponseData()->~HttpResponseData(); diff --git a/src/WebSocket.h b/src/WebSocket.h index 6ed3497..b2181ce 100644 --- a/src/WebSocket.h +++ b/src/WebSocket.h @@ -34,7 +34,7 @@ struct WebSocket : AsyncSocket { private: typedef AsyncSocket Super; - void *init(bool perMessageDeflate, CompressOptions compressOptions, std::string &&backpressure) { + void *init(bool perMessageDeflate, CompressOptions compressOptions, BackPressure &&backpressure) { new (us_socket_ext(SSL, (us_socket_t *) this)) WebSocketData(perMessageDeflate, compressOptions, std::move(backpressure)); return this; } diff --git a/src/WebSocketData.h b/src/WebSocketData.h index d0cea6f..6a4c52e 100644 --- a/src/WebSocketData.h +++ b/src/WebSocketData.h @@ -50,7 +50,7 @@ private: /* We could be a subscriber */ Subscriber *subscriber = nullptr; public: - WebSocketData(bool perMessageDeflate, CompressOptions compressOptions, std::string &&backpressure) : AsyncSocketData(std::move(backpressure)), WebSocketState() { + WebSocketData(bool perMessageDeflate, CompressOptions compressOptions, BackPressure &&backpressure) : AsyncSocketData(std::move(backpressure)), WebSocketState() { compressionStatus = perMessageDeflate ? ENABLED : DISABLED; /* Initialize the dedicated sliding window */