3#ifdef FASTLED_HAS_NETWORKING
16HttpStreamServer::HttpStreamServer(u16 port, u32 heartbeatIntervalMs)
19 , mLastProcessedClientId(0) {
21 ConnectionConfig config;
25 mRecvBuffer.reserve(16384);
32bool HttpStreamServer::connect() {
39 if (!mNativeServer->start()) {
44 mConnection.onConnected();
49void HttpStreamServer::disconnect() {
51 mNativeServer->stop();
53 mClientStates.clear();
54 mConnection.onDisconnected();
57bool HttpStreamServer::isConnected()
const {
58 return mNativeServer && mNativeServer->isListening();
61u16 HttpStreamServer::port()
const {
62 return mNativeServer ? mNativeServer->port() : 0;
65void HttpStreamServer::acceptClients() {
71 mNativeServer->acceptClients();
77 for (u32 clientId : clientIds) {
78 ClientState*
state = getOrCreateClientState(clientId);
84 if (!
state->httpHeaderReceived) {
85 if (readHttpRequestHeader(clientId)) {
87 if (!sendHttpResponseHeader(clientId)) {
89 disconnectClient(clientId);
99 for (
auto& pair : mClientStates) {
100 u32 clientId = pair.first;
102 for (u32 activeId : activeClientIds) {
103 if (activeId == clientId) {
113 for (u32 clientId : toRemove) {
114 removeClientState(clientId);
118size_t HttpStreamServer::getClientCount()
const {
119 return mNativeServer ? mNativeServer->getClientCount() : 0;
122void HttpStreamServer::disconnectClient(u32 clientId) {
124 mNativeServer->disconnectClient(clientId);
126 removeClientState(clientId);
130 return mNativeServer ? mNativeServer->getClientIds() :
fl::vector<u32>();
134 if (!isConnected()) {
139 mNativeServer->broadcast(data);
140 return static_cast<int>(data.
size());
144 if (!isConnected()) {
150 if (clientIds.
empty()) {
157 for (
size_t i = 0; i < clientIds.
size(); i++) {
158 if (clientIds[i] == mLastProcessedClientId) {
159 startIdx = (i + 1) % clientIds.
size();
166 size_t idx = (startIdx +
offset) % clientIds.
size();
167 u32 clientId = clientIds[idx];
169 ClientState*
state = getOrCreateClientState(clientId);
175 int received = mNativeServer->recv(clientId, buffer);
177 mLastProcessedClientId = clientId;
185void HttpStreamServer::triggerReconnect() {
191bool HttpStreamServer::readHttpRequestHeader(u32 clientId) {
192 ClientState*
state = getOrCreateClientState(clientId);
197 if (
state->httpHeaderReceived) {
206 const size_t MAX_HEADER_SIZE = 8192;
208 while (
state->headerBuffer.size() < MAX_HEADER_SIZE) {
209 int received = mNativeServer->recv(clientId, buffer);
217 state->headerBuffer.append(
reinterpret_cast<const char*
>(buffer), received);
220 if (
state->headerBuffer.size() >= 4) {
221 size_t pos =
state->headerBuffer.find(
"\r\n\r\n");
233 if (hdr.
find(
"POST /rpc") != 0) {
249 state->httpHeaderReceived =
true;
253bool HttpStreamServer::sendHttpResponseHeader(u32 clientId) {
254 ClientState*
state = getOrCreateClientState(clientId);
259 if (
state->httpHeaderSent) {
265 header.
append(
"HTTP/1.1 200 OK\r\n");
266 header.
append(
"Content-Type: application/json\r\n");
267 header.
append(
"Transfer-Encoding: chunked\r\n");
268 header.
append(
"Connection: keep-alive\r\n");
273 if (sent !=
static_cast<int>(header.
size())) {
277 state->httpHeaderSent =
true;
281HttpStreamServer::ClientState* HttpStreamServer::getOrCreateClientState(u32 clientId) {
283 auto it = mClientStates.find(clientId);
284 if (it != mClientStates.end()) {
289 mClientStates.insert(
fl::make_pair(clientId, ClientState(clientId)));
292 it = mClientStates.find(clientId);
293 if (it != mClientStates.end()) {
300void HttpStreamServer::removeClientState(u32 clientId) {
301 auto it = mClientStates.find(clientId);
302 if (it != mClientStates.end()) {
303 mClientStates.erase(it);
fl::size find(const char &value) const FL_NOEXCEPT
const char * c_str() const FL_NOEXCEPT
fl::size size() const FL_NOEXCEPT
Base class for HTTP streaming transport Implements RequestSource and ResponseSink for Remote class Ma...
constexpr fl::size size() const FL_NOEXCEPT
string & append(const bitset_fixed< N > &bs) FL_NOEXCEPT
static constexpr fl::size npos
fl::size size() const FL_NOEXCEPT
bool empty() const FL_NOEXCEPT
void push_back(const T &value) FL_NOEXCEPT
fl::UISlider offset("Offset", 0.0f, 0.0f, 1.0f, 0.01f)
Centralized logging categories for FastLED hardware interfaces and subsystems.
fl::enable_if<!fl::is_array< T >::value, unique_ptr< T > >::type make_unique(Args &&... args) FL_NOEXCEPT
pair< typename fl::decay< T1 >::type, typename fl::decay< T2 >::type > make_pair(T1 &&t, T2 &&u) FL_NOEXCEPT
Base definition for an LED controller.