1
0
mirror of https://github.com/esp8266/Arduino.git synced 2025-10-18 09:50:40 +03:00

Movable HTTPClient and fixing WiFiClient copy (#8237)

- =default for default ctor, destructor, move ctor and the assignment move
- use `std::unique_ptr<WiFiClient>` instead of raw pointer to the client
- implement `virtual std::unique_ptr<WiFiClient> WiFiClient::clone()` to safely copy the WiFiClientSecure instance, without accidentally slicing it (i.e. using the pointer with incorrect type, calling base WiFiClient virtual methods)
- replace headers pointer array with `std::unique_ptr<T[]>` to simplify the move operations
- substitute userAgent with the default one when it is empty
(may be a subject to change though, b/c now there is a global static `String`)

Allow HTTPClient to be placed inside of movable classes (e.g. std::optional, requested in the linked issue) or to be returned from functions. Class logic stays as-is, only the underlying member types are changed.

Notice that WiFiClient connection object is now copied, and the internal ClientContext will be preserved even after the original WiFiClient object was destroyed.

replaces #8236
resolves #8231
and, possibly #5734
This commit is contained in:
Max Prokhorov
2021-10-13 04:19:51 +03:00
committed by GitHub
parent b7a2f44b50
commit 40b26b769c
5 changed files with 73 additions and 46 deletions

View File

@@ -39,6 +39,13 @@ class WiFiClientSecureCtx : public WiFiClient {
WiFiClientSecureCtx& operator=(const WiFiClientSecureCtx&) = delete;
// TODO: usage is invalid b/c of deleted copy, but this will only trigger an error when it is actually used by something
// TODO: don't remove just yet to avoid including the WiFiClient default implementation and unintentionally causing
// a 'slice' that this method tries to avoid in the first place
std::unique_ptr<WiFiClient> clone() const override {
return std::unique_ptr<WiFiClient>(new WiFiClientSecureCtx(*this));
}
int connect(IPAddress ip, uint16_t port) override;
int connect(const String& host, uint16_t port) override;
int connect(const char* name, uint16_t port) override;
@@ -231,13 +238,23 @@ class WiFiClientSecure : public WiFiClient {
// Instead, all virtual functions call their counterpart in "WiFiClientecureCtx* _ctx"
// which also derives from WiFiClient (this parent is the one which is eventually used)
// TODO: notice that this complicates the implementation by having two distinct ways the client connection is managed, consider:
// - implementing the secure connection details in the ClientContext
// (i.e. delegate the write & read functions there)
// - simplify the inheritance chain by implementing base wificlient class and inherit the original wificlient and wificlientsecure from it
// - abstract internals so it's possible to seamlessly =default copy and move with the instance *without* resorting to manual copy and initialization of each member
// TODO: prefer implementing virtual overrides in the .cpp (or, at least one of them)
public:
WiFiClientSecure():_ctx(new WiFiClientSecureCtx()) { _owned = _ctx.get(); }
WiFiClientSecure(const WiFiClientSecure &rhs): WiFiClient(), _ctx(rhs._ctx) { if (_ctx) _owned = _ctx.get(); }
~WiFiClientSecure() override { _ctx = nullptr; }
WiFiClientSecure& operator=(const WiFiClientSecure&) = default; // The shared-ptrs handle themselves automatically
WiFiClientSecure& operator=(const WiFiClientSecure&) = default;
std::unique_ptr<WiFiClient> clone() const override { return std::unique_ptr<WiFiClient>(new WiFiClientSecure(*this)); }
uint8_t status() override { return _ctx->status(); }
int connect(IPAddress ip, uint16_t port) override { return _ctx->connect(ip, port); }