Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support multiple HTTP connections #4

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion amp-embedded-infra-lib
Submodule amp-embedded-infra-lib updated 71 files
+1 −1 .clusterfuzzlite/Dockerfile
+1 −1 .devcontainer/Dockerfile
+1 −8 .devcontainer/devcontainer.json
+0 −0 .github/CODE_OF_CONDUCT.md
+43 −2 .github/CONTRIBUTING.md
+15 −0 .github/SECURITY.md
+0 −43 .github/linters/goodcheck.yml
+0 −17 .github/matchers/gcc-problem-matcher.json
+0 −18 .github/matchers/msvc-problem-matcher.json
+13 −18 .github/workflows/ci.yml
+2 −2 .github/workflows/documentation.yml
+2 −2 .github/workflows/linting-formatting.yml
+1 −2 .github/workflows/release-please.yml
+1 −1 .github/workflows/security.yml
+5 −1 .github/workflows/social-interaction.yml
+5 −18 .github/workflows/static-analysis.yml
+35 −7 .github/workflows/validate-pr.yml
+0 −1 .mega-linter.yml
+1 −1 .release-please-manifest.json
+29 −0 CHANGELOG.md
+1 −1 CMakeLists.txt
+1 −1 README.md
+0 −12 SECURITY.md
+1 −1 documents/antora.yml
+0 −2 external/crypto/micro-ecc/CMakeLists.txt
+0 −2 external/segger_rtt/CMakeLists.txt
+22 −0 hal/interfaces/AdcMultiChannel.hpp
+1 −1 hal/interfaces/CMakeLists.txt
+0 −42 hal/interfaces/Can.cpp
+60 −10 hal/interfaces/Can.hpp
+53 −6 hal/interfaces/test/TestCan.cpp
+17 −0 hal/interfaces/test_doubles/AdcMultiChannelMock.hpp
+18 −0 hal/interfaces/test_doubles/AdcMultiChannelStub.cpp
+24 −0 hal/interfaces/test_doubles/AdcMultiChannelStub.hpp
+3 −0 hal/interfaces/test_doubles/CMakeLists.txt
+17 −1 infra/event/QueueForOneReaderOneIrqWriter.hpp
+4 −8 infra/stream/StreamWriterFile.cpp
+2 −2 infra/stream/StreamWriterFile.hpp
+1 −0 infra/stream/test/CMakeLists.txt
+69 −0 infra/stream/test/TestStreamWriterFile.cpp
+25 −23 infra/util/BoundedString.hpp
+1 −0 infra/util/SharedObjectAllocator.hpp
+10 −1 infra/util/SharedObjectAllocatorFixedSize.hpp
+69 −3 infra/util/SharedObjectAllocatorHeap.hpp
+3 −0 infra/util/test/TestBoundedString.cpp
+3 −3 protobuf/echo/TracingEcho.hpp
+1 −1 protobuf/echo/protocol_buffer_echo.cmake
+2 −2 services/network/SingleConnectionListener.cpp
+2 −2 services/network/SingleConnectionListener.hpp
+5 −0 services/network/TracingConnectionMbedTls.cpp
+1 −0 services/network/TracingConnectionMbedTls.hpp
+5 −5 services/network/test/TestSingleConnectionListener.cpp
+2 −2 services/network_instantiations/EchoInstantiation.cpp
+7 −0 services/tracer/CMakeLists.txt
+2 −2 services/tracer/TracingEchoInstantiation.hpp
+1 −0 services/tracer/TracingEchoInstantiationSecured.cpp
+42 −0 services/tracer/TracingEchoInstantiationSecured.hpp
+2 −0 services/util/CMakeLists.txt
+2 −2 services/util/EchoInstantiation.hpp
+1 −0 services/util/EchoInstantiationSecured.cpp
+47 −0 services/util/EchoInstantiationSecured.hpp
+1 −1 services/util/EchoOnSesameSymmetricKey.cpp
+1 −1 services/util/EchoOnSesameSymmetricKey.hpp
+5 −5 services/util/SesameSecured.cpp
+9 −1 services/util/SesameSecured.hpp
+7 −6 services/util/Terminal.cpp
+14 −5 services/util/Terminal.hpp
+2 −2 services/util/test/TestEchoOnSesameSymmetricKey.cpp
+1 −1 services/util/test/TestSesameSecured.cpp
+5 −4 services/util/test/TestTerminal.cpp
+1 −1 sonar-project.properties
96 changes: 88 additions & 8 deletions postmaster/frontend/ReportingHttpServer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,93 @@ namespace application
reporter(false, services::IPAddress());
}

ReportingHttpServer::ReportingHttpServer(infra::BoundedString& buffer, services::ConnectionFactory& connectionFactory, uint16_t port, const infra::Function<void(bool open, services::IPAddress address)>& reporter)
: SingleConnectionListener(connectionFactory, port, { connectionCreator })
ReportingHttpServer::ReportingHttpServer(ConnectionAllocator& allocator, services::ConnectionFactory& connectionFactory, uint16_t port, const infra::Function<void(bool open, services::IPAddress address)>& reporter)
: connectionAllocator(allocator)
, reporter(reporter)
, buffer(buffer)
, connectionCreator([this](infra::Optional<ReportingHttpServerConnectionObserver>& value, services::IPAddress address)
{
value.Emplace(this->buffer, *this, this->reporter, address);
})
{}
{
listener = connectionFactory.Listen(port, *this, services::IPVersions::both);
}

void ReportingHttpServer::Stop(const infra::Function<void()>& onDone, bool force)
{
listener = nullptr;
waitingCreatedObserver = nullptr;

StopConnections(onDone, force);
}

void ReportingHttpServer::SetNewConnectionStrategy(services::NewConnectionStrategy& newConnectionStrategy)
{
this->newConnectionStrategy = &newConnectionStrategy;
}

void ReportingHttpServer::StopCurrentConnection(void* listener)
{
StopConnections([this]()
{
newConnectionStrategy->StartNewConnection();
},
false);
}

void ReportingHttpServer::StartNewConnection()
{
connectionAllocator.OnAllocatable(nullptr);
auto connectionObserver = connectionAllocator.Allocate(*this, reporter, waitingAddress);
if (connectionObserver != nullptr)
waitingCreatedObserver(connectionObserver);
else
{
connectionAllocator.OnAllocatable([this]()
{
newConnectionStrategy->StartNewConnection();
});

CloseOrAbortAllConnections(false);
}
}

void ReportingHttpServer::ConnectionAccepted(infra::AutoResetFunction<void(infra::SharedPtr<services::ConnectionObserver> connectionObserver)>&& createdObserver, services::IPAddress address)
{
waitingCreatedObserver = std::move(createdObserver);
waitingAddress = address;

newConnectionStrategy->StartNewConnection();
}

void ReportingHttpServer::StopConnections(const infra::Function<void()>& onDone, bool force)
{
onStopConnectionsDone = onDone;

if (connectionAllocator.NoneAllocated())
onStopConnectionsDone();
else
connectionAllocator.OnAllocatable([this, force]()
{
StopConnections(onStopConnectionsDone, force);
});

CloseOrAbortAllConnections(force);
}

void ReportingHttpServer::CloseOrAbortAllConnections(bool force)
{
for (auto& connection : connections)
if (force)
connection.Abort();
else
connection.Close();
}

ReportingHttpServer::Connection::Connection(ReportingHttpServer& httpServer, const infra::Function<void(bool open, services::IPAddress address)>& reporter, services::IPAddress address)
: ReportingHttpServerConnectionObserver::WithBuffer<BufferSize>(httpServer, reporter, address)
, httpServer(httpServer)
{
httpServer.connections.push_back(*this);
}

ReportingHttpServer::Connection::~Connection()
{
httpServer.connections.erase(*this);
}
}
64 changes: 57 additions & 7 deletions postmaster/frontend/ReportingHttpServer.hpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#ifndef POSTMASTER_REPORTING_HTTP_SERVER_HPP
#define POSTMASTER_REPORTING_HTTP_SERVER_HPP

#include "infra/util/IntrusiveList.hpp"
#include "infra/util/SharedObjectAllocatorFixedSize.hpp"
#include "services/network/HttpServer.hpp"

namespace application
Expand All @@ -9,6 +11,10 @@ namespace application
: public services::HttpServerConnectionObserver
{
public:
template<size_t BufferSize>
using WithBuffer = infra::WithStorage<ReportingHttpServerConnectionObserver,
infra::BoundedString::WithStorage<BufferSize>>;

ReportingHttpServerConnectionObserver(infra::BoundedString& buffer, HttpPageServer& httpServer, const infra::Function<void(bool open, services::IPAddress address)>& reporter, services::IPAddress address);
~ReportingHttpServerConnectionObserver();

Expand All @@ -17,19 +23,63 @@ namespace application
};

class ReportingHttpServer
: public services::SingleConnectionListener
, public services::HttpPageServer
: public services::HttpPageServer
, public services::NewConnectionStrategy
, private services::ServerConnectionObserverFactory
{
public:
template<::size_t BufferSize>
using WithBuffer = infra::WithStorage<ReportingHttpServer, infra::BoundedString::WithStorage<BufferSize>>;
static constexpr std::size_t BufferSize = 8192;

class Connection
: public infra::IntrusiveList<Connection>::NodeType
, public ReportingHttpServerConnectionObserver::WithBuffer<BufferSize>
{
public:
Connection(ReportingHttpServer& httpServer, const infra::Function<void(bool open, services::IPAddress address)>& reporter, services::IPAddress address);
Connection(const Connection& other) = delete;
Connection& operator=(const Connection& other) = delete;
~Connection();

private:
ReportingHttpServer& httpServer;
};

using ConnectionAllocator = infra::SharedObjectAllocator<Connection, void(ReportingHttpServer& httpServer, const infra::Function<void(bool open, services::IPAddress address)>& reporter, services::IPAddress address)>;

using ConnectionAllocatorFixedSize = infra::SharedObjectAllocatorFixedSize<Connection,
void(ReportingHttpServer& httpServer, const infra::Function<void(bool open, services::IPAddress address)>& reporter, services::IPAddress address)>;

template<std::size_t Connections>
using WithConnections = infra::WithStorage<ReportingHttpServer, typename ConnectionAllocatorFixedSize::template WithStorage<Connections>>;

ReportingHttpServer(ConnectionAllocator& allocator, services::ConnectionFactory& connectionFactory, uint16_t port, const infra::Function<void(bool open, services::IPAddress address)>& reporter);

ReportingHttpServer(infra::BoundedString& buffer, services::ConnectionFactory& connectionFactory, uint16_t port, const infra::Function<void(bool open, services::IPAddress address)>& reporter);
void Stop(const infra::Function<void()>& onDone, bool force);
void SetNewConnectionStrategy(services::NewConnectionStrategy& newConnectionStrategy);

// Implementation of NewConnectionStrategy
void StopCurrentConnection(void* listener) override;
void StartNewConnection() override;

private:
// Implementation of ServerConnectionObserverFactory
void ConnectionAccepted(infra::AutoResetFunction<void(infra::SharedPtr<services::ConnectionObserver> connectionObserver)>&& createdObserver, services::IPAddress address) override;

void StopConnections(const infra::Function<void()>& onDone, bool force);
void CloseOrAbortAllConnections(bool force);

private:
services::NewConnectionStrategy* newConnectionStrategy = this;
infra::Function<void(bool open, services::IPAddress address)> reporter;
infra::BoundedString& buffer;
infra::Creator<services::ConnectionObserver, ReportingHttpServerConnectionObserver, void(services::IPAddress address)> connectionCreator;
infra::SharedPtr<void> listener;

ConnectionAllocator& connectionAllocator;
infra::IntrusiveList<Connection> connections;

infra::AutoResetFunction<void(infra::SharedPtr<services::ConnectionObserver> connectionObserver)> waitingCreatedObserver;
services::IPAddress waitingAddress;

infra::Function<void()> onStopConnectionsDone;
};
}

Expand Down
14 changes: 7 additions & 7 deletions postmaster/instantiations/EchoServer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,24 +21,24 @@ namespace main_
return echoConnection;
}

SingleConnectionLink::SingleConnectionLink(services::SingleConnectionListener& listener1, services::SingleConnectionListener& listener2)
SingleConnectionLink::SingleConnectionLink(application::ReportingHttpServer& listener1, services::SingleConnectionListener& listener2)
: listener1(listener1)
, listener2(listener2)
{
listener1.SetNewConnectionStrategy(*this);
listener2.SetNewConnectionStrategy(*this);
}

void SingleConnectionLink::StopCurrentConnection(services::SingleConnectionListener& listener)
void SingleConnectionLink::StopCurrentConnection(void* listener)
{
if (&listener == &listener1)
if (listener == &listener1)
listener1RequestedNewConnection = true;
if (&listener == &listener2)
if (listener == &listener2)
listener2RequestedNewConnection = true;

numStopped = 0;
listener1.StopCurrentConnection(listener1);
listener2.StopCurrentConnection(listener2);
listener1.StopCurrentConnection(&listener1);
listener2.StopCurrentConnection(&listener2);
}

void SingleConnectionLink::StartNewConnection()
Expand All @@ -53,7 +53,7 @@ namespace main_
listener1.StartNewConnection();

if (listener2RequestedNewConnection)
StopCurrentConnection(listener1);
StopCurrentConnection(&listener1);
}
else if (listener2RequestedNewConnection)
{
Expand Down
7 changes: 4 additions & 3 deletions postmaster/instantiations/EchoServer.hpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#include "postmaster/frontend/ReportingHttpServer.hpp"
#include "postmaster/instantiations/UartCreator.hpp"
#include "protobuf/echo/ServiceForwarder.hpp"
#include "services/network/Connection.hpp"
Expand Down Expand Up @@ -42,15 +43,15 @@ namespace main_
: private services::NewConnectionStrategy
{
public:
SingleConnectionLink(services::SingleConnectionListener& listener1, services::SingleConnectionListener& listener2);
SingleConnectionLink(application::ReportingHttpServer& listener1, services::SingleConnectionListener& listener2);

private:
void StopCurrentConnection(services::SingleConnectionListener& listener) override;
void StopCurrentConnection(void* listener) override;
void StartNewConnection() override;

private:
uint32_t numStopped = 0;
services::SingleConnectionListener& listener1;
application::ReportingHttpServer& listener1;
services::SingleConnectionListener& listener2;

bool listener1RequestedNewConnection = false;
Expand Down
16 changes: 12 additions & 4 deletions postmaster/instantiations/HttpServer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,21 @@

namespace main_
{
HttpServer::HttpServer(services::ConnectionFactory& connectionFactory, services::ConfigurationStoreAccess<infra::BoundedString>& hostname,
HttpServer::HttpServer(application::ReportingHttpServer::ConnectionAllocator& allocator, services::ConnectionFactory& connectionFactory, uint16_t port, services::ConfigurationStoreAccess<infra::BoundedString>& hostname,
services::ConfigurationStoreAccess<infra::BoundedString>& attributes, services::ConfigurationStoreAccess<infra::BoundedString>& password,
application::Authentication& authentication, application::PostmasterDiscovery& postmasterDiscovery,
UartCreator& uartProgrammerCreator, UartCreator& uartExternalCreator, hal::Flash& upgradeFlash, hal::Reset& reset, const infra::Function<void(bool open, services::IPAddress address)>& reporter, const infra::Function<void(bool receiving)>& receivingTarget, const infra::Function<void(bool receiving)>& receivingSelf, hal::GpioPin& resetTarget, hal::GpioPin& boot0)
: HttpServerFrontEnd(connectionFactory, hostname, attributes, password, authentication, reporter, receivingTarget, receivingSelf)
const infra::Function<void(bool open, services::IPAddress address)>& reporter, const infra::Function<void(bool receiving)>& receivingTarget, const infra::Function<void(bool receiving)>& receivingSelf)
: HttpServerFrontEnd(allocator, connectionFactory, port, hostname, attributes, password, authentication, reporter, receivingTarget, receivingSelf)
, discovery("discovery", postmasterDiscovery)
{
server.AddPage(discovery);
}

HttpServerSingleConnection::HttpServerSingleConnection(services::ConnectionFactory& connectionFactory, uint16_t port, services::ConfigurationStoreAccess<infra::BoundedString>& hostname,
services::ConfigurationStoreAccess<infra::BoundedString>& attributes, services::ConfigurationStoreAccess<infra::BoundedString>& password,
application::Authentication& authentication, application::PostmasterDiscovery& postmasterDiscovery,
UartCreator& uartProgrammerCreator, UartCreator& uartExternalCreator, hal::Flash& upgradeFlash, hal::Reset& reset, const infra::Function<void(bool open, services::IPAddress address)>& reporter, const infra::Function<void(bool receiving)>& receivingTarget, const infra::Function<void(bool receiving)>& receivingSelf, hal::GpioPin& resetTarget, hal::GpioPin& boot0)
: HttpServer::WithConnections<1>(connectionFactory, port, hostname, attributes, password, authentication, postmasterDiscovery, reporter, receivingTarget, receivingSelf)
, uartProgrammerCreator(uartProgrammerCreator)
, uartExternalCreator(uartExternalCreator)
, selfFirmwarePage{ authentication, "firmware/self" }
Expand All @@ -25,6 +34,5 @@ namespace main_
server.AddPage(targetUartExternal.page);
server.AddPage(targetUartEchoProgrammer.page);
server.AddPage(targetUartEchoExternal.page);
server.AddPage(discovery);
}
}
17 changes: 15 additions & 2 deletions postmaster/instantiations/HttpServer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,28 @@ namespace main_
struct HttpServer
: public HttpServerFrontEnd
{
HttpServer(services::ConnectionFactory& connectionFactory, services::ConfigurationStoreAccess<infra::BoundedString>& hostname,
template<std::size_t Connections>
using WithConnections = infra::WithStorage<HttpServer, application::ReportingHttpServer::ConnectionAllocatorFixedSize::WithStorage<Connections>>;

HttpServer(application::ReportingHttpServer::ConnectionAllocator& allocator, services::ConnectionFactory& connectionFactory, uint16_t port, services::ConfigurationStoreAccess<infra::BoundedString>& hostname,
services::ConfigurationStoreAccess<infra::BoundedString>& attributes, services::ConfigurationStoreAccess<infra::BoundedString>& password,
application::Authentication& authentication, application::PostmasterDiscovery& postmasterDiscovery,
const infra::Function<void(bool open, services::IPAddress address)>& reporter, const infra::Function<void(bool receiving)>& receivingTarget, const infra::Function<void(bool receiving)>& receivingSelf);

application::HttpPageDiscovery discovery;
};

struct HttpServerSingleConnection
: public HttpServer::WithConnections<1>
{
HttpServerSingleConnection(services::ConnectionFactory& connectionFactory, uint16_t port, services::ConfigurationStoreAccess<infra::BoundedString>& hostname,
services::ConfigurationStoreAccess<infra::BoundedString>& attributes, services::ConfigurationStoreAccess<infra::BoundedString>& password,
application::Authentication& authentication, application::PostmasterDiscovery& postmasterDiscovery,
UartCreator& uartProgrammerCreator, UartCreator& uartExternalCreator, hal::Flash& upgradeFlash, hal::Reset& reset, const infra::Function<void(bool open, services::IPAddress address)>& reporter, const infra::Function<void(bool receiving)>& receivingTarget, const infra::Function<void(bool receiving)>& receivingSelf, hal::GpioPin& resetTarget, hal::GpioPin& boot0);

UartCreator& uartProgrammerCreator;
UartCreator& uartExternalCreator;

application::HttpPageDiscovery discovery;
application::AuthenticatedHttpPage::WithPage<application::HttpPageFirmware> selfFirmwarePage;
main_::SelfProgrammer selfProgrammer;

Expand Down
4 changes: 2 additions & 2 deletions postmaster/instantiations/HttpServerFrontEnd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@

namespace main_
{
HttpServerFrontEnd::HttpServerFrontEnd(services::ConnectionFactory& connectionFactory, services::ConfigurationStoreAccess<infra::BoundedString>& hostname,
HttpServerFrontEnd::HttpServerFrontEnd(application::ReportingHttpServer::ConnectionAllocator& allocator, services::ConnectionFactory& connectionFactory, uint16_t port, services::ConfigurationStoreAccess<infra::BoundedString>& hostname,
services::ConfigurationStoreAccess<infra::BoundedString>& attributes, services::ConfigurationStoreAccess<infra::BoundedString>& password, application::Authentication& authentication,
const infra::Function<void(bool open, services::IPAddress address)>& reporter, const infra::Function<void(bool receiving)>& receivingTarget,
const infra::Function<void(bool receiving)>& receivingSelf)
: configuration{ authentication, "configuration", hostname, attributes, password }
, server{ connectionFactory, 80, reporter }
, server{ allocator, connectionFactory, port, reporter }
{
server.AddPage(frontendHtml);
server.AddPage(frontendCss);
Expand Down
9 changes: 4 additions & 5 deletions postmaster/instantiations/HttpServerFrontEnd.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,23 +13,22 @@
namespace main_
{
struct HttpServerFrontEnd
: public services::Stoppable
{
HttpServerFrontEnd(services::ConnectionFactory& connectionFactory, services::ConfigurationStoreAccess<infra::BoundedString>& hostname,
HttpServerFrontEnd(application::ReportingHttpServer::ConnectionAllocator& allocator, services::ConnectionFactory& connectionFactory, uint16_t port, services::ConfigurationStoreAccess<infra::BoundedString>& hostname,
services::ConfigurationStoreAccess<infra::BoundedString>& attributes, services::ConfigurationStoreAccess<infra::BoundedString>& password,
application::Authentication& authentication, const infra::Function<void(bool open, services::IPAddress address)>& reporter, const infra::Function<void(bool receiving)>& receivingTarget, const infra::Function<void(bool receiving)>& receivingSelf);

void Stop(const infra::Function<void()>& onDone) override
void Stop(const infra::Function<void()>& onDone)
{
server.Stop(onDone);
server.Stop(onDone, true);
}

services::HttpPageWithContent frontendHtml{ "", page_contents::indexHtml, "text/html;charset=UTF-8" };
services::HttpPageWithContent frontendCss{ "style.css", page_contents::styleCss, "text/css" };
services::HttpPageWithContent frontendJs{ "upload.js", page_contents::uploadJs, "text/javascript" };
application::AuthenticatedHttpPage::WithPage<application::HttpPageConfiguration> configuration;

application::ReportingHttpServer::WithBuffer<8192> server;
application::ReportingHttpServer server;
};
}

Expand Down
2 changes: 1 addition & 1 deletion postmaster/instantiations_st/EthernetPostmaster.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ namespace main_
application::Authentication authentication;
infra::Creator<services::Stoppable, main_::NetworkConnected, void(services::LightweightIp& lightweightIp)> networkCreator;

main_::Ethernet<3, 0, 4> ethernet;
main_::Ethernet<4, 0, 9> ethernet;
};
}

Expand Down
2 changes: 1 addition & 1 deletion postmaster/instantiations_st/HttpServerSt.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
namespace main_
{
struct HttpServerSt
: public HttpServer
: public HttpServerSingleConnection
{
HttpServerSt(services::ConnectionFactory& connectionFactory, services::ConfigurationStoreAccess<infra::BoundedString>& hostname,
services::ConfigurationStoreAccess<infra::BoundedString>& attributes, services::ConfigurationStoreAccess<infra::BoundedString>& password,
Expand Down
Loading
Loading