Updated getTLV() so it uses a fixed buffer as intermediate step
This is much more memory efficient. Instead of decoding entire STRING from base64 to a temporary buffer or potentially very large size and then unpacking into TLV object, we decode a maximum of 48 characters at a time and unpack the resulting 36 (max) bytes until entire STRING is consumed. getTLV() returns pack_size of final TLV, unless there is a problem with conversion, in which cae TLV is wiped and return value=0
This commit is contained in:
parent
eb821f002f
commit
f137b0bee5
|
|
@ -735,23 +735,39 @@ class SpanCharacteristic{
|
||||||
setValFinish(notify);
|
setValFinish(notify);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
size_t getTLV(TLV8 &tlv){
|
size_t getTLV(TLV8 &tlv){
|
||||||
|
|
||||||
if(format<FORMAT::TLV_ENC)
|
if(format<FORMAT::TLV_ENC)
|
||||||
return(0);
|
return(0);
|
||||||
|
|
||||||
|
const size_t bufSize=36; // maximum size of buffer to store decoded bytes before unpacking into TLV; must be multiple of 3
|
||||||
|
TempBuffer<uint8_t> tBuf(bufSize); // create fixed-size buffer to store decoded bytes
|
||||||
|
tlv.wipe(); // clear TLV completely
|
||||||
|
|
||||||
|
size_t nChars=strlen(value.STRING); // total characters to decode
|
||||||
|
uint8_t *p=(uint8_t *)value.STRING; // set pointer to beginning of value
|
||||||
|
const size_t decodeSize=bufSize/3*4; // number of characters to decode in each pass
|
||||||
|
int status=0;
|
||||||
|
|
||||||
|
while(nChars>0){
|
||||||
size_t olen;
|
size_t olen;
|
||||||
mbedtls_base64_decode(NULL,0,&olen,(uint8_t *)value.STRING,strlen(value.STRING)); // get length of buffer needed to decode
|
size_t n=nChars<decodeSize?nChars:decodeSize;
|
||||||
TempBuffer<uint8_t> tBuf(olen); // create temporary buffer
|
|
||||||
|
|
||||||
int ret=mbedtls_base64_decode(tBuf,olen,&olen,(uint8_t *)value.STRING,strlen(value.STRING));
|
|
||||||
|
|
||||||
|
int ret=mbedtls_base64_decode(tBuf,tBuf.len(),&olen,p,n);
|
||||||
if(ret==MBEDTLS_ERR_BASE64_INVALID_CHARACTER){
|
if(ret==MBEDTLS_ERR_BASE64_INVALID_CHARACTER){
|
||||||
LOG0("\n*** WARNING: Can't decode Characteristic::%s with getTLV(). Data is not in base-64 format\n\n",hapName);
|
LOG0("\n*** WARNING: Can't decode Characteristic::%s with getTLV(). Data is not in base-64 format\n\n",hapName);
|
||||||
|
tlv.wipe();
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
status=tlv.unpack(tBuf,olen);
|
||||||
|
p+=n;
|
||||||
|
nChars-=n;
|
||||||
|
}
|
||||||
|
if(status>0){
|
||||||
|
LOG0("\n*** WARNING: Can't unpack Characteristic::%s with getTLV(). TLV record is incomplete or corrupted\n\n",hapName);
|
||||||
|
tlv.wipe();
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
tlv.unpack(tBuf,olen);
|
|
||||||
return(tlv.pack_size());
|
return(tlv.pack_size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
13
src/TLV8.cpp
13
src/TLV8.cpp
|
|
@ -160,7 +160,10 @@ size_t TLV8::pack(uint8_t *buf, size_t bufSize){
|
||||||
|
|
||||||
/////////////////////////////////////
|
/////////////////////////////////////
|
||||||
|
|
||||||
void TLV8::unpack(uint8_t *buf, size_t bufSize){
|
int TLV8::unpack(uint8_t *buf, size_t bufSize){
|
||||||
|
|
||||||
|
if(bufSize==0)
|
||||||
|
return(-1);
|
||||||
|
|
||||||
if(empty())
|
if(empty())
|
||||||
unpackPhase=0;
|
unpackPhase=0;
|
||||||
|
|
@ -171,18 +174,17 @@ void TLV8::unpack(uint8_t *buf, size_t bufSize){
|
||||||
case 0:
|
case 0:
|
||||||
unpackTag=*buf++;
|
unpackTag=*buf++;
|
||||||
bufSize--;
|
bufSize--;
|
||||||
|
add(unpackTag);
|
||||||
unpackPhase=1;
|
unpackPhase=1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 1:
|
case 1:
|
||||||
unpackBytes=*buf++;
|
unpackBytes=*buf++;
|
||||||
bufSize--;
|
bufSize--;
|
||||||
if(unpackBytes==0){
|
if(unpackBytes==0)
|
||||||
add(unpackTag);
|
|
||||||
unpackPhase=0;
|
unpackPhase=0;
|
||||||
} else {
|
else
|
||||||
unpackPhase=2;
|
unpackPhase=2;
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
|
|
@ -196,6 +198,7 @@ void TLV8::unpack(uint8_t *buf, size_t bufSize){
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return(unpackPhase);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -107,7 +107,7 @@ class TLV8 : public std::list<tlv8_t, Mallocator<tlv8_t>> {
|
||||||
void osprint(std::ostream& os, TLV8_it it1){osprint(os, it1, it1++);}
|
void osprint(std::ostream& os, TLV8_it it1){osprint(os, it1, it1++);}
|
||||||
void osprint(std::ostream& os){osprint(os, begin(), end());}
|
void osprint(std::ostream& os){osprint(os, begin(), end());}
|
||||||
|
|
||||||
void unpack(uint8_t *buf, size_t bufSize);
|
int unpack(uint8_t *buf, size_t bufSize);
|
||||||
|
|
||||||
void wipe(){std::list<tlv8_t, Mallocator<tlv8_t>>().swap(*this);}
|
void wipe(){std::list<tlv8_t, Mallocator<tlv8_t>>().swap(*this);}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -123,7 +123,6 @@ struct HomeSpanTV : Service::Television {
|
||||||
|
|
||||||
TLV8 orderTLV;
|
TLV8 orderTLV;
|
||||||
|
|
||||||
Serial.printf("BEFORE:\n");
|
|
||||||
hsTV->displayOrder->getTLV(orderTLV);
|
hsTV->displayOrder->getTLV(orderTLV);
|
||||||
orderTLV.print();
|
orderTLV.print();
|
||||||
orderTLV.wipe();
|
orderTLV.wipe();
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue