Experimental: bump 30 bit receive limit to 62 bit
This commit is contained in:
+17
-17
@@ -29,18 +29,18 @@
|
|||||||
|
|
||||||
namespace uWS {
|
namespace uWS {
|
||||||
|
|
||||||
constexpr uint32_t STATE_HAS_SIZE = 0x80000000;
|
constexpr uint64_t STATE_HAS_SIZE = 1ull << (sizeof(uint64_t) * 8 - 1);//0x80000000;
|
||||||
constexpr uint32_t STATE_IS_CHUNKED = 0x40000000;
|
constexpr uint64_t STATE_IS_CHUNKED = 1ull << (sizeof(uint64_t) * 8 - 2);//0x40000000;
|
||||||
constexpr uint32_t STATE_SIZE_MASK = 0x3FFFFFFF;
|
constexpr uint64_t STATE_SIZE_MASK = ~(3ull << (sizeof(uint64_t) * 8 - 2));//0x3FFFFFFF;
|
||||||
constexpr uint32_t STATE_IS_ERROR = 0xFFFFFFFF;
|
constexpr uint64_t STATE_IS_ERROR = ~0ull;//0xFFFFFFFF;
|
||||||
constexpr uint32_t STATE_SIZE_OVERFLOW = 0x0F000000;
|
constexpr uint64_t STATE_SIZE_OVERFLOW = 0x0Full << (sizeof(uint64_t) * 8 - 8);//0x0F000000;
|
||||||
|
|
||||||
inline unsigned int chunkSize(unsigned int state) {
|
inline uint64_t chunkSize(uint64_t state) {
|
||||||
return state & STATE_SIZE_MASK;
|
return state & STATE_SIZE_MASK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reads hex number until CR or out of data to consume. Updates state. Returns bytes consumed. */
|
/* Reads hex number until CR or out of data to consume. Updates state. Returns bytes consumed. */
|
||||||
inline void consumeHexNumber(std::string_view &data, unsigned int &state) {
|
inline void consumeHexNumber(std::string_view &data, uint64_t &state) {
|
||||||
/* Consume everything higher than 32 */
|
/* Consume everything higher than 32 */
|
||||||
while (data.length() && data.data()[0] > 32) {
|
while (data.length() && data.data()[0] > 32) {
|
||||||
|
|
||||||
@@ -59,9 +59,9 @@ namespace uWS {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// extract state bits
|
// extract state bits
|
||||||
unsigned int bits = /*state &*/ STATE_IS_CHUNKED;
|
uint64_t bits = /*state &*/ STATE_IS_CHUNKED;
|
||||||
|
|
||||||
state = (state & STATE_SIZE_MASK) * 16u + number;
|
state = (state & STATE_SIZE_MASK) * 16ull + number;
|
||||||
|
|
||||||
state |= bits;
|
state |= bits;
|
||||||
data.remove_prefix(1);
|
data.remove_prefix(1);
|
||||||
@@ -78,7 +78,7 @@ namespace uWS {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void decChunkSize(unsigned int &state, unsigned int by) {
|
inline void decChunkSize(uint64_t &state, unsigned int by) {
|
||||||
|
|
||||||
//unsigned int bits = state & STATE_IS_CHUNKED;
|
//unsigned int bits = state & STATE_IS_CHUNKED;
|
||||||
|
|
||||||
@@ -87,21 +87,21 @@ namespace uWS {
|
|||||||
//state |= bits;
|
//state |= bits;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool hasChunkSize(unsigned int state) {
|
inline bool hasChunkSize(uint64_t state) {
|
||||||
return state & STATE_HAS_SIZE;
|
return state & STATE_HAS_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Are we in the middle of parsing chunked encoding? */
|
/* Are we in the middle of parsing chunked encoding? */
|
||||||
inline bool isParsingChunkedEncoding(unsigned int state) {
|
inline bool isParsingChunkedEncoding(uint64_t state) {
|
||||||
return state & ~STATE_SIZE_MASK;
|
return state & ~STATE_SIZE_MASK;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool isParsingInvalidChunkedEncoding(unsigned int state) {
|
inline bool isParsingInvalidChunkedEncoding(uint64_t state) {
|
||||||
return state == STATE_IS_ERROR;
|
return state == STATE_IS_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Returns next chunk (empty or not), or if all data was consumed, nullopt is returned. */
|
/* Returns next chunk (empty or not), or if all data was consumed, nullopt is returned. */
|
||||||
static std::optional<std::string_view> getNextChunk(std::string_view &data, unsigned int &state, bool trailer = false) {
|
static std::optional<std::string_view> getNextChunk(std::string_view &data, uint64_t &state, bool trailer = false) {
|
||||||
|
|
||||||
while (data.length()) {
|
while (data.length()) {
|
||||||
|
|
||||||
@@ -167,7 +167,7 @@ namespace uWS {
|
|||||||
/* We will consume all our input data */
|
/* We will consume all our input data */
|
||||||
std::string_view emitSoon;
|
std::string_view emitSoon;
|
||||||
if (chunkSize(state) > 2) {
|
if (chunkSize(state) > 2) {
|
||||||
unsigned int maximalAppEmit = chunkSize(state) - 2;
|
uint64_t maximalAppEmit = chunkSize(state) - 2;
|
||||||
if (data.length() > maximalAppEmit) {
|
if (data.length() > maximalAppEmit) {
|
||||||
emitSoon = data.substr(0, maximalAppEmit);
|
emitSoon = data.substr(0, maximalAppEmit);
|
||||||
} else {
|
} else {
|
||||||
@@ -195,10 +195,10 @@ namespace uWS {
|
|||||||
|
|
||||||
std::string_view *data;
|
std::string_view *data;
|
||||||
std::optional<std::string_view> chunk;
|
std::optional<std::string_view> chunk;
|
||||||
unsigned int *state;
|
uint64_t *state;
|
||||||
bool trailer;
|
bool trailer;
|
||||||
|
|
||||||
ChunkIterator(std::string_view *data, unsigned int *state, bool trailer = false) : data(data), state(state), trailer(trailer) {
|
ChunkIterator(std::string_view *data, uint64_t *state, bool trailer = false) : data(data), state(state), trailer(trailer) {
|
||||||
chunk = uWS::getNextChunk(*data, *state, trailer);
|
chunk = uWS::getNextChunk(*data, *state, trailer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+6
-6
@@ -180,7 +180,7 @@ struct HttpParser {
|
|||||||
private:
|
private:
|
||||||
std::string fallback;
|
std::string fallback;
|
||||||
/* This guy really has only 30 bits since we reserve two highest bits to chunked encoding parsing state */
|
/* This guy really has only 30 bits since we reserve two highest bits to chunked encoding parsing state */
|
||||||
unsigned int remainingStreamingBytes = 0;
|
uint64_t remainingStreamingBytes = 0;
|
||||||
|
|
||||||
/* Returns UINT_MAX on error. Maximum 999999999 is allowed. */
|
/* Returns UINT_MAX on error. Maximum 999999999 is allowed. */
|
||||||
static unsigned int toUnsignedInteger(std::string_view str) {
|
static unsigned int toUnsignedInteger(std::string_view str) {
|
||||||
@@ -506,7 +506,7 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!CONSUME_MINIMALLY) {
|
if (!CONSUME_MINIMALLY) {
|
||||||
unsigned int emittable = std::min<unsigned int>(remainingStreamingBytes, length);
|
unsigned int emittable = (unsigned int) std::min<uint64_t>(remainingStreamingBytes, length);
|
||||||
dataHandler(user, std::string_view(data, emittable), emittable == remainingStreamingBytes);
|
dataHandler(user, std::string_view(data, emittable), emittable == remainingStreamingBytes);
|
||||||
remainingStreamingBytes -= emittable;
|
remainingStreamingBytes -= emittable;
|
||||||
|
|
||||||
@@ -561,8 +561,8 @@ public:
|
|||||||
} else {
|
} else {
|
||||||
void *returnedUser = dataHandler(user, std::string_view(data, remainingStreamingBytes), true);
|
void *returnedUser = dataHandler(user, std::string_view(data, remainingStreamingBytes), true);
|
||||||
|
|
||||||
data += remainingStreamingBytes;
|
data += (unsigned int) remainingStreamingBytes;
|
||||||
length -= remainingStreamingBytes;
|
length -= (unsigned int) remainingStreamingBytes;
|
||||||
|
|
||||||
remainingStreamingBytes = 0;
|
remainingStreamingBytes = 0;
|
||||||
|
|
||||||
@@ -617,8 +617,8 @@ public:
|
|||||||
} else {
|
} else {
|
||||||
void *returnedUser = dataHandler(user, std::string_view(data, remainingStreamingBytes), true);
|
void *returnedUser = dataHandler(user, std::string_view(data, remainingStreamingBytes), true);
|
||||||
|
|
||||||
data += remainingStreamingBytes;
|
data += (unsigned int) remainingStreamingBytes;
|
||||||
length -= remainingStreamingBytes;
|
length -= (unsigned int) remainingStreamingBytes;
|
||||||
|
|
||||||
remainingStreamingBytes = 0;
|
remainingStreamingBytes = 0;
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
#include "../src/ChunkedEncoding.h"
|
#include "../src/ChunkedEncoding.h"
|
||||||
|
|
||||||
void consumeChunkEncoding(int maxConsume, std::string_view &chunkEncoded, unsigned int &state) {
|
void consumeChunkEncoding(int maxConsume, std::string_view &chunkEncoded, uint64_t &state) {
|
||||||
//int maxConsume = 200;
|
//int maxConsume = 200;
|
||||||
|
|
||||||
if (uWS::isParsingChunkedEncoding(state)) {
|
if (uWS::isParsingChunkedEncoding(state)) {
|
||||||
@@ -80,7 +80,7 @@ void runBetterTest(unsigned int maxConsume) {
|
|||||||
std::string buffer = ss.str();
|
std::string buffer = ss.str();
|
||||||
std::string_view chunkEncoded = buffer;
|
std::string_view chunkEncoded = buffer;
|
||||||
|
|
||||||
unsigned int state = 0;
|
uint64_t state = 0;
|
||||||
|
|
||||||
if (uWS::isParsingChunkedEncoding(state)) {
|
if (uWS::isParsingChunkedEncoding(state)) {
|
||||||
std::abort();
|
std::abort();
|
||||||
@@ -128,7 +128,7 @@ void runTest(unsigned int maxConsume) {
|
|||||||
unsigned int stoppedWithClearState = 0;
|
unsigned int stoppedWithClearState = 0;
|
||||||
|
|
||||||
/* Begin with a clear state and the full data */
|
/* Begin with a clear state and the full data */
|
||||||
unsigned int state = 0;
|
uint64_t state = 0;
|
||||||
unsigned int chunkOffset = 0;
|
unsigned int chunkOffset = 0;
|
||||||
std::string_view chunkEncoded = buffer;
|
std::string_view chunkEncoded = buffer;
|
||||||
|
|
||||||
@@ -200,7 +200,7 @@ void testWithoutTrailer() {
|
|||||||
std::string buffer = ss.str();
|
std::string buffer = ss.str();
|
||||||
std::string_view dataToConsume(buffer.data(), buffer.length());
|
std::string_view dataToConsume(buffer.data(), buffer.length());
|
||||||
|
|
||||||
unsigned int state = uWS::STATE_IS_CHUNKED;
|
uint64_t state = uWS::STATE_IS_CHUNKED;
|
||||||
|
|
||||||
for (auto chunk : uWS::ChunkIterator(&dataToConsume, &state)) {
|
for (auto chunk : uWS::ChunkIterator(&dataToConsume, &state)) {
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user