librats 0.7.1 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/native-src/CMakeLists.txt +15 -2
  2. package/native-src/src/bt_client.cpp +18 -5
  3. package/native-src/src/bt_client.h +3 -1
  4. package/native-src/src/bt_network.cpp +297 -184
  5. package/native-src/src/bt_network.h +25 -5
  6. package/native-src/src/bt_peer_connection.cpp +11 -0
  7. package/native-src/src/bt_peer_connection.h +6 -0
  8. package/native-src/src/bt_torrent.cpp +17 -6
  9. package/native-src/src/bt_torrent.h +1 -0
  10. package/native-src/src/bt_types.h +287 -20
  11. package/native-src/src/dht.cpp +26 -8
  12. package/native-src/src/dht.h +1 -1
  13. package/native-src/src/ice.cpp +1 -1
  14. package/native-src/src/io_poller.cpp +910 -0
  15. package/native-src/src/io_poller.h +138 -0
  16. package/native-src/src/krpc.cpp +8 -1
  17. package/native-src/src/krpc.h +3 -2
  18. package/native-src/src/librats.cpp +824 -1213
  19. package/native-src/src/librats.h +167 -54
  20. package/native-src/src/librats_bittorrent.cpp +4 -7
  21. package/native-src/src/librats_c.cpp +13 -1
  22. package/native-src/src/librats_c.h +2 -0
  23. package/native-src/src/librats_discovery.cpp +309 -0
  24. package/native-src/src/librats_encryption.cpp +130 -283
  25. package/native-src/src/librats_file_transfer.cpp +2 -6
  26. package/native-src/src/librats_gossipsub.cpp +1 -5
  27. package/native-src/src/librats_ice.cpp +1 -1
  28. package/native-src/src/librats_log_macros.h +36 -0
  29. package/native-src/src/librats_logging.cpp +10 -7
  30. package/native-src/src/librats_mdns.cpp +1 -11
  31. package/native-src/src/librats_persistence.cpp +1 -11
  32. package/native-src/src/librats_reconnection.cpp +2 -13
  33. package/native-src/src/librats_statistic.cpp +97 -0
  34. package/native-src/src/logger.h +40 -4
  35. package/native-src/src/network_utils.cpp +175 -373
  36. package/native-src/src/network_utils.h +2 -113
  37. package/native-src/src/socket.cpp +485 -883
  38. package/native-src/src/socket.h +36 -130
  39. package/native-src/src/stun.cpp +3 -5
  40. package/native-src/src/tracker.cpp +3 -2
  41. package/native-src/src/turn.cpp +4 -6
  42. package/package.json +1 -1
@@ -0,0 +1,138 @@
1
+ #pragma once
2
+
3
+ /**
4
+ * @file io_poller.h
5
+ * @brief Platform-optimal I/O multiplexing abstraction
6
+ *
7
+ * Provides a unified interface over platform-specific I/O multiplexers:
8
+ * - Linux: epoll (O(1) per event, scales to millions of fds)
9
+ * - macOS/BSD: kqueue (O(1) per event, scales to millions of fds)
10
+ * - Windows: IOCP (true async completion ports, O(1) per event)
11
+ *
12
+ * Usage:
13
+ * auto poller = IOPoller::create();
14
+ * poller->add(fd, PollIn);
15
+ *
16
+ * PollResult results[64];
17
+ * int n = poller->wait(results, 64, 100); // 100ms timeout
18
+ * for (int i = 0; i < n; i++) {
19
+ * if (results[i].events & PollIn) handle_read(results[i].fd);
20
+ * if (results[i].events & PollOut) handle_write(results[i].fd);
21
+ * }
22
+ */
23
+
24
+ #include "socket.h"
25
+
26
+ #include <memory>
27
+ #include <cstdint>
28
+
29
+ namespace librats {
30
+
31
+ //=============================================================================
32
+ // Poll Event Flags
33
+ //=============================================================================
34
+
35
+ /**
36
+ * @brief I/O event flags for polling
37
+ */
38
+ enum PollFlags : uint32_t {
39
+ PollNone = 0,
40
+ PollIn = 1 << 0, ///< Socket is readable (data available or connection accepted)
41
+ PollOut = 1 << 1, ///< Socket is writable (can send or connect completed)
42
+ PollErr = 1 << 2, ///< Error condition on socket
43
+ PollHup = 1 << 3, ///< Hang up / peer disconnected
44
+ };
45
+
46
+ inline uint32_t operator|(PollFlags a, PollFlags b) {
47
+ return static_cast<uint32_t>(a) | static_cast<uint32_t>(b);
48
+ }
49
+
50
+ //=============================================================================
51
+ // Poll Result
52
+ //=============================================================================
53
+
54
+ /**
55
+ * @brief Result entry from a poll wait
56
+ */
57
+ struct PollResult {
58
+ socket_t fd; ///< The socket that has events
59
+ uint32_t events; ///< Bitmask of PollFlags that occurred
60
+ };
61
+
62
+ //=============================================================================
63
+ // IOPoller Abstract Interface
64
+ //=============================================================================
65
+
66
+ /**
67
+ * @brief Abstract I/O multiplexer
68
+ *
69
+ * Thread-safety:
70
+ * - add/modify/remove: Safe to call from any thread (epoll_ctl is thread-safe,
71
+ * kqueue changes are atomic, WSAPoll rebuilds on wait).
72
+ * - wait: Should be called from a single I/O thread.
73
+ * - add/modify/remove can be called concurrently with wait().
74
+ */
75
+ class IOPoller {
76
+ public:
77
+ virtual ~IOPoller() = default;
78
+
79
+ /**
80
+ * @brief Create the platform-optimal poller instance
81
+ *
82
+ * Returns:
83
+ * - EpollPoller on Linux
84
+ * - KqueuePoller on macOS/FreeBSD
85
+ * - IocpPoller on Windows (I/O Completion Ports)
86
+ */
87
+ static std::unique_ptr<IOPoller> create();
88
+
89
+ /**
90
+ * @brief Add a socket to the poll set
91
+ *
92
+ * @param fd Socket to monitor
93
+ * @param events Bitmask of PollFlags to watch for
94
+ * @return true on success
95
+ */
96
+ virtual bool add(socket_t fd, uint32_t events) = 0;
97
+
98
+ /**
99
+ * @brief Modify the event mask for a monitored socket
100
+ *
101
+ * @param fd Socket already in the poll set
102
+ * @param events New bitmask of PollFlags
103
+ * @return true on success
104
+ */
105
+ virtual bool modify(socket_t fd, uint32_t events) = 0;
106
+
107
+ /**
108
+ * @brief Remove a socket from the poll set
109
+ *
110
+ * @param fd Socket to remove
111
+ * @return true on success (false if fd was not registered)
112
+ */
113
+ virtual bool remove(socket_t fd) = 0;
114
+
115
+ /**
116
+ * @brief Wait for I/O events
117
+ *
118
+ * Blocks until events occur or timeout expires.
119
+ *
120
+ * @param results Array to fill with ready socket events
121
+ * @param max_results Maximum entries in results array
122
+ * @param timeout_ms Timeout in milliseconds (-1 = block forever, 0 = non-blocking)
123
+ * @return Number of ready descriptors (0 on timeout, -1 on error)
124
+ */
125
+ virtual int wait(PollResult* results, int max_results, int timeout_ms) = 0;
126
+
127
+ /**
128
+ * @brief Get the backend name (for logging/diagnostics)
129
+ */
130
+ virtual const char* name() const = 0;
131
+
132
+ // Non-copyable
133
+ IOPoller() = default;
134
+ IOPoller(const IOPoller&) = delete;
135
+ IOPoller& operator=(const IOPoller&) = delete;
136
+ };
137
+
138
+ } // namespace librats
@@ -60,7 +60,7 @@ KrpcMessage KrpcProtocol::create_get_peers_query(const std::string& transaction_
60
60
  return message;
61
61
  }
62
62
 
63
- KrpcMessage KrpcProtocol::create_announce_peer_query(const std::string& transaction_id, const NodeId& sender_id, const InfoHash& info_hash, uint16_t port, const std::string& token) {
63
+ KrpcMessage KrpcProtocol::create_announce_peer_query(const std::string& transaction_id, const NodeId& sender_id, const InfoHash& info_hash, uint16_t port, const std::string& token, bool implied_port) {
64
64
  KrpcMessage message;
65
65
  message.type = KrpcMessageType::Query;
66
66
  message.transaction_id = transaction_id;
@@ -68,6 +68,7 @@ KrpcMessage KrpcProtocol::create_announce_peer_query(const std::string& transact
68
68
  message.sender_id = sender_id;
69
69
  message.info_hash = info_hash;
70
70
  message.port = port;
71
+ message.implied_port = implied_port;
71
72
  message.token = token;
72
73
  return message;
73
74
  }
@@ -176,6 +177,9 @@ BencodeValue KrpcProtocol::encode_query(const KrpcMessage& message) {
176
177
  args["info_hash"] = BencodeValue(node_id_to_string(message.info_hash));
177
178
  args["port"] = BencodeValue(static_cast<int64_t>(message.port));
178
179
  args["token"] = BencodeValue(message.token);
180
+ if (message.implied_port) {
181
+ args["implied_port"] = BencodeValue(static_cast<int64_t>(1));
182
+ }
179
183
  break;
180
184
  }
181
185
 
@@ -316,6 +320,9 @@ std::unique_ptr<KrpcMessage> KrpcProtocol::decode_query(const BencodeValue& data
316
320
  if (args.has_key("token")) {
317
321
  message->token = args["token"].as_string();
318
322
  }
323
+ if (args.has_key("implied_port")) {
324
+ message->implied_port = (args["implied_port"].as_integer() != 0);
325
+ }
319
326
  break;
320
327
  }
321
328
 
@@ -68,6 +68,7 @@ struct KrpcMessage {
68
68
  NodeId target_id;
69
69
  InfoHash info_hash;
70
70
  uint16_t port;
71
+ bool implied_port; // BEP 5: if true, use UDP source port instead of 'port' field
71
72
  std::string token;
72
73
 
73
74
  // For responses
@@ -79,7 +80,7 @@ struct KrpcMessage {
79
80
  KrpcErrorCode error_code;
80
81
  std::string error_message;
81
82
 
82
- KrpcMessage() : type(KrpcMessageType::Query), query_type(KrpcQueryType::Ping), sender_id(), target_id(), info_hash(), port(0), response_id(), error_code(KrpcErrorCode::GenericError) {}
83
+ KrpcMessage() : type(KrpcMessageType::Query), query_type(KrpcQueryType::Ping), sender_id(), target_id(), info_hash(), port(0), implied_port(false), response_id(), error_code(KrpcErrorCode::GenericError) {}
83
84
  };
84
85
 
85
86
  /**
@@ -96,7 +97,7 @@ public:
96
97
  static KrpcMessage create_ping_query(const std::string& transaction_id, const NodeId& sender_id);
97
98
  static KrpcMessage create_find_node_query(const std::string& transaction_id, const NodeId& sender_id, const NodeId& target_id);
98
99
  static KrpcMessage create_get_peers_query(const std::string& transaction_id, const NodeId& sender_id, const InfoHash& info_hash);
99
- static KrpcMessage create_announce_peer_query(const std::string& transaction_id, const NodeId& sender_id, const InfoHash& info_hash, uint16_t port, const std::string& token);
100
+ static KrpcMessage create_announce_peer_query(const std::string& transaction_id, const NodeId& sender_id, const InfoHash& info_hash, uint16_t port, const std::string& token, bool implied_port = false);
100
101
 
101
102
  static KrpcMessage create_ping_response(const std::string& transaction_id, const NodeId& response_id);
102
103
  static KrpcMessage create_find_node_response(const std::string& transaction_id, const NodeId& response_id, const std::vector<KrpcNode>& nodes);