Mirror of espurna firmware for wireless switches and more
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.
 
 
 
 
 
 

133 lines
3.5 KiB

/*
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 <IPAddress.h>
#include <cstdint>
#include <memory>
#include <vector>
#include "system.h"
#include "ws.h"
// -----------------------------------------------------------------------------
// WS authentication
// -----------------------------------------------------------------------------
struct WsTicket {
using TimeSource = espurna::time::CoreClock;
IPAddress ip;
TimeSource::time_point timestamp{};
};
// -----------------------------------------------------------------------------
// 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
class WsPostponedCallbacks {
public:
using TimeSource = espurna::time::CpuClock;
enum class Mode {
Sequence,
All
};
WsPostponedCallbacks(uint32_t client_id, ws_on_send_callback_f&& cb) :
_client_id(client_id),
_timestamp(TimeSource::now()),
_mode(Mode::All),
_storage(new ws_on_send_callback_list_t {std::move(cb)}),
_callbacks(*_storage.get()),
_current(_callbacks.begin())
{}
WsPostponedCallbacks(uint32_t client_id, const ws_on_send_callback_f& cb) :
_client_id(client_id),
_timestamp(TimeSource::now()),
_mode(Mode::All),
_storage(new ws_on_send_callback_list_t {cb}),
_callbacks(*_storage.get()),
_current(_callbacks.begin())
{}
template <typename T>
explicit WsPostponedCallbacks(T&& cb) :
WsPostponedCallbacks(0, std::forward<T>(cb))
{}
WsPostponedCallbacks(uint32_t client_id, const ws_on_send_callback_list_t& cbs, Mode mode = Mode::Sequence) :
_client_id(client_id),
_timestamp(TimeSource::now()),
_mode(mode),
_callbacks(cbs),
_current(_callbacks.begin())
{}
WsPostponedCallbacks(uint32_t client_id, ws_on_send_callback_list_t&& cbs, Mode mode = Mode::All) :
_client_id(client_id),
_timestamp(TimeSource::now()),
_mode(mode),
_storage(new ws_on_send_callback_list_t(std::move(cbs))),
_callbacks(*_storage.get()),
_current(_callbacks.begin())
{}
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;
}
}
uint32_t id() const {
return _client_id;
}
TimeSource::time_point timestamp() const {
return _timestamp;
}
private:
uint32_t _client_id;
TimeSource::time_point _timestamp;
Mode _mode;
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;
};