chore: import local project into Gitea
This commit is contained in:
@@ -0,0 +1,355 @@
|
||||
/*
|
||||
Asynchronous TCP library for Espressif MCUs
|
||||
|
||||
Copyright (c) 2016 Hristo Gochkov. All rights reserved.
|
||||
This file is part of the esp8266 core for Arduino environment.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#if !defined(_RPAsyncTCP_LOGLEVEL_)
|
||||
#define _RPAsyncTCP_LOGLEVEL_ 1
|
||||
#endif
|
||||
|
||||
#include "AsyncPrinter.h"
|
||||
#include "debug.h"
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
AsyncPrinter::AsyncPrinter()
|
||||
: _client(NULL)
|
||||
, _data_cb(NULL)
|
||||
, _data_arg(NULL)
|
||||
, _close_cb(NULL)
|
||||
, _close_arg(NULL)
|
||||
, _tx_buffer(NULL)
|
||||
, _tx_buffer_size(TCP_MSS)
|
||||
, next(NULL)
|
||||
{}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
AsyncPrinter::AsyncPrinter(AsyncClient *client, size_t txBufLen)
|
||||
: _client(client)
|
||||
, _data_cb(NULL)
|
||||
, _data_arg(NULL)
|
||||
, _close_cb(NULL)
|
||||
, _close_arg(NULL)
|
||||
, _tx_buffer(NULL)
|
||||
, _tx_buffer_size(txBufLen)
|
||||
, next(NULL)
|
||||
{
|
||||
_attachCallbacks();
|
||||
_tx_buffer = new (std::nothrow) cbuf(_tx_buffer_size);
|
||||
|
||||
if (_tx_buffer == NULL)
|
||||
{
|
||||
panic(); //What should we do?
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
AsyncPrinter::~AsyncPrinter()
|
||||
{
|
||||
_on_close();
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
void AsyncPrinter::onData(ApDataHandler cb, void *arg)
|
||||
{
|
||||
_data_cb = cb;
|
||||
_data_arg = arg;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
void AsyncPrinter::onClose(ApCloseHandler cb, void *arg)
|
||||
{
|
||||
_close_cb = cb;
|
||||
_close_arg = arg;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
int AsyncPrinter::connect(IPAddress ip, uint16_t port)
|
||||
{
|
||||
if (_client != NULL && connected())
|
||||
return 0;
|
||||
|
||||
_client = new (std::nothrow) AsyncClient();
|
||||
|
||||
if (_client == NULL)
|
||||
{
|
||||
panic();
|
||||
}
|
||||
|
||||
_client->onConnect([](void *obj, AsyncClient * c)
|
||||
{
|
||||
((AsyncPrinter*)(obj))->_onConnect(c);
|
||||
}, this);
|
||||
|
||||
if (_client->connect(ip, port))
|
||||
{
|
||||
while (_client && _client->state() < 4)
|
||||
delay(1);
|
||||
|
||||
return connected();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
int AsyncPrinter::connect(const char *host, uint16_t port)
|
||||
{
|
||||
if (_client != NULL && connected())
|
||||
return 0;
|
||||
|
||||
_client = new (std::nothrow) AsyncClient();
|
||||
|
||||
if (_client == NULL)
|
||||
{
|
||||
panic();
|
||||
}
|
||||
|
||||
_client->onConnect([](void *obj, AsyncClient * c)
|
||||
{
|
||||
((AsyncPrinter*)(obj))->_onConnect(c);
|
||||
}, this);
|
||||
|
||||
if (_client->connect(host, port))
|
||||
{
|
||||
while (_client && _client->state() < 4)
|
||||
delay(1);
|
||||
|
||||
return connected();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
void AsyncPrinter::_onConnect(AsyncClient *c)
|
||||
{
|
||||
RPAsyncTCP_UNUSED(c);
|
||||
|
||||
if (_tx_buffer != NULL)
|
||||
{
|
||||
cbuf *b = _tx_buffer;
|
||||
_tx_buffer = NULL;
|
||||
delete b;
|
||||
}
|
||||
|
||||
_tx_buffer = new (std::nothrow) cbuf(_tx_buffer_size);
|
||||
|
||||
if (_tx_buffer)
|
||||
{
|
||||
panic();
|
||||
}
|
||||
|
||||
_attachCallbacks();
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
AsyncPrinter::operator bool()
|
||||
{
|
||||
return connected();
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
AsyncPrinter & AsyncPrinter::operator=(const AsyncPrinter &other)
|
||||
{
|
||||
if (_client != NULL)
|
||||
{
|
||||
_client->close(true);
|
||||
_client = NULL;
|
||||
}
|
||||
|
||||
_tx_buffer_size = other._tx_buffer_size;
|
||||
|
||||
if (_tx_buffer != NULL)
|
||||
{
|
||||
cbuf *b = _tx_buffer;
|
||||
_tx_buffer = NULL;
|
||||
delete b;
|
||||
}
|
||||
|
||||
_tx_buffer = new (std::nothrow) cbuf(other._tx_buffer_size);
|
||||
|
||||
if (_tx_buffer == NULL)
|
||||
{
|
||||
panic();
|
||||
}
|
||||
|
||||
_client = other._client;
|
||||
_attachCallbacks();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
size_t AsyncPrinter::write(uint8_t data)
|
||||
{
|
||||
return write(&data, 1);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
size_t AsyncPrinter::write(const uint8_t *data, size_t len)
|
||||
{
|
||||
if (_tx_buffer == NULL || !connected())
|
||||
return 0;
|
||||
|
||||
size_t toWrite = 0;
|
||||
size_t toSend = len;
|
||||
|
||||
while (_tx_buffer->room() < toSend)
|
||||
{
|
||||
toWrite = _tx_buffer->room();
|
||||
_tx_buffer->write((const char*)data, toWrite);
|
||||
|
||||
while (connected() && !_client->canSend())
|
||||
delay(0);
|
||||
|
||||
if (!connected())
|
||||
return 0; // or len - toSend;
|
||||
|
||||
_sendBuffer();
|
||||
toSend -= toWrite;
|
||||
}
|
||||
|
||||
_tx_buffer->write((const char*)(data + (len - toSend)), toSend);
|
||||
|
||||
while (connected() && !_client->canSend())
|
||||
delay(0);
|
||||
|
||||
if (!connected())
|
||||
return 0; // or len - toSend;
|
||||
|
||||
_sendBuffer();
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
bool AsyncPrinter::connected()
|
||||
{
|
||||
return (_client != NULL && _client->connected());
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
void AsyncPrinter::close()
|
||||
{
|
||||
if (_client != NULL)
|
||||
_client->close(true);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
size_t AsyncPrinter::_sendBuffer()
|
||||
{
|
||||
size_t available = _tx_buffer->available();
|
||||
|
||||
if (!connected() || !_client->canSend() || available == 0)
|
||||
return 0;
|
||||
|
||||
size_t sendable = _client->space();
|
||||
|
||||
if (sendable < available)
|
||||
available = sendable;
|
||||
|
||||
char *out = new (std::nothrow) char[available];
|
||||
|
||||
if (out == NULL)
|
||||
{
|
||||
panic(); // Connection should be aborted instead
|
||||
}
|
||||
|
||||
_tx_buffer->read(out, available);
|
||||
size_t sent = _client->write(out, available);
|
||||
delete out;
|
||||
|
||||
return sent;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
void AsyncPrinter::_onData(void *data, size_t len)
|
||||
{
|
||||
if (_data_cb)
|
||||
_data_cb(_data_arg, this, (uint8_t*)data, len);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
void AsyncPrinter::_on_close()
|
||||
{
|
||||
if (_client != NULL)
|
||||
{
|
||||
_client = NULL;
|
||||
}
|
||||
|
||||
if (_tx_buffer != NULL)
|
||||
{
|
||||
cbuf *b = _tx_buffer;
|
||||
_tx_buffer = NULL;
|
||||
delete b;
|
||||
}
|
||||
|
||||
if (_close_cb)
|
||||
_close_cb(_close_arg, this);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
void AsyncPrinter::_attachCallbacks()
|
||||
{
|
||||
_client->onPoll([](void *obj, AsyncClient * c)
|
||||
{
|
||||
RPAsyncTCP_UNUSED(c);
|
||||
((AsyncPrinter*)(obj))->_sendBuffer();
|
||||
}, this);
|
||||
|
||||
_client->onAck([](void *obj, AsyncClient * c, size_t len, uint32_t time)
|
||||
{
|
||||
RPAsyncTCP_UNUSED(c);
|
||||
RPAsyncTCP_UNUSED(len);
|
||||
RPAsyncTCP_UNUSED(time);
|
||||
|
||||
((AsyncPrinter*)(obj))->_sendBuffer();
|
||||
}, this);
|
||||
|
||||
_client->onDisconnect([](void *obj, AsyncClient * c)
|
||||
{
|
||||
((AsyncPrinter*)(obj))->_on_close(); delete c;
|
||||
}, this);
|
||||
|
||||
_client->onData([](void *obj, AsyncClient * c, void *data, size_t len)
|
||||
{
|
||||
RPAsyncTCP_UNUSED(c);
|
||||
((AsyncPrinter*)(obj))->_onData(data, len);
|
||||
}, this);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
Asynchronous TCP library for Espressif MCUs
|
||||
|
||||
Copyright (c) 2016 Hristo Gochkov. All rights reserved.
|
||||
This file is part of the esp8266 core for Arduino environment.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef ASYNCPRINTER_H_
|
||||
#define ASYNCPRINTER_H_
|
||||
|
||||
#include "Arduino.h"
|
||||
#include "RPAsyncTCP.h"
|
||||
#include "cbuf.h"
|
||||
|
||||
class AsyncPrinter;
|
||||
|
||||
typedef std::function<void(void*, AsyncPrinter*, uint8_t*, size_t)> ApDataHandler;
|
||||
typedef std::function<void(void*, AsyncPrinter*)> ApCloseHandler;
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
class AsyncPrinter: public Print
|
||||
{
|
||||
private:
|
||||
AsyncClient *_client;
|
||||
ApDataHandler _data_cb;
|
||||
void *_data_arg;
|
||||
ApCloseHandler _close_cb;
|
||||
void *_close_arg;
|
||||
cbuf *_tx_buffer;
|
||||
size_t _tx_buffer_size;
|
||||
|
||||
void _onConnect(AsyncClient *c);
|
||||
|
||||
public:
|
||||
AsyncPrinter *next;
|
||||
|
||||
AsyncPrinter();
|
||||
AsyncPrinter(AsyncClient *client, size_t txBufLen = TCP_MSS);
|
||||
virtual ~AsyncPrinter();
|
||||
|
||||
int connect(IPAddress ip, uint16_t port);
|
||||
int connect(const char *host, uint16_t port);
|
||||
|
||||
void onData(ApDataHandler cb, void *arg);
|
||||
void onClose(ApCloseHandler cb, void *arg);
|
||||
|
||||
operator bool();
|
||||
AsyncPrinter & operator=(const AsyncPrinter &other);
|
||||
|
||||
size_t write(uint8_t data);
|
||||
size_t write(const uint8_t *data, size_t len);
|
||||
|
||||
bool connected();
|
||||
void close();
|
||||
|
||||
size_t _sendBuffer();
|
||||
void _onData(void *data, size_t len);
|
||||
void _on_close();
|
||||
void _attachCallbacks();
|
||||
};
|
||||
|
||||
#endif /* ASYNCPRINTER_H_ */
|
||||
@@ -0,0 +1,127 @@
|
||||
#ifndef _DEBUG_PRINT_MACROS_H
|
||||
#define _DEBUG_PRINT_MACROS_H
|
||||
|
||||
// Some customizable print macros to suite the debug needs de jour.
|
||||
|
||||
// Debug macros
|
||||
// #include <pgmspace.h>
|
||||
// https://stackoverflow.com/questions/8487986/file-macro-shows-full-path
|
||||
// This value is resolved at compile time.
|
||||
#define _FILENAME_ strrchr("/" __FILE__, '/')
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
#if defined(DEBUG_ESP_PORT) && !defined(DEBUG_TIME_STAMP_FMT)
|
||||
#define DEBUG_TIME_STAMP_FMT "%06u.%03u "
|
||||
|
||||
struct _DEBUG_TIME_STAMP
|
||||
{
|
||||
unsigned dec;
|
||||
unsigned whole;
|
||||
};
|
||||
|
||||
inline struct _DEBUG_TIME_STAMP debugTimeStamp()
|
||||
{
|
||||
struct _DEBUG_TIME_STAMP st;
|
||||
unsigned now = millis() % 1000000000;
|
||||
st.dec = now % 1000;
|
||||
st.whole = now / 1000;
|
||||
return st;
|
||||
}
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
#if defined(DEBUG_ESP_PORT) && !defined(DEBUG_GENERIC)
|
||||
#define DEBUG_GENERIC( module, format, ... ) \
|
||||
do { \
|
||||
struct _DEBUG_TIME_STAMP st = debugTimeStamp(); \
|
||||
DEBUG_ESP_PORT.printf( DEBUG_TIME_STAMP_FMT module " " format, st.whole, st.dec, ##__VA_ARGS__ ); \
|
||||
} while(false)
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
#if defined(DEBUG_ESP_PORT) && !defined(DEBUG_GENERIC_P)
|
||||
#define DEBUG_GENERIC_P( module, format, ... ) \
|
||||
do { \
|
||||
struct _DEBUG_TIME_STAMP st = debugTimeStamp(); \
|
||||
DEBUG_ESP_PORT.printf_P(PSTR( DEBUG_TIME_STAMP_FMT module " " format ), st.whole, st.dec, ##__VA_ARGS__ ); \
|
||||
} while(false)
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
#if defined(DEBUG_GENERIC) && !defined(ASSERT_GENERIC)
|
||||
#define ASSERT_GENERIC( a, module ) \
|
||||
do { \
|
||||
if ( !(a) ) { \
|
||||
DEBUG_GENERIC( module, "%s:%s:%u: ASSERT("#a") failed!\n", __FILE__, __func__, __LINE__); \
|
||||
DEBUG_ESP_PORT.flush(); \
|
||||
} \
|
||||
} while(false)
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
#if defined(DEBUG_GENERIC_P) && !defined(ASSERT_GENERIC_P)
|
||||
#define ASSERT_GENERIC_P( a, module ) \
|
||||
do { \
|
||||
if ( !(a) ) { \
|
||||
DEBUG_GENERIC_P( module, "%s:%s:%u: ASSERT("#a") failed!\n", __FILE__, __func__, __LINE__); \
|
||||
DEBUG_ESP_PORT.flush(); \
|
||||
} \
|
||||
} while(false)
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef DEBUG_GENERIC
|
||||
#define DEBUG_GENERIC(...) do { (void)0;} while(false)
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef DEBUG_GENERIC_P
|
||||
#define DEBUG_GENERIC_P(...) do { (void)0;} while(false)
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef ASSERT_GENERIC
|
||||
#define ASSERT_GENERIC(...) do { (void)0;} while(false)
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef ASSERT_GENERIC_P
|
||||
#define ASSERT_GENERIC_P(...) do { (void)0;} while(false)
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef DEBUG_ESP_PRINTF
|
||||
#define DEBUG_ESP_PRINTF( format, ...) DEBUG_GENERIC_P("[%s]", format, &_FILENAME_[1], ##__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
#if defined(DEBUG_ESP_ASYNC_TCP) && !defined(ASYNC_TCP_DEBUG)
|
||||
#define ASYNC_TCP_DEBUG( format, ...) DEBUG_GENERIC_P("[ASYNC_TCP]", format, ##__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef ASYNC_TCP_ASSERT
|
||||
#define ASYNC_TCP_ASSERT( a ) ASSERT_GENERIC_P( (a), "[ASYNC_TCP]")
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
#if defined(DEBUG_ESP_TCP_SSL) && !defined(TCP_SSL_DEBUG)
|
||||
#define TCP_SSL_DEBUG( format, ...) DEBUG_GENERIC_P("[TCP_SSL]", format, ##__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
#endif //_DEBUG_PRINT_MACROS_H
|
||||
2056
WiFiX-Enhanced/.pio/libdeps/esp32_main/RPAsyncTCP/src/RPAsyncTCP.cpp
Normal file
2056
WiFiX-Enhanced/.pio/libdeps/esp32_main/RPAsyncTCP/src/RPAsyncTCP.cpp
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,417 @@
|
||||
#ifndef RPAsyncTCP_H_
|
||||
#define RPAsyncTCP_H_
|
||||
|
||||
#include "Arduino.h"
|
||||
#include <WiFi.h>
|
||||
|
||||
#if ASYNC_TCP_SSL_ENABLED
|
||||
#undef ASYNC_TCP_SSL_ENABLED
|
||||
#define ASYNC_TCP_SSL_ENABLED false
|
||||
|
||||
#warning ASYNC_TCP_SSL_ENABLED is not ready yet. Disable it
|
||||
#endif
|
||||
|
||||
#define DEBUG_ESP_ASYNC_TCP true
|
||||
#include "RPAsyncTCP_Debug.h"
|
||||
|
||||
#include <async_config.h>
|
||||
#include "IPAddress.h"
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
|
||||
extern "C"
|
||||
{
|
||||
#include "lwip/ip_addr.h"
|
||||
#include "lwip/err.h"
|
||||
#include "lwip/tcp.h"
|
||||
#include "lwip/pbuf.h"
|
||||
};
|
||||
|
||||
#ifndef RPAsyncTCP_UNUSED
|
||||
#define RPAsyncTCP_UNUSED(x) (void)(x)
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////
|
||||
|
||||
class AsyncClient;
|
||||
class AsyncServer;
|
||||
class ACErrorTracker;
|
||||
|
||||
#define ASYNC_MAX_ACK_TIME 5000
|
||||
#define ASYNC_WRITE_FLAG_COPY 0x01 //to allocate new buffer to hold the data while sending
|
||||
#define ASYNC_WRITE_FLAG_MORE 0x02 //not send PSH flag. More data to be sent before the application should react.
|
||||
|
||||
/////////////////////////////////////////////////
|
||||
|
||||
struct tcp_pcb;
|
||||
|
||||
#if ASYNC_TCP_SSL_ENABLED
|
||||
struct SSL_;
|
||||
typedef struct SSL_ SSL;
|
||||
struct SSL_CTX_;
|
||||
typedef struct SSL_CTX_ SSL_CTX;
|
||||
#endif
|
||||
|
||||
typedef std::function<void(void*, AsyncClient*)> AcConnectHandler;
|
||||
typedef std::function<void(void*, AsyncClient*, size_t len, uint32_t time)> AcAckHandler;
|
||||
typedef std::function<void(void*, AsyncClient*, err_t error)> AcErrorHandler;
|
||||
typedef std::function<void(void*, AsyncClient*, void *data, size_t len)> AcDataHandler;
|
||||
typedef std::function<void(void*, AsyncClient*, struct pbuf *pb)> AcPacketHandler;
|
||||
typedef std::function<void(void*, AsyncClient*, uint32_t time)> AcTimeoutHandler;
|
||||
typedef std::function<void(void*, size_t event)> AsNotifyHandler;
|
||||
|
||||
enum error_events
|
||||
{
|
||||
EE_OK = 0,
|
||||
EE_ABORTED, // Callback or foreground aborted connections
|
||||
EE_ERROR_CB, // Stack initiated aborts via error Callbacks.
|
||||
EE_CONNECTED_CB,
|
||||
EE_RECV_CB,
|
||||
EE_ACCEPT_CB,
|
||||
EE_MAX
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////
|
||||
|
||||
// DEBUG_MORE is for gathering more information on which CBs close events are
|
||||
// occuring and count.
|
||||
// #define DEBUG_MORE 1
|
||||
class ACErrorTracker
|
||||
{
|
||||
private:
|
||||
AsyncClient *_client;
|
||||
err_t _close_error;
|
||||
int _errored;
|
||||
|
||||
#if DEBUG_ESP_ASYNC_TCP
|
||||
size_t _connectionId;
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_MORE
|
||||
AsNotifyHandler _error_event_cb;
|
||||
void* _error_event_cb_arg;
|
||||
#endif
|
||||
|
||||
protected:
|
||||
friend class AsyncClient;
|
||||
friend class AsyncServer;
|
||||
|
||||
#ifdef DEBUG_MORE
|
||||
void onErrorEvent(AsNotifyHandler cb, void *arg);
|
||||
#endif
|
||||
|
||||
#if DEBUG_ESP_ASYNC_TCP
|
||||
void setConnectionId(size_t id)
|
||||
{
|
||||
_connectionId = id;
|
||||
}
|
||||
|
||||
size_t getConnectionId()
|
||||
{
|
||||
return _connectionId;
|
||||
}
|
||||
#endif
|
||||
|
||||
void setCloseError(err_t e);
|
||||
void setErrored(size_t errorEvent);
|
||||
err_t getCallbackCloseError();
|
||||
|
||||
void clearClient()
|
||||
{
|
||||
if (_client) _client = NULL;
|
||||
}
|
||||
|
||||
public:
|
||||
err_t getCloseError() const
|
||||
{
|
||||
return _close_error;
|
||||
}
|
||||
|
||||
bool hasClient() const
|
||||
{
|
||||
return (_client != NULL);
|
||||
}
|
||||
|
||||
ACErrorTracker(AsyncClient *c);
|
||||
~ACErrorTracker() {}
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////
|
||||
|
||||
class AsyncClient
|
||||
{
|
||||
protected:
|
||||
friend class AsyncTCPbuffer;
|
||||
friend class AsyncServer;
|
||||
tcp_pcb* _pcb;
|
||||
AcConnectHandler _connect_cb;
|
||||
void* _connect_cb_arg;
|
||||
AcConnectHandler _discard_cb;
|
||||
void* _discard_cb_arg;
|
||||
AcAckHandler _sent_cb;
|
||||
void* _sent_cb_arg;
|
||||
AcErrorHandler _error_cb;
|
||||
void* _error_cb_arg;
|
||||
AcDataHandler _recv_cb;
|
||||
void* _recv_cb_arg;
|
||||
AcPacketHandler _pb_cb;
|
||||
void* _pb_cb_arg;
|
||||
AcTimeoutHandler _timeout_cb;
|
||||
void* _timeout_cb_arg;
|
||||
AcConnectHandler _poll_cb;
|
||||
void* _poll_cb_arg;
|
||||
bool _pcb_busy;
|
||||
|
||||
#if ASYNC_TCP_SSL_ENABLED
|
||||
bool _pcb_secure;
|
||||
bool _handshake_done;
|
||||
#endif
|
||||
|
||||
uint32_t _pcb_sent_at;
|
||||
bool _close_pcb;
|
||||
bool _ack_pcb;
|
||||
uint32_t _tx_unacked_len;
|
||||
uint32_t _tx_acked_len;
|
||||
uint32_t _tx_unsent_len;
|
||||
uint32_t _rx_ack_len;
|
||||
uint32_t _rx_last_packet;
|
||||
uint32_t _rx_since_timeout;
|
||||
uint32_t _ack_timeout;
|
||||
uint16_t _connect_port;
|
||||
u8_t _recv_pbuf_flags;
|
||||
std::shared_ptr<ACErrorTracker> _errorTracker;
|
||||
|
||||
void _close();
|
||||
void _connected(std::shared_ptr<ACErrorTracker>& closeAbort, void* pcb, err_t err);
|
||||
void _error(err_t err);
|
||||
|
||||
#if ASYNC_TCP_SSL_ENABLED
|
||||
void _ssl_error(int8_t err);
|
||||
#endif
|
||||
|
||||
void _poll(std::shared_ptr<ACErrorTracker>& closeAbort, tcp_pcb* pcb);
|
||||
void _sent(std::shared_ptr<ACErrorTracker>& closeAbort, tcp_pcb* pcb, uint16_t len);
|
||||
|
||||
#if LWIP_VERSION_MAJOR == 1
|
||||
void _dns_found(struct ip_addr *ipaddr);
|
||||
#else
|
||||
void _dns_found(ip_addr_t *p);
|
||||
#endif
|
||||
|
||||
static err_t _s_poll(void *arg, struct tcp_pcb *tpcb);
|
||||
static err_t _s_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *pb, err_t err);
|
||||
static void _s_error(void *arg, err_t err);
|
||||
static err_t _s_sent(void *arg, struct tcp_pcb *tpcb, uint16_t len);
|
||||
static err_t _s_connected(void* arg, void* tpcb, err_t err);
|
||||
|
||||
#if LWIP_VERSION_MAJOR == 1
|
||||
static void _s_dns_found(const char *name, struct ip_addr *ipaddr, void *arg);
|
||||
#else
|
||||
static void _s_dns_found(const char *name, ip_addr_t *p, void *arg);
|
||||
#endif
|
||||
|
||||
#if ASYNC_TCP_SSL_ENABLED
|
||||
static void _s_data(void *arg, struct tcp_pcb *tcp, uint8_t * data, size_t len);
|
||||
static void _s_handshake(void *arg, struct tcp_pcb *tcp, SSL *ssl);
|
||||
static void _s_ssl_error(void *arg, struct tcp_pcb *tcp, int8_t err);
|
||||
#endif
|
||||
|
||||
std::shared_ptr<ACErrorTracker> getACErrorTracker() const
|
||||
{
|
||||
return _errorTracker;
|
||||
};
|
||||
|
||||
void setCloseError(err_t e) const
|
||||
{
|
||||
_errorTracker->setCloseError(e);
|
||||
}
|
||||
|
||||
public:
|
||||
AsyncClient* prev;
|
||||
AsyncClient* next;
|
||||
|
||||
#if ASYNC_TCP_SSL_ENABLED
|
||||
AsyncClient(tcp_pcb* pcb = 0, SSL_CTX * ssl_ctx = NULL);
|
||||
#else
|
||||
AsyncClient(tcp_pcb* pcb = 0);
|
||||
#endif
|
||||
|
||||
~AsyncClient();
|
||||
|
||||
AsyncClient & operator=(const AsyncClient &other);
|
||||
AsyncClient & operator+=(const AsyncClient &other);
|
||||
|
||||
bool operator==(const AsyncClient &other) const;
|
||||
|
||||
bool operator!=(const AsyncClient &other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
#if ASYNC_TCP_SSL_ENABLED
|
||||
bool connect(IPAddress ip, uint16_t port, bool secure = false);
|
||||
bool connect(const char* host, uint16_t port, bool secure = false);
|
||||
#else
|
||||
bool connect(IPAddress ip, uint16_t port);
|
||||
bool connect(const char* host, uint16_t port);
|
||||
#endif
|
||||
|
||||
void close(bool now = false);
|
||||
void stop();
|
||||
void abort();
|
||||
bool free();
|
||||
|
||||
bool canSend() const;//ack is not pending
|
||||
size_t space() const;
|
||||
size_t add(const char* data, size_t size, uint8_t apiflags = 0); //add for sending
|
||||
bool send();//send all data added with the method above
|
||||
size_t ack(size_t len); //ack data that you have not acked using the method below
|
||||
|
||||
void ackLater()
|
||||
{
|
||||
_ack_pcb = false; //will not ack the current packet. Call from onData
|
||||
}
|
||||
|
||||
bool isRecvPush()
|
||||
{
|
||||
return !!(_recv_pbuf_flags & PBUF_FLAG_PUSH);
|
||||
}
|
||||
|
||||
#if DEBUG_ESP_ASYNC_TCP
|
||||
size_t getConnectionId() const
|
||||
{
|
||||
return _errorTracker->getConnectionId();
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ASYNC_TCP_SSL_ENABLED
|
||||
SSL *getSSL();
|
||||
#endif
|
||||
|
||||
size_t write(const char* data);
|
||||
size_t write(const char* data, size_t size, uint8_t apiflags = 0); //only when canSend() == true
|
||||
|
||||
uint8_t state() const;
|
||||
bool connecting() const;
|
||||
bool connected() const;
|
||||
bool disconnecting() const;
|
||||
bool disconnected() const;
|
||||
bool freeable() const;//disconnected or disconnecting
|
||||
|
||||
uint16_t getMss() const;
|
||||
uint32_t getRxTimeout() const;
|
||||
void setRxTimeout(uint32_t timeout);//no RX data timeout for the connection in seconds
|
||||
uint32_t getAckTimeout() const;
|
||||
void setAckTimeout(uint32_t timeout);//no ACK timeout for the last sent packet in milliseconds
|
||||
void setNoDelay(bool nodelay);
|
||||
bool getNoDelay() const;
|
||||
uint32_t getRemoteAddress() const;
|
||||
uint16_t getRemotePort() const;
|
||||
uint32_t getLocalAddress() const;
|
||||
uint16_t getLocalPort() const;
|
||||
|
||||
IPAddress remoteIP() const;
|
||||
uint16_t remotePort() const;
|
||||
IPAddress localIP() const;
|
||||
uint16_t localPort() const;
|
||||
|
||||
void onConnect(AcConnectHandler cb, void* arg = 0); //on successful connect
|
||||
void onDisconnect(AcConnectHandler cb, void* arg = 0); //disconnected
|
||||
void onAck(AcAckHandler cb, void* arg = 0); //ack received
|
||||
void onError(AcErrorHandler cb, void* arg = 0); //unsuccessful connect or error
|
||||
void onData(AcDataHandler cb, void* arg = 0); //data received (called if onPacket is not used)
|
||||
void onPacket(AcPacketHandler cb, void* arg = 0); //data received
|
||||
void onTimeout(AcTimeoutHandler cb, void* arg = 0); //ack timeout
|
||||
void onPoll(AcConnectHandler cb, void* arg = 0); //every 125ms when connected
|
||||
void ackPacket(struct pbuf * pb);
|
||||
|
||||
const char * errorToString(err_t error) const;
|
||||
const char * stateToString() const;
|
||||
|
||||
void _recv(std::shared_ptr<ACErrorTracker>& closeAbort, tcp_pcb* pcb, pbuf* pb, err_t err);
|
||||
|
||||
err_t getCloseError() const
|
||||
{
|
||||
return _errorTracker->getCloseError();
|
||||
}
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////
|
||||
|
||||
#if ASYNC_TCP_SSL_ENABLED
|
||||
typedef std::function<int(void* arg, const char *filename, uint8_t **buf)> AcSSlFileHandler;
|
||||
struct pending_pcb;
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////
|
||||
|
||||
class AsyncServer
|
||||
{
|
||||
protected:
|
||||
uint16_t _port;
|
||||
IPAddress _addr;
|
||||
bool _noDelay;
|
||||
tcp_pcb* _pcb;
|
||||
AcConnectHandler _connect_cb;
|
||||
void* _connect_cb_arg;
|
||||
|
||||
#if ASYNC_TCP_SSL_ENABLED
|
||||
struct pending_pcb * _pending;
|
||||
SSL_CTX * _ssl_ctx;
|
||||
AcSSlFileHandler _file_cb;
|
||||
void* _file_cb_arg;
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_MORE
|
||||
int _event_count[EE_MAX];
|
||||
#endif
|
||||
|
||||
public:
|
||||
|
||||
AsyncServer(IPAddress addr, uint16_t port);
|
||||
AsyncServer(uint16_t port);
|
||||
~AsyncServer();
|
||||
void onClient(AcConnectHandler cb, void* arg);
|
||||
|
||||
#if ASYNC_TCP_SSL_ENABLED
|
||||
void onSslFileRequest(AcSSlFileHandler cb, void* arg);
|
||||
void beginSecure(const char *cert, const char *private_key_file, const char *password);
|
||||
#endif
|
||||
|
||||
void begin();
|
||||
void end();
|
||||
void setNoDelay(bool nodelay);
|
||||
bool getNoDelay() const;
|
||||
uint8_t status() const;
|
||||
|
||||
#ifdef DEBUG_MORE
|
||||
int getEventCount(size_t ee) const
|
||||
{
|
||||
return _event_count[ee];
|
||||
}
|
||||
#endif
|
||||
|
||||
protected:
|
||||
err_t _accept(tcp_pcb* newpcb, err_t err);
|
||||
static err_t _s_accept(void *arg, tcp_pcb* newpcb, err_t err);
|
||||
|
||||
#ifdef DEBUG_MORE
|
||||
int incEventCount(size_t ee)
|
||||
{
|
||||
return ++_event_count[ee];
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ASYNC_TCP_SSL_ENABLED
|
||||
int _cert(const char *filename, uint8_t **buf);
|
||||
err_t _poll(tcp_pcb* pcb);
|
||||
err_t _recv(tcp_pcb *pcb, struct pbuf *pb, err_t err);
|
||||
static int _s_cert(void *arg, const char *filename, uint8_t **buf);
|
||||
static err_t _s_poll(void *arg, struct tcp_pcb *tpcb);
|
||||
static err_t _s_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *pb, err_t err);
|
||||
#endif
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////
|
||||
|
||||
#endif /* RPAsyncTCP_H_ */
|
||||
@@ -0,0 +1,65 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef RPAsyncTCP_DEBUG_H
|
||||
#define RPAsyncTCP_DEBUG_H
|
||||
|
||||
#ifdef RPAsyncTCP_DEBUG_PORT
|
||||
#define DBG_PORT_ATCP RPAsyncTCP_DEBUG_PORT
|
||||
#else
|
||||
#define DBG_PORT_ATCP Serial
|
||||
#endif
|
||||
|
||||
// Change _RPAsyncTCP_LOGLEVEL_ to set tracing and logging verbosity
|
||||
// 0: DISABLED: no logging
|
||||
// 1: ERROR: errors
|
||||
// 2: WARN: errors and warnings
|
||||
// 3: INFO: errors, warnings and informational (default)
|
||||
// 4: DEBUG: errors, warnings, informational and debug
|
||||
|
||||
#ifndef _RPAsyncTCP_LOGLEVEL_
|
||||
#define _RPAsyncTCP_LOGLEVEL_ 1
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
#define ATCP_PRINT_MARK ATCP_PRINT("[ATCP] ")
|
||||
#define ATCP_PRINT_SP DBG_PORT_ATCP.print(" ")
|
||||
|
||||
#define ATCP_PRINT DBG_PORT_ATCP.print
|
||||
#define ATCP_PRINTLN DBG_PORT_ATCP.println
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
#define ATCP_LOGERROR(x) if(_RPAsyncTCP_LOGLEVEL_>0) { ATCP_PRINT_MARK; ATCP_PRINTLN(x); }
|
||||
#define ATCP_LOGERROR0(x) if(_RPAsyncTCP_LOGLEVEL_>0) { ATCP_PRINT(x); }
|
||||
#define ATCP_LOGERROR1(x,y) if(_RPAsyncTCP_LOGLEVEL_>0) { ATCP_PRINT_MARK; ATCP_PRINT(x); ATCP_PRINT_SP; ATCP_PRINTLN(y); }
|
||||
#define ATCP_LOGERROR2(x,y,z) if(_RPAsyncTCP_LOGLEVEL_>0) { ATCP_PRINT_MARK; ATCP_PRINT(x); ATCP_PRINT_SP; ATCP_PRINT(y); ATCP_PRINT_SP; ATCP_PRINTLN(z); }
|
||||
#define ATCP_LOGERROR3(x,y,z,w) if(_RPAsyncTCP_LOGLEVEL_>0) { ATCP_PRINT_MARK; ATCP_PRINT(x); ATCP_PRINT_SP; ATCP_PRINT(y); ATCP_PRINT_SP; ATCP_PRINT(z); ATCP_PRINT_SP; ATCP_PRINTLN(w); }
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
#define ATCP_LOGWARN(x) if(_RPAsyncTCP_LOGLEVEL_>1) { ATCP_PRINT_MARK; ATCP_PRINTLN(x); }
|
||||
#define ATCP_LOGWARN0(x) if(_RPAsyncTCP_LOGLEVEL_>1) { ATCP_PRINT(x); }
|
||||
#define ATCP_LOGWARN1(x,y) if(_RPAsyncTCP_LOGLEVEL_>1) { ATCP_PRINT_MARK; ATCP_PRINT(x); ATCP_PRINT_SP; ATCP_PRINTLN(y); }
|
||||
#define ATCP_LOGWARN2(x,y,z) if(_RPAsyncTCP_LOGLEVEL_>1) { ATCP_PRINT_MARK; ATCP_PRINT(x); ATCP_PRINT_SP; ATCP_PRINT(y); ATCP_PRINT_SP; ATCP_PRINTLN(z); }
|
||||
#define ATCP_LOGWARN3(x,y,z,w) if(_RPAsyncTCP_LOGLEVEL_>1) { ATCP_PRINT_MARK; ATCP_PRINT(x); ATCP_PRINT_SP; ATCP_PRINT(y); ATCP_PRINT_SP; ATCP_PRINT(z); ATCP_PRINT_SP; ATCP_PRINTLN(w); }
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
#define ATCP_LOGINFO(x) if(_RPAsyncTCP_LOGLEVEL_>2) { ATCP_PRINT_MARK; ATCP_PRINTLN(x); }
|
||||
#define ATCP_LOGINFO0(x) if(_RPAsyncTCP_LOGLEVEL_>2) { ATCP_PRINT(x); }
|
||||
#define ATCP_LOGINFO1(x,y) if(_RPAsyncTCP_LOGLEVEL_>2) { ATCP_PRINT_MARK; ATCP_PRINT(x); ATCP_PRINT_SP; ATCP_PRINTLN(y); }
|
||||
#define ATCP_LOGINFO2(x,y,z) if(_RPAsyncTCP_LOGLEVEL_>2) { ATCP_PRINT_MARK; ATCP_PRINT(x); ATCP_PRINT_SP; ATCP_PRINT(y); ATCP_PRINT_SP; ATCP_PRINTLN(z); }
|
||||
#define ATCP_LOGINFO3(x,y,z,w) if(_RPAsyncTCP_LOGLEVEL_>2) { ATCP_PRINT_MARK; ATCP_PRINT(x); ATCP_PRINT_SP; ATCP_PRINT(y); ATCP_PRINT_SP; ATCP_PRINT(z); ATCP_PRINT_SP; ATCP_PRINTLN(w); }
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
#define ATCP_LOGDEBUG(x) if(_RPAsyncTCP_LOGLEVEL_>3) { ATCP_PRINT_MARK; ATCP_PRINTLN(x); }
|
||||
#define ATCP_LOGDEBUG0(x) if(_RPAsyncTCP_LOGLEVEL_>3) { ATCP_PRINT(x); }
|
||||
#define ATCP_LOGDEBUG1(x,y) if(_RPAsyncTCP_LOGLEVEL_>3) { ATCP_PRINT_MARK; ATCP_PRINT(x); ATCP_PRINT_SP; ATCP_PRINTLN(y); }
|
||||
#define ATCP_LOGDEBUG2(x,y,z) if(_RPAsyncTCP_LOGLEVEL_>3) { ATCP_PRINT_MARK; ATCP_PRINT(x); ATCP_PRINT_SP; ATCP_PRINT(y); ATCP_PRINT_SP; ATCP_PRINTLN(z); }
|
||||
#define ATCP_LOGDEBUG3(x,y,z,w) if(_RPAsyncTCP_LOGLEVEL_>3) { ATCP_PRINT_MARK; ATCP_PRINT(x); ATCP_PRINT_SP; ATCP_PRINT(y); ATCP_PRINT_SP; ATCP_PRINT(z); ATCP_PRINT_SP; ATCP_PRINTLN(w); }
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
#endif //RPAsyncTCP_DEBUG_H
|
||||
@@ -0,0 +1,721 @@
|
||||
#include <Arduino.h>
|
||||
#include "debug.h"
|
||||
|
||||
#if !defined(_RPAsyncTCP_LOGLEVEL_)
|
||||
#define _RPAsyncTCP_LOGLEVEL_ 1
|
||||
#endif
|
||||
|
||||
#include "RPAsyncTCP_buffer.h"
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
AsyncTCPbuffer::AsyncTCPbuffer(AsyncClient* client)
|
||||
{
|
||||
if (client == NULL)
|
||||
{
|
||||
ATCP_LOGDEBUG("client is null!!!");
|
||||
panic();
|
||||
}
|
||||
|
||||
_client = client;
|
||||
_TXbufferWrite = new (std::nothrow) cbuf(TCP_MSS);
|
||||
_TXbufferRead = _TXbufferWrite;
|
||||
_RXbuffer = new (std::nothrow) cbuf(100);
|
||||
_RXmode = ATB_RX_MODE_FREE;
|
||||
_rxSize = 0;
|
||||
_rxTerminator = 0x00;
|
||||
_rxReadBytesPtr = NULL;
|
||||
_rxReadStringPtr = NULL;
|
||||
_cbDisconnect = NULL;
|
||||
|
||||
_cbRX = NULL;
|
||||
_cbDone = NULL;
|
||||
_attachCallbacks();
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
AsyncTCPbuffer::~AsyncTCPbuffer()
|
||||
{
|
||||
if (_client)
|
||||
{
|
||||
_client->close();
|
||||
}
|
||||
|
||||
if (_RXbuffer)
|
||||
{
|
||||
delete _RXbuffer;
|
||||
_RXbuffer = NULL;
|
||||
}
|
||||
|
||||
if (_TXbufferWrite)
|
||||
{
|
||||
// will be deleted in _TXbufferRead chain
|
||||
_TXbufferWrite = NULL;
|
||||
}
|
||||
|
||||
if (_TXbufferRead)
|
||||
{
|
||||
cbuf * next = _TXbufferRead->next;
|
||||
delete _TXbufferRead;
|
||||
|
||||
while (next != NULL)
|
||||
{
|
||||
_TXbufferRead = next;
|
||||
next = _TXbufferRead->next;
|
||||
delete _TXbufferRead;
|
||||
}
|
||||
|
||||
_TXbufferRead = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
size_t AsyncTCPbuffer::write(String & data)
|
||||
{
|
||||
return write(data.c_str(), data.length());
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
size_t AsyncTCPbuffer::write(uint8_t data)
|
||||
{
|
||||
return write(&data, 1);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
size_t AsyncTCPbuffer::write(const char* data)
|
||||
{
|
||||
return write((const uint8_t *) data, strlen(data));
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
size_t AsyncTCPbuffer::write(const char *data, size_t len)
|
||||
{
|
||||
return write((const uint8_t *) data, len);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
write data in to buffer and try to send the data
|
||||
@param data
|
||||
@param len
|
||||
@return
|
||||
*/
|
||||
size_t AsyncTCPbuffer::write(const uint8_t *data, size_t len)
|
||||
{
|
||||
if (_TXbufferWrite == NULL || _client == NULL || !_client->connected() || data == NULL || len == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t bytesLeft = len;
|
||||
|
||||
while (bytesLeft)
|
||||
{
|
||||
size_t w = _TXbufferWrite->write((const char*) data, bytesLeft);
|
||||
bytesLeft -= w;
|
||||
data += w;
|
||||
|
||||
_sendBuffer();
|
||||
|
||||
// add new buffer since we have more data
|
||||
if (_TXbufferWrite->full() && bytesLeft > 0)
|
||||
{
|
||||
/*
|
||||
// to less ram!!!
|
||||
if(ESP.getFreeHeap() < 4096) {
|
||||
ATCP_LOGDEBUG("run out of Heap can not send all Data!");
|
||||
return (len - bytesLeft);
|
||||
}
|
||||
*/
|
||||
cbuf * next = new (std::nothrow) cbuf(TCP_MSS);
|
||||
|
||||
if (next == NULL)
|
||||
{
|
||||
ATCP_LOGDEBUG("run out of Heap!");
|
||||
panic();
|
||||
}
|
||||
else
|
||||
{
|
||||
ATCP_LOGDEBUG("new cbuf");
|
||||
}
|
||||
|
||||
// add new buffer to chain (current cbuf)
|
||||
_TXbufferWrite->next = next;
|
||||
|
||||
// move ptr for next data
|
||||
_TXbufferWrite = next;
|
||||
}
|
||||
}
|
||||
|
||||
return len;
|
||||
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
wait until all data has send out
|
||||
*/
|
||||
void AsyncTCPbuffer::flush()
|
||||
{
|
||||
while (!_TXbufferWrite->empty())
|
||||
{
|
||||
while (connected() && !_client->canSend())
|
||||
{
|
||||
delay(0);
|
||||
}
|
||||
|
||||
if (!connected())
|
||||
return;
|
||||
_sendBuffer();
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
void AsyncTCPbuffer::noCallback()
|
||||
{
|
||||
_RXmode = ATB_RX_MODE_NONE;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
void AsyncTCPbuffer::readStringUntil(char terminator, String * str, AsyncTCPbufferDoneCb done)
|
||||
{
|
||||
if (_client == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ATCP_LOGDEBUG1("readStringUntil terminator:", terminator);
|
||||
|
||||
_RXmode = ATB_RX_MODE_NONE;
|
||||
_cbDone = done;
|
||||
_rxReadStringPtr = str;
|
||||
_rxTerminator = terminator;
|
||||
_rxSize = 0;
|
||||
_RXmode = ATB_RX_MODE_TERMINATOR_STRING;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
/*
|
||||
void AsyncTCPbuffer::readBytesUntil(char terminator, char *buffer, size_t length, AsyncTCPbufferDoneCb done)
|
||||
{
|
||||
_RXmode = ATB_RX_MODE_NONE;
|
||||
_cbDone = done;
|
||||
_rxReadBytesPtr = (uint8_t *) buffer;
|
||||
_rxTerminator = terminator;
|
||||
_rxSize = length;
|
||||
_RXmode = ATB_RX_MODE_TERMINATOR;
|
||||
_handleRxBuffer(NULL, 0);
|
||||
}
|
||||
|
||||
void AsyncTCPbuffer::readBytesUntil(char terminator, uint8_t *buffer, size_t length, AsyncTCPbufferDoneCb done)
|
||||
{
|
||||
readBytesUntil(terminator, (char *) buffer, length, done);
|
||||
}
|
||||
*/
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
void AsyncTCPbuffer::readBytes(char *buffer, size_t length, AsyncTCPbufferDoneCb done)
|
||||
{
|
||||
if (_client == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ATCP_LOGDEBUG1("readBytes length:", length);
|
||||
_RXmode = ATB_RX_MODE_NONE;
|
||||
_cbDone = done;
|
||||
_rxReadBytesPtr = (uint8_t *) buffer;
|
||||
_rxSize = length;
|
||||
_RXmode = ATB_RX_MODE_READ_BYTES;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
void AsyncTCPbuffer::readBytes(uint8_t *buffer, size_t length, AsyncTCPbufferDoneCb done)
|
||||
{
|
||||
readBytes((char *) buffer, length, done);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
void AsyncTCPbuffer::onData(AsyncTCPbufferDataCb cb)
|
||||
{
|
||||
if (_client == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ATCP_LOGDEBUG("onData");
|
||||
|
||||
_RXmode = ATB_RX_MODE_NONE;
|
||||
_cbDone = NULL;
|
||||
_cbRX = cb;
|
||||
_RXmode = ATB_RX_MODE_FREE;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
void AsyncTCPbuffer::onDisconnect(AsyncTCPbufferDisconnectCb cb)
|
||||
{
|
||||
_cbDisconnect = cb;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
IPAddress AsyncTCPbuffer::remoteIP()
|
||||
{
|
||||
if (!_client)
|
||||
{
|
||||
return IPAddress(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
return _client->remoteIP();
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
uint16_t AsyncTCPbuffer::remotePort()
|
||||
{
|
||||
if (!_client)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return _client->remotePort();
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
bool AsyncTCPbuffer::connected()
|
||||
{
|
||||
if (!_client)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return _client->connected();
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
void AsyncTCPbuffer::stop()
|
||||
{
|
||||
|
||||
if (!_client)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_client->stop();
|
||||
_client = NULL;
|
||||
|
||||
if (_cbDone)
|
||||
{
|
||||
switch (_RXmode)
|
||||
{
|
||||
case ATB_RX_MODE_READ_BYTES:
|
||||
case ATB_RX_MODE_TERMINATOR:
|
||||
case ATB_RX_MODE_TERMINATOR_STRING:
|
||||
_RXmode = ATB_RX_MODE_NONE;
|
||||
_cbDone(false, NULL);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
_RXmode = ATB_RX_MODE_NONE;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
void AsyncTCPbuffer::close()
|
||||
{
|
||||
stop();
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
attachCallbacks to AsyncClient class
|
||||
*/
|
||||
void AsyncTCPbuffer::_attachCallbacks()
|
||||
{
|
||||
if (!_client)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ATCP_LOGDEBUG("attachCallbacks");
|
||||
|
||||
_client->onPoll([](void *obj, AsyncClient * c)
|
||||
{
|
||||
RPAsyncTCP_UNUSED(c);
|
||||
AsyncTCPbuffer* b = ((AsyncTCPbuffer*)(obj));
|
||||
|
||||
if ((b->_TXbufferRead != NULL) && !b->_TXbufferRead->empty())
|
||||
{
|
||||
b->_sendBuffer();
|
||||
}
|
||||
|
||||
// if(!b->_RXbuffer->empty()) {
|
||||
// b->_handleRxBuffer(NULL, 0);
|
||||
// }
|
||||
}, this);
|
||||
|
||||
_client->onAck([](void *obj, AsyncClient * c, size_t len, uint32_t time)
|
||||
{
|
||||
RPAsyncTCP_UNUSED(c);
|
||||
RPAsyncTCP_UNUSED(len);
|
||||
RPAsyncTCP_UNUSED(time);
|
||||
ATCP_LOGDEBUG("onAck");
|
||||
((AsyncTCPbuffer*)(obj))->_sendBuffer();
|
||||
}, this);
|
||||
|
||||
_client->onDisconnect([](void *obj, AsyncClient * c)
|
||||
{
|
||||
ATCP_LOGDEBUG("onDisconnect");
|
||||
AsyncTCPbuffer* b = ((AsyncTCPbuffer*)(obj));
|
||||
b->_client = NULL;
|
||||
bool del = true;
|
||||
|
||||
if (b->_cbDisconnect)
|
||||
{
|
||||
del = b->_cbDisconnect(b);
|
||||
}
|
||||
|
||||
delete c;
|
||||
|
||||
if (del)
|
||||
{
|
||||
delete b;
|
||||
}
|
||||
}, this);
|
||||
|
||||
_client->onData([](void *obj, AsyncClient * c, void *buf, size_t len)
|
||||
{
|
||||
RPAsyncTCP_UNUSED(c);
|
||||
AsyncTCPbuffer* b = ((AsyncTCPbuffer*)(obj));
|
||||
b->_rxData((uint8_t *)buf, len);
|
||||
}, this);
|
||||
|
||||
_client->onTimeout([](void *obj, AsyncClient * c, uint32_t time)
|
||||
{
|
||||
RPAsyncTCP_UNUSED(obj);
|
||||
RPAsyncTCP_UNUSED(time);
|
||||
|
||||
ATCP_LOGDEBUG("onTimeout");
|
||||
|
||||
c->close();
|
||||
}, this);
|
||||
|
||||
ATCP_LOGDEBUG("attachCallbacks Done.");
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
send TX buffer if possible
|
||||
*/
|
||||
void AsyncTCPbuffer::_sendBuffer()
|
||||
{
|
||||
//ATCP_LOGDEBUG("_sendBuffer...");
|
||||
size_t available = _TXbufferRead->available();
|
||||
|
||||
if (available == 0 || _client == NULL || !_client->connected() || !_client->canSend())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
while (connected() && (_client->space() > 0) && (_TXbufferRead->available() > 0) && _client->canSend())
|
||||
{
|
||||
available = _TXbufferRead->available();
|
||||
|
||||
if (available > _client->space())
|
||||
{
|
||||
available = _client->space();
|
||||
}
|
||||
|
||||
char *out = new (std::nothrow) char[available];
|
||||
|
||||
if (out == NULL)
|
||||
{
|
||||
ATCP_LOGDEBUG("to less heap, try later.");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// read data from buffer
|
||||
_TXbufferRead->peek(out, available);
|
||||
|
||||
// send data
|
||||
size_t send = _client->write((const char*) out, available);
|
||||
|
||||
if (send != available)
|
||||
{
|
||||
ATCP_LOGDEBUG3("_sendBuffer write failed send:", send, ", available:", available);
|
||||
|
||||
if (!connected())
|
||||
{
|
||||
ATCP_LOGDEBUG("incomplete transfer, connection lost.");
|
||||
}
|
||||
}
|
||||
|
||||
// remove really send data from buffer
|
||||
_TXbufferRead->remove(send);
|
||||
|
||||
// if buffer is empty and there is a other buffer in chain delete the empty one
|
||||
if (_TXbufferRead->available() == 0 && _TXbufferRead->next != NULL)
|
||||
{
|
||||
cbuf * old = _TXbufferRead;
|
||||
_TXbufferRead = _TXbufferRead->next;
|
||||
delete old;
|
||||
|
||||
ATCP_LOGDEBUG("delete cbuf");
|
||||
}
|
||||
|
||||
delete[] out;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
called on incoming data
|
||||
@param buf
|
||||
@param len
|
||||
*/
|
||||
void AsyncTCPbuffer::_rxData(uint8_t *buf, size_t len)
|
||||
{
|
||||
if (!_client || !_client->connected())
|
||||
{
|
||||
ATCP_LOGDEBUG("not connected!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_RXbuffer)
|
||||
{
|
||||
ATCP_LOGDEBUG("_rxData no _RXbuffer!");
|
||||
return;
|
||||
}
|
||||
|
||||
ATCP_LOGDEBUG3("_rxData len:", len, ", RXmode:", _RXmode);
|
||||
|
||||
size_t handled = 0;
|
||||
|
||||
if (_RXmode != ATB_RX_MODE_NONE)
|
||||
{
|
||||
handled = _handleRxBuffer((uint8_t *) buf, len);
|
||||
buf += handled;
|
||||
len -= handled;
|
||||
|
||||
// handle as much as possible before using the buffer
|
||||
if (_RXbuffer->empty())
|
||||
{
|
||||
while (_RXmode != ATB_RX_MODE_NONE && handled != 0 && len > 0)
|
||||
{
|
||||
handled = _handleRxBuffer(buf, len);
|
||||
buf += handled;
|
||||
len -= handled;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (len > 0)
|
||||
{
|
||||
|
||||
if (_RXbuffer->room() < len)
|
||||
{
|
||||
// to less space
|
||||
ATCP_LOGDEBUG("_rxData buffer full try resize");
|
||||
_RXbuffer->resizeAdd((len + _RXbuffer->room()));
|
||||
|
||||
if (_RXbuffer->room() < len)
|
||||
{
|
||||
ATCP_LOGDEBUG1("_rxData buffer to full can only handle:", _RXbuffer->room());
|
||||
}
|
||||
}
|
||||
|
||||
_RXbuffer->write((const char *) (buf), len);
|
||||
}
|
||||
|
||||
if (!_RXbuffer->empty() && _RXmode != ATB_RX_MODE_NONE)
|
||||
{
|
||||
// handle as much as possible data in buffer
|
||||
handled = _handleRxBuffer(NULL, 0);
|
||||
|
||||
while (_RXmode != ATB_RX_MODE_NONE && handled != 0)
|
||||
{
|
||||
handled = _handleRxBuffer(NULL, 0);
|
||||
}
|
||||
}
|
||||
|
||||
// clean up ram
|
||||
if (_RXbuffer->empty() && _RXbuffer->room() != 100)
|
||||
{
|
||||
_RXbuffer->resize(100);
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
size_t AsyncTCPbuffer::_handleRxBuffer(uint8_t *buf, size_t len)
|
||||
{
|
||||
if (!_client || !_client->connected() || _RXbuffer == NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
ATCP_LOGDEBUG3("_handleRxBuffer len:", len, ", RXmode:", _RXmode);
|
||||
|
||||
size_t BufferAvailable = _RXbuffer->available();
|
||||
size_t r = 0;
|
||||
|
||||
if (_RXmode == ATB_RX_MODE_NONE)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else if (_RXmode == ATB_RX_MODE_FREE)
|
||||
{
|
||||
if (_cbRX == NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (BufferAvailable > 0)
|
||||
{
|
||||
uint8_t * b = new (std::nothrow) uint8_t[BufferAvailable];
|
||||
|
||||
if (b == NULL)
|
||||
{
|
||||
panic(); //TODO: What action should this be ?
|
||||
}
|
||||
|
||||
_RXbuffer->peek((char *) b, BufferAvailable);
|
||||
r = _cbRX(b, BufferAvailable);
|
||||
_RXbuffer->remove(r);
|
||||
}
|
||||
|
||||
if (r == BufferAvailable && buf && (len > 0))
|
||||
{
|
||||
return _cbRX(buf, len);
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
else if (_RXmode == ATB_RX_MODE_READ_BYTES)
|
||||
{
|
||||
if (_rxReadBytesPtr == NULL || _cbDone == NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t newReadCount = 0;
|
||||
|
||||
if (BufferAvailable)
|
||||
{
|
||||
r = _RXbuffer->read((char *) _rxReadBytesPtr, _rxSize);
|
||||
_rxSize -= r;
|
||||
_rxReadBytesPtr += r;
|
||||
}
|
||||
|
||||
if (_RXbuffer->empty() && (len > 0) && buf)
|
||||
{
|
||||
r = len;
|
||||
|
||||
if (r > _rxSize)
|
||||
{
|
||||
r = _rxSize;
|
||||
}
|
||||
|
||||
memcpy(_rxReadBytesPtr, buf, r);
|
||||
_rxReadBytesPtr += r;
|
||||
_rxSize -= r;
|
||||
newReadCount += r;
|
||||
}
|
||||
|
||||
if (_rxSize == 0)
|
||||
{
|
||||
_RXmode = ATB_RX_MODE_NONE;
|
||||
_cbDone(true, NULL);
|
||||
}
|
||||
|
||||
// add left over bytes to Buffer
|
||||
return newReadCount;
|
||||
|
||||
}
|
||||
else if (_RXmode == ATB_RX_MODE_TERMINATOR)
|
||||
{
|
||||
// TODO implement read terminator non string
|
||||
|
||||
}
|
||||
else if (_RXmode == ATB_RX_MODE_TERMINATOR_STRING)
|
||||
{
|
||||
if (_rxReadStringPtr == NULL || _cbDone == NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// handle Buffer
|
||||
if (BufferAvailable > 0)
|
||||
{
|
||||
while (!_RXbuffer->empty())
|
||||
{
|
||||
char c = _RXbuffer->read();
|
||||
|
||||
if (c == _rxTerminator || c == 0x00)
|
||||
{
|
||||
_RXmode = ATB_RX_MODE_NONE;
|
||||
_cbDone(true, _rxReadStringPtr);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
(*_rxReadStringPtr) += c;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (_RXbuffer->empty() && (len > 0) && buf)
|
||||
{
|
||||
size_t newReadCount = 0;
|
||||
|
||||
while (newReadCount < len)
|
||||
{
|
||||
char c = (char) * buf;
|
||||
buf++;
|
||||
newReadCount++;
|
||||
|
||||
if (c == _rxTerminator || c == 0x00)
|
||||
{
|
||||
_RXmode = ATB_RX_MODE_NONE;
|
||||
_cbDone(true, _rxReadStringPtr);
|
||||
return newReadCount;
|
||||
}
|
||||
else
|
||||
{
|
||||
(*_rxReadStringPtr) += c;
|
||||
}
|
||||
}
|
||||
|
||||
return newReadCount;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
#ifndef RPAsyncTCP_BUFFER_H_
|
||||
#define RPAsyncTCP_BUFFER_H_
|
||||
|
||||
#ifndef DEBUG_ASYNC_TCP
|
||||
#define DEBUG_ASYNC_TCP(...)
|
||||
#endif
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <cbuf.h>
|
||||
|
||||
#include "RPAsyncTCP.h"
|
||||
|
||||
typedef enum
|
||||
{
|
||||
ATB_RX_MODE_NONE,
|
||||
ATB_RX_MODE_FREE,
|
||||
ATB_RX_MODE_READ_BYTES,
|
||||
ATB_RX_MODE_TERMINATOR,
|
||||
ATB_RX_MODE_TERMINATOR_STRING
|
||||
} atbRxMode_t;
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
class AsyncTCPbuffer: public Print
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
typedef std::function<size_t(uint8_t * payload, size_t length)> AsyncTCPbufferDataCb;
|
||||
typedef std::function<void(bool ok, void * ret)> AsyncTCPbufferDoneCb;
|
||||
typedef std::function<bool(AsyncTCPbuffer * obj)> AsyncTCPbufferDisconnectCb;
|
||||
|
||||
AsyncTCPbuffer(AsyncClient* c);
|
||||
virtual ~AsyncTCPbuffer();
|
||||
|
||||
size_t write(String & data);
|
||||
size_t write(uint8_t data);
|
||||
size_t write(const char* data);
|
||||
size_t write(const char *data, size_t len);
|
||||
size_t write(const uint8_t *data, size_t len);
|
||||
|
||||
void flush();
|
||||
|
||||
void noCallback();
|
||||
|
||||
void readStringUntil(char terminator, String * str, AsyncTCPbufferDoneCb done);
|
||||
|
||||
// TODO implement read terminator non string
|
||||
//void readBytesUntil(char terminator, char *buffer, size_t length, AsyncTCPbufferDoneCb done);
|
||||
//void readBytesUntil(char terminator, uint8_t *buffer, size_t length, AsyncTCPbufferDoneCb done);
|
||||
|
||||
void readBytes(char *buffer, size_t length, AsyncTCPbufferDoneCb done);
|
||||
void readBytes(uint8_t *buffer, size_t length, AsyncTCPbufferDoneCb done);
|
||||
|
||||
// TODO implement
|
||||
// void setTimeout(size_t timeout);
|
||||
|
||||
void onData(AsyncTCPbufferDataCb cb);
|
||||
void onDisconnect(AsyncTCPbufferDisconnectCb cb);
|
||||
|
||||
IPAddress remoteIP();
|
||||
uint16_t remotePort();
|
||||
IPAddress localIP();
|
||||
uint16_t localPort();
|
||||
|
||||
bool connected();
|
||||
|
||||
void stop();
|
||||
void close();
|
||||
|
||||
protected:
|
||||
AsyncClient* _client;
|
||||
cbuf * _TXbufferRead;
|
||||
cbuf * _TXbufferWrite;
|
||||
cbuf * _RXbuffer;
|
||||
atbRxMode_t _RXmode;
|
||||
size_t _rxSize;
|
||||
char _rxTerminator;
|
||||
uint8_t * _rxReadBytesPtr;
|
||||
String * _rxReadStringPtr;
|
||||
|
||||
AsyncTCPbufferDataCb _cbRX;
|
||||
AsyncTCPbufferDoneCb _cbDone;
|
||||
AsyncTCPbufferDisconnectCb _cbDisconnect;
|
||||
|
||||
void _attachCallbacks();
|
||||
void _sendBuffer();
|
||||
void _on_close();
|
||||
void _rxData(uint8_t *buf, size_t len);
|
||||
size_t _handleRxBuffer(uint8_t *buf, size_t len);
|
||||
};
|
||||
|
||||
#endif /* RPAsyncTCP_BUFFER_H_ */
|
||||
@@ -0,0 +1,615 @@
|
||||
#if !defined(_RPAsyncTCP_LOGLEVEL_)
|
||||
#define _RPAsyncTCP_LOGLEVEL_ 1
|
||||
#endif
|
||||
|
||||
#include "Arduino.h"
|
||||
#include "SyncClient.h"
|
||||
#include "RPAsyncTCP.h"
|
||||
#include "cbuf.h"
|
||||
|
||||
#define DEBUG_ESP_SYNC_CLIENT
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
#if defined(DEBUG_ESP_SYNC_CLIENT) && !defined(SYNC_CLIENT_DEBUG)
|
||||
#define SYNC_CLIENT_DEBUG( format, ...) DEBUG_GENERIC_P("[SYNC_CLIENT]", format, ##__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef SYNC_CLIENT_DEBUG
|
||||
#define SYNC_CLIENT_DEBUG(...) do { (void)0;} while(false)
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
/*
|
||||
Without LWIP_NETIF_TX_SINGLE_PBUF, all tcp_writes default to "no copy".
|
||||
Referenced data must be preserved and free-ed from the specified tcp_sent()
|
||||
callback. Alternative, tcp_writes need to use the TCP_WRITE_FLAG_COPY
|
||||
attribute.
|
||||
*/
|
||||
static_assert(LWIP_NETIF_TX_SINGLE_PBUF, "Required, tcp_write() must always copy.");
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
SyncClient::SyncClient(size_t txBufLen)
|
||||
: _client(NULL)
|
||||
, _tx_buffer(NULL)
|
||||
, _tx_buffer_size(txBufLen)
|
||||
, _rx_buffer(NULL)
|
||||
, _ref(NULL)
|
||||
{
|
||||
ref();
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
SyncClient::SyncClient(AsyncClient *client, size_t txBufLen)
|
||||
: _client(client)
|
||||
, _tx_buffer(new (std::nothrow) cbuf(txBufLen))
|
||||
, _tx_buffer_size(txBufLen)
|
||||
, _rx_buffer(NULL)
|
||||
, _ref(NULL)
|
||||
{
|
||||
if (ref() > 0 && _client != NULL)
|
||||
_attachCallbacks();
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
SyncClient::~SyncClient()
|
||||
{
|
||||
if (0 == unref())
|
||||
_release();
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
void SyncClient::_release()
|
||||
{
|
||||
if (_client != NULL)
|
||||
{
|
||||
_client->onData(NULL, NULL);
|
||||
_client->onAck(NULL, NULL);
|
||||
_client->onPoll(NULL, NULL);
|
||||
_client->abort();
|
||||
_client = NULL;
|
||||
}
|
||||
|
||||
if (_tx_buffer != NULL)
|
||||
{
|
||||
cbuf *b = _tx_buffer;
|
||||
_tx_buffer = NULL;
|
||||
delete b;
|
||||
}
|
||||
|
||||
while (_rx_buffer != NULL)
|
||||
{
|
||||
cbuf *b = _rx_buffer;
|
||||
_rx_buffer = _rx_buffer->next;
|
||||
delete b;
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
int SyncClient::ref()
|
||||
{
|
||||
if (_ref == NULL)
|
||||
{
|
||||
_ref = new (std::nothrow) int;
|
||||
|
||||
if (_ref != NULL)
|
||||
*_ref = 0;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
return (++*_ref);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
int SyncClient::unref()
|
||||
{
|
||||
int count = -1;
|
||||
|
||||
if (_ref != NULL)
|
||||
{
|
||||
count = --*_ref;
|
||||
|
||||
if (0 == count)
|
||||
{
|
||||
delete _ref;
|
||||
_ref = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
#if ASYNC_TCP_SSL_ENABLED
|
||||
int SyncClient::_connect(const IPAddress& ip, uint16_t port, bool secure)
|
||||
#else
|
||||
int SyncClient::_connect(const IPAddress& ip, uint16_t port)
|
||||
#endif
|
||||
{
|
||||
if (connected())
|
||||
return 0;
|
||||
|
||||
if (_client != NULL)
|
||||
delete _client;
|
||||
|
||||
_client = new (std::nothrow) AsyncClient();
|
||||
|
||||
if (_client == NULL)
|
||||
return 0;
|
||||
|
||||
_client->onConnect([](void *obj, AsyncClient * c)
|
||||
{
|
||||
((SyncClient*)(obj))->_onConnect(c);
|
||||
}, this);
|
||||
|
||||
_attachCallbacks_Disconnect();
|
||||
|
||||
#if ASYNC_TCP_SSL_ENABLED
|
||||
if (_client->connect(ip, port, secure))
|
||||
#else
|
||||
if (_client->connect(ip, port))
|
||||
#endif
|
||||
{
|
||||
while (_client != NULL && !_client->connected() && !_client->disconnecting())
|
||||
delay(1);
|
||||
|
||||
return connected();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
#if ASYNC_TCP_SSL_ENABLED
|
||||
int SyncClient::connect(const char *host, uint16_t port, bool secure)
|
||||
#else
|
||||
int SyncClient::connect(const char *host, uint16_t port)
|
||||
#endif
|
||||
{
|
||||
if (connected())
|
||||
return 0;
|
||||
|
||||
if (_client != NULL)
|
||||
delete _client;
|
||||
|
||||
_client = new (std::nothrow) AsyncClient();
|
||||
|
||||
if (_client == NULL)
|
||||
return 0;
|
||||
|
||||
_client->onConnect([](void *obj, AsyncClient * c)
|
||||
{
|
||||
((SyncClient*)(obj))->_onConnect(c);
|
||||
}, this);
|
||||
|
||||
_attachCallbacks_Disconnect();
|
||||
|
||||
#if ASYNC_TCP_SSL_ENABLED
|
||||
if (_client->connect(host, port, secure))
|
||||
#else
|
||||
if (_client->connect(host, port))
|
||||
#endif
|
||||
{
|
||||
while (_client != NULL && !_client->connected() && !_client->disconnecting())
|
||||
delay(1);
|
||||
|
||||
return connected();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
//#define SYNCCLIENT_NEW_OPERATOR_EQUAL
|
||||
#ifdef SYNCCLIENT_NEW_OPERATOR_EQUAL
|
||||
|
||||
/*
|
||||
New behavior for operator=
|
||||
|
||||
Allow for the object to be placed on a queue and transfered to a new container
|
||||
with buffers still in tact. Avoiding receive data drops. Transfers rx and tx
|
||||
buffers. Supports return by value.
|
||||
|
||||
Note, this is optional, the old behavior is the default.
|
||||
|
||||
*/
|
||||
SyncClient & SyncClient::operator=(const SyncClient &other)
|
||||
{
|
||||
int *rhsref = other._ref;
|
||||
++*rhsref; // Just in case the left and right side are the same object with different containers
|
||||
|
||||
if (0 == unref())
|
||||
_release();
|
||||
|
||||
_ref = other._ref;
|
||||
ref();
|
||||
--*rhsref;
|
||||
|
||||
// Why do I not test _tx_buffer for != NULL and free?
|
||||
// I allow for the lh target container, to be a copy of an active
|
||||
// connection. Thus we are just reusing the container.
|
||||
// The above unref() handles releaseing the previous client of the container.
|
||||
_tx_buffer_size = other._tx_buffer_size;
|
||||
_tx_buffer = other._tx_buffer;
|
||||
_client = other._client;
|
||||
|
||||
if (_client != NULL && _tx_buffer == NULL)
|
||||
_tx_buffer = new (std::nothrow) cbuf(_tx_buffer_size);
|
||||
|
||||
_rx_buffer = other._rx_buffer;
|
||||
|
||||
if (_client)
|
||||
_attachCallbacks();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
#else // ! SYNCCLIENT_NEW_OPERATOR_EQUAL
|
||||
|
||||
// This is the origianl logic with null checks
|
||||
SyncClient & SyncClient::operator=(const SyncClient &other)
|
||||
{
|
||||
if (_client != NULL)
|
||||
{
|
||||
_client->abort();
|
||||
_client->free();
|
||||
_client = NULL;
|
||||
}
|
||||
_tx_buffer_size = other._tx_buffer_size;
|
||||
|
||||
if (_tx_buffer != NULL)
|
||||
{
|
||||
cbuf *b = _tx_buffer;
|
||||
_tx_buffer = NULL;
|
||||
delete b;
|
||||
}
|
||||
|
||||
while (_rx_buffer != NULL)
|
||||
{
|
||||
cbuf *b = _rx_buffer;
|
||||
_rx_buffer = b->next;
|
||||
delete b;
|
||||
}
|
||||
|
||||
if (other._client != NULL)
|
||||
_tx_buffer = new (std::nothrow) cbuf(other._tx_buffer_size);
|
||||
|
||||
_client = other._client;
|
||||
|
||||
if (_client)
|
||||
_attachCallbacks();
|
||||
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
void SyncClient::setTimeout(uint32_t seconds)
|
||||
{
|
||||
if (_client != NULL)
|
||||
_client->setRxTimeout(seconds);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
uint8_t SyncClient::status()
|
||||
{
|
||||
if (_client == NULL)
|
||||
return 0;
|
||||
|
||||
return _client->state();
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
uint8_t SyncClient::connected()
|
||||
{
|
||||
return (_client != NULL && _client->connected());
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
bool SyncClient::stop(unsigned int maxWaitMs)
|
||||
{
|
||||
RPAsyncTCP_UNUSED(maxWaitMs);
|
||||
|
||||
if (_client != NULL)
|
||||
_client->close(true);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
size_t SyncClient::_sendBuffer()
|
||||
{
|
||||
if (_client == NULL || _tx_buffer == NULL)
|
||||
return 0;
|
||||
|
||||
size_t available = _tx_buffer->available();
|
||||
|
||||
if ( !connected() || !_client->canSend() || (available == 0) )
|
||||
return 0;
|
||||
|
||||
size_t sendable = _client->space();
|
||||
|
||||
if (sendable < available)
|
||||
available = sendable;
|
||||
|
||||
char *out = new (std::nothrow) char[available];
|
||||
|
||||
if (out == NULL)
|
||||
return 0;
|
||||
|
||||
_tx_buffer->read(out, available);
|
||||
size_t sent = _client->write(out, available);
|
||||
delete[] out;
|
||||
|
||||
return sent;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
void SyncClient::_onData(void *data, size_t len)
|
||||
{
|
||||
_client->ackLater();
|
||||
cbuf *b = new (std::nothrow) cbuf(len + 1);
|
||||
|
||||
if (b != NULL)
|
||||
{
|
||||
b->write((const char *)data, len);
|
||||
|
||||
if (_rx_buffer == NULL)
|
||||
_rx_buffer = b;
|
||||
else
|
||||
{
|
||||
cbuf *p = _rx_buffer;
|
||||
while (p->next != NULL)
|
||||
p = p->next;
|
||||
p->next = b;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// We ran out of memory. This fail causes lost receive data.
|
||||
// The connection should be closed in a manner that conveys something
|
||||
// bad/abnormal has happened to the connection. Hence, we abort the
|
||||
// connection to avoid possible data corruption.
|
||||
// Note, callbacks maybe called.
|
||||
_client->abort();
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
void SyncClient::_onDisconnect()
|
||||
{
|
||||
if (_client != NULL)
|
||||
{
|
||||
_client = NULL;
|
||||
}
|
||||
|
||||
if (_tx_buffer != NULL)
|
||||
{
|
||||
cbuf *b = _tx_buffer;
|
||||
_tx_buffer = NULL;
|
||||
delete b;
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
void SyncClient::_onConnect(AsyncClient *c)
|
||||
{
|
||||
_client = c;
|
||||
|
||||
if (_tx_buffer != NULL)
|
||||
{
|
||||
cbuf *b = _tx_buffer;
|
||||
_tx_buffer = NULL;
|
||||
delete b;
|
||||
}
|
||||
|
||||
_tx_buffer = new (std::nothrow) cbuf(_tx_buffer_size);
|
||||
_attachCallbacks_AfterConnected();
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
void SyncClient::_attachCallbacks()
|
||||
{
|
||||
_attachCallbacks_Disconnect();
|
||||
_attachCallbacks_AfterConnected();
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
void SyncClient::_attachCallbacks_AfterConnected()
|
||||
{
|
||||
_client->onAck([](void *obj, AsyncClient * c, size_t len, uint32_t time)
|
||||
{
|
||||
RPAsyncTCP_UNUSED(c);
|
||||
RPAsyncTCP_UNUSED(len);
|
||||
RPAsyncTCP_UNUSED(time);
|
||||
((SyncClient*)(obj))->_sendBuffer();
|
||||
}, this);
|
||||
|
||||
_client->onData([](void *obj, AsyncClient * c, void *data, size_t len)
|
||||
{ RPAsyncTCP_UNUSED(c);
|
||||
((SyncClient*)(obj))->_onData(data, len);
|
||||
}, this);
|
||||
|
||||
_client->onTimeout([](void *obj, AsyncClient * c, uint32_t time)
|
||||
{
|
||||
RPAsyncTCP_UNUSED(obj);
|
||||
RPAsyncTCP_UNUSED(time);
|
||||
c->close();
|
||||
}, this);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
void SyncClient::_attachCallbacks_Disconnect()
|
||||
{
|
||||
_client->onDisconnect([](void *obj, AsyncClient * c)
|
||||
{
|
||||
((SyncClient*)(obj))->_onDisconnect();
|
||||
delete c;
|
||||
}, this);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
size_t SyncClient::write(uint8_t data)
|
||||
{
|
||||
return write(&data, 1);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
size_t SyncClient::write(const uint8_t *data, size_t len)
|
||||
{
|
||||
if (_tx_buffer == NULL || !connected())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t toWrite = 0;
|
||||
size_t toSend = len;
|
||||
|
||||
while (_tx_buffer->room() < toSend)
|
||||
{
|
||||
toWrite = _tx_buffer->room();
|
||||
_tx_buffer->write((const char*)data, toWrite);
|
||||
|
||||
while (connected() && !_client->canSend())
|
||||
delay(0);
|
||||
|
||||
if (!connected())
|
||||
return 0;
|
||||
|
||||
_sendBuffer();
|
||||
toSend -= toWrite;
|
||||
}
|
||||
|
||||
_tx_buffer->write((const char*)(data + (len - toSend)), toSend);
|
||||
|
||||
if (connected() && _client->canSend())
|
||||
_sendBuffer();
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
int SyncClient::available()
|
||||
{
|
||||
if (_rx_buffer == NULL)
|
||||
return 0;
|
||||
|
||||
size_t a = 0;
|
||||
cbuf *b = _rx_buffer;
|
||||
|
||||
while (b != NULL)
|
||||
{
|
||||
a += b->available();
|
||||
b = b->next;
|
||||
}
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
int SyncClient::peek()
|
||||
{
|
||||
if (_rx_buffer == NULL)
|
||||
return -1;
|
||||
|
||||
return _rx_buffer->peek();
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
int SyncClient::read(uint8_t *data, size_t len)
|
||||
{
|
||||
if (_rx_buffer == NULL)
|
||||
return -1;
|
||||
|
||||
size_t readSoFar = 0;
|
||||
|
||||
while (_rx_buffer != NULL && (len - readSoFar) >= _rx_buffer->available())
|
||||
{
|
||||
cbuf *b = _rx_buffer;
|
||||
_rx_buffer = _rx_buffer->next;
|
||||
size_t toRead = b->available();
|
||||
readSoFar += b->read((char*)(data + readSoFar), toRead);
|
||||
|
||||
if (connected())
|
||||
{
|
||||
_client->ack(b->size() - 1);
|
||||
}
|
||||
|
||||
delete b;
|
||||
}
|
||||
|
||||
if (_rx_buffer != NULL && readSoFar < len)
|
||||
{
|
||||
readSoFar += _rx_buffer->read((char*)(data + readSoFar), (len - readSoFar));
|
||||
}
|
||||
|
||||
return readSoFar;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
int SyncClient::read()
|
||||
{
|
||||
uint8_t res = 0;
|
||||
|
||||
if (read(&res, 1) != 1)
|
||||
return -1;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
bool SyncClient::flush(unsigned int maxWaitMs)
|
||||
{
|
||||
RPAsyncTCP_UNUSED(maxWaitMs);
|
||||
|
||||
if (_tx_buffer == NULL || !connected())
|
||||
return false;
|
||||
|
||||
if (_tx_buffer->available())
|
||||
{
|
||||
while (connected() && !_client->canSend())
|
||||
delay(0);
|
||||
|
||||
if (_client == NULL || _tx_buffer == NULL)
|
||||
return false;
|
||||
|
||||
_sendBuffer();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
@@ -0,0 +1,125 @@
|
||||
#ifndef SYNCCLIENT_H_
|
||||
#define SYNCCLIENT_H_
|
||||
|
||||
#define LWIP_NETIF_TX_SINGLE_PBUF 1
|
||||
|
||||
#include "Client.h"
|
||||
// Needed for Arduino core releases prior to 2.5.0, because of changes
|
||||
// made to accommodate Arduino core 2.5.0
|
||||
// CONST was 1st defined in Core 2.5.0 in IPAddress.h
|
||||
#ifndef CONST
|
||||
#define CONST
|
||||
#endif
|
||||
|
||||
#include <async_config.h>
|
||||
|
||||
class cbuf;
|
||||
class AsyncClient;
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
class SyncClient: public Client
|
||||
{
|
||||
private:
|
||||
AsyncClient *_client;
|
||||
cbuf *_tx_buffer;
|
||||
size_t _tx_buffer_size;
|
||||
cbuf *_rx_buffer;
|
||||
int *_ref;
|
||||
|
||||
size_t _sendBuffer();
|
||||
void _onData(void *data, size_t len);
|
||||
void _onConnect(AsyncClient *c);
|
||||
void _onDisconnect();
|
||||
void _attachCallbacks();
|
||||
void _attachCallbacks_Disconnect();
|
||||
void _attachCallbacks_AfterConnected();
|
||||
void _release();
|
||||
|
||||
public:
|
||||
SyncClient(size_t txBufLen = TCP_MSS);
|
||||
SyncClient(AsyncClient *client, size_t txBufLen = TCP_MSS);
|
||||
virtual ~SyncClient();
|
||||
|
||||
int ref();
|
||||
int unref();
|
||||
|
||||
operator bool()
|
||||
{
|
||||
return connected();
|
||||
}
|
||||
|
||||
SyncClient & operator=(const SyncClient &other);
|
||||
|
||||
#if ASYNC_TCP_SSL_ENABLED
|
||||
int _connect(const IPAddress& ip, uint16_t port, bool secure);
|
||||
|
||||
int connect(CONST IPAddress& ip, uint16_t port, bool secure)
|
||||
{
|
||||
return _connect(ip, port, secure);
|
||||
}
|
||||
|
||||
int connect(IPAddress ip, uint16_t port, bool secure)
|
||||
{
|
||||
return _connect(reinterpret_cast<const IPAddress&>(ip), port, secure);
|
||||
}
|
||||
|
||||
int connect(const char *host, uint16_t port, bool secure);
|
||||
|
||||
int connect(CONST IPAddress& ip, uint16_t port)
|
||||
{
|
||||
return _connect(ip, port, false);
|
||||
}
|
||||
|
||||
int connect(IPAddress ip, uint16_t port)
|
||||
{
|
||||
return _connect(reinterpret_cast<const IPAddress&>(ip), port, false);
|
||||
}
|
||||
|
||||
int connect(const char *host, uint16_t port)
|
||||
{
|
||||
return connect(host, port, false);
|
||||
}
|
||||
#else
|
||||
int _connect(const IPAddress& ip, uint16_t port);
|
||||
|
||||
int connect(CONST IPAddress& ip, uint16_t port)
|
||||
{
|
||||
return _connect(ip, port);
|
||||
}
|
||||
|
||||
int connect(IPAddress ip, uint16_t port)
|
||||
{
|
||||
return _connect(reinterpret_cast<const IPAddress&>(ip), port);
|
||||
}
|
||||
|
||||
int connect(const char *host, uint16_t port);
|
||||
#endif
|
||||
void setTimeout(uint32_t seconds);
|
||||
|
||||
uint8_t status();
|
||||
uint8_t connected();
|
||||
|
||||
bool stop(unsigned int maxWaitMs);
|
||||
bool flush(unsigned int maxWaitMs);
|
||||
|
||||
void stop()
|
||||
{
|
||||
(void)stop(0);
|
||||
}
|
||||
|
||||
void flush()
|
||||
{
|
||||
(void)flush(0);
|
||||
}
|
||||
|
||||
size_t write(uint8_t data);
|
||||
size_t write(const uint8_t *data, size_t len);
|
||||
|
||||
int available();
|
||||
int peek();
|
||||
int read();
|
||||
int read(uint8_t *data, size_t len);
|
||||
};
|
||||
|
||||
#endif /* SYNCCLIENT_H_ */
|
||||
@@ -0,0 +1,12 @@
|
||||
#ifndef _RP2040W_ASYNC_CONFIG_H_
|
||||
#define _RP2040W_ASYNC_CONFIG_H_
|
||||
|
||||
#ifndef TCP_MSS
|
||||
// May have been definded as a -DTCP_MSS option on the compile line or not.
|
||||
// Arduino core 2.3.0 or earlier does not do the -DTCP_MSS option.
|
||||
// Later versions may set this option with info from board.txt.
|
||||
// However, Core 2.4.0 and up board.txt does not define TCP_MSS for lwIP v1.4
|
||||
#define TCP_MSS MBED_CONF_LWIP_TCP_MSS //(1460)
|
||||
#endif
|
||||
|
||||
#endif // _RP2040W_ASYNC_CONFIG_H_
|
||||
109
WiFiX-Enhanced/.pio/libdeps/esp32_main/RPAsyncTCP/src/c_types.h
Normal file
109
WiFiX-Enhanced/.pio/libdeps/esp32_main/RPAsyncTCP/src/c_types.h
Normal file
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* ESPRESSIF MIT License
|
||||
*
|
||||
* Copyright (c) 2016 <ESPRESSIF SYSTEMS (SHANGHAI) PTE LTD>
|
||||
*
|
||||
* Permission is hereby granted for use on ESPRESSIF SYSTEMS ESP8266 only, in which case,
|
||||
* it is free of charge, to any person obtaining a copy of this software and associated
|
||||
* documentation files (the "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the Software is furnished
|
||||
* to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or
|
||||
* substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _C_TYPES_H_
|
||||
#define _C_TYPES_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdarg.h>
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
typedef signed char sint8_t;
|
||||
typedef signed short sint16_t;
|
||||
typedef signed long sint32_t;
|
||||
typedef signed long long sint64_t;
|
||||
typedef unsigned long long u_int64_t;
|
||||
typedef float real32_t;
|
||||
typedef double real64_t;
|
||||
|
||||
typedef unsigned char uint8;
|
||||
typedef unsigned char u8;
|
||||
typedef signed char sint8;
|
||||
typedef signed char int8;
|
||||
typedef signed char s8;
|
||||
typedef unsigned short uint16;
|
||||
typedef unsigned short u16;
|
||||
typedef signed short sint16;
|
||||
typedef signed short s16;
|
||||
typedef unsigned int uint32;
|
||||
typedef unsigned int u_int;
|
||||
typedef unsigned int u32;
|
||||
typedef signed int sint32;
|
||||
typedef signed int s32;
|
||||
typedef int int32;
|
||||
typedef signed long long sint64;
|
||||
typedef unsigned long long uint64;
|
||||
typedef unsigned long long u64;
|
||||
typedef float real32;
|
||||
typedef double real64;
|
||||
|
||||
#define __le16 u16
|
||||
|
||||
#define LOCAL static
|
||||
|
||||
#ifndef NULL
|
||||
#define NULL (void *)0
|
||||
#endif /* NULL */
|
||||
|
||||
/* probably should not put STATUS here */
|
||||
typedef enum
|
||||
{
|
||||
OK = 0,
|
||||
FAIL,
|
||||
PENDING,
|
||||
BUSY,
|
||||
CANCEL,
|
||||
} STATUS;
|
||||
|
||||
#define BIT(nr) (1UL << (nr))
|
||||
|
||||
#define REG_SET_BIT(_r, _b) (*(volatile uint32_t*)(_r) |= (_b))
|
||||
#define REG_CLR_BIT(_r, _b) (*(volatile uint32_t*)(_r) &= ~(_b))
|
||||
|
||||
#define DMEM_ATTR __attribute__((section(".bss")))
|
||||
#define SHMEM_ATTR
|
||||
|
||||
#ifdef ICACHE_FLASH
|
||||
#define __ICACHE_STRINGIZE_NX(A) #A
|
||||
#define __ICACHE_STRINGIZE(A) __ICACHE_STRINGIZE_NX(A)
|
||||
#define ICACHE_FLASH_ATTR __attribute__((section("\".irom0.text." __FILE__ "." __ICACHE_STRINGIZE(__LINE__) "." __ICACHE_STRINGIZE(__COUNTER__) "\"")))
|
||||
#define ICACHE_RAM_ATTR __attribute__((section("\".iram.text." __FILE__ "." __ICACHE_STRINGIZE(__LINE__) "." __ICACHE_STRINGIZE(__COUNTER__) "\"")))
|
||||
#else
|
||||
#define ICACHE_FLASH_ATTR
|
||||
#define ICACHE_RAM_ATTR
|
||||
#endif /* ICACHE_FLASH */
|
||||
|
||||
// counterpart https://github.com/espressif/arduino-esp32/blob/master/cores/esp32/esp8266-compat.h
|
||||
#define IRAM_ATTR ICACHE_RAM_ATTR
|
||||
|
||||
#define STORE_ATTR __attribute__((aligned(4)))
|
||||
|
||||
#ifndef __cplusplus
|
||||
#define BOOL bool
|
||||
#define TRUE true
|
||||
#define FALSE false
|
||||
#endif /* !__cplusplus */
|
||||
|
||||
#endif /* _C_TYPES_H_ */
|
||||
221
WiFiX-Enhanced/.pio/libdeps/esp32_main/RPAsyncTCP/src/cbuf.cpp
Normal file
221
WiFiX-Enhanced/.pio/libdeps/esp32_main/RPAsyncTCP/src/cbuf.cpp
Normal file
@@ -0,0 +1,221 @@
|
||||
/*
|
||||
cbuf.cpp - Circular buffer implementation
|
||||
Copyright (c) 2014 Ivan Grokhotkov. All rights reserved.
|
||||
This file is part of the esp8266 core for Arduino environment.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "cbuf.h"
|
||||
#include "c_types.h"
|
||||
|
||||
cbuf::cbuf(size_t size) :
|
||||
next(NULL), _size(size), _buf(new char[size]), _bufend(_buf + size), _begin(_buf), _end(_begin)
|
||||
{
|
||||
}
|
||||
|
||||
cbuf::~cbuf()
|
||||
{
|
||||
delete[] _buf;
|
||||
}
|
||||
|
||||
size_t cbuf::resizeAdd(size_t addSize)
|
||||
{
|
||||
return resize(_size + addSize);
|
||||
}
|
||||
|
||||
size_t cbuf::resize(size_t newSize)
|
||||
{
|
||||
size_t bytes_available = available();
|
||||
|
||||
// not lose any data
|
||||
// if data can be lost use remove or flush before resize
|
||||
if ((newSize <= bytes_available) || (newSize == _size))
|
||||
{
|
||||
return _size;
|
||||
}
|
||||
|
||||
char *newbuf = new char[newSize];
|
||||
char *oldbuf = _buf;
|
||||
|
||||
if (!newbuf)
|
||||
{
|
||||
return _size;
|
||||
}
|
||||
|
||||
if (_buf)
|
||||
{
|
||||
read(newbuf, bytes_available);
|
||||
memset((newbuf + bytes_available), 0x00, (newSize - bytes_available));
|
||||
}
|
||||
|
||||
_begin = newbuf;
|
||||
_end = newbuf + bytes_available;
|
||||
_bufend = newbuf + newSize;
|
||||
_size = newSize;
|
||||
|
||||
_buf = newbuf;
|
||||
delete[] oldbuf;
|
||||
|
||||
return _size;
|
||||
}
|
||||
|
||||
size_t ICACHE_RAM_ATTR cbuf::available() const
|
||||
{
|
||||
if (_end >= _begin)
|
||||
{
|
||||
return _end - _begin;
|
||||
}
|
||||
|
||||
return _size - (_begin - _end);
|
||||
}
|
||||
|
||||
size_t cbuf::size()
|
||||
{
|
||||
return _size;
|
||||
}
|
||||
|
||||
size_t cbuf::room() const
|
||||
{
|
||||
if (_end >= _begin)
|
||||
{
|
||||
return _size - (_end - _begin) - 1;
|
||||
}
|
||||
|
||||
return _begin - _end - 1;
|
||||
}
|
||||
|
||||
int cbuf::peek()
|
||||
{
|
||||
if (empty())
|
||||
return -1;
|
||||
|
||||
return static_cast<int>(*_begin);
|
||||
}
|
||||
|
||||
size_t cbuf::peek(char *dst, size_t size)
|
||||
{
|
||||
size_t bytes_available = available();
|
||||
size_t size_to_read = (size < bytes_available) ? size : bytes_available;
|
||||
size_t size_read = size_to_read;
|
||||
char * begin = _begin;
|
||||
|
||||
if (_end < _begin && size_to_read > (size_t) (_bufend - _begin))
|
||||
{
|
||||
size_t top_size = _bufend - _begin;
|
||||
memcpy(dst, _begin, top_size);
|
||||
begin = _buf;
|
||||
size_to_read -= top_size;
|
||||
dst += top_size;
|
||||
}
|
||||
|
||||
memcpy(dst, begin, size_to_read);
|
||||
|
||||
return size_read;
|
||||
}
|
||||
|
||||
int ICACHE_RAM_ATTR cbuf::read()
|
||||
{
|
||||
if (empty())
|
||||
return -1;
|
||||
|
||||
char result = *_begin;
|
||||
_begin = wrap_if_bufend(_begin + 1);
|
||||
|
||||
return static_cast<int>(result);
|
||||
}
|
||||
|
||||
size_t cbuf::read(char* dst, size_t size)
|
||||
{
|
||||
size_t bytes_available = available();
|
||||
size_t size_to_read = (size < bytes_available) ? size : bytes_available;
|
||||
size_t size_read = size_to_read;
|
||||
|
||||
if (_end < _begin && size_to_read > (size_t) (_bufend - _begin))
|
||||
{
|
||||
size_t top_size = _bufend - _begin;
|
||||
memcpy(dst, _begin, top_size);
|
||||
_begin = _buf;
|
||||
size_to_read -= top_size;
|
||||
dst += top_size;
|
||||
}
|
||||
|
||||
memcpy(dst, _begin, size_to_read);
|
||||
_begin = wrap_if_bufend(_begin + size_to_read);
|
||||
|
||||
return size_read;
|
||||
}
|
||||
|
||||
size_t ICACHE_RAM_ATTR cbuf::write(char c)
|
||||
{
|
||||
if (full())
|
||||
return 0;
|
||||
|
||||
*_end = c;
|
||||
_end = wrap_if_bufend(_end + 1);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
size_t cbuf::write(const char* src, size_t size)
|
||||
{
|
||||
size_t bytes_available = room();
|
||||
size_t size_to_write = (size < bytes_available) ? size : bytes_available;
|
||||
size_t size_written = size_to_write;
|
||||
|
||||
if (_end >= _begin && size_to_write > (size_t) (_bufend - _end))
|
||||
{
|
||||
size_t top_size = _bufend - _end;
|
||||
memcpy(_end, src, top_size);
|
||||
_end = _buf;
|
||||
size_to_write -= top_size;
|
||||
src += top_size;
|
||||
}
|
||||
|
||||
memcpy(_end, src, size_to_write);
|
||||
_end = wrap_if_bufend(_end + size_to_write);
|
||||
|
||||
return size_written;
|
||||
}
|
||||
|
||||
void cbuf::flush()
|
||||
{
|
||||
_begin = _buf;
|
||||
_end = _buf;
|
||||
}
|
||||
|
||||
size_t cbuf::remove(size_t size)
|
||||
{
|
||||
size_t bytes_available = available();
|
||||
|
||||
if (size >= bytes_available)
|
||||
{
|
||||
flush();
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t size_to_remove = (size < bytes_available) ? size : bytes_available;
|
||||
|
||||
if (_end < _begin && size_to_remove > (size_t) (_bufend - _begin))
|
||||
{
|
||||
size_t top_size = _bufend - _begin;
|
||||
_begin = _buf;
|
||||
size_to_remove -= top_size;
|
||||
}
|
||||
|
||||
_begin = wrap_if_bufend(_begin + size_to_remove);
|
||||
|
||||
return available();
|
||||
}
|
||||
78
WiFiX-Enhanced/.pio/libdeps/esp32_main/RPAsyncTCP/src/cbuf.h
Normal file
78
WiFiX-Enhanced/.pio/libdeps/esp32_main/RPAsyncTCP/src/cbuf.h
Normal file
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
cbuf.h - Circular buffer implementation
|
||||
Copyright (c) 2014 Ivan Grokhotkov. All rights reserved.
|
||||
This file is part of the esp8266 core for Arduino environment.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef __cbuf_h
|
||||
#define __cbuf_h
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
class cbuf
|
||||
{
|
||||
public:
|
||||
cbuf(size_t size);
|
||||
~cbuf();
|
||||
|
||||
size_t resizeAdd(size_t addSize);
|
||||
size_t resize(size_t newSize);
|
||||
size_t available() const;
|
||||
size_t size();
|
||||
|
||||
size_t room() const;
|
||||
|
||||
inline bool empty() const
|
||||
{
|
||||
return _begin == _end;
|
||||
}
|
||||
|
||||
inline bool full() const
|
||||
{
|
||||
return wrap_if_bufend(_end + 1) == _begin;
|
||||
}
|
||||
|
||||
int peek();
|
||||
size_t peek(char *dst, size_t size);
|
||||
|
||||
int read();
|
||||
size_t read(char* dst, size_t size);
|
||||
|
||||
size_t write(char c);
|
||||
size_t write(const char* src, size_t size);
|
||||
|
||||
void flush();
|
||||
size_t remove(size_t size);
|
||||
|
||||
cbuf *next;
|
||||
|
||||
private:
|
||||
inline char* wrap_if_bufend(char* ptr) const
|
||||
{
|
||||
return (ptr == _bufend) ? _buf : ptr;
|
||||
}
|
||||
|
||||
size_t _size;
|
||||
char* _buf;
|
||||
const char* _bufend;
|
||||
char* _begin;
|
||||
char* _end;
|
||||
};
|
||||
|
||||
#endif//__cbuf_h
|
||||
@@ -0,0 +1,4 @@
|
||||
|
||||
void panic()
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
#ifndef DEBUG_H_
|
||||
#define DEBUG_H_
|
||||
|
||||
void panic();
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,802 @@
|
||||
#if !defined(_RPAsyncTCP_LOGLEVEL_)
|
||||
#define _RPAsyncTCP_LOGLEVEL_ 1
|
||||
#endif
|
||||
|
||||
#include <async_config.h>
|
||||
|
||||
#if ASYNC_TCP_SSL_ENABLED
|
||||
|
||||
#include "lwip/opt.h"
|
||||
#include "lwip/tcp.h"
|
||||
#include "lwip/inet.h"
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <tcp_axtls.h>
|
||||
|
||||
uint8_t * default_private_key = NULL;
|
||||
uint16_t default_private_key_len = 0;
|
||||
|
||||
uint8_t * default_certificate = NULL;
|
||||
uint16_t default_certificate_len = 0;
|
||||
|
||||
static uint8_t _tcp_ssl_has_client = 0;
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
SSL_CTX * tcp_ssl_new_server_ctx(const char *cert, const char *private_key_file, const char *password)
|
||||
{
|
||||
uint32_t options = SSL_CONNECT_IN_PARTS;
|
||||
SSL_CTX *ssl_ctx;
|
||||
|
||||
if (private_key_file)
|
||||
{
|
||||
options |= SSL_NO_DEFAULT_KEY;
|
||||
}
|
||||
|
||||
if ((ssl_ctx = ssl_ctx_new(options, SSL_DEFAULT_SVR_SESS)) == NULL)
|
||||
{
|
||||
TCP_SSL_DEBUG("tcp_ssl_new_server_ctx: failed to allocate context\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (private_key_file)
|
||||
{
|
||||
int obj_type = SSL_OBJ_RSA_KEY;
|
||||
|
||||
if (strstr(private_key_file, ".p8"))
|
||||
obj_type = SSL_OBJ_PKCS8;
|
||||
else if (strstr(private_key_file, ".p12"))
|
||||
obj_type = SSL_OBJ_PKCS12;
|
||||
|
||||
if (ssl_obj_load(ssl_ctx, obj_type, private_key_file, password))
|
||||
{
|
||||
TCP_SSL_DEBUG("tcp_ssl_new_server_ctx: load private key '%s' failed\n", private_key_file);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (cert)
|
||||
{
|
||||
if (ssl_obj_load(ssl_ctx, SSL_OBJ_X509_CERT, cert, NULL))
|
||||
{
|
||||
TCP_SSL_DEBUG("tcp_ssl_new_server_ctx: load certificate '%s' failed\n", cert);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return ssl_ctx;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
struct tcp_ssl_pcb
|
||||
{
|
||||
struct tcp_pcb *tcp;
|
||||
int fd;
|
||||
SSL_CTX* ssl_ctx;
|
||||
SSL *ssl;
|
||||
uint8_t type;
|
||||
int handshake;
|
||||
void * arg;
|
||||
tcp_ssl_data_cb_t on_data;
|
||||
tcp_ssl_handshake_cb_t on_handshake;
|
||||
tcp_ssl_error_cb_t on_error;
|
||||
int last_wr;
|
||||
struct pbuf *tcp_pbuf;
|
||||
int pbuf_offset;
|
||||
struct tcp_ssl_pcb * next;
|
||||
};
|
||||
|
||||
typedef struct tcp_ssl_pcb tcp_ssl_t;
|
||||
|
||||
static tcp_ssl_t * tcp_ssl_array = NULL;
|
||||
static int tcp_ssl_next_fd = 0;
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
uint8_t tcp_ssl_has_client()
|
||||
{
|
||||
return _tcp_ssl_has_client;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
tcp_ssl_t * tcp_ssl_new(struct tcp_pcb *tcp)
|
||||
{
|
||||
|
||||
if (tcp_ssl_next_fd < 0)
|
||||
{
|
||||
tcp_ssl_next_fd = 0;//overflow
|
||||
}
|
||||
|
||||
tcp_ssl_t * new_item = (tcp_ssl_t*)malloc(sizeof(tcp_ssl_t));
|
||||
|
||||
if (!new_item)
|
||||
{
|
||||
TCP_SSL_DEBUG("tcp_ssl_new: failed to allocate tcp_ssl\n");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
new_item->tcp = tcp;
|
||||
new_item->handshake = SSL_NOT_OK;
|
||||
new_item->arg = NULL;
|
||||
new_item->on_data = NULL;
|
||||
new_item->on_handshake = NULL;
|
||||
new_item->on_error = NULL;
|
||||
new_item->tcp_pbuf = NULL;
|
||||
new_item->pbuf_offset = 0;
|
||||
new_item->next = NULL;
|
||||
new_item->ssl_ctx = NULL;
|
||||
new_item->ssl = NULL;
|
||||
new_item->type = TCP_SSL_TYPE_CLIENT;
|
||||
new_item->fd = tcp_ssl_next_fd++;
|
||||
|
||||
if (tcp_ssl_array == NULL)
|
||||
{
|
||||
tcp_ssl_array = new_item;
|
||||
}
|
||||
else
|
||||
{
|
||||
tcp_ssl_t * item = tcp_ssl_array;
|
||||
|
||||
while (item->next != NULL)
|
||||
item = item->next;
|
||||
|
||||
item->next = new_item;
|
||||
}
|
||||
|
||||
TCP_SSL_DEBUG("tcp_ssl_new: %d\n", new_item->fd);
|
||||
|
||||
return new_item;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
tcp_ssl_t* tcp_ssl_get(struct tcp_pcb *tcp)
|
||||
{
|
||||
if (tcp == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
tcp_ssl_t * item = tcp_ssl_array;
|
||||
|
||||
while (item && item->tcp != tcp)
|
||||
{
|
||||
item = item->next;
|
||||
}
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
int tcp_ssl_new_client(struct tcp_pcb *tcp)
|
||||
{
|
||||
SSL_CTX* ssl_ctx;
|
||||
tcp_ssl_t * tcp_ssl;
|
||||
|
||||
if (tcp == NULL)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (tcp_ssl_get(tcp) != NULL)
|
||||
{
|
||||
TCP_SSL_DEBUG("tcp_ssl_new_client: tcp_ssl already exists\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ssl_ctx = ssl_ctx_new(SSL_CONNECT_IN_PARTS | SSL_SERVER_VERIFY_LATER, 1);
|
||||
|
||||
if (ssl_ctx == NULL)
|
||||
{
|
||||
TCP_SSL_DEBUG("tcp_ssl_new_client: failed to allocate ssl context\n");
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
tcp_ssl = tcp_ssl_new(tcp);
|
||||
|
||||
if (tcp_ssl == NULL)
|
||||
{
|
||||
ssl_ctx_free(ssl_ctx);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
tcp_ssl->ssl_ctx = ssl_ctx;
|
||||
|
||||
tcp_ssl->ssl = ssl_client_new(ssl_ctx, tcp_ssl->fd, NULL, 0, NULL);
|
||||
|
||||
if (tcp_ssl->ssl == NULL)
|
||||
{
|
||||
TCP_SSL_DEBUG("tcp_ssl_new_client: failed to allocate ssl\n");
|
||||
tcp_ssl_free(tcp);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
return tcp_ssl->fd;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
int tcp_ssl_new_server(struct tcp_pcb *tcp, SSL_CTX* ssl_ctx)
|
||||
{
|
||||
tcp_ssl_t * tcp_ssl;
|
||||
|
||||
if (tcp == NULL)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ssl_ctx == NULL)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (tcp_ssl_get(tcp) != NULL)
|
||||
{
|
||||
TCP_SSL_DEBUG("tcp_ssl_new_server: tcp_ssl already exists\n");
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
tcp_ssl = tcp_ssl_new(tcp);
|
||||
|
||||
if (tcp_ssl == NULL)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
tcp_ssl->type = TCP_SSL_TYPE_SERVER;
|
||||
tcp_ssl->ssl_ctx = ssl_ctx;
|
||||
|
||||
_tcp_ssl_has_client = 1;
|
||||
tcp_ssl->ssl = ssl_server_new(ssl_ctx, tcp_ssl->fd);
|
||||
|
||||
if (tcp_ssl->ssl == NULL)
|
||||
{
|
||||
TCP_SSL_DEBUG("tcp_ssl_new_server: failed to allocate ssl\n");
|
||||
tcp_ssl_free(tcp);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
return tcp_ssl->fd;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
int tcp_ssl_free(struct tcp_pcb *tcp)
|
||||
{
|
||||
if (tcp == NULL)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
tcp_ssl_t * item = tcp_ssl_array;
|
||||
|
||||
if (item->tcp == tcp)
|
||||
{
|
||||
tcp_ssl_array = tcp_ssl_array->next;
|
||||
|
||||
if (item->tcp_pbuf != NULL)
|
||||
{
|
||||
pbuf_free(item->tcp_pbuf);
|
||||
}
|
||||
|
||||
TCP_SSL_DEBUG("tcp_ssl_free: %d\n", item->fd);
|
||||
|
||||
if (item->ssl)
|
||||
ssl_free(item->ssl);
|
||||
|
||||
if (item->type == TCP_SSL_TYPE_CLIENT && item->ssl_ctx)
|
||||
ssl_ctx_free(item->ssl_ctx);
|
||||
|
||||
if (item->type == TCP_SSL_TYPE_SERVER)
|
||||
_tcp_ssl_has_client = 0;
|
||||
|
||||
free(item);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
while (item->next && item->next->tcp != tcp)
|
||||
item = item->next;
|
||||
|
||||
if (item->next == NULL)
|
||||
{
|
||||
return ERR_TCP_SSL_INVALID_CLIENTFD_DATA;//item not found
|
||||
}
|
||||
|
||||
tcp_ssl_t * i = item->next;
|
||||
item->next = i->next;
|
||||
|
||||
if (i->tcp_pbuf != NULL)
|
||||
{
|
||||
pbuf_free(i->tcp_pbuf);
|
||||
}
|
||||
|
||||
TCP_SSL_DEBUG("tcp_ssl_free: %d\n", i->fd);
|
||||
|
||||
if (i->ssl)
|
||||
ssl_free(i->ssl);
|
||||
|
||||
if (i->type == TCP_SSL_TYPE_CLIENT && i->ssl_ctx)
|
||||
ssl_ctx_free(i->ssl_ctx);
|
||||
|
||||
if (i->type == TCP_SSL_TYPE_SERVER)
|
||||
_tcp_ssl_has_client = 0;
|
||||
|
||||
free(i);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef AXTLS_2_0_0_SNDBUF
|
||||
|
||||
int tcp_ssl_sndbuf(struct tcp_pcb *tcp)
|
||||
{
|
||||
int expected;
|
||||
int available;
|
||||
int result = -1;
|
||||
|
||||
if (tcp == NULL)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
tcp_ssl_t * tcp_ssl = tcp_ssl_get(tcp);
|
||||
|
||||
if (!tcp_ssl)
|
||||
{
|
||||
TCP_SSL_DEBUG("tcp_ssl_sndbuf: tcp_ssl is NULL\n");
|
||||
return result;
|
||||
}
|
||||
|
||||
available = tcp_sndbuf(tcp);
|
||||
|
||||
if (!available)
|
||||
{
|
||||
TCP_SSL_DEBUG("tcp_ssl_sndbuf: tcp_sndbuf is zero\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
result = available;
|
||||
|
||||
while ((expected = ssl_calculate_write_length(tcp_ssl->ssl, result)) > available)
|
||||
{
|
||||
result -= (expected - available) + 4;
|
||||
}
|
||||
|
||||
if (expected > 0)
|
||||
{
|
||||
//TCP_SSL_DEBUG("tcp_ssl_sndbuf: tcp_sndbuf is %d from %d\n", result, available);
|
||||
return result;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif // AXTLS_2_0_0_SNDBUF
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
int tcp_ssl_write(struct tcp_pcb *tcp, uint8_t *data, size_t len)
|
||||
{
|
||||
if (tcp == NULL)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
tcp_ssl_t * tcp_ssl = tcp_ssl_get(tcp);
|
||||
|
||||
if (!tcp_ssl)
|
||||
{
|
||||
TCP_SSL_DEBUG("tcp_ssl_write: tcp_ssl is NULL\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
tcp_ssl->last_wr = 0;
|
||||
|
||||
#ifdef AXTLS_2_0_0_SNDBUF
|
||||
int expected_len = ssl_calculate_write_length(tcp_ssl->ssl, len);
|
||||
int available_len = tcp_sndbuf(tcp);
|
||||
|
||||
if (expected_len < 0 || expected_len > available_len)
|
||||
{
|
||||
TCP_SSL_DEBUG("tcp_ssl_write: data will not fit! %u < %d(%u)\r\n", available_len, expected_len, len);
|
||||
|
||||
return -1;
|
||||
}
|
||||
#endif // AXTLS_2_0_0_SNDBUF
|
||||
|
||||
int rc = ssl_write(tcp_ssl->ssl, data, len);
|
||||
|
||||
//TCP_SSL_DEBUG("tcp_ssl_write: %u -> %d (%d)\r\n", len, tcp_ssl->last_wr, rc);
|
||||
|
||||
if (rc < 0)
|
||||
{
|
||||
if (rc != SSL_CLOSE_NOTIFY)
|
||||
{
|
||||
TCP_SSL_DEBUG("tcp_ssl_write error: %d\r\n", rc);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
return tcp_ssl->last_wr;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
Reads data from the SSL over TCP stream. Returns decrypted data.
|
||||
@param tcp_pcb *tcp - pointer to the raw tcp object
|
||||
@param pbuf *p - pointer to the buffer with the TCP packet data
|
||||
|
||||
@return int
|
||||
0 - when everything is fine but there are no symbols to process yet
|
||||
< 0 - when there is an error
|
||||
> 0 - the length of the clear text characters that were read
|
||||
*/
|
||||
int tcp_ssl_read(struct tcp_pcb *tcp, struct pbuf *p)
|
||||
{
|
||||
if (tcp == NULL)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
tcp_ssl_t* fd_data = NULL;
|
||||
|
||||
int read_bytes = 0;
|
||||
int total_bytes = 0;
|
||||
uint8_t *read_buf;
|
||||
|
||||
fd_data = tcp_ssl_get(tcp);
|
||||
|
||||
if (fd_data == NULL)
|
||||
{
|
||||
TCP_SSL_DEBUG("tcp_ssl_read: tcp_ssl is NULL\n");
|
||||
return ERR_TCP_SSL_INVALID_CLIENTFD_DATA;
|
||||
}
|
||||
|
||||
if (p == NULL)
|
||||
{
|
||||
TCP_SSL_DEBUG("tcp_ssl_read:p == NULL\n");
|
||||
return ERR_TCP_SSL_INVALID_DATA;
|
||||
}
|
||||
|
||||
//TCP_SSL_DEBUG("READY TO READ SOME DATA\n");
|
||||
|
||||
fd_data->tcp_pbuf = p;
|
||||
fd_data->pbuf_offset = 0;
|
||||
|
||||
do
|
||||
{
|
||||
read_bytes = ssl_read(fd_data->ssl, &read_buf);
|
||||
//TCP_SSL_DEBUG("tcp_ssl_ssl_read: %d\n", read_bytes);
|
||||
|
||||
if (read_bytes < SSL_OK)
|
||||
{
|
||||
if (read_bytes != SSL_CLOSE_NOTIFY)
|
||||
{
|
||||
TCP_SSL_DEBUG("tcp_ssl_read: read error: %d\n", read_bytes);
|
||||
}
|
||||
|
||||
total_bytes = read_bytes;
|
||||
break;
|
||||
}
|
||||
else if (read_bytes > 0)
|
||||
{
|
||||
if (fd_data->on_data)
|
||||
{
|
||||
fd_data->on_data(fd_data->arg, tcp, read_buf, read_bytes);
|
||||
}
|
||||
|
||||
total_bytes += read_bytes;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (fd_data->handshake != SSL_OK)
|
||||
{
|
||||
fd_data->handshake = ssl_handshake_status(fd_data->ssl);
|
||||
|
||||
if (fd_data->handshake == SSL_OK)
|
||||
{
|
||||
//TCP_SSL_DEBUG("tcp_ssl_read: handshake OK\n");
|
||||
if (fd_data->on_handshake)
|
||||
fd_data->on_handshake(fd_data->arg, fd_data->tcp, fd_data->ssl);
|
||||
}
|
||||
else if (fd_data->handshake != SSL_NOT_OK)
|
||||
{
|
||||
TCP_SSL_DEBUG("tcp_ssl_read: handshake error: %d\n", fd_data->handshake);
|
||||
|
||||
if (fd_data->on_error)
|
||||
fd_data->on_error(fd_data->arg, fd_data->tcp, fd_data->handshake);
|
||||
|
||||
return fd_data->handshake;
|
||||
}
|
||||
}
|
||||
}
|
||||
} while (p->tot_len - fd_data->pbuf_offset > 0);
|
||||
|
||||
tcp_recved(tcp, p->tot_len);
|
||||
fd_data->tcp_pbuf = NULL;
|
||||
pbuf_free(p);
|
||||
|
||||
return total_bytes;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
SSL * tcp_ssl_get_ssl(struct tcp_pcb *tcp)
|
||||
{
|
||||
tcp_ssl_t * tcp_ssl = tcp_ssl_get(tcp);
|
||||
|
||||
if (tcp_ssl)
|
||||
{
|
||||
return tcp_ssl->ssl;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
bool tcp_ssl_has(struct tcp_pcb *tcp)
|
||||
{
|
||||
return tcp_ssl_get(tcp) != NULL;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
int tcp_ssl_is_server(struct tcp_pcb *tcp)
|
||||
{
|
||||
tcp_ssl_t * tcp_ssl = tcp_ssl_get(tcp);
|
||||
|
||||
if (tcp_ssl)
|
||||
{
|
||||
return tcp_ssl->type;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
void tcp_ssl_arg(struct tcp_pcb *tcp, void * arg)
|
||||
{
|
||||
tcp_ssl_t * item = tcp_ssl_get(tcp);
|
||||
|
||||
if (item)
|
||||
{
|
||||
item->arg = arg;
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
void tcp_ssl_data(struct tcp_pcb *tcp, tcp_ssl_data_cb_t arg)
|
||||
{
|
||||
tcp_ssl_t * item = tcp_ssl_get(tcp);
|
||||
|
||||
if (item)
|
||||
{
|
||||
item->on_data = arg;
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
void tcp_ssl_handshake(struct tcp_pcb *tcp, tcp_ssl_handshake_cb_t arg)
|
||||
{
|
||||
tcp_ssl_t * item = tcp_ssl_get(tcp);
|
||||
|
||||
if (item)
|
||||
{
|
||||
item->on_handshake = arg;
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
void tcp_ssl_err(struct tcp_pcb *tcp, tcp_ssl_error_cb_t arg)
|
||||
{
|
||||
tcp_ssl_t * item = tcp_ssl_get(tcp);
|
||||
|
||||
if (item)
|
||||
{
|
||||
item->on_error = arg;
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
static tcp_ssl_file_cb_t _tcp_ssl_file_cb = NULL;
|
||||
static void * _tcp_ssl_file_arg = NULL;
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
void tcp_ssl_file(tcp_ssl_file_cb_t cb, void * arg)
|
||||
{
|
||||
_tcp_ssl_file_cb = cb;
|
||||
_tcp_ssl_file_arg = arg;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
int ax_get_file(const char *filename, uint8_t **buf)
|
||||
{
|
||||
//TCP_SSL_DEBUG("ax_get_file: %s\n", filename);
|
||||
if (_tcp_ssl_file_cb)
|
||||
{
|
||||
return _tcp_ssl_file_cb(_tcp_ssl_file_arg, filename, buf);
|
||||
}
|
||||
|
||||
*buf = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
tcp_ssl_t* tcp_ssl_get_by_fd(int fd)
|
||||
{
|
||||
tcp_ssl_t * item = tcp_ssl_array;
|
||||
|
||||
while (item && item->fd != fd)
|
||||
{
|
||||
item = item->next;
|
||||
}
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
/*
|
||||
The LWIP tcp raw version of the SOCKET_WRITE(A, B, C)
|
||||
*/
|
||||
int ax_port_write(int fd, uint8_t *data, uint16_t len)
|
||||
{
|
||||
tcp_ssl_t *fd_data = NULL;
|
||||
int tcp_len = 0;
|
||||
err_t err = ERR_OK;
|
||||
|
||||
//TCP_SSL_DEBUG("ax_port_write: %d, %d\n", fd, len);
|
||||
|
||||
fd_data = tcp_ssl_get_by_fd(fd);
|
||||
|
||||
if (fd_data == NULL)
|
||||
{
|
||||
//TCP_SSL_DEBUG("ax_port_write: tcp_ssl[%d] is NULL\n", fd);
|
||||
|
||||
return ERR_MEM;
|
||||
}
|
||||
|
||||
if (data == NULL || len == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (tcp_sndbuf(fd_data->tcp) < len)
|
||||
{
|
||||
tcp_len = tcp_sndbuf(fd_data->tcp);
|
||||
|
||||
if (tcp_len == 0)
|
||||
{
|
||||
TCP_SSL_DEBUG("ax_port_write: tcp_sndbuf is zero: %d\n", len);
|
||||
|
||||
return ERR_MEM;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
tcp_len = len;
|
||||
}
|
||||
|
||||
if (tcp_len > 2 * fd_data->tcp->mss)
|
||||
{
|
||||
tcp_len = 2 * fd_data->tcp->mss;
|
||||
}
|
||||
|
||||
err = tcp_write(fd_data->tcp, data, tcp_len, TCP_WRITE_FLAG_COPY);
|
||||
|
||||
if (err < ERR_OK)
|
||||
{
|
||||
if (err == ERR_MEM)
|
||||
{
|
||||
TCP_SSL_DEBUG("ax_port_write: No memory %d (%d)\n", tcp_len, len);
|
||||
return err;
|
||||
}
|
||||
|
||||
TCP_SSL_DEBUG("ax_port_write: tcp_write error: %d\n", err);
|
||||
|
||||
return err;
|
||||
}
|
||||
else if (err == ERR_OK)
|
||||
{
|
||||
//TCP_SSL_DEBUG("ax_port_write: tcp_output: %d / %d\n", tcp_len, len);
|
||||
err = tcp_output(fd_data->tcp);
|
||||
|
||||
if (err != ERR_OK)
|
||||
{
|
||||
TCP_SSL_DEBUG("ax_port_write: tcp_output err: %d\n", err);
|
||||
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
fd_data->last_wr += tcp_len;
|
||||
|
||||
return tcp_len;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
/*
|
||||
The LWIP tcp raw version of the SOCKET_READ(A, B, C)
|
||||
*/
|
||||
int ax_port_read(int fd, uint8_t *data, int len)
|
||||
{
|
||||
tcp_ssl_t *fd_data = NULL;
|
||||
uint8_t *read_buf = NULL;
|
||||
uint8_t *pread_buf = NULL;
|
||||
u16_t recv_len = 0;
|
||||
|
||||
//TCP_SSL_DEBUG("ax_port_read: %d, %d\n", fd, len);
|
||||
|
||||
fd_data = tcp_ssl_get_by_fd(fd);
|
||||
|
||||
if (fd_data == NULL)
|
||||
{
|
||||
TCP_SSL_DEBUG("ax_port_read: tcp_ssl[%d] is NULL\n", fd);
|
||||
|
||||
return ERR_TCP_SSL_INVALID_CLIENTFD_DATA;
|
||||
}
|
||||
|
||||
if (fd_data->tcp_pbuf == NULL || fd_data->tcp_pbuf->tot_len == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
read_buf = (uint8_t*) calloc(fd_data->tcp_pbuf->len + 1, sizeof(uint8_t));
|
||||
pread_buf = read_buf;
|
||||
|
||||
if (pread_buf != NULL)
|
||||
{
|
||||
recv_len = pbuf_copy_partial(fd_data->tcp_pbuf, read_buf, len, fd_data->pbuf_offset);
|
||||
fd_data->pbuf_offset += recv_len;
|
||||
}
|
||||
|
||||
if (recv_len != 0)
|
||||
{
|
||||
memcpy(data, read_buf, recv_len);
|
||||
}
|
||||
|
||||
if (len < recv_len)
|
||||
{
|
||||
TCP_SSL_DEBUG("ax_port_read: got %d bytes more than expected\n", recv_len - len);
|
||||
}
|
||||
|
||||
free(pread_buf);
|
||||
pread_buf = NULL;
|
||||
|
||||
return recv_len;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
void ax_wdt_feed() {}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
#endif // ASYNC_TCP_SSL_ENABLED
|
||||
@@ -0,0 +1,73 @@
|
||||
#ifndef LWIPR_COMPAT_H
|
||||
#define LWIPR_COMPAT_H
|
||||
|
||||
#include <async_config.h>
|
||||
|
||||
#if ASYNC_TCP_SSL_ENABLED
|
||||
|
||||
#include "lwipopts.h"
|
||||
/*
|
||||
All those functions will run only if LWIP tcp raw mode is used
|
||||
*/
|
||||
#if LWIP_RAW==1
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "include/ssl.h"
|
||||
|
||||
#define ERR_TCP_SSL_INVALID_SSL -101
|
||||
#define ERR_TCP_SSL_INVALID_TCP -102
|
||||
#define ERR_TCP_SSL_INVALID_CLIENTFD -103
|
||||
#define ERR_TCP_SSL_INVALID_CLIENTFD_DATA -104
|
||||
#define ERR_TCP_SSL_INVALID_DATA -105
|
||||
|
||||
#define TCP_SSL_TYPE_CLIENT 0
|
||||
#define TCP_SSL_TYPE_SERVER 1
|
||||
|
||||
#define tcp_ssl_ssl_write(A, B, C) tcp_ssl_write(A, B, C)
|
||||
#define tcp_ssl_ssl_read(A, B) tcp_ssl_read(A, B)
|
||||
|
||||
typedef void (* tcp_ssl_data_cb_t)(void *arg, struct tcp_pcb *tcp, uint8_t * data, size_t len);
|
||||
typedef void (* tcp_ssl_handshake_cb_t)(void *arg, struct tcp_pcb *tcp, SSL *ssl);
|
||||
typedef void (* tcp_ssl_error_cb_t)(void *arg, struct tcp_pcb *tcp, int8_t error);
|
||||
typedef int (* tcp_ssl_file_cb_t)(void *arg, const char *filename, uint8_t **buf);
|
||||
|
||||
uint8_t tcp_ssl_has_client();
|
||||
|
||||
int tcp_ssl_new_client(struct tcp_pcb *tcp);
|
||||
|
||||
SSL_CTX * tcp_ssl_new_server_ctx(const char *cert, const char *private_key_file, const char *password);
|
||||
int tcp_ssl_new_server(struct tcp_pcb *tcp, SSL_CTX* ssl_ctx);
|
||||
int tcp_ssl_is_server(struct tcp_pcb *tcp);
|
||||
|
||||
int tcp_ssl_free(struct tcp_pcb *tcp);
|
||||
int tcp_ssl_read(struct tcp_pcb *tcp, struct pbuf *p);
|
||||
|
||||
#ifdef AXTLS_2_0_0_SNDBUF
|
||||
int tcp_ssl_sndbuf(struct tcp_pcb *tcp);
|
||||
#endif
|
||||
|
||||
int tcp_ssl_write(struct tcp_pcb *tcp, uint8_t *data, size_t len);
|
||||
|
||||
void tcp_ssl_file(tcp_ssl_file_cb_t cb, void * arg);
|
||||
|
||||
void tcp_ssl_arg(struct tcp_pcb *tcp, void * arg);
|
||||
void tcp_ssl_data(struct tcp_pcb *tcp, tcp_ssl_data_cb_t arg);
|
||||
void tcp_ssl_handshake(struct tcp_pcb *tcp, tcp_ssl_handshake_cb_t arg);
|
||||
void tcp_ssl_err(struct tcp_pcb *tcp, tcp_ssl_error_cb_t arg);
|
||||
|
||||
SSL * tcp_ssl_get_ssl(struct tcp_pcb *tcp);
|
||||
bool tcp_ssl_has(struct tcp_pcb *tcp);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* LWIP_RAW==1 */
|
||||
|
||||
#endif /* ASYNC_TCP_SSL_ENABLED */
|
||||
|
||||
#endif /* LWIPR_COMPAT_H */
|
||||
Reference in New Issue
Block a user