|
8 | 8 |
|
9 | 9 | namespace SL { |
10 | 10 | namespace WS_LITE { |
11 | | - const size_t LARGE_BUFFER_SIZE = 300 * 1024; |
| 11 | + const size_t LARGE_BUFFER_SIZE = 4 * 1024 * 1024; // 4 MB temp buffer |
12 | 12 | class IWebSocket; |
13 | 13 | struct HttpHeader; |
14 | 14 | struct WSMessage; |
15 | | - struct WebSocketContext { |
| 15 | + class WebSocketContext { |
| 16 | + unsigned char *InflateBuffer = nullptr; |
| 17 | + size_t InflateBufferSize = 0; |
| 18 | + std::unique_ptr<unsigned char[]> TempInflateBuffer; |
| 19 | + z_stream InflationStream = {}; |
| 20 | + auto returnemptyinflate() |
| 21 | + { |
| 22 | + unsigned char *p = nullptr; |
| 23 | + size_t o = 0; |
| 24 | + return std::make_tuple(p, o); |
| 25 | + } |
16 | 26 |
|
17 | | - WebSocketContext() : inflationBuffer(std::make_unique<char[]>(LARGE_BUFFER_SIZE)) { inflateInit2(&inflationStream, -MAX_WBITS); } |
18 | | - ~WebSocketContext() { inflateEnd(&inflationStream); } |
19 | | - auto inflate(unsigned char *data, size_t data_len) |
| 27 | + public: |
| 28 | + WebSocketContext() |
| 29 | + { |
| 30 | + TempInflateBuffer = std::make_unique<unsigned char[]>(MaxPayload); |
| 31 | + inflateInit2(&InflationStream, -MAX_WBITS); |
| 32 | + } |
| 33 | + ~WebSocketContext() { inflateEnd(&InflationStream); } |
| 34 | + auto beginInflate() |
| 35 | + { |
| 36 | + InflateBufferSize = 0; |
| 37 | + free(InflateBuffer); |
| 38 | + InflateBuffer = nullptr; |
| 39 | + } |
| 40 | + auto Inflate(unsigned char *data, size_t data_len) |
20 | 41 | { |
21 | | - dynamicInflationBuffer.clear(); |
22 | | - inflationStream.next_in = (Bytef *)data; |
23 | | - inflationStream.avail_in = data_len; |
| 42 | + InflationStream.next_in = (Bytef *)data; |
| 43 | + InflationStream.avail_in = data_len; |
24 | 44 |
|
25 | 45 | int err; |
26 | 46 | do { |
27 | | - inflationStream.next_out = (Bytef *)inflationBuffer.get(); |
28 | | - inflationStream.avail_out = LARGE_BUFFER_SIZE; |
29 | | - err = ::inflate(&inflationStream, Z_FINISH); |
30 | | - if (!inflationStream.avail_in) { |
| 47 | + InflationStream.next_out = (Bytef *)TempInflateBuffer.get(); |
| 48 | + InflationStream.avail_out = LARGE_BUFFER_SIZE; |
| 49 | + err = ::inflate(&InflationStream, Z_FINISH); |
| 50 | + if (!InflationStream.avail_in) { |
31 | 51 | break; |
32 | 52 | } |
| 53 | + auto growsize = LARGE_BUFFER_SIZE - InflationStream.avail_out; |
| 54 | + InflateBufferSize += growsize; |
| 55 | + auto beforesize = InflateBufferSize; |
| 56 | + InflateBuffer = static_cast<unsigned char *>(realloc(InflateBuffer, InflateBufferSize)); |
| 57 | + if (!InflateBuffer) { |
| 58 | + SL_WS_LITE_LOG(Logging_Levels::ERROR_log_level, "INFLATE MEMORY ALLOCATION ERROR!!! Tried to realloc " << InflateBufferSize); |
| 59 | + return returnemptyinflate(); |
| 60 | + } |
| 61 | + memcpy(InflateBuffer + beforesize, TempInflateBuffer.get(), growsize); |
| 62 | + } while (err == Z_BUF_ERROR && InflateBufferSize <= MaxPayload); |
33 | 63 |
|
34 | | - dynamicInflationBuffer.append(inflationBuffer.get(), LARGE_BUFFER_SIZE - inflationStream.avail_out); |
35 | | - } while (err == Z_BUF_ERROR && dynamicInflationBuffer.length() <= MaxPayload); |
36 | | - |
37 | | - inflateReset(&inflationStream); |
| 64 | + inflateReset(&InflationStream); |
38 | 65 |
|
39 | | - if ((err != Z_BUF_ERROR && err != Z_OK) || dynamicInflationBuffer.length() > MaxPayload) { |
40 | | - unsigned char *p = nullptr; |
41 | | - size_t o = 0; |
42 | | - return std::make_tuple(p, o); |
| 66 | + if ((err != Z_BUF_ERROR && err != Z_OK) || InflateBufferSize > MaxPayload) { |
| 67 | + return returnemptyinflate(); |
43 | 68 | } |
44 | | - if (!dynamicInflationBuffer.empty()) { |
45 | | - dynamicInflationBuffer.append(inflationBuffer.get(), LARGE_BUFFER_SIZE - inflationStream.avail_out); |
46 | | - return std::make_tuple((unsigned char *)dynamicInflationBuffer.data(), dynamicInflationBuffer.length()); |
| 69 | + if (InflateBufferSize > 0) { |
| 70 | + auto growsize = LARGE_BUFFER_SIZE - InflationStream.avail_out; |
| 71 | + InflateBufferSize += growsize; |
| 72 | + auto beforesize = InflateBufferSize; |
| 73 | + InflateBuffer = static_cast<unsigned char *>(realloc(InflateBuffer, InflateBufferSize)); |
| 74 | + if (!InflateBuffer) { |
| 75 | + SL_WS_LITE_LOG(Logging_Levels::ERROR_log_level, "INFLATE MEMORY ALLOCATION ERROR!!! Tried to realloc " << InflateBufferSize); |
| 76 | + return returnemptyinflate(); |
| 77 | + } |
| 78 | + memcpy(InflateBuffer + beforesize, TempInflateBuffer.get(), growsize); |
| 79 | + return std::make_tuple(InflateBuffer, InflateBufferSize); |
47 | 80 | } |
48 | | - |
49 | | - return std::make_tuple((unsigned char *)inflationBuffer.get(), LARGE_BUFFER_SIZE - (size_t)inflationStream.avail_out); |
| 81 | + return std::make_tuple(TempInflateBuffer.get(), LARGE_BUFFER_SIZE - (size_t)InflationStream.avail_out); |
50 | 82 | } |
51 | | - std::string dynamicInflationBuffer; |
52 | | - std::unique_ptr<char[]> inflationBuffer; |
53 | | - z_stream inflationStream = {}; |
54 | | - |
| 83 | + auto endInflate() { beginInflate(); } |
55 | 84 | std::function<void(const std::shared_ptr<IWebSocket> &, const HttpHeader &)> onConnection; |
56 | 85 | std::function<void(const std::shared_ptr<IWebSocket> &, const WSMessage &)> onMessage; |
57 | 86 | std::function<void(const std::shared_ptr<IWebSocket> &, unsigned short, const std::string &)> onDisconnection; |
|
0 commit comments