• C/C++ P2P自定义发现协议 Xndp。


    Xndp.h

    1. #pragma once
    2. #include
    3. #include
    4. #include
    5. #include
    6. namespace frp {
    7. namespace discover {
    8. /* X Network Discovery Protocol. */
    9. class Xndp : public IDisposable { /* Apply to P2P(peer-to-peer) is based on NAT/UDP put holes.*/
    10. #pragma pack(push,1)
    11. struct XndpPacket {
    12. Byte kf;
    13. UInt16 len; /* Packet size. */
    14. UInt16 checksum; /* Check sum. */
    15. UInt32 id;
    16. Byte cmd;
    17. };
    18. struct XndpRegisterEntryRequestPacket : XndpPacket {
    19. Byte type; /* frp::configuration::MappingType */
    20. UInt16 port;
    21. };
    22. struct XndpReisterReplyPacket : XndpPacket {
    23. Byte err;
    24. };
    25. struct XndpQueryEntryReplyPacket : XndpReisterReplyPacket {
    26. Byte type; /* frp::configuration::MappingType */
    27. UInt16 port;
    28. Byte af;
    29. UInt16 dst_port;
    30. Byte dst_addr[16];
    31. };
    32. typedef XndpRegisterEntryRequestPacket XndpQueryEntryRequestPacket;
    33. #pragma pack(pop)
    34. enum {
    35. XNDP_KF = 0x7E,
    36. XNDP_REGST_ENTRY = 0x2A, /* Registry entry. */
    37. XNDP_QUERY_ENTRY = 0x2E, /* Query entry. */
    38. XNDP_PUSH_MESSAGE = 0x2C,
    39. XNDP_ENTRY_TIMEOUT = 10000,
    40. XNDP_CALLER_TIMEOUT = 3000,
    41. XNDP_ERROR_SUCCESS = 0,
    42. XNDP_ERROR_INVALID_ENTRY_TYPE = 1,
    43. XNDP_ERROR_INVALID_ENTRY_PORT = 2,
    44. XNDP_ERROR_NOT_FOUND_ENTRY = 3,
    45. };
    46. typedef boost::asio::ip::udp::endpoint XNDP_ENDPOINT;
    47. struct XndpEntry {
    48. XNDP_ENDPOINT destinationEP; /* Mapped to a public address. */
    49. UInt64 last; /* Last activity times. */
    50. Byte type;
    51. UInt16 port;
    52. };
    53. /* s mode. */
    54. typedef std::shared_ptr XndpEntryPtr;
    55. typedef std::unordered_map XndpEntry2LevelTable;
    56. typedef std::unordered_map XndpEntry1LevelTable;
    57. public:
    58. typedef std::function<void(
    59. UInt32 id,
    60. Byte* buffer,
    61. int length,
    62. boost::asio::ip::udp::endpoint& remoteEP)> MessageEventHandler;
    63. MessageEventHandler MessageEvent;
    64. public:
    65. Xndp(const std::shared_ptr& hosting) noexcept;
    66. Xndp(const std::shared_ptr& hosting, int bindport) noexcept;
    67. public:
    68. boost::asio::ip::udp::endpoint GetLocalEndPoint() noexcept;
    69. boost::asio::ip::udp::socket& GetSocket() noexcept;
    70. std::shared_ptr GetContext() noexcept;
    71. std::shared_ptr GetHosting() noexcept;
    72. public:
    73. virtual bool IsAvailable() noexcept;
    74. virtual bool Open() noexcept;
    75. void Close() noexcept;
    76. virtual void Dispose() noexcept override;
    77. public:
    78. typedef std::function<void(bool)> RegisterAsyncCallback;
    79. typedef std::function<void(bool, boost::asio::ip::udp::endpoint&)> QueryAsyncCallback;
    80. virtual bool RegisterAsync(
    81. frp::configuration::MappingType mapping_type,
    82. int mapping_port,
    83. RegisterAsyncCallback callback,
    84. const boost::asio::ip::udp::endpoint& destinationEP) noexcept;
    85. virtual bool QueryAsync(
    86. frp::configuration::MappingType mapping_type,
    87. int mapping_port,
    88. QueryAsyncCallback callback,
    89. const boost::asio::ip::udp::endpoint& destinationEP) noexcept;
    90. virtual bool PushAsync(
    91. UInt32 id,
    92. const void* message,
    93. const int message_size,
    94. const boost::asio::ip::udp::endpoint& destinationEP) noexcept;
    95. static boost::asio::ip::udp::endpoint ToEndPoint(const std::string host, int port) noexcept;
    96. protected:
    97. virtual void Timeout(UInt64 now) noexcept;
    98. private:
    99. bool SetTimeout() noexcept;
    100. int PacketSerializeMini(XndpPacket* packet) noexcept;
    101. bool OnXndpProc() noexcept;
    102. bool OnRegisterEntryServer(XndpPacket* packet, const boost::asio::ip::udp::endpoint& remoteEP) noexcept;
    103. bool OnQueryEntryServer(XndpPacket* packet, const boost::asio::ip::udp::endpoint& remoteEP) noexcept;
    104. bool ReplyToDestination(XndpPacket* packet, const boost::asio::ip::udp::endpoint& remoteEP) noexcept;
    105. void ProcessEntryTimeout(UInt64 now) noexcept;
    106. private:
    107. /* c mode. */
    108. struct XndpCallerContext { /* rpc, stop wait ARQ. */
    109. std::shared_ptr message;
    110. int message_size;
    111. int retry_count;
    112. UInt64 initial_time;
    113. XNDP_ENDPOINT destination;
    114. UInt32 id;
    115. QueryAsyncCallback query_ac;
    116. RegisterAsyncCallback register_ac;
    117. };
    118. typedef std::unordered_map XndpCallerContextTable;
    119. bool OnRegisterEntryClient(XndpPacket* packet) noexcept;
    120. bool OnQueryEntryClient(XndpPacket* packet) noexcept;
    121. bool PopCallerContext(UInt32 id, XndpCallerContext& context) noexcept;
    122. void ProcessCallerTimeout(UInt64 now) noexcept;
    123. template<typename TCallback>
    124. bool RequireArgument(
    125. frp::configuration::MappingType mapping_type,
    126. int mapping_port,
    127. TCallback& callback,
    128. const boost::asio::ip::udp::endpoint& destinationEP) noexcept;
    129. UInt32 NewId() noexcept;
    130. template<typename TXndpRequestPacket>
    131. bool AddXndpCaller(
    132. Byte command,
    133. Byte mapping_type,
    134. int mapping_port,
    135. const QueryAsyncCallback& qac,
    136. const RegisterAsyncCallback& rac,
    137. const boost::asio::ip::udp::endpoint& destinationEP) noexcept;
    138. void OnTimeoutError(XndpCallerContext& context) noexcept;
    139. private:
    140. std::atomic<bool> disposed_;
    141. std::atomic aid_;
    142. int bindport_;
    143. std::shared_ptr hosting_;
    144. std::shared_ptr context_;
    145. std::shared_ptr buffer_;
    146. boost::asio::ip::udp::socket socket_;
    147. boost::asio::ip::udp::endpoint localEP_;
    148. boost::asio::ip::udp::endpoint endpoint_;
    149. boost::asio::deadline_timer timeout_;
    150. XndpEntry1LevelTable entries_;
    151. XndpCallerContextTable callers_;
    152. };
    153. }
    154. }

    Xndp.cpp

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. using frp::configuration::MappingType;
    7. using frp::net::AddressFamily;
    8. using frp::net::Ipep;
    9. using frp::net::IPEndPoint;
    10. using frp::net::Socket;
    11. using frp::collections::Dictionary;
    12. namespace frp {
    13. namespace discover {
    14. Xndp::Xndp(const std::shared_ptr& hosting) noexcept
    15. : Xndp(hosting, IPEndPoint::MinPort) {
    16. }
    17. Xndp::Xndp(const std::shared_ptr& hosting, int bindport) noexcept
    18. : disposed_(false)
    19. , aid_(0)
    20. , bindport_(bindport)
    21. , hosting_(hosting)
    22. , context_(hosting->GetContext())
    23. , buffer_(hosting->GetBuffer())
    24. , socket_(*context_)
    25. , timeout_(*context_) {
    26. if (bindport < IPEndPoint::MinPort || bindport > IPEndPoint::MaxPort) {
    27. bindport = IPEndPoint::MinPort;
    28. }
    29. if (!Socket::OpenSocket(socket_, boost::asio::ip::address_v6::any(), bindport)) {
    30. bindport = IPEndPoint::MinPort;
    31. }
    32. else {
    33. bindport = Socket::LocalPort(socket_);
    34. }
    35. boost::system::error_code ec;
    36. if (bindport) {
    37. boost::asio::ip::udp::endpoint localEP = socket_.local_endpoint(ec);
    38. if (!ec) {
    39. localEP_ = localEP;
    40. }
    41. }
    42. }
    43. boost::asio::ip::udp::endpoint Xndp::GetLocalEndPoint() noexcept {
    44. return localEP_;
    45. }
    46. std::shared_ptr Xndp::GetContext() noexcept {
    47. return context_;
    48. }
    49. std::shared_ptr Xndp::GetHosting() noexcept {
    50. return hosting_;
    51. }
    52. bool Xndp::IsAvailable() noexcept {
    53. return !disposed_ && socket_.is_open();
    54. }
    55. void Xndp::Close() noexcept {
    56. Dispose();
    57. }
    58. void Xndp::Dispose() noexcept {
    59. if (!disposed_.exchange(true)) {
    60. /* Releases the socket and timer held. */
    61. Socket::Closesocket(socket_);
    62. frp::threading::Hosting::Cancel(timeout_);
    63. /* Releases all managed table member data. */
    64. entries_.clear();
    65. Dictionary::ReleaseAllPairs(callers_,
    66. [this](XndpCallerContext& context) noexcept {
    67. OnTimeoutError(context);
    68. });
    69. /* Deletes the message event listener bound to the current class instance object. */
    70. MessageEvent = MessageEventHandler();
    71. }
    72. }
    73. bool Xndp::Open() noexcept {
    74. if (!IsAvailable()) {
    75. return false;
    76. }
    77. return SetTimeout() && OnXndpProc();
    78. }
    79. bool Xndp::SetTimeout() noexcept {
    80. if (disposed_) {
    81. return false;
    82. }
    83. std::shared_ptr reference = GetReference();
    84. timeout_.expires_from_now(boost::posix_time::milliseconds(1000));
    85. timeout_.async_wait(
    86. [reference, this](const boost::system::error_code& ec) noexcept {
    87. if (!ec) {
    88. Timeout(hosting_->CurrentMillisec());
    89. SetTimeout();
    90. }
    91. });
    92. return true;
    93. }
    94. void Xndp::Timeout(UInt64 now) noexcept {
    95. ProcessEntryTimeout(now);
    96. ProcessCallerTimeout(now);
    97. }
    98. void Xndp::ProcessEntryTimeout(UInt64 now) noexcept {
    99. XndpEntry1LevelTable::iterator tail = entries_.begin();
    100. XndpEntry1LevelTable::iterator endl = entries_.end();
    101. if (tail != endl) {
    102. std::vector releases;
    103. for (; tail != endl; tail++) {
    104. XndpEntry2LevelTable::iterator tail2 = tail->second.begin();
    105. XndpEntry2LevelTable::iterator endl2 = tail->second.end();
    106. for (; tail2 != endl2; tail2++) {
    107. XndpEntryPtr& entry = tail2->second;
    108. if (entry->last > now) {
    109. releases.push_back(std::move(entry));
    110. }
    111. else {
    112. UInt64 diff = now - entry->last;
    113. if (diff >= XNDP_ENTRY_TIMEOUT) {
    114. releases.push_back(std::move(entry));
    115. }
    116. }
    117. }
    118. }
    119. for (std::size_t index = 0, length = releases.size(); index < length; index++) {
    120. XndpEntryPtr& entry = releases[index];
    121. if (entry) {
    122. Dictionary::TryRemove2Layer(entries_, entry->type, entry->port);
    123. }
    124. }
    125. }
    126. }
    127. void Xndp::ProcessCallerTimeout(UInt64 now) noexcept {
    128. XndpCallerContextTable::iterator tail = callers_.begin();
    129. XndpCallerContextTable::iterator endl = callers_.end();
    130. if (tail != endl) {
    131. std::vector releases;
    132. for (; tail != endl; tail++) {
    133. XndpCallerContext& context = tail->second;
    134. if (!IsAvailable()) {
    135. releases.push_back(context.id);
    136. continue;
    137. }
    138. UInt64 initial_time = context.initial_time;
    139. if (initial_time > now) {
    140. releases.push_back(context.id);
    141. continue;
    142. }
    143. UInt64 diff = now - initial_time;
    144. if (diff >= XNDP_CALLER_TIMEOUT) {
    145. releases.push_back(context.id);
    146. continue;
    147. }
    148. UInt32 retry_count = ++context.retry_count;
    149. if (retry_count >= 3) {
    150. releases.push_back(context.id);
    151. continue;
    152. }
    153. boost::system::error_code ec;
    154. socket_.send_to(boost::asio::buffer(context.message.get(), context.message_size), context.destination, 0, ec);
    155. }
    156. for (std::size_t index = 0, length = releases.size(); index < length; index++) {
    157. XndpCallerContext context;
    158. if (Dictionary::TryRemove(callers_, releases[index], context)) {
    159. OnTimeoutError(context);
    160. }
    161. }
    162. }
    163. }
    164. void Xndp::OnTimeoutError(XndpCallerContext& context) noexcept {
    165. if (context.register_ac) {
    166. context.register_ac(false);
    167. }
    168. if (context.query_ac) {
    169. boost::asio::ip::udp::endpoint nanoEP;
    170. context.query_ac(false, nanoEP);
    171. }
    172. }
    173. bool Xndp::OnXndpProc() noexcept {
    174. if (!IsAvailable()) {
    175. return false;
    176. }
    177. std::shared_ptr reference = GetReference();
    178. socket_.async_receive_from(boost::asio::buffer(buffer_.get(), frp::threading::Hosting::BufferSize), endpoint_,
    179. [reference, this](const boost::system::error_code& ec, std::size_t sz) noexcept {
    180. /* If it is an Xndp packet, the packet is processed; otherwise, the packet is displayed. */
    181. int length = std::max<int>(ec ? -1 : sz, -1);
    182. if (length >= sizeof(XndpPacket)) {
    183. XndpPacket* packet = (XndpPacket*)buffer_.get();
    184. do {
    185. /* The key frame is inconsistent. */
    186. if (packet->kf != XNDP_KF) {
    187. break;
    188. }
    189. /* Check frame length validity. */
    190. int len = ntohs(packet->len);
    191. if (len != length) {
    192. break;
    193. }
    194. /* Check packet checksum. */
    195. int checksum = frp::messages::inet_chksum(packet, len);
    196. if (checksum != 0) {
    197. break;
    198. }
    199. /* This is a malicious external attack. */
    200. if (packet->cmd != XNDP_REGST_ENTRY && packet->cmd != XNDP_QUERY_ENTRY && packet->cmd != XNDP_PUSH_MESSAGE) {
    201. break;
    202. }
    203. /* Converts data from network byte order to local byte order. */
    204. packet->len = len;
    205. packet->id = ntohl(packet->id);
    206. /* The action of processing the request. */
    207. switch (packet->cmd) {
    208. case XNDP_REGST_ENTRY:
    209. if (bindport_) {
    210. OnRegisterEntryServer(packet, endpoint_);
    211. }
    212. else {
    213. OnRegisterEntryClient(packet);
    214. }
    215. break;
    216. case XNDP_QUERY_ENTRY:
    217. if (bindport_) {
    218. OnQueryEntryServer(packet, endpoint_);
    219. }
    220. else {
    221. OnQueryEntryClient(packet);
    222. }
    223. break;
    224. case XNDP_PUSH_MESSAGE:
    225. /* If the packets are not Xndp packets, they belong to other protocols that pass through the Intranet. */
    226. int message_size = len - sizeof(XndpPacket);
    227. if (message_size > 0) {
    228. MessageEventHandler handler = MessageEvent;
    229. if (handler) {
    230. handler(packet->id, (Byte*)(packet + 1), message_size, endpoint_);
    231. }
    232. }
    233. break;
    234. };
    235. } while (0);
    236. }
    237. OnXndpProc();
    238. });
    239. return true;
    240. }
    241. bool Xndp::OnRegisterEntryServer(XndpPacket* packet, const boost::asio::ip::udp::endpoint& remoteEP) noexcept {
    242. XndpRegisterEntryRequestPacket* request = (XndpRegisterEntryRequestPacket*)packet;
    243. if (request->len < sizeof(XndpRegisterEntryRequestPacket)) {
    244. return false;
    245. }
    246. else {
    247. request->port = ntohs(request->port);
    248. }
    249. XndpReisterReplyPacket reply;
    250. reply.checksum = 0;
    251. reply.id = packet->id;
    252. reply.cmd = packet->cmd;
    253. reply.len = sizeof(reply);
    254. reply.err = XNDP_ERROR_SUCCESS;
    255. if (request->type < MappingType::MappingType_TCP || request->type >= MappingType::MappingType_MaxType) {
    256. reply.err = XNDP_ERROR_INVALID_ENTRY_TYPE;
    257. }
    258. elif(request->port <= IPEndPoint::MinPort || request->port > IPEndPoint::MaxPort) {
    259. reply.err = XNDP_ERROR_INVALID_ENTRY_PORT;
    260. }
    261. else {
    262. XndpEntryPtr& entry = entries_[request->type][request->port];
    263. if (!entry) {
    264. entry = make_shared_object();
    265. }
    266. entry->destinationEP = IPEndPoint::ToEndPoint(IPEndPoint::V6ToV4(IPEndPoint::ToEndPoint(remoteEP)));
    267. entry->port = request->port;
    268. entry->type = request->type;
    269. entry->last = hosting_->CurrentMillisec();
    270. }
    271. return ReplyToDestination(&reply, remoteEP);
    272. }
    273. bool Xndp::OnQueryEntryServer(XndpPacket* packet, const boost::asio::ip::udp::endpoint& remoteEP) noexcept {
    274. XndpQueryEntryRequestPacket* request = (XndpQueryEntryRequestPacket*)packet;
    275. if (request->len < sizeof(XndpQueryEntryRequestPacket)) {
    276. return false;
    277. }
    278. else {
    279. request->port = ntohs(request->port);
    280. }
    281. XndpQueryEntryReplyPacket reply;
    282. reply.checksum = 0;
    283. reply.id = packet->id;
    284. reply.cmd = packet->cmd;
    285. reply.len = sizeof(reply);
    286. reply.err = XNDP_ERROR_SUCCESS;
    287. reply.type = IPEndPoint::MinPort;
    288. reply.port = MappingType::MappingType_TCP;
    289. if (request->type < MappingType::MappingType_TCP || request->type >= MappingType::MappingType_MaxType) {
    290. reply.err = XNDP_ERROR_INVALID_ENTRY_TYPE;
    291. }
    292. elif(request->port <= IPEndPoint::MinPort || request->port > IPEndPoint::MaxPort) {
    293. reply.err = XNDP_ERROR_INVALID_ENTRY_PORT;
    294. }
    295. else {
    296. XndpEntryPtr entry;
    297. if (!Dictionary::TryGetValue2Layer(entries_, request->type, request->port, entry) || !entry) {
    298. reply.err = XNDP_ERROR_NOT_FOUND_ENTRY;
    299. }
    300. else {
    301. boost::asio::ip::address address = entry->destinationEP.address();
    302. if (address.is_v4()) {
    303. boost::asio::ip::address_v4::bytes_type address_bytes = address.to_v4().to_bytes();
    304. memcpy(reply.dst_addr, address_bytes.data(), address_bytes.size());
    305. reply.af = AddressFamily::InterNetwork;
    306. }
    307. else {
    308. boost::asio::ip::address_v6::bytes_type address_bytes = address.to_v6().to_bytes();
    309. memcpy(reply.dst_addr, address_bytes.data(), address_bytes.size());
    310. reply.af = AddressFamily::InterNetworkV6;
    311. }
    312. reply.type = entry->type;
    313. reply.port = htons(entry->port);
    314. reply.dst_port = htons(entry->destinationEP.port());
    315. }
    316. }
    317. return ReplyToDestination(&reply, remoteEP);
    318. }
    319. template<typename TCallback>
    320. bool Xndp::RequireArgument(
    321. frp::configuration::MappingType mapping_type,
    322. int mapping_port,
    323. TCallback& callback,
    324. const boost::asio::ip::udp::endpoint& destinationEP) noexcept {
    325. typedef frp::net::IPEndPoint IPEndPoint;
    326. typedef frp::configuration::MappingType MappingType;
    327. if (!IsAvailable()) {
    328. return false;
    329. }
    330. elif(!callback) {
    331. return false;
    332. }
    333. elif(mapping_type < MappingType::MappingType_TCP || mapping_type >= MappingType::MappingType_MaxType) {
    334. return false;
    335. }
    336. elif(mapping_port <= IPEndPoint::MinPort || mapping_port > IPEndPoint::MaxPort) {
    337. return false;
    338. }
    339. boost::asio::ip::address address = destinationEP.address();
    340. if (address.is_multicast() || address.is_unspecified()) {
    341. return false;
    342. }
    343. return true;
    344. }
    345. template<typename TXndpRequestPacket>
    346. bool Xndp::AddXndpCaller(
    347. Byte command,
    348. Byte mapping_type,
    349. int mapping_port,
    350. const QueryAsyncCallback& qac,
    351. const RegisterAsyncCallback& rac,
    352. const boost::asio::ip::udp::endpoint& destinationEP) noexcept {
    353. typedef frp::net::IPEndPoint IPEndPoint;
    354. int message_size = sizeof(TXndpRequestPacket);
    355. std::shared_ptr message = make_shared_alloc(message_size);
    356. if (!message) {
    357. return false;
    358. }
    359. UInt32 id = NewId();
    360. TXndpRequestPacket* request = (TXndpRequestPacket*)message.get();
    361. request->checksum = 0;
    362. request->cmd = command;
    363. request->id = id;
    364. request->len = message_size;
    365. request->type = mapping_type;
    366. request->port = htons(mapping_port);
    367. if (PacketSerializeMini(request) < 1) {
    368. return false;
    369. }
    370. XNDP_ENDPOINT remoteEP = IPEndPoint::ToEndPoint(IPEndPoint::V4ToV6(IPEndPoint::ToEndPoint(destinationEP)));
    371. XndpCallerContext& context = callers_[id];
    372. context.id = id;
    373. context.destination = remoteEP;
    374. context.initial_time = hosting_->CurrentMillisec();
    375. context.query_ac = qac;
    376. context.register_ac = rac;
    377. context.retry_count = 0;
    378. context.message = message;
    379. context.message_size = message_size;
    380. boost::system::error_code ec;
    381. socket_.send_to(boost::asio::buffer(request, message_size), remoteEP, 0, ec);
    382. return ec ? false : true;
    383. }
    384. int Xndp::PacketSerializeMini(XndpPacket* packet) noexcept {
    385. int length = packet->len;
    386. if (length < sizeof(XndpPacket)) {
    387. return 0;
    388. }
    389. packet->kf = XNDP_KF;
    390. packet->checksum = 0;
    391. packet->id = htonl(packet->id);
    392. packet->len = htons(length);
    393. UInt16 checksum = frp::messages::inet_chksum(packet, length);
    394. if (checksum == 0) {
    395. checksum = 0xffff;
    396. }
    397. packet->checksum = htons(checksum);
    398. return length;
    399. }
    400. bool Xndp::ReplyToDestination(XndpPacket* packet, const boost::asio::ip::udp::endpoint& remoteEP) noexcept {
    401. if (!IsAvailable()) {
    402. return false;
    403. }
    404. int length = PacketSerializeMini(packet);
    405. if (length < 1) {
    406. return false;
    407. }
    408. boost::system::error_code ec;
    409. socket_.send_to(boost::asio::buffer(packet, length), remoteEP, 0, ec);
    410. return ec ? false : true;
    411. }
    412. bool Xndp::RegisterAsync(MappingType mapping_type, int mapping_port, RegisterAsyncCallback callback, const boost::asio::ip::udp::endpoint& destinationEP) noexcept {
    413. if (!RequireArgument(mapping_type, mapping_port, callback, destinationEP)) {
    414. return false;
    415. }
    416. return AddXndpCaller(XNDP_REGST_ENTRY,
    417. mapping_type, mapping_port, NULL, callback, destinationEP);
    418. }
    419. bool Xndp::QueryAsync(MappingType mapping_type, int mapping_port, QueryAsyncCallback callback, const boost::asio::ip::udp::endpoint& destinationEP) noexcept {
    420. if (!RequireArgument(mapping_type, mapping_port, callback, destinationEP)) {
    421. return false;
    422. }
    423. return AddXndpCaller(XNDP_QUERY_ENTRY,
    424. mapping_type, mapping_port, callback, NULL, destinationEP);
    425. }
    426. bool Xndp::PushAsync(UInt32 id, const void* message, const int message_size, const boost::asio::ip::udp::endpoint& destinationEP) noexcept {
    427. if (!message || message_size < 1) {
    428. return false;
    429. }
    430. int chunk_size = sizeof(XndpPacket) + message_size;
    431. std::shared_ptr chunk = make_shared_alloc(chunk_size);
    432. if (!message) {
    433. return false;
    434. }
    435. XndpPacket* packet = (XndpPacket*)chunk.get();
    436. packet->checksum = 0;
    437. packet->cmd = XNDP_PUSH_MESSAGE;
    438. packet->id = id;
    439. packet->len = chunk_size;
    440. memcpy(packet + 1, message, message_size);
    441. if (PacketSerializeMini(packet) < 1) {
    442. return false;
    443. }
    444. boost::system::error_code ec;
    445. socket_.send_to(boost::asio::buffer(packet, chunk_size), destinationEP, 0, ec);
    446. return ec ? false : true;
    447. }
    448. UInt32 Xndp::NewId() noexcept {
    449. for (;;) {
    450. int id = aid_++;
    451. if (!id) {
    452. continue;
    453. }
    454. if (!Dictionary::ContainsKey(callers_, id)) {
    455. return id;
    456. }
    457. }
    458. }
    459. boost::asio::ip::udp::socket& Xndp::GetSocket() noexcept {
    460. return socket_;
    461. }
    462. bool Xndp::PopCallerContext(UInt32 id, XndpCallerContext& context) noexcept {
    463. return Dictionary::TryRemove(callers_, id, context);
    464. }
    465. bool Xndp::OnRegisterEntryClient(XndpPacket* packet) noexcept {
    466. XndpReisterReplyPacket* reply = (XndpReisterReplyPacket*)packet;
    467. if (reply->len < sizeof(XndpReisterReplyPacket)) {
    468. return false;
    469. }
    470. XndpCallerContext caller;
    471. if (!PopCallerContext(reply->id, caller)) {
    472. return false;
    473. }
    474. caller.register_ac(reply->err == XNDP_ERROR_SUCCESS);
    475. return true;
    476. }
    477. bool Xndp::OnQueryEntryClient(XndpPacket* packet) noexcept {
    478. XndpQueryEntryReplyPacket* reply = (XndpQueryEntryReplyPacket*)packet;
    479. if (reply->len < sizeof(XndpQueryEntryReplyPacket)) {
    480. return false;
    481. }
    482. XndpCallerContext caller;
    483. if (!PopCallerContext(reply->id, caller)) {
    484. return false;
    485. }
    486. if (reply->err != XNDP_ERROR_SUCCESS) {
    487. boost::asio::ip::udp::endpoint noneEP;
    488. caller.query_ac(false, noneEP);
    489. }
    490. else {
    491. boost::asio::ip::address address;
    492. if (reply->af == AddressFamily::InterNetwork) {
    493. address = boost::asio::ip::address_v4(*(boost::asio::ip::address_v4::bytes_type*)reply->dst_addr);
    494. }
    495. else {
    496. address = boost::asio::ip::address_v6(*(boost::asio::ip::address_v6::bytes_type*)reply->dst_addr);
    497. }
    498. boost::asio::ip::udp::endpoint destinationEP(address, ntohs(reply->dst_port));
    499. caller.query_ac(true, destinationEP);
    500. }
    501. return true;
    502. }
    503. boost::asio::ip::udp::endpoint Xndp::ToEndPoint(const std::string host, int port) noexcept {
    504. return IPEndPoint::ToEndPoint(Ipep::GetEndPoint(host, port));
    505. }
    506. }
    507. }

  • 相关阅读:
    matplotlib制图初级篇
    音视频 SDL vs2017配置
    力扣—最长回文子串
    C++ 二叉树非递归先/后序 + 实战力扣题
    CSS 清除浮动
    navicat升级后,失效,重新ok,navicat彻底卸载
    Ant-design中表单多级对象做嵌套表单校验
    【笔试题】【day7】
    PTV Vissim学习
    硬链接和软链接的区别
  • 原文地址:https://blog.csdn.net/liulilittle/article/details/126868692