Replaced appropriate snprintf() with asprintf() and used *m in sscanf

Optimized use of heap memory instead of stack memory for temporary variables, and makes code easier to read, provided all heap usage is free() at end of each function.

Also removed char *hostName as a member variable of homeSpan.  It's never actually used since MDNS constructs its own copy of hostName as needed.
This commit is contained in:
Gregg 2023-07-26 22:46:20 -05:00
parent 0f6e58435e
commit 793f7882b1
4 changed files with 37 additions and 43 deletions

View File

@ -114,12 +114,6 @@ void HAPClient::init(){
printControllers(); printControllers();
// create broadcaset name from server base name plus accessory ID (without ':')
int nChars=snprintf(NULL,0,"%s-%2.2s%2.2s%2.2s%2.2s%2.2s%2.2s",homeSpan.hostNameBase,accessory.ID,accessory.ID+3,accessory.ID+6,accessory.ID+9,accessory.ID+12,accessory.ID+15);
homeSpan.hostName=(char *)malloc(nChars+1);
sprintf(homeSpan.hostName,"%s-%2.2s%2.2s%2.2s%2.2s%2.2s%2.2s",homeSpan.hostNameBase,accessory.ID,accessory.ID+3,accessory.ID+6,accessory.ID+9,accessory.ID+12,accessory.ID+15);
tlv8.create(kTLVType_State,1,"STATE"); // define the actual TLV records needed for the implementation of HAP; one for each kTLVType needed (HAP Table 5-6) tlv8.create(kTLVType_State,1,"STATE"); // define the actual TLV records needed for the implementation of HAP; one for each kTLVType needed (HAP Table 5-6)
tlv8.create(kTLVType_PublicKey,384,"PUBKEY"); tlv8.create(kTLVType_PublicKey,384,"PUBKEY");
tlv8.create(kTLVType_Method,1,"METHOD"); tlv8.create(kTLVType_Method,1,"METHOD");
@ -876,9 +870,8 @@ int HAPClient::getAccessoriesURL(){
TempBuffer <char> jBuf(nBytes+1); TempBuffer <char> jBuf(nBytes+1);
homeSpan.sprintfAttributes(jBuf.get()); // create JSON database (will need to re-cast to uint8_t* below) homeSpan.sprintfAttributes(jBuf.get()); // create JSON database (will need to re-cast to uint8_t* below)
int nChars=snprintf(NULL,0,"HTTP/1.1 200 OK\r\nContent-Type: application/hap+json\r\nContent-Length: %d\r\n\r\n",nBytes); // create '200 OK' Body with Content Length = size of JSON Buf char *body;
char body[nChars+1]; asprintf(&body,"HTTP/1.1 200 OK\r\nContent-Type: application/hap+json\r\nContent-Length: %d\r\n\r\n",nBytes);
sprintf(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());
@ -888,6 +881,7 @@ int HAPClient::getAccessoriesURL(){
LOG2("\n"); LOG2("\n");
sendEncrypted(body,(uint8_t *)jBuf.get(),nBytes); sendEncrypted(body,(uint8_t *)jBuf.get(),nBytes);
free(body);
return(1); return(1);
@ -1087,9 +1081,8 @@ int HAPClient::getCharacteristicsURL(char *urlBuf){
boolean sFlag=strstr(jsonBuf,"status"); // status attribute found? boolean sFlag=strstr(jsonBuf,"status"); // status attribute found?
int nChars=snprintf(NULL,0,"HTTP/1.1 %s\r\nContent-Type: application/hap+json\r\nContent-Length: %d\r\n\r\n",!sFlag?"200 OK":"207 Multi-Status",nBytes); char *body;
char body[nChars+1]; asprintf(&body,"HTTP/1.1 %s\r\nContent-Type: application/hap+json\r\nContent-Length: %d\r\n\r\n",!sFlag?"200 OK":"207 Multi-Status",nBytes);
sprintf(body,"HTTP/1.1 %s\r\nContent-Type: application/hap+json\r\nContent-Length: %d\r\n\r\n",!sFlag?"200 OK":"207 Multi-Status",nBytes);
LOG2("\n>>>>>>>>>> "); LOG2("\n>>>>>>>>>> ");
LOG2(client.remoteIP()); LOG2(client.remoteIP());
@ -1099,7 +1092,8 @@ int HAPClient::getCharacteristicsURL(char *urlBuf){
LOG2("\n"); LOG2("\n");
sendEncrypted(body,(uint8_t *)jsonBuf,nBytes); // note recasting of jsonBuf into uint8_t* sendEncrypted(body,(uint8_t *)jsonBuf,nBytes); // note recasting of jsonBuf into uint8_t*
free(body);
return(1); return(1);
} }
@ -1148,9 +1142,8 @@ int HAPClient::putCharacteristicsURL(char *json){
char jsonBuf[nBytes+1]; char jsonBuf[nBytes+1];
homeSpan.sprintfAttributes(pObj,n,jsonBuf); homeSpan.sprintfAttributes(pObj,n,jsonBuf);
int nChars=snprintf(NULL,0,"HTTP/1.1 207 Multi-Status\r\nContent-Type: application/hap+json\r\nContent-Length: %d\r\n\r\n",nBytes); // create Body with Content Length = size of JSON Buf char *body;
char body[nChars+1]; asprintf(&body,"HTTP/1.1 207 Multi-Status\r\nContent-Type: application/hap+json\r\nContent-Length: %d\r\n\r\n",nBytes);
sprintf(body,"HTTP/1.1 207 Multi-Status\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());
@ -1160,6 +1153,7 @@ int HAPClient::putCharacteristicsURL(char *json){
LOG2("\n"); LOG2("\n");
sendEncrypted(body,(uint8_t *)jsonBuf,nBytes); // note recasting of jsonBuf into uint8_t* sendEncrypted(body,(uint8_t *)jsonBuf,nBytes); // note recasting of jsonBuf into uint8_t*
free(body);
} }
@ -1209,9 +1203,8 @@ int HAPClient::putPrepareURL(char *json){
sprintf(jsonBuf,"{\"status\":%d}",(int)status); sprintf(jsonBuf,"{\"status\":%d}",(int)status);
int nBytes=strlen(jsonBuf); int nBytes=strlen(jsonBuf);
int nChars=snprintf(NULL,0,"HTTP/1.1 200 OK\r\nContent-Type: application/hap+json\r\nContent-Length: %d\r\n\r\n",nBytes); // create Body with Content Length = size of JSON Buf char *body;
char body[nChars+1]; asprintf(&body,"HTTP/1.1 200 OK\r\nContent-Type: application/hap+json\r\nContent-Length: %d\r\n\r\n",nBytes);
sprintf(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());
@ -1221,6 +1214,7 @@ int HAPClient::putPrepareURL(char *json){
LOG2("\n"); LOG2("\n");
sendEncrypted(body,(uint8_t *)jsonBuf,nBytes); // note recasting of jsonBuf into uint8_t* sendEncrypted(body,(uint8_t *)jsonBuf,nBytes); // note recasting of jsonBuf into uint8_t*
free(body);
return(1); return(1);
} }
@ -1403,9 +1397,8 @@ void HAPClient::eventNotify(SpanBuf *pObj, int nObj, int ignoreClient){
char jsonBuf[nBytes+1]; char jsonBuf[nBytes+1];
homeSpan.sprintfNotify(pObj,nObj,jsonBuf,cNum); homeSpan.sprintfNotify(pObj,nObj,jsonBuf,cNum);
int nChars=snprintf(NULL,0,"EVENT/1.0 200 OK\r\nContent-Type: application/hap+json\r\nContent-Length: %d\r\n\r\n",nBytes); // create Body with Content Length = size of JSON Buf char *body;
char body[nChars+1]; asprintf(&body,"EVENT/1.0 200 OK\r\nContent-Type: application/hap+json\r\nContent-Length: %d\r\n\r\n",nBytes);
sprintf(body,"EVENT/1.0 200 OK\r\nContent-Type: application/hap+json\r\nContent-Length: %d\r\n\r\n",nBytes);
LOG2("\n>>>>>>>>>> "); LOG2("\n>>>>>>>>>> ");
LOG2(hap[cNum]->client.remoteIP()); LOG2(hap[cNum]->client.remoteIP());
@ -1415,6 +1408,7 @@ void HAPClient::eventNotify(SpanBuf *pObj, int nObj, int ignoreClient){
LOG2("\n"); LOG2("\n");
hap[cNum]->sendEncrypted(body,(uint8_t *)jsonBuf,nBytes); // note recasting of jsonBuf into uint8_t* hap[cNum]->sendEncrypted(body,(uint8_t *)jsonBuf,nBytes); // note recasting of jsonBuf into uint8_t*
free(body);
} // if there are characteristic updates to notify client cNum } // if there are characteristic updates to notify client cNum
} // if client exists } // if client exists
@ -1431,9 +1425,8 @@ void HAPClient::tlvRespond(){
uint8_t tlvData[nBytes]; // create buffer uint8_t tlvData[nBytes]; // create buffer
tlv8.pack(tlvData); // pack TLV records into buffer tlv8.pack(tlvData); // pack TLV records into buffer
int nChars=snprintf(NULL,0,"HTTP/1.1 200 OK\r\nContent-Type: application/pairing+tlv8\r\nContent-Length: %d\r\n\r\n",nBytes); // create Body with Content Length = size of TLV data char *body;
char body[nChars+1]; asprintf(&body,"HTTP/1.1 200 OK\r\nContent-Type: application/pairing+tlv8\r\nContent-Length: %d\r\n\r\n",nBytes); // create Body with Content Length = size of TLV data
sprintf(body,"HTTP/1.1 200 OK\r\nContent-Type: application/pairing+tlv8\r\nContent-Length: %d\r\n\r\n",nBytes);
LOG2("\n>>>>>>>>>> "); LOG2("\n>>>>>>>>>> ");
LOG2(client.remoteIP()); LOG2(client.remoteIP());
@ -1449,6 +1442,8 @@ void HAPClient::tlvRespond(){
sendEncrypted(body,tlvData,nBytes); sendEncrypted(body,tlvData,nBytes);
} }
free(body);
} // tlvRespond } // tlvRespond
////////////////////////////////////// //////////////////////////////////////

View File

@ -429,31 +429,26 @@ void Span::checkConnect(){
memcpy(id,HAPClient::accessory.ID,17); // copy ID bytes memcpy(id,HAPClient::accessory.ID,17); // copy ID bytes
id[17]='\0'; // add terminating null id[17]='\0'; // add terminating null
// create broadcaset name from server base name plus accessory ID (without ':') // create broadcast name from server base name plus accessory ID (without ':')
int nChars; char *hostName;
if(!hostNameSuffix)
nChars=snprintf(NULL,0,"%s-%.2s%.2s%.2s%.2s%.2s%.2s",hostNameBase,id,id+3,id+6,id+9,id+12,id+15);
else
nChars=snprintf(NULL,0,"%s%s",hostNameBase,hostNameSuffix);
char hostName[nChars+1];
if(!hostNameSuffix) if(!hostNameSuffix)
sprintf(hostName,"%s-%.2s%.2s%.2s%.2s%.2s%.2s",hostNameBase,id,id+3,id+6,id+9,id+12,id+15); asprintf(&hostName,"%s-%.2s%.2s%.2s%.2s%.2s%.2s",hostNameBase,id,id+3,id+6,id+9,id+12,id+15);
else else
sprintf(hostName,"%s%s",hostNameBase,hostNameSuffix); asprintf(&hostName,"%s%s",hostNameBase,hostNameSuffix);
char d[strlen(hostName)+1]; char *d;
sscanf(hostName,"%[A-Za-z0-9-]",d); sscanf(hostName,"%m[A-Za-z0-9-]",&d);
if(strlen(hostName)>255|| hostName[0]=='-' || hostName[strlen(hostName)-1]=='-' || strlen(hostName)!=strlen(d)){ if(strlen(hostName)>255 || hostName[0]=='-' || hostName[strlen(hostName)-1]=='-' || strlen(hostName)!=strlen(d)){
LOG0("\n*** Error: Can't start MDNS due to invalid hostname '%s'.\n",hostName); LOG0("\n*** Error: Can't start MDNS due to invalid hostname '%s'.\n",hostName);
LOG0("*** Hostname must consist of 255 or less alphanumeric characters or a hyphen, except that the hyphen cannot be the first or last character.\n"); LOG0("*** Hostname must consist of 255 or less alphanumeric characters or a hyphen, except that the hyphen cannot be the first or last character.\n");
LOG0("*** PROGRAM HALTED!\n\n"); LOG0("*** PROGRAM HALTED!\n\n");
while(1); while(1);
} }
free(d);
LOG0("\nStarting MDNS...\n\n"); LOG0("\nStarting MDNS...\n\n");
LOG0("HostName: %s.local:%d\n",hostName,tcpPortNum); LOG0("HostName: %s.local:%d\n",hostName,tcpPortNum);
@ -534,6 +529,8 @@ void Span::checkConnect(){
if(wifiCallback) if(wifiCallback)
wifiCallback(); wifiCallback();
free(hostName);
} // initWiFi } // initWiFi

View File

@ -202,7 +202,6 @@ class Span{
const char *displayName; // display name for this device - broadcast as part of Bonjour MDNS const char *displayName; // display name for this device - broadcast as part of Bonjour MDNS
const char *hostNameBase; // base of hostName of this device - full host name broadcast by Bonjour MDNS will have 6-byte accessoryID as well as '.local' automatically appended const char *hostNameBase; // base of hostName of this device - full host name broadcast by Bonjour MDNS will have 6-byte accessoryID as well as '.local' automatically appended
const char *hostNameSuffix=NULL; // optional "suffix" of hostName of this device. If specified, will be used as the hostName suffix instead of the 6-byte accessoryID const char *hostNameSuffix=NULL; // optional "suffix" of hostName of this device. If specified, will be used as the hostName suffix instead of the 6-byte accessoryID
char *hostName; // full host name of this device - constructed from hostNameBase and 6-byte AccessoryID
const char *modelName; // model name of this device - broadcast as Bonjour field "md" const char *modelName; // model name of this device - broadcast as Bonjour field "md"
char category[3]=""; // category ID of primary accessory - broadcast as Bonjour field "ci" (HAP Section 13) char category[3]=""; // category ID of primary accessory - broadcast as Bonjour field "ci" (HAP Section 13)
unsigned long snapTime; // current time (in millis) snapped before entering Service loops() or updates() unsigned long snapTime; // current time (in millis) snapped before entering Service loops() or updates()

View File

@ -51,10 +51,13 @@ void setup() {
Serial.begin(115200); Serial.begin(115200);
homeSpan.setControlPin(21); // homeSpan.setHostNameSuffix("");
// homeSpan.setControlPin(21);
homeSpan.setLogLevel(2) homeSpan.setLogLevel(2);
.setStatusPin(13);
// .setStatusPin(13);
// homeSpan.setSerialInputDisable(true); // homeSpan.setSerialInputDisable(true);
// homeSpan.enableOTA(); // homeSpan.enableOTA();