Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use smart pointers for PcapLiveDeviceList's internal memory management. #1440

20 changes: 12 additions & 8 deletions Pcap++/header/PcapLiveDeviceList.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include "IpAddress.h"
#include "PcapLiveDevice.h"
#include <vector>
#include <memory>


/// @file
Expand All @@ -23,20 +24,26 @@ namespace pcpp
class PcapLiveDeviceList
{
private:
std::vector<PcapLiveDevice*> m_LiveDeviceList;
std::vector<std::unique_ptr<PcapLiveDevice>> m_LiveDeviceList;
// Vector of raw device pointers to keep the signature of getPcapLiveDevicesList, as it returns a reference.
std::vector<PcapLiveDevice*> m_LiveDeviceListView;

std::vector<IPv4Address> m_DnsServers;

// private c'tor
PcapLiveDeviceList();
// private copy c'tor
PcapLiveDeviceList( const PcapLiveDeviceList& other );
PcapLiveDeviceList& operator=(const PcapLiveDeviceList& other);

void init();

void setDnsServers();

void updateLiveDeviceListView() const;
public:
PcapLiveDeviceList(const PcapLiveDeviceList&) = delete;
PcapLiveDeviceList(PcapLiveDeviceList&&) noexcept = delete;
PcapLiveDeviceList& operator=(const PcapLiveDeviceList&) = delete;
PcapLiveDeviceList& operator=(PcapLiveDeviceList&&) noexcept = delete;

/**
* The access method to the singleton
* @return The singleton instance of this class
Expand All @@ -50,7 +57,7 @@ namespace pcpp
/**
* @return A vector containing pointers to all live devices currently installed on the machine
*/
const std::vector<PcapLiveDevice*>& getPcapLiveDevicesList() const { return m_LiveDeviceList; }
const std::vector<PcapLiveDevice*>& getPcapLiveDevicesList() const { return m_LiveDeviceListView; };

/**
* Get a pointer to the live device by its IP address. IP address can be both IPv4 or IPv6
Expand Down Expand Up @@ -110,9 +117,6 @@ namespace pcpp
* Reset the live device list and DNS server list, meaning clear and refetch them
*/
void reset();

// d'tor
~PcapLiveDeviceList();
};

} // namespace pcpp
57 changes: 25 additions & 32 deletions Pcap++/src/PcapLiveDeviceList.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,6 @@ PcapLiveDeviceList::PcapLiveDeviceList()
init();
}

PcapLiveDeviceList::~PcapLiveDeviceList()
{
for(const auto &devIter : m_LiveDeviceList)
{
delete devIter;
}
}

void PcapLiveDeviceList::init()
{
std::unique_ptr<pcap_if_t, internal::PcapFreeAllDevsDeleter> interfaceList;
Expand All @@ -57,13 +49,18 @@ void PcapLiveDeviceList::init()
for (pcap_if_t* currInterface = interfaceList.get(); currInterface != nullptr; currInterface = currInterface->next)
{
#if defined(_WIN32)
PcapLiveDevice* dev = new WinPcapLiveDevice(currInterface, true, true, true);
auto dev = std::unique_ptr<PcapLiveDevice>(new WinPcapLiveDevice(currInterface, true, true, true));
#else //__linux__, __APPLE__, __FreeBSD__
PcapLiveDevice* dev = new PcapLiveDevice(currInterface, true, true, true);
auto dev = std::unique_ptr<PcapLiveDevice>(new PcapLiveDevice(currInterface, true, true, true));
#endif
m_LiveDeviceList.insert(m_LiveDeviceList.end(), dev);
m_LiveDeviceList.push_back(std::move(dev));
}

m_LiveDeviceListView.resize(m_LiveDeviceList.size());
// Full update of all elements of the view vector to synchronize them with the main vector.
std::transform(m_LiveDeviceList.begin(), m_LiveDeviceList.end(), m_LiveDeviceListView.begin(),
[](const std::unique_ptr<PcapLiveDevice>& ptr) { return ptr.get(); });

setDnsServers();
}

Expand Down Expand Up @@ -268,19 +265,19 @@ PcapLiveDevice* PcapLiveDeviceList::getPcapLiveDeviceByIp(const IPAddress& ipAdd
PcapLiveDevice* PcapLiveDeviceList::getPcapLiveDeviceByIp(const IPv4Address& ipAddr) const
{
PCPP_LOG_DEBUG("Searching all live devices...");
for(const auto &devIter : m_LiveDeviceList)
for(const auto& devicePtr : m_LiveDeviceList)
{
PCPP_LOG_DEBUG("Searching device '" << devIter->m_Name << "'. Searching all addresses...");
for(const auto &addrIter : devIter->m_Addresses)
PCPP_LOG_DEBUG("Searching device '" << devicePtr->m_Name << "'. Searching all addresses...");
for(const auto& addressInfo : devicePtr->m_Addresses)
{
if (Logger::getInstance().isDebugEnabled(PcapLogModuleLiveDevice) && addrIter.addr != nullptr)
if (Logger::getInstance().isDebugEnabled(PcapLogModuleLiveDevice) && addressInfo.addr != nullptr)
{
std::array<char, INET6_ADDRSTRLEN> addrAsString;
internal::sockaddr2string(addrIter.addr, addrAsString.data(), addrAsString.size());
internal::sockaddr2string(addressInfo.addr, addrAsString.data(), addrAsString.size());
PCPP_LOG_DEBUG("Searching address " << addrAsString.data());
}

in_addr* currAddr = internal::try_sockaddr2in_addr(addrIter.addr);
in_addr* currAddr = internal::try_sockaddr2in_addr(addressInfo.addr);
if (currAddr == nullptr)
{
PCPP_LOG_DEBUG("Address is nullptr");
Expand All @@ -290,7 +287,7 @@ PcapLiveDevice* PcapLiveDeviceList::getPcapLiveDeviceByIp(const IPv4Address& ipA
if (*currAddr == ipAddr)
{
PCPP_LOG_DEBUG("Found matched address!");
return devIter;
return devicePtr.get();
}
}
}
Expand All @@ -301,19 +298,19 @@ PcapLiveDevice* PcapLiveDeviceList::getPcapLiveDeviceByIp(const IPv4Address& ipA
PcapLiveDevice* PcapLiveDeviceList::getPcapLiveDeviceByIp(const IPv6Address& ip6Addr) const
{
PCPP_LOG_DEBUG("Searching all live devices...");
for(const auto &devIter : m_LiveDeviceList)
for(const auto& devicePtr : m_LiveDeviceList)
{
PCPP_LOG_DEBUG("Searching device '" << devIter->m_Name << "'. Searching all addresses...");
for(const auto &addrIter : devIter->m_Addresses)
PCPP_LOG_DEBUG("Searching device '" << devicePtr->m_Name << "'. Searching all addresses...");
for(const auto& addressInfo : devicePtr->m_Addresses)
{
if (Logger::getInstance().isDebugEnabled(PcapLogModuleLiveDevice) && addrIter.addr != nullptr)
if (Logger::getInstance().isDebugEnabled(PcapLogModuleLiveDevice) && addressInfo.addr != nullptr)
{
std::array<char, INET6_ADDRSTRLEN> addrAsString;
internal::sockaddr2string(addrIter.addr, addrAsString.data(), addrAsString.size());
internal::sockaddr2string(addressInfo.addr, addrAsString.data(), addrAsString.size());
PCPP_LOG_DEBUG("Searching address " << addrAsString.data());
}

in6_addr* currAddr = internal::try_sockaddr2in6_addr(addrIter.addr);
in6_addr* currAddr = internal::try_sockaddr2in6_addr(addressInfo.addr);
if (currAddr == nullptr)
{
PCPP_LOG_DEBUG("Address is nullptr");
Expand All @@ -323,7 +320,7 @@ PcapLiveDevice* PcapLiveDeviceList::getPcapLiveDeviceByIp(const IPv6Address& ip6
if (*currAddr == ip6Addr)
{
PCPP_LOG_DEBUG("Found matched address!");
return devIter;
return devicePtr.get();
}
}
}
Expand Down Expand Up @@ -353,15 +350,15 @@ PcapLiveDevice* PcapLiveDeviceList::getPcapLiveDeviceByName(const std::string& n
{
PCPP_LOG_DEBUG("Searching all live devices...");
auto devIter = std::find_if(m_LiveDeviceList.begin(), m_LiveDeviceList.end(),
[&name](const PcapLiveDevice *dev) { return dev->getName() == name; });
[&name](const std::unique_ptr<PcapLiveDevice>& dev) { return dev->getName() == name; });

if (devIter == m_LiveDeviceList.end())
{
PCPP_LOG_DEBUG("Found no live device with name '" << name << "'");
return nullptr;
}

return *devIter;
return devIter->get();
}

PcapLiveDevice* PcapLiveDeviceList::getPcapLiveDeviceByIpOrName(const std::string& ipOrName) const
Expand All @@ -384,11 +381,7 @@ PcapLiveDeviceList* PcapLiveDeviceList::clone()

void PcapLiveDeviceList::reset()
{
for(auto devIter : m_LiveDeviceList)
{
delete devIter;
}

m_LiveDeviceListView.clear();
m_LiveDeviceList.clear();
m_DnsServers.clear();

Expand Down
Loading