Skip to content

Commit d304fc2

Browse files
committed
Top 10 ports - Introduce TopPorts class
1 parent 6532d55 commit d304fc2

File tree

1 file changed

+89
-0
lines changed

1 file changed

+89
-0
lines changed

input/topPorts.hpp

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
/**
2+
* \file topPorts.hpp
3+
* \brief Template class implementing the most popular ports.
4+
* \author Damir Zainullin <[email protected]>
5+
* \date 2024
6+
*/
7+
#pragma once
8+
9+
#include <array>
10+
#include <cmath>
11+
#include <cstdint>
12+
#include <functional>
13+
#include <limits>
14+
#include <queue>
15+
#include <unordered_map>
16+
#include <unordered_set>
17+
18+
namespace ipxp {
19+
/**
20+
* \brief Top ports counter.
21+
* \tparam TopPortsCount Number of the most popular ports to store.
22+
*/
23+
template<std::size_t TopPortsCount>
24+
class TopPorts {
25+
public:
26+
/**
27+
* \brief Insert a port into the top ports.
28+
* \param port Port to insert.
29+
*/
30+
void insert(uint16_t port) noexcept
31+
{
32+
m_port_frequencies[port]++;
33+
34+
if (m_ports_present.size() < TopPortsCount) {
35+
m_ports_present.insert(port);
36+
m_least_popuplar_top_port = find_least_popular_top_port();
37+
return;
38+
}
39+
40+
if (auto it = m_ports_present.find(port); it == m_ports_present.end()
41+
&& m_port_frequencies[port] > m_port_frequencies[m_least_popuplar_top_port]) {
42+
m_ports_present.erase(m_least_popuplar_top_port);
43+
m_least_popuplar_top_port = port;
44+
m_ports_present.insert(port);
45+
} else if (port == m_least_popuplar_top_port) {
46+
m_least_popuplar_top_port = find_least_popular_top_port();
47+
}
48+
}
49+
50+
/**
51+
* \brief Get the top ports.
52+
* \return Pair of the top ports array and their count.
53+
*/
54+
std::pair<std::array<std::pair<uint16_t, size_t>, TopPortsCount>, size_t>
55+
get_top_ports() const noexcept
56+
{
57+
std::array<std::pair<uint16_t, size_t>, TopPortsCount> res;
58+
std::transform(
59+
m_ports_present.begin(),
60+
m_ports_present.end(),
61+
res.begin(),
62+
[this](uint16_t port) { return std::make_pair(port, m_port_frequencies[port]); });
63+
std::sort(res.begin(), res.begin() + m_ports_present.size(), [] (const std::pair<uint16_t, size_t>& port1, const std::pair<uint16_t, size_t>& port2){ return port1.second > port2.second;});
64+
return {res, m_ports_present.size()};
65+
}
66+
67+
private:
68+
uint16_t find_least_popular_top_port() const noexcept
69+
{
70+
return *std::min_element(
71+
m_ports_present.begin(),
72+
m_ports_present.end(),
73+
[this](uint16_t port1, uint16_t port2) {
74+
return m_port_frequencies[port1] < m_port_frequencies[port2];
75+
});
76+
}
77+
78+
std::array<std::size_t, 65536> m_port_frequencies {};
79+
uint16_t m_least_popuplar_top_port {0};
80+
using PortFrequencyPair = std::pair<std::size_t, uint16_t>;
81+
std::priority_queue<
82+
std::pair<std::size_t, uint16_t>,
83+
std::vector<std::pair<std::size_t, uint16_t>>,
84+
std::greater<>>
85+
m_top_ports;
86+
std::unordered_set<uint16_t> m_ports_present;
87+
};
88+
89+
} // namespace ipxp

0 commit comments

Comments
 (0)