Reputation: 11452
I have the following code that iterates a Buffer looking for a packet end marker. There could be several packets within this Buffer object so I am using the packet markers to find the data, process it and then move onto the next one by slicing the buffer. I am however missing packets as my condition on the for loop is buffer.length and the buffer length is changing (getting shorter) but the i value is always increasing! Any thoughts on how I can tackle this?
The bufferFragment is to capture partial packets and attach them to the beginning of the next packet. This part works.
for (var i = 0; i < buffer.length; i++)
{
if (buffer[i] == 16 && buffer[i + 1] == 3)
{
dataPacket = buffer.slice(0,i+4);
parseData(dataPacket);
buffer = buffer.slice(i+4);
}
else
{
bufferFragment = buffer;
}
}
UPDATE
It seems that in certain situations when the loop is longer that is get greedy and captures more data than it should.
Here is a full test script (http://runnable.com/U75ce4esNHFj7028)
var testBufferText = "100207b097a5085da120f30000461003e39410020736e7bb085d4952890000011003a9401002070c8a1f094ca120f394743e10038907100207a41c22095d4008de0000011003437e1002058e535109a0000a1a9b580000000000a963bf10035c45100207d49681095d4952890000011003827b10020b012447505654472c2c542c2c4d2c302e3130392c4e2c302e3230312c4b2c412a32380d0a10032a621002073e36c3095da120f300004610036e461002072297e7095d49528900000110038c5f1002017866350a8d40622d588135b07db35d000000100305ce1002070c673c0a5da120f30000461003fc331002071c21950a0d5aa29a00fc711003165e10";
var testBuffer = new Buffer(testBufferText,'hex');
var bufferFragment;
extractPackets(testBuffer);
function extractPackets(data)
{
var buffer = new Buffer(data);
var origBuffer = buffer;
var findCount = 0;
var startFlag = false;
var shortenedFlag = 0;
var appendedData = false;
if (bufferFragment)
{
buffer = Buffer.concat([bufferFragment, buffer]);
concatBuffer = new Buffer(buffer.length);
buffer.copy(concatBuffer);
appendedData = bufferFragment;
bufferFragment = undefined;
}
for (var i = 0; i < buffer.length; i++) {
if (buffer[i] == 16 && buffer[i + 1] == 16)
{
shortenedFlag += 1;
buffer = Buffer.concat([buffer.slice(0, i), buffer.slice(i + 1)]);
}
}
for (var i = 0; i < buffer.length; i++) {
//Look for a DLE Packet
if (buffer[i] == 16)
{
if (buffer[i + 1] != 16 && buffer[i + 1] != 3)
{
startFlag = true;
break;
}
}
else
{
buffer = buffer.slice(i + 1);
}
}
var sameAsTempBuffer = new Buffer(buffer.length);
buffer.copy(sameAsTempBuffer);
// if we detected a start, look for end of packet 10 03
if(startFlag == true)
{
for (var i = 0; i < buffer.length; i++)
{
if (buffer[i] == 16 && buffer[i + 1] == 3)
{
var dataPacket = buffer.slice(0,i+4);
buffer = buffer.slice(i+4);
i -= 4;
console.log("Data Packet to Process",dataPacket);
}
}
}
if (buffer.length)
{
bufferFragment = buffer;
}
return;
}
And the output is
Data Packet to Process <Buffer 10 02 07 b0 97 a5 08 5d a1 20 f3 00 00 46 10 03 e3 94>
Data Packet to Process <Buffer 10 02 07 36 e7 bb 08 5d 49 52 89 00 00 01 10 03 a9 40>
Data Packet to Process <Buffer 10 02 07 0c 8a 1f 09 4c a1 20 f3 94 74 3e 10 03 89 07>
Data Packet to Process <Buffer 10 02 07 a4 1c 22 09 5d 40 08 de 00 00 01 10 03 43 7e>
Data Packet to Process <Buffer 10 02 05 8e 53 51 09 a0 00 0a 1a 9b 58 00 00 00 00 00 a9 63 bf 10 03 5c 45>
Data Packet to Process <Buffer 10 02 07 d4 96 81 09 5d 49 52 89 00 00 01 10 03 82 7b 10 02 0b 01 24 47 50 56 54 47 2c 2c 54 2c 2c 4d 2c 30 2e 31 30 39 2c 4e 2c 30 2e 32 30 31 2c 4b 2c ...>
Data Packet to Process <Buffer 10 02 07 3e 36 c3 09 5d a1 20 f3 00 00 46 10 03 6e 46 10 02 07 22 97 e7 09 5d 49 52 89 00 00 01 10 03 8c 5f 10 02 01 78 66 35 0a 8d 40 62 2d 58 81 35 b0 ...>
The first 5 are ok and then the loop gets greedy and tries to capture more packets!
Upvotes: 2
Views: 1282
Reputation: 11452
Actually found the answer! The key was adding i to the offset!
var testBufferText = "100207b097a5085da120f30000461003e39410020736e7bb085d4952890000011003a9401002070c8a1f094ca120f394743e10038907100207a41c22095d4008de0000011003437e1002058e535109a0000a1a9b580000000000a963bf10035c45100207d49681095d4952890000011003827b10020b012447505654472c2c542c2c4d2c302e3130392c4e2c302e3230312c4b2c412a32380d0a10032a621002073e36c3095da120f300004610036e461002072297e7095d49528900000110038c5f1002017866350a8d40622d588135b07db35d000000100305ce1002070c673c0a5da120f30000461003fc331002071c21950a0d5aa29a00fc711003165e10";
var testBuffer = new Buffer(testBufferText,'hex');
var bufferFragment;
extractPackets(testBuffer);
function extractPackets(data)
{
var buffer = new Buffer(data);
var origBuffer = buffer;
var findCount = 0;
var startFlag = false;
var shortenedFlag = 0;
var appendedData = false;
if (bufferFragment)
{
buffer = Buffer.concat([bufferFragment, buffer]);
concatBuffer = new Buffer(buffer.length);
buffer.copy(concatBuffer);
appendedData = bufferFragment;
bufferFragment = undefined;
}
for (var i = 0; i < buffer.length; i++) {
if (buffer[i] == 16 && buffer[i + 1] == 16)
{
shortenedFlag += 1;
buffer = Buffer.concat([buffer.slice(0, i), buffer.slice(i + 1)]);
}
}
for (var i = 0; i < buffer.length; i++) {
//Look for a DLE Packet
if (buffer[i] == 16)
{
if (buffer[i + 1] != 16 && buffer[i + 1] != 3)
{
startFlag = true;
break;
}
}
else
{
buffer = buffer.slice(i + 1);
}
}
var sameAsTempBuffer = new Buffer(buffer.length);
buffer.copy(sameAsTempBuffer);
// if we detected a start, look for end of packet 10 03
if(startFlag == true)
{
for (var i = 0; i < buffer.length; i++)
{
if (buffer[i] == 16 && buffer[i + 1] == 3)
{
var dataPacket = buffer.slice(0,i+4);
buffer = buffer.slice(i+4);
i -= i + 4;
console.log("Data Packet to Process",dataPacket);
}
}
}
if (buffer.length)
{
bufferFragment = buffer;
}
return;
}
Upvotes: 2