#ifndef TCP_H #define TCP_H extern "C" { #include "mem.h" #include "espconn.h" } class TCP; typedef void (*TCPDataCallback)(TCP* tcp, const uint8_t* data, uint16_t len); typedef void (*TCPConnectCallback)(TCP* tcp); typedef void (*TCPDisconnectCallback)(TCP* tcp); #include "../Debug.h" #include "IP.h" class TCP { private: static constexpr const char* NAME = "TCP"; espconn* con; esp_tcp tcp; bool connected = false; TCPDataCallback onData = nullptr; TCPConnectCallback onConnect = nullptr; TCPDisconnectCallback onDisconnect = nullptr; void* userData = nullptr; public: TCP() { init(); } /** dtor */ ~TCP() { cleanup(); } /** send data to the other side */ bool send(const uint8_t* data, const size_t dataLen) { const int res = espconn_sent(con, (unsigned char*)data, dataLen); return (res == 0); } /** connect to the given IP and port */ void connect(const IP ip, const Port port) { disconnect(); debugMod2(NAME, "connect(%s, %d)", ip.toString(), port); con->proto.tcp->remote_port = port; con->proto.tcp->local_port = espconn_port(); os_memcpy(con->proto.tcp->remote_ip, ip.getPtr(), 4); espconn_connect(con); connected = true; } /** terminate connection */ void disconnect() { if (!connected) {return;} espconn_disconnect(con); connected = false; } void hold() { if (connected) { espconn_recv_hold(con); } } void unhold() { if (connected) { espconn_recv_unhold(con); } } /** set the callback to call whenever data is received */ void setDataCallback(TCPDataCallback callback) { this->onData = callback; } /** set the callback to call when connection is established */ void setConnectCallback(TCPConnectCallback callback) { this->onConnect = callback; } /** set the callback to call when connection is lost */ void setDisconnectCallback(TCPDisconnectCallback callback) { this->onDisconnect = callback; } /** attach user-data to this object. can bed used within callbacks */ void setUserData(void* ptr) { this->userData = ptr; } /** get previously attached user data */ void* getUserData() const { return this->userData; } private: /** called for incoming data */ static void _onData(void* ptr, char* data, unsigned short len) { TCP* tcp = (TCP*) ((espconn*)ptr)->reverse; if (tcp->onData) {tcp->onData(tcp, (const uint8_t*)data, len);} } /** called when connection is established */ static void _onConnect(void* ptr) { TCP* tcp = (TCP*) ((espconn*)ptr)->reverse; if (tcp->onConnect) {tcp->onConnect(tcp);} tcp->connected = true; } /** called when connection is lost */ static void _onDisconnect(void* ptr) { TCP* tcp = (TCP*) ((espconn*)ptr)->reverse; if (tcp->onDisconnect) {tcp->onDisconnect(tcp);} tcp->connected = false; } /** initialize the UDP "connection" */ void init() { debugMod(NAME, "init()"); // allocate connection-objects con = (espconn*) os_zalloc(sizeof(espconn)); ets_memset( con, 0, sizeof( espconn ) ); // configure con->type = ESPCONN_TCP; con->state = ESPCONN_NONE; //con->proto.tcp = (esp_tcp*) os_zalloc(sizeof(esp_tcp)); con->proto.tcp = &tcp; // attach ourselves for the callback con->reverse = (void*) this; // user-data to refer to this class espconn_regist_recvcb(con, _onData); espconn_regist_connectcb(con, _onConnect); espconn_regist_disconcb(con, _onDisconnect); // espconn_regist_reconcb(con, _onDisconnect); } /** cleanup everything */ void cleanup() { debugMod(NAME, "cleanup()"); espconn_delete(con); //os_free(con->proto.tcp); os_free(con); con = nullptr; } }; #endif // TCP_H