Fork of the espurna firmware for `mhsw` switches
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

87 lines
2.8 KiB

6 years ago
  1. /*
  2. WebSocketIncommingBuffer
  3. Code by Hermann Kraus (https://bitbucket.org/hermr2d2/)
  4. and slightly modified.
  5. */
  6. #pragma once
  7. #define MAX_WS_MSG_SIZE 4000
  8. typedef std::function<void(AsyncWebSocketClient *client, uint8_t *data, size_t len)> AwsMessageHandler;
  9. class WebSocketIncommingBuffer {
  10. public:
  11. WebSocketIncommingBuffer(AwsMessageHandler cb, bool terminate_string = true, bool cb_on_fragments = false) :
  12. _cb(cb),
  13. _terminate_string(terminate_string),
  14. _cb_on_fragments(cb_on_fragments),
  15. _buffer(0)
  16. {}
  17. ~WebSocketIncommingBuffer() {
  18. if (_buffer) delete _buffer;
  19. }
  20. void data_event(AsyncWebSocketClient *client, AwsFrameInfo *info, uint8_t *data, size_t len) {
  21. if ((info->final || _cb_on_fragments)
  22. && !_terminate_string
  23. && info->index == 0
  24. && info->len == len) {
  25. /* The whole message is in a single frame and we got all of it's
  26. data therefore we can parse it without copying the data first.*/
  27. _cb(client, data, len);
  28. } else {
  29. if (info->len > MAX_WS_MSG_SIZE) return;
  30. /* Check if previous fragment was discarded because it was too long. */
  31. //if (!_cb_on_fragments && info->num > 0 && !_buffer) return;
  32. if (!_buffer) _buffer = new std::vector<uint8_t>();
  33. if (info->index == 0) {
  34. //New frame => preallocate memory
  35. if (_cb_on_fragments) {
  36. _buffer->reserve(info->len + 1);
  37. } else {
  38. /* The current fragment would lead to a message which is
  39. too long. So discard everything received so far. */
  40. if (info->len + _buffer->size() > MAX_WS_MSG_SIZE) {
  41. delete _buffer;
  42. _buffer = 0;
  43. return;
  44. } else {
  45. _buffer->reserve(info->len + _buffer->size() + 1);
  46. }
  47. }
  48. }
  49. //assert(_buffer->size() == info->index);
  50. _buffer->insert(_buffer->end(), data, data+len);
  51. if (info->index + len == info->len
  52. && (info->final || _cb_on_fragments)) {
  53. // Frame/message complete
  54. if (_terminate_string) _buffer->push_back(0);
  55. _cb(client, _buffer->data(), _buffer->size());
  56. _buffer->clear();
  57. }
  58. }
  59. }
  60. private:
  61. AwsMessageHandler _cb;
  62. bool _terminate_string;
  63. bool _cb_on_fragments;
  64. std::vector<uint8_t> *_buffer;
  65. };