Skip to content

Commit d8938f7

Browse files
[TMP] extending Client apis
1 parent 47eb863 commit d8938f7

File tree

6 files changed

+186
-7
lines changed

6 files changed

+186
-7
lines changed

api/Client.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "IPAddress.h"
2424

2525
namespace arduino {
26+
// TODO define explicit poll method
2627

2728
// The objective of this interface is to split the definition of a Client that
2829
// works with streams and one that works with discrete sized messages
@@ -40,9 +41,10 @@ class ClientConnect {
4041

4142
class Client : public Stream, ClientConnect {
4243
public:
43-
virtual size_t write(uint8_t) = 0;
44-
virtual size_t write(const uint8_t *buf, size_t size) = 0;
45-
virtual int read(uint8_t *buf, size_t size) = 0;
44+
// Note: already defined in print and Stream
45+
// virtual size_t write(uint8_t) = 0;
46+
// virtual size_t write(const uint8_t *buf, size_t size) = 0;
47+
// virtual int read(uint8_t *buf, size_t size) = 0;
4648
virtual void stop() = 0;
4749
protected:
4850
uint8_t* rawIPAddress(IPAddress& addr) { return addr.raw_address(); }; // FIXME this is a utility function

api/Stream.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ class Stream : public Print
6767

6868
void setTimeout(unsigned long timeout); // sets maximum milliseconds to wait for stream data, default is 1 second
6969
unsigned long getTimeout(void) { return _timeout; }
70-
70+
7171
bool find(const char *target); // reads data from the stream until the target string is found
7272
bool find(const uint8_t *target) { return find ((const char *)target); }
7373
// returns true if target string is found, false if timed out (see setTimeout)
@@ -94,7 +94,7 @@ class Stream : public Print
9494
float parseFloat(LookaheadMode lookahead = SKIP_ALL, char ignore = NO_IGNORE_CHAR);
9595
// float version of parseInt
9696

97-
size_t readBytes( char *buffer, size_t length); // read chars from stream into buffer
97+
virtual size_t readBytes( char *buffer, size_t length); // read chars from stream into buffer
9898
size_t readBytes( uint8_t *buffer, size_t length) { return readBytes((char *)buffer, length); }
9999
// terminates if length characters have been read or timeout (see setTimeout)
100100
// returns the number of characters placed in the buffer (0 means no valid data found)
@@ -130,4 +130,4 @@ class Stream : public Print
130130

131131
}
132132

133-
using arduino::Stream;
133+
using arduino::Stream;

api/net/NetworkInterface.h

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
#pragma once
2+
3+
#include "../IPAddress.h"
4+
5+
#ifndef MAX_NETIFACES
6+
#define MAX_NETIFACES 4
7+
#endif
8+
9+
class NetworkInterfaceManager {
10+
public:
11+
static NetworkInterface* getIface(size_t i) { return netiface[i]; }
12+
13+
NetworkInterfaceManager& getInstance() {
14+
static NetworkInterfaceManager nim;
15+
return nim;
16+
}
17+
18+
private:
19+
NetworkInterfaceManager(): default_netif(nullptr) {
20+
memset(&netifaces, 0, sizeof(netifaces));
21+
}
22+
23+
~NetworkInterfaceManager() = default;
24+
25+
class NetworkInterface;
26+
27+
// should this be a std::vector? generally only one net interface will be used
28+
NetworkInterface* netifaces[MAX_NETIFACES];
29+
NetworkInterface* default_netif;
30+
31+
void appendIface(NetworkInterface* netif) {
32+
for (NetworkInterface* ptr = netifaces;
33+
ptr < netifaces + MAX_NETIFACES;
34+
ptr++;) {
35+
if(ptr == nullptr) {
36+
ptr = netif;
37+
38+
if(default_netif == nullptr) {
39+
default_netif = netif;
40+
}
41+
}
42+
}
43+
}
44+
45+
friend NetworkInterface;
46+
47+
public:
48+
void setDefault(size_t i) {
49+
if(i < MAX_NETIFACES) {
50+
default_netif = netifaces[i];
51+
}
52+
}
53+
54+
NetworkInterface* getDefault() {
55+
return default_netif;
56+
}
57+
};
58+
59+
// this requires cpp17
60+
// TODO name?
61+
inline NetworkInterfaceManager& NetIfaceManager = NetworkInterfaceManager::getInstance();
62+
63+
// TODO there are different kinds of network interfaces, should we define an enum containing the values from
64+
// ConnectionHandler?
65+
//
66+
// TODO this is the base level for a Network interface, specific implementations with kind specific
67+
// methods should also be defined, i.e. Wifi, Wifi sta + Wifi ap, Ethernet, GSM
68+
//
69+
// TODO should we append the network interface only when begin happened with success? how do we know that?
70+
//
71+
// TODO should a network interface also have a ping method?
72+
//
73+
// TODO define explicit poll method
74+
class NetworkInterface {
75+
public:
76+
NetworkInterface() {
77+
NetworkInterfaceManager.getInstance().appendIface(this);
78+
}
79+
virtual ~NetworkInterface() = default;
80+
81+
virtual IPAddress localIP() = 0
82+
virtual IPAddress subnetMask() = 0;
83+
virtual IPAddress gatewayIP() = 0;
84+
virtual IPAddress dnsServerIP() = 0;
85+
86+
// TODO define how a mac address should be represented, 8 bytes/6 bytes
87+
virtual void setMACAddress(const uint8_t* mac) = 0;
88+
virtual void getMACAddress(const uint8_t* mac) = 0;
89+
90+
// A concrete network interface may have different settings that can be plugged in the begin call
91+
// so there will be overloaded begin calls
92+
virtual bool begin() = 0;
93+
virtual bool end() = 0;
94+
protected:
95+
// NOTE return autopointer with implementation of a client class?
96+
};
97+

api/net/TCPClient.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#include "TCPClient.h"
2+
3+
4+
namespace arduino { namespace net {
5+
6+
}} // arduino::net

api/net/TCPClient.h

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
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+
}}

api/Tls.h renamed to api/net/Tls.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#pragma once
22

3-
#include "Client.h"
3+
#include "../Client.h"
44

55

66
namespace arduino {
@@ -13,6 +13,8 @@ enum class CertificateFormat {
1313
Pem,
1414
}
1515

16+
// TLS
17+
1618
class Tls: public ClientConnect {
1719
public:
1820
virtual ~Tls() = default;

0 commit comments

Comments
 (0)