librats 0.3.1 → 0.5.1
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.
- package/README.md +405 -405
- package/binding.gyp +96 -95
- package/lib/index.d.ts +522 -522
- package/lib/index.js +82 -82
- package/native-src/3rdparty/android/ifaddrs-android.c +600 -0
- package/native-src/3rdparty/android/ifaddrs-android.h +54 -0
- package/native-src/CMakeLists.txt +360 -0
- package/native-src/LICENSE +21 -0
- package/native-src/src/bencode.cpp +485 -0
- package/native-src/src/bencode.h +145 -0
- package/native-src/src/bittorrent.cpp +3682 -0
- package/native-src/src/bittorrent.h +731 -0
- package/native-src/src/dht.cpp +2342 -0
- package/native-src/src/dht.h +501 -0
- package/native-src/src/encrypted_socket.cpp +817 -0
- package/native-src/src/encrypted_socket.h +239 -0
- package/native-src/src/file_transfer.cpp +1808 -0
- package/native-src/src/file_transfer.h +567 -0
- package/native-src/src/fs.cpp +639 -0
- package/native-src/src/fs.h +108 -0
- package/native-src/src/gossipsub.cpp +1137 -0
- package/native-src/src/gossipsub.h +403 -0
- package/native-src/src/ice.cpp +1386 -0
- package/native-src/src/ice.h +328 -0
- package/native-src/src/json.hpp +25526 -0
- package/native-src/src/krpc.cpp +558 -0
- package/native-src/src/krpc.h +145 -0
- package/native-src/src/librats.cpp +2715 -0
- package/native-src/src/librats.h +1729 -0
- package/native-src/src/librats_bittorrent.cpp +167 -0
- package/native-src/src/librats_c.cpp +1317 -0
- package/native-src/src/librats_c.h +237 -0
- package/native-src/src/librats_encryption.cpp +123 -0
- package/native-src/src/librats_file_transfer.cpp +226 -0
- package/native-src/src/librats_gossipsub.cpp +293 -0
- package/native-src/src/librats_ice.cpp +515 -0
- package/native-src/src/librats_logging.cpp +158 -0
- package/native-src/src/librats_mdns.cpp +171 -0
- package/native-src/src/librats_nat.cpp +571 -0
- package/native-src/src/librats_persistence.cpp +815 -0
- package/native-src/src/logger.h +412 -0
- package/native-src/src/mdns.cpp +1178 -0
- package/native-src/src/mdns.h +253 -0
- package/native-src/src/network_utils.cpp +598 -0
- package/native-src/src/network_utils.h +162 -0
- package/native-src/src/noise.cpp +981 -0
- package/native-src/src/noise.h +227 -0
- package/native-src/src/os.cpp +371 -0
- package/native-src/src/os.h +40 -0
- package/native-src/src/rats_export.h +17 -0
- package/native-src/src/sha1.cpp +163 -0
- package/native-src/src/sha1.h +42 -0
- package/native-src/src/socket.cpp +1376 -0
- package/native-src/src/socket.h +309 -0
- package/native-src/src/stun.cpp +484 -0
- package/native-src/src/stun.h +349 -0
- package/native-src/src/threadmanager.cpp +105 -0
- package/native-src/src/threadmanager.h +53 -0
- package/native-src/src/tracker.cpp +1110 -0
- package/native-src/src/tracker.h +268 -0
- package/native-src/src/version.cpp +24 -0
- package/native-src/src/version.h.in +45 -0
- package/native-src/version.rc.in +31 -0
- package/package.json +62 -68
- package/scripts/build-librats.js +241 -194
- package/scripts/postinstall.js +52 -52
- package/scripts/prepare-package.js +187 -91
- package/scripts/verify-installation.js +119 -119
- package/src/librats_node.cpp +1174 -1174
|
@@ -0,0 +1,328 @@
|
|
|
1
|
+
#ifndef LIBRATS_ICE_H
|
|
2
|
+
#define LIBRATS_ICE_H
|
|
3
|
+
|
|
4
|
+
#include "socket.h"
|
|
5
|
+
#include "stun.h"
|
|
6
|
+
#include "json.hpp"
|
|
7
|
+
#include <string>
|
|
8
|
+
#include <vector>
|
|
9
|
+
#include <memory>
|
|
10
|
+
#include <functional>
|
|
11
|
+
#include <chrono>
|
|
12
|
+
#include <atomic>
|
|
13
|
+
#include <thread>
|
|
14
|
+
#include <mutex>
|
|
15
|
+
#include <unordered_map>
|
|
16
|
+
#include <condition_variable>
|
|
17
|
+
|
|
18
|
+
namespace librats {
|
|
19
|
+
|
|
20
|
+
// ICE Candidate Types
|
|
21
|
+
enum class IceCandidateType {
|
|
22
|
+
HOST, // Local interface address
|
|
23
|
+
SERVER_REFLEXIVE, // Public address discovered via STUN
|
|
24
|
+
PEER_REFLEXIVE, // Address discovered during connectivity checks
|
|
25
|
+
RELAY // Address allocated on TURN server
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
// ICE Candidate Transport Protocol
|
|
29
|
+
enum class IceTransport {
|
|
30
|
+
UDP,
|
|
31
|
+
TCP
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
// ICE Candidate Structure
|
|
35
|
+
struct IceCandidate {
|
|
36
|
+
std::string foundation; // Foundation for grouping candidates
|
|
37
|
+
uint32_t component_id; // Component identifier (1 for RTP, 2 for RTCP, etc.)
|
|
38
|
+
IceTransport transport; // Transport protocol
|
|
39
|
+
uint32_t priority; // Candidate priority
|
|
40
|
+
std::string ip; // IP address
|
|
41
|
+
uint16_t port; // Port number
|
|
42
|
+
IceCandidateType type; // Candidate type
|
|
43
|
+
std::string related_ip; // Related address (for reflexive/relay candidates)
|
|
44
|
+
uint16_t related_port; // Related port
|
|
45
|
+
std::string ufrag; // Username fragment
|
|
46
|
+
std::string pwd; // Password
|
|
47
|
+
|
|
48
|
+
// Optional TURN server info (for relay candidates)
|
|
49
|
+
std::string turn_server;
|
|
50
|
+
uint16_t turn_port;
|
|
51
|
+
|
|
52
|
+
IceCandidate();
|
|
53
|
+
std::string to_sdp() const;
|
|
54
|
+
static IceCandidate from_sdp(const std::string& sdp_line);
|
|
55
|
+
nlohmann::json to_json() const;
|
|
56
|
+
static IceCandidate from_json(const nlohmann::json& json);
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
// ICE Candidate Pair for connectivity checks
|
|
60
|
+
struct IceCandidatePair {
|
|
61
|
+
IceCandidate local;
|
|
62
|
+
IceCandidate remote;
|
|
63
|
+
uint64_t priority;
|
|
64
|
+
bool nominated;
|
|
65
|
+
std::chrono::steady_clock::time_point last_check_time;
|
|
66
|
+
int check_count;
|
|
67
|
+
bool succeeded;
|
|
68
|
+
|
|
69
|
+
IceCandidatePair(const IceCandidate& local, const IceCandidate& remote);
|
|
70
|
+
uint64_t calculate_priority() const;
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
// ICE Connection State
|
|
74
|
+
enum class IceConnectionState {
|
|
75
|
+
NEW,
|
|
76
|
+
GATHERING,
|
|
77
|
+
CHECKING,
|
|
78
|
+
CONNECTED,
|
|
79
|
+
COMPLETED,
|
|
80
|
+
FAILED,
|
|
81
|
+
DISCONNECTED,
|
|
82
|
+
CLOSED
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
// ICE Role
|
|
86
|
+
enum class IceRole {
|
|
87
|
+
CONTROLLING,
|
|
88
|
+
CONTROLLED
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
// NAT Type Detection Results
|
|
92
|
+
enum class NatType {
|
|
93
|
+
UNKNOWN,
|
|
94
|
+
OPEN_INTERNET, // No NAT
|
|
95
|
+
FULL_CONE, // Full cone NAT
|
|
96
|
+
RESTRICTED_CONE, // Restricted cone NAT
|
|
97
|
+
PORT_RESTRICTED, // Port restricted cone NAT
|
|
98
|
+
SYMMETRIC, // Symmetric NAT
|
|
99
|
+
BLOCKED // UDP blocked
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
// ICE Configuration
|
|
103
|
+
struct IceConfig {
|
|
104
|
+
std::vector<std::string> stun_servers;
|
|
105
|
+
std::vector<std::string> turn_servers;
|
|
106
|
+
std::vector<std::string> turn_usernames;
|
|
107
|
+
std::vector<std::string> turn_passwords;
|
|
108
|
+
bool enable_host_candidates;
|
|
109
|
+
bool enable_server_reflexive_candidates;
|
|
110
|
+
bool enable_relay_candidates;
|
|
111
|
+
bool enable_tcp_candidates;
|
|
112
|
+
int stun_timeout_ms;
|
|
113
|
+
int turn_timeout_ms;
|
|
114
|
+
int connectivity_check_timeout_ms;
|
|
115
|
+
int max_connectivity_checks;
|
|
116
|
+
|
|
117
|
+
IceConfig();
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
// ICE Events
|
|
121
|
+
class IceAgent;
|
|
122
|
+
using IceCandidateCallback = std::function<void(const IceCandidate&)>;
|
|
123
|
+
using IceStateChangeCallback = std::function<void(IceConnectionState)>;
|
|
124
|
+
using IceConnectedCallback = std::function<void(const std::string& local_addr, const std::string& remote_addr)>;
|
|
125
|
+
using IceDataCallback = std::function<void(const std::vector<uint8_t>&, const std::string& from_addr)>;
|
|
126
|
+
|
|
127
|
+
// TURN Client for relay candidates
|
|
128
|
+
class TurnClient {
|
|
129
|
+
public:
|
|
130
|
+
TurnClient(const std::string& server, uint16_t port,
|
|
131
|
+
const std::string& username, const std::string& password);
|
|
132
|
+
~TurnClient();
|
|
133
|
+
|
|
134
|
+
bool allocate_relay(std::string& allocated_ip, uint16_t& allocated_port);
|
|
135
|
+
bool create_permission(const std::string& peer_ip);
|
|
136
|
+
bool send_data(const std::vector<uint8_t>& data, const std::string& peer_ip, uint16_t peer_port);
|
|
137
|
+
std::vector<uint8_t> receive_data(std::string& from_ip, uint16_t& from_port, int timeout_ms = 1000);
|
|
138
|
+
void refresh_allocation();
|
|
139
|
+
void deallocate();
|
|
140
|
+
|
|
141
|
+
bool is_allocated() const { return allocated_; }
|
|
142
|
+
std::string get_allocated_ip() const { return allocated_ip_; }
|
|
143
|
+
uint16_t get_allocated_port() const { return allocated_port_; }
|
|
144
|
+
|
|
145
|
+
private:
|
|
146
|
+
std::string server_;
|
|
147
|
+
uint16_t port_;
|
|
148
|
+
std::string username_;
|
|
149
|
+
std::string password_;
|
|
150
|
+
socket_t socket_;
|
|
151
|
+
bool allocated_;
|
|
152
|
+
std::string allocated_ip_;
|
|
153
|
+
uint16_t allocated_port_;
|
|
154
|
+
std::string realm_;
|
|
155
|
+
std::string nonce_;
|
|
156
|
+
std::chrono::steady_clock::time_point last_refresh_;
|
|
157
|
+
|
|
158
|
+
bool send_allocate_request();
|
|
159
|
+
bool send_refresh_request();
|
|
160
|
+
bool handle_allocate_response(const std::vector<uint8_t>& response);
|
|
161
|
+
bool authenticate_with_server();
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
// NAT Type Detector
|
|
165
|
+
class NatTypeDetector {
|
|
166
|
+
public:
|
|
167
|
+
NatTypeDetector();
|
|
168
|
+
~NatTypeDetector();
|
|
169
|
+
|
|
170
|
+
NatType detect_nat_type(const std::vector<std::string>& stun_servers, int timeout_ms = 5000);
|
|
171
|
+
std::string nat_type_to_string(NatType type) const;
|
|
172
|
+
|
|
173
|
+
private:
|
|
174
|
+
bool test_udp_blocked(const std::string& stun_server, int timeout_ms);
|
|
175
|
+
bool test_open_internet(const std::string& stun_server, int timeout_ms);
|
|
176
|
+
bool test_full_cone(const std::string& stun_server1, const std::string& stun_server2, int timeout_ms);
|
|
177
|
+
bool test_symmetric_nat(const std::string& stun_server1, const std::string& stun_server2, int timeout_ms);
|
|
178
|
+
|
|
179
|
+
StunAddress get_mapped_address(const std::string& stun_server, int timeout_ms);
|
|
180
|
+
StunAddress get_mapped_address_different_port(const std::string& stun_server, int timeout_ms);
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
// Main ICE Agent
|
|
184
|
+
class IceAgent {
|
|
185
|
+
public:
|
|
186
|
+
IceAgent(IceRole role, const IceConfig& config = IceConfig());
|
|
187
|
+
~IceAgent();
|
|
188
|
+
|
|
189
|
+
// Lifecycle
|
|
190
|
+
bool start();
|
|
191
|
+
void stop();
|
|
192
|
+
void shutdown_immediate();
|
|
193
|
+
bool is_running() const { return running_.load(); }
|
|
194
|
+
|
|
195
|
+
// Configuration
|
|
196
|
+
void set_config(const IceConfig& config) { config_ = config; }
|
|
197
|
+
IceConfig get_config() const { return config_; }
|
|
198
|
+
void set_role(IceRole role) { role_ = role; }
|
|
199
|
+
IceRole get_role() const { return role_; }
|
|
200
|
+
|
|
201
|
+
// Credentials
|
|
202
|
+
void set_local_credentials(const std::string& ufrag, const std::string& pwd);
|
|
203
|
+
void set_remote_credentials(const std::string& ufrag, const std::string& pwd);
|
|
204
|
+
std::pair<std::string, std::string> get_local_credentials() const;
|
|
205
|
+
|
|
206
|
+
// Candidate gathering
|
|
207
|
+
void gather_candidates();
|
|
208
|
+
std::vector<IceCandidate> get_local_candidates() const;
|
|
209
|
+
void add_remote_candidate(const IceCandidate& candidate);
|
|
210
|
+
void add_remote_candidates(const std::vector<IceCandidate>& candidates);
|
|
211
|
+
|
|
212
|
+
// Connectivity establishment
|
|
213
|
+
void start_connectivity_checks();
|
|
214
|
+
void restart_ice();
|
|
215
|
+
|
|
216
|
+
// Data transmission
|
|
217
|
+
bool send_data(const std::vector<uint8_t>& data);
|
|
218
|
+
bool send_data_to(const std::vector<uint8_t>& data, const std::string& addr);
|
|
219
|
+
|
|
220
|
+
// State
|
|
221
|
+
IceConnectionState get_connection_state() const { return state_.load(); }
|
|
222
|
+
bool is_connected() const { return state_.load() == IceConnectionState::CONNECTED ||
|
|
223
|
+
state_.load() == IceConnectionState::COMPLETED; }
|
|
224
|
+
|
|
225
|
+
// NAT traversal utilities
|
|
226
|
+
NatType detect_nat_type();
|
|
227
|
+
bool perform_hole_punching(const std::string& peer_ip, uint16_t peer_port);
|
|
228
|
+
bool coordinate_connection(const nlohmann::json& signaling_data);
|
|
229
|
+
|
|
230
|
+
// Callbacks
|
|
231
|
+
void set_candidate_callback(IceCandidateCallback callback) { candidate_callback_ = callback; }
|
|
232
|
+
void set_state_change_callback(IceStateChangeCallback callback) { state_change_callback_ = callback; }
|
|
233
|
+
void set_connected_callback(IceConnectedCallback callback) { connected_callback_ = callback; }
|
|
234
|
+
void set_data_callback(IceDataCallback callback) { data_callback_ = callback; }
|
|
235
|
+
|
|
236
|
+
// Signaling support
|
|
237
|
+
nlohmann::json get_local_description() const;
|
|
238
|
+
bool set_remote_description(const nlohmann::json& remote_desc);
|
|
239
|
+
nlohmann::json create_connection_offer() const;
|
|
240
|
+
nlohmann::json create_connection_answer(const nlohmann::json& offer) const;
|
|
241
|
+
|
|
242
|
+
// Statistics and debugging
|
|
243
|
+
std::vector<IceCandidatePair> get_candidate_pairs() const;
|
|
244
|
+
IceCandidatePair get_selected_pair() const;
|
|
245
|
+
nlohmann::json get_statistics() const;
|
|
246
|
+
|
|
247
|
+
private:
|
|
248
|
+
IceRole role_;
|
|
249
|
+
IceConfig config_;
|
|
250
|
+
std::atomic<bool> running_;
|
|
251
|
+
std::atomic<IceConnectionState> state_;
|
|
252
|
+
|
|
253
|
+
// Credentials
|
|
254
|
+
std::string local_ufrag_;
|
|
255
|
+
std::string local_pwd_;
|
|
256
|
+
std::string remote_ufrag_;
|
|
257
|
+
std::string remote_pwd_;
|
|
258
|
+
|
|
259
|
+
// Candidates
|
|
260
|
+
std::vector<IceCandidate> local_candidates_;
|
|
261
|
+
std::vector<IceCandidate> remote_candidates_;
|
|
262
|
+
mutable std::mutex candidates_mutex_;
|
|
263
|
+
|
|
264
|
+
// Candidate pairs and connectivity checks
|
|
265
|
+
std::vector<IceCandidatePair> candidate_pairs_;
|
|
266
|
+
IceCandidatePair selected_pair_;
|
|
267
|
+
mutable std::mutex pairs_mutex_;
|
|
268
|
+
|
|
269
|
+
// Networking
|
|
270
|
+
socket_t udp_socket_;
|
|
271
|
+
socket_t tcp_socket_;
|
|
272
|
+
std::unique_ptr<TurnClient> turn_client_;
|
|
273
|
+
std::unique_ptr<NatTypeDetector> nat_detector_;
|
|
274
|
+
|
|
275
|
+
// Threading
|
|
276
|
+
std::thread gather_thread_;
|
|
277
|
+
std::thread check_thread_;
|
|
278
|
+
std::thread receive_thread_;
|
|
279
|
+
|
|
280
|
+
// Conditional variables for immediate shutdown
|
|
281
|
+
std::condition_variable shutdown_cv_;
|
|
282
|
+
std::mutex shutdown_mutex_;
|
|
283
|
+
|
|
284
|
+
// Callbacks
|
|
285
|
+
IceCandidateCallback candidate_callback_;
|
|
286
|
+
IceStateChangeCallback state_change_callback_;
|
|
287
|
+
IceConnectedCallback connected_callback_;
|
|
288
|
+
IceDataCallback data_callback_;
|
|
289
|
+
|
|
290
|
+
// Internal methods
|
|
291
|
+
void set_state(IceConnectionState new_state);
|
|
292
|
+
void gather_host_candidates();
|
|
293
|
+
void gather_server_reflexive_candidates();
|
|
294
|
+
void gather_relay_candidates();
|
|
295
|
+
void gather_tcp_candidates();
|
|
296
|
+
|
|
297
|
+
void connectivity_check_loop();
|
|
298
|
+
bool perform_connectivity_check(IceCandidatePair& pair);
|
|
299
|
+
void form_candidate_pairs();
|
|
300
|
+
void prioritize_candidate_pairs();
|
|
301
|
+
void nominate_pair(IceCandidatePair& pair);
|
|
302
|
+
|
|
303
|
+
void receive_loop();
|
|
304
|
+
void handle_incoming_data(const std::vector<uint8_t>& data, const std::string& from_addr);
|
|
305
|
+
bool is_stun_message(const std::vector<uint8_t>& data);
|
|
306
|
+
void handle_stun_message(const std::vector<uint8_t>& data, const std::string& from_addr);
|
|
307
|
+
|
|
308
|
+
uint32_t calculate_candidate_priority(IceCandidateType type, uint16_t local_pref, uint16_t component_id);
|
|
309
|
+
std::string generate_foundation(const IceCandidate& candidate);
|
|
310
|
+
std::string generate_ufrag();
|
|
311
|
+
std::string generate_password();
|
|
312
|
+
|
|
313
|
+
// Hole punching helpers
|
|
314
|
+
bool udp_hole_punch(const std::string& peer_ip, uint16_t peer_port);
|
|
315
|
+
bool tcp_hole_punch(const std::string& peer_ip, uint16_t peer_port);
|
|
316
|
+
bool coordinate_hole_punch(const nlohmann::json& punch_data);
|
|
317
|
+
};
|
|
318
|
+
|
|
319
|
+
// Utility functions
|
|
320
|
+
std::string ice_candidate_type_to_string(IceCandidateType type);
|
|
321
|
+
IceCandidateType string_to_ice_candidate_type(const std::string& type_str);
|
|
322
|
+
std::string ice_transport_to_string(IceTransport transport);
|
|
323
|
+
IceTransport string_to_ice_transport(const std::string& transport_str);
|
|
324
|
+
std::string ice_connection_state_to_string(IceConnectionState state);
|
|
325
|
+
|
|
326
|
+
} // namespace librats
|
|
327
|
+
|
|
328
|
+
#endif // LIBRATS_ICE_H
|