|
| 1 | +#pragma once |
| 2 | + |
| 3 | +namespace arduino { namespace net { |
| 4 | + |
| 5 | +// In most arduino platforms Client classes are bound to a Network interface by inheritance |
| 6 | +// This because there is no routing mechanism that decouples the client from the lower level. |
| 7 | +// For this reason we need to differentiate from one client to another by allocating and |
| 8 | +// deallocating the concrete client |
| 9 | + |
| 10 | +// TODO what can we do to handle Zephyr/mbedos clients? those are not statically bound to an interface, |
| 11 | +// wrapping them could mean wasting resources: |
| 12 | +// - The general use TCPclient could be a typedef? |
| 13 | + |
| 14 | +// TLS client integration into the wrapper: |
| 15 | +// - PIMPL, which implementation is instantiated only if a method of TLS client is called |
| 16 | +// - Issue that the Flash is always being consumed since it may be instantiated at runtime (MACRO Exclusion?) |
| 17 | +// - RAM is not being consumed for TLS structures unless specifically required |
| 18 | +// - TLS client is not a tcp client 2 classes definition are required |
| 19 | +// - Flash is being used only if the class is being used |
| 20 | +// - Client embedding may be of use (TCPClient -> TLSClient -> HttpClient) |
| 21 | +// + the last layer may be instantiated with default values, but can be still embedded manually |
| 22 | +// - middleware definition: between TCPclient and the user there are multiple middleware layers |
| 23 | +// that act as layer 5/6 of iso/osi stack, TLS is one of them (are there any others?) |
| 24 | +// - sort of client embedding, which may be more flexible |
| 25 | +// - I always instantiate a TCPClient, but if I need Http, I will add it as middleware to the current instance |
| 26 | +// + If HttpClient has different specifics from a TCPClient they might be hard to expose |
| 27 | +// - It could be nice to have an explicit connectSSL in client which enables SSL |
| 28 | + |
| 29 | +class TCPClientConnect: public ClientConnect { |
| 30 | +public: |
| 31 | + |
| 32 | + // default generic TCPClient associated with default net interface |
| 33 | + TCPClientConnect() |
| 34 | + : _factory(TCPClientConnect::_factory) { |
| 35 | + } |
| 36 | + |
| 37 | + ~TCPClientConnect(); |
| 38 | + |
| 39 | + int connect(IPAddress ip, uint16_t port) override; |
| 40 | + int connect(const char *host, uint16_t port) override; |
| 41 | + void disconnect() override; |
| 42 | + |
| 43 | + uint8_t connected() override; |
| 44 | + operator bool() override; |
| 45 | + |
| 46 | +protected: |
| 47 | + // the factory should provide a way to allocate and deallocate the client |
| 48 | + // there should be a default factory that uses to use the default network interface |
| 49 | + static std::function<std::unique_ptr<Client>()> _factory; |
| 50 | + |
| 51 | + // factories can be changed per instance |
| 52 | + std::function<std::unique_ptr<Client>()> _factory; |
| 53 | + |
| 54 | + // the client should be instantiated when calling connect, if it fails the Client is deleted |
| 55 | + // otherwise it is called when the stop/end call is performed |
| 56 | + // unique_ptr is being used to propagate the allocation and deallocation methods that a factory may provide |
| 57 | + std::unique_ptr<Client> client; |
| 58 | + |
| 59 | + // TODO should a client keep the Network interface reference? |
| 60 | + |
| 61 | + friend TCPClient; |
| 62 | +}; |
| 63 | + |
| 64 | +class TCPClient: public Client, TCPClientConnect { |
| 65 | +public: |
| 66 | + size_t write(uint8_t) override; |
| 67 | + size_t write(const uint8_t *buf, size_t size) override; |
| 68 | + int read(uint8_t *buf, size_t size) override; |
| 69 | + void stop() override; |
| 70 | +}; |
| 71 | + |
| 72 | +}} |
0 commit comments