many changes :Py

This commit is contained in:
kazu
2018-07-08 17:47:59 +02:00
parent 11ed5a9159
commit 528a00b0e9
14 changed files with 843 additions and 91 deletions

160
net/HTTP.h Normal file
View File

@@ -0,0 +1,160 @@
#ifndef HTTP_H
#define HTTP_H
#include "TCP.h"
#include "../Debug.h"
class HTTPClient;
typedef void (*HTTPCBodyDataCallback)(HTTPClient* httpc, const uint8_t* data, uint16_t len);
typedef void (*HTTPCConnectCallback)(HTTPClient* httpc);
typedef void (*HTTPCDisconnectCallback)(HTTPClient* httpc);
class HTTPClient {
static constexpr const char* NAME = "HTTPC";
TCP tcp;
espconn dns;
ip_addr_t ip;
char host[64];
char query[128];
bool gotHeader = false;
int numBreaks = 0;
HTTPCConnectCallback onConnect = nullptr;
HTTPCDisconnectCallback onDisconnect = nullptr;
HTTPCBodyDataCallback onBodyData = nullptr;
public:
/** ctor */
HTTPClient() {
debugMod(NAME, "init()");
tcp.setUserData(this);
tcp.setDataCallback(_onData);
tcp.setConnectCallback(_onConnect);
tcp.setDisconnectCallback(_onDisconnect);
}
void hold() {
tcp.hold();
}
void unhold() {
tcp.unhold();
}
void setBodyDataCallback(HTTPCBodyDataCallback c) {
this->onBodyData = c;
}
void setConnectCallback(HTTPCConnectCallback c) {
this->onConnect = c;
}
void setDisconnectCallback(HTTPCDisconnectCallback c) {
this->onDisconnect = c;
}
/** connect to the given IP/Port */
void connect(const char* url) {
//strcpy(this->url, url);
const char* hostStart = &url[7]; // skip the "http://"
const char* hostEnd = strchr(hostStart, '/'); // find the terminating /
strncpy(this->host, hostStart, hostEnd-hostStart); // hostname only
this->host[hostEnd-hostStart] = 0; // 0 terminator!!
strcpy(this->query, hostEnd); // query only
debugMod3(NAME, "connect(%s) -> host: '%s' query: '%s'", url, this->host, this->query);
resolveHost(this->host);
}
void disconnect() {
tcp.disconnect();
gotHeader = false;
numBreaks = 0;
}
private:
/** from TCP: connected */
static void _onConnect(TCP* tcp) {
debugMod(NAME, "connected");
HTTPClient* httpc = (HTTPClient*) tcp->getUserData();
if (httpc->onConnect) {httpc->onConnect(httpc);}
httpc->sendRequest();
}
/** from TCP: disconnected */
static void _onDisconnect(TCP* tcp) {
debugMod(NAME, "disconnected");
HTTPClient* httpc = (HTTPClient*) tcp->getUserData();
if (httpc->onDisconnect) {httpc->onDisconnect(httpc);}
}
/** from TCP: got data */
static void _onData(TCP* tcp, const uint8_t* data, const uint16_t dataLen) {
HTTPClient* httpc = (HTTPClient*) tcp->getUserData();
httpc->onData(data, dataLen);
}
/** analyze incoming data */
void onData(const uint8_t* data, uint16_t dataLen) {
// header not yet received. scan incoming data. count number of consecutive linebreaks
if (!gotHeader) {
while(dataLen && !gotHeader) {
const char c = *data;
if (c == '\r' || c == '\n') {++numBreaks;} else {numBreaks = 0;}
if (numBreaks == 4) {
debugMod(NAME, "got header");
gotHeader = true;
}
++data; --dataLen;
}
}
// maybe we got the header now
if (gotHeader && dataLen) {
if (onBodyData) {
onBodyData(this, data, dataLen);
}
}
}
private:
/** resolve hostname. creates callback */
void resolveHost(const char* c) {
debugMod1(NAME, "dns lookup: %s", c);
dns.reverse = (void*) this;
espconn_gethostbyname(&dns, c, &ip, _onHostResolved);
}
/** send the request header */
void sendRequest() {
char buf[128];
const int len = os_sprintf(buf, "GET %s HTTP/1.1\r\nicy-metadata:1\r\n\r\n", this->query);
debugMod(NAME, buf);
tcp.send((const uint8_t*)buf, len);
}
static void _onHostResolved(const char* name, ip_addr_t* ipaddr, void* arg ) {
HTTPClient* http = (HTTPClient*) ((espconn*)arg)->reverse;
if (ipaddr) {
//debugMod1(NAME, "dns lookup returned: %s", tmp.toString());
http->tcp.connect(IP(*ipaddr), 80);
} else {
debugMod1(NAME, "dns lookup failed: %s", name);
}
}
};
#endif // HTTP_H

View File

@@ -5,21 +5,40 @@
struct IP {
uint32_t val;
//uint32_t val;
ip_addr addr;
/** empty ctor */
IP() : val(0) {
;
explicit IP() {
addr.addr = 0;
}
/** ctor with IP-string */
IP(const char* ipStr) {
explicit IP(const char* ipStr) {
set(ipStr);
}
/** set the IP */
/** ctor with ip_addr_t */
explicit IP(ip_addr addr) : addr(addr) {
;
}
/** set the IP by string: x.x.x.x */
void set(const char* ipStr) {
val = ipaddr_addr(ipStr);
addr.addr = ipaddr_addr(ipStr);
}
/** convert to ip_addr/ip_addr_t */
const ip_addr* getPtr() const {
return &addr;
}
/** convert to string */
const char* toString() const {
//static char str[16];
//ipaddr_aton(str, (ip_addr*)&addr);
//return str;
return ipaddr_ntoa(&addr);
}
};

170
net/TCP.h Normal file
View File

@@ -0,0 +1,170 @@
#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

View File

@@ -52,7 +52,7 @@ public:
// set remote port and IP
con->proto.udp->remote_port = port;
os_memcpy(con->proto.udp->remote_ip, &(ip.val), 4);
os_memcpy(con->proto.udp->remote_ip, ip.getPtr(), 4);
//os_printf("send %d bytes\r\n", dataLen);
//os_printf("IP: %d.%d.%d.%d\n\r", con->proto.udp->remote_ip[0], con->proto.udp->remote_ip[1], con->proto.udp->remote_ip[2], con->proto.udp->remote_ip[3]);