From 3da2b9a311b240affc93f954cbc6dca656dea554 Mon Sep 17 00:00:00 2001 From: Gregg Date: Sun, 6 Sep 2020 08:24:13 -0500 Subject: [PATCH] Change Config.cpp to Network.cpp Move all configuration code into Network.cpp, eliminating any calls or connection to HAP.cpp. Network.cpp is now standalone for HomeSpan.cpp to call directly to handle ALL apects of WiFI and Setup Code initialization. Also move TempBuffer from HAP.h to Utils.h so it can be used by Network.h --- src/Configure.h | 20 ----- src/HAP.cpp | 8 +- src/HAP.h | 26 ------ src/HomeSpan.cpp | 61 +------------- src/HomeSpan.h | 3 - src/{Configure.cpp => Network.cpp} | 123 ++++++++++++++++++++++++++++- src/Network.h | 26 ++++++ src/Utils.h | 24 ++++++ 8 files changed, 175 insertions(+), 116 deletions(-) delete mode 100644 src/Configure.h rename src/{Configure.cpp => Network.cpp} (55%) create mode 100644 src/Network.h diff --git a/src/Configure.h b/src/Configure.h deleted file mode 100644 index 282bc1b..0000000 --- a/src/Configure.h +++ /dev/null @@ -1,20 +0,0 @@ - -#include -#include "Settings.h" - -/////////////////////////////// - -struct Configure { - - struct { - char ssid[MAX_SSID+1]; - char pwd[MAX_PWD+1]; - } wifiData; - - char setupCode[9]; - unsigned long timer; // time of trying to connect to WiFi - - void processRequest(WiFiClient &client, char *body, char *formData); - int getFormValue(char *formData, char *tag, char *value, int maxSize); - -}; diff --git a/src/HAP.cpp b/src/HAP.cpp index 737ffdc..62091ec 100644 --- a/src/HAP.cpp +++ b/src/HAP.cpp @@ -3,6 +3,7 @@ #include #include "HAP.h" +#include "Utils.h" ////////////////////////////////////// @@ -163,12 +164,6 @@ void HAPClient::processRequest(){ LOG2(body); LOG2("\n------------ END BODY! ------------\n"); - if(homeSpan.needsConfiguration){ // device not yet configured - content[cLen]='\0'; // add a trailing null on end of any contents, which should always be text-based - configure.processRequest(client, body, (char *)content); // process request - return; - } - if(!strncmp(body,"POST ",5)){ // this is a POST request if(cLen==0){ @@ -1571,5 +1566,4 @@ Accessory HAPClient::accessory; Controller HAPClient::controllers[MAX_CONTROLLERS]; SRP6A HAPClient::srp; int HAPClient::conNum; -Configure HAPClient::configure; diff --git a/src/HAP.h b/src/HAP.h index 6c4aa2d..ed4e755 100644 --- a/src/HAP.h +++ b/src/HAP.h @@ -7,7 +7,6 @@ #include "HKDF.h" #include "SRP.h" #include "HomeSpan.h" -#include "Configure.h" ///////////////////////////////////////////////// // NONCE Structure (HAP used last 64 of 96 bits) @@ -59,7 +58,6 @@ struct HAPClient { static Accessory accessory; // Accessory ID and Ed25519 public and secret keys- permanently stored static Controller controllers[MAX_CONTROLLERS]; // Paired Controller IDs and ED25519 long-term public keys - permanently stored static int conNum; // connection number - used to keep track of per-connection EV notifications - static Configure configure; // initial configuration of WiFi credentials and Setup Code // individual structures and data defined for each Hap Client connection @@ -121,30 +119,6 @@ struct HAPClient { static void eventNotify(SpanBuf *pObj, int nObj, int ignoreClient=-1); // transmits EVENT Notifications for nObj SpanBuf objects, pObj, with optional flag to ignore a specific client }; -///////////////////////////////////////////////// -// Creates a temporary buffer that is freed after -// going out of scope - -template -struct TempBuffer { - bufType *buf; - int nBytes; - - TempBuffer(size_t len){ - nBytes=len*sizeof(bufType); - buf=(bufType *)heap_caps_malloc(nBytes,MALLOC_CAP_8BIT); - } - - ~TempBuffer(){ - heap_caps_free(buf); - } - - int len(){ - return(nBytes); - } - -}; - ///////////////////////////////////////////////// // Extern Variables diff --git a/src/HomeSpan.cpp b/src/HomeSpan.cpp index 18e21c3..55ee342 100644 --- a/src/HomeSpan.cpp +++ b/src/HomeSpan.cpp @@ -2,10 +2,10 @@ #include #include #include -#include #include "Utils.h" #include "HAP.h" +#include "Network.h" using namespace Utils; @@ -205,6 +205,8 @@ int Span::getFreeSlot(){ void Span::initWifi(){ + Network network; // initialization of WiFi credentials and Setup Code + struct { char ssid[MAX_SSID+1]; char pwd[MAX_PWD+1]; @@ -230,7 +232,7 @@ void Span::initWifi(){ } else { statusLED.start(500,0.3,2,1000); - configure(hostName); + network.configure(hostName); Serial.print("Please configure network...\n"); sprintf(wifiData.ssid,"MyNetwork"); @@ -334,61 +336,6 @@ void Span::initWifi(){ /////////////////////////////// -void Span::configure(char *apName){ - - Serial.print("WiFi Configuration required. Please connect to Access Point: "); - Serial.print(apName); - Serial.print("\n"); - - const byte DNS_PORT = 53; - WiFiServer apServer(80); - DNSServer dnsServer; - IPAddress apIP(192, 168, 4, 1); - - WiFi.mode(WIFI_AP); - WiFi.softAP(apName,"homespan",1,false,1); - dnsServer.start(DNS_PORT, "*", apIP); - apServer.begin(); - - needsConfiguration=true; - - while(needsConfiguration){ - - dnsServer.processNextRequest(); - - if(hap[0].client=apServer.available()){ // found a new HTTP client - LOG2("=======================================\n"); - LOG1("** Access Point Client Connected: ("); - LOG1(millis()/1000); - LOG1(" sec) "); - LOG1(hap[0].client.remoteIP()); - LOG1("\n"); - LOG2("\n"); - } - - if(hap[0].client && hap[0].client.available()){ // if connection exists and data is available - - HAPClient::conNum=0; // set connection number - hap[0].processRequest(); // process HAP request - - if(!hap[0].client){ // client disconnected by server - LOG1("** Disconnecting AP Client ("); - LOG1(millis()/1000); - LOG1(" sec)\n"); - } - - LOG2("\n"); - - } // process HAP Client - - } - - while(1); - -} - -/////////////////////////////// - void Span::processSerialCommand(char *c){ switch(c[0]){ diff --git a/src/HomeSpan.h b/src/HomeSpan.h index c14e742..0427094 100644 --- a/src/HomeSpan.h +++ b/src/HomeSpan.h @@ -54,8 +54,6 @@ struct Span{ unsigned long resetTime; // tracks time once reset button is pressed Blinker statusLED=Blinker(LED_BUILTIN); // indicates HomeSpan status - - boolean needsConfiguration=false; // tracks whether device needs to be configured with WiFi credentials and a Setup Code SpanConfig hapConfig; // track configuration changes to the HAP Accessory database; used to increment the configuration number (c#) when changes found vector Accessories; // vector of pointers to all Accessories @@ -73,7 +71,6 @@ struct Span{ int getFreeSlot(); // returns free HAPClient slot number. HAPClients slot keep track of each active HAPClient connection void initWifi(); // initialize and connect to WiFi network void processSerialCommand(char *c); // process command 'c' (typically from readSerial, though can be called with any 'c') - void configure(char *hostName); // configure homeSpan WiFi and Setup Code using temporary Captive Access Point 'hostName' int sprintfAttributes(char *cBuf); // prints Attributes JSON database into buf, unless buf=NULL; return number of characters printed, excluding null terminator, even if buf=NULL void prettyPrint(char *buf, int nsp=2); // print arbitrary JSON from buf to serial monitor, formatted with indentions of 'nsp' spaces diff --git a/src/Configure.cpp b/src/Network.cpp similarity index 55% rename from src/Configure.cpp rename to src/Network.cpp index afdff99..0fee554 100644 --- a/src/Configure.cpp +++ b/src/Network.cpp @@ -1,9 +1,108 @@ -#include "Configure.h" +#include + +#include "Network.h" +#include "Utils.h" /////////////////////////////// -void Configure::processRequest(WiFiClient &client, char *body, char *formData){ +void Network::configure(char *apName){ + + Serial.print("WiFi Configuration required. Please enter details here of connect to Access Point: "); + Serial.print(apName); + Serial.print("\n"); + + WiFiServer apServer(80); + + TempBuffer tempBuffer(MAX_HTTP+1); + uint8_t *httpBuf=tempBuffer.buf; + + const byte DNS_PORT = 53; + DNSServer dnsServer; + IPAddress apIP(192, 168, 4, 1); + + WiFi.mode(WIFI_AP); + WiFi.softAP(apName,"homespan",1,false,1); // only allow one connection at a time + dnsServer.start(DNS_PORT, "*", apIP); + apServer.begin(); + + boolean needsConfiguration=true; + + while(needsConfiguration){ + + dnsServer.processNextRequest(); + + if(client=apServer.available()){ // found a new HTTP client + LOG2("=======================================\n"); + LOG1("** Access Point Client Connected: ("); + LOG1(millis()/1000); + LOG1(" sec) "); + LOG1(client.remoteIP()); + LOG1("\n"); + LOG2("\n"); + } + + if(client && client.available()){ // if connection exists and data is available + + LOG2("<<<<<<<<< "); + LOG2(client.remoteIP()); + LOG2(" <<<<<<<<<\n"); + + int nBytes=client.read(httpBuf,MAX_HTTP+1); // read all available bytes up to maximum allowed+1 + + if(nBytes>MAX_HTTP){ // exceeded maximum number of bytes allowed + badRequestError(); + Serial.print("\n*** ERROR: Exceeded maximum HTTP message length\n\n"); + continue; + } + + httpBuf[nBytes]='\0'; // add null character to enable string functions + char *body=(char *)httpBuf; // char pointer to start of HTTP Body + char *p; // char pointer used for searches + + if(!(p=strstr((char *)httpBuf,"\r\n\r\n"))){ + badRequestError(); + Serial.print("\n*** ERROR: Malformed HTTP request (can't find blank line indicating end of BODY)\n\n"); + continue; + } + + *p='\0'; // null-terminate end of HTTP Body to faciliate additional string processing + uint8_t *content=(uint8_t *)p+4; // byte pointer to start of optional HTTP Content + int cLen=0; // length of optional HTTP Content + + if((p=strstr(body,"Content-Length: "))) // Content-Length is specified + cLen=atoi(p+16); + if(nBytes!=strlen(body)+4+cLen){ + badRequestError(); + Serial.print("\n*** ERROR: Malformed HTTP request (Content-Length plus Body Length does not equal total number of bytes read)\n\n"); + continue; + } + + LOG2(body); + LOG2("\n------------ END BODY! ------------\n"); + + content[cLen]='\0'; // add a trailing null on end of any contents, which should always be text-based + processRequest(body, (char *)content); // process request + + if(!client){ // client disconnected by server + LOG1("** Disconnecting AP Client ("); + LOG1(millis()/1000); + LOG1(" sec)\n"); + } + + LOG2("\n"); + + } // process HAP Client + + } + + while(1); + +} + +/////////////////////////////// + +void Network::processRequest(char *body, char *formData){ String responseHead="HTTP/1.1 200 OK\r\nContent-type: text/html\r\n"; @@ -94,7 +193,7 @@ void Configure::processRequest(WiFiClient &client, char *body, char *formData){ ////////////////////////////////////// -int Configure::getFormValue(char *formData, char *tag, char *value, int maxSize){ +int Network::getFormValue(char *formData, char *tag, char *value, int maxSize){ char *s=strstr(formData,tag); // find start of tag @@ -120,3 +219,21 @@ int Configure::getFormValue(char *formData, char *tag, char *value, int maxSize) } ////////////////////////////////////// + +int Network::badRequestError(){ + + char s[]="HTTP/1.1 400 Bad Request\r\n\r\n"; + LOG2("\n>>>>>>>>>> "); + LOG2(client.remoteIP()); + LOG2(" >>>>>>>>>>\n"); + LOG2(s); + client.print(s); + LOG2("------------ SENT! --------------\n"); + + delay(1); + client.stop(); + + return(-1); +} + +////////////////////////////////////// diff --git a/src/Network.h b/src/Network.h new file mode 100644 index 0000000..b2ac5be --- /dev/null +++ b/src/Network.h @@ -0,0 +1,26 @@ + +#include +#include "Settings.h" + +/////////////////////////////// + +struct Network { + + struct { + char ssid[MAX_SSID+1]; + char pwd[MAX_PWD+1]; + } wifiData; + + const int MAX_HTTP=4095; // max number of bytes in HTTP message + + char setupCode[9]; // 8-digit Setup Code with room for null terminator + + WiFiClient client; // client used for HTTP calls + unsigned long timer; // time of trying to connect to WiFi + + void configure(char *hostName); // configure homeSpan WiFi and Setup Code using temporary Captive Access Point 'hostName' + void processRequest(char *body, char *formData); // process the HTTP request + int getFormValue(char *formData, char *tag, char *value, int maxSize); // search for 'tag' in 'formData' and copy result into 'value' up to 'maxSize' characters; returns number of characters, else -1 if 'tag' not found + int badRequestError(); // return 400 error + +}; diff --git a/src/Utils.h b/src/Utils.h index e116bf0..a6cbf3b 100644 --- a/src/Utils.h +++ b/src/Utils.h @@ -7,3 +7,27 @@ char *readSerial(char *c, int max); // read serial port into 'c' until +struct TempBuffer { + bufType *buf; + int nBytes; + + TempBuffer(size_t len){ + nBytes=len*sizeof(bufType); + buf=(bufType *)heap_caps_malloc(nBytes,MALLOC_CAP_8BIT); + } + + ~TempBuffer(){ + heap_caps_free(buf); + } + + int len(){ + return(nBytes); + } + +};