Browse Source

Fixed capture-duration calculation error caused by an overflow in tv_usec

Stefan Schmidt 6 years ago
parent
commit
e58d6be34d

+ 5 - 5
code/Test/test_internalQueries.py

@@ -23,7 +23,7 @@ class UnitTestInternalQueries(unittest.TestCase):
                           ("Unrecognized packets", 10, "PDUs"), ("% Recognized packets", 99.49949949949949, "%"),
                           ("% Unrecognized packets", 0.5005005005005005, "%"),
                           ("Last unknown PDU", '1970-01-01 01:07:39.604899'),
-                          ('Capture duration', '385.429443359375', 'seconds'),
+                          ('Capture duration', '384.454345703125', 'seconds'),
                           ('Capture start', '\t1970-01-01 01:01:45.647675'),
                           ('Capture end', '\t1970-01-01 01:08:10.102034')])
 
@@ -31,7 +31,7 @@ class UnitTestInternalQueries(unittest.TestCase):
         self.assertEqual(controller.statistics.get_packet_count(), 1998)
 
     def test_get_capture_duration(self):
-        self.assertEqual(controller.statistics.get_capture_duration(), '385.429443359375')
+        self.assertEqual(controller.statistics.get_capture_duration(), '384.454345703125')
 
     def test_get_pcap_timestamp_start(self):
         self.assertEqual(controller.statistics.get_pcap_timestamp_start(), '1970-01-01 01:01:45.647675')
@@ -42,14 +42,14 @@ class UnitTestInternalQueries(unittest.TestCase):
     # FIXME: This seems to be the only testcase where float values differ slightly between macOS and Linux
     def test_get_general_file_statistics(self):
         file_stats = controller.statistics.get_general_file_statistics()
-        self.assertEqual(file_stats[0], ('Avg. packet rate', 5.183828353881836, 'packets/sec'))
+        self.assertEqual(file_stats[0], ('Avg. packet rate', 5.196976184844971, 'packets/sec'))
         self.assertEqual(file_stats[1], ('Avg. packet size', 0.0, 'kbytes'))
         self.assertEqual(file_stats[2], ('Avg. packets sent', 90.0, 'packets'))
         self.assertEqual(file_stats[3][0], 'Avg. bandwidth in')
-        self.assertAlmostEqual(file_stats[3][1], 0.6286947727203369, places=5)
+        self.assertAlmostEqual(file_stats[3][1], 0.6302894353866577, places=5)
         self.assertEqual(file_stats[3][2], 'kbit/s')
         self.assertEqual(file_stats[4][0], 'Avg. bandwidth out')
-        self.assertAlmostEqual(file_stats[4][1], 0.6286947727203369, places=5)
+        self.assertAlmostEqual(file_stats[4][1], 0.6302894353866577, places=5)
 
     # INTERNAL QUERY TESTS
     def test_get_ip_address_count(self):

+ 15 - 8
code_boost/src/cxx/statistics.cpp

@@ -620,13 +620,17 @@ bool statistics::getDoExtraTests() {
  */
 std::string statistics::getCaptureDurationTimestamp() const {
     // Calculate duration
-    time_t t = (timestamp_lastPacket.seconds() - timestamp_firstPacket.seconds());
-    time_t ms = (timestamp_lastPacket.microseconds() - timestamp_firstPacket.microseconds());
-    long int hour = t / 3600;
-    long int remainder = (t - hour * 3600);
+    timeval fp, lp, d;
+    fp.tv_sec = timestamp_firstPacket.seconds();
+    fp.tv_usec = timestamp_firstPacket.microseconds();
+    lp.tv_sec = timestamp_lastPacket.seconds();
+    lp.tv_usec = timestamp_lastPacket.microseconds();
+    timersub(&lp, &fp, &d);
+    long int hour = d.tv_sec / 3600;
+    long int remainder = (d.tv_sec - hour * 3600);
     long int minute = remainder / 60;
     long int second = (remainder - minute * 60) % 60;
-    long int microseconds = ms;
+    long int microseconds = d.tv_usec;
     // Build desired output format: YYYY-mm-dd hh:mm:ss
     char out[64];
     sprintf(out, "%02ld:%02ld:%02ld.%06ld ", hour, minute, second, microseconds);
@@ -639,9 +643,12 @@ std::string statistics::getCaptureDurationTimestamp() const {
  * S: seconds (UNIX time), mmmmmm: microseconds
  */
 float statistics::getCaptureDurationSeconds() const {
-    timeval d;
-    d.tv_sec = timestamp_lastPacket.seconds() - timestamp_firstPacket.seconds();
-    d.tv_usec = timestamp_lastPacket.microseconds() - timestamp_firstPacket.microseconds();
+    timeval fp, lp, d;
+    fp.tv_sec = timestamp_firstPacket.seconds();
+    fp.tv_usec = timestamp_firstPacket.microseconds();
+    lp.tv_sec = timestamp_lastPacket.seconds();
+    lp.tv_usec = timestamp_lastPacket.microseconds();
+    timersub(&lp, &fp, &d);
     char buf[64];
     snprintf(buf, sizeof(buf), "%u.%06u", static_cast<uint>(d.tv_sec), static_cast<uint>(d.tv_usec));
     return std::stof(std::string(buf));

+ 1 - 1
code_boost/src/cxx/statistics_db.h

@@ -22,7 +22,7 @@ public:
     /*
      * Database version: Increment number on every change in the C++ code!
      */
-    static const int DB_VERSION = 10;
+    static const int DB_VERSION = 11;
 
     /*
      * Methods for writing values into database