Nodejs - use javascript to calculate the date of two 32-bit words

0

I'm writing parser which parses a pcapng file (A wire shark pcap next generation file). While there are solutions out there for this, I could not find one that existed within the NPM ecosystem. So I decided to spin my own. This works well so far and I can successfully decipher all the different blocks.

Currently using Node 6.11.

I am struggling though with determining the timestamp of an enhanced packet block. Per the documentation, this is what comprises the EHP:

   0                   1                   2                   3
   0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +---------------------------------------------------------------+
 0 |                    Block Type = 0x00000006                    |
   +---------------------------------------------------------------+
 4 |                      Block Total Length                       |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 8 |                         Interface ID                          |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
12 |                        Timestamp (High)                       |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
16 |                        Timestamp (Low)                        |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
20 |                    Captured Packet Length                     |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
24 |                    Original Packet Length                     |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
28 /                                                               /
   /                          Packet Data                          /
   /              variable length, padded to 32 bits               /
   /                                                               /
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   /                                                               /
   /                      Options (variable)                       /
   /                                                               /
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                      Block Total Length                       |
   +---------------------------------------------------------------+

Timestamp (High) and Timestamp (Low): upper 32 bits and lower 32 bits of a 64-bit timestamp. The timestamp is a single 64-bit unsigned integer that represents the number of units of time that have elapsed since 1970-01-01 00:00:00 UTC. The length of a unit of time is specified by the 'if_tsresol' option (see Figure 10) of the Interface Description block referenced by this packet. Note that, unlike timestamps in the libpcap file format, timestamps in Enhanced Packet Blocks are not saved as two 32-bit values that represent the seconds and microseconds that have elapsed since 1970-01-01 00:00:00 UTC. Timestamps in Enhanced Packet Blocks are saved as two 32-bit words that represent the upper and lower 32 bits of a single 64-bit quantity.

So, how do I go about figuring out the timestamp here? Apparently this is comprised of two 32-bit words to create a 64 bit number. However javascript doesn't handle 64 bit ints.

I did try using node-int64, but have been unsuccessful with it. Has yielded results of infinity.

Here is the specific slice of buffer I'm using:

Uint8Array[8]
0:46
1:89
2:5
3:0
4:9
5:12
6:15
7:31

and it's hex representation...

timeBuffer.toString('hex')
"2e590500090c0f1f"

This buffer is actually the first four bytes of the Timestamp(high), and the bytes 4-8 would be the Timestamp(low).

Essentially I'm trying to determine the actual timestamp here. I can do so by passing in a number value to new Date(12345678789) for example. Just can't wrap my head around the way this is stored. How does someone take two, 32-bit words, and glue them together such that I can pull out the time since 1970?

javascript
node.js
parsing
buffer
asked on Stack Overflow Oct 11, 2017 by dvsoukup

1 Answer

0

Right, JS doesn't support 64-bit ints, but you can always use floats. The microseconds part won't be accurate due to rounding errors, but since you're after standard js dates, which only have milliseconds resolution, this shouldn't be a problem:

buf = Buffer.from("2e590500090c0f1f", 'hex')

h = buf.readUInt32LE(0);
l = buf.readUInt32LE(4);

t = h * 0x100000000 + l;

console.log(new Date(t / 1000)); // 2017-09-14T22:51:48.000Z

Your other solutions don't work probably because of the format being a bit confusing: the 64-bit number is stored big endian (highest part first), while its parts (32-bit words) are little endian.

answered on Stack Overflow Oct 11, 2017 by georg • edited Oct 11, 2017 by georg

User contributions licensed under CC BY-SA 3.0