18 #include <hicn/transport/portability/c_portability.h>
19 #include <hicn/transport/utils/branch_prediction.h>
20 #include <hicn/transport/utils/log.h>
21 #include <hicn/transport/utils/string_utils.h>
28 #include "forwarder_interface.h"
30 #define RETRY_INTERVAL 300
34 static constexpr
char server_header[] =
"server";
35 static constexpr
char prefix_header[] =
"prefix";
36 static constexpr
char port_header[] =
"port";
38 using OnForwarderConfiguredCallback = std::function<void(
bool)>;
42 using ListenerRetrievedCallback = std::function<void(std::error_code)>;
44 template <
typename Callback>
46 : forwarder_interface_(io_service),
47 resolver_(io_service),
50 hicn_listen_port_(~0),
51 listener_retrieved_callback_(std::forward<Callback>(callback)) {}
56 forwarder_interface_.close();
59 void tryToConnectToForwarder() {
60 doTryToConnectToForwarder(std::make_error_code(std::errc(0)));
63 void doTryToConnectToForwarder(std::error_code ec) {
66 int ret = forwarder_interface_.connectToForwarder();
71 <<
"Could not connect to local forwarder. Retrying.";
73 timer_.expires_from_now(std::chrono::milliseconds(RETRY_INTERVAL));
74 timer_.async_wait(std::bind(&ForwarderConfig::doTryToConnectToForwarder,
75 this, std::placeholders::_1));
79 doGetMainListener(std::make_error_code(std::errc(0)));
83 <<
"Timer for re-trying forwarder connection canceled.";
87 void doGetMainListener(std::error_code ec) {
90 int ret = forwarder_interface_.getMainListenerPort();
95 <<
"Could not retrieve main listener port from the forwarder. "
98 timer_.expires_from_now(std::chrono::milliseconds(RETRY_INTERVAL));
99 timer_.async_wait(std::bind(&ForwarderConfig::doGetMainListener,
this,
100 std::placeholders::_1));
104 hicn_listen_port_ = uint16_t(ret);
105 listener_retrieved_callback_(std::make_error_code(std::errc(0)));
109 <<
"Timer for retrieving main hicn listener canceled.";
113 template <
typename Callback>
114 TRANSPORT_ALWAYS_INLINE
bool parseHicnHeader(std::string& header,
115 Callback&& callback) {
116 std::stringstream ss(header);
118 std::string port_string;
122 getline(ss, substr,
',');
124 if (TRANSPORT_EXPECT_FALSE(substr.empty())) {
129 auto it = std::find_if(substr.begin(), substr.end(),
130 [](
int ch) { return ch ==
'='; });
131 if (it != std::end(substr)) {
132 auto key = std::string(substr.begin(), it);
133 auto value = std::string(it + 1, substr.end());
135 if (key == server_header) {
136 ret->remote_addr = value;
137 }
else if (key == prefix_header) {
138 auto it = std::find_if(value.begin(), value.end(),
139 [](
int ch) { return ch ==
'/'; });
141 if (it != std::end(value)) {
142 ret->route_addr = std::string(value.begin(), it);
143 ret->route_len = std::stoul(std::string(it + 1, value.end()));
147 }
else if (key == port_header) {
148 ret->remote_port = std::stoul(value);
161 resolver_.resolve({ret->remote_addr, port_string,
162 asio::ip::resolver_query_base::numeric_service});
164 #if ((ASIO_VERSION / 100 % 1000) < 12)
165 asio::ip::udp::resolver::iterator end;
169 for (
auto it = results.begin(); it != results.end(); it++) {
171 if (it->endpoint().address().is_v4()) {
173 ret->remote_addr = it->endpoint().address().to_string();
174 ret->family = AF_INET;
175 std::string _prefix = ret->route_addr;
176 forwarder_interface_.createFaceAndRoute(
177 RouteInfoPtr(ret), [callback = std::forward<Callback>(callback),
178 configured_prefix = std::move(_prefix)](
179 uint32_t route_id,
bool result) {
180 callback(result, configured_prefix);
185 #if ((ASIO_VERSION / 100 % 1000) < 12)
195 asio::ip::udp::resolver resolver_;
196 std::uint32_t retx_count_;
197 asio::steady_timer timer_;
198 uint16_t hicn_listen_port_;
199 ListenerRetrievedCallback listener_retrieved_callback_;