- /*
-
- Part of the WEBSOCKET MODULE
-
- Copyright (C) 2016-2019 by Xose Pérez <xose dot perez at gmail dot com>
- Copyright (C) 2019 by Maxim Prokhorov <prokhorov dot max at outlook dot com>
-
- */
-
- #pragma once
-
- #include "espurna.h"
- #include "ws.h"
-
- #include <IPAddress.h>
-
- #include <cstdint>
- #include <memory>
- #include <vector>
-
- // -----------------------------------------------------------------------------
- // WS authentication
- // -----------------------------------------------------------------------------
-
- struct WsTicket {
- IPAddress ip;
- unsigned long timestamp = 0;
- };
-
- // -----------------------------------------------------------------------------
- // WS callbacks
- // -----------------------------------------------------------------------------
-
- // The idea here is to bind either:
- // - constant 'callbacks' list as reference, which was registered via wsRegister()
- // - in-place callback / callbacks that will be moved inside this container
-
- struct WsPostponedCallbacks {
-
- public:
-
- enum class Mode {
- Sequence,
- All
- };
-
- WsPostponedCallbacks(uint32_t client_id, ws_on_send_callback_f&& cb) :
- client_id(client_id),
- timestamp(ESP.getCycleCount()),
- _storage(new ws_on_send_callback_list_t {std::move(cb)}),
- _callbacks(*_storage.get()),
- _current(_callbacks.begin()),
- _mode(Mode::All)
- {}
-
- WsPostponedCallbacks(uint32_t client_id, const ws_on_send_callback_f& cb) :
- client_id(client_id),
- timestamp(ESP.getCycleCount()),
- _storage(new ws_on_send_callback_list_t {cb}),
- _callbacks(*_storage.get()),
- _current(_callbacks.begin()),
- _mode(Mode::All)
- {}
-
- template <typename T>
- explicit WsPostponedCallbacks(T&& cb) :
- WsPostponedCallbacks(0, std::forward<T>(cb))
- {}
-
- WsPostponedCallbacks(const uint32_t client_id, const ws_on_send_callback_list_t& cbs, Mode mode = Mode::Sequence) :
- client_id(client_id),
- timestamp(ESP.getCycleCount()),
- _callbacks(cbs),
- _current(_callbacks.begin()),
- _mode(mode)
- {}
-
- WsPostponedCallbacks(const uint32_t client_id, ws_on_send_callback_list_t&& cbs, Mode mode = Mode::All) :
- client_id(client_id),
- timestamp(ESP.getCycleCount()),
- _storage(new ws_on_send_callback_list_t(std::move(cbs))),
- _callbacks(*_storage.get()),
- _current(_callbacks.begin()),
- _mode(mode)
- {}
-
- bool done() {
- return _current == _callbacks.end();
- }
-
- void sendAll(JsonObject& root) {
- _current = _callbacks.end();
- for (auto& callback : _callbacks) {
- callback(root);
- }
- }
-
- void sendCurrent(JsonObject& root) {
- if (_current == _callbacks.end()) return;
- (*_current)(root);
- ++_current;
- }
-
- void send(JsonObject& root) {
- switch (_mode) {
- case Mode::Sequence:
- sendCurrent(root);
- break;
- case Mode::All:
- sendAll(root);
- break;
- }
- }
-
- const uint32_t client_id;
- const decltype(ESP.getCycleCount()) timestamp;
-
- private:
-
- std::unique_ptr<ws_on_send_callback_list_t> _storage;
-
- const ws_on_send_callback_list_t& _callbacks;
- ws_on_send_callback_list_t::const_iterator _current;
-
- const Mode _mode;
-
- };
-
- // -----------------------------------------------------------------------------
- // Debug
- // -----------------------------------------------------------------------------
-
- struct WsDebug {
-
- using Message = std::pair<String, String>;
- using MsgList = std::vector<Message>;
-
- WsDebug(size_t capacity) :
- _flush(false),
- _current(0),
- _capacity(capacity)
- {
- _messages.reserve(_capacity);
- }
-
- void clear() {
- _messages.clear();
- _current = 0;
- _flush = false;
- }
-
- template <typename T = Message>
- void add(T&& message) {
- if (_current >= _capacity) {
- _flush = true;
- send(wsConnected());
- }
-
- _messages.emplace(_messages.begin() + _current, std::forward<T>(message));
- _flush = true;
- ++_current;
- }
-
- void add(const char* prefix, const char* message) {
- add(std::move(std::make_pair(prefix, message)));
- }
-
- void send(bool connected);
-
- private:
-
- bool _flush;
- size_t _current;
- const size_t _capacity;
- MsgList _messages;
-
- };
|