Xndp.h
- #pragma once
-
- #include
- #include
- #include
- #include
-
- namespace frp {
- namespace discover {
- /* X Network Discovery Protocol. */
- class Xndp : public IDisposable { /* Apply to P2P(peer-to-peer) is based on NAT/UDP put holes.*/
- #pragma pack(push,1)
- struct XndpPacket {
- Byte kf;
- UInt16 len; /* Packet size. */
- UInt16 checksum; /* Check sum. */
- UInt32 id;
- Byte cmd;
- };
- struct XndpRegisterEntryRequestPacket : XndpPacket {
- Byte type; /* frp::configuration::MappingType */
- UInt16 port;
- };
- struct XndpReisterReplyPacket : XndpPacket {
- Byte err;
- };
- struct XndpQueryEntryReplyPacket : XndpReisterReplyPacket {
- Byte type; /* frp::configuration::MappingType */
- UInt16 port;
- Byte af;
- UInt16 dst_port;
- Byte dst_addr[16];
- };
- typedef XndpRegisterEntryRequestPacket XndpQueryEntryRequestPacket;
- #pragma pack(pop)
- enum {
- XNDP_KF = 0x7E,
- XNDP_REGST_ENTRY = 0x2A, /* Registry entry. */
- XNDP_QUERY_ENTRY = 0x2E, /* Query entry. */
- XNDP_PUSH_MESSAGE = 0x2C,
- XNDP_ENTRY_TIMEOUT = 10000,
- XNDP_CALLER_TIMEOUT = 3000,
- XNDP_ERROR_SUCCESS = 0,
- XNDP_ERROR_INVALID_ENTRY_TYPE = 1,
- XNDP_ERROR_INVALID_ENTRY_PORT = 2,
- XNDP_ERROR_NOT_FOUND_ENTRY = 3,
- };
- typedef boost::asio::ip::udp::endpoint XNDP_ENDPOINT;
- struct XndpEntry {
- XNDP_ENDPOINT destinationEP; /* Mapped to a public address. */
- UInt64 last; /* Last activity times. */
- Byte type;
- UInt16 port;
- };
- /* s mode. */
- typedef std::shared_ptr
XndpEntryPtr; - typedef std::unordered_map
XndpEntry2LevelTable; - typedef std::unordered_map
XndpEntry1LevelTable; -
- public:
- typedef std::function<void(
- UInt32 id,
- Byte* buffer,
- int length,
- boost::asio::ip::udp::endpoint& remoteEP)> MessageEventHandler;
- MessageEventHandler MessageEvent;
-
- public:
- Xndp(const std::shared_ptr
& hosting) noexcept; - Xndp(const std::shared_ptr
& hosting, int bindport) noexcept; -
- public:
- boost::asio::ip::udp::endpoint GetLocalEndPoint() noexcept;
- boost::asio::ip::udp::socket& GetSocket() noexcept;
- std::shared_ptr
GetContext() noexcept ; - std::shared_ptr
GetHosting() noexcept ; -
- public:
- virtual bool IsAvailable() noexcept;
- virtual bool Open() noexcept;
- void Close() noexcept;
- virtual void Dispose() noexcept override;
-
- public:
- typedef std::function<void(bool)> RegisterAsyncCallback;
- typedef std::function<void(bool, boost::asio::ip::udp::endpoint&)> QueryAsyncCallback;
- virtual bool RegisterAsync(
- frp::configuration::MappingType mapping_type,
- int mapping_port,
- RegisterAsyncCallback callback,
- const boost::asio::ip::udp::endpoint& destinationEP) noexcept;
- virtual bool QueryAsync(
- frp::configuration::MappingType mapping_type,
- int mapping_port,
- QueryAsyncCallback callback,
- const boost::asio::ip::udp::endpoint& destinationEP) noexcept;
- virtual bool PushAsync(
- UInt32 id,
- const void* message,
- const int message_size,
- const boost::asio::ip::udp::endpoint& destinationEP) noexcept;
- static boost::asio::ip::udp::endpoint ToEndPoint(const std::string host, int port) noexcept;
-
- protected:
- virtual void Timeout(UInt64 now) noexcept;
-
- private:
- bool SetTimeout() noexcept;
- int PacketSerializeMini(XndpPacket* packet) noexcept;
- bool OnXndpProc() noexcept;
- bool OnRegisterEntryServer(XndpPacket* packet, const boost::asio::ip::udp::endpoint& remoteEP) noexcept;
- bool OnQueryEntryServer(XndpPacket* packet, const boost::asio::ip::udp::endpoint& remoteEP) noexcept;
- bool ReplyToDestination(XndpPacket* packet, const boost::asio::ip::udp::endpoint& remoteEP) noexcept;
- void ProcessEntryTimeout(UInt64 now) noexcept;
-
- private:
- /* c mode. */
- struct XndpCallerContext { /* rpc, stop wait ARQ. */
- std::shared_ptr
message; - int message_size;
- int retry_count;
- UInt64 initial_time;
- XNDP_ENDPOINT destination;
- UInt32 id;
- QueryAsyncCallback query_ac;
- RegisterAsyncCallback register_ac;
- };
- typedef std::unordered_map
XndpCallerContextTable; - bool OnRegisterEntryClient(XndpPacket* packet) noexcept;
- bool OnQueryEntryClient(XndpPacket* packet) noexcept;
- bool PopCallerContext(UInt32 id, XndpCallerContext& context) noexcept;
- void ProcessCallerTimeout(UInt64 now) noexcept;
- template<typename TCallback>
- bool RequireArgument(
- frp::configuration::MappingType mapping_type,
- int mapping_port,
- TCallback& callback,
- const boost::asio::ip::udp::endpoint& destinationEP) noexcept;
- UInt32 NewId() noexcept;
- template<typename TXndpRequestPacket>
- bool AddXndpCaller(
- Byte command,
- Byte mapping_type,
- int mapping_port,
- const QueryAsyncCallback& qac,
- const RegisterAsyncCallback& rac,
- const boost::asio::ip::udp::endpoint& destinationEP) noexcept;
- void OnTimeoutError(XndpCallerContext& context) noexcept;
-
- private:
- std::atomic<bool> disposed_;
- std::atomic
aid_; - int bindport_;
- std::shared_ptr
hosting_; - std::shared_ptr
context_; - std::shared_ptr
buffer_; - boost::asio::ip::udp::socket socket_;
- boost::asio::ip::udp::endpoint localEP_;
- boost::asio::ip::udp::endpoint endpoint_;
- boost::asio::deadline_timer timeout_;
- XndpEntry1LevelTable entries_;
- XndpCallerContextTable callers_;
- };
- }
- }
Xndp.cpp
- #include
- #include
- #include
- #include
- #include
-
- using frp::configuration::MappingType;
- using frp::net::AddressFamily;
- using frp::net::Ipep;
- using frp::net::IPEndPoint;
- using frp::net::Socket;
- using frp::collections::Dictionary;
-
- namespace frp {
- namespace discover {
- Xndp::Xndp(const std::shared_ptr
& hosting) noexcept - : Xndp(hosting, IPEndPoint::MinPort) {
-
- }
-
- Xndp::Xndp(const std::shared_ptr
& hosting, int bindport) noexcept - : disposed_(false)
- , aid_(0)
- , bindport_(bindport)
- , hosting_(hosting)
- , context_(hosting->GetContext())
- , buffer_(hosting->GetBuffer())
- , socket_(*context_)
- , timeout_(*context_) {
- if (bindport < IPEndPoint::MinPort || bindport > IPEndPoint::MaxPort) {
- bindport = IPEndPoint::MinPort;
- }
-
- if (!Socket::OpenSocket(socket_, boost::asio::ip::address_v6::any(), bindport)) {
- bindport = IPEndPoint::MinPort;
- }
- else {
- bindport = Socket::LocalPort(socket_);
- }
-
- boost::system::error_code ec;
- if (bindport) {
- boost::asio::ip::udp::endpoint localEP = socket_.local_endpoint(ec);
- if (!ec) {
- localEP_ = localEP;
- }
- }
- }
-
- boost::asio::ip::udp::endpoint Xndp::GetLocalEndPoint() noexcept {
- return localEP_;
- }
-
- std::shared_ptr
Xndp::GetContext() noexcept { - return context_;
- }
-
- std::shared_ptr
Xndp::GetHosting() noexcept { - return hosting_;
- }
-
- bool Xndp::IsAvailable() noexcept {
- return !disposed_ && socket_.is_open();
- }
-
- void Xndp::Close() noexcept {
- Dispose();
- }
-
- void Xndp::Dispose() noexcept {
- if (!disposed_.exchange(true)) {
- /* Releases the socket and timer held. */
- Socket::Closesocket(socket_);
- frp::threading::Hosting::Cancel(timeout_);
-
- /* Releases all managed table member data. */
- entries_.clear();
- Dictionary::ReleaseAllPairs(callers_,
- [this](XndpCallerContext& context) noexcept {
- OnTimeoutError(context);
- });
-
- /* Deletes the message event listener bound to the current class instance object. */
- MessageEvent = MessageEventHandler();
- }
- }
-
- bool Xndp::Open() noexcept {
- if (!IsAvailable()) {
- return false;
- }
-
- return SetTimeout() && OnXndpProc();
- }
-
- bool Xndp::SetTimeout() noexcept {
- if (disposed_) {
- return false;
- }
-
- std::shared_ptr
reference = GetReference(); - timeout_.expires_from_now(boost::posix_time::milliseconds(1000));
- timeout_.async_wait(
- [reference, this](const boost::system::error_code& ec) noexcept {
- if (!ec) {
- Timeout(hosting_->CurrentMillisec());
- SetTimeout();
- }
- });
- return true;
- }
-
- void Xndp::Timeout(UInt64 now) noexcept {
- ProcessEntryTimeout(now);
- ProcessCallerTimeout(now);
- }
-
- void Xndp::ProcessEntryTimeout(UInt64 now) noexcept {
- XndpEntry1LevelTable::iterator tail = entries_.begin();
- XndpEntry1LevelTable::iterator endl = entries_.end();
- if (tail != endl) {
- std::vector
releases; - for (; tail != endl; tail++) {
- XndpEntry2LevelTable::iterator tail2 = tail->second.begin();
- XndpEntry2LevelTable::iterator endl2 = tail->second.end();
- for (; tail2 != endl2; tail2++) {
- XndpEntryPtr& entry = tail2->second;
- if (entry->last > now) {
- releases.push_back(std::move(entry));
- }
- else {
- UInt64 diff = now - entry->last;
- if (diff >= XNDP_ENTRY_TIMEOUT) {
- releases.push_back(std::move(entry));
- }
- }
- }
- }
-
- for (std::size_t index = 0, length = releases.size(); index < length; index++) {
- XndpEntryPtr& entry = releases[index];
- if (entry) {
- Dictionary::TryRemove2Layer(entries_, entry->type, entry->port);
- }
- }
- }
- }
-
- void Xndp::ProcessCallerTimeout(UInt64 now) noexcept {
- XndpCallerContextTable::iterator tail = callers_.begin();
- XndpCallerContextTable::iterator endl = callers_.end();
- if (tail != endl) {
- std::vector
releases; - for (; tail != endl; tail++) {
- XndpCallerContext& context = tail->second;
- if (!IsAvailable()) {
- releases.push_back(context.id);
- continue;
- }
-
- UInt64 initial_time = context.initial_time;
- if (initial_time > now) {
- releases.push_back(context.id);
- continue;
- }
-
- UInt64 diff = now - initial_time;
- if (diff >= XNDP_CALLER_TIMEOUT) {
- releases.push_back(context.id);
- continue;
- }
-
- UInt32 retry_count = ++context.retry_count;
- if (retry_count >= 3) {
- releases.push_back(context.id);
- continue;
- }
-
- boost::system::error_code ec;
- socket_.send_to(boost::asio::buffer(context.message.get(), context.message_size), context.destination, 0, ec);
- }
-
- for (std::size_t index = 0, length = releases.size(); index < length; index++) {
- XndpCallerContext context;
- if (Dictionary::TryRemove(callers_, releases[index], context)) {
- OnTimeoutError(context);
- }
- }
- }
- }
-
- void Xndp::OnTimeoutError(XndpCallerContext& context) noexcept {
- if (context.register_ac) {
- context.register_ac(false);
- }
-
- if (context.query_ac) {
- boost::asio::ip::udp::endpoint nanoEP;
- context.query_ac(false, nanoEP);
- }
- }
-
- bool Xndp::OnXndpProc() noexcept {
- if (!IsAvailable()) {
- return false;
- }
-
- std::shared_ptr
reference = GetReference(); - socket_.async_receive_from(boost::asio::buffer(buffer_.get(), frp::threading::Hosting::BufferSize), endpoint_,
- [reference, this](const boost::system::error_code& ec, std::size_t sz) noexcept {
- /* If it is an Xndp packet, the packet is processed; otherwise, the packet is displayed. */
- int length = std::max<int>(ec ? -1 : sz, -1);
- if (length >= sizeof(XndpPacket)) {
- XndpPacket* packet = (XndpPacket*)buffer_.get();
- do {
- /* The key frame is inconsistent. */
- if (packet->kf != XNDP_KF) {
- break;
- }
-
- /* Check frame length validity. */
- int len = ntohs(packet->len);
- if (len != length) {
- break;
- }
-
- /* Check packet checksum. */
- int checksum = frp::messages::inet_chksum(packet, len);
- if (checksum != 0) {
- break;
- }
-
- /* This is a malicious external attack. */
- if (packet->cmd != XNDP_REGST_ENTRY && packet->cmd != XNDP_QUERY_ENTRY && packet->cmd != XNDP_PUSH_MESSAGE) {
- break;
- }
-
- /* Converts data from network byte order to local byte order. */
- packet->len = len;
- packet->id = ntohl(packet->id);
-
- /* The action of processing the request. */
- switch (packet->cmd) {
- case XNDP_REGST_ENTRY:
- if (bindport_) {
- OnRegisterEntryServer(packet, endpoint_);
- }
- else {
- OnRegisterEntryClient(packet);
- }
- break;
- case XNDP_QUERY_ENTRY:
- if (bindport_) {
- OnQueryEntryServer(packet, endpoint_);
- }
- else {
- OnQueryEntryClient(packet);
- }
- break;
- case XNDP_PUSH_MESSAGE:
- /* If the packets are not Xndp packets, they belong to other protocols that pass through the Intranet. */
- int message_size = len - sizeof(XndpPacket);
- if (message_size > 0) {
- MessageEventHandler handler = MessageEvent;
- if (handler) {
- handler(packet->id, (Byte*)(packet + 1), message_size, endpoint_);
- }
- }
- break;
- };
- } while (0);
- }
- OnXndpProc();
- });
- return true;
- }
-
- bool Xndp::OnRegisterEntryServer(XndpPacket* packet, const boost::asio::ip::udp::endpoint& remoteEP) noexcept {
- XndpRegisterEntryRequestPacket* request = (XndpRegisterEntryRequestPacket*)packet;
- if (request->len < sizeof(XndpRegisterEntryRequestPacket)) {
- return false;
- }
- else {
- request->port = ntohs(request->port);
- }
-
- XndpReisterReplyPacket reply;
- reply.checksum = 0;
- reply.id = packet->id;
- reply.cmd = packet->cmd;
- reply.len = sizeof(reply);
- reply.err = XNDP_ERROR_SUCCESS;
-
- if (request->type < MappingType::MappingType_TCP || request->type >= MappingType::MappingType_MaxType) {
- reply.err = XNDP_ERROR_INVALID_ENTRY_TYPE;
- }
- elif(request->port <= IPEndPoint::MinPort || request->port > IPEndPoint::MaxPort) {
- reply.err = XNDP_ERROR_INVALID_ENTRY_PORT;
- }
- else {
- XndpEntryPtr& entry = entries_[request->type][request->port];
- if (!entry) {
- entry = make_shared_object
(); - }
-
- entry->destinationEP = IPEndPoint::ToEndPoint
(IPEndPoint::V6ToV4(IPEndPoint::ToEndPoint(remoteEP))); - entry->port = request->port;
- entry->type = request->type;
- entry->last = hosting_->CurrentMillisec();
- }
- return ReplyToDestination(&reply, remoteEP);
- }
-
- bool Xndp::OnQueryEntryServer(XndpPacket* packet, const boost::asio::ip::udp::endpoint& remoteEP) noexcept {
- XndpQueryEntryRequestPacket* request = (XndpQueryEntryRequestPacket*)packet;
- if (request->len < sizeof(XndpQueryEntryRequestPacket)) {
- return false;
- }
- else {
- request->port = ntohs(request->port);
- }
-
- XndpQueryEntryReplyPacket reply;
- reply.checksum = 0;
- reply.id = packet->id;
- reply.cmd = packet->cmd;
- reply.len = sizeof(reply);
- reply.err = XNDP_ERROR_SUCCESS;
- reply.type = IPEndPoint::MinPort;
- reply.port = MappingType::MappingType_TCP;
-
- if (request->type < MappingType::MappingType_TCP || request->type >= MappingType::MappingType_MaxType) {
- reply.err = XNDP_ERROR_INVALID_ENTRY_TYPE;
- }
- elif(request->port <= IPEndPoint::MinPort || request->port > IPEndPoint::MaxPort) {
- reply.err = XNDP_ERROR_INVALID_ENTRY_PORT;
- }
- else {
- XndpEntryPtr entry;
- if (!Dictionary::TryGetValue2Layer(entries_, request->type, request->port, entry) || !entry) {
- reply.err = XNDP_ERROR_NOT_FOUND_ENTRY;
- }
- else {
- boost::asio::ip::address address = entry->destinationEP.address();
- if (address.is_v4()) {
- boost::asio::ip::address_v4::bytes_type address_bytes = address.to_v4().to_bytes();
- memcpy(reply.dst_addr, address_bytes.data(), address_bytes.size());
- reply.af = AddressFamily::InterNetwork;
- }
- else {
- boost::asio::ip::address_v6::bytes_type address_bytes = address.to_v6().to_bytes();
- memcpy(reply.dst_addr, address_bytes.data(), address_bytes.size());
- reply.af = AddressFamily::InterNetworkV6;
- }
- reply.type = entry->type;
- reply.port = htons(entry->port);
- reply.dst_port = htons(entry->destinationEP.port());
- }
- }
- return ReplyToDestination(&reply, remoteEP);
- }
-
- template<typename TCallback>
- bool Xndp::RequireArgument(
- frp::configuration::MappingType mapping_type,
- int mapping_port,
- TCallback& callback,
- const boost::asio::ip::udp::endpoint& destinationEP) noexcept {
- typedef frp::net::IPEndPoint IPEndPoint;
- typedef frp::configuration::MappingType MappingType;
-
- if (!IsAvailable()) {
- return false;
- }
- elif(!callback) {
- return false;
- }
- elif(mapping_type < MappingType::MappingType_TCP || mapping_type >= MappingType::MappingType_MaxType) {
- return false;
- }
- elif(mapping_port <= IPEndPoint::MinPort || mapping_port > IPEndPoint::MaxPort) {
- return false;
- }
-
- boost::asio::ip::address address = destinationEP.address();
- if (address.is_multicast() || address.is_unspecified()) {
- return false;
- }
- return true;
- }
-
- template<typename TXndpRequestPacket>
- bool Xndp::AddXndpCaller(
- Byte command,
- Byte mapping_type,
- int mapping_port,
- const QueryAsyncCallback& qac,
- const RegisterAsyncCallback& rac,
- const boost::asio::ip::udp::endpoint& destinationEP) noexcept {
- typedef frp::net::IPEndPoint IPEndPoint;
-
- int message_size = sizeof(TXndpRequestPacket);
- std::shared_ptr
message = make_shared_alloc(message_size); - if (!message) {
- return false;
- }
-
- UInt32 id = NewId();
- TXndpRequestPacket* request = (TXndpRequestPacket*)message.get();
- request->checksum = 0;
- request->cmd = command;
- request->id = id;
- request->len = message_size;
- request->type = mapping_type;
- request->port = htons(mapping_port);
- if (PacketSerializeMini(request) < 1) {
- return false;
- }
-
- XNDP_ENDPOINT remoteEP = IPEndPoint::ToEndPoint
(IPEndPoint::V4ToV6(IPEndPoint::ToEndPoint(destinationEP))); - XndpCallerContext& context = callers_[id];
- context.id = id;
- context.destination = remoteEP;
- context.initial_time = hosting_->CurrentMillisec();
- context.query_ac = qac;
- context.register_ac = rac;
- context.retry_count = 0;
- context.message = message;
- context.message_size = message_size;
-
- boost::system::error_code ec;
- socket_.send_to(boost::asio::buffer(request, message_size), remoteEP, 0, ec);
- return ec ? false : true;
- }
-
- int Xndp::PacketSerializeMini(XndpPacket* packet) noexcept {
- int length = packet->len;
- if (length < sizeof(XndpPacket)) {
- return 0;
- }
-
- packet->kf = XNDP_KF;
- packet->checksum = 0;
- packet->id = htonl(packet->id);
- packet->len = htons(length);
-
- UInt16 checksum = frp::messages::inet_chksum(packet, length);
- if (checksum == 0) {
- checksum = 0xffff;
- }
- packet->checksum = htons(checksum);
- return length;
- }
-
- bool Xndp::ReplyToDestination(XndpPacket* packet, const boost::asio::ip::udp::endpoint& remoteEP) noexcept {
- if (!IsAvailable()) {
- return false;
- }
-
- int length = PacketSerializeMini(packet);
- if (length < 1) {
- return false;
- }
-
- boost::system::error_code ec;
- socket_.send_to(boost::asio::buffer(packet, length), remoteEP, 0, ec);
- return ec ? false : true;
- }
-
- bool Xndp::RegisterAsync(MappingType mapping_type, int mapping_port, RegisterAsyncCallback callback, const boost::asio::ip::udp::endpoint& destinationEP) noexcept {
- if (!RequireArgument(mapping_type, mapping_port, callback, destinationEP)) {
- return false;
- }
-
- return AddXndpCaller
(XNDP_REGST_ENTRY, - mapping_type, mapping_port, NULL, callback, destinationEP);
- }
-
- bool Xndp::QueryAsync(MappingType mapping_type, int mapping_port, QueryAsyncCallback callback, const boost::asio::ip::udp::endpoint& destinationEP) noexcept {
- if (!RequireArgument(mapping_type, mapping_port, callback, destinationEP)) {
- return false;
- }
-
- return AddXndpCaller
(XNDP_QUERY_ENTRY, - mapping_type, mapping_port, callback, NULL, destinationEP);
- }
-
- bool Xndp::PushAsync(UInt32 id, const void* message, const int message_size, const boost::asio::ip::udp::endpoint& destinationEP) noexcept {
- if (!message || message_size < 1) {
- return false;
- }
-
- int chunk_size = sizeof(XndpPacket) + message_size;
- std::shared_ptr
chunk = make_shared_alloc(chunk_size); - if (!message) {
- return false;
- }
-
- XndpPacket* packet = (XndpPacket*)chunk.get();
- packet->checksum = 0;
- packet->cmd = XNDP_PUSH_MESSAGE;
- packet->id = id;
- packet->len = chunk_size;
- memcpy(packet + 1, message, message_size);
-
- if (PacketSerializeMini(packet) < 1) {
- return false;
- }
-
- boost::system::error_code ec;
- socket_.send_to(boost::asio::buffer(packet, chunk_size), destinationEP, 0, ec);
- return ec ? false : true;
- }
-
- UInt32 Xndp::NewId() noexcept {
- for (;;) {
- int id = aid_++;
- if (!id) {
- continue;
- }
-
- if (!Dictionary::ContainsKey(callers_, id)) {
- return id;
- }
- }
- }
-
- boost::asio::ip::udp::socket& Xndp::GetSocket() noexcept {
- return socket_;
- }
-
- bool Xndp::PopCallerContext(UInt32 id, XndpCallerContext& context) noexcept {
- return Dictionary::TryRemove(callers_, id, context);
- }
-
- bool Xndp::OnRegisterEntryClient(XndpPacket* packet) noexcept {
- XndpReisterReplyPacket* reply = (XndpReisterReplyPacket*)packet;
- if (reply->len < sizeof(XndpReisterReplyPacket)) {
- return false;
- }
-
- XndpCallerContext caller;
- if (!PopCallerContext(reply->id, caller)) {
- return false;
- }
-
- caller.register_ac(reply->err == XNDP_ERROR_SUCCESS);
- return true;
- }
-
- bool Xndp::OnQueryEntryClient(XndpPacket* packet) noexcept {
- XndpQueryEntryReplyPacket* reply = (XndpQueryEntryReplyPacket*)packet;
- if (reply->len < sizeof(XndpQueryEntryReplyPacket)) {
- return false;
- }
-
- XndpCallerContext caller;
- if (!PopCallerContext(reply->id, caller)) {
- return false;
- }
-
- if (reply->err != XNDP_ERROR_SUCCESS) {
- boost::asio::ip::udp::endpoint noneEP;
- caller.query_ac(false, noneEP);
- }
- else {
- boost::asio::ip::address address;
- if (reply->af == AddressFamily::InterNetwork) {
- address = boost::asio::ip::address_v4(*(boost::asio::ip::address_v4::bytes_type*)reply->dst_addr);
- }
- else {
- address = boost::asio::ip::address_v6(*(boost::asio::ip::address_v6::bytes_type*)reply->dst_addr);
- }
-
- boost::asio::ip::udp::endpoint destinationEP(address, ntohs(reply->dst_port));
- caller.query_ac(true, destinationEP);
- }
- return true;
- }
-
- boost::asio::ip::udp::endpoint Xndp::ToEndPoint(const std::string host, int port) noexcept {
- return IPEndPoint::ToEndPoint
(Ipep::GetEndPoint(host, port)); - }
- }
- }