9#ifndef _STREAMDECODERS_H_
10#define _STREAMDECODERS_H_
32 bool feed(
const char* data,
size_t count) {
33 for (
size_t n = 0; n < count && !error; n++)
37 bool feed(
const std::string& data) {
return feed(data.data(), data.size()); }
39 const std::string&
body()
const {
return decoded; }
44 state = ST_SIZE; sizeLine.clear(); decoded.clear();
45 chunkRemaining = 0; complete =
false; error =
false;
58 void feedByte(
char c) {
63 size_t end = sizeLine.find(
';');
64 std::string hex = (end == std::string::npos) ? sizeLine : sizeLine.substr(0, end);
65 while (!hex.empty() && (hex[hex.size()-1] ==
'\r' || hex[hex.size()-1] ==
' '))
66 hex.erase(hex.size()-1);
67 if (!parseHex(hex, chunkRemaining)) { error =
true;
return; }
69 if (chunkRemaining == 0) { state = ST_TRAILER; sizeLine.clear(); }
76 if (--chunkRemaining == 0) state = ST_BODY_CRLF;
79 if (c ==
'\r') state = ST_BODY_LF;
80 else if (c ==
'\n') state = ST_SIZE;
84 if (c ==
'\n') state = ST_SIZE;
90 std::string line = sizeLine;
91 if (!line.empty() && line[line.size()-1] ==
'\r') line.erase(line.size()-1);
93 if (line.empty()) { complete =
true; state = ST_DONE; }
102 static bool parseHex(
const std::string& s,
size_t& out) {
103 if (s.empty())
return false;
105 for (
size_t n = 0; n < s.size(); n++) {
106 char c = s[n];
int d;
107 if (c >=
'0' && c <=
'9') d = c -
'0';
108 else if (c >=
'a' && c <=
'f') d = c -
'a' + 10;
109 else if (c >=
'A' && c <=
'F') d = c -
'A' + 10;
111 v = (v << 4) | (
size_t)d;
118 std::string sizeLine;
120 size_t chunkRemaining;
139 bool feed(
const char* data,
size_t count) {
140 for (
size_t n = 0; n < count && !error && !done; n++)
144 bool feed(
const std::string& data) {
return feed(data.data(), data.size()); }
149 if (events.empty())
return false;
150 out = events.front();
151 events.erase(events.begin());
158 line.clear(); eventData.clear(); events.clear();
159 haveData =
false; done =
false; error =
false;
163 static const size_t MAX_LINE = 1024 * 1024;
165 void feedByte(
char c) {
166 if (c ==
'\n') { processLine(); line.clear();
return; }
168 if (line.size() > MAX_LINE) error =
true;
173 if (!line.empty() && line[line.size()-1] ==
'\r') line.erase(line.size()-1);
176 if (eventData ==
"[DONE]") done =
true;
177 else events.push_back(eventData);
179 eventData.clear(); haveData =
false;
182 if (line.compare(0, 5,
"data:") == 0) {
184 if (start < line.size() && line[start] ==
' ') start++;
185 if (haveData) eventData +=
'\n';
186 eventData += line.substr(start);
193 std::string eventData;
195 std::vector<std::string> events;
228template<
class Connection>
232 : con(c), timeout(timeoutMS) {}
234 unsigned int size = 0;
235 bool ok = con.receiveAvailable(buf, size, (
unsigned int)maxSize, timeout);
236 if (ok && size > 0) { got = size;
return SRC_DATA; }
241 unsigned int timeout;
257 const std::function<
void(
const char*,
size_t)>& onData,
258 size_t maxIterations = 100000,
size_t readSize = 4096) {
259 std::vector<char> buf(readSize);
260 size_t delivered = dec.
body().size();
261 for (
size_t iter = 0; iter < maxIterations; iter++) {
268 const std::string& body = dec.
body();
269 if (onData && body.size() > delivered)
270 onData(body.data() + delivered, body.size() - delivered);
271 delivered = body.size();
283 const std::function<
void(
const std::string&)>& onEvent,
284 size_t maxIterations = 100000,
size_t readSize = 4096) {
285 std::vector<char> buf(readSize);
286 for (
size_t iter = 0; iter < maxIterations; iter++) {
293 while (parser.
nextEvent(ev)) {
if (onEvent) onEvent(ev); }
297 while (parser.
nextEvent(ev)) {
if (onEvent) onEvent(ev); }
325 bool feed(
const char* data,
size_t count) {
326 if (error)
return false;
327 if (buf.size() + count > MAX_BUFFER) { error =
true;
return false; }
328 buf.append(data, count);
330 while (!error && tryParseFrame()) {
331 if (++guard > MAX_FRAMES_PER_FEED) { error =
true;
break; }
335 bool feed(
const std::string& data) {
return feed(data.data(), data.size()); }
340 if (frames.empty())
return false;
341 out = frames.front();
342 frames.erase(frames.begin());
347 void reset() { buf.clear(); frames.clear(); error =
false; }
350 static const size_t MAX_BUFFER = 16 * 1024 * 1024;
351 static const size_t MAX_FRAMES_PER_FEED = 100000;
352 static const size_t PRELUDE_SIZE = 12;
353 static const size_t MIN_FRAME = 16;
355 static uint32_t be32(
const unsigned char* p) {
356 return ((uint32_t)p[0] << 24) | ((uint32_t)p[1] << 16) |
357 ((uint32_t)p[2] << 8) | (uint32_t)p[3];
359 static uint16_t be16(
const unsigned char* p) {
360 return (uint16_t)(((uint16_t)p[0] << 8) | (uint16_t)p[1]);
364 static bool crcMatches(
const unsigned char* data,
size_t len,
365 const unsigned char* wireCrc) {
368 unsigned char computed[4];
370 return memcmp(computed, wireCrc, 4) == 0;
376 bool tryParseFrame() {
377 if (buf.size() < PRELUDE_SIZE)
return false;
378 const unsigned char* p = (
const unsigned char*)buf.data();
379 uint32_t totalLen = be32(p);
380 uint32_t headersLen = be32(p + 4);
383 if (!crcMatches(p, 8, p + 8)) { error =
true;
return false; }
384 if (totalLen < MIN_FRAME || totalLen > MAX_BUFFER ||
385 (
size_t)headersLen > (
size_t)totalLen - MIN_FRAME)
386 { error =
true;
return false; }
387 if (buf.size() < totalLen)
return false;
390 if (!crcMatches(p, (
size_t)totalLen - 4, p + totalLen - 4))
391 { error =
true;
return false; }
394 if (!parseHeaders(p + PRELUDE_SIZE, headersLen, f.eventType))
395 { error =
true;
return false; }
396 size_t payloadLen = (size_t)totalLen - MIN_FRAME - headersLen;
397 f.
payload.assign(buf.data() + PRELUDE_SIZE + headersLen, payloadLen);
399 buf.erase(0, totalLen);
406 bool parseHeaders(
const unsigned char* h,
size_t len, std::string& eventType) {
407 size_t pos = 0, guard = 0;
409 if (++guard > 1000)
return false;
410 size_t keyLen = h[pos++];
411 if (pos + keyLen + 1 > len)
return false;
412 std::string key((
const char*)h + pos, keyLen);
414 unsigned char type = h[pos++];
417 case 0:
case 1: valLen = 0;
break;
418 case 2: valLen = 1;
break;
419 case 3: valLen = 2;
break;
420 case 4: valLen = 4;
break;
421 case 5:
case 8: valLen = 8;
break;
423 if (pos + 2 > len)
return false;
424 valLen = be16(h + pos); pos += 2;
426 case 9: valLen = 16;
break;
427 default:
return false;
429 if (pos + valLen > len)
return false;
430 if (type == 7 && key ==
":event-type")
431 eventType.assign((
const char*)h + pos, valLen);
438 std::vector<Frame> frames;
449 size_t maxIterations = 100000,
size_t readSize = 4096) {
450 std::vector<char> buf(readSize);
451 for (
size_t iter = 0; iter < maxIterations; iter++) {
458 while (parser.
nextFrame(f)) {
if (onFrame) onFrame(f); }
462 while (parser.
nextFrame(f)) {
if (onFrame) onFrame(f); }
ConnectionByteSource(Connection &c, unsigned int timeoutMS)
StreamReadResult read(char *buf, size_t maxSize, size_t &got)
bool nextFrame(Frame &out)
bool feed(const char *data, size_t count)
bool feed(const std::string &data)
bool feed(const char *data, size_t count)
const std::string & body() const
bool feed(const std::string &data)
bool nextEvent(std::string &out)
bool feed(const char *data, size_t count)
bool feed(const std::string &data)
virtual ~StreamByteSource()
virtual StreamReadResult read(char *buf, size_t maxSize, size_t &got)=0
std::string getHash()
return latest hash as 8 hex characters
void add(const void *data, size_t numBytes)
add arbitrary number of bytes
Third-party (vendored): CRC32 checksum from Stephan Brumme's portable hashing library (create....
StreamPumpResult pumpChunkedStream(StreamByteSource &src, HTTPChunkedDecoder &dec, const std::function< void(const char *, size_t)> &onData, size_t maxIterations=100000, size_t readSize=4096)
StreamPumpResult pumpSSEStream(StreamByteSource &src, SSEEventParser &parser, const std::function< void(const std::string &)> &onEvent, size_t maxIterations=100000, size_t readSize=4096)
StreamPumpResult pumpEventStream(StreamByteSource &src, EventStreamFrameParser &parser, const std::function< void(const EventStreamFrameParser::Frame &)> &onFrame, size_t maxIterations=100000, size_t readSize=4096)