Skip to content

Commit 8fc29bf

Browse files
committed
Use error codes in port binding routine ("Break on exception" finally becomes usable), move implementation to cpp file, reduce code duplication
1 parent c4c9220 commit 8fc29bf

File tree

2 files changed

+55
-60
lines changed

2 files changed

+55
-60
lines changed

src/socket_utils.cpp

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#include "socket_utils.h"
2-
#include <boost/endian/conversion.hpp>
32
#include "common.h"
4-
3+
#include <boost/endian/conversion.hpp>
4+
#include <boost/system/system_error.hpp>
55

66
// === Implementation of the socket utils ===
77

@@ -17,3 +17,42 @@ double lsl::measure_endian_performance() {
1717
lslboost::endian::endian_reverse_inplace(data);
1818
return k;
1919
}
20+
21+
template <typename Socket, typename Protocol>
22+
uint16_t bind_port_in_range_(Socket &sock, Protocol protocol) {
23+
const api_config *cfg = api_config::get_instance();
24+
lslboost::system::error_code ec;
25+
for (uint16_t port = cfg->base_port(), e = port + cfg->port_range(); port < e; port++) {
26+
sock.bind(typename Protocol::endpoint(protocol, port), ec);
27+
if (ec == lslboost::system::errc::address_in_use) continue;
28+
if (!ec) return port;
29+
}
30+
if (cfg->allow_random_ports()) {
31+
for (int k = 0; k < 100; ++k) {
32+
uint16_t port = 1025 + rand() % 64000;
33+
sock.bind(typename Protocol::endpoint(protocol, port), ec);
34+
if (ec == lslboost::system::errc::address_in_use) continue;
35+
if (!ec) return port;
36+
}
37+
}
38+
return 0;
39+
}
40+
41+
const std::string all_ports_bound_msg(
42+
"All local ports were found occupied. You may have more open outlets on this machine than your "
43+
"PortRange setting allows (see "
44+
"https://labstreaminglayer.readthedocs.io/info/network-connectivity.html"
45+
") or you have a problem with your network configuration.");
46+
47+
uint16_t lsl::bind_port_in_range(udp::socket &acc, udp protocol) {
48+
uint16_t port = bind_port_in_range_(acc, protocol);
49+
if (!port) throw std::runtime_error(all_ports_bound_msg);
50+
return port;
51+
}
52+
53+
uint16_t lsl::bind_and_listen_to_port_in_range(tcp::acceptor &sock, tcp protocol, int backlog) {
54+
uint16_t port = bind_port_in_range_(sock, protocol);
55+
if (!port) throw std::runtime_error(all_ports_bound_msg);
56+
sock.listen(backlog);
57+
return port;
58+
}

src/socket_utils.h

Lines changed: 14 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -2,69 +2,25 @@
22
#define SOCKET_UTILS_H
33

44
#include "api_config.h"
5-
#include <boost/system/system_error.hpp>
65
#include <boost/asio/detail/chrono.hpp>
6+
#include <boost/asio/ip/tcp.hpp>
7+
#include <boost/asio/ip/udp.hpp>
8+
9+
using namespace lslboost::asio::ip;
710

811
namespace lsl {
9-
inline lslboost::asio::chrono::milliseconds timeout_sec(double timeout_seconds) {
10-
return lslboost::asio::chrono::milliseconds(static_cast<unsigned int>(1000*timeout_seconds));
11-
}
12+
inline lslboost::asio::chrono::milliseconds timeout_sec(double timeout_seconds) {
13+
return lslboost::asio::chrono::milliseconds(static_cast<unsigned int>(1000 * timeout_seconds));
14+
}
1215

13-
/// Bind a socket (or acceptor) to a free port in the configured port range or throw an error otherwise.
14-
template <class Socket, class Protocol>
15-
uint16_t bind_port_in_range(Socket &sock, Protocol protocol) {
16-
for (int k=0,e=api_config::get_instance()->port_range(); k<e; k++) {
17-
try {
18-
sock.bind(typename Protocol::endpoint(protocol,(uint16_t)(k + api_config::get_instance()->base_port())));
19-
return k + api_config::get_instance()->base_port();
20-
} catch (lslboost::system::system_error &) { /* port occupied */ }
21-
}
22-
if (api_config::get_instance()->allow_random_ports()) {
23-
for (int k=0; k < 100; ++k) {
24-
uint16_t port = 1025 + rand()%64000;
25-
try {
26-
sock.bind(typename Protocol::endpoint(protocol,port));
27-
return port;
28-
} catch (lslboost::system::system_error &) { /* port occupied */ }
29-
}
30-
}
31-
throw std::runtime_error(
32-
"All local ports were found occupied. You may have more open outlets on this machine "
33-
"than your PortRange setting allows (see "
34-
"https://labstreaminglayer.readthedocs.io/info/network-connectivity.html) or you "
35-
"have a problem with your network configuration.");
36-
}
16+
/// Bind a socket to a free port in the configured port range or throw an error otherwise.
17+
uint16_t bind_port_in_range(udp::socket &sock, udp protocol);
3718

38-
/// Bind to and listen at a socket (or acceptor) on a free port in the configured port range or throw an error otherwise.
39-
template <class Socket, class Protocol>
40-
uint16_t bind_and_listen_to_port_in_range(Socket &sock, Protocol protocol, int backlog) {
41-
for (int k=0,e=api_config::get_instance()->port_range(); k<e; k++) {
42-
try {
43-
sock.bind(typename Protocol::endpoint(protocol,(uint16_t)(k + api_config::get_instance()->base_port())));
44-
sock.listen(backlog);
45-
return k + api_config::get_instance()->base_port();
46-
} catch (lslboost::system::system_error &) { /* port occupied */ }
47-
}
48-
if (api_config::get_instance()->allow_random_ports()) {
49-
for (int k = 0; k < 100; ++k) {
50-
uint16_t port = 1025 + rand()%64000;
51-
try {
52-
sock.bind(typename Protocol::endpoint(protocol,port));
53-
sock.listen(backlog);
54-
return port;
55-
} catch (lslboost::system::system_error &) { /* port occupied */ }
56-
}
57-
}
58-
throw std::runtime_error(
59-
"All local ports were found occupied. You may have more open outlets on this machine "
60-
"than your PortRange setting allows (see "
61-
"https://labstreaminglayer.readthedocs.io/info/network-connectivity.html) or you "
62-
"have a problem with your network configuration.");
63-
}
19+
/// Bind and listen to an acceptor on a free port in the configured port range or throw an error.
20+
uint16_t bind_and_listen_to_port_in_range(tcp::acceptor &acc, tcp protocol, int backlog);
6421

65-
/// Measure the endian conversion performance of this machine.
66-
double measure_endian_performance();
67-
}
22+
/// Measure the endian conversion performance of this machine.
23+
double measure_endian_performance();
24+
} // namespace lsl
6825

6926
#endif
70-

0 commit comments

Comments
 (0)