bug 872: ns3::PcapFileWrapper::Write explodes stack
This commit is contained in:
@@ -219,7 +219,7 @@ main (int argc, char *argv[])
|
||||
ns3TcpSocket->TraceConnectWithoutContext ("CongestionWindow", MakeBoundCallback (&CwndChange, stream));
|
||||
|
||||
PcapHelper pcapHelper;
|
||||
Ptr<PcapFileWrapper> file = pcapHelper.CreateFile ("sixth.pcap", "w", PcapHelper::DLT_PPP);
|
||||
Ptr<PcapFileWrapper> file = pcapHelper.CreateFile ("sixth.pcap", std::ios::out, PcapHelper::DLT_PPP);
|
||||
devices.Get (1)->TraceConnectWithoutContext("PhyRxDrop", MakeBoundCallback (&RxDrop, file));
|
||||
|
||||
Simulator::Stop (Seconds(20));
|
||||
|
||||
@@ -31,19 +31,19 @@ using namespace ns3;
|
||||
// Some utility functions for the tests.
|
||||
// ===========================================================================
|
||||
|
||||
uint16_t
|
||||
static uint16_t
|
||||
Swap (uint16_t val)
|
||||
{
|
||||
return ((val >> 8) & 0x00ff) | ((val << 8) & 0xff00);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
static uint32_t
|
||||
Swap (uint32_t val)
|
||||
{
|
||||
return ((val >> 24) & 0x000000ff) | ((val >> 8) & 0x0000ff00) | ((val << 8) & 0x00ff0000) | ((val << 24) & 0xff000000);
|
||||
}
|
||||
|
||||
bool
|
||||
static bool
|
||||
CheckFileExists (std::string filename)
|
||||
{
|
||||
FILE * p = fopen (filename.c_str (), "rb");
|
||||
@@ -57,7 +57,7 @@ CheckFileExists (std::string filename)
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
static bool
|
||||
CheckFileLength (std::string filename, uint64_t sizeExpected)
|
||||
{
|
||||
FILE * p = fopen (filename.c_str (), "rb");
|
||||
@@ -93,7 +93,7 @@ private:
|
||||
};
|
||||
|
||||
WriteModeCreateTestCase::WriteModeCreateTestCase ()
|
||||
: TestCase ("Check to see that PcapFile::Open with mode \"w\" works")
|
||||
: TestCase ("Check to see that PcapFile::Open with mode std::ios::out works")
|
||||
{
|
||||
}
|
||||
|
||||
@@ -125,25 +125,26 @@ WriteModeCreateTestCase::DoRun (void)
|
||||
// Opening a new file in write mode should result in an empty file of the
|
||||
// given name.
|
||||
//
|
||||
bool err = f.Open (m_testFilename, "w");
|
||||
f.Open (m_testFilename, std::ios::out);
|
||||
|
||||
NS_TEST_ASSERT_MSG_EQ (err, false, "Open (" << m_testFilename << ", \"w\") returns error");
|
||||
NS_TEST_ASSERT_MSG_EQ (f.Fail (), false, "Open (" << m_testFilename << ", \"w\") returns error");
|
||||
f.Close ();
|
||||
|
||||
NS_TEST_ASSERT_MSG_EQ (CheckFileExists (m_testFilename), true,
|
||||
"Open (" << m_testFilename << ", \"w\") does not create file");
|
||||
"Open (" << m_testFilename << ", \"std::ios::out\") does not create file");
|
||||
NS_TEST_ASSERT_MSG_EQ (CheckFileLength (m_testFilename, 0), true,
|
||||
"Open (" << m_testFilename << ", \"w\") does not result in an empty file");
|
||||
"Open (" << m_testFilename << ", \"std::ios::out\") does not result in an empty file");
|
||||
|
||||
//
|
||||
// Calling Init() on a file created with "w" should result in a file just
|
||||
// Calling Init() on a file created with "std::ios::out" should result in a file just
|
||||
// long enough to contain the pcap file header.
|
||||
//
|
||||
err = f.Open (m_testFilename, "w");
|
||||
NS_TEST_ASSERT_MSG_EQ (err, false, "Open (" << m_testFilename << ", \"w\") returns error");
|
||||
f.Open (m_testFilename, std::ios::out);
|
||||
NS_TEST_ASSERT_MSG_EQ (f.Fail (), false, "Open (" << m_testFilename <<
|
||||
", \"std::ios::out\") returns error");
|
||||
|
||||
err = f.Init (1234, 5678, 7);
|
||||
NS_TEST_ASSERT_MSG_EQ (err, false, "Init (1234, 5678, 7) returns error");
|
||||
f.Init (1234, 5678, 7);
|
||||
NS_TEST_ASSERT_MSG_EQ (f.Fail (), false, "Init (1234, 5678, 7) returns error");
|
||||
|
||||
f.Close ();
|
||||
|
||||
@@ -154,8 +155,9 @@ WriteModeCreateTestCase::DoRun (void)
|
||||
// Opening an existing file in write mode should result in that file being
|
||||
// emptied.
|
||||
//
|
||||
err = f.Open (m_testFilename, "w");
|
||||
NS_TEST_ASSERT_MSG_EQ (err, false, "Open (" << m_testFilename << ", \"w\") returns error");
|
||||
f.Open (m_testFilename, std::ios::out);
|
||||
NS_TEST_ASSERT_MSG_EQ (f.Fail (), false, "Open (" << m_testFilename <<
|
||||
", \"std::ios::out\") returns error");
|
||||
|
||||
f.Close ();
|
||||
|
||||
@@ -165,22 +167,23 @@ WriteModeCreateTestCase::DoRun (void)
|
||||
//
|
||||
// Initialize the file again.
|
||||
//
|
||||
err = f.Open (m_testFilename, "w");
|
||||
NS_TEST_ASSERT_MSG_EQ (err, false,
|
||||
f.Open (m_testFilename, std::ios::out);
|
||||
NS_TEST_ASSERT_MSG_EQ (f.Fail (), false,
|
||||
"Open (" << m_testFilename << ", \"w\") returns error");
|
||||
|
||||
err = f.Init (1234, 5678, 7);
|
||||
NS_TEST_ASSERT_MSG_EQ (err, false, "Init (1234, 5678, 7) returns error");
|
||||
f.Init (1234, 5678, 7);
|
||||
NS_TEST_ASSERT_MSG_EQ (f.Fail (), false, "Init (1234, 5678, 7) returns error");
|
||||
|
||||
//
|
||||
// Now we should be able to write to it since it was opened in "w" mode.
|
||||
// Now we should be able to write to it since it was opened in std::ios::out mode.
|
||||
// This is just a permissions check so we don't actually look at the
|
||||
// data.
|
||||
//
|
||||
uint8_t buffer[128];
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
err = f.Write (0, 0, buffer, 128);
|
||||
NS_TEST_ASSERT_MSG_EQ (err, false, "Write (write-only-file " << m_testFilename << ") returns error");
|
||||
f.Write (0, 0, buffer, 128);
|
||||
NS_TEST_ASSERT_MSG_EQ (f.Fail (), false, "Write (write-only-file " << m_testFilename <<
|
||||
") returns error");
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -204,7 +207,7 @@ private:
|
||||
};
|
||||
|
||||
ReadModeCreateTestCase::ReadModeCreateTestCase ()
|
||||
: TestCase ("Check to see that PcapFile::Open with mode \"r\" works")
|
||||
: TestCase ("Check to see that PcapFile::Open with mode \"std::ios::in\" works")
|
||||
{
|
||||
}
|
||||
|
||||
@@ -235,55 +238,64 @@ ReadModeCreateTestCase::DoRun (void)
|
||||
//
|
||||
// Opening a non-existing file in read mode should result in an error.
|
||||
//
|
||||
bool err = f.Open (m_testFilename, "r");
|
||||
NS_TEST_ASSERT_MSG_EQ (err, true, "Open (non-existing-filename " << m_testFilename << ", \"r\") does not return error");
|
||||
|
||||
NS_TEST_ASSERT_MSG_EQ (CheckFileExists (m_testFilename), false,
|
||||
"Open (" << m_testFilename << ", \"r\") unexpectedly created a file");
|
||||
f.Open (m_testFilename, std::ios::in);
|
||||
NS_TEST_ASSERT_MSG_EQ (f.Fail (), true, "Open (non-existing-filename " << m_testFilename <<
|
||||
", \"std::ios::in\") does not return error");
|
||||
f.Close ();
|
||||
f.Clear ();
|
||||
NS_TEST_ASSERT_MSG_EQ (CheckFileExists (m_testFilename), false, "Open (" << m_testFilename <<
|
||||
", \"std::ios::in\") unexpectedly created a file");
|
||||
|
||||
//
|
||||
// Okay, now create an uninitialized file using previously tested operations
|
||||
//
|
||||
err = f.Open (m_testFilename, "w");
|
||||
NS_TEST_ASSERT_MSG_EQ (err, false, "Open (filename, \"w\") returns error");
|
||||
f.Open (m_testFilename, std::ios::out);
|
||||
NS_TEST_ASSERT_MSG_EQ (f.Fail (), false, "Open (filename, \"std::ios::out\") returns error");
|
||||
f.Close ();
|
||||
|
||||
//
|
||||
// Opening this file should result in an error since it has no pcap file header.
|
||||
//
|
||||
err = f.Open (m_testFilename, "r");
|
||||
NS_TEST_ASSERT_MSG_EQ (err, true, "Open (non-initialized-filename " << m_testFilename << ", \"r\") does not return error");
|
||||
f.Open (m_testFilename, std::ios::in);
|
||||
NS_TEST_ASSERT_MSG_EQ (f.Fail (), true, "Open (non-initialized-filename " << m_testFilename <<
|
||||
", \"std::ios::in\") does not return error");
|
||||
f.Close ();
|
||||
f.Clear ();
|
||||
|
||||
//
|
||||
// Okay, now open that non-initialized file in write mode and initialize it
|
||||
// Note that we open it in write mode to initialize it.
|
||||
//
|
||||
err = f.Open (m_testFilename, "w");
|
||||
NS_TEST_ASSERT_MSG_EQ (err, false, "Open (" << m_testFilename << ", \"w\") returns error");
|
||||
f.Open (m_testFilename, std::ios::out);
|
||||
NS_TEST_ASSERT_MSG_EQ (f.Fail (), false, "Open (" << m_testFilename <<
|
||||
", \"std::ios::out\") returns error");
|
||||
|
||||
err = f.Init (1234, 5678, 7);
|
||||
NS_TEST_ASSERT_MSG_EQ (err, false, "Init (1234, 5678, 7) returns error");
|
||||
f.Init (1234, 5678, 7);
|
||||
NS_TEST_ASSERT_MSG_EQ (f.Fail (), false, "Init (1234, 5678, 7) returns error");
|
||||
f.Close ();
|
||||
|
||||
//
|
||||
// Opening this file should now work since it has a pcap file header.
|
||||
//
|
||||
err = f.Open (m_testFilename, "r");
|
||||
NS_TEST_ASSERT_MSG_EQ (err, false, "Open (initialized-filename " << m_testFilename << ", \"r\") returns error");
|
||||
f.Open (m_testFilename, std::ios::in);
|
||||
NS_TEST_ASSERT_MSG_EQ (f.Fail (), false, "Open (initialized-filename " << m_testFilename <<
|
||||
", \"std::ios::in\") returns error");
|
||||
|
||||
//
|
||||
// Now we should not be able to write to it since it was opened in "r" mode
|
||||
// even if it has been initialized..
|
||||
//
|
||||
uint8_t buffer[128];
|
||||
err = f.Write (0, 0, buffer, 128);
|
||||
NS_TEST_ASSERT_MSG_EQ (err, true, "Write (read-only-file " << m_testFilename << ") does not return error");
|
||||
|
||||
f.Write (0, 0, buffer, 128);
|
||||
NS_TEST_ASSERT_MSG_EQ (f.Fail (), true, "Write (read-only-file " << m_testFilename <<
|
||||
") does not return error");
|
||||
f.Close ();
|
||||
f.Clear ();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#if 0
|
||||
// ===========================================================================
|
||||
// Test case to make sure that the Pcap File Object can open an existing pcap
|
||||
// file for appending.
|
||||
@@ -303,7 +315,7 @@ private:
|
||||
};
|
||||
|
||||
AppendModeCreateTestCase::AppendModeCreateTestCase ()
|
||||
: TestCase ("Check to see that PcapFile::Open with mode \"a\" works")
|
||||
: TestCase ("Check to see that PcapFile::Open with mode \"std::ios::app\" works")
|
||||
{
|
||||
}
|
||||
|
||||
@@ -334,54 +346,63 @@ AppendModeCreateTestCase::DoRun (void)
|
||||
//
|
||||
// Opening a non-existing file in append mode should result in an error.
|
||||
//
|
||||
bool err = f.Open (m_testFilename, "a");
|
||||
NS_TEST_ASSERT_MSG_EQ (err, true, "Open (non-existing-filename " << m_testFilename << ", \"a\") does not return error");
|
||||
f.Open (m_testFilename, std::ios::out | std::ios::app);
|
||||
NS_TEST_ASSERT_MSG_EQ (f.Fail (), true, "Open (non-existing-filename " << m_testFilename <<
|
||||
", \"std::ios::app\") does not return error");
|
||||
f.Close ();
|
||||
f.Clear ();
|
||||
|
||||
NS_TEST_ASSERT_MSG_EQ (CheckFileExists (m_testFilename), false,
|
||||
"Open (" << m_testFilename << ", \"a\") unexpectedly created a file");
|
||||
"Open (" << m_testFilename << ", \"std::ios::app\") unexpectedly created a file");
|
||||
|
||||
//
|
||||
// Okay, now create an uninitialized file using previously tested operations
|
||||
//
|
||||
err = f.Open (m_testFilename, "w");
|
||||
NS_TEST_ASSERT_MSG_EQ (err, false, "Open (" << m_testFilename << ", \"w\") returns error");
|
||||
f.Open (m_testFilename, std::ios::out);
|
||||
NS_TEST_ASSERT_MSG_EQ (f.Fail (), false, "Open (" << m_testFilename <<
|
||||
", \"std::ios::out\") returns error");
|
||||
f.Close ();
|
||||
|
||||
//
|
||||
// Opening this file should result in an error since it has no pcap file header.
|
||||
//
|
||||
err = f.Open (m_testFilename, "a");
|
||||
NS_TEST_ASSERT_MSG_EQ (err, true, "Open (non-initialized-filename " << m_testFilename << ", \"a\") does not return error");
|
||||
f.Open (m_testFilename, std::ios::out | std::ios::app);
|
||||
NS_TEST_ASSERT_MSG_EQ (f.Fail (), true, "Open (non-initialized-filename " << m_testFilename <<
|
||||
", \"std::ios::app\") does not return error");
|
||||
f.Close ();
|
||||
f.Clear ();
|
||||
|
||||
//
|
||||
// Okay, now open that non-initialized file in write mode and initialize it.
|
||||
//
|
||||
err = f.Open (m_testFilename, "w");
|
||||
NS_TEST_ASSERT_MSG_EQ (err, false, "Open (non-initialized-filename " << m_testFilename << ", \"w\") returns error");
|
||||
f.Open (m_testFilename, std::ios::out);
|
||||
NS_TEST_ASSERT_MSG_EQ (f.Fail (), false, "Open (non-initialized-filename " << m_testFilename <<
|
||||
", \"std::ios::out\") returns error");
|
||||
|
||||
err = f.Init (1234, 5678, 7);
|
||||
NS_TEST_ASSERT_MSG_EQ (err, false, "Init (1234, 5678, 7) returns error");
|
||||
f.Init (1234, 5678, 7);
|
||||
NS_TEST_ASSERT_MSG_EQ (f.Fail (), false, "Init (1234, 5678, 7) returns error");
|
||||
f.Close ();
|
||||
|
||||
//
|
||||
// Opening this file should now work since it has a pcap file header.
|
||||
//
|
||||
err = f.Open (m_testFilename, "a");
|
||||
NS_TEST_ASSERT_MSG_EQ (err, false, "Open (initialized-filename " << m_testFilename << ", \"r\") returns error");
|
||||
f.Open (m_testFilename, std::ios::out | std::ios::app);
|
||||
NS_TEST_ASSERT_MSG_EQ (f.Fail (), false, "Open (initialized-filename " << m_testFilename <<
|
||||
", \"std::ios::app\") returns error");
|
||||
|
||||
//
|
||||
// We should be able to write to it since it was opened in "a" mode.
|
||||
// We should be able to write to it since it was opened in "std::ios::app" mode.
|
||||
//
|
||||
uint8_t buffer[128];
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
err = f.Write (0, 0, buffer, 128);
|
||||
NS_TEST_ASSERT_MSG_EQ (err, false, "Write (append-mode-file " << m_testFilename << ") returns error");
|
||||
f.Write (0, 0, buffer, 128);
|
||||
NS_TEST_ASSERT_MSG_EQ (f.Fail (), false, "Write (append-mode-file " << m_testFilename << ") returns error");
|
||||
|
||||
f.Close ();
|
||||
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
// ===========================================================================
|
||||
// Test case to make sure that the Pcap File Object can write out correct pcap
|
||||
@@ -433,14 +454,15 @@ FileHeaderTestCase::DoRun (void)
|
||||
//
|
||||
// Create an uninitialized file using previously tested operations
|
||||
//
|
||||
bool err = f.Open (m_testFilename, "w");
|
||||
NS_TEST_ASSERT_MSG_EQ (err, false, "Open (" << m_testFilename << ", \"w\") returns error");
|
||||
|
||||
f.Open (m_testFilename, std::ios::out);
|
||||
NS_TEST_ASSERT_MSG_EQ (f.Fail (), false, "Open (" << m_testFilename <<
|
||||
", \"std::ios::out\") returns error");
|
||||
|
||||
//
|
||||
// Initialize the pcap file header.
|
||||
//
|
||||
err = f.Init (1234, 5678, 7);
|
||||
NS_TEST_ASSERT_MSG_EQ (err, false,
|
||||
f.Init (1234, 5678, 7);
|
||||
NS_TEST_ASSERT_MSG_EQ (f.Fail (), false,
|
||||
"Init (1234, 5678, 7) returns error");
|
||||
f.Close ();
|
||||
|
||||
@@ -525,8 +547,9 @@ FileHeaderTestCase::DoRun (void)
|
||||
// automagically fixed up when using a PcapFile to read the values, so we
|
||||
// don't have to do anything special here.
|
||||
//
|
||||
err = f.Open (m_testFilename, "r");
|
||||
NS_TEST_ASSERT_MSG_EQ (err, false, "Open (existing-initialized-file " << m_testFilename << ", \"r\") returns error");
|
||||
f.Open (m_testFilename, std::ios::in);
|
||||
NS_TEST_ASSERT_MSG_EQ (f.Fail (), false, "Open (existing-initialized-file " << m_testFilename <<
|
||||
", \"std::ios::in\") returns error");
|
||||
|
||||
NS_TEST_ASSERT_MSG_EQ (f.GetMagic (), 0xa1b2c3d4, "Read back magic number incorrectly");
|
||||
NS_TEST_ASSERT_MSG_EQ (f.GetVersionMajor (), 2, "Read back version major incorrectly");
|
||||
@@ -535,12 +558,14 @@ FileHeaderTestCase::DoRun (void)
|
||||
NS_TEST_ASSERT_MSG_EQ (f.GetSigFigs (), 0, "Read back sig figs incorrectly");
|
||||
NS_TEST_ASSERT_MSG_EQ (f.GetSnapLen (), 5678, "Read back snap len incorrectly");
|
||||
NS_TEST_ASSERT_MSG_EQ (f.GetDataLinkType (), 1234, "Read back data link type incorrectly");
|
||||
f.Close ();
|
||||
|
||||
//
|
||||
// Re-open the file to erase its contents.
|
||||
//
|
||||
err = f.Open (m_testFilename, "w");
|
||||
NS_TEST_ASSERT_MSG_EQ (err, false, "Open (" << m_testFilename << ", \"w\") returns error");
|
||||
f.Open (m_testFilename, std::ios::out);
|
||||
NS_TEST_ASSERT_MSG_EQ (f.Fail (), false, "Open (" << m_testFilename <<
|
||||
", \"std::ios::out\") returns error");
|
||||
|
||||
//
|
||||
// Initialize the pcap file header, turning on swap mode manually to force
|
||||
@@ -550,8 +575,8 @@ FileHeaderTestCase::DoRun (void)
|
||||
// a no-op and we're always writing foreign-endian files. In that case,
|
||||
// this test case is really just a duplicate of the previous.
|
||||
//
|
||||
err = f.Init (1234, 5678, 7, true);
|
||||
NS_TEST_ASSERT_MSG_EQ (err, false, "Init (1234, 5678, 7) returns error");
|
||||
f.Init (1234, 5678, 7, true);
|
||||
NS_TEST_ASSERT_MSG_EQ (f.Fail (), false, "Init (1234, 5678, 7) returns error");
|
||||
f.Close ();
|
||||
|
||||
//
|
||||
@@ -599,8 +624,9 @@ FileHeaderTestCase::DoRun (void)
|
||||
// machine is writing out a big-endian file by default, but we can't do that
|
||||
// since it breaks regression testing.
|
||||
//
|
||||
err = f.Open (m_testFilename, "r");
|
||||
NS_TEST_ASSERT_MSG_EQ (err, false, "Open (existing-initialized-file " << m_testFilename << ", \"r\") returns error");
|
||||
f.Open (m_testFilename, std::ios::in);
|
||||
NS_TEST_ASSERT_MSG_EQ (f.Fail (), false, "Open (existing-initialized-file " << m_testFilename <<
|
||||
", \"std::ios::in\") returns error");
|
||||
|
||||
NS_TEST_ASSERT_MSG_EQ (f.GetSwapMode (), true, "Byte-swapped file not correctly indicated");
|
||||
|
||||
@@ -667,14 +693,15 @@ RecordHeaderTestCase::DoRun (void)
|
||||
//
|
||||
// Create an uninitialized file using previously tested operations
|
||||
//
|
||||
bool err = f.Open (m_testFilename, "w");
|
||||
NS_TEST_ASSERT_MSG_EQ (err, false, "Open (" << m_testFilename << ", \"w\") returns error");
|
||||
f.Open (m_testFilename, std::ios::out);
|
||||
NS_TEST_ASSERT_MSG_EQ (f.Fail (), false, "Open (" << m_testFilename <<
|
||||
", \"std::ios::out\") returns error");
|
||||
|
||||
//
|
||||
// Initialize the pcap file header.
|
||||
//
|
||||
err = f.Init (37, 43, -7);
|
||||
NS_TEST_ASSERT_MSG_EQ (err, false, "Init (37, 43, -7) returns error");
|
||||
f.Init (37, 43, -7);
|
||||
NS_TEST_ASSERT_MSG_EQ (f.Fail (), false, "Init (37, 43, -7) returns error");
|
||||
|
||||
//
|
||||
// Initialize a buffer with a counting pattern to check the data later.
|
||||
@@ -690,8 +717,8 @@ RecordHeaderTestCase::DoRun (void)
|
||||
// mode. The packet data written should be limited to 43 bytes in length
|
||||
// by the Init() call above.
|
||||
//
|
||||
err = f.Write (1234, 5678, bufferOut, 128);
|
||||
NS_TEST_ASSERT_MSG_EQ (err, false, "Write (write-only-file " << m_testFilename << ") returns error");
|
||||
f.Write (1234, 5678, bufferOut, 128);
|
||||
NS_TEST_ASSERT_MSG_EQ (f.Fail (), false, "Write (write-only-file " << m_testFilename << ") returns error");
|
||||
f.Close ();
|
||||
|
||||
//
|
||||
@@ -785,18 +812,20 @@ RecordHeaderTestCase::DoRun (void)
|
||||
// Let's see if the PcapFile object can figure out how to do the same thing and
|
||||
// correctly read in a packet.
|
||||
//
|
||||
err = f.Open (m_testFilename, "r");
|
||||
NS_TEST_ASSERT_MSG_EQ (err, false, "Open (" << m_testFilename << ", \"r\") of existing good file returns error");
|
||||
f.Open (m_testFilename, std::ios::in);
|
||||
NS_TEST_ASSERT_MSG_EQ (f.Fail (), false, "Open (" << m_testFilename <<
|
||||
", \"std::ios::in\") of existing good file returns error");
|
||||
|
||||
uint32_t tsSec, tsUsec, inclLen, origLen, readLen;
|
||||
|
||||
err = f.Read (bufferIn, sizeof(bufferIn), tsSec, tsUsec, inclLen, origLen, readLen);
|
||||
NS_TEST_ASSERT_MSG_EQ (err, false, "Read() of known good packet returns error");
|
||||
f.Read (bufferIn, sizeof(bufferIn), tsSec, tsUsec, inclLen, origLen, readLen);
|
||||
NS_TEST_ASSERT_MSG_EQ (f.Fail (), false, "Read() of known good packet returns error");
|
||||
NS_TEST_ASSERT_MSG_EQ (tsSec, 1234, "Incorrectly read seconds timestap from known good packet");
|
||||
NS_TEST_ASSERT_MSG_EQ (tsUsec, 5678, "Incorrectly read microseconds timestap from known good packet");
|
||||
NS_TEST_ASSERT_MSG_EQ (inclLen, 43, "Incorrectly read included length from known good packet");
|
||||
NS_TEST_ASSERT_MSG_EQ (origLen, 128, "Incorrectly read original length from known good packet");
|
||||
NS_TEST_ASSERT_MSG_EQ (readLen, 43, "Incorrectly constructed actual read length from known good packet given buffer size");
|
||||
f.Close ();
|
||||
|
||||
//
|
||||
// Did the data come back correctly?
|
||||
@@ -815,22 +844,23 @@ RecordHeaderTestCase::DoRun (void)
|
||||
//
|
||||
// Open the file in write mode to clear the data.
|
||||
//
|
||||
err = f.Open (m_testFilename, "w");
|
||||
NS_TEST_ASSERT_MSG_EQ (err, false, "Open (" << m_testFilename << ", \"w\") returns error");
|
||||
f.Open (m_testFilename, std::ios::out);
|
||||
NS_TEST_ASSERT_MSG_EQ (f.Fail (), false, "Open (" << m_testFilename <<
|
||||
", \"std::ios::out\") returns error");
|
||||
|
||||
//
|
||||
// Initialize the pcap file header, forcing the object into swap mode.
|
||||
//
|
||||
err = f.Init (37, 43, -7, true);
|
||||
NS_TEST_ASSERT_MSG_EQ (err, false, "Init (37, 43, -7) returns error");
|
||||
f.Init (37, 43, -7, true);
|
||||
NS_TEST_ASSERT_MSG_EQ (f.Fail (), false, "Init (37, 43, -7) returns error");
|
||||
|
||||
//
|
||||
// Now we should be able to write a packet to it since it was opened in "w"
|
||||
// mode. The packet data written should be limited to 43 bytes in length
|
||||
// by the Init() call above.
|
||||
//
|
||||
err = f.Write (1234, 5678, bufferOut, 128);
|
||||
NS_TEST_ASSERT_MSG_EQ (err, false, "Write (write-only-file " << m_testFilename << ") returns error");
|
||||
f.Write (1234, 5678, bufferOut, 128);
|
||||
NS_TEST_ASSERT_MSG_EQ (f.Fail (), false, "Write (write-only-file " << m_testFilename << ") returns error");
|
||||
f.Close ();
|
||||
|
||||
//
|
||||
@@ -892,11 +922,12 @@ RecordHeaderTestCase::DoRun (void)
|
||||
// correctly read in a packet. The record header info should come back to us
|
||||
// swapped back into correct form.
|
||||
//
|
||||
err = f.Open (m_testFilename, "r");
|
||||
NS_TEST_ASSERT_MSG_EQ (err, false, "Open (" << m_testFilename << ", \"r\") of existing good file returns error");
|
||||
f.Open (m_testFilename, std::ios::in);
|
||||
NS_TEST_ASSERT_MSG_EQ (f.Fail (), false, "Open (" << m_testFilename <<
|
||||
", \"std::ios::in\") of existing good file returns error");
|
||||
|
||||
err = f.Read (bufferIn, sizeof(bufferIn), tsSec, tsUsec, inclLen, origLen, readLen);
|
||||
NS_TEST_ASSERT_MSG_EQ (err, false, "Read() of known good packet returns error");
|
||||
f.Read (bufferIn, sizeof(bufferIn), tsSec, tsUsec, inclLen, origLen, readLen);
|
||||
NS_TEST_ASSERT_MSG_EQ (f.Fail (), false, "Read() of known good packet returns error");
|
||||
NS_TEST_ASSERT_MSG_EQ (tsSec, 1234, "Incorrectly read seconds timestap from known good packet");
|
||||
NS_TEST_ASSERT_MSG_EQ (tsUsec, 5678, "Incorrectly read microseconds timestap from known good packet");
|
||||
NS_TEST_ASSERT_MSG_EQ (inclLen, 43, "Incorrectly read included length from known good packet");
|
||||
@@ -988,8 +1019,9 @@ ReadFileTestCase::DoRun (void)
|
||||
//
|
||||
//
|
||||
std::string filename = NS_TEST_SOURCEDIR + "known.pcap";
|
||||
bool err = f.Open (filename, "r");
|
||||
NS_TEST_ASSERT_MSG_EQ (err, false, "Open (" << filename << ", \"w\") returns error");
|
||||
f.Open (filename, std::ios::in);
|
||||
NS_TEST_ASSERT_MSG_EQ (f.Fail (), false, "Open (" << filename <<
|
||||
", \"std::ios::in\") returns error");
|
||||
|
||||
//
|
||||
// We are going to read out the file header and all of the packets to make
|
||||
@@ -1006,8 +1038,8 @@ ReadFileTestCase::DoRun (void)
|
||||
|
||||
for (uint32_t i = 0; i < N_KNOWN_PACKETS; ++i, ++p)
|
||||
{
|
||||
err = f.Read (data, sizeof(data), tsSec, tsUsec, inclLen, origLen, readLen);
|
||||
NS_TEST_ASSERT_MSG_EQ (err, false, "Read() of known good pcap file returns error");
|
||||
f.Read (data, sizeof(data), tsSec, tsUsec, inclLen, origLen, readLen);
|
||||
NS_TEST_ASSERT_MSG_EQ (f.Fail (), false, "Read() of known good pcap file returns error");
|
||||
NS_TEST_ASSERT_MSG_EQ (tsSec, p->tsSec, "Incorrectly read seconds timestap from known good pcap file");
|
||||
NS_TEST_ASSERT_MSG_EQ (tsUsec, p->tsUsec, "Incorrectly read microseconds timestap from known good pcap file");
|
||||
NS_TEST_ASSERT_MSG_EQ (inclLen, p->inclLen, "Incorrectly read included length from known good packet");
|
||||
@@ -1019,8 +1051,8 @@ ReadFileTestCase::DoRun (void)
|
||||
// The file should now be at EOF since we've read all of the packets.
|
||||
// Another packet read should return an error.
|
||||
//
|
||||
err = f.Read (data, 1, tsSec, tsUsec, inclLen, origLen, readLen);
|
||||
NS_TEST_ASSERT_MSG_EQ (err, true, "Read() of known good pcap file at EOF does not return error");
|
||||
f.Read (data, 1, tsSec, tsUsec, inclLen, origLen, readLen);
|
||||
NS_TEST_ASSERT_MSG_EQ (f.Eof (), true, "Read() of known good pcap file at EOF does not return error");
|
||||
|
||||
f.Close ();
|
||||
|
||||
@@ -1061,17 +1093,17 @@ DiffTestCase::DoRun (void)
|
||||
std::string filename2 = "different.pcap";
|
||||
PcapFile f;
|
||||
|
||||
bool err = f.Open (filename2, "w");
|
||||
NS_TEST_ASSERT_MSG_EQ (err, false, "Open (" << filename2 << ", \"w\") returns error");
|
||||
err = f.Init (1, N_PACKET_BYTES);
|
||||
NS_TEST_ASSERT_MSG_EQ (err, false, "Init (1, " << N_PACKET_BYTES << ") returns error");
|
||||
f.Open (filename2, std::ios::out);
|
||||
NS_TEST_ASSERT_MSG_EQ (f.Fail (), false, "Open (" << filename2 << ", \"std::ios::out\") returns error");
|
||||
f.Init (1, N_PACKET_BYTES);
|
||||
NS_TEST_ASSERT_MSG_EQ (f.Fail (), false, "Init (1, " << N_PACKET_BYTES << ") returns error");
|
||||
|
||||
for (uint32_t i = 0; i < N_KNOWN_PACKETS; ++i)
|
||||
{
|
||||
PacketEntry const & p = knownPackets[i];
|
||||
|
||||
err = f.Write (p.tsSec, p.tsUsec, (uint8_t const *)p.data, p.origLen);
|
||||
NS_TEST_EXPECT_MSG_EQ (err, false, "Write must not fail");
|
||||
f.Write (p.tsSec, p.tsUsec, (uint8_t const *)p.data, p.origLen);
|
||||
NS_TEST_EXPECT_MSG_EQ (f.Fail (), false, "Write must not fail");
|
||||
}
|
||||
f.Close ();
|
||||
|
||||
@@ -1094,7 +1126,7 @@ PcapFileTestSuite::PcapFileTestSuite ()
|
||||
{
|
||||
AddTestCase (new WriteModeCreateTestCase);
|
||||
AddTestCase (new ReadModeCreateTestCase);
|
||||
AddTestCase (new AppendModeCreateTestCase);
|
||||
//AddTestCase (new AppendModeCreateTestCase);
|
||||
AddTestCase (new FileHeaderTestCase);
|
||||
AddTestCase (new RecordHeaderTestCase);
|
||||
AddTestCase (new ReadFileTestCase);
|
||||
|
||||
@@ -54,19 +54,36 @@ PcapFileWrapper::~PcapFileWrapper ()
|
||||
Close ();
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
PcapFileWrapper::Fail (void) const
|
||||
{
|
||||
return m_file.Fail ();
|
||||
}
|
||||
bool
|
||||
PcapFileWrapper::Eof (void) const
|
||||
{
|
||||
return m_file.Eof ();
|
||||
}
|
||||
void
|
||||
PcapFileWrapper::Clear (void)
|
||||
{
|
||||
m_file.Clear ();
|
||||
}
|
||||
|
||||
void
|
||||
PcapFileWrapper::Close (void)
|
||||
{
|
||||
m_file.Close ();
|
||||
}
|
||||
|
||||
bool
|
||||
PcapFileWrapper::Open (std::string const &filename, std::string const &mode)
|
||||
void
|
||||
PcapFileWrapper::Open (std::string const &filename, std::ios::openmode mode)
|
||||
{
|
||||
return m_file.Open (filename, mode);
|
||||
m_file.Open (filename, mode);
|
||||
}
|
||||
|
||||
bool
|
||||
void
|
||||
PcapFileWrapper::Init (uint32_t dataLinkType, uint32_t snapLen, int32_t tzCorrection)
|
||||
{
|
||||
//
|
||||
@@ -76,66 +93,42 @@ PcapFileWrapper::Init (uint32_t dataLinkType, uint32_t snapLen, int32_t tzCorrec
|
||||
//
|
||||
if (snapLen != std::numeric_limits<uint32_t>::max ())
|
||||
{
|
||||
return m_file.Init (dataLinkType, snapLen, tzCorrection);
|
||||
m_file.Init (dataLinkType, snapLen, tzCorrection);
|
||||
}
|
||||
else
|
||||
{
|
||||
return m_file.Init (dataLinkType, m_snapLen, tzCorrection);
|
||||
m_file.Init (dataLinkType, m_snapLen, tzCorrection);
|
||||
}
|
||||
|
||||
//
|
||||
// Quiet the compiler
|
||||
//
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
void
|
||||
PcapFileWrapper::Write (Time t, Ptr<const Packet> p)
|
||||
{
|
||||
uint8_t buffer[PcapFile::SNAPLEN_DEFAULT];
|
||||
|
||||
uint64_t current = t.GetMicroSeconds ();
|
||||
uint64_t s = current / 1000000;
|
||||
uint64_t us = current % 1000000;
|
||||
|
||||
uint32_t bufferSize = p->GetSize ();
|
||||
p->CopyData (buffer, bufferSize);
|
||||
bool rc = m_file.Write (s, us, buffer, bufferSize);
|
||||
return rc;
|
||||
m_file.Write (s, us, p);
|
||||
}
|
||||
|
||||
bool
|
||||
void
|
||||
PcapFileWrapper::Write (Time t, Header &header, Ptr<const Packet> p)
|
||||
{
|
||||
uint8_t buffer[PcapFile::SNAPLEN_DEFAULT];
|
||||
|
||||
uint64_t current = t.GetMicroSeconds ();
|
||||
uint64_t s = current / 1000000;
|
||||
uint64_t us = current % 1000000;
|
||||
|
||||
Buffer headerBuffer;
|
||||
uint32_t headerSize = header.GetSerializedSize ();
|
||||
uint32_t packetSize = p->GetSize ();
|
||||
uint32_t bufferSize = headerSize + packetSize;
|
||||
|
||||
headerBuffer.AddAtStart (headerSize);
|
||||
header.Serialize (headerBuffer.Begin ());
|
||||
|
||||
headerBuffer.Begin ().Read (buffer, headerSize);
|
||||
p->CopyData (&buffer[headerSize], packetSize);
|
||||
bool rc = m_file.Write (s, us, buffer, bufferSize);
|
||||
|
||||
return rc;
|
||||
m_file.Write (s, us, header, p);
|
||||
}
|
||||
|
||||
bool
|
||||
void
|
||||
PcapFileWrapper::Write (Time t, uint8_t const *buffer, uint32_t length)
|
||||
{
|
||||
uint64_t current = t.GetMicroSeconds ();
|
||||
uint64_t s = current / 1000000;
|
||||
uint64_t us = current % 1000000;
|
||||
|
||||
return m_file.Write (s, us, buffer, length);
|
||||
m_file.Write (s, us, buffer, length);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
|
||||
#include <string.h>
|
||||
#include <limits>
|
||||
#include <fstream>
|
||||
#include "ns3/ptr.h"
|
||||
#include "ns3/packet.h"
|
||||
#include "ns3/nstime.h"
|
||||
@@ -42,64 +43,34 @@ public:
|
||||
PcapFileWrapper ();
|
||||
~PcapFileWrapper ();
|
||||
|
||||
|
||||
/**
|
||||
* Create a new pcap file wrapper representing a new or existing pcap file.
|
||||
* Semantics are similar to the C standard library function \c fopen
|
||||
*
|
||||
* Possible modes are:
|
||||
*
|
||||
* \verbatim
|
||||
* "r": Open a file for reading. The file must exist. The pcap header
|
||||
* is assumed to exist in the file and will be read and checked.
|
||||
* The file seek position indicator is set to point to the first
|
||||
* packet on exit.
|
||||
*
|
||||
* "w": Create an empty file for writing. If a file with the same name
|
||||
* already exists its content is erased and the file is treated as a
|
||||
* new empty pcap file. The file is assumed not to have a pcap
|
||||
* header and the caller is responsible for calling Init before saving
|
||||
* any packet data. The file seek position indicator is set to point
|
||||
* to the beginning of the file on exit since there will be no pcap
|
||||
* header.
|
||||
*
|
||||
* "a": Append to an existing file. This mode allows for adding packet data
|
||||
* to the end of an existing pcap file. The file must exist and have a
|
||||
* valid pcap header written (N.B. this is different from standard fopen
|
||||
* semantics). The file seek position indicator is set to point
|
||||
* to the end of the file on exit.
|
||||
*
|
||||
* "r+": Open a file for update -- both reading and writing. The file must
|
||||
* exist. The pcap header is assumed to have been written to the
|
||||
* file and will be read and checked. The file seek position indicator
|
||||
* is set to point to the first packet on exit.
|
||||
*
|
||||
* "w+": Create an empty file for both reading and writing. If a file with
|
||||
* the same name already exists, its content is erased and the file is
|
||||
* treated as a new empty pcap file. Since this new file will not have
|
||||
* a pcap header, the caller is responsible for calling Init before
|
||||
* saving any packet data. On exit, the file seek position indicator is
|
||||
* set to point to the beginning of the file.
|
||||
*
|
||||
* "a+" Open a file for reading and appending. The file must exist and have a
|
||||
* valid pcap header written (N.B. this is different from standard fopen
|
||||
* semantics). The file seek position indicator is set to point
|
||||
* to the end of the file on exit. Existing content is preserved.
|
||||
* \endverbatim
|
||||
* \return true if the 'fail' bit is set in the underlying iostream, false otherwise.
|
||||
*/
|
||||
bool Fail (void) const;
|
||||
/**
|
||||
* \return true if the 'eof' bit is set in the underlying iostream, false otherwise.
|
||||
*/
|
||||
bool Eof (void) const;
|
||||
/**
|
||||
* Clear all state bits of the underlying iostream.
|
||||
*/
|
||||
void Clear (void);
|
||||
|
||||
/**
|
||||
* Create a new pcap file or open an existing pcap file. Semantics are
|
||||
* similar to the stdc++ io stream classes.
|
||||
*
|
||||
* Since a pcap file is always a binary file, the file type is automatically
|
||||
* selected as a binary file. For example, providing a mode string "a+"
|
||||
* results in the underlying OS file being opened in "a+b" mode.
|
||||
* selected as a binary file (fstream::binary is automatically ored with the mode
|
||||
* field).
|
||||
*
|
||||
* \param filename String containing the name of the file.
|
||||
*
|
||||
* \param mode String containing the access mode for the file.
|
||||
*
|
||||
* \returns Error indication that should be interpreted as, "did an error
|
||||
* happen"? That is, the method returns false if the open succeeds, true
|
||||
* otherwise. The errno variable will be set by the OS to to provide a
|
||||
* more descriptive failure indication.
|
||||
*/
|
||||
bool Open (std::string const &filename, std::string const &mode);
|
||||
void Open (std::string const &filename, std::ios::openmode mode);
|
||||
|
||||
/**
|
||||
* Close the underlying pcap file.
|
||||
@@ -126,12 +97,10 @@ public:
|
||||
* time zone from UTC/GMT. For example, Pacific Standard Time in the US is
|
||||
* GMT-8, so one would enter -8 for that correction. Defaults to 0 (UTC).
|
||||
*
|
||||
* \return false if the open succeeds, true otherwise.
|
||||
*
|
||||
* \warning Calling this method on an existing file will result in the loss
|
||||
* any existing data.
|
||||
*/
|
||||
bool Init (uint32_t dataLinkType,
|
||||
void Init (uint32_t dataLinkType,
|
||||
uint32_t snapLen = std::numeric_limits<uint32_t>::max (),
|
||||
int32_t tzCorrection = PcapFile::ZONE_DEFAULT);
|
||||
|
||||
@@ -141,9 +110,8 @@ public:
|
||||
* \param t Packet timestamp as ns3::Time.
|
||||
* \param p Packet to write to the pcap file.
|
||||
*
|
||||
* \return true on error, false otherwise
|
||||
*/
|
||||
bool Write (Time t, Ptr<const Packet> p);
|
||||
void Write (Time t, Ptr<const Packet> p);
|
||||
|
||||
/**
|
||||
* \brief Write the provided header along with the packet to the pcap file.
|
||||
@@ -156,9 +124,8 @@ public:
|
||||
* \param header The Header to prepend to the packet.
|
||||
* \param p Packet to write to the pcap file.
|
||||
*
|
||||
* \return true on error, false otherwise
|
||||
*/
|
||||
bool Write (Time t, Header &header, Ptr<const Packet> p);
|
||||
void Write (Time t, Header &header, Ptr<const Packet> p);
|
||||
|
||||
/**
|
||||
* \brief Write the provided data buffer to the pcap file.
|
||||
@@ -167,9 +134,8 @@ public:
|
||||
* \param buffer The buffer to write.
|
||||
* \param length The size of the buffer.
|
||||
*
|
||||
* \return true on error, false otherwise
|
||||
*/
|
||||
bool Write (Time t, uint8_t const *buffer, uint32_t length);
|
||||
void Write (Time t, uint8_t const *buffer, uint32_t length);
|
||||
|
||||
/*
|
||||
* \brief Returns the magic number of the pcap file as defined by the magic_number
|
||||
|
||||
@@ -19,10 +19,12 @@
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <cstring>
|
||||
|
||||
#include "ns3/assert.h"
|
||||
#include "ns3/packet.h"
|
||||
#include "ns3/fatal-error.h"
|
||||
#include "ns3/header.h"
|
||||
#include "ns3/buffer.h"
|
||||
#include "pcap-file.h"
|
||||
//
|
||||
// This file is used as part of the ns-3 test framework, so please refrain from
|
||||
@@ -41,28 +43,37 @@ const uint16_t VERSION_MINOR = 4; /**< Minor version of supported pc
|
||||
const int32_t SIGFIGS_DEFAULT = 0; /**< Significant figures for timestamps (libpcap doesn't even bother) */
|
||||
|
||||
PcapFile::PcapFile ()
|
||||
: m_filename (""),
|
||||
m_filePtr (0),
|
||||
m_haveFileHeader (false),
|
||||
: m_file (),
|
||||
m_swapMode (false)
|
||||
{
|
||||
}
|
||||
{}
|
||||
|
||||
PcapFile::~PcapFile ()
|
||||
{
|
||||
Close ();
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
PcapFile::Fail (void) const
|
||||
{
|
||||
return m_file.fail ();
|
||||
}
|
||||
bool
|
||||
PcapFile::Eof (void) const
|
||||
{
|
||||
return m_file.eof ();
|
||||
}
|
||||
void
|
||||
PcapFile::Clear (void)
|
||||
{
|
||||
m_file.clear ();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PcapFile::Close (void)
|
||||
{
|
||||
if (m_filePtr)
|
||||
{
|
||||
fclose (m_filePtr);
|
||||
}
|
||||
m_filePtr = 0;
|
||||
m_filename = "";
|
||||
m_haveFileHeader = false;
|
||||
m_file.close ();
|
||||
}
|
||||
|
||||
uint32_t
|
||||
@@ -152,18 +163,14 @@ PcapFile::Swap (PcapRecordHeader *from, PcapRecordHeader *to)
|
||||
to->m_origLen = Swap (from->m_origLen);
|
||||
}
|
||||
|
||||
bool
|
||||
void
|
||||
PcapFile::WriteFileHeader (void)
|
||||
{
|
||||
//
|
||||
// If we're initializing the file, we need to write the pcap file header
|
||||
// at the start of the file.
|
||||
//
|
||||
int result = fseek (m_filePtr, 0, SEEK_SET);
|
||||
if (result)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
m_file.seekp (0, std::ios::beg);
|
||||
|
||||
//
|
||||
// We have the ability to write out the pcap file header in a foreign endian
|
||||
@@ -191,57 +198,34 @@ PcapFile::WriteFileHeader (void)
|
||||
// Watch out for memory alignment differences between machines, so write
|
||||
// them all individually.
|
||||
//
|
||||
result = 0;
|
||||
|
||||
result |= (fwrite (&headerOut->m_magicNumber, sizeof(headerOut->m_magicNumber), 1, m_filePtr) != 1);
|
||||
result |= (fwrite (&headerOut->m_versionMajor, sizeof(headerOut->m_versionMajor), 1, m_filePtr) != 1);
|
||||
result |= (fwrite (&headerOut->m_versionMinor, sizeof(headerOut->m_versionMinor), 1, m_filePtr) != 1);
|
||||
result |= (fwrite (&headerOut->m_zone, sizeof(headerOut->m_zone), 1, m_filePtr) != 1);
|
||||
result |= (fwrite (&headerOut->m_sigFigs, sizeof(headerOut->m_sigFigs), 1, m_filePtr) != 1);
|
||||
result |= (fwrite (&headerOut->m_snapLen, sizeof(headerOut->m_snapLen), 1, m_filePtr) != 1);
|
||||
result |= (fwrite (&headerOut->m_type, sizeof(headerOut->m_type), 1, m_filePtr) != 1);
|
||||
|
||||
//
|
||||
// If any of the fwrites above did not succeed in writinging the correct
|
||||
// number of objects, result will be nonzero and will indicate an error.
|
||||
//
|
||||
return result != 0;
|
||||
m_file.write ((const char *)&headerOut->m_magicNumber, sizeof(headerOut->m_magicNumber));
|
||||
m_file.write ((const char *)&headerOut->m_versionMajor, sizeof(headerOut->m_versionMajor));
|
||||
m_file.write ((const char *)&headerOut->m_versionMinor, sizeof(headerOut->m_versionMinor));
|
||||
m_file.write ((const char *)&headerOut->m_zone, sizeof(headerOut->m_zone));
|
||||
m_file.write ((const char *)&headerOut->m_sigFigs, sizeof(headerOut->m_sigFigs));
|
||||
m_file.write ((const char *)&headerOut->m_snapLen, sizeof(headerOut->m_snapLen));
|
||||
m_file.write ((const char *)&headerOut->m_type, sizeof(headerOut->m_type));
|
||||
}
|
||||
|
||||
bool
|
||||
void
|
||||
PcapFile::ReadAndVerifyFileHeader (void)
|
||||
{
|
||||
//
|
||||
// Pcap file header is always at the start of the file
|
||||
//
|
||||
int result = fseek (m_filePtr, 0, SEEK_SET);
|
||||
if (result)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
m_file.seekg (0, std::ios::beg);
|
||||
|
||||
//
|
||||
// Watch out for memory alignment differences between machines, so read
|
||||
// them all individually.
|
||||
//
|
||||
result = 0;
|
||||
|
||||
result |= (fread (&m_fileHeader.m_magicNumber, sizeof(m_fileHeader.m_magicNumber), 1, m_filePtr) != 1);
|
||||
result |= (fread (&m_fileHeader.m_versionMajor, sizeof(m_fileHeader.m_versionMajor), 1, m_filePtr) != 1);
|
||||
result |= (fread (&m_fileHeader.m_versionMinor, sizeof(m_fileHeader.m_versionMinor), 1, m_filePtr) != 1);
|
||||
result |= (fread (&m_fileHeader.m_zone, sizeof(m_fileHeader.m_zone), 1, m_filePtr) != 1);
|
||||
result |= (fread (&m_fileHeader.m_sigFigs, sizeof(m_fileHeader.m_sigFigs), 1, m_filePtr) != 1);
|
||||
result |= (fread (&m_fileHeader.m_snapLen, sizeof(m_fileHeader.m_snapLen), 1, m_filePtr) != 1);
|
||||
result |= (fread (&m_fileHeader.m_type, sizeof(m_fileHeader.m_type), 1, m_filePtr) != 1);
|
||||
|
||||
//
|
||||
// If any of the freads above did not succeed in reading the correct number of
|
||||
// objects, result will be nonzero.
|
||||
//
|
||||
if (result)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
m_file.read ((char *)&m_fileHeader.m_magicNumber, sizeof(m_fileHeader.m_magicNumber));
|
||||
m_file.read ((char *)&m_fileHeader.m_versionMajor, sizeof(m_fileHeader.m_versionMajor));
|
||||
m_file.read ((char *)&m_fileHeader.m_versionMinor, sizeof(m_fileHeader.m_versionMinor));
|
||||
m_file.read ((char *)&m_fileHeader.m_zone, sizeof(m_fileHeader.m_zone));
|
||||
m_file.read ((char *)&m_fileHeader.m_sigFigs, sizeof(m_fileHeader.m_sigFigs));
|
||||
m_file.read ((char *)&m_fileHeader.m_snapLen, sizeof(m_fileHeader.m_snapLen));
|
||||
m_file.read ((char *)&m_fileHeader.m_type, sizeof(m_fileHeader.m_type));
|
||||
|
||||
//
|
||||
// There are four possible magic numbers that can be there. Normal and byte
|
||||
@@ -251,14 +235,15 @@ PcapFile::ReadAndVerifyFileHeader (void)
|
||||
if (m_fileHeader.m_magicNumber != MAGIC && m_fileHeader.m_magicNumber != SWAPPED_MAGIC &&
|
||||
m_fileHeader.m_magicNumber != NS_MAGIC && m_fileHeader.m_magicNumber != NS_SWAPPED_MAGIC)
|
||||
{
|
||||
return true;
|
||||
m_file.setstate (std::ios::failbit);
|
||||
}
|
||||
|
||||
//
|
||||
// If the magic number is swapped, then we can assume that everything else we read
|
||||
// is swapped.
|
||||
//
|
||||
m_swapMode = (m_fileHeader.m_magicNumber == SWAPPED_MAGIC || m_fileHeader.m_magicNumber == NS_SWAPPED_MAGIC) ? true : false;
|
||||
m_swapMode = (m_fileHeader.m_magicNumber == SWAPPED_MAGIC
|
||||
|| m_fileHeader.m_magicNumber == NS_SWAPPED_MAGIC) ? true : false;
|
||||
|
||||
if (m_swapMode)
|
||||
{
|
||||
@@ -270,7 +255,7 @@ PcapFile::ReadAndVerifyFileHeader (void)
|
||||
//
|
||||
if (m_fileHeader.m_versionMajor != VERSION_MAJOR || m_fileHeader.m_versionMinor != VERSION_MINOR)
|
||||
{
|
||||
return true;
|
||||
m_file.setstate (std::ios::failbit);
|
||||
}
|
||||
|
||||
//
|
||||
@@ -279,111 +264,34 @@ PcapFile::ReadAndVerifyFileHeader (void)
|
||||
//
|
||||
if (m_fileHeader.m_zone < -12 || m_fileHeader.m_zone > 12)
|
||||
{
|
||||
return true;
|
||||
m_file.setstate (std::ios::failbit);
|
||||
}
|
||||
|
||||
m_haveFileHeader = true;
|
||||
return false;
|
||||
if (m_file.fail ())
|
||||
{
|
||||
m_file.close ();
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
PcapFile::Open (std::string const &filename, std::string const &mode)
|
||||
void
|
||||
PcapFile::Open (std::string const &filename, std::ios::openmode mode)
|
||||
{
|
||||
//
|
||||
// If opening a new file, implicit close of any existing file required.
|
||||
//
|
||||
Close ();
|
||||
|
||||
NS_ASSERT ((mode & std::ios::app) == 0);
|
||||
NS_ASSERT (!m_file.fail ());
|
||||
//
|
||||
// All pcap files are binary files, so we just do this automatically.
|
||||
//
|
||||
std::string realMode = mode + "b";
|
||||
mode |= std::ios::binary;
|
||||
|
||||
//
|
||||
// Our modes may be subtly different from the standard fopen semantics since
|
||||
// we need to have a pcap file header to succeed in some cases; so we need
|
||||
// to process different modes according to our own definitions of the modes.
|
||||
//
|
||||
// In the case of read modes, we must read, check and save the pcap file
|
||||
// header as well as just opening the file.
|
||||
//
|
||||
// In the case of write modes, we just pass the call on through to the
|
||||
// library.
|
||||
//
|
||||
// In the case of append modes, we change the semantics to require the
|
||||
// given file to exist. We can't just create a file since we can't make up
|
||||
// a pcap file header on our own.
|
||||
//
|
||||
if (realMode == "rb" || realMode == "r+b")
|
||||
m_file.open (filename.c_str (), mode);
|
||||
if (mode & std::ios::in)
|
||||
{
|
||||
m_filePtr = fopen (filename.c_str (), realMode.c_str ());
|
||||
if (m_filePtr == 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
m_filename = filename;
|
||||
return ReadAndVerifyFileHeader ();
|
||||
}
|
||||
else if (realMode == "wb" || realMode == "w+b")
|
||||
{
|
||||
m_filePtr = fopen (filename.c_str (), realMode.c_str ());
|
||||
if (m_filePtr)
|
||||
{
|
||||
m_filename = filename;
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (realMode == "ab" || realMode == "a+b")
|
||||
{
|
||||
//
|
||||
// Remember that semantics for append are different here. We never create
|
||||
// a file since we can't make up a pcap file header. We first have to
|
||||
// open the file in read-only mode and check to see that it exists and
|
||||
// read the file header. If this all works out, then we can go ahead and
|
||||
// open the file in append mode and seek to the end (imlicitly).
|
||||
//
|
||||
m_filePtr = fopen (filename.c_str (), "rb");
|
||||
if (m_filePtr == 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool result = ReadAndVerifyFileHeader ();
|
||||
if (result == true)
|
||||
{
|
||||
Close ();
|
||||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
// We have a properly initialized file and have the pcap file header
|
||||
// loaded and checked. This means that the file meets all of the
|
||||
// critera for opening in append mode, but the file is in read-only mode
|
||||
// now -- we must close it and open it in the correct mode.
|
||||
//
|
||||
fclose (m_filePtr);
|
||||
m_filePtr = 0;
|
||||
|
||||
m_filePtr = fopen (filename.c_str (), realMode.c_str ());
|
||||
if (m_filePtr == 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
m_filename = filename;
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
// will set the fail bit if file header is invalid.
|
||||
ReadAndVerifyFileHeader ();
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
void
|
||||
PcapFile::Init (uint32_t dataLinkType, uint32_t snapLen, int32_t timeZoneCorrection, bool swapMode)
|
||||
{
|
||||
//
|
||||
@@ -397,8 +305,6 @@ PcapFile::Init (uint32_t dataLinkType, uint32_t snapLen, int32_t timeZoneCorrect
|
||||
m_fileHeader.m_snapLen = snapLen;
|
||||
m_fileHeader.m_type = dataLinkType;
|
||||
|
||||
m_haveFileHeader = true;
|
||||
|
||||
//
|
||||
// We use pcap files for regression testing. We do byte-for-byte comparisons
|
||||
// in those tests to determine pass or fail. If we allow big endian systems
|
||||
@@ -426,16 +332,13 @@ PcapFile::Init (uint32_t dataLinkType, uint32_t snapLen, int32_t timeZoneCorrect
|
||||
//
|
||||
m_swapMode = swapMode | bigEndian;
|
||||
|
||||
return WriteFileHeader ();
|
||||
WriteFileHeader ();
|
||||
}
|
||||
|
||||
bool
|
||||
PcapFile::Write (uint32_t tsSec, uint32_t tsUsec, uint8_t const * const data, uint32_t totalLen)
|
||||
uint32_t
|
||||
PcapFile::WritePacketHeader (uint32_t tsSec, uint32_t tsUsec, uint32_t totalLen)
|
||||
{
|
||||
if (m_haveFileHeader == false)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
NS_ASSERT (m_file.good ());
|
||||
|
||||
uint32_t inclLen = totalLen > m_fileHeader.m_snapLen ? m_fileHeader.m_snapLen : totalLen;
|
||||
|
||||
@@ -454,19 +357,44 @@ PcapFile::Write (uint32_t tsSec, uint32_t tsUsec, uint8_t const * const data, ui
|
||||
// Watch out for memory alignment differences between machines, so write
|
||||
// them all individually.
|
||||
//
|
||||
uint32_t result = 0;
|
||||
|
||||
result |= (fwrite (&header.m_tsSec, sizeof(header.m_tsSec), 1, m_filePtr) != 1);
|
||||
result |= (fwrite (&header.m_tsUsec, sizeof(header.m_tsUsec), 1, m_filePtr) != 1);
|
||||
result |= (fwrite (&header.m_inclLen, sizeof(header.m_inclLen), 1, m_filePtr) != 1);
|
||||
result |= (fwrite (&header.m_origLen, sizeof(header.m_origLen), 1, m_filePtr) != 1);
|
||||
|
||||
result |= fwrite (data, 1, inclLen, m_filePtr) != inclLen;
|
||||
|
||||
return result != 0;
|
||||
m_file.write ((const char *)&header.m_tsSec, sizeof(header.m_tsSec));
|
||||
m_file.write ((const char *)&header.m_tsUsec, sizeof(header.m_tsUsec));
|
||||
m_file.write ((const char *)&header.m_inclLen, sizeof(header.m_inclLen));
|
||||
m_file.write ((const char *)&header.m_origLen, sizeof(header.m_origLen));
|
||||
return inclLen;
|
||||
}
|
||||
|
||||
bool
|
||||
void
|
||||
PcapFile::Write (uint32_t tsSec, uint32_t tsUsec, uint8_t const * const data, uint32_t totalLen)
|
||||
{
|
||||
uint32_t inclLen = WritePacketHeader (tsSec, tsUsec, totalLen);
|
||||
m_file.write ((const char *)data, inclLen);
|
||||
}
|
||||
|
||||
void
|
||||
PcapFile::Write (uint32_t tsSec, uint32_t tsUsec, Ptr<const Packet> p)
|
||||
{
|
||||
uint32_t inclLen = WritePacketHeader (tsSec, tsUsec, p->GetSize ());
|
||||
p->CopyData (&m_file, inclLen);
|
||||
}
|
||||
|
||||
void
|
||||
PcapFile::Write (uint32_t tsSec, uint32_t tsUsec, Header &header, Ptr<const Packet> p)
|
||||
{
|
||||
uint32_t headerSize = header.GetSerializedSize ();
|
||||
uint32_t totalSize = headerSize + p->GetSize ();
|
||||
uint32_t inclLen = WritePacketHeader (tsSec, tsUsec, totalSize);
|
||||
|
||||
Buffer headerBuffer;
|
||||
headerBuffer.AddAtStart (headerSize);
|
||||
header.Serialize (headerBuffer.Begin ());
|
||||
uint32_t toCopy = std::min (headerSize, inclLen);
|
||||
headerBuffer.CopyData (&m_file, toCopy);
|
||||
inclLen -= toCopy;
|
||||
p->CopyData (&m_file, inclLen);
|
||||
}
|
||||
|
||||
void
|
||||
PcapFile::Read (
|
||||
uint8_t * const data,
|
||||
uint32_t maxBytes,
|
||||
@@ -476,10 +404,7 @@ PcapFile::Read (
|
||||
uint32_t &origLen,
|
||||
uint32_t &readLen)
|
||||
{
|
||||
if (m_haveFileHeader == false)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
NS_ASSERT (m_file.good ());
|
||||
|
||||
PcapRecordHeader header;
|
||||
|
||||
@@ -487,21 +412,10 @@ PcapFile::Read (
|
||||
// Watch out for memory alignment differences between machines, so read
|
||||
// them all individually.
|
||||
//
|
||||
uint32_t result = 0;
|
||||
|
||||
result |= (fread (&header.m_tsSec, sizeof(header.m_tsSec), 1, m_filePtr) != 1);
|
||||
result |= (fread (&header.m_tsUsec, sizeof(header.m_tsUsec), 1, m_filePtr) != 1);
|
||||
result |= (fread (&header.m_inclLen, sizeof(header.m_inclLen), 1, m_filePtr) != 1);
|
||||
result |= (fread (&header.m_origLen, sizeof(header.m_origLen), 1, m_filePtr) != 1);
|
||||
|
||||
//
|
||||
// If any of the freads above did not succeed in reading the correct number of
|
||||
// objects, result will be nonzero.
|
||||
//
|
||||
if (result)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
m_file.read ((char *)&header.m_tsSec, sizeof(header.m_tsSec));
|
||||
m_file.read ((char *)&header.m_tsUsec, sizeof(header.m_tsUsec));
|
||||
m_file.read ((char *)&header.m_inclLen, sizeof(header.m_inclLen));
|
||||
m_file.read ((char *)&header.m_origLen, sizeof(header.m_origLen));
|
||||
|
||||
if (m_swapMode)
|
||||
{
|
||||
@@ -521,11 +435,7 @@ PcapFile::Read (
|
||||
// for example, to figure out what is going on.
|
||||
//
|
||||
readLen = maxBytes < header.m_inclLen ? maxBytes : header.m_inclLen;
|
||||
result = fread (data, 1, readLen, m_filePtr) != readLen;
|
||||
if (result)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
m_file.read ((char *)data, readLen);
|
||||
|
||||
//
|
||||
// To keep the file pointer pointed in the right place, however, we always
|
||||
@@ -533,15 +443,8 @@ PcapFile::Read (
|
||||
//
|
||||
if (readLen < header.m_inclLen)
|
||||
{
|
||||
uint64_t pos = ftell (m_filePtr);
|
||||
int result = fseek (m_filePtr, pos + header.m_inclLen - readLen, SEEK_SET);
|
||||
if (result)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
m_file.seekg (header.m_inclLen - readLen, std::ios::cur);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
@@ -549,59 +452,58 @@ PcapFile::Diff (std::string const & f1, std::string const & f2,
|
||||
uint32_t & sec, uint32_t & usec,
|
||||
uint32_t snapLen)
|
||||
{
|
||||
PcapFile pcap[2];
|
||||
for (int i = 0; i < 2; ++i)
|
||||
PcapFile pcap1, pcap2;
|
||||
pcap1.Open (f1, std::ios::in);
|
||||
pcap2.Open (f2, std::ios::in);
|
||||
bool bad = pcap1.Fail () || pcap2.Fail ();
|
||||
if (bad)
|
||||
{
|
||||
std::string const & file = (i == 0) ? f1 : f2;
|
||||
bool err = pcap[i].Open (file, "r");
|
||||
if (err)
|
||||
{
|
||||
// Can't open file
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
uint8_t data[2][snapLen];
|
||||
uint32_t tsSec[2], tsUsec[2], inclLen[2], origLen[2], readLen[2];
|
||||
bool err[2];
|
||||
bool diff(false);
|
||||
uint8_t *data1 = new uint8_t [snapLen] ();
|
||||
uint8_t *data2 = new uint8_t [snapLen] ();
|
||||
uint32_t tsSec1, tsSec2;
|
||||
uint32_t tsUsec1, tsUsec2;
|
||||
uint32_t inclLen1, inclLen2;
|
||||
uint32_t origLen1, origLen2;
|
||||
uint32_t readLen1, readLen2;
|
||||
bool diff = false;
|
||||
|
||||
while (1)
|
||||
while (!pcap1.Eof () && !pcap2.Eof ()
|
||||
&& !pcap1.Fail () && !pcap2.Fail ())
|
||||
{
|
||||
for (int i = 0; i < 2; ++i)
|
||||
err[i] = pcap[i].Read (data[i], snapLen, tsSec[i], tsUsec[i], inclLen[i], origLen[i], readLen[i]);
|
||||
|
||||
sec = tsSec[0];
|
||||
usec = tsUsec[0];
|
||||
|
||||
if (err[0] != err[1])
|
||||
{
|
||||
diff = true; // Read status doesn't match
|
||||
break;
|
||||
}
|
||||
|
||||
if (err[0]) break; // nothing left
|
||||
|
||||
if (tsSec[0] != tsSec[1] || tsUsec[0] != tsUsec[1])
|
||||
pcap1.Read (data1, snapLen, tsSec1, tsUsec1, inclLen1, origLen1, readLen1);
|
||||
pcap2.Read (data2, snapLen, tsSec2, tsUsec2, inclLen2, origLen2, readLen2);
|
||||
|
||||
if (tsSec1 != tsSec2 || tsUsec1 != tsUsec2)
|
||||
{
|
||||
diff = true; // Next packet timestamps do not match
|
||||
break;
|
||||
}
|
||||
|
||||
if (readLen[0] != readLen[1])
|
||||
if (readLen1 != readLen2)
|
||||
{
|
||||
diff = true; // Packet lengths do not match
|
||||
break;
|
||||
}
|
||||
|
||||
if (std::memcmp(data[0], data[1], readLen[0]) != 0)
|
||||
if (std::memcmp(data1, data2, readLen1) != 0)
|
||||
{
|
||||
diff = true; // Packet data do not match
|
||||
break;
|
||||
}
|
||||
}
|
||||
pcap[0].Close ();
|
||||
pcap[1].Close ();
|
||||
sec = tsSec1;
|
||||
usec = tsUsec1;
|
||||
|
||||
bad = pcap1.Fail () || pcap2.Fail ();
|
||||
bool eof = pcap1.Eof () && pcap2.Eof ();
|
||||
if (bad && !eof)
|
||||
{
|
||||
diff = true;
|
||||
}
|
||||
|
||||
return diff;
|
||||
}
|
||||
|
||||
|
||||
@@ -22,10 +22,15 @@
|
||||
#define PCAP_FILE_H
|
||||
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
#include <stdint.h>
|
||||
#include "ns3/ptr.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
class Packet;
|
||||
class Header;
|
||||
|
||||
/*
|
||||
* A class representing a pcap file. This allows easy creation, writing and
|
||||
* reading of files composed of stored packets; which may be viewed using
|
||||
@@ -42,68 +47,36 @@ public:
|
||||
PcapFile ();
|
||||
~PcapFile ();
|
||||
|
||||
/**
|
||||
* \return true if the 'fail' bit is set in the underlying iostream, false otherwise.
|
||||
*/
|
||||
bool Fail (void) const;
|
||||
/**
|
||||
* \return true if the 'eof' bit is set in the underlying iostream, false otherwise.
|
||||
*/
|
||||
bool Eof (void) const;
|
||||
/**
|
||||
* Clear all state bits of the underlying iostream.
|
||||
*/
|
||||
void Clear (void);
|
||||
|
||||
/**
|
||||
* Create a new pcap file or open an existing pcap file. Semantics are
|
||||
* similar to the C standard library function \c fopen, but differ in that
|
||||
* similar to the stdc++ io stream classes, but differ in that
|
||||
* positions in the file are based on packets not characters. For example
|
||||
* if the file is opened for reading, the file position indicator (seek
|
||||
* position) points to the beginning of the first packet in the file, not
|
||||
* zero (which would point to the start of the pcap header).
|
||||
*
|
||||
* Possible modes are:
|
||||
*
|
||||
* \verbatim
|
||||
* "r": Open a file for reading. The file must exist. The pcap header
|
||||
* is assumed to exist in the file and will be read and checked.
|
||||
* The file seek position indicator is set to point to the first
|
||||
* packet on exit.
|
||||
*
|
||||
* "w": Create an empty file for writing. If a file with the same name
|
||||
* already exists its content is erased and the file is treated as a
|
||||
* new empty pcap file. The file is assumed not to have a pcap
|
||||
* header and the caller is responsible for calling Init before saving
|
||||
* any packet data. The file seek position indicator is set to point
|
||||
* to the beginning of the file on exit since there will be no pcap
|
||||
* header.
|
||||
*
|
||||
* "a": Append to an existing file. This mode allows for adding packet data
|
||||
* to the end of an existing pcap file. The file must exist and have a
|
||||
* valid pcap header written (N.B. this is different from standard fopen
|
||||
* semantics). The file seek position indicator is set to point
|
||||
* to the end of the file on exit.
|
||||
*
|
||||
* "r+": Open a file for update -- both reading and writing. The file must
|
||||
* exist. The pcap header is assumed to have been written to the
|
||||
* file and will be read and checked. The file seek position indicator
|
||||
* is set to point to the first packet on exit.
|
||||
*
|
||||
* "w+": Create an empty file for both reading and writing. If a file with
|
||||
* the same name already exists, its content is erased and the file is
|
||||
* treated as a new empty pcap file. Since this new file will not have
|
||||
* a pcap header, the caller is responsible for calling Init before
|
||||
* saving any packet data. On exit, the file seek position indicator is
|
||||
* set to point to the beginning of the file.
|
||||
*
|
||||
* "a+" Open a file for reading and appending. The file must exist and have a
|
||||
* valid pcap header written (N.B. this is different from standard fopen
|
||||
* semantics). The file seek position indicator is set to point
|
||||
* to the end of the file on exit. Existing content is preserved.
|
||||
* \endverbatim
|
||||
*
|
||||
* Since a pcap file is always a binary file, the file type is automatically
|
||||
* selected as a binary file. For example, providing a mode string "a+"
|
||||
* results in the underlying OS file being opened in "a+b" mode.
|
||||
* selected as a binary file (fstream::binary is automatically ored with the mode
|
||||
* field).
|
||||
*
|
||||
* \param filename String containing the name of the file.
|
||||
*
|
||||
* \param mode String containing the access mode for the file.
|
||||
*
|
||||
* \returns Error indication that should be interpreted as, "did an error
|
||||
* happen"? That is, the method returns false if the open succeeds, true
|
||||
* otherwise. The errno variable will be set by the OS to to provide a
|
||||
* more descriptive failure indication.
|
||||
* \param mode the access mode for the file.
|
||||
*/
|
||||
bool Open (std::string const &filename, std::string const &mode);
|
||||
void Open (std::string const &filename, std::ios::openmode mode);
|
||||
|
||||
/**
|
||||
* Close the underlying file.
|
||||
@@ -138,7 +111,7 @@ public:
|
||||
* \warning Calling this method on an existing file will result in the loss
|
||||
* any existing data.
|
||||
*/
|
||||
bool Init (uint32_t dataLinkType,
|
||||
void Init (uint32_t dataLinkType,
|
||||
uint32_t snapLen = SNAPLEN_DEFAULT,
|
||||
int32_t timeZoneCorrection = ZONE_DEFAULT,
|
||||
bool swapMode = false);
|
||||
@@ -151,9 +124,29 @@ public:
|
||||
* \param data Data buffer
|
||||
* \param totalLen Total packet length
|
||||
*
|
||||
* \return true on error, false otherwise
|
||||
*/
|
||||
bool Write (uint32_t tsSec, uint32_t tsUsec, uint8_t const * const data, uint32_t totalLen);
|
||||
void Write (uint32_t tsSec, uint32_t tsUsec, uint8_t const * const data, uint32_t totalLen);
|
||||
|
||||
/**
|
||||
* \brief Write next packet to file
|
||||
*
|
||||
* \param tsSec Packet timestamp, seconds
|
||||
* \param tsUsec Packet timestamp, microseconds
|
||||
* \param p Packet to write
|
||||
*
|
||||
*/
|
||||
void Write (uint32_t tsSec, uint32_t tsUsec, Ptr<const Packet> p);
|
||||
/**
|
||||
* \brief Write next packet to file
|
||||
*
|
||||
* \param tsSec Packet timestamp, seconds
|
||||
* \param tsUsec Packet timestamp, microseconds
|
||||
* \param header Header to write, in front of packet
|
||||
* \param p Packet to write
|
||||
*
|
||||
*/
|
||||
void Write (uint32_t tsSec, uint32_t tsUsec, Header &header, Ptr<const Packet> p);
|
||||
|
||||
|
||||
/**
|
||||
* \brief Read next packet from file
|
||||
@@ -166,9 +159,8 @@ public:
|
||||
* \param origLen [out] Original length
|
||||
* \param readLen [out] Number of bytes read
|
||||
*
|
||||
* \return true if read failed, false otherwise
|
||||
*/
|
||||
bool Read (uint8_t * const data,
|
||||
void Read (uint8_t * const data,
|
||||
uint32_t maxBytes,
|
||||
uint32_t &tsSec,
|
||||
uint32_t &tsUsec,
|
||||
@@ -290,13 +282,13 @@ private:
|
||||
void Swap (PcapFileHeader *from, PcapFileHeader *to);
|
||||
void Swap (PcapRecordHeader *from, PcapRecordHeader *to);
|
||||
|
||||
bool WriteFileHeader (void);
|
||||
bool ReadAndVerifyFileHeader (void);
|
||||
void WriteFileHeader (void);
|
||||
uint32_t WritePacketHeader (uint32_t tsSec, uint32_t tsUsec, uint32_t totalLen);
|
||||
void ReadAndVerifyFileHeader (void);
|
||||
|
||||
std::string m_filename;
|
||||
FILE *m_filePtr;
|
||||
std::fstream m_file;
|
||||
PcapFileHeader m_fileHeader;
|
||||
bool m_haveFileHeader;
|
||||
bool m_swapMode;
|
||||
};
|
||||
|
||||
|
||||
@@ -98,7 +98,8 @@ CsmaHelper::EnablePcapInternal (std::string prefix, Ptr<NetDevice> nd, bool prom
|
||||
filename = pcapHelper.GetFilenameFromDevice (prefix, device);
|
||||
}
|
||||
|
||||
Ptr<PcapFileWrapper> file = pcapHelper.CreateFile (filename, "w", PcapHelper::DLT_EN10MB);
|
||||
Ptr<PcapFileWrapper> file = pcapHelper.CreateFile (filename, std::ios::out,
|
||||
PcapHelper::DLT_EN10MB);
|
||||
if (promiscuous)
|
||||
{
|
||||
pcapHelper.HookDefaultSink<CsmaNetDevice> (device, "PromiscSniffer", file);
|
||||
@@ -159,7 +160,7 @@ CsmaHelper::EnableAsciiInternal (
|
||||
filename = asciiTraceHelper.GetFilenameFromDevice (prefix, device);
|
||||
}
|
||||
|
||||
Ptr<OutputStreamWrapper> theStream = asciiTraceHelper.CreateFileStream (filename, "w");
|
||||
Ptr<OutputStreamWrapper> theStream = asciiTraceHelper.CreateFileStream (filename);
|
||||
|
||||
//
|
||||
// The MacRx trace source provides our "r" event.
|
||||
|
||||
@@ -91,7 +91,7 @@ EmuHelper::EnablePcapInternal (std::string prefix, Ptr<NetDevice> nd, bool promi
|
||||
filename = pcapHelper.GetFilenameFromDevice (prefix, device);
|
||||
}
|
||||
|
||||
Ptr<PcapFileWrapper> file = pcapHelper.CreateFile (filename, "w", PcapHelper::DLT_EN10MB);
|
||||
Ptr<PcapFileWrapper> file = pcapHelper.CreateFile (filename, std::ios::out, PcapHelper::DLT_EN10MB);
|
||||
if (promiscuous)
|
||||
{
|
||||
pcapHelper.HookDefaultSink<EmuNetDevice> (device, "PromiscSniffer", file);
|
||||
@@ -152,7 +152,7 @@ EmuHelper::EnableAsciiInternal (
|
||||
filename = asciiTraceHelper.GetFilenameFromDevice (prefix, device);
|
||||
}
|
||||
|
||||
Ptr<OutputStreamWrapper> theStream = asciiTraceHelper.CreateFileStream (filename, "w");
|
||||
Ptr<OutputStreamWrapper> theStream = asciiTraceHelper.CreateFileStream (filename);
|
||||
|
||||
//
|
||||
// The MacRx trace source provides our "r" event.
|
||||
|
||||
@@ -470,7 +470,7 @@ InternetStackHelper::EnablePcapIpv4Internal (std::string prefix, Ptr<Ipv4> ipv4,
|
||||
filename = pcapHelper.GetFilenameFromInterfacePair (prefix, ipv4, interface);
|
||||
}
|
||||
|
||||
Ptr<PcapFileWrapper> file = pcapHelper.CreateFile (filename, "w", PcapHelper::DLT_RAW);
|
||||
Ptr<PcapFileWrapper> file = pcapHelper.CreateFile (filename, std::ios::out, PcapHelper::DLT_RAW);
|
||||
|
||||
//
|
||||
// However, we only hook the trace source once to avoid multiple trace sink
|
||||
@@ -562,7 +562,7 @@ InternetStackHelper::EnablePcapIpv6Internal (std::string prefix, Ptr<Ipv6> ipv6,
|
||||
filename = pcapHelper.GetFilenameFromInterfacePair (prefix, ipv6, interface);
|
||||
}
|
||||
|
||||
Ptr<PcapFileWrapper> file = pcapHelper.CreateFile (filename, "w", PcapHelper::DLT_RAW);
|
||||
Ptr<PcapFileWrapper> file = pcapHelper.CreateFile (filename, std::ios::out, PcapHelper::DLT_RAW);
|
||||
|
||||
//
|
||||
// However, we only hook the trace source once to avoid multiple trace sink
|
||||
@@ -714,7 +714,7 @@ InternetStackHelper::EnableAsciiIpv4Internal (
|
||||
filename = asciiTraceHelper.GetFilenameFromInterfacePair (prefix, ipv4, interface);
|
||||
}
|
||||
|
||||
Ptr<OutputStreamWrapper> theStream = asciiTraceHelper.CreateFileStream (filename, "w");
|
||||
Ptr<OutputStreamWrapper> theStream = asciiTraceHelper.CreateFileStream (filename);
|
||||
|
||||
//
|
||||
// However, we only hook the trace sources once to avoid multiple trace sink
|
||||
@@ -909,7 +909,7 @@ InternetStackHelper::EnableAsciiIpv6Internal (
|
||||
filename = asciiTraceHelper.GetFilenameFromInterfacePair (prefix, ipv6, interface);
|
||||
}
|
||||
|
||||
Ptr<OutputStreamWrapper> theStream = asciiTraceHelper.CreateFileStream (filename, "w");
|
||||
Ptr<OutputStreamWrapper> theStream = asciiTraceHelper.CreateFileStream (filename);
|
||||
|
||||
//
|
||||
// However, we only hook the trace sources once to avoid multiple trace sink
|
||||
|
||||
@@ -99,7 +99,8 @@ PointToPointHelper::EnablePcapInternal (std::string prefix, Ptr<NetDevice> nd, b
|
||||
filename = pcapHelper.GetFilenameFromDevice (prefix, device);
|
||||
}
|
||||
|
||||
Ptr<PcapFileWrapper> file = pcapHelper.CreateFile (filename, "w", PcapHelper::DLT_PPP);
|
||||
Ptr<PcapFileWrapper> file = pcapHelper.CreateFile (filename, std::ios::out,
|
||||
PcapHelper::DLT_PPP);
|
||||
pcapHelper.HookDefaultSink<PointToPointNetDevice> (device, "PromiscSniffer", file);
|
||||
}
|
||||
|
||||
@@ -154,7 +155,7 @@ PointToPointHelper::EnableAsciiInternal (
|
||||
filename = asciiTraceHelper.GetFilenameFromDevice (prefix, device);
|
||||
}
|
||||
|
||||
Ptr<OutputStreamWrapper> theStream = asciiTraceHelper.CreateFileStream (filename, "w");
|
||||
Ptr<OutputStreamWrapper> theStream = asciiTraceHelper.CreateFileStream (filename);
|
||||
|
||||
//
|
||||
// The MacRx trace source provides our "r" event.
|
||||
|
||||
@@ -48,7 +48,7 @@ PcapHelper::~PcapHelper ()
|
||||
Ptr<PcapFileWrapper>
|
||||
PcapHelper::CreateFile (
|
||||
std::string filename,
|
||||
std::string filemode,
|
||||
std::ios::openmode filemode,
|
||||
uint32_t dataLinkType,
|
||||
uint32_t snapLen,
|
||||
int32_t tzCorrection)
|
||||
@@ -56,11 +56,11 @@ PcapHelper::CreateFile (
|
||||
NS_LOG_FUNCTION (filename << filemode << dataLinkType << snapLen << tzCorrection);
|
||||
|
||||
Ptr<PcapFileWrapper> file = CreateObject<PcapFileWrapper> ();
|
||||
bool err = file->Open (filename, filemode);
|
||||
NS_ABORT_MSG_IF (err, "Unable to Open " << filename << " for mode " << filemode);
|
||||
file->Open (filename, filemode);
|
||||
NS_ABORT_MSG_IF (file->Fail (), "Unable to Open " << filename << " for mode " << filemode);
|
||||
|
||||
err = file->Init (dataLinkType, snapLen, tzCorrection);
|
||||
NS_ABORT_MSG_IF (err, "Unable to Init " << filename);
|
||||
file->Init (dataLinkType, snapLen, tzCorrection);
|
||||
NS_ABORT_MSG_IF (file->Fail (), "Unable to Init " << filename);
|
||||
|
||||
//
|
||||
// Note that the pcap helper promptly forgets all about the pcap file. We
|
||||
@@ -181,27 +181,13 @@ AsciiTraceHelper::~AsciiTraceHelper ()
|
||||
}
|
||||
|
||||
Ptr<OutputStreamWrapper>
|
||||
AsciiTraceHelper::CreateFileStream (std::string filename, std::string filemode)
|
||||
AsciiTraceHelper::CreateFileStream (std::string filename, std::ios::openmode filemode)
|
||||
{
|
||||
NS_LOG_FUNCTION (filename << filemode);
|
||||
|
||||
std::ofstream *ofstream = new std::ofstream;
|
||||
std::ios_base::openmode mode = std::ios_base::out | std::ios_base::trunc;
|
||||
|
||||
if (filemode == "a")
|
||||
{
|
||||
mode = std::ios_base::out | std::ios_base::app;
|
||||
}
|
||||
else if (filemode == "w")
|
||||
{
|
||||
mode = std::ios_base::out | std::ios_base::trunc;
|
||||
}
|
||||
else
|
||||
{
|
||||
NS_ABORT_MSG ("AsciiTraceHelper::CreateFileStream(): Unexpected file mode");
|
||||
}
|
||||
|
||||
ofstream->open (filename.c_str (), mode);
|
||||
ofstream->open (filename.c_str (), filemode);
|
||||
NS_ABORT_MSG_UNLESS (ofstream->is_open (), "AsciiTraceHelper::CreateFileStream(): Unable to Open " <<
|
||||
filename << " for mode " << filemode);
|
||||
|
||||
|
||||
@@ -84,7 +84,7 @@ public:
|
||||
/**
|
||||
* @brief Create and initialize a pcap file.
|
||||
*/
|
||||
Ptr<PcapFileWrapper> CreateFile (std::string filename, std::string filemode,
|
||||
Ptr<PcapFileWrapper> CreateFile (std::string filename, std::ios::openmode filemode,
|
||||
uint32_t dataLinkType, uint32_t snapLen = 65535, int32_t tzCorrection = 0);
|
||||
/**
|
||||
* @brief Hook a trace source to the default trace sink
|
||||
@@ -156,7 +156,8 @@ public:
|
||||
* that can solve the problem so we use one of those to carry the stream
|
||||
* around and deal with the lifetime issues.
|
||||
*/
|
||||
Ptr<OutputStreamWrapper> CreateFileStream (std::string filename, std::string filemode = "w");
|
||||
Ptr<OutputStreamWrapper> CreateFileStream (std::string filename,
|
||||
std::ios::openmode filemode = std::ios::out);
|
||||
|
||||
/**
|
||||
* @brief Hook a trace source to the default enqueue operation trace sink that
|
||||
|
||||
@@ -480,7 +480,7 @@ WimaxHelper::EnableAsciiInternal (Ptr<OutputStreamWrapper> stream,
|
||||
{
|
||||
filename = asciiTraceHelper.GetFilenameFromDevice (prefix, device);
|
||||
}
|
||||
Ptr<OutputStreamWrapper> theStream = asciiTraceHelper.CreateFileStream (filename, "w");
|
||||
Ptr<OutputStreamWrapper> theStream = asciiTraceHelper.CreateFileStream (filename);
|
||||
|
||||
uint32_t nodeid = nd->GetNode ()->GetId ();
|
||||
uint32_t deviceid = nd->GetIfIndex ();
|
||||
@@ -586,7 +586,7 @@ WimaxHelper::EnablePcapInternal (std::string prefix, Ptr<NetDevice> nd, bool exp
|
||||
filename = pcapHelper.GetFilenameFromDevice (prefix, device);
|
||||
}
|
||||
|
||||
Ptr<PcapFileWrapper> file = pcapHelper.CreateFile (filename, "w", PcapHelper::DLT_EN10MB);
|
||||
Ptr<PcapFileWrapper> file = pcapHelper.CreateFile (filename, std::ios::out, PcapHelper::DLT_EN10MB);
|
||||
|
||||
phy->TraceConnectWithoutContext ("Tx", MakeBoundCallback (&PcapSniffTxEvent, file));
|
||||
phy->TraceConnectWithoutContext ("Rx", MakeBoundCallback (&PcapSniffRxEvent, file));
|
||||
|
||||
@@ -409,7 +409,7 @@ YansWifiPhyHelper::EnablePcapInternal (std::string prefix, Ptr<NetDevice> nd, bo
|
||||
filename = pcapHelper.GetFilenameFromDevice (prefix, device);
|
||||
}
|
||||
|
||||
Ptr<PcapFileWrapper> file = pcapHelper.CreateFile (filename, "w", m_pcapDlt);
|
||||
Ptr<PcapFileWrapper> file = pcapHelper.CreateFile (filename, std::ios::out, m_pcapDlt);
|
||||
|
||||
phy->TraceConnectWithoutContext ("PromiscSnifferTx", MakeBoundCallback (&PcapSniffTxEvent, file));
|
||||
phy->TraceConnectWithoutContext ("PromiscSnifferRx", MakeBoundCallback (&PcapSniffRxEvent, file));
|
||||
|
||||
Reference in New Issue
Block a user