REDAC HybridController
Firmware for LUCIDAC/REDAC Teensy
Loading...
Searching...
No Matches
jsonl_server.cpp
Go to the documentation of this file.
1// Copyright (c) 2024 anabrid GmbH
2// Contact: https://www.anabrid.com/licensing/
3//
4// SPDX-License-Identifier: MIT OR GPL-2.0-or-later
5
6#include "proto/main.pb.h"
7#include "protocol/jsonl_server.h"
8
9#include "net/ethernet.h"
10#include "protocol/protocol.h"
11#include "utils/logging.h"
12
13void msg::ApplicationServer::begin() {
14 server.begin(net::StartupConfig::get().jsonl_port);
15}
16
17FASTRUN
18void msg::ApplicationServer::_accept_clients() {
19 net::EthernetClient client_socket = server.accept();
20
21 if (!client_socket) return;
22 auto remote_ip = client_socket.remoteIP();
23
24 // note there is also net::EthernetClient::maxSockets(), which is dominated by basic system constraints.
25 // This limit here is rather dominated by application level constraints and can probably be a counter
26 // measure against ddos attacks.
27 if (clients.size() == net::StartupConfig::get().max_connections) {
28 LOG5("Cannot accept client from ", remote_ip, " because maximum number of connections (",
29 net::StartupConfig::get().max_connections, ") already reached.");
30 client_socket.stop();
31 return;
32 }
33
34
35 // note that the following code copies "socket" object multiple times. When using pointers into
36 // the struct, do not use the pointer to the wrong version.
37 // TODO: Clean up code.
38 auto socket = std::make_shared<net::EthernetClient>(std::move(client_socket));
39
40 LOG4("Client ", static_cast<unsigned>(clients.size()), " connected from ", remote_ip);
41 auto& client = clients.emplace_back(ApplicationClient{
42 .socket = socket,
43 .transport = transport::Transport(
44 std::make_shared<transport::DelimitedInputStream<std::shared_ptr<Client>>>(socket),
45 std::make_shared<transport::DelimitedMessageOutputStream<std::shared_ptr<Client>>>(socket),
46 std::make_shared<transport::DelimitedMessageOutputStream<std::shared_ptr<Client>>>(socket),
47 remote_ip
48 ),
49 });
50
51 client.user_context.set_remote_identifier(net::auth::RemoteIdentifier{remote_ip});
52}
53
54FASTRUN
55void msg::ApplicationServer::_handle_clients() {
56 // using iterator instead range-based loop because EthernetClient lacks == operator
57 // so we use list::erase instead of list::remove.
58 for (auto it = clients.begin(); it != clients.end(); ++it) {
59 auto& client = *it;
60 auto& socket = client.socket;
61
62 if (socket->connected()) {
63 if (socket->available() > 0) {
64 Broker::get().process(client.transport);
65 //client.last_contact.reset();
66 }/* else if (client.last_contact.expired(net::StartupConfig::get().connection_timeout_ms)) {
67 LOG3("Client timed out after ",
68 net::StartupConfig::get().connection_timeout_ms, " ms of idling");
69 socket->stop();
70 }*/
71 } else {
72 LOG3("Client was ", client.user_context, ", disconnected");
73 socket->stop(); // important, stop waits
74 clients.erase(it);
75 return; // iterator invalidated, better start loop() freshly.
76 }
77 }
78}
79
80FASTRUN
81void msg::ApplicationServer::loop() {
82 _accept_clients();
83 _handle_clients();
84}