Skip to content

Commit f38d7f8

Browse files
util: Replaced bitset with Fixed_bitmap, inversed bits, allow 65535 as eph port, fixed wrap around issue
1 parent 9bfbb43 commit f38d7f8

3 files changed

Lines changed: 31 additions & 19 deletions

File tree

api/net/inet_common.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ namespace net {
161161
static constexpr uint16_t USER_START {1024};
162162
static constexpr uint16_t USER_END {49151};
163163
static constexpr uint16_t DYNAMIC_START {49152};
164-
static constexpr uint16_t DYNAMIC_END {65535}; // 65535 should never be assigned
164+
static constexpr uint16_t DYNAMIC_END {65535};
165165

166166
static constexpr bool is_dynamic(const uint16_t port) noexcept
167167
{ return port > USER_END; }

api/net/port_util.hpp

Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
#define NET_PORT_UTIL_HPP
2121

2222
#include "inet_common.hpp"
23-
#include <bitset>
23+
#include <util/fixed_bitmap.hpp>
2424

2525
namespace 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
*/
3537
class Port_util {
3638
public:
@@ -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

108112
private:
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

test/net/unit/port_util_test.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,14 +39,18 @@ CASE("Generating ephemeral port throws when all are bound")
3939
{
4040
net::Port_util util;
4141

42+
EXPECT(util.has_free_ephemeral() == true);
43+
4244
// Bind all
4345
for(auto i = 0; i < (net::port_ranges::DYNAMIC_END - net::port_ranges::DYNAMIC_START); ++i)
4446
util.bind(util.get_next_ephemeral());
4547

48+
EXPECT(util.has_free_ephemeral() == false);
49+
4650
EXPECT_THROWS_AS(util.get_next_ephemeral(), net::Port_error);
4751
}
4852

49-
CASE("[.expectedfailure] Generating ephemeral handles wrap around")
53+
CASE("Generating ephemeral handles wrap around")
5054
{
5155
net::Port_util util;
5256

0 commit comments

Comments
 (0)