6#include <boost/url.hpp>
7#include <boost/algorithm/string.hpp>
8#include <boost/asio.hpp>
9#include <boost/chrono.hpp>
10#include <boost/thread.hpp>
12#include "e2sarError.hpp"
14using namespace boost::asio;
15using namespace std::string_literals;
22 const u_int16_t DATAPLANE_PORT = 19522;
33 enum class TokenType {
34 admin, instance, session
61 std::string adminToken;
63 std::string instanceToken;
65 std::string sessionToken;
67 std::string sessionId;
70 ip::address dataAddrv4;
71 ip::address dataAddrv6;
85 EjfatURI(
const std::string &uri, TokenType tt=TokenType::admin,
bool preferV6=
false);
118 if (!instanceToken.empty())
119 return instanceToken;
121 return E2SARErrorInfo{E2SARErrorc::ParameterNotAvailable,
"Instance token not available"s};
127 if (!sessionToken.empty())
130 return E2SARErrorInfo{E2SARErrorc::ParameterNotAvailable,
"Session token not available"s};
136 if (!adminToken.empty())
139 return E2SARErrorInfo{E2SARErrorc::ParameterNotAvailable,
"Admin token not available"s};
175 if (a.first.is_v4()) {
176 dataAddrv4 = a.first;
180 dataAddrv6 = a.first;
204 inline const result<std::pair<ip::address, u_int16_t>>
get_cpAddr()
const
206 return std::pair<ip::address, u_int16_t>(cpAddr, cpPort);
210 inline const result<std::pair<std::string, u_int16_t>>
get_cpHost()
const
213 return std::pair<std::string, u_int16_t>(cpHost, cpPort);
215 return E2SARErrorInfo{E2SARErrorc::ParameterNotAvailable,
"Control plane hostname not available"s};
233 return haveDatav4 || haveDatav6;
243 inline const result<std::pair<ip::address, u_int16_t>>
get_dataAddrv4() const noexcept
246 return std::pair<ip::address, u_int16_t>(dataAddrv4, dataPort);
247 return E2SARErrorInfo{E2SARErrorc::ParameterNotAvailable,
"Data plane address not available"s};
251 inline const result<std::pair<ip::address, u_int16_t>>
get_dataAddrv6() const noexcept
254 return std::pair<ip::address, u_int16_t>(dataAddrv6, dataPort);
255 return E2SARErrorInfo{E2SARErrorc::ParameterNotAvailable,
"Data plane address not available"s};
259 inline const result<std::pair<ip::address, u_int16_t>>
get_syncAddr() const noexcept
262 return std::pair<ip::address, u_int16_t>(syncAddr, syncPort);
263 return E2SARErrorInfo{E2SARErrorc::ParameterNotAvailable,
"Sync address not available"s};
269 operator std::string()
const;
271 const std::string to_string(TokenType tt = TokenType::admin)
const;
278 static inline result<EjfatURI>
getFromEnv(
const std::string &envVar =
"EJFAT_URI"s,
279 TokenType tt=TokenType::admin,
bool preferV6=
false) noexcept
281 const char *envStr = std::getenv(envVar.c_str());
282 if (envStr !=
nullptr)
286 return EjfatURI(envStr, tt, preferV6);
290 return E2SARErrorInfo{E2SARErrorc::CaughtException,
"Unable to parse EJFAT_URI from environment variable: "s +
static_cast<std::string
>(e)};
293 return E2SARErrorInfo{E2SARErrorc::Undefined,
"Environment variable "s + envVar +
" not defined."s};
302 TokenType tt=TokenType::admin,
bool preferV6=
false) noexcept
306 return EjfatURI(uriStr, tt, preferV6);
310 return E2SARErrorInfo{E2SARErrorc::CaughtException,
"Unable to parse URI from string: "s +
static_cast<std::string
>(e)};
319 static inline result<EjfatURI>
getFromFile(
const std::string &fileName =
"/tmp/ejfat_uri"s,
320 TokenType tt=TokenType::admin,
bool preferV6=
false) noexcept
322 if (!fileName.empty())
324 std::ifstream file(fileName);
328 if (std::getline(file, uriLine))
333 return EjfatURI(uriLine, tt, preferV6);
337 return E2SARErrorInfo{E2SARErrorc::CaughtException,
"Unable to parse URI: "s +
static_cast<std::string
>(e)};
341 return E2SARErrorInfo{E2SARErrorc::Undefined,
"Unable to parse URI."s};
344 return E2SARErrorInfo{E2SARErrorc::NotFound,
"Unable to find file "s + fileName};
358 static inline const result<ip::address> string_to_ip(const std::
string &addr) noexcept
367 ip::make_address(addr.substr(1, addr.length() - 2));
373 return ip::make_address(addr.substr(1, addr.length() - 2));
376 return ip::make_address(addr);
378 catch (boost::system::system_error &e)
380 return E2SARErrorInfo{E2SARErrorc::ParameterError,
"Unable to convert IP address from "s + addr};
387 static inline const result<u_int16_t> string_to_port(
const std::string &port_string)
noexcept
391 u_int16_t port = std::stoi(port_string);
392 if (port < 1024 || port > 65535)
395 return E2SARErrorInfo{E2SARErrorc::OutOfRange,
"Port value "s + port_string +
" is out of range"s};
399 catch (
const std::exception &e)
401 return E2SARErrorInfo{E2SARErrorc::ParameterError,
"Unable to convert "s + port_string +
" to integer"s};
408 static inline const result<std::pair<ip::address, u_int16_t>> string_tuple_to_ip_and_port(
const std::string &t)
noexcept
411 auto const pos = t.find_last_of(
"]:");
414 if ((pos == std::string::npos) || (t[pos] ==
']'))
416 auto r1 = string_to_ip(t);
418 return std::pair<ip::address, u_int16_t>(r1.value(), 0);
420 return E2SARErrorInfo{E2SARErrorc::ParameterError,
"Unable to convert "s + t +
" to ip address and port"s};
424 auto r1 = string_to_ip(t.substr(0, pos));
425 auto r2 = string_to_port(t.substr(pos + 1));
427 return std::pair<ip::address, int>(r1.value(), r2.value());
428 return E2SARErrorInfo{E2SARErrorc::ParameterError,
"Unable to convert "s + t +
" to ip address and port"s};
437 static inline result<std::vector<ip::address>> resolveHost(
const std::string &host_name)
noexcept
440 std::vector<ip::address> addresses;
441 boost::asio::io_service io_service;
445 ip::udp::resolver resolver(io_service);
446 ip::udp::resolver::query query(host_name,
"443");
447 ip::udp::resolver::iterator iter = resolver.resolve(query);
448 ip::udp::resolver::iterator end;
452 ip::udp::endpoint endpoint = *iter++;
453 addresses.push_back(endpoint.address());
460 return E2SARErrorInfo{E2SARErrorc::NotFound,
"Unable to convert "s + host_name +
" to ip address"s};
466 std::size_t operator()(
const std::pair<u_int64_t, u_int16_t>& p)
const {
467 u_int64_t hash1 = p.first;
468 u_int64_t tmp = p.second;
469 u_int64_t hash2 = tmp | tmp << 16 | tmp << 32 | tmp << 48;
470 return hash1 ^ hash2;
475 bool operator()(
const std::pair<u_int64_t, u_int16_t>& lhs,
const std::pair<u_int64_t, u_int16_t>& rhs)
const {
476 return lhs.first == rhs.first && lhs.second == rhs.second;
488 static inline float clockEntropyTest(
int totalTests = 5000,
int sleepMs = 1)
490 std::vector<int_least64_t> points;
491 std::vector<int> bins(256, 0);
493 for (
int i = 0; i < totalTests; i++)
495 auto now = boost::chrono::system_clock::now();
496 auto nowUsec = boost::chrono::duration_cast<boost::chrono::microseconds>(now.time_since_epoch()).count();
497 bins[nowUsec & 0xff]++;
498 auto until = now + boost::chrono::milliseconds(sleepMs);
499 boost::this_thread::sleep_until(until);
504 for (
size_t i = 0; i < bins.size(); i++)
506 float prob =
static_cast<float>(bins[i])/(totalTests*1.0);
507 entropy += prob * std::log(prob);
511 entropy *= -1.0/std::log(2);
515 template<
typename Container>
516 std::string concatWithSeparator(
const Container& c,
const std::string& sep=
","s)
518 typename Container::const_iterator it = c.begin();
530 inline void busyWaitUsecs(
const boost::chrono::steady_clock::time_point &tp, int64_t usecs)
535 if (boost::chrono::duration_cast<boost::chrono::microseconds>(boost::chrono::high_resolution_clock::now()
536 - tp).count() > usecs)
541 using OptimizationsWord = u_int16_t;
558 inline static OptimizationsWord toWord(Code o)
560 return 1 <<
static_cast<int>(o);
562 inline static std::string toString(Code o)
566 case Code::none:
return "none"s;
567 case Code::sendmmsg:
return "sendmmsg";
568 case Code::liburing_recv:
return "liburing_recv";
569 case Code::liburing_send:
return "liburing_send";
574 inline static Code fromString(
const std::string& opt)
578 else if (opt ==
"sendmmsg"s)
579 return Code::sendmmsg;
580 else if (opt ==
"liburing_recv"s)
581 return Code::liburing_recv;
582 else if (opt ==
"liburing_send"s)
583 return Code::liburing_send;
584 return Code::unknown;
589 const static std::vector<std::string> availableAsStrings()
noexcept;
594 const static OptimizationsWord availableAsWord()
noexcept;
600 static result<int> select(std::vector<std::string>& opt)
noexcept;
606 static result <int> select(std::vector<Code> &opt)
noexcept;
611 const static std::vector<std::string> selectedAsStrings()
noexcept;
616 const static OptimizationsWord selectedAsWord()
noexcept;
621 const static std::vector<Code> selectedAsList()
noexcept;
626 const static bool isSelected(Code o)
noexcept;
629 static const std::vector<Optimizations::Code> available;
632 OptimizationsWord selected_optimizations;
Definition e2sarError.hpp:61
Definition e2sarUtil.hpp:31
EjfatURI(const std::string &uri, TokenType tt=TokenType::admin, bool preferV6=false)
Definition e2sarUtil.cpp:188
const result< std::pair< ip::address, u_int16_t > > get_syncAddr() const noexcept
Definition e2sarUtil.hpp:259
const result< std::string > get_SessionToken() const
Definition e2sarUtil.hpp:125
void set_lbName(const std::string &n)
Definition e2sarUtil.hpp:143
~EjfatURI()
Definition e2sarUtil.hpp:88
bool get_useTls() const
Definition e2sarUtil.hpp:98
const bool has_dataAddrv4() const
Definition e2sarUtil.hpp:219
void set_InstanceToken(const std::string &t)
Definition e2sarUtil.hpp:104
const result< std::pair< ip::address, u_int16_t > > get_dataAddrv6() const noexcept
Definition e2sarUtil.hpp:251
const std::string get_lbId() const
Definition e2sarUtil.hpp:192
const result< std::pair< std::string, u_int16_t > > get_cpHost() const
Definition e2sarUtil.hpp:210
static result< EjfatURI > getFromEnv(const std::string &envVar="EJFAT_URI"s, TokenType tt=TokenType::admin, bool preferV6=false) noexcept
Definition e2sarUtil.hpp:278
const bool has_syncAddr() const
Definition e2sarUtil.hpp:237
void set_sessionId(const std::string &i)
Definition e2sarUtil.hpp:155
const result< std::string > get_AdminToken() const
Definition e2sarUtil.hpp:134
const result< std::pair< ip::address, u_int16_t > > get_cpAddr() const
Definition e2sarUtil.hpp:204
const std::string get_sessionId() const
Definition e2sarUtil.hpp:198
void set_dataAddr(const std::pair< ip::address, u_int16_t > &a)
Definition e2sarUtil.hpp:173
const result< std::string > get_InstanceToken() const
Definition e2sarUtil.hpp:116
static result< EjfatURI > getFromFile(const std::string &fileName="/tmp/ejfat_uri"s, TokenType tt=TokenType::admin, bool preferV6=false) noexcept
Definition e2sarUtil.hpp:319
void set_SessionToken(const std::string &t)
Definition e2sarUtil.hpp:110
const bool has_dataAddrv6() const
Definition e2sarUtil.hpp:225
static result< EjfatURI > getFromString(const std::string &uriStr, TokenType tt=TokenType::admin, bool preferV6=false) noexcept
Definition e2sarUtil.hpp:301
result< std::vector< ip::address > > getDataplaneLocalAddresses(bool v6=false) noexcept
Definition e2sarUtil.cpp:399
const bool has_dataAddr() const
Definition e2sarUtil.hpp:231
const result< std::pair< ip::address, u_int16_t > > get_dataAddrv4() const noexcept
Definition e2sarUtil.hpp:243
void set_syncAddr(const std::pair< ip::address, u_int16_t > &a)
Definition e2sarUtil.hpp:163
const std::string get_lbName() const
Definition e2sarUtil.hpp:186
void set_lbId(const std::string &i)
Definition e2sarUtil.hpp:149
Definition e2sarUtil.hpp:546
Definition e2sarError.hpp:41
Definition e2sarUtil.hpp:474
Definition e2sarUtil.hpp:465