Skip to content

Commit

Permalink
Add validate function for multi-client connection validation.
Browse files Browse the repository at this point in the history
  • Loading branch information
mobizt committed Aug 22, 2023
1 parent 959243e commit 4d9bf9c
Show file tree
Hide file tree
Showing 10 changed files with 336 additions and 15 deletions.
29 changes: 29 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,35 @@ The Sessions and ServerSessions for ESP8266 BearSSL will be renamed to BearSSL_S

For ESP32, the certificate bundle is not currenty supported.

## Additional Functions



#### Validate the last Client connection with these host and port.

param **`host`** The server host name.

param **`port`** The server port to connect.

The Client connection will be closed when the provided host or port is not match with that of last connection.

```cpp
void validate(const char *host, uint16_t port);
```
#### Validate the last Client connection with these IP and port.
param **`ip`** The server IP to connect.
param **`port`** The server port to connect.
The Client connection will be closed when the provided IP or port is not match with that of last connection.
```cpp
void validate(IPAddress ip, uint16_t port);
```

## MIT License

Copyright (c) 2023 mobizt
Expand Down
220 changes: 220 additions & 0 deletions examples/session/session.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,220 @@
/**
* This example shows how to connect to server via https using the SSL client and store the session to speed up handshake.
*
* This example works on the Arduino-Pico SDK from Earle F. Philhower.
* https://github.com/earlephilhower/arduino-pico
*
* Email: [email protected]
*
* Github: https://github.com/mobizt/ESP_SSLSClient
*
* Copyright (c) 2023 mobizt
*
*/

#include <Arduino.h>
#if defined(ESP32) || defined(ARDUINO_RASPBERRY_PI_PICO_W)
#include <WiFi.h>
#elif defined(ESP8266)
#include <ESP8266WiFi.h>
#elif __has_include(<WiFiNINA.h>)
#include <WiFiNINA.h>
#elif __has_include(<WiFi101.h>)
#include <WiFi101.h>
#elif __has_include(<WiFiS3.h>)
#include <WiFiS3.h>
#endif

#include <ESP_SSLClient.h>

#define WIFI_SSID "WIFI_AP"
#define WIFI_PASSWORD "WIFI_PASSWORD"

ESP_SSLClient ssl_client;

// EthernetClient basic_client;
// GSMClient basic_client;
WiFiClient basic_client;

#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
WiFiMulti multi;
#endif

BearSSL_Session session1;

BearSSL_Session session2;

const char *host1 = "reqres.in";

const char *uri1 = "/api/users";

const char *contentType1 = "application/json";

String payload1 = "{\"title\":\"hello\"}";

const char *host2 = "jsonplaceholder.typicode.com";

const char *uri2 = "/posts";

const char *contentType2 = "application/json";

String payload2 = "{\"title\":\"foo\",\"body\": \"bar\",\"userId\": 1}";

void connect(const char *method, BearSSL_Session *session, uint32_t timeout, bool closeSession, const char *host, uint16_t port, const char *uri, const char *contentType, const char *payload, bool showResponse)
{

if (session)
{
if (session->getSession()->cipher_suite > 0)
Serial.println("### CONNECT WITH SESSION");
else
Serial.println("### CONNECT WITH EMPTY SESSION");
}
else
Serial.println("### CONNECT WITHOUT SESSION");

unsigned long ms = millis();

// Validation for currently connecting host and port.
// Close connection when it's not match that of the last connection.
ssl_client.validate(host, port);

if (!ssl_client.connected())
{
Serial.print("Connecting to ");
Serial.print(host);
Serial.print("... ");

ssl_client.setSession(session);

if (!ssl_client.connect(host, port))
{
Serial.println(" failed\n");
Serial.println();
return;
}
Serial.println(" ok");
Serial.print("Connect and negotiate time... ");
Serial.println(millis() - ms);
}

Serial.print("Send ");
Serial.print(method);
Serial.println(" request...");

ssl_client.print(method);
ssl_client.print(" ");
if (uri[0] != '/')
ssl_client.print("/");
ssl_client.print(uri);
ssl_client.print(" HTTP/1.1\n");
ssl_client.print("Host: ");
ssl_client.print(host);
ssl_client.print("\n");

if (strcasecmp(method, "post") == 0 || strcasecmp(method, "put") == 0)
{
ssl_client.print("Content-Type: ");
ssl_client.print(contentType);
ssl_client.print("\n");
ssl_client.print("Content-Length: ");
ssl_client.print(strlen(payload));
ssl_client.print("\n\n");
ssl_client.print(payload);
}

Serial.print("Read response...");
ms = millis();
while (!ssl_client.available() && millis() - ms < timeout)
{
delay(0);
}

if (millis() - ms > timeout)
{
Serial.println(" timed out");
}
else
{
if (showResponse)
Serial.println();

while (ssl_client.available())
{
char res = ssl_client.read();
if (showResponse)
Serial.print(res);
}

if (!showResponse)
Serial.println("ok");

Serial.println();
}

if (closeSession)
ssl_client.stop();

Serial.println();
}

void setup()
{
Serial.begin(115200);

ssl_client.setSession(&session1);

#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
multi.addAP(WIFI_SSID, WIFI_PASSWORD);
multi.run();
#else
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
#endif

Serial.print("Connecting to Wi-Fi");
unsigned long ms = millis();
while (WiFi.status() != WL_CONNECTED)
{
Serial.print(".");
delay(300);
#if defined(ARDUINO_RASPBERRY_PI_PICO_W)
if (millis() - ms > 10000)
break;
#endif
}
Serial.println();
Serial.print("Connected with IP: ");
Serial.println(WiFi.localIP());
Serial.println();

// ignore server ssl certificate verification
ssl_client.setInsecure();

// Set the receive and transmit buffers size in bytes for memory allocation (512 to 16384).
ssl_client.setBufferSizes(1024 /* rx */, 512 /* tx */);

/** Call setDebugLevel(level) to set the debug
* esp_ssl_debug_none = 0
* esp_ssl_debug_error = 1
* esp_ssl_debug_warn = 2
* esp_ssl_debug_info = 3
* esp_ssl_debug_dump = 4
*/
ssl_client.setDebugLevel(1);

// assign the basic client
ssl_client.setClient(&basic_client);
}

void loop()
{
connect("POST", nullptr, 3000, true, host1, 443, uri1, contentType1, payload1.c_str(), false);
delay(5000);
connect("POST", nullptr, 3000, true, host2, 443, uri2, contentType2, payload2.c_str(), false);
delay(5000);

connect("POST", &session1, 3000, true, host1, 443, uri1, contentType1, payload1.c_str(), false);
delay(5000);
connect("POST", &session2, 3000, true, host2, 443, uri2, contentType2, payload2.c_str(), false);
delay(5000);
}
2 changes: 2 additions & 0 deletions keywords.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ ESP_SSLClient KEYWORD1

setClient KEYWORD2
connect KEYWORD2
connected KEYWORD2
validate KEYWORD2
available KEYWORD2
read KEYWORD2
write KEYWORD2
Expand Down
2 changes: 1 addition & 1 deletion library.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "ESP_SSLClient",
"version": "2.1.4",
"version": "2.1.5",
"keywords": "communication, REST, esp32, esp8266, arduino",
"description": "This library provided the Secure Layer Networking (SSL/TLS) TCP Client for ESP8266, ESP32 and Raspberry Pi RP2040, Teensy, SAMD, AVR and other Arduino devices (except for avr) that support external networking interfaces e.g., WiFiClient, EthernetClient and GSMClient.",
"repository": {
Expand Down
2 changes: 1 addition & 1 deletion library.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name=ESP_SSLClient

version=2.1.4
version=2.1.5

author=Mobizt

Expand Down
4 changes: 2 additions & 2 deletions src/ESP_SSLClient.h
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
/**
*
* The ESP SSL Client Class, ESP_SSLClient.h v2.1.4
* The ESP SSL Client Class, ESP_SSLClient.h v2.1.5
*
* Created August 16, 2023
* Created August 22, 2023
*
* The MIT License (MIT)
* Copyright (c) 2023 K. Suwatchai (Mobizt)
Expand Down
37 changes: 35 additions & 2 deletions src/client/BSSL_SSL_Client.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/**
* BSSL_SSL_Client library v1.0.9 for Arduino devices.
* BSSL_SSL_Client library v1.0.10 for Arduino devices.
*
* Created August 13, 2003
* Created August 22, 2003
*
* This work contains codes based on WiFiClientSecure from Earle F. Philhower and SSLClient from OSU OPEnS Lab.
*
Expand Down Expand Up @@ -194,6 +194,16 @@ uint8_t BSSL_SSL_Client::connected()
return c_con && br_con;
}

void BSSL_SSL_Client::validate(const char *host, uint16_t port)
{
mConnectionValidate(host, IPAddress(), port);
}

void BSSL_SSL_Client::validate(IPAddress ip, uint16_t port)
{
mConnectionValidate(nullptr, ip, port);
}

int BSSL_SSL_Client::available()
{
if (!mIsClientInitialized(false))
Expand Down Expand Up @@ -425,9 +435,14 @@ int BSSL_SSL_Client::connectSSL(IPAddress ip, uint16_t port)
if (!mIsClientInitialized(true))
return 0;

validate(ip, port);

if (!_basic_client->connected() && !mConnectBasicClient(nullptr, ip, port))
return 0;

_ip = ip;
_port = port;

return mConnectSSL(nullptr);
}

Expand All @@ -437,9 +452,14 @@ int BSSL_SSL_Client::connectSSL(const char *host, uint16_t port)
if (!mIsClientInitialized(true))
return 0;

validate(host, port);

if (!_basic_client->connected() && !mConnectBasicClient(host, IPAddress(), port))
return 0;

_host = host;
_port = port;

return mConnectSSL(host);
}

Expand Down Expand Up @@ -1377,6 +1397,8 @@ int BSSL_SSL_Client::mConnectBasicClient(const char *host, IPAddress ip, uint16_
if (!mIsClientInitialized(true))
return 0;

mConnectionValidate(host, ip, port);

if (!(host ? _basic_client->connect(host, port) : _basic_client->connect(ip, port)))
{
#if defined(ESP_SSLCLIENT_ENABLE_DEBUG)
Expand Down Expand Up @@ -1570,6 +1592,17 @@ int BSSL_SSL_Client::mConnectSSL(const char *host)
return 1;
}

void BSSL_SSL_Client::mConnectionValidate(const char *host, IPAddress ip, uint16_t port)
{
if (_basic_client->connected() &&
host
? (strcasecmp(host, _host.c_str()) != 0 || port != _port)
: (ip != _ip || port != _port))
{
_basic_client->stop();
}
}

int BSSL_SSL_Client::mRunUntil(const unsigned target, unsigned long timeout)
{
unsigned lastState = 0;
Expand Down
Loading

0 comments on commit 4d9bf9c

Please sign in to comment.