Converted sprintfAttributes to printfAttributes and added encryption to HapOut

Success!
This commit is contained in:
Gregg 2023-12-30 23:07:09 -06:00
parent 83924a6bdf
commit f2cb880e4e
5 changed files with 196 additions and 30 deletions

View File

@ -337,7 +337,7 @@ int HAPClient::postPairSetupURL(uint8_t *content, size_t len){
iosTLV.print(); iosTLV.print();
LOG2("------------ END TLVS! ------------\n"); LOG2("------------ END TLVS! ------------\n");
LOG2("In Pair Setup #%d (%s)...",conNum,client.remoteIP().toString().c_str()); LOG1("In Pair Setup #%d (%s)...",conNum,client.remoteIP().toString().c_str());
auto itState=iosTLV.find(kTLVType_State); auto itState=iosTLV.find(kTLVType_State);
@ -584,7 +584,7 @@ int HAPClient::postPairVerifyURL(uint8_t *content, size_t len){
iosTLV.print(); iosTLV.print();
LOG2("------------ END TLVS! ------------\n"); LOG2("------------ END TLVS! ------------\n");
LOG2("In Pair Verify #%d (%s)...",conNum,client.remoteIP().toString().c_str()); LOG1("In Pair Verify #%d (%s)...",conNum,client.remoteIP().toString().c_str());
auto itState=iosTLV.find(kTLVType_State); auto itState=iosTLV.find(kTLVType_State);
@ -772,7 +772,7 @@ int HAPClient::postPairingsURL(uint8_t *content, size_t len){
iosTLV.print(); iosTLV.print();
LOG2("------------ END TLVS! ------------\n"); LOG2("------------ END TLVS! ------------\n");
LOG2("In Post Pairings #%d (%s)...",conNum,client.remoteIP().toString().c_str()); LOG1("In Post Pairings #%d (%s)...",conNum,client.remoteIP().toString().c_str());
auto itState=iosTLV.find(kTLVType_State); auto itState=iosTLV.find(kTLVType_State);
auto itMethod=iosTLV.find(kTLVType_Method); auto itMethod=iosTLV.find(kTLVType_Method);
@ -898,28 +898,38 @@ int HAPClient::getAccessoriesURL(){
return(0); return(0);
} }
LOG1("In Get Accessories #"); LOG1("In Get Accessories #%d (%s)...",conNum,client.remoteIP().toString().c_str());
LOG1(conNum);
LOG1(" (");
LOG1(client.remoteIP());
LOG1(")...\n");
int nBytes = homeSpan.sprintfAttributes(NULL); // get size of HAP attributes JSON homeSpan.printfAttributes();
TempBuffer<char> jBuf(nBytes+1); size_t nBytes=hapOut.getSize();
homeSpan.sprintfAttributes(jBuf); // create JSON database (will need to re-cast to uint8_t* below) hapOut.flush();
char *body; LOG2("\n>>>>>>>>>> %s >>>>>>>>>>\n",client.remoteIP().toString().c_str());
asprintf(&body,"HTTP/1.1 200 OK\r\nContent-Type: application/hap+json\r\nContent-Length: %d\r\n\r\n",nBytes);
hapOut.setLogLevel(2).setHapClient(this);
hapOut << "HTTP/1.1 200 OK\r\nContent-Type: application/hap+json\r\nContent-Length: " << nBytes << "\r\n\r\n";
homeSpan.printfAttributes();
hapOut.flush();
LOG2("\n-------- SENT ENCRYPTED! --------\n");
// int nBytes = homeSpan.sprintfAttributes(NULL); // get size of HAP attributes JSON
// TempBuffer<char> jBuf(nBytes+1);
// homeSpan.sprintfAttributes(jBuf); // create JSON database (will need to re-cast to uint8_t* below)
// char *body;
// asprintf(&body,"HTTP/1.1 200 OK\r\nContent-Type: application/hap+json\r\nContent-Length: %d\r\n\r\n",nBytes);
LOG2("\n>>>>>>>>>> "); // LOG2("\n>>>>>>>>>> ");
LOG2(client.remoteIP()); // LOG2(client.remoteIP());
LOG2(" >>>>>>>>>>\n"); // LOG2(" >>>>>>>>>>\n");
LOG2(body); // LOG2(body);
LOG2(jBuf.get()); // LOG2(jBuf.get());
LOG2("\n"); // LOG2("\n");
sendEncrypted(body,(uint8_t *)jBuf.get(),nBytes); // sendEncrypted(body,(uint8_t *)jBuf.get(),nBytes);
free(body); // free(body);
return(1); return(1);
@ -1638,7 +1648,8 @@ void Nonce::inc(){
HapOut::HapStreamBuffer::HapStreamBuffer(){ HapOut::HapStreamBuffer::HapStreamBuffer(){
buffer=(char *)HS_MALLOC(bufSize+1); // add 1 for adding null terminator when printing text buffer=(char *)HS_MALLOC(bufSize+1); // add 1 for adding null terminator when printing text
encBuf=(uint8_t *)HS_MALLOC(bufSize+18); // 2-byte AAD + encrypted data + 16-byte authentication tag
setp(buffer, buffer+bufSize-1); setp(buffer, buffer+bufSize-1);
} }
@ -1664,7 +1675,19 @@ void HapOut::HapStreamBuffer::flushBuffer(){
} }
if(hapClient!=NULL){ if(hapClient!=NULL){
hapClient->client.write(buffer,num); if(!hapClient->cPair){ // if not encrypted
hapClient->client.write(buffer,num); // transmit data buffer
} else { // if encrypted
encBuf[0]=num%256; // store number of bytes that encrypts this frame (AAD bytes)
encBuf[1]=num/256;
crypto_aead_chacha20poly1305_ietf_encrypt(encBuf+2,NULL,(uint8_t *)buffer,num,encBuf,2,NULL,hapClient->a2cNonce.get(),hapClient->a2cKey); // encrypt buffer with AAD prepended and authentication tag appended
hapClient->client.write(encBuf,num+18); // transmit encrypted frame
hapClient->a2cNonce.inc(); // increment nonce
}
delay(1); delay(1);
} }

View File

@ -190,6 +190,7 @@ class HapOut : public std::ostream {
const size_t bufSize=1024; // max allowed for HAP encrypted records const size_t bufSize=1024; // max allowed for HAP encrypted records
char *buffer; char *buffer;
uint8_t *encBuf;
HAPClient *hapClient=NULL; HAPClient *hapClient=NULL;
int logLevel=255; // default is NOT to print anything int logLevel=255; // default is NOT to print anything
boolean enablePrettyPrint=false; boolean enablePrettyPrint=false;

View File

@ -620,12 +620,20 @@ void Span::processSerialCommand(const char *c){
case 'd': { case 'd': {
TempBuffer<char> qBuf(sprintfAttributes(NULL)+1); // TempBuffer<char> qBuf(sprintfAttributes(NULL)+1);
sprintfAttributes(qBuf); // sprintfAttributes(qBuf);
LOG0("\n*** Attributes Database: size=%d configuration=%d ***\n\n",qBuf.len()-1,hapConfig.configNumber); printfAttributes();
prettyPrint(qBuf); LOG0("\n*** Attributes Database: size=%d configuration=%d ***\n\n",hapOut.getSize(),hapConfig.configNumber);
LOG0("\n*** End Database ***\n\n"); hapOut.flush();
// LOG0("\n*** Attributes Database: size=%d configuration=%d ***\n\n",qBuf.len()-1,hapConfig.configNumber);
// prettyPrint(qBuf);
hapOut.setLogLevel(0);
printfAttributes();
hapOut.flush();
LOG0("\n\n*** End Database ***\n\n");
} }
break; break;
@ -1232,6 +1240,21 @@ Span& Span::setWifiCredentials(const char *ssid, const char *pwd){
/////////////////////////////// ///////////////////////////////
void Span::printfAttributes(int flags){
hapOut << "{\"accessories\":[";
for(int i=0;i<Accessories.size();i++){
Accessories[i]->printfAttributes(flags);
if(i+1<Accessories.size())
hapOut << "," ;
}
hapOut << "]}";
}
///////////////////////////////
int Span::sprintfAttributes(char *cBuf, int flags){ int Span::sprintfAttributes(char *cBuf, int flags){
int nBytes=0; int nBytes=0;
@ -1680,6 +1703,21 @@ SpanAccessory::~SpanAccessory(){
/////////////////////////////// ///////////////////////////////
void SpanAccessory::printfAttributes(int flags){
hapOut << "{\"aid\":" << aid << ",\"services\":[";
for(int i=0;i<Services.size();i++){
Services[i]->printfAttributes(flags);
if(i+1<Services.size())
hapOut << ",";
}
hapOut << "]}";
}
///////////////////////////////
int SpanAccessory::sprintfAttributes(char *cBuf, int flags){ int SpanAccessory::sprintfAttributes(char *cBuf, int flags){
int nBytes=0; int nBytes=0;
@ -1772,6 +1810,39 @@ SpanService *SpanService::addLink(SpanService *svc){
/////////////////////////////// ///////////////////////////////
void SpanService::printfAttributes(int flags){
hapOut << "{\"iid\":" << iid << ",\"type\":\"" << type << "\",";
if(hidden)
hapOut << "\"hidden\":true,";
if(primary)
hapOut << "\"primary\":true,";
if(!linkedServices.empty()){
hapOut << "\"linked\":[";
for(int i=0;i<linkedServices.size();i++){
hapOut << linkedServices[i]->iid;
if(i+1<linkedServices.size())
hapOut << ",";
}
hapOut << "],";
}
hapOut << "\"characteristics\":[";
for(int i=0;i<Characteristics.size();i++){
Characteristics[i]->printfAttributes(flags);
if(i+1<Characteristics.size())
hapOut << ",";
}
hapOut << "]}";
}
///////////////////////////////
int SpanService::sprintfAttributes(char *cBuf, int flags){ int SpanService::sprintfAttributes(char *cBuf, int flags){
int nBytes=0; int nBytes=0;
@ -1859,6 +1930,72 @@ SpanCharacteristic::~SpanCharacteristic(){
/////////////////////////////// ///////////////////////////////
void SpanCharacteristic::printfAttributes(int flags){
const char permCodes[][7]={"pr","pw","ev","aa","tw","hd","wr"};
const char formatCodes[][9]={"bool","uint8","uint16","uint32","uint64","int","float","string","data"};
hapOut << "{\"iid\":" << iid;
if(flags&GET_TYPE)
hapOut << ",\"type\":\"" << type << "\"";
if((perms&PR) && (flags&GET_VALUE)){
if(perms&NV && !(flags&GET_NV))
hapOut << ",\"value\":null";
else
hapOut << ",\"value\":" << uvPrint(value).c_str();
}
if(flags&GET_META){
hapOut << ",\"format\":\"" << formatCodes[format] << "\"";
if(customRange && (flags&GET_META)){
hapOut << ",\"minValue\":" << uvPrint(minValue).c_str() << "\"maxValue\":" << uvPrint(maxValue).c_str();
if(uvGet<float>(stepValue)>0)
hapOut << ",\"minStep\":" << uvPrint(stepValue).c_str();
}
if(unit){
if(strlen(unit)>0)
hapOut << ",\"unit\":\"" << unit << "\"";
else
hapOut << ",\"unit\":null";
}
if(validValues){
hapOut << ",\"valid-values\":" << validValues;
}
}
if(desc && (flags&GET_DESC)){
hapOut << ",\"description\":\"" << desc << "\"";
}
if(flags&GET_PERMS){
hapOut << ",\"perms\":[";
for(int i=0;i<7;i++){
if(perms&(1<<i)){
hapOut << "\"" << permCodes[i] <<"\"";
if(perms>=(1<<(i+1)))
hapOut << ",";
}
}
hapOut << "]";
}
if(flags&GET_AID)
hapOut << ",\"aid\":" << aid;
if(flags&GET_EV)
hapOut << ",\"ev\":" << (ev[HAPClient::conNum]?"true":"false");
hapOut << "}";
}
///////////////////////////////
int SpanCharacteristic::sprintfAttributes(char *cBuf, int flags){ int SpanCharacteristic::sprintfAttributes(char *cBuf, int flags){
int nBytes=0; int nBytes=0;

View File

@ -286,6 +286,7 @@ class Span{
void reboot(); // reboots device void reboot(); // reboots device
int sprintfAttributes(char *cBuf, int flags=GET_VALUE|GET_META|GET_PERMS|GET_TYPE|GET_DESC); // prints Attributes JSON database into buf, unless buf=NULL; return number of characters printed, excluding null terminator int sprintfAttributes(char *cBuf, int flags=GET_VALUE|GET_META|GET_PERMS|GET_TYPE|GET_DESC); // prints Attributes JSON database into buf, unless buf=NULL; return number of characters printed, excluding null terminator
void printfAttributes(int flags=GET_VALUE|GET_META|GET_PERMS|GET_TYPE|GET_DESC); // writes Attributes JSON database to hapOut stream
void prettyPrint(char *buf, int nsp=2, int minLogLevel=0); // print arbitrary JSON from buf to serial monitor, formatted with indentions of 'nsp' spaces, subject to specified minimum log level void prettyPrint(char *buf, int nsp=2, int minLogLevel=0); // print arbitrary JSON from buf to serial monitor, formatted with indentions of 'nsp' spaces, subject to specified minimum log level
SpanCharacteristic *find(uint32_t aid, int iid); // return Characteristic with matching aid and iid (else NULL if not found) SpanCharacteristic *find(uint32_t aid, int iid); // return Characteristic with matching aid and iid (else NULL if not found)
@ -409,6 +410,7 @@ class SpanAccessory{
vector<SpanService *, Mallocator<SpanService*>> Services; // vector of pointers to all Services in this Accessory vector<SpanService *, Mallocator<SpanService*>> Services; // vector of pointers to all Services in this Accessory
int sprintfAttributes(char *cBuf, int flags); // prints Accessory JSON database into buf, unless buf=NULL; return number of characters printed, excluding null terminator, even if buf=NULL int sprintfAttributes(char *cBuf, int flags); // prints Accessory JSON database into buf, unless buf=NULL; return number of characters printed, excluding null terminator, even if buf=NULL
void printfAttributes(int flags); // writes Accessory JSON to hapOut stream
protected: protected:
@ -440,6 +442,7 @@ class SpanService{
SpanAccessory *accessory=NULL; // pointer to Accessory containing this Service SpanAccessory *accessory=NULL; // pointer to Accessory containing this Service
int sprintfAttributes(char *cBuf, int flags); // prints Service JSON records into buf; return number of characters printed, excluding null terminator int sprintfAttributes(char *cBuf, int flags); // prints Service JSON records into buf; return number of characters printed, excluding null terminator
void printfAttributes(int flags); // writes Service JSON to hapOut stream
protected: protected:
@ -505,8 +508,10 @@ class SpanCharacteristic{
unsigned long updateTime=0; // last time value was updated (in millis) either by PUT /characteristic OR by setVal() unsigned long updateTime=0; // last time value was updated (in millis) either by PUT /characteristic OR by setVal()
UVal newValue; // the updated value requested by PUT /characteristic UVal newValue; // the updated value requested by PUT /characteristic
SpanService *service=NULL; // pointer to Service containing this Characteristic SpanService *service=NULL; // pointer to Service containing this Characteristic
int sprintfAttributes(char *cBuf, int flags); // prints Characteristic JSON records into buf, according to flags mask; return number of characters printed, excluding null terminator int sprintfAttributes(char *val, int flags); // prints Characteristic JSON records into buf; return number of characters printed, excluding null terminator
void printfAttributes(int flags); // writes Characteristic JSON to hapOut stream
StatusCode loadUpdate(char *val, char *ev); // load updated val/ev from PUT /characteristic JSON request. Return intitial HAP status code (checks to see if characteristic is found, is writable, etc.) StatusCode loadUpdate(char *val, char *ev); // load updated val/ev from PUT /characteristic JSON request. Return intitial HAP status code (checks to see if characteristic is found, is writable, etc.)
String uvPrint(UVal &u){ String uvPrint(UVal &u){

View File

@ -27,7 +27,7 @@
#include "HomeSpan.h" #include "HomeSpan.h"
#define MAX_LIGHTS 1 #define MAX_LIGHTS 3
void setup() { void setup() {