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
This commit is contained in:
Gregg 2020-09-06 08:24:13 -05:00
parent af3c093cdc
commit 3da2b9a311
8 changed files with 175 additions and 116 deletions

View File

@ -1,20 +0,0 @@
#include <WiFi.h>
#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);
};

View File

@ -3,6 +3,7 @@
#include <sodium.h>
#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;

View File

@ -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 <class bufType>
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

View File

@ -2,10 +2,10 @@
#include <ESPmDNS.h>
#include <nvs_flash.h>
#include <sodium.h>
#include <DNSServer.h>
#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]){

View File

@ -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<SpanAccessory *> 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

View File

@ -1,9 +1,108 @@
#include "Configure.h"
#include <DNSServer.h>
#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 <uint8_t> 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);
}
//////////////////////////////////////

26
src/Network.h Normal file
View File

@ -0,0 +1,26 @@
#include <WiFi.h>
#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
};

View File

@ -7,3 +7,27 @@ char *readSerial(char *c, int max); // read serial port into 'c' until <newlin
String mask(char *c, int n); // simply utility that creates a String from 'c' with all except the first and last 'n' characters replaced by '*'
}
/////////////////////////////////////////////////
// Creates a temporary buffer that is freed after
// going out of scope
template <class bufType>
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);
}
};