2020#define NET_PORT_UTIL_HPP
2121
2222#include " inet_common.hpp"
23- #include < bitset >
23+ #include < util/fixed_bitmap.hpp >
2424
2525namespace net {
2626
@@ -30,7 +30,9 @@ struct Port_error : public std::runtime_error {
3030};
3131
3232/* *
33- * @brief Class for port utility.
33+ * @brief Class for handling a full range of network ports.
34+ * Generates ephemeral ports and track what ports are bound or not.
35+ * 1 means free, 0 means bound (occupied)
3436 */
3537class Port_util {
3638public:
@@ -40,10 +42,15 @@ class Port_util {
4042 */
4143 Port_util ()
4244 : ports(),
45+ eph_view{ // set the ephemeral view to be between 49152-65535
46+ ports.data () + port_ranges::DYNAMIC_START,
47+ (port_ranges::DYNAMIC_END - port_ranges::DYNAMIC_START + 1 ) / sizeof (MemBitmap::word)
48+ },
4349 ephemeral_ (net::new_ephemeral_port()),
4450 eph_count (0 )
4551 {
46- ports.set (port_ranges::DYNAMIC_END);
52+ // all ports are free
53+ ports.set_all ();
4754 }
4855
4956 /* *
@@ -65,8 +72,7 @@ class Port_util {
6572 */
6673 void bind (const uint16_t port) noexcept
6774 {
68- Expects (port < port_ranges::DYNAMIC_END);
69- ports.set (port);
75+ ports.reset (port);
7076
7177 if (port_ranges::is_dynamic (port)) ++eph_count;
7278 }
@@ -78,8 +84,7 @@ class Port_util {
7884 */
7985 void unbind (const uint16_t port) noexcept
8086 {
81- Expects (port < port_ranges::DYNAMIC_END);
82- ports.reset (port);
87+ ports.set (port);
8388
8489 if (port_ranges::is_dynamic (port)) --eph_count;
8590 }
@@ -93,8 +98,7 @@ class Port_util {
9398 */
9499 bool is_bound (const uint16_t port) const noexcept
95100 {
96- Expects (port < port_ranges::DYNAMIC_END);
97- return ports[port];
101+ return !ports[port];
98102 }
99103
100104 /* *
@@ -106,9 +110,10 @@ class Port_util {
106110 { return eph_count < (port_ranges::DYNAMIC_END - port_ranges::DYNAMIC_START); }
107111
108112private:
109- std::bitset<65536 > ports;
110- uint16_t ephemeral_;
111- uint16_t eph_count;
113+ Fixed_bitmap<65536 > ports;
114+ MemBitmap eph_view;
115+ uint16_t ephemeral_;
116+ uint16_t eph_count;
112117
113118 /* *
114119 * @brief Increment the ephemeral port by one.
@@ -122,13 +127,16 @@ class Port_util {
122127 ephemeral_++;
123128
124129 // wrap around to dynamic start if end
125- if (UNLIKELY (ephemeral_ == port_ranges::DYNAMIC_END ))
130+ if (UNLIKELY (ephemeral_ == 0 ))
126131 ephemeral_ = port_ranges::DYNAMIC_START;
127132
128- // TODO: Avoid wrap around, increment ephemeral to next free port.
129- // while(is_bound(ephemeral_)) ++ephemeral_; // worst case is like 16k iterations :D
130- // need a solution that checks each word of the subset (the dynamic range)
131- // FIXME: this may happen...
133+ if (UNLIKELY ( is_bound (ephemeral_) ))
134+ {
135+ auto i = eph_view.first_set ();
136+ Ensures (i != -1 && " Did not found a free ephemeral even tho has_free_ephemeral() == true..." );
137+ ephemeral_ = port_ranges::DYNAMIC_START + i;
138+ }
139+
132140 Expects (not is_bound (ephemeral_) && " Generated ephemeral port is already bound. Please fix me!" );
133141 }
134142}; // < class Port_util
0 commit comments