Skip to content

Commit 5eb5fcd

Browse files
authored
Simplified the implementation of PcapNgFileWriterDevice opening. (#1804)
* Streamlined PcapNgFileWriterDevice to have all open configurations pass through a single point `openImpl`. * Streamlined PcapNgFileReader's metadata accessors. * Added check to ensure no append mode open can be made with new metadata. * Added overrides to fix CI. * Fixed cppcheck error about virtual call in destructor. * Split openImpl to openWrite and openAppend. * Reverted fetching of metadata to individual blocks. Changed PcapNgMetadata to private struct of PcapNgFileWriterDevice.
1 parent 8bcb200 commit 5eb5fcd

File tree

2 files changed

+106
-96
lines changed

2 files changed

+106
-96
lines changed

Pcap++/header/PcapFileDevice.h

Lines changed: 43 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -461,25 +461,9 @@ namespace pcpp
461461
/// A destructor for this class
462462
virtual ~PcapNgFileWriterDevice()
463463
{
464-
close();
464+
PcapNgFileWriterDevice::close();
465465
}
466466

467-
/// Open the file in a write mode. If file doesn't exist, it will be created. If it does exist it will be
468-
/// overwritten, meaning all its current content will be deleted. As opposed to open(), this method also allows
469-
/// writing several metadata attributes that will be stored in the header of the file
470-
/// @param[in] os A string describing the operating system that was used to capture the packets. If this string
471-
/// is empty or null it will be ignored
472-
/// @param[in] hardware A string describing the hardware that was used to capture the packets. If this string is
473-
/// empty or null it will be ignored
474-
/// @param[in] captureApp A string describing the application that was used to capture the packets. If this
475-
/// string is empty or null it will be ignored
476-
/// @param[in] fileComment A string containing a user-defined comment that will be part of the metadata of the
477-
/// file. If this string is empty or null it will be ignored
478-
/// @return True if file was opened/created successfully or if file is already opened. False if opening the file
479-
/// failed for some reason (an error will be printed to log)
480-
bool open(const std::string& os, const std::string& hardware, const std::string& captureApp,
481-
const std::string& fileComment);
482-
483467
/// The pcap-ng format allows adding a user-defined comment for each stored packet. This method writes a
484468
/// RawPacket to the file and adds a comment to it. Before using this method please verify the file is opened
485469
/// using open(). This method won't change the written packet or the input comment
@@ -497,7 +481,7 @@ namespace pcpp
497481
/// @param[in] packet A reference for an existing RawPcket to write to the file
498482
/// @return True if a packet was written successfully. False will be returned if the file isn't opened (an error
499483
/// will be printed to log)
500-
bool writePacket(RawPacket const& packet);
484+
bool writePacket(RawPacket const& packet) override;
501485

502486
/// Write multiple RawPacket to the file. Before using this method please verify the file is opened using
503487
/// open(). This method won't change the written packets or the RawPacketVector instance
@@ -506,13 +490,13 @@ namespace pcpp
506490
/// @return True if all packets were written successfully to the file. False will be returned if the file isn't
507491
/// opened (also, an error log will be printed) or if at least one of the packets wasn't written successfully to
508492
/// the file
509-
bool writePackets(const RawPacketVector& packets);
493+
bool writePackets(const RawPacketVector& packets) override;
510494

511495
/// Open the file in a write mode. If file doesn't exist, it will be created. If it does exist it will be
512496
/// overwritten, meaning all its current content will be deleted
513497
/// @return True if file was opened/created successfully or if file is already opened. False if opening the file
514498
/// failed for some reason (an error will be printed to log)
515-
bool open();
499+
bool open() override;
516500

517501
/// Same as open(), but enables to open the file in append mode in which packets will be appended to the file
518502
/// instead of overwrite its current content. In append mode file must exist, otherwise opening will fail
@@ -521,23 +505,58 @@ namespace pcpp
521505
/// @return True of managed to open the file successfully. In case appendMode is set to true, false will be
522506
/// returned if file wasn't found or couldn't be read, if file type is not pcap-ng. In case appendMode is set to
523507
/// false, please refer to open() for return values
524-
bool open(bool appendMode);
508+
bool open(bool appendMode) override;
509+
510+
/// Open the file in a write mode. If file doesn't exist, it will be created. If it does exist it will be
511+
/// overwritten, meaning all its current content will be deleted. As opposed to open(), this method also allows
512+
/// writing several metadata attributes that will be stored in the header of the file
513+
/// @param[in] os A string describing the operating system that was used to capture the packets. If this string
514+
/// is empty or null it will be ignored
515+
/// @param[in] hardware A string describing the hardware that was used to capture the packets. If this string is
516+
/// empty or null it will be ignored
517+
/// @param[in] captureApp A string describing the application that was used to capture the packets. If this
518+
/// string is empty or null it will be ignored
519+
/// @param[in] fileComment A string containing a user-defined comment that will be part of the metadata of the
520+
/// file. If this string is empty or null it will be ignored
521+
/// @return True if file was opened/created successfully or if file is already opened. False if opening the file
522+
/// failed for some reason (an error will be printed to log)
523+
bool open(const std::string& os, const std::string& hardware, const std::string& captureApp,
524+
const std::string& fileComment);
525525

526526
/// Flush packets to the pcap-ng file
527527
void flush();
528528

529529
/// Flush and close the pcap-ng file
530-
void close();
530+
void close() override;
531531

532532
/// Get statistics of packets written so far.
533533
/// @param[out] stats The stats struct where stats are returned
534-
void getStatistics(PcapStats& stats) const;
534+
void getStatistics(PcapStats& stats) const override;
535535

536536
/// Set a filter for PcapNG writer device. Only packets that match the filter will be persisted
537537
/// @param[in] filterAsString The filter to be set in Berkeley Packet Filter (BPF) syntax
538538
/// (http://biot.com/capstats/bpf.html)
539539
/// @return True if filter set successfully, false otherwise
540-
bool setFilter(std::string filterAsString);
540+
bool setFilter(std::string filterAsString) override;
541+
542+
private:
543+
/// @struct PcapNgMetadata
544+
/// @brief A struct for holding the metadata of a pcap-ng file. The metadata includes the operating system,
545+
/// hardware, capture application and file comment.
546+
struct PcapNgMetadata
547+
{
548+
/// The operating system that was used for capturing the packets
549+
std::string os;
550+
/// The hardware that was used for capturing the packets
551+
std::string hardware;
552+
/// The capture application that was used for capturing the packets
553+
std::string captureApplication;
554+
/// The comment that was written inside the file
555+
std::string comment;
556+
};
557+
558+
bool openWrite(PcapNgMetadata const* metadata = nullptr);
559+
bool openAppend();
541560
};
542561

543562
} // namespace pcpp

Pcap++/src/PcapFileDevice.cpp

Lines changed: 63 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -492,75 +492,59 @@ namespace pcpp
492492
if (m_LightPcapNg == nullptr)
493493
{
494494
PCPP_LOG_ERROR("Pcapng file device '" << m_FileName << "' not opened");
495-
return "";
495+
return {};
496496
}
497497

498498
light_pcapng_file_info* fileInfo = light_pcang_get_file_info(toLightPcapNgT(m_LightPcapNg));
499-
if (fileInfo == nullptr)
500-
return "";
501-
char* res = fileInfo->os_desc;
502-
size_t len = fileInfo->os_desc_size;
503-
if (len == 0 || res == nullptr)
504-
return "";
505-
506-
return std::string(res, len);
499+
if (fileInfo == nullptr || fileInfo->os_desc == nullptr || fileInfo->os_desc_size == 0)
500+
return {};
501+
502+
return std::string(fileInfo->os_desc, fileInfo->os_desc_size);
507503
}
508504

509505
std::string PcapNgFileReaderDevice::getHardware() const
510506
{
511507
if (m_LightPcapNg == nullptr)
512508
{
513509
PCPP_LOG_ERROR("Pcapng file device '" << m_FileName << "' not opened");
514-
return "";
510+
return {};
515511
}
516512

517513
light_pcapng_file_info* fileInfo = light_pcang_get_file_info(toLightPcapNgT(m_LightPcapNg));
518-
if (fileInfo == nullptr)
519-
return "";
520-
char* res = fileInfo->hardware_desc;
521-
size_t len = fileInfo->hardware_desc_size;
522-
if (len == 0 || res == nullptr)
523-
return "";
524-
525-
return std::string(res, len);
514+
if (fileInfo == nullptr || fileInfo->hardware_desc == nullptr || fileInfo->hardware_desc_size == 0)
515+
return {};
516+
517+
return std::string(fileInfo->hardware_desc, fileInfo->hardware_desc_size);
526518
}
527519

528520
std::string PcapNgFileReaderDevice::getCaptureApplication() const
529521
{
530522
if (m_LightPcapNg == nullptr)
531523
{
532524
PCPP_LOG_ERROR("Pcapng file device '" << m_FileName << "' not opened");
533-
return "";
525+
return {};
534526
}
535527

536528
light_pcapng_file_info* fileInfo = light_pcang_get_file_info(toLightPcapNgT(m_LightPcapNg));
537-
if (fileInfo == nullptr)
538-
return "";
539-
char* res = fileInfo->user_app_desc;
540-
size_t len = fileInfo->user_app_desc_size;
541-
if (len == 0 || res == nullptr)
542-
return "";
543-
544-
return std::string(res, len);
529+
if (fileInfo == nullptr || fileInfo->user_app_desc == nullptr || fileInfo->user_app_desc_size == 0)
530+
return {};
531+
532+
return std::string(fileInfo->user_app_desc, fileInfo->user_app_desc_size);
545533
}
546534

547535
std::string PcapNgFileReaderDevice::getCaptureFileComment() const
548536
{
549537
if (m_LightPcapNg == nullptr)
550538
{
551539
PCPP_LOG_ERROR("Pcapng file device '" << m_FileName << "' not opened");
552-
return "";
540+
return {};
553541
}
554542

555543
light_pcapng_file_info* fileInfo = light_pcang_get_file_info(toLightPcapNgT(m_LightPcapNg));
556-
if (fileInfo == nullptr)
557-
return "";
558-
char* res = fileInfo->file_comment;
559-
size_t len = fileInfo->file_comment_size;
560-
if (len == 0 || res == nullptr)
561-
return "";
562-
563-
return std::string(res, len);
544+
if (fileInfo == nullptr || fileInfo->file_comment == nullptr || fileInfo->file_comment_size == 0)
545+
return {};
546+
547+
return std::string(fileInfo->file_comment, fileInfo->file_comment_size);
564548
}
565549

566550
// ~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -867,38 +851,6 @@ namespace pcpp
867851
m_CompressionLevel = compressionLevel;
868852
}
869853

870-
bool PcapNgFileWriterDevice::open(const std::string& os, const std::string& hardware, const std::string& captureApp,
871-
const std::string& fileComment)
872-
{
873-
if (m_LightPcapNg != nullptr)
874-
{
875-
PCPP_LOG_DEBUG("Pcap-ng descriptor already opened. Nothing to do");
876-
return true;
877-
}
878-
879-
m_NumOfPacketsNotWritten = 0;
880-
m_NumOfPacketsWritten = 0;
881-
882-
light_pcapng_file_info* info =
883-
light_create_file_info(os.c_str(), hardware.c_str(), captureApp.c_str(), fileComment.c_str());
884-
885-
m_LightPcapNg = toLightPcapNgHandle(light_pcapng_open_write(m_FileName.c_str(), info, m_CompressionLevel));
886-
if (m_LightPcapNg == nullptr)
887-
{
888-
PCPP_LOG_ERROR("Error opening file writer device for file '"
889-
<< m_FileName << "': light_pcapng_open_write returned nullptr");
890-
891-
light_free_file_info(info);
892-
893-
m_DeviceOpened = false;
894-
return false;
895-
}
896-
897-
m_DeviceOpened = true;
898-
PCPP_LOG_DEBUG("pcap-ng writer device for file '" << m_FileName << "' opened successfully");
899-
return true;
900-
}
901-
902854
bool PcapNgFileWriterDevice::writePacket(RawPacket const& packet, const std::string& comment)
903855
{
904856
if (m_LightPcapNg == nullptr)
@@ -955,6 +907,30 @@ namespace pcpp
955907

956908
bool PcapNgFileWriterDevice::open()
957909
{
910+
return openWrite();
911+
}
912+
913+
bool PcapNgFileWriterDevice::open(bool appendMode)
914+
{
915+
return appendMode ? openAppend() : openWrite();
916+
}
917+
918+
bool PcapNgFileWriterDevice::open(const std::string& os, const std::string& hardware, const std::string& captureApp,
919+
const std::string& fileComment)
920+
{
921+
PcapNgMetadata metadata;
922+
metadata.os = os;
923+
metadata.hardware = hardware;
924+
metadata.captureApplication = captureApp;
925+
metadata.comment = fileComment;
926+
return openWrite(&metadata);
927+
}
928+
929+
bool PcapNgFileWriterDevice::openWrite(PcapNgMetadata const* metadata)
930+
{
931+
// TODO: Ambiguity in the API
932+
// If the user calls open() and then open(true) - should we close the first one or report failure?
933+
// Currently the method reports a success, but the opened device would not match the appendMode.
958934
if (m_LightPcapNg != nullptr)
959935
{
960936
PCPP_LOG_DEBUG("Pcap-ng descriptor already opened. Nothing to do");
@@ -964,7 +940,16 @@ namespace pcpp
964940
m_NumOfPacketsNotWritten = 0;
965941
m_NumOfPacketsWritten = 0;
966942

967-
light_pcapng_file_info* info = light_create_default_file_info();
943+
light_pcapng_file_info* info;
944+
if (metadata == nullptr)
945+
{
946+
info = light_create_default_file_info();
947+
}
948+
else
949+
{
950+
info = light_create_file_info(metadata->os.c_str(), metadata->hardware.c_str(),
951+
metadata->captureApplication.c_str(), metadata->comment.c_str());
952+
}
968953

969954
m_LightPcapNg = toLightPcapNgHandle(light_pcapng_open_write(m_FileName.c_str(), info, m_CompressionLevel));
970955
if (m_LightPcapNg == nullptr)
@@ -983,10 +968,16 @@ namespace pcpp
983968
return true;
984969
}
985970

986-
bool PcapNgFileWriterDevice::open(bool appendMode)
971+
bool PcapNgFileWriterDevice::openAppend()
987972
{
988-
if (!appendMode)
989-
return open();
973+
// TODO: Ambiguity in the API
974+
// If the user calls open() and then open(true) - should we close the first one or report failure?
975+
// Currently the method reports a success, but the opened device would not match the appendMode.
976+
if (m_LightPcapNg != nullptr)
977+
{
978+
PCPP_LOG_DEBUG("Pcap-ng descriptor already opened. Nothing to do");
979+
return true;
980+
}
990981

991982
m_NumOfPacketsNotWritten = 0;
992983
m_NumOfPacketsWritten = 0;

0 commit comments

Comments
 (0)