almost finished documenting, moved SSLSession implementation into it's own file, fixed infinite loop when overflowing m_iobuf

This commit is contained in:
Noah Laptop 2019-03-31 12:55:58 -07:00
parent cd94d0bf3b
commit 648104c7e3
8 changed files with 265 additions and 250 deletions

View file

@ -18,20 +18,6 @@
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/**
* SSLCLient.h
*
* This library was created to provide SSL functionality to the {@link https://learn.adafruit.com/adafruit-wiz5500-wiznet-ethernet-featherwing/overview}
* Adafruit Ethernet shield. Since this shield does not implement SSL functionality on
* its own, we need to use an external library: in this case BearSSL {@link https://bearssl.org/},
* which is also used in the Arduino ESP8266 core. SSLClient will serve to implement the
* BearSSL functionality inbetween EthernetClient and the User, such that the user.
*
* This file specifically controls the class templating used to allow SSLClient to interface
* with all of the CLient-based classes. To see details on the implementations of the functions
* in SSLClient, please see {@link ./SSLClientImpl.h}.
*/
#include <type_traits>
#include "Client.h"
#include "SSLClientImpl.h"
@ -41,27 +27,13 @@
#define SSLClient_H_
/**
* \brief The main SSLClient class
*
* TODO: fix this blurb
*
* This class serves as a templating proxy class for the SSLClientImpl to do the real work.
*
* A problem arose when writing this class: I wanted the user to be able to construct
* this class in a single line of code (e.g. SSLClient(EthernetClient())), but I also
* wanted to avoid the use of dynamic memory if possible. In an attempt to solve this
* problem I used a templated classes. However, becuase of the Arduino build process
* this meant that the implementations for all the functions had to be in a header
* file (a weird effect of using templated classes and linking) which would slow down
* the build quite a bit. As a comprimise, I instead decided to build the main class (SSLCLient)
* as a templated class, and have use a not templated implementation class (SSLClientImpl)
* that would be able to reside in a seperate file. This gets the best of both worlds
* from the client side, however from the developer side it can be a bit confusing.
* @brief The main SSLClient class
* Check out README.md for more info.
*/
template <class C, size_t SessionCache = 1>
class SSLClient : public SSLClientImpl {
/**
/*
* static checks
* I'm a java developer, so I want to ensure that my inheritance is safe.
* These checks ensure that all the functions we use on class C are
@ -81,22 +53,20 @@ static_assert(SessionCache <= 3, "You need to decrease the size of m_iobuf in or
public:
/**
* @brief copies the client object, and passes the various parameters to the SSLCLientImpl functions.
*
* We copy the client because we aren't sure the Client object
* is going to exists past the inital creation of the SSLClient.
* @brief Initialize SSLClient with all of the prerequisites needed.
*
* @pre You will need to generate an array of trust_anchors (root certificates)
* based off of the domains you want to make SSL connections to. Check out the
* Wiki on the pycert-bearssl tool for a simple way to do this.
* TrustAnchors.md file for more info.
* @pre The analog_pin should be set to input.
*
* @param client The base network device to create an SSL socket on. This object will be copied
* and the copy will be stored in SSLClient.
* @param trust_anchors Trust anchors used in the verification
* of the SSL server certificate, generated using the `brssl` command
* line utility. For more information see the samples or bearssl.org
* @param trust_anchors_num The number of trust anchors stored
* @param analog_pin An analog pin to pull random bytes from, used in seeding the RNG
* @param debug whether to enable or disable debug logging, must be constexpr
* of the SSL server certificate. Check out TrustAnchors.md for more info.
* @param trust_anchors_num The number of objects in the trust_anchors array.
* @param analog_pin An analog pin to pull random bytes from, used in seeding the RNG.
* @param debug whether to enable or disable debug logging.
*/
explicit SSLClient(const C& client, const br_x509_trust_anchor *trust_anchors, const size_t trust_anchors_num, const int analog_pin, const DebugLevel debug = SSL_WARN)
: SSLClientImpl(trust_anchors, trust_anchors_num, analog_pin, debug)
@ -113,93 +83,81 @@ public:
//========================================
/**
* @brief Connect over SSL to a host specified by an ip address
* @brief Connect over SSL to a host specified by an IP address.
*
* SSLClient::connect(host, port) should be preffered over this function,
* SSLClient::connect(host, port) should be preferred over this function,
* as verifying the domain name is a step in ensuring the certificate is
* legitimate, which is important to the security of the device. Additionally,
* SSL sessions cannot be resumed, which can drastically increase initial
* connect time.
*
* This function initializes EthernetClient by calling EthernetClient::connect
* with the parameters supplied, then once the socket is open initializes
* the appropriete bearssl contexts. Due to the design of the SSL standard,
* This function initializes the socket by calling m_client::connect(IPAddress, uint16_t)
* with the parameters supplied, then once the socket uses BearSSL to
* to complete a SSL handshake. Due to the design of the SSL standard,
* this function will probably take an extended period (1-4sec) to negotiate
* the handshake and finish the connection. This function runs until the SSL
* handshake succeeds or fails, as found in most Arduino libraries.
* handshake succeeds or fails.
*
* The implementation for this function can be found in SSLClientImpl::connect_impl(IPAddress, uint16_t)
* SSL requires the client to generate some random bits (to be later combined
* with some random bits from the server), so SSLClient uses the least significant
* bits from the analog pin supplied in the constructor. The random bits are generated
* from 16 consecutive analogReads, and given to BearSSL before the handshake
* starts.
*
* @pre The underlying client object (passed in through the ctor) in a non-
* error state, and must be able to access the server being connected to.
* @pre SSLCLient can only have one connection at a time, so the client
* object must not already have a socket open.
* @pre There must be sufficient memory availible on the device to verify
* The implementation for this function can be found in SSLClientImpl::connect_impl(IPAddress, uint16_t).
*
* @pre The underlying client object (passed in through the constructor) is in a non-
* error state, and must be able to access the IP.
* @pre SSLClient can only have one connection at a time, so the client
* object must not already be connected.
* @pre There must be sufficient memory available on the device to verify
* the certificate (if the free memory drops below 8000 bytes during certain
* points in the connection, SSLCLient will fail).
* @pre There must be a trust anchor given to the ctor that corresponds to
* points in the connection, SSLClient will fail).
* @pre There must be a trust anchor given to the constructor that corresponds to
* the certificate provided by the IP address being connected to. For more
* information check out the wiki on the pycert-bearssl tool.
* @pre The analog pin passed to the ctor must be set to input, and must
* be wired to something sort of random (floating is fine).
* information check out TrustAnchors.md .
*
* @param ip The ip address to connect to
* @param ip The IP address to connect to
* @param port the port to connect to
* @returns 1 if success, 0 if failure (as found in EthernetClient)
* @returns 1 if success, 0 if failure
*/
virtual int connect(IPAddress ip, uint16_t port) { return connect_impl(ip, port); }
/**
* @brief Connect over SSL using connect(ip, port), using a DNS lookup to
* get the IP Address first.
* @brief Connect over SSL to a host specified by a hostname.
*
* This function initializes EthernetClient by calling EthernetClient::connect
* This function initializes the socket by calling m_client::connect(const char*, uint16_t)
* with the parameters supplied, then once the socket is open uses BearSSL to
* to complete a SSL handshake. This function runs until the SSL handshake
* succeeds or fails, as found in most Arduino libraries.
* succeeds or fails.
*
* SSL requires the client to generate some random bits (to be later combined
* with some random bits from the server), so SSLClient uses the least signinigant
* bits from the analog pin supplied in the ctor. The random bits are generated
* with some random bits from the server), so SSLClient uses the least significant
* bits from the analog pin supplied in the constructor. The random bits are generated
* from 16 consecutive analogReads, and given to BearSSL before the handshake
* starts.
*
* Due to the design of the SSL standard, this function will probably take an
* extended period (1-4sec) to negotiate the handshake and finish the
* connection. Since the hostname is provided, however, BearSSL is able to keep
* a session cache of the clients we have connected to. This should reduce
* connection time to about 100-200ms. In order to use this feature, the website
* you are connecting to must support it (most do by default), you must
* reuse the same SSLClient object, and you must reconnect to the same server.
* SSLClient automatcally stores an IP address and hostname in each session,
* ensuring that if you call connect("www.google.com") SSLClient will use a
* cached IP address instead of another DNS lookup. Because some websites have
* multiple servers on a single IP address (github.com is an example), however,
* you may find that even if you are connecting to the same host the connection
* does not resume. This is a flaw in the SSL session protocol, and has been
* resolved in future versions. On top of all that, SSL sessions can expire
* based on server criteria, which will result in a regular connection time.
* Because of all these factors, it is generally prudent to assume the
* connection will not be resumed, and go from there.
* This function will usually take around 4-10 seconds. If possible, this function
* also attempts to resume the SSL session if one is present matching the hostname
* string, which will reduce connection time to 100-500ms. To read more about this
* functionality, check out Session Caching in the README.
*
* The implementation for this function can be found in SSLClientImpl::connect_impl(const char*, uint16_t)
*
* @pre The underlying client object (passed in through the ctor) in a non-
* error state, and must be able to access the server being connected to.
* @pre SSLCLient can only have one connection at a time, so the client
* object must not already have a socket open.
* @pre There must be sufficient memory availible on the device to verify
* @pre The underlying client object (passed in through the constructor) is in a non-
* error state, and must be able to access the IP.
* @pre SSLClient can only have one connection at a time, so the client
* object must not already be connected.
* @pre There must be sufficient memory available on the device to verify
* the certificate (if the free memory drops below 8000 bytes during certain
* points in the connection, SSLCLient will fail).
* @pre There must be a trust anchor given to the ctor that corresponds to
* points in the connection, SSLClient will fail).
* @pre There must be a trust anchor given to the constructor that corresponds to
* the certificate provided by the IP address being connected to. For more
* information check out the wiki on the pycert-bearssl tool.
* @pre The analog pin passed to the ctor must be set to input, and must
* be wired to something sort of random (floating is fine).
* information check out TrustAnchors.md .
*
* @param host The cstring host ("www.google.com")
* @param port the port to connect to (443)
* @returns 1 of success, 0 if failure (as found in EthernetClient).
* @param host The hostname as a null-terminated c-string ("www.google.com")
* @param port The port to connect to on the host (443 for HTTPS)
* @returns 1 of success, 0 if failure
*/
virtual int connect(const char *host, uint16_t port) { return connect_impl(host, port); }
@ -208,36 +166,14 @@ public:
/**
* @brief Write some bytes to the SSL connection
*
* Assuming all preconditions are met, this function waits for BearSSL
* to be ready for data to be sent, then writes data to the BearSSL IO
* buffer, BUT does not initally send the data. Insead, it is
* then checked if the BearSSL IO buffer is full, and if so, this function
* waits until BearSSL has flushed the buffer (written it to the
* network client) and fills the buffer again. If the function finds
* that the BearSSL buffer is not full, it returns the number of
* bytes written. In other words, this function will only write data
* to the network if the BearSSL IO buffer is full. Instead, you must call
* SSLClient::availible or SSLClient::flush, which will detect that
* the buffer is ready for writing, and will write the data to the network.
*
* This was implemented as a buffered function because users of Arduino Client
* libraries will often write to the network as such:
* @code{.cpp}
* Client client;
* ...
* client.println("GET /asciilogo.txt HTTP/1.1");
* client.println("Host: arduino.cc");
* client.println("Connection: close");
* while (!client.available()) { ... }
* ...
* @endcode
* This is fine with most network clients. With SSL, however, if we are encryting and
* writing to the network every write() call this will result in a lot of
* small encryption tasks. Encryption takes a lot of time and code, and in general
* the larger the batch we can do it in the better. For this reason, write()
* implicitly buffers until SSLClient::availible is called, or until the buffer is full.
* If you would like to trigger a network write manually without using the SSLClient::available,
* you can also call SSLClient::flush, which will write all data and return when finished.
* Assuming all preconditions are met, this function writes data to the BearSSL IO
* buffer, BUT does not initially send the data. Instead, you must call
* SSLClient::available or SSLClient::flush, which will detect that
* the buffer is ready for writing, and will write the data to the network.
* Alternatively, if this function is requested to write a larger amount of data than SSLClientImpl::m_iobuf
* can handle, data will be written to the network in pages the size of SSLClientImpl::m_iobuf until
* all the data in buf is sent--attempting to keep all writes to the network grouped together. For information
* on why this is the case check out README.md .
*
* The implementation for this function can be found in SSLClientImpl::write_impl(const uint8_t*, size_t)
*
@ -256,18 +192,18 @@ public:
* @brief Returns the number of bytes availible to read from the SSL Socket
*
* This function updates the state of the SSL engine (including writing any data,
* see SSLClient::write) and as a result should be called periodically when writing
* or expecting data. Additionally, since this function returns zero if there are
* no bytes and if SSLClient::connected is false (this same behavior is found
* see SSLClient::write) and as a result should be called periodically when expecting data.
* Additionally, since if there are no bytes and if SSLClient::connected is false
* this function returns zero (this same behavior is found
* in EthernetClient), it is prudent to ensure in your own code that the
* preconditions are met before checking this function to prevent an ambigious
* preconditions are met before checking this function to prevent an ambiguous
* result.
*
* The implementation for this function can be found in SSLClientImpl::available
*
* @pre SSLClient::connected must be true.
*
* @returns The number of bytes availible (can be zero), or zero if any of the pre
* @returns The number of bytes available (can be zero), or zero if any of the pre
* conditions aren't satisfied.
*/
virtual int available() { return available_impl(); }
@ -280,38 +216,14 @@ public:
/**
* @brief Read size bytes from the SSL socket buffer, copying them into *buf, and return the number of bytes read.
*
* This function checks if bytes are ready to be read by calling SSLClient::availible,
* and if so copies size number of bytes from the IO buffer into the buf pointer, and deletes
* that number of bytes from the SSLClient buffer. Data read using this function will not
* This function checks if bytes are ready to be read by calling SSLClient::available,
* and if so copies size number of bytes from the IO buffer into the buf pointer.
* Data read using this function will not
* include any SSL or socket commands, as the Client and BearSSL will capture those and
* process them seperatley.
* process them separately.
*
* It should be noted that a common problem I encountered with SSL connections is
* buffer overflow, caused by the server sending too much data at once. This problem
* is caused by the microcontroller being unable to copy and decrypt data faster
* than it is being recieved, forcing some data to be discarded. This usually puts BearSSL
* in an invalid state in which it is unable to recover, causing SSLClient to close
* the connection with a write error. If you are experiencing frequent timeout problems,
* this could be the reason why.
*
* In order to remedy this problem the device must be able to read the data faster than
* it is being recieved, or have a cache large enough to store the entire recieve payload.
* Since SSL's encryption forces the device to read slowly, this means we must increase
* the cache size. Depending on your platform, there are a number of ways this can be
* done:
* - Sometimes your communication sheild will have an internal buffer, which can be expanded
* through the driver code. This is the case with the Arduino Ethernet library (in the form
* of the MAX_SOCK_NUM and ETHERNET_LARGE_BUFFERS macros), however the library must be
* modified for the change to take effect.
* - SSLClient has an internal buffer SSLClientImpl::m_iobuf, which can be expanded. This will have very
* limited usefulness, however, as BearSSL limits the amount of data that can be processed
* based on the stage in the SSL handshake.
* - If none of the above are viable, it is possible to implement your own Client class which
* has an internal buffer much larger than both the driver and BearSSL. This would require
* in-depth knowlege of programming and the communication shield you are working with.
* Another important question to ask with this problem is: do I need to acsess this website?
* Often times there are other ways to get data that we need that do the same thing,
* and these other ways may offer smaller and more managable response payloads.
* If you find that you are having a lot of timeout errors, SSLClient may be experiencing a buffer
* overflow. Checkout README.md for more information.
*
* The implementation for this function can be found in SSLClientImpl::read_impl(uint8_t*, size_t)
*
@ -328,15 +240,15 @@ public:
* @brief view the first byte of the buffer, without removing it from the SSLClient Buffer
* The implementation for this function can be found in SSLClientImpl::peek
* @pre SSLClient::available must be >0
* @returns The first byte recieved, or -1 if the preconditions are not satisfied (warning:
* do not use if your data may be -1, as the return value is ambigious)
* @returns The first byte received, or -1 if the preconditions are not satisfied (warning:
* do not use if your data may be -1, as the return value is ambiguous)
*/
virtual int peek() { return peek_impl(); }
/**
* @brief Force writing the buffered bytes from SSLClient::write to the network.
* This function is blocking until all bytes from the buffer are written. For
* an explanation of how writing with SSLClient works, please see SSLCLient::write.
* an explanation of how writing with SSLClient works, please see SSLClient::write.
* The implementation for this function can be found in SSLClientImpl::flush.
*/
virtual void flush() { return flush_impl(); }
@ -353,9 +265,9 @@ public:
/**
* @brief Check if the device is connected.
* Use this function to determine if SSLClient is still connected and a SSL connection is active.
* It should be noted that SSLClient::availible should be prefered over this function for rapid
* polling--both functions send and recieve data to the Client device, however SSLClient::availible
* has some delays built in to protect the Client device from being polled too frequently.
* It should be noted that SSLClient::available should be preferred over this function for rapid
* polling--both functions send and receive data with the SSLClient::m_client device, however SSLClient::available
* has some delays built in to protect SSLClient::m_client from being polled too frequently.
*
* The implementation for this function can be found in SSLClientImpl::connected_impl.
*
@ -368,16 +280,16 @@ public:
//========================================
/**
* @brief Get a sesssion reference corressponding to a host and IP, or a reference to a emptey session if none exist
* @brief Get a session reference corresponding to a host and IP, or a reference to a empty session if none exist
*
* If no session corresponding to the host and ip exist, then this function will cycle through
* sessions in a rotating order. This allows the ssession cache to continuially store sessions,
* If no session corresponding to the host and IP exist, then this function will cycle through
* sessions in a rotating order. This allows the session cache to continually store sessions,
* however it will also result in old sessions being cleared and returned. In general, it is a
* good idea to use a SessionCache size equal to the number of domains you plan on connecting to.
*
* The implementation for this function can be found at SSLClientImpl::get_session_impl.
*
* @param host A hostname c string, or NULL if one is not availible
* @param host A hostname c string, or NULL if one is not available
* @param ip An IP address
* @returns A reference to an SSLSession object
*/
@ -388,13 +300,13 @@ public:
*
* The implementation for this function can be found at SSLClientImpl::remove_session_impl.
*
* @param host A hostname c string, or NULL if one is not availible
* @param host A hostname c string, or NULL if one is not available
* @param ip An IP address
*/
virtual void removeSession(const char* host, const IPAddress& addr) { return remove_session_impl(host, addr); }
/**
* @brief Get the meximum number of SSL sessions that can be stored at once
* @brief Get the maximum number of SSL sessions that can be stored at once
* @returns The SessionCache template parameter.
*/
virtual size_t getSessionCount() const { return SessionCache; }
@ -437,7 +349,7 @@ public:
}
}
/** @brief returns a refernence to the client object stored in this class. Take care not to break it. */
/** @brief returns a reference to the client object stored in this class. Take care not to break it. */
C& getClient() { return m_client; }
protected:

View file

@ -135,6 +135,7 @@ size_t SSLClientImpl::write_impl(const uint8_t *buf, size_t size) {
size_t alen;
unsigned char *br_buf = br_ssl_engine_sendapp_buf(&m_sslctx.eng, &alen);
size_t cur_idx = 0;
bool did_overflow = false;
// while there are still elements to write
while (cur_idx < size) {
// run until the ssl socket is ready to write, unless we've already written
@ -152,8 +153,13 @@ size_t SSLClientImpl::write_impl(const uint8_t *buf, size_t size) {
// so we only send the smallest of the buffer size or our data size - how much we've already sent
const size_t cpamount = m_write_idx + (size - cur_idx) > alen ? alen : size - cur_idx;
memcpy(br_buf + m_write_idx, buf + cur_idx, cpamount);
// if we filled the buffer, reset m_write_idx
if (cpamount == alen) m_write_idx = 0;
// if we filled the buffer, reset m_write_idx, and mark the data for sending
// or if we've overflowed since we're writing to the network already we may as well finish
if (cpamount == alen || did_overflow) {
m_write_idx = 0;
br_ssl_engine_sendapp_ack(&m_sslctx.eng, alen);
did_overflow = true;
}
// else increment
else m_write_idx += cpamount;
// increment the buffer pointer

View file

@ -30,7 +30,7 @@
* @brief Static constants defining the possible errors encountered.
*
* If SSLClient encounters an error, it will generally output
* logs into the serial moniter. If you need a way of programmatically
* logs into the serial monitor. If you need a way of programmatically
* checking the errors, you can do so with SSLClient::getWriteError(),
* which will return one of these values.
*/
@ -44,7 +44,7 @@ enum Error {
SSL_CLIENT_WRTIE_ERROR,
/** An internal error occurred with BearSSL, check logs for diagnosis. */
SSL_BR_WRITE_ERROR,
/** An internal error occured with SSLClient, and you probably need to submit an issue on Github. */
/** An internal error occurred with SSLClient, and you probably need to submit an issue on Github. */
SSL_INTERNAL_ERROR,
/** SSLClient detected that there was not enough memory (>8000 bytes) to continue. */
SSL_OUT_OF_MEMORY
@ -53,47 +53,24 @@ enum Error {
/**
* @brief Level of verbosity used in logging for SSLClient.
*
* Use these values when initializing SSLCLient to set how many logs you
* would like to see in the Serial moniter.
* Use these values when initializing SSLClient to set how many logs you
* would like to see in the Serial monitor.
*/
enum DebugLevel {
/** No logging output */
SSL_NONE = 0,
/** Only output errors that result in connection failure */
SSL_ERROR = 1,
/** Ouput errors and warnings (useful when just starting to develop) */
/** Output errors and warnings (useful when just starting to develop) */
SSL_WARN = 2,
/** Output errors, warnings, and internal information (very verbose) */
SSL_INFO = 3,
};
/**
* On error, any function in this class will terminate the socket.
* TODO: Write what this is */
/** @brief Implementation code to be inherited by SSLClient */
class SSLClientImpl : public Client {
public:
/**
* @brief initializes SSL contexts for bearSSL
*
* @pre You will need to generate an array of trust_anchors (root certificates)
* based off of the domains you want to make SSL connections to. Check out the
* Wiki on the pycert-bearssl tool for a simple way to do this.
* @pre The analog_pin should be set to input.
* @pre The session_ray must be an array of the size returned by SSLClient::getSessionCount()
* filled with SSLSession objects.
*
* @post set_client must be called immediatly after to set the client class
* pointer and Session pointer.
*
* @param trust_anchors Trust anchors used in the verification
* of the SSL server certificate, generated using the `brssl` command
* line utility. For more information see the samples or bearssl.org
* @param trust_anchors_num The number of trust anchors stored
* @param analog_pin An analog pin to pull random bytes from, used in seeding the RNG
* @param session_ray A pointer to the array of SSLSessions created by SSLClient
* @param debug whether to enable or disable debug logging, must be constexpr
*/
/** See SSLClient::SSLClient */
explicit SSLClientImpl(const br_x509_trust_anchor *trust_anchors,
const size_t trust_anchors_num, const int analog_pin, const DebugLevel debug);
@ -185,7 +162,7 @@ private:
int m_start_ssl(const char* host, SSLSession& ssl_ses);
/** run the bearssl engine until a certain state */
int m_run_until(const unsigned target);
/** proxy for availble that returns the state */
/** proxy for available that returns the state */
unsigned m_update_engine();
/** utility function to find a session index based off of a host and IP */
int m_get_session_index(const char* host, const IPAddress& addr) const;

24
src/SSLSession.cpp Normal file
View file

@ -0,0 +1,24 @@
#include "SSLSession.h"
/* See SSLSession.h */
void SSLSession::set_parameters(const IPAddress& ip, const char* hostname) {
// copy the hostname
if (hostname != NULL) m_hostname = hostname;
// or if there's no hostname, clear the string
else m_hostname = "";
// and the IP address
m_ip = ip;
// check if both values are valid, and if so set valid to true
if (m_ip != INADDR_NONE && session_id_len > 0
&& (hostname == NULL || m_hostname)) m_valid_session = true;
// else clear
else clear_parameters();
}
/* see SSLSession.h */
void SSLSession::clear_parameters() {
// clear the hostname , ip, and valid session flags
m_hostname = "";
m_ip = INADDR_NONE;
m_valid_session = false;
}

View file

@ -26,6 +26,8 @@
*/
#include "bearssl.h"
#include "Arduino.h"
#include "IPAddress.h"
#ifndef SSLSession_H_
#define SSLSession_H_
@ -104,19 +106,7 @@ public:
* Take care that this value is corrent, SSLSession performs no validation
* of the hostname.
*/
void set_parameters(const IPAddress& ip, const char* hostname = NULL) {
// copy the hostname
if (hostname != NULL) m_hostname = hostname;
// or if there's no hostname, clear the string
else m_hostname = "";
// and the IP address
m_ip = ip;
// check if both values are valid, and if so set valid to true
if (m_ip != INADDR_NONE && session_id_len > 0
&& (hostname == NULL || m_hostname)) m_valid_session = true;
// else clear
else clear_parameters();
}
void set_parameters(const IPAddress& ip, const char* hostname = NULL);
/**
* @brief delete the parameters and invalidate the session
@ -124,12 +114,7 @@ public:
* this function preserves the String object, allowing it
* to better handle the dynamic memory needed.
*/
void clear_parameters() {
// clear the hostname , ip, and valid session flags
m_hostname = "";
m_ip = INADDR_NONE;
m_valid_session = false;
}
void clear_parameters();
/** @brief returns a pointer to the ::br_ssl_session_parameters component of this class */
br_ssl_session_parameters* to_br_session() { return (br_ssl_session_parameters *)this; }
@ -142,4 +127,6 @@ private:
IPAddress m_ip;
};
#endif /* SSLSession_H_ */