librats 1.0.2 → 2.2.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.
- package/README.md +145 -331
- package/binding.gyp +16 -3
- package/lib/index.d.ts +288 -696
- package/lib/index.js +407 -44
- package/native-src/3rdparty/android/ifaddrs-android.c +1 -0
- package/native-src/3rdparty/android/ifaddrs-android.h +1 -0
- package/native-src/CMakeLists.txt +404 -179
- package/native-src/LICENSE +1 -1
- package/native-src/src/librats/bindings/rats.cpp +762 -0
- package/native-src/src/librats/bindings/rats.h +380 -0
- package/native-src/src/librats/bittorrent/bencode.cpp +437 -0
- package/native-src/src/librats/bittorrent/bencode.h +176 -0
- package/native-src/src/librats/bittorrent/bitfield.cpp +97 -0
- package/native-src/src/librats/bittorrent/bitfield.h +76 -0
- package/native-src/src/librats/bittorrent/byte_io.h +58 -0
- package/native-src/src/librats/bittorrent/choker.cpp +25 -0
- package/native-src/src/librats/bittorrent/choker.h +46 -0
- package/native-src/src/librats/bittorrent/client.cpp +413 -0
- package/native-src/src/librats/bittorrent/client.h +227 -0
- package/native-src/src/librats/bittorrent/disk_io.cpp +209 -0
- package/native-src/src/librats/bittorrent/disk_io.h +150 -0
- package/native-src/src/librats/bittorrent/extensions.cpp +191 -0
- package/native-src/src/librats/bittorrent/extensions.h +94 -0
- package/native-src/src/librats/bittorrent/file_storage.cpp +77 -0
- package/native-src/src/librats/bittorrent/file_storage.h +79 -0
- package/native-src/src/librats/bittorrent/log.h +42 -0
- package/native-src/src/librats/bittorrent/magnet_uri.cpp +98 -0
- package/native-src/src/librats/bittorrent/magnet_uri.h +35 -0
- package/native-src/src/librats/bittorrent/peer_connection.cpp +502 -0
- package/native-src/src/librats/bittorrent/peer_connection.h +194 -0
- package/native-src/src/librats/bittorrent/peer_list.cpp +68 -0
- package/native-src/src/librats/bittorrent/peer_list.h +75 -0
- package/native-src/src/librats/bittorrent/piece_picker.cpp +352 -0
- package/native-src/src/librats/bittorrent/piece_picker.h +201 -0
- package/native-src/src/librats/bittorrent/reactor.cpp +97 -0
- package/native-src/src/librats/bittorrent/reactor.h +89 -0
- package/native-src/src/librats/bittorrent/resume_data.cpp +72 -0
- package/native-src/src/librats/bittorrent/resume_data.h +41 -0
- package/native-src/src/librats/bittorrent/store_buffer.cpp +48 -0
- package/native-src/src/librats/bittorrent/store_buffer.h +47 -0
- package/native-src/src/librats/bittorrent/torrent.cpp +870 -0
- package/native-src/src/librats/bittorrent/torrent.h +260 -0
- package/native-src/src/librats/bittorrent/torrent_creator.cpp +129 -0
- package/native-src/src/librats/bittorrent/torrent_creator.h +58 -0
- package/native-src/src/librats/bittorrent/torrent_info.cpp +314 -0
- package/native-src/src/librats/bittorrent/torrent_info.h +118 -0
- package/native-src/src/librats/bittorrent/tracker.cpp +374 -0
- package/native-src/src/librats/bittorrent/tracker.h +108 -0
- package/native-src/src/librats/bittorrent/types.cpp +206 -0
- package/native-src/src/librats/bittorrent/types.h +86 -0
- package/native-src/src/librats/core/address.cpp +35 -0
- package/native-src/src/librats/core/address.h +78 -0
- package/native-src/src/librats/core/bytes.h +69 -0
- package/native-src/src/librats/core/chained_send_buffer.cpp +172 -0
- package/native-src/src/librats/core/chained_send_buffer.h +183 -0
- package/native-src/src/librats/core/endpoint_parse.cpp +41 -0
- package/native-src/src/librats/core/endpoint_parse.h +31 -0
- package/native-src/src/librats/core/event_bus.h +70 -0
- package/native-src/src/librats/core/host_endpoint.h +56 -0
- package/native-src/src/{io_poller.cpp → librats/core/io_poller.cpp} +520 -65
- package/native-src/src/{io_poller.h → librats/core/io_poller.h} +12 -6
- package/native-src/src/librats/core/ip_address.cpp +120 -0
- package/native-src/src/librats/core/ip_address.h +109 -0
- package/native-src/src/librats/core/mpsc_queue.h +47 -0
- package/native-src/src/librats/core/notifier.h +74 -0
- package/native-src/src/librats/core/receive_buffer.cpp +219 -0
- package/native-src/src/librats/core/receive_buffer.h +171 -0
- package/native-src/src/librats/core/service_registry.h +58 -0
- package/native-src/src/{socket.cpp → librats/core/socket.cpp} +625 -118
- package/native-src/src/librats/core/socket.h +496 -0
- package/native-src/src/librats/core/timer_queue.h +105 -0
- package/native-src/src/librats/core/types.cpp +43 -0
- package/native-src/src/librats/core/types.h +103 -0
- package/native-src/src/librats/core/wakeup_pipe.h +83 -0
- package/native-src/src/{crypto → librats/crypto}/blake2_endian.h +21 -23
- package/native-src/src/{crypto → librats/crypto}/blake2b.c +34 -33
- package/native-src/src/{crypto → librats/crypto}/blake2b.h +7 -6
- package/native-src/src/{crypto → librats/crypto}/blake2s.c +55 -54
- package/native-src/src/{crypto → librats/crypto}/blake2s.h +13 -12
- package/native-src/src/{crypto → librats/crypto}/chacha.c +22 -21
- package/native-src/src/{crypto → librats/crypto}/chacha.h +14 -13
- package/native-src/src/{crypto → librats/crypto}/chachapoly.c +56 -56
- package/native-src/src/{crypto → librats/crypto}/chachapoly.h +24 -17
- package/native-src/src/{crc32.cpp → librats/crypto/crc32.cpp} +1 -1
- package/native-src/src/{crc32.h → librats/crypto/crc32.h} +3 -1
- package/native-src/src/{crypto → librats/crypto}/curve25519.c +6 -4
- package/native-src/src/{crypto → librats/crypto}/curve25519.h +6 -3
- package/native-src/src/librats/crypto/hkdf.c +266 -0
- package/native-src/src/{crypto → librats/crypto}/hkdf.h +19 -19
- package/native-src/src/{noise.cpp → librats/crypto/noise.cpp} +84 -73
- package/native-src/src/{noise.h → librats/crypto/noise.h} +18 -8
- package/native-src/src/{crypto → librats/crypto}/poly1305.c +47 -46
- package/native-src/src/librats/crypto/poly1305.h +37 -0
- package/native-src/src/{sha1.cpp → librats/crypto/sha1.cpp} +33 -1
- package/native-src/src/{sha1.h → librats/crypto/sha1.h} +14 -6
- package/native-src/src/{crypto → librats/crypto}/sha256.c +15 -14
- package/native-src/src/{crypto → librats/crypto}/sha256.h +8 -7
- package/native-src/src/{crypto → librats/crypto}/sha512.c +15 -14
- package/native-src/src/{crypto → librats/crypto}/sha512.h +8 -7
- package/native-src/src/librats/dht/announce.cpp +37 -0
- package/native-src/src/librats/dht/announce.h +41 -0
- package/native-src/src/librats/dht/bep42.cpp +109 -0
- package/native-src/src/librats/dht/bep42.h +48 -0
- package/native-src/src/librats/dht/dht.cpp +501 -0
- package/native-src/src/librats/dht/dht.h +119 -0
- package/native-src/src/librats/dht/dht_runner.cpp +103 -0
- package/native-src/src/librats/dht/dht_runner.h +71 -0
- package/native-src/src/librats/dht/dos_blocker.cpp +42 -0
- package/native-src/src/librats/dht/dos_blocker.h +47 -0
- package/native-src/src/librats/dht/find_peers.cpp +52 -0
- package/native-src/src/librats/dht/find_peers.h +73 -0
- package/native-src/src/librats/dht/id.h +167 -0
- package/native-src/src/{krpc.cpp → librats/dht/krpc.cpp} +32 -81
- package/native-src/src/{krpc.h → librats/dht/krpc.h} +19 -23
- package/native-src/src/librats/dht/log.h +38 -0
- package/native-src/src/librats/dht/node.cpp +473 -0
- package/native-src/src/librats/dht/node.h +164 -0
- package/native-src/src/librats/dht/node_entry.h +81 -0
- package/native-src/src/librats/dht/observer.h +72 -0
- package/native-src/src/librats/dht/persistence.cpp +90 -0
- package/native-src/src/librats/dht/persistence.h +32 -0
- package/native-src/src/librats/dht/routing_table.cpp +559 -0
- package/native-src/src/librats/dht/routing_table.h +185 -0
- package/native-src/src/librats/dht/rpc_manager.cpp +127 -0
- package/native-src/src/librats/dht/rpc_manager.h +77 -0
- package/native-src/src/librats/dht/storage.cpp +92 -0
- package/native-src/src/librats/dht/storage.h +74 -0
- package/native-src/src/librats/dht/transport.h +27 -0
- package/native-src/src/librats/dht/traversal.cpp +326 -0
- package/native-src/src/librats/dht/traversal.h +120 -0
- package/native-src/src/librats/dht/udp_transport.cpp +49 -0
- package/native-src/src/librats/dht/udp_transport.h +51 -0
- package/native-src/src/librats/mdns/log.h +22 -0
- package/native-src/src/{mdns.cpp → librats/mdns/mdns.cpp} +75 -40
- package/native-src/src/{mdns.h → librats/mdns/mdns.h} +9 -8
- package/native-src/src/{natpmp.cpp → librats/nat/natpmp.cpp} +12 -9
- package/native-src/src/{natpmp.h → librats/nat/natpmp.h} +3 -3
- package/native-src/src/{port_mapping.h → librats/nat/port_mapping.h} +3 -2
- package/native-src/src/{stun.cpp → librats/nat/stun.cpp} +4 -4
- package/native-src/src/{stun.h → librats/nat/stun.h} +1 -1
- package/native-src/src/{upnp.cpp → librats/nat/upnp.cpp} +6 -6
- package/native-src/src/{upnp.h → librats/nat/upnp.h} +2 -2
- package/native-src/src/librats/node/circuit_service.h +84 -0
- package/native-src/src/librats/node/config.h +110 -0
- package/native-src/src/librats/node/dial_service.h +54 -0
- package/native-src/src/librats/node/dialer.cpp +264 -0
- package/native-src/src/librats/node/dialer.h +188 -0
- package/native-src/src/librats/node/host_events.h +26 -0
- package/native-src/src/librats/node/identify.cpp +130 -0
- package/native-src/src/librats/node/identify.h +71 -0
- package/native-src/src/librats/node/nat_status.cpp +103 -0
- package/native-src/src/librats/node/nat_status.h +118 -0
- package/native-src/src/librats/node/node.cpp +865 -0
- package/native-src/src/librats/node/node.h +344 -0
- package/native-src/src/librats/node/node_context.h +33 -0
- package/native-src/src/librats/node/peer_network.h +91 -0
- package/native-src/src/librats/peer/peer.h +49 -0
- package/native-src/src/librats/peer/peer_book.cpp +181 -0
- package/native-src/src/librats/peer/peer_book.h +88 -0
- package/native-src/src/librats/peer/peer_id.cpp +72 -0
- package/native-src/src/librats/peer/peer_id.h +62 -0
- package/native-src/src/librats/peer/peer_info.h +37 -0
- package/native-src/src/librats/peer/peer_table.cpp +170 -0
- package/native-src/src/librats/peer/peer_table.h +148 -0
- package/native-src/src/librats/security/handshaker.h +66 -0
- package/native-src/src/librats/security/identity.h +43 -0
- package/native-src/src/librats/security/noise_security.cpp +122 -0
- package/native-src/src/librats/security/noise_security.h +37 -0
- package/native-src/src/librats/security/plaintext_security.h +106 -0
- package/native-src/src/librats/security/session.h +37 -0
- package/native-src/src/{storage.cpp → librats/storage/storage.cpp} +369 -522
- package/native-src/src/{storage.h → librats/storage/storage.h} +135 -299
- package/native-src/src/librats/subsystems/bittorrent.cpp +211 -0
- package/native-src/src/librats/subsystems/bittorrent.h +136 -0
- package/native-src/src/librats/subsystems/dht_discovery.cpp +202 -0
- package/native-src/src/librats/subsystems/dht_discovery.h +123 -0
- package/native-src/src/librats/subsystems/dht_service.h +36 -0
- package/native-src/src/librats/subsystems/file_transfer.cpp +972 -0
- package/native-src/src/librats/subsystems/file_transfer.h +367 -0
- package/native-src/src/librats/subsystems/hole_punch.cpp +605 -0
- package/native-src/src/librats/subsystems/hole_punch.h +290 -0
- package/native-src/src/librats/subsystems/hole_punch_service.h +38 -0
- package/native-src/src/librats/subsystems/mdns_discovery.cpp +66 -0
- package/native-src/src/librats/subsystems/mdns_discovery.h +55 -0
- package/native-src/src/librats/subsystems/message_json.cpp +112 -0
- package/native-src/src/librats/subsystems/message_json.h +88 -0
- package/native-src/src/librats/subsystems/peer_exchange.cpp +241 -0
- package/native-src/src/librats/subsystems/peer_exchange.h +136 -0
- package/native-src/src/librats/subsystems/ping_service.cpp +98 -0
- package/native-src/src/librats/subsystems/ping_service.h +66 -0
- package/native-src/src/librats/subsystems/port_mapping_service.cpp +192 -0
- package/native-src/src/librats/subsystems/port_mapping_service.h +84 -0
- package/native-src/src/librats/subsystems/pubsub.cpp +567 -0
- package/native-src/src/librats/subsystems/pubsub.h +175 -0
- package/native-src/src/librats/subsystems/reconnection.cpp +239 -0
- package/native-src/src/librats/subsystems/reconnection.h +126 -0
- package/native-src/src/librats/subsystems/relay.cpp +1142 -0
- package/native-src/src/librats/subsystems/relay.h +211 -0
- package/native-src/src/librats/subsystems/relay_service.h +46 -0
- package/native-src/src/librats/transport/connection.cpp +343 -0
- package/native-src/src/librats/transport/connection.h +283 -0
- package/native-src/src/librats/transport/link.h +96 -0
- package/native-src/src/librats/transport/reactor.cpp +588 -0
- package/native-src/src/librats/transport/reactor.h +262 -0
- package/native-src/src/librats/transport/reactor_pool.h +81 -0
- package/native-src/src/librats/transport/relay_link.cpp +208 -0
- package/native-src/src/librats/transport/relay_link.h +303 -0
- package/native-src/src/librats/transport/tcp_link.cpp +49 -0
- package/native-src/src/librats/transport/tcp_link.h +43 -0
- package/native-src/src/librats/transport/udp_mux.cpp +617 -0
- package/native-src/src/librats/transport/udp_mux.h +363 -0
- package/native-src/src/librats/transport/udp_packet.cpp +121 -0
- package/native-src/src/librats/transport/udp_packet.h +190 -0
- package/native-src/src/librats/transport/udp_stream.cpp +1194 -0
- package/native-src/src/librats/transport/udp_stream.h +614 -0
- package/native-src/src/librats/util/features.h.in +51 -0
- package/native-src/src/{fs.cpp → librats/util/fs.cpp} +51 -3
- package/native-src/src/librats/util/fs.h +136 -0
- package/native-src/src/librats/util/json.cpp +1002 -0
- package/native-src/src/librats/util/json.h +444 -0
- package/native-src/src/{logger.cpp → librats/util/logger.cpp} +1 -1
- package/native-src/src/{logger.h → librats/util/logger.h} +43 -31
- package/native-src/src/{network_monitor.cpp → librats/util/network_monitor.cpp} +12 -4
- package/native-src/src/{network_monitor.h → librats/util/network_monitor.h} +2 -1
- package/native-src/src/{network_utils.cpp → librats/util/network_utils.cpp} +38 -23
- package/native-src/src/{network_utils.h → librats/util/network_utils.h} +15 -8
- package/native-src/src/{os.cpp → librats/util/os.cpp} +48 -18
- package/native-src/src/librats/util/rats_export.h +69 -0
- package/native-src/src/{version.cpp → librats/util/version.cpp} +2 -2
- package/native-src/src/{version.h.in → librats/util/version.h.in} +1 -1
- package/native-src/src/librats/wire/frame.cpp +76 -0
- package/native-src/src/librats/wire/frame.h +111 -0
- package/native-src/src/librats/wire/message_router.cpp +45 -0
- package/native-src/src/librats/wire/message_router.h +47 -0
- package/package.json +5 -4
- package/scripts/build-librats.js +1 -0
- package/scripts/postinstall.js +3 -3
- package/scripts/prepare-package.js +4 -4
- package/scripts/verify-installation.js +63 -105
- package/src/librats_node.cpp +1067 -1323
- package/native-src/src/bencode.cpp +0 -485
- package/native-src/src/bencode.h +0 -145
- package/native-src/src/bittorrent.cpp +0 -14
- package/native-src/src/bittorrent.h +0 -74
- package/native-src/src/bt_bitfield.cpp +0 -372
- package/native-src/src/bt_bitfield.h +0 -316
- package/native-src/src/bt_choker.cpp +0 -228
- package/native-src/src/bt_choker.h +0 -147
- package/native-src/src/bt_client.cpp +0 -1047
- package/native-src/src/bt_client.h +0 -445
- package/native-src/src/bt_create_torrent.cpp +0 -677
- package/native-src/src/bt_create_torrent.h +0 -473
- package/native-src/src/bt_extension.cpp +0 -469
- package/native-src/src/bt_extension.h +0 -309
- package/native-src/src/bt_file_storage.cpp +0 -261
- package/native-src/src/bt_file_storage.h +0 -298
- package/native-src/src/bt_handshake.cpp +0 -134
- package/native-src/src/bt_handshake.h +0 -157
- package/native-src/src/bt_messages.cpp +0 -364
- package/native-src/src/bt_messages.h +0 -324
- package/native-src/src/bt_network.cpp +0 -1007
- package/native-src/src/bt_network.h +0 -417
- package/native-src/src/bt_peer_connection.cpp +0 -742
- package/native-src/src/bt_peer_connection.h +0 -592
- package/native-src/src/bt_piece_picker.cpp +0 -786
- package/native-src/src/bt_piece_picker.h +0 -473
- package/native-src/src/bt_resume_data.cpp +0 -410
- package/native-src/src/bt_resume_data.h +0 -249
- package/native-src/src/bt_torrent.cpp +0 -2120
- package/native-src/src/bt_torrent.h +0 -641
- package/native-src/src/bt_torrent_info.cpp +0 -659
- package/native-src/src/bt_torrent_info.h +0 -418
- package/native-src/src/bt_types.h +0 -621
- package/native-src/src/chained_send_buffer.cpp +0 -75
- package/native-src/src/chained_send_buffer.h +0 -137
- package/native-src/src/crypto/hkdf.c +0 -266
- package/native-src/src/crypto/poly1305.h +0 -36
- package/native-src/src/dht.cpp +0 -3311
- package/native-src/src/dht.h +0 -717
- package/native-src/src/disk_io.cpp +0 -632
- package/native-src/src/disk_io.h +0 -315
- package/native-src/src/file_transfer.cpp +0 -1415
- package/native-src/src/file_transfer.h +0 -286
- package/native-src/src/fs.h +0 -108
- package/native-src/src/gossipsub.cpp +0 -1139
- package/native-src/src/gossipsub.h +0 -403
- package/native-src/src/ice.cpp +0 -893
- package/native-src/src/ice.h +0 -559
- package/native-src/src/json.hpp +0 -25526
- package/native-src/src/librats.cpp +0 -2378
- package/native-src/src/librats.h +0 -2324
- package/native-src/src/librats_bittorrent.cpp +0 -601
- package/native-src/src/librats_c.cpp +0 -1557
- package/native-src/src/librats_c.h +0 -323
- package/native-src/src/librats_discovery.cpp +0 -402
- package/native-src/src/librats_encryption.cpp +0 -275
- package/native-src/src/librats_file_transfer.cpp +0 -144
- package/native-src/src/librats_gossipsub.cpp +0 -289
- package/native-src/src/librats_ice.cpp +0 -213
- package/native-src/src/librats_log_macros.h +0 -36
- package/native-src/src/librats_logging.cpp +0 -173
- package/native-src/src/librats_mdns.cpp +0 -166
- package/native-src/src/librats_persistence.cpp +0 -796
- package/native-src/src/librats_portmap.cpp +0 -419
- package/native-src/src/librats_reconnection.cpp +0 -218
- package/native-src/src/librats_statistic.cpp +0 -105
- package/native-src/src/librats_storage.cpp +0 -189
- package/native-src/src/rats_export.h +0 -17
- package/native-src/src/receive_buffer.cpp +0 -82
- package/native-src/src/receive_buffer.h +0 -127
- package/native-src/src/socket.h +0 -228
- package/native-src/src/threadmanager.cpp +0 -105
- package/native-src/src/threadmanager.h +0 -53
- package/native-src/src/tracker.cpp +0 -1264
- package/native-src/src/tracker.h +0 -319
- package/native-src/src/turn.cpp +0 -762
- package/native-src/src/turn.h +0 -460
- package/native-src/src/wakeup_pipe.h +0 -60
- /package/native-src/src/{os.h → librats/util/os.h} +0 -0
|
@@ -1,1557 +0,0 @@
|
|
|
1
|
-
#include "librats_c.h"
|
|
2
|
-
#include "librats.h"
|
|
3
|
-
#include "logger.h"
|
|
4
|
-
#include "ice.h"
|
|
5
|
-
#include <stdlib.h>
|
|
6
|
-
#include <string.h>
|
|
7
|
-
#include <algorithm>
|
|
8
|
-
#include <cctype>
|
|
9
|
-
#include <unordered_map>
|
|
10
|
-
#include <cstdio>
|
|
11
|
-
|
|
12
|
-
using namespace librats;
|
|
13
|
-
|
|
14
|
-
struct rats_client_wrapper {
|
|
15
|
-
std::unique_ptr<RatsClient> client;
|
|
16
|
-
|
|
17
|
-
// Stored C callbacks and user data
|
|
18
|
-
rats_connection_cb connection_cb = nullptr;
|
|
19
|
-
void* connection_ud = nullptr;
|
|
20
|
-
|
|
21
|
-
rats_string_cb string_cb = nullptr;
|
|
22
|
-
void* string_ud = nullptr;
|
|
23
|
-
|
|
24
|
-
rats_binary_cb binary_cb = nullptr;
|
|
25
|
-
void* binary_ud = nullptr;
|
|
26
|
-
|
|
27
|
-
rats_json_cb json_cb = nullptr;
|
|
28
|
-
void* json_ud = nullptr;
|
|
29
|
-
|
|
30
|
-
rats_disconnect_cb disconnect_cb = nullptr;
|
|
31
|
-
void* disconnect_ud = nullptr;
|
|
32
|
-
|
|
33
|
-
rats_peer_discovered_cb peer_discovered_cb = nullptr;
|
|
34
|
-
void* peer_discovered_ud = nullptr;
|
|
35
|
-
|
|
36
|
-
rats_file_progress_cb file_progress_cb = nullptr;
|
|
37
|
-
void* file_progress_ud = nullptr;
|
|
38
|
-
|
|
39
|
-
// File transfer callbacks
|
|
40
|
-
rats_file_request_cb file_request_cb = nullptr;
|
|
41
|
-
void* file_request_ud = nullptr;
|
|
42
|
-
|
|
43
|
-
rats_directory_request_cb directory_request_cb = nullptr;
|
|
44
|
-
void* directory_request_ud = nullptr;
|
|
45
|
-
|
|
46
|
-
rats_directory_progress_cb directory_progress_cb = nullptr;
|
|
47
|
-
void* directory_progress_ud = nullptr;
|
|
48
|
-
|
|
49
|
-
// Message handlers - using a simple map for demonstration
|
|
50
|
-
std::unordered_map<std::string, std::pair<rats_message_cb, void*>> message_handlers;
|
|
51
|
-
|
|
52
|
-
// GossipSub topic callbacks
|
|
53
|
-
std::unordered_map<std::string, std::pair<rats_topic_message_cb, void*>> topic_message_handlers;
|
|
54
|
-
std::unordered_map<std::string, std::pair<rats_topic_json_message_cb, void*>> topic_json_message_handlers;
|
|
55
|
-
std::unordered_map<std::string, std::pair<rats_topic_peer_joined_cb, void*>> topic_peer_joined_handlers;
|
|
56
|
-
std::unordered_map<std::string, std::pair<rats_topic_peer_left_cb, void*>> topic_peer_left_handlers;
|
|
57
|
-
};
|
|
58
|
-
|
|
59
|
-
static char* rats_strdup_owned(const std::string& s) {
|
|
60
|
-
size_t n = s.size();
|
|
61
|
-
char* out = static_cast<char*>(malloc(n + 1));
|
|
62
|
-
if (!out) return nullptr;
|
|
63
|
-
memcpy(out, s.c_str(), n);
|
|
64
|
-
out[n] = '\0';
|
|
65
|
-
return out;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
extern "C" {
|
|
69
|
-
|
|
70
|
-
void rats_string_free(const char* str) {
|
|
71
|
-
if (str) free((void*)str);
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
const char* rats_get_version_string(void) {
|
|
75
|
-
return rats_get_library_version_string();
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
void rats_get_version(int* major, int* minor, int* patch, int* build) {
|
|
79
|
-
rats_get_library_version(major, minor, patch, build);
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
const char* rats_get_git_describe(void) {
|
|
83
|
-
return rats_get_library_git_describe();
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
uint32_t rats_get_abi(void) {
|
|
87
|
-
return rats_get_library_abi();
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
rats_client_t rats_create(int listen_port) {
|
|
91
|
-
try {
|
|
92
|
-
rats_client_wrapper* wrap = new rats_client_wrapper();
|
|
93
|
-
wrap->client = std::make_unique<RatsClient>(listen_port);
|
|
94
|
-
return static_cast<rats_client_t>(wrap);
|
|
95
|
-
} catch (...) {
|
|
96
|
-
return nullptr;
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
void rats_destroy(rats_client_t handle) {
|
|
101
|
-
if (!handle) return;
|
|
102
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
103
|
-
// Ensure stopped
|
|
104
|
-
wrap->client->stop();
|
|
105
|
-
delete wrap;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
int rats_start(rats_client_t handle) {
|
|
109
|
-
if (!handle) return RATS_ERROR_INVALID_HANDLE;
|
|
110
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
111
|
-
return wrap->client->start() ? RATS_SUCCESS : RATS_ERROR_OPERATION_FAILED;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
void rats_stop(rats_client_t handle) {
|
|
115
|
-
if (!handle) return;
|
|
116
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
117
|
-
wrap->client->stop();
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
int rats_connect(rats_client_t handle, const char* host, int port) {
|
|
121
|
-
if (!handle || !host) return 0;
|
|
122
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
123
|
-
return wrap->client->connect_to_peer(std::string(host), port) ? 1 : 0;
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
int rats_get_listen_port(rats_client_t handle) {
|
|
127
|
-
if (!handle) return 0;
|
|
128
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
129
|
-
return wrap->client->get_listen_port();
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
int rats_broadcast_string(rats_client_t handle, const char* message) {
|
|
133
|
-
if (!handle || !message) return 0;
|
|
134
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
135
|
-
return wrap->client->broadcast_string_to_peers(std::string(message));
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
int rats_send_string(rats_client_t handle, const char* peer_id, const char* message) {
|
|
139
|
-
if (!handle) return RATS_ERROR_INVALID_HANDLE;
|
|
140
|
-
if (!peer_id || !message) return RATS_ERROR_INVALID_PARAMETER;
|
|
141
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
142
|
-
return wrap->client->send_string_to_peer_id(std::string(peer_id), std::string(message)) ? RATS_SUCCESS : RATS_ERROR_OPERATION_FAILED;
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
int rats_get_peer_count(rats_client_t handle) {
|
|
146
|
-
if (!handle) return 0;
|
|
147
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
148
|
-
return wrap->client->get_peer_count();
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
char* rats_get_our_peer_id(rats_client_t handle) {
|
|
152
|
-
if (!handle) return nullptr;
|
|
153
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
154
|
-
return rats_strdup_owned(wrap->client->get_our_peer_id());
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
char* rats_get_connection_statistics_json(rats_client_t handle) {
|
|
158
|
-
if (!handle) return nullptr;
|
|
159
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
160
|
-
auto json = wrap->client->get_connection_statistics();
|
|
161
|
-
return rats_strdup_owned(json.dump());
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
void rats_set_console_logging_enabled(int enabled) {
|
|
165
|
-
Logger::getInstance().set_console_logging_enabled(enabled != 0);
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
int rats_is_console_logging_enabled(void) {
|
|
169
|
-
return Logger::getInstance().is_console_logging_enabled() ? 1 : 0;
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
void rats_set_logging_enabled(int enabled) {
|
|
173
|
-
// Global logger control through any client instance is awkward; use singleton
|
|
174
|
-
Logger::getInstance().set_file_logging_enabled(enabled != 0);
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
void rats_set_log_level(const char* level_str) {
|
|
178
|
-
if (!level_str) return;
|
|
179
|
-
std::string lvl(level_str);
|
|
180
|
-
// Map string to LogLevel
|
|
181
|
-
std::string upper = lvl;
|
|
182
|
-
std::transform(upper.begin(), upper.end(), upper.begin(), ::toupper);
|
|
183
|
-
LogLevel level = LogLevel::INFO;
|
|
184
|
-
if (upper == "DEBUG") level = LogLevel::DEBUG;
|
|
185
|
-
else if (upper == "INFO") level = LogLevel::INFO;
|
|
186
|
-
else if (upper == "WARN" || upper == "WARNING") level = LogLevel::WARN;
|
|
187
|
-
else if (upper == "ERROR") level = LogLevel::ERROR;
|
|
188
|
-
Logger::getInstance().set_log_level(level);
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
void rats_set_log_file_path(rats_client_t handle, const char* file_path) {
|
|
193
|
-
if (!handle || !file_path) return;
|
|
194
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
195
|
-
wrap->client->set_log_file_path(std::string(file_path));
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
char* rats_get_log_file_path(rats_client_t handle) {
|
|
199
|
-
if (!handle) return nullptr;
|
|
200
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
201
|
-
return rats_strdup_owned(wrap->client->get_log_file_path());
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
void rats_set_log_colors_enabled(rats_client_t handle, int enabled) {
|
|
205
|
-
if (!handle) return;
|
|
206
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
207
|
-
wrap->client->set_log_colors_enabled(enabled != 0);
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
int rats_is_log_colors_enabled(rats_client_t handle) {
|
|
211
|
-
if (!handle) return 0;
|
|
212
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
213
|
-
return wrap->client->is_log_colors_enabled() ? 1 : 0;
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
void rats_set_log_timestamps_enabled(rats_client_t handle, int enabled) {
|
|
217
|
-
if (!handle) return;
|
|
218
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
219
|
-
wrap->client->set_log_timestamps_enabled(enabled != 0);
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
int rats_is_log_timestamps_enabled(rats_client_t handle) {
|
|
223
|
-
if (!handle) return 0;
|
|
224
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
225
|
-
return wrap->client->is_log_timestamps_enabled() ? 1 : 0;
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
void rats_set_log_rotation_size(rats_client_t handle, size_t max_size_bytes) {
|
|
229
|
-
if (!handle) return;
|
|
230
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
231
|
-
wrap->client->set_log_rotation_size(max_size_bytes);
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
void rats_set_log_retention_count(rats_client_t handle, int count) {
|
|
235
|
-
if (!handle) return;
|
|
236
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
237
|
-
wrap->client->set_log_retention_count(count);
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
void rats_set_log_rotate_on_startup(rats_client_t handle, int enabled) {
|
|
241
|
-
if (!handle) return;
|
|
242
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
243
|
-
wrap->client->set_log_rotate_on_startup(enabled != 0);
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
int rats_is_log_rotate_on_startup_enabled(rats_client_t handle) {
|
|
247
|
-
if (!handle) return 0;
|
|
248
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
249
|
-
return wrap->client->is_log_rotate_on_startup_enabled() ? 1 : 0;
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
void rats_clear_log_file(rats_client_t handle) {
|
|
253
|
-
if (!handle) return;
|
|
254
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
255
|
-
wrap->client->clear_log_file();
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
void rats_set_connection_callback(rats_client_t handle, rats_connection_cb cb, void* user_data) {
|
|
259
|
-
if (!handle) return;
|
|
260
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
261
|
-
wrap->connection_cb = cb;
|
|
262
|
-
wrap->connection_ud = user_data;
|
|
263
|
-
wrap->client->set_connection_callback([wrap](socket_t, const std::string& peer_id) {
|
|
264
|
-
if (wrap->connection_cb) {
|
|
265
|
-
wrap->connection_cb(wrap->connection_ud, peer_id.c_str());
|
|
266
|
-
}
|
|
267
|
-
});
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
void rats_set_string_callback(rats_client_t handle, rats_string_cb cb, void* user_data) {
|
|
271
|
-
if (!handle) return;
|
|
272
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
273
|
-
wrap->string_cb = cb;
|
|
274
|
-
wrap->string_ud = user_data;
|
|
275
|
-
wrap->client->set_string_data_callback([wrap](socket_t, const std::string& peer_id, const std::string& data) {
|
|
276
|
-
if (wrap->string_cb) {
|
|
277
|
-
wrap->string_cb(wrap->string_ud, peer_id.c_str(), data.c_str());
|
|
278
|
-
}
|
|
279
|
-
});
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
void rats_set_disconnect_callback(rats_client_t handle, rats_disconnect_cb cb, void* user_data) {
|
|
283
|
-
if (!handle) return;
|
|
284
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
285
|
-
wrap->disconnect_cb = cb;
|
|
286
|
-
wrap->disconnect_ud = user_data;
|
|
287
|
-
wrap->client->set_disconnect_callback([wrap](socket_t, const std::string& peer_id) {
|
|
288
|
-
if (wrap->disconnect_cb) {
|
|
289
|
-
wrap->disconnect_cb(wrap->disconnect_ud, peer_id.c_str());
|
|
290
|
-
}
|
|
291
|
-
});
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
// ===================== NEW C API IMPLEMENTATIONS =====================
|
|
295
|
-
|
|
296
|
-
// Peer configuration
|
|
297
|
-
rats_error_t rats_set_max_peers(rats_client_t handle, int max_peers) {
|
|
298
|
-
if (!handle) return RATS_ERROR_INVALID_HANDLE;
|
|
299
|
-
if (max_peers <= 0) return RATS_ERROR_INVALID_PARAMETER;
|
|
300
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
301
|
-
wrap->client->set_max_peers(max_peers);
|
|
302
|
-
return RATS_SUCCESS;
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
int rats_get_max_peers(rats_client_t handle) {
|
|
306
|
-
if (!handle) return 0;
|
|
307
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
308
|
-
return wrap->client->get_max_peers();
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
int rats_is_peer_limit_reached(rats_client_t handle) {
|
|
312
|
-
if (!handle) return 0;
|
|
313
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
314
|
-
return wrap->client->is_peer_limit_reached() ? 1 : 0;
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
rats_error_t rats_disconnect_peer_by_id(rats_client_t handle, const char* peer_id) {
|
|
318
|
-
if (!handle || !peer_id) return RATS_ERROR_INVALID_PARAMETER;
|
|
319
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
320
|
-
wrap->client->disconnect_peer_by_id(std::string(peer_id));
|
|
321
|
-
return RATS_SUCCESS;
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
// Binary data operations
|
|
325
|
-
rats_error_t rats_send_binary(rats_client_t handle, const char* peer_id, const void* data, size_t size) {
|
|
326
|
-
if (!handle || !peer_id || !data || size == 0) return RATS_ERROR_INVALID_PARAMETER;
|
|
327
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
328
|
-
|
|
329
|
-
std::vector<uint8_t> binary_data(static_cast<const uint8_t*>(data),
|
|
330
|
-
static_cast<const uint8_t*>(data) + size);
|
|
331
|
-
|
|
332
|
-
return wrap->client->send_binary_to_peer_id(std::string(peer_id), binary_data) ?
|
|
333
|
-
RATS_SUCCESS : RATS_ERROR_OPERATION_FAILED;
|
|
334
|
-
}
|
|
335
|
-
|
|
336
|
-
int rats_broadcast_binary(rats_client_t handle, const void* data, size_t size) {
|
|
337
|
-
if (!handle || !data || size == 0) return 0;
|
|
338
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
339
|
-
|
|
340
|
-
std::vector<uint8_t> binary_data(static_cast<const uint8_t*>(data),
|
|
341
|
-
static_cast<const uint8_t*>(data) + size);
|
|
342
|
-
|
|
343
|
-
return wrap->client->broadcast_binary_to_peers(binary_data);
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
// JSON operations
|
|
347
|
-
rats_error_t rats_send_json(rats_client_t handle, const char* peer_id, const char* json_str) {
|
|
348
|
-
if (!handle || !peer_id || !json_str) return RATS_ERROR_INVALID_PARAMETER;
|
|
349
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
350
|
-
|
|
351
|
-
try {
|
|
352
|
-
nlohmann::json json_data = nlohmann::json::parse(json_str);
|
|
353
|
-
return wrap->client->send_json_to_peer_id(std::string(peer_id), json_data) ?
|
|
354
|
-
RATS_SUCCESS : RATS_ERROR_OPERATION_FAILED;
|
|
355
|
-
} catch (const nlohmann::json::exception&) {
|
|
356
|
-
return RATS_ERROR_JSON_PARSE;
|
|
357
|
-
}
|
|
358
|
-
}
|
|
359
|
-
|
|
360
|
-
int rats_broadcast_json(rats_client_t handle, const char* json_str) {
|
|
361
|
-
if (!handle || !json_str) return 0;
|
|
362
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
363
|
-
|
|
364
|
-
try {
|
|
365
|
-
nlohmann::json json_data = nlohmann::json::parse(json_str);
|
|
366
|
-
return wrap->client->broadcast_json_to_peers(json_data);
|
|
367
|
-
} catch (const nlohmann::json::exception&) {
|
|
368
|
-
return 0;
|
|
369
|
-
}
|
|
370
|
-
}
|
|
371
|
-
|
|
372
|
-
// DHT Discovery
|
|
373
|
-
rats_error_t rats_start_dht_discovery(rats_client_t handle, int dht_port) {
|
|
374
|
-
if (!handle) return RATS_ERROR_INVALID_HANDLE;
|
|
375
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
376
|
-
return wrap->client->start_dht_discovery(dht_port) ? RATS_SUCCESS : RATS_ERROR_OPERATION_FAILED;
|
|
377
|
-
}
|
|
378
|
-
|
|
379
|
-
void rats_stop_dht_discovery(rats_client_t handle) {
|
|
380
|
-
if (!handle) return;
|
|
381
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
382
|
-
wrap->client->stop_dht_discovery();
|
|
383
|
-
}
|
|
384
|
-
|
|
385
|
-
int rats_is_dht_running(rats_client_t handle) {
|
|
386
|
-
if (!handle) return 0;
|
|
387
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
388
|
-
return wrap->client->is_dht_running() ? 1 : 0;
|
|
389
|
-
}
|
|
390
|
-
|
|
391
|
-
rats_error_t rats_announce_for_hash(rats_client_t handle, const char* content_hash, int port,
|
|
392
|
-
rats_peers_found_cb callback, void* user_data) {
|
|
393
|
-
if (!handle || !content_hash) return RATS_ERROR_INVALID_PARAMETER;
|
|
394
|
-
if (strlen(content_hash) != 40) return RATS_ERROR_INVALID_PARAMETER; // SHA1 hash must be 40 chars
|
|
395
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
396
|
-
|
|
397
|
-
uint16_t announce_port = (port <= 0) ? 0 : static_cast<uint16_t>(port);
|
|
398
|
-
|
|
399
|
-
// Create C++ callback wrapper if C callback is provided
|
|
400
|
-
std::function<void(const std::vector<std::string>&)> cpp_callback = nullptr;
|
|
401
|
-
if (callback) {
|
|
402
|
-
cpp_callback = [callback, user_data](const std::vector<std::string>& peers) {
|
|
403
|
-
// Convert vector to C-style array
|
|
404
|
-
std::vector<const char*> c_peers;
|
|
405
|
-
c_peers.reserve(peers.size());
|
|
406
|
-
for (const auto& peer : peers) {
|
|
407
|
-
c_peers.push_back(peer.c_str());
|
|
408
|
-
}
|
|
409
|
-
callback(user_data, c_peers.data(), static_cast<int>(c_peers.size()));
|
|
410
|
-
};
|
|
411
|
-
}
|
|
412
|
-
|
|
413
|
-
return wrap->client->announce_for_hash(std::string(content_hash), announce_port, cpp_callback) ?
|
|
414
|
-
RATS_SUCCESS : RATS_ERROR_OPERATION_FAILED;
|
|
415
|
-
}
|
|
416
|
-
|
|
417
|
-
size_t rats_get_dht_routing_table_size(rats_client_t handle) {
|
|
418
|
-
if (!handle) return 0;
|
|
419
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
420
|
-
return wrap->client->get_dht_routing_table_size();
|
|
421
|
-
}
|
|
422
|
-
|
|
423
|
-
// Automatic discovery
|
|
424
|
-
|
|
425
|
-
void rats_start_automatic_peer_discovery(rats_client_t handle) {
|
|
426
|
-
if (!handle) return;
|
|
427
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
428
|
-
wrap->client->start_automatic_peer_discovery();
|
|
429
|
-
}
|
|
430
|
-
|
|
431
|
-
void rats_stop_automatic_peer_discovery(rats_client_t handle) {
|
|
432
|
-
if (!handle) return;
|
|
433
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
434
|
-
wrap->client->stop_automatic_peer_discovery();
|
|
435
|
-
}
|
|
436
|
-
|
|
437
|
-
int rats_is_automatic_discovery_running(rats_client_t handle) {
|
|
438
|
-
if (!handle) return 0;
|
|
439
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
440
|
-
return wrap->client->is_automatic_discovery_running() ? 1 : 0;
|
|
441
|
-
}
|
|
442
|
-
|
|
443
|
-
char* rats_get_discovery_hash(rats_client_t handle) {
|
|
444
|
-
if (!handle) return nullptr;
|
|
445
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
446
|
-
return rats_strdup_owned(wrap->client->get_discovery_hash());
|
|
447
|
-
}
|
|
448
|
-
|
|
449
|
-
char* rats_get_rats_peer_discovery_hash(void) {
|
|
450
|
-
return rats_strdup_owned(RatsClient::get_rats_peer_discovery_hash());
|
|
451
|
-
}
|
|
452
|
-
|
|
453
|
-
// mDNS Discovery
|
|
454
|
-
rats_error_t rats_start_mdns_discovery(rats_client_t handle, const char* service_name) {
|
|
455
|
-
if (!handle) return RATS_ERROR_INVALID_HANDLE;
|
|
456
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
457
|
-
|
|
458
|
-
std::string service = service_name ? std::string(service_name) : std::string("");
|
|
459
|
-
return wrap->client->start_mdns_discovery(service) ? RATS_SUCCESS : RATS_ERROR_OPERATION_FAILED;
|
|
460
|
-
}
|
|
461
|
-
|
|
462
|
-
void rats_stop_mdns_discovery(rats_client_t handle) {
|
|
463
|
-
if (!handle) return;
|
|
464
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
465
|
-
wrap->client->stop_mdns_discovery();
|
|
466
|
-
}
|
|
467
|
-
|
|
468
|
-
int rats_is_mdns_running(rats_client_t handle) {
|
|
469
|
-
if (!handle) return 0;
|
|
470
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
471
|
-
return wrap->client->is_mdns_running() ? 1 : 0;
|
|
472
|
-
}
|
|
473
|
-
|
|
474
|
-
rats_error_t rats_query_mdns_services(rats_client_t handle) {
|
|
475
|
-
if (!handle) return RATS_ERROR_INVALID_HANDLE;
|
|
476
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
477
|
-
return wrap->client->query_mdns_services() ? RATS_SUCCESS : RATS_ERROR_OPERATION_FAILED;
|
|
478
|
-
}
|
|
479
|
-
|
|
480
|
-
// Encryption
|
|
481
|
-
rats_error_t rats_set_encryption_enabled(rats_client_t handle, int enabled) {
|
|
482
|
-
if (!handle) return RATS_ERROR_INVALID_HANDLE;
|
|
483
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
484
|
-
wrap->client->set_encryption_enabled(enabled != 0);
|
|
485
|
-
return RATS_SUCCESS;
|
|
486
|
-
}
|
|
487
|
-
|
|
488
|
-
int rats_is_encryption_enabled(rats_client_t handle) {
|
|
489
|
-
if (!handle) return 0;
|
|
490
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
491
|
-
return wrap->client->is_encryption_enabled() ? 1 : 0;
|
|
492
|
-
}
|
|
493
|
-
|
|
494
|
-
// Protocol configuration
|
|
495
|
-
rats_error_t rats_set_protocol_name(rats_client_t handle, const char* protocol_name) {
|
|
496
|
-
if (!handle || !protocol_name) return RATS_ERROR_INVALID_PARAMETER;
|
|
497
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
498
|
-
wrap->client->set_protocol_name(std::string(protocol_name));
|
|
499
|
-
return RATS_SUCCESS;
|
|
500
|
-
}
|
|
501
|
-
|
|
502
|
-
rats_error_t rats_set_protocol_version(rats_client_t handle, const char* protocol_version) {
|
|
503
|
-
if (!handle || !protocol_version) return RATS_ERROR_INVALID_PARAMETER;
|
|
504
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
505
|
-
wrap->client->set_protocol_version(std::string(protocol_version));
|
|
506
|
-
return RATS_SUCCESS;
|
|
507
|
-
}
|
|
508
|
-
|
|
509
|
-
char* rats_get_protocol_name(rats_client_t handle) {
|
|
510
|
-
if (!handle) return nullptr;
|
|
511
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
512
|
-
return rats_strdup_owned(wrap->client->get_protocol_name());
|
|
513
|
-
}
|
|
514
|
-
|
|
515
|
-
char* rats_get_protocol_version(rats_client_t handle) {
|
|
516
|
-
if (!handle) return nullptr;
|
|
517
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
518
|
-
return rats_strdup_owned(wrap->client->get_protocol_version());
|
|
519
|
-
}
|
|
520
|
-
|
|
521
|
-
// Message Exchange API
|
|
522
|
-
rats_error_t rats_on_message(rats_client_t handle, const char* message_type,
|
|
523
|
-
rats_message_cb callback, void* user_data) {
|
|
524
|
-
if (!handle || !message_type || !callback) return RATS_ERROR_INVALID_PARAMETER;
|
|
525
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
526
|
-
|
|
527
|
-
// Store the C callback
|
|
528
|
-
wrap->message_handlers[std::string(message_type)] = std::make_pair(callback, user_data);
|
|
529
|
-
|
|
530
|
-
// Set up C++ callback that calls the C callback
|
|
531
|
-
wrap->client->on(std::string(message_type), [wrap, callback, user_data](const std::string& peer_id, const nlohmann::json& data) {
|
|
532
|
-
if (callback) {
|
|
533
|
-
std::string json_str = data.dump();
|
|
534
|
-
callback(user_data, peer_id.c_str(), json_str.c_str());
|
|
535
|
-
}
|
|
536
|
-
});
|
|
537
|
-
|
|
538
|
-
return RATS_SUCCESS;
|
|
539
|
-
}
|
|
540
|
-
|
|
541
|
-
rats_error_t rats_send_message(rats_client_t handle, const char* peer_id,
|
|
542
|
-
const char* message_type, const char* data) {
|
|
543
|
-
if (!handle || !peer_id || !message_type || !data) return RATS_ERROR_INVALID_PARAMETER;
|
|
544
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
545
|
-
|
|
546
|
-
try {
|
|
547
|
-
nlohmann::json json_data = nlohmann::json::parse(data);
|
|
548
|
-
wrap->client->send(std::string(peer_id), std::string(message_type), json_data);
|
|
549
|
-
return RATS_SUCCESS;
|
|
550
|
-
} catch (const nlohmann::json::exception&) {
|
|
551
|
-
// If not valid JSON, send as string value
|
|
552
|
-
nlohmann::json string_data = std::string(data);
|
|
553
|
-
wrap->client->send(std::string(peer_id), std::string(message_type), string_data);
|
|
554
|
-
return RATS_SUCCESS;
|
|
555
|
-
}
|
|
556
|
-
}
|
|
557
|
-
|
|
558
|
-
rats_error_t rats_broadcast_message(rats_client_t handle, const char* message_type, const char* data) {
|
|
559
|
-
if (!handle || !message_type || !data) return RATS_ERROR_INVALID_PARAMETER;
|
|
560
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
561
|
-
|
|
562
|
-
try {
|
|
563
|
-
nlohmann::json json_data = nlohmann::json::parse(data);
|
|
564
|
-
wrap->client->send(std::string(message_type), json_data);
|
|
565
|
-
return RATS_SUCCESS;
|
|
566
|
-
} catch (const nlohmann::json::exception&) {
|
|
567
|
-
// If not valid JSON, send as string value
|
|
568
|
-
nlohmann::json string_data = std::string(data);
|
|
569
|
-
wrap->client->send(std::string(message_type), string_data);
|
|
570
|
-
return RATS_SUCCESS;
|
|
571
|
-
}
|
|
572
|
-
}
|
|
573
|
-
|
|
574
|
-
// File Transfer
|
|
575
|
-
char* rats_send_file(rats_client_t handle, const char* peer_id,
|
|
576
|
-
const char* file_path, const char* remote_filename) {
|
|
577
|
-
if (!handle || !peer_id || !file_path) return nullptr;
|
|
578
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
579
|
-
|
|
580
|
-
std::string remote_name = remote_filename ? std::string(remote_filename) : std::string("");
|
|
581
|
-
std::string transfer_id = wrap->client->send_file(std::string(peer_id),
|
|
582
|
-
std::string(file_path), remote_name);
|
|
583
|
-
|
|
584
|
-
return transfer_id.empty() ? nullptr : rats_strdup_owned(transfer_id);
|
|
585
|
-
}
|
|
586
|
-
|
|
587
|
-
rats_error_t rats_accept_file_transfer(rats_client_t handle, const char* transfer_id,
|
|
588
|
-
const char* local_path) {
|
|
589
|
-
if (!handle || !transfer_id || !local_path) return RATS_ERROR_INVALID_PARAMETER;
|
|
590
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
591
|
-
|
|
592
|
-
return wrap->client->accept_file_transfer(std::string(transfer_id), std::string(local_path)) ?
|
|
593
|
-
RATS_SUCCESS : RATS_ERROR_OPERATION_FAILED;
|
|
594
|
-
}
|
|
595
|
-
|
|
596
|
-
rats_error_t rats_reject_file_transfer(rats_client_t handle, const char* transfer_id,
|
|
597
|
-
const char* reason) {
|
|
598
|
-
if (!handle || !transfer_id) return RATS_ERROR_INVALID_PARAMETER;
|
|
599
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
600
|
-
|
|
601
|
-
std::string reject_reason = reason ? std::string(reason) : std::string("");
|
|
602
|
-
return wrap->client->reject_file_transfer(std::string(transfer_id), reject_reason) ?
|
|
603
|
-
RATS_SUCCESS : RATS_ERROR_OPERATION_FAILED;
|
|
604
|
-
}
|
|
605
|
-
|
|
606
|
-
rats_error_t rats_cancel_file_transfer(rats_client_t handle, const char* transfer_id) {
|
|
607
|
-
if (!handle || !transfer_id) return RATS_ERROR_INVALID_PARAMETER;
|
|
608
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
609
|
-
|
|
610
|
-
return wrap->client->cancel_file_transfer(std::string(transfer_id)) ?
|
|
611
|
-
RATS_SUCCESS : RATS_ERROR_OPERATION_FAILED;
|
|
612
|
-
}
|
|
613
|
-
|
|
614
|
-
// Enhanced callbacks
|
|
615
|
-
void rats_set_binary_callback(rats_client_t handle, rats_binary_cb cb, void* user_data) {
|
|
616
|
-
if (!handle) return;
|
|
617
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
618
|
-
wrap->binary_cb = cb;
|
|
619
|
-
wrap->binary_ud = user_data;
|
|
620
|
-
wrap->client->set_binary_data_callback([wrap](socket_t, const std::string& peer_id, const std::vector<uint8_t>& data) {
|
|
621
|
-
if (wrap->binary_cb) {
|
|
622
|
-
wrap->binary_cb(wrap->binary_ud, peer_id.c_str(), data.data(), data.size());
|
|
623
|
-
}
|
|
624
|
-
});
|
|
625
|
-
}
|
|
626
|
-
|
|
627
|
-
void rats_set_json_callback(rats_client_t handle, rats_json_cb cb, void* user_data) {
|
|
628
|
-
if (!handle) return;
|
|
629
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
630
|
-
wrap->json_cb = cb;
|
|
631
|
-
wrap->json_ud = user_data;
|
|
632
|
-
wrap->client->set_json_data_callback([wrap](socket_t, const std::string& peer_id, const nlohmann::json& data) {
|
|
633
|
-
if (wrap->json_cb) {
|
|
634
|
-
std::string json_str = data.dump();
|
|
635
|
-
wrap->json_cb(wrap->json_ud, peer_id.c_str(), json_str.c_str());
|
|
636
|
-
}
|
|
637
|
-
});
|
|
638
|
-
}
|
|
639
|
-
|
|
640
|
-
void rats_set_peer_discovered_callback(rats_client_t handle, rats_peer_discovered_cb cb, void* user_data) {
|
|
641
|
-
if (!handle) return;
|
|
642
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
643
|
-
wrap->peer_discovered_cb = cb;
|
|
644
|
-
wrap->peer_discovered_ud = user_data;
|
|
645
|
-
wrap->client->set_mdns_callback([wrap](const std::string& host, int port, const std::string& service_name) {
|
|
646
|
-
if (wrap->peer_discovered_cb) {
|
|
647
|
-
wrap->peer_discovered_cb(wrap->peer_discovered_ud, host.c_str(), port, service_name.c_str());
|
|
648
|
-
}
|
|
649
|
-
});
|
|
650
|
-
}
|
|
651
|
-
|
|
652
|
-
void rats_set_file_progress_callback(rats_client_t handle, rats_file_progress_cb cb, void* user_data) {
|
|
653
|
-
if (!handle) return;
|
|
654
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
655
|
-
wrap->file_progress_cb = cb;
|
|
656
|
-
wrap->file_progress_ud = user_data;
|
|
657
|
-
|
|
658
|
-
wrap->client->on_file_transfer_progress([wrap](const FileTransferProgress& progress) {
|
|
659
|
-
if (wrap->file_progress_cb) {
|
|
660
|
-
int progress_percent = progress.get_completion_percentage();
|
|
661
|
-
std::string status_str = "IN_PROGRESS"; // Default status
|
|
662
|
-
switch (progress.status) {
|
|
663
|
-
case FileTransferStatus::PENDING: status_str = "PENDING"; break;
|
|
664
|
-
case FileTransferStatus::STARTING: status_str = "STARTING"; break;
|
|
665
|
-
case FileTransferStatus::IN_PROGRESS: status_str = "IN_PROGRESS"; break;
|
|
666
|
-
case FileTransferStatus::PAUSED: status_str = "PAUSED"; break;
|
|
667
|
-
case FileTransferStatus::COMPLETED: status_str = "COMPLETED"; break;
|
|
668
|
-
case FileTransferStatus::FAILED: status_str = "FAILED"; break;
|
|
669
|
-
case FileTransferStatus::CANCELLED: status_str = "CANCELLED"; break;
|
|
670
|
-
case FileTransferStatus::RESUMING: status_str = "RESUMING"; break;
|
|
671
|
-
}
|
|
672
|
-
wrap->file_progress_cb(wrap->file_progress_ud, progress.transfer_id.c_str(), progress_percent, status_str.c_str());
|
|
673
|
-
}
|
|
674
|
-
});
|
|
675
|
-
}
|
|
676
|
-
|
|
677
|
-
char* rats_send_directory(rats_client_t handle, const char* peer_id, const char* directory_path, const char* remote_directory_name, int recursive) {
|
|
678
|
-
if (!handle || !peer_id || !directory_path) return nullptr;
|
|
679
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
680
|
-
|
|
681
|
-
std::string remote_name = remote_directory_name ? std::string(remote_directory_name) : std::string("");
|
|
682
|
-
(void)recursive; // directory transfers are always recursive
|
|
683
|
-
std::string transfer_id = wrap->client->send_directory(std::string(peer_id), std::string(directory_path), remote_name);
|
|
684
|
-
|
|
685
|
-
return transfer_id.empty() ? nullptr : rats_strdup_owned(transfer_id);
|
|
686
|
-
}
|
|
687
|
-
|
|
688
|
-
// Pull-style requests are not supported in this version; transfers are push-only.
|
|
689
|
-
char* rats_request_file(rats_client_t handle, const char* peer_id, const char* remote_file_path, const char* local_path) {
|
|
690
|
-
(void)handle; (void)peer_id; (void)remote_file_path; (void)local_path;
|
|
691
|
-
return nullptr;
|
|
692
|
-
}
|
|
693
|
-
|
|
694
|
-
char* rats_request_directory(rats_client_t handle, const char* peer_id, const char* remote_directory_path, const char* local_directory_path, int recursive) {
|
|
695
|
-
(void)handle; (void)peer_id; (void)remote_directory_path; (void)local_directory_path; (void)recursive;
|
|
696
|
-
return nullptr;
|
|
697
|
-
}
|
|
698
|
-
|
|
699
|
-
rats_error_t rats_accept_directory_transfer(rats_client_t handle, const char* transfer_id, const char* local_path) {
|
|
700
|
-
if (!handle || !transfer_id || !local_path) return RATS_ERROR_INVALID_PARAMETER;
|
|
701
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
702
|
-
|
|
703
|
-
return wrap->client->accept_file_transfer(std::string(transfer_id), std::string(local_path)) ? RATS_SUCCESS : RATS_ERROR_OPERATION_FAILED;
|
|
704
|
-
}
|
|
705
|
-
|
|
706
|
-
rats_error_t rats_reject_directory_transfer(rats_client_t handle, const char* transfer_id, const char* reason) {
|
|
707
|
-
if (!handle || !transfer_id) return RATS_ERROR_INVALID_PARAMETER;
|
|
708
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
709
|
-
|
|
710
|
-
std::string reject_reason = reason ? std::string(reason) : std::string("");
|
|
711
|
-
return wrap->client->reject_file_transfer(std::string(transfer_id), reject_reason) ? RATS_SUCCESS : RATS_ERROR_OPERATION_FAILED;
|
|
712
|
-
}
|
|
713
|
-
|
|
714
|
-
rats_error_t rats_pause_file_transfer(rats_client_t handle, const char* transfer_id) {
|
|
715
|
-
if (!handle || !transfer_id) return RATS_ERROR_INVALID_PARAMETER;
|
|
716
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
717
|
-
|
|
718
|
-
return wrap->client->pause_file_transfer(std::string(transfer_id)) ? RATS_SUCCESS : RATS_ERROR_OPERATION_FAILED;
|
|
719
|
-
}
|
|
720
|
-
|
|
721
|
-
rats_error_t rats_resume_file_transfer(rats_client_t handle, const char* transfer_id) {
|
|
722
|
-
if (!handle || !transfer_id) return RATS_ERROR_INVALID_PARAMETER;
|
|
723
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
724
|
-
|
|
725
|
-
return wrap->client->resume_file_transfer(std::string(transfer_id)) ? RATS_SUCCESS : RATS_ERROR_OPERATION_FAILED;
|
|
726
|
-
}
|
|
727
|
-
|
|
728
|
-
char* rats_get_file_transfer_progress_json(rats_client_t handle, const char* transfer_id) {
|
|
729
|
-
if (!handle || !transfer_id) return nullptr;
|
|
730
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
731
|
-
|
|
732
|
-
auto progress = wrap->client->get_file_transfer_progress(std::string(transfer_id));
|
|
733
|
-
if (!progress) return nullptr;
|
|
734
|
-
|
|
735
|
-
// Convert progress to JSON
|
|
736
|
-
nlohmann::json progress_json;
|
|
737
|
-
progress_json["transfer_id"] = progress->transfer_id;
|
|
738
|
-
progress_json["filename"] = progress->filename;
|
|
739
|
-
progress_json["local_path"] = progress->local_path;
|
|
740
|
-
progress_json["peer_id"] = progress->peer_id;
|
|
741
|
-
progress_json["bytes_transferred"] = progress->bytes_transferred;
|
|
742
|
-
progress_json["total_bytes"] = progress->total_bytes;
|
|
743
|
-
progress_json["completion_percentage"] = progress->get_completion_percentage();
|
|
744
|
-
progress_json["status"] = static_cast<int>(progress->status);
|
|
745
|
-
progress_json["direction"] = static_cast<int>(progress->direction);
|
|
746
|
-
|
|
747
|
-
return rats_strdup_owned(progress_json.dump());
|
|
748
|
-
}
|
|
749
|
-
|
|
750
|
-
char* rats_get_file_transfer_statistics_json(rats_client_t handle) {
|
|
751
|
-
if (!handle) return nullptr;
|
|
752
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
753
|
-
auto stats = wrap->client->get_file_transfer_statistics();
|
|
754
|
-
return rats_strdup_owned(stats.dump());
|
|
755
|
-
}
|
|
756
|
-
|
|
757
|
-
// File transfer callback setters
|
|
758
|
-
void rats_set_file_request_callback(rats_client_t handle, rats_file_request_cb cb, void* user_data) {
|
|
759
|
-
if (!handle) return;
|
|
760
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
761
|
-
wrap->file_request_cb = cb;
|
|
762
|
-
wrap->file_request_ud = user_data;
|
|
763
|
-
|
|
764
|
-
if (cb) {
|
|
765
|
-
// Fires for every incoming offer (file or directory). The C app should
|
|
766
|
-
// then call rats_accept_file_transfer()/rats_reject_file_transfer().
|
|
767
|
-
wrap->client->on_file_transfer_request([wrap](const IncomingTransferOffer& offer) {
|
|
768
|
-
if (wrap->file_request_cb) {
|
|
769
|
-
wrap->file_request_cb(wrap->file_request_ud, offer.peer_id.c_str(),
|
|
770
|
-
offer.transfer_id.c_str(), "", offer.name.c_str());
|
|
771
|
-
}
|
|
772
|
-
});
|
|
773
|
-
}
|
|
774
|
-
}
|
|
775
|
-
|
|
776
|
-
// Directory offers arrive through the unified file-request callback above;
|
|
777
|
-
// this setter is kept for ABI compatibility and simply records the callback.
|
|
778
|
-
void rats_set_directory_request_callback(rats_client_t handle, rats_directory_request_cb cb, void* user_data) {
|
|
779
|
-
if (!handle) return;
|
|
780
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
781
|
-
wrap->directory_request_cb = cb;
|
|
782
|
-
wrap->directory_request_ud = user_data;
|
|
783
|
-
}
|
|
784
|
-
|
|
785
|
-
// Directory progress arrives through the unified file-progress callback above;
|
|
786
|
-
// this setter is kept for ABI compatibility and simply records the callback.
|
|
787
|
-
void rats_set_directory_progress_callback(rats_client_t handle, rats_directory_progress_cb cb, void* user_data) {
|
|
788
|
-
if (!handle) return;
|
|
789
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
790
|
-
wrap->directory_progress_cb = cb;
|
|
791
|
-
wrap->directory_progress_ud = user_data;
|
|
792
|
-
}
|
|
793
|
-
|
|
794
|
-
// Peer information
|
|
795
|
-
char** rats_get_peer_ids(rats_client_t handle, int* count) {
|
|
796
|
-
if (!handle || !count) {
|
|
797
|
-
if (count) *count = 0;
|
|
798
|
-
return nullptr;
|
|
799
|
-
}
|
|
800
|
-
|
|
801
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
802
|
-
auto peers = wrap->client->get_validated_peers();
|
|
803
|
-
|
|
804
|
-
*count = static_cast<int>(peers.size());
|
|
805
|
-
if (*count == 0) return nullptr;
|
|
806
|
-
|
|
807
|
-
char** peer_ids = static_cast<char**>(malloc(*count * sizeof(char*)));
|
|
808
|
-
if (!peer_ids) {
|
|
809
|
-
*count = 0;
|
|
810
|
-
return nullptr;
|
|
811
|
-
}
|
|
812
|
-
|
|
813
|
-
for (int i = 0; i < *count; ++i) {
|
|
814
|
-
peer_ids[i] = rats_strdup_owned(peers[i].peer_id);
|
|
815
|
-
if (!peer_ids[i]) {
|
|
816
|
-
// Clean up on allocation failure
|
|
817
|
-
for (int j = 0; j < i; ++j) {
|
|
818
|
-
free(peer_ids[j]);
|
|
819
|
-
}
|
|
820
|
-
free(peer_ids);
|
|
821
|
-
*count = 0;
|
|
822
|
-
return nullptr;
|
|
823
|
-
}
|
|
824
|
-
}
|
|
825
|
-
|
|
826
|
-
return peer_ids;
|
|
827
|
-
}
|
|
828
|
-
|
|
829
|
-
char* rats_get_peer_info_json(rats_client_t handle, const char* peer_id) {
|
|
830
|
-
if (!handle || !peer_id) return nullptr;
|
|
831
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
832
|
-
|
|
833
|
-
auto peer = wrap->client->get_peer_by_id(std::string(peer_id));
|
|
834
|
-
if (!peer) return nullptr;
|
|
835
|
-
|
|
836
|
-
// Create JSON representation of peer info
|
|
837
|
-
nlohmann::json peer_info;
|
|
838
|
-
peer_info["peer_id"] = peer->peer_id;
|
|
839
|
-
peer_info["ip"] = peer->ip;
|
|
840
|
-
peer_info["port"] = peer->port;
|
|
841
|
-
peer_info["is_outgoing"] = peer->is_outgoing;
|
|
842
|
-
peer_info["handshake_completed"] = peer->is_handshake_completed();
|
|
843
|
-
peer_info["version"] = peer->version;
|
|
844
|
-
peer_info["encryption_enabled"] = peer->encryption_enabled;
|
|
845
|
-
|
|
846
|
-
return rats_strdup_owned(peer_info.dump());
|
|
847
|
-
}
|
|
848
|
-
|
|
849
|
-
char** rats_get_validated_peer_ids(rats_client_t handle, int* count) {
|
|
850
|
-
if (!handle || !count) {
|
|
851
|
-
if (count) *count = 0;
|
|
852
|
-
return nullptr;
|
|
853
|
-
}
|
|
854
|
-
|
|
855
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
856
|
-
auto peers = wrap->client->get_validated_peers();
|
|
857
|
-
|
|
858
|
-
*count = static_cast<int>(peers.size());
|
|
859
|
-
if (*count == 0) return nullptr;
|
|
860
|
-
|
|
861
|
-
char** peer_ids = static_cast<char**>(malloc(*count * sizeof(char*)));
|
|
862
|
-
if (!peer_ids) {
|
|
863
|
-
*count = 0;
|
|
864
|
-
return nullptr;
|
|
865
|
-
}
|
|
866
|
-
|
|
867
|
-
for (int i = 0; i < *count; ++i) {
|
|
868
|
-
peer_ids[i] = rats_strdup_owned(peers[i].peer_id);
|
|
869
|
-
if (!peer_ids[i]) {
|
|
870
|
-
// Clean up on allocation failure
|
|
871
|
-
for (int j = 0; j < i; ++j) {
|
|
872
|
-
free(peer_ids[j]);
|
|
873
|
-
}
|
|
874
|
-
free(peer_ids);
|
|
875
|
-
*count = 0;
|
|
876
|
-
return nullptr;
|
|
877
|
-
}
|
|
878
|
-
}
|
|
879
|
-
|
|
880
|
-
return peer_ids;
|
|
881
|
-
}
|
|
882
|
-
|
|
883
|
-
// ===================== GOSSIPSUB FUNCTIONALITY =====================
|
|
884
|
-
|
|
885
|
-
int rats_is_gossipsub_available(rats_client_t handle) {
|
|
886
|
-
if (!handle) return 0;
|
|
887
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
888
|
-
return wrap->client->is_gossipsub_available() ? 1 : 0;
|
|
889
|
-
}
|
|
890
|
-
|
|
891
|
-
int rats_is_gossipsub_running(rats_client_t handle) {
|
|
892
|
-
if (!handle) return 0;
|
|
893
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
894
|
-
return wrap->client->is_gossipsub_running() ? 1 : 0;
|
|
895
|
-
}
|
|
896
|
-
|
|
897
|
-
rats_error_t rats_subscribe_to_topic(rats_client_t handle, const char* topic) {
|
|
898
|
-
if (!handle || !topic) return RATS_ERROR_INVALID_PARAMETER;
|
|
899
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
900
|
-
return wrap->client->subscribe_to_topic(std::string(topic)) ? RATS_SUCCESS : RATS_ERROR_OPERATION_FAILED;
|
|
901
|
-
}
|
|
902
|
-
|
|
903
|
-
rats_error_t rats_unsubscribe_from_topic(rats_client_t handle, const char* topic) {
|
|
904
|
-
if (!handle || !topic) return RATS_ERROR_INVALID_PARAMETER;
|
|
905
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
906
|
-
return wrap->client->unsubscribe_from_topic(std::string(topic)) ? RATS_SUCCESS : RATS_ERROR_OPERATION_FAILED;
|
|
907
|
-
}
|
|
908
|
-
|
|
909
|
-
int rats_is_subscribed_to_topic(rats_client_t handle, const char* topic) {
|
|
910
|
-
if (!handle || !topic) return 0;
|
|
911
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
912
|
-
return wrap->client->is_subscribed_to_topic(std::string(topic)) ? 1 : 0;
|
|
913
|
-
}
|
|
914
|
-
|
|
915
|
-
char** rats_get_subscribed_topics(rats_client_t handle, int* count) {
|
|
916
|
-
if (!handle || !count) {
|
|
917
|
-
if (count) *count = 0;
|
|
918
|
-
return nullptr;
|
|
919
|
-
}
|
|
920
|
-
|
|
921
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
922
|
-
auto topics = wrap->client->get_subscribed_topics();
|
|
923
|
-
|
|
924
|
-
*count = static_cast<int>(topics.size());
|
|
925
|
-
if (*count == 0) return nullptr;
|
|
926
|
-
|
|
927
|
-
char** topic_array = static_cast<char**>(malloc(*count * sizeof(char*)));
|
|
928
|
-
if (!topic_array) {
|
|
929
|
-
*count = 0;
|
|
930
|
-
return nullptr;
|
|
931
|
-
}
|
|
932
|
-
|
|
933
|
-
for (int i = 0; i < *count; ++i) {
|
|
934
|
-
topic_array[i] = rats_strdup_owned(topics[i]);
|
|
935
|
-
if (!topic_array[i]) {
|
|
936
|
-
// Clean up on allocation failure
|
|
937
|
-
for (int j = 0; j < i; ++j) {
|
|
938
|
-
free(topic_array[j]);
|
|
939
|
-
}
|
|
940
|
-
free(topic_array);
|
|
941
|
-
*count = 0;
|
|
942
|
-
return nullptr;
|
|
943
|
-
}
|
|
944
|
-
}
|
|
945
|
-
|
|
946
|
-
return topic_array;
|
|
947
|
-
}
|
|
948
|
-
|
|
949
|
-
rats_error_t rats_publish_to_topic(rats_client_t handle, const char* topic, const char* message) {
|
|
950
|
-
if (!handle || !topic || !message) return RATS_ERROR_INVALID_PARAMETER;
|
|
951
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
952
|
-
return wrap->client->publish_to_topic(std::string(topic), std::string(message)) ? RATS_SUCCESS : RATS_ERROR_OPERATION_FAILED;
|
|
953
|
-
}
|
|
954
|
-
|
|
955
|
-
rats_error_t rats_publish_json_to_topic(rats_client_t handle, const char* topic, const char* json_str) {
|
|
956
|
-
if (!handle || !topic || !json_str) return RATS_ERROR_INVALID_PARAMETER;
|
|
957
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
958
|
-
|
|
959
|
-
try {
|
|
960
|
-
nlohmann::json json_data = nlohmann::json::parse(json_str);
|
|
961
|
-
return wrap->client->publish_json_to_topic(std::string(topic), json_data) ? RATS_SUCCESS : RATS_ERROR_OPERATION_FAILED;
|
|
962
|
-
} catch (const nlohmann::json::exception&) {
|
|
963
|
-
return RATS_ERROR_JSON_PARSE;
|
|
964
|
-
}
|
|
965
|
-
}
|
|
966
|
-
|
|
967
|
-
char** rats_get_topic_peers(rats_client_t handle, const char* topic, int* count) {
|
|
968
|
-
if (!handle || !topic || !count) {
|
|
969
|
-
if (count) *count = 0;
|
|
970
|
-
return nullptr;
|
|
971
|
-
}
|
|
972
|
-
|
|
973
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
974
|
-
auto peers = wrap->client->get_topic_peers(std::string(topic));
|
|
975
|
-
|
|
976
|
-
*count = static_cast<int>(peers.size());
|
|
977
|
-
if (*count == 0) return nullptr;
|
|
978
|
-
|
|
979
|
-
char** peer_array = static_cast<char**>(malloc(*count * sizeof(char*)));
|
|
980
|
-
if (!peer_array) {
|
|
981
|
-
*count = 0;
|
|
982
|
-
return nullptr;
|
|
983
|
-
}
|
|
984
|
-
|
|
985
|
-
for (int i = 0; i < *count; ++i) {
|
|
986
|
-
peer_array[i] = rats_strdup_owned(peers[i]);
|
|
987
|
-
if (!peer_array[i]) {
|
|
988
|
-
// Clean up on allocation failure
|
|
989
|
-
for (int j = 0; j < i; ++j) {
|
|
990
|
-
free(peer_array[j]);
|
|
991
|
-
}
|
|
992
|
-
free(peer_array);
|
|
993
|
-
*count = 0;
|
|
994
|
-
return nullptr;
|
|
995
|
-
}
|
|
996
|
-
}
|
|
997
|
-
|
|
998
|
-
return peer_array;
|
|
999
|
-
}
|
|
1000
|
-
|
|
1001
|
-
char** rats_get_topic_mesh_peers(rats_client_t handle, const char* topic, int* count) {
|
|
1002
|
-
if (!handle || !topic || !count) {
|
|
1003
|
-
if (count) *count = 0;
|
|
1004
|
-
return nullptr;
|
|
1005
|
-
}
|
|
1006
|
-
|
|
1007
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
1008
|
-
auto peers = wrap->client->get_topic_mesh_peers(std::string(topic));
|
|
1009
|
-
|
|
1010
|
-
*count = static_cast<int>(peers.size());
|
|
1011
|
-
if (*count == 0) return nullptr;
|
|
1012
|
-
|
|
1013
|
-
char** peer_array = static_cast<char**>(malloc(*count * sizeof(char*)));
|
|
1014
|
-
if (!peer_array) {
|
|
1015
|
-
*count = 0;
|
|
1016
|
-
return nullptr;
|
|
1017
|
-
}
|
|
1018
|
-
|
|
1019
|
-
for (int i = 0; i < *count; ++i) {
|
|
1020
|
-
peer_array[i] = rats_strdup_owned(peers[i]);
|
|
1021
|
-
if (!peer_array[i]) {
|
|
1022
|
-
// Clean up on allocation failure
|
|
1023
|
-
for (int j = 0; j < i; ++j) {
|
|
1024
|
-
free(peer_array[j]);
|
|
1025
|
-
}
|
|
1026
|
-
free(peer_array);
|
|
1027
|
-
*count = 0;
|
|
1028
|
-
return nullptr;
|
|
1029
|
-
}
|
|
1030
|
-
}
|
|
1031
|
-
|
|
1032
|
-
return peer_array;
|
|
1033
|
-
}
|
|
1034
|
-
|
|
1035
|
-
char* rats_get_gossipsub_statistics_json(rats_client_t handle) {
|
|
1036
|
-
if (!handle) return nullptr;
|
|
1037
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
1038
|
-
auto stats = wrap->client->get_gossipsub_statistics();
|
|
1039
|
-
return rats_strdup_owned(stats.dump());
|
|
1040
|
-
}
|
|
1041
|
-
|
|
1042
|
-
// GossipSub callback setters
|
|
1043
|
-
void rats_set_topic_message_callback(rats_client_t handle, const char* topic, rats_topic_message_cb cb, void* user_data) {
|
|
1044
|
-
if (!handle || !topic) return;
|
|
1045
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
1046
|
-
|
|
1047
|
-
std::string topic_str(topic);
|
|
1048
|
-
if (cb) {
|
|
1049
|
-
wrap->topic_message_handlers[topic_str] = std::make_pair(cb, user_data);
|
|
1050
|
-
wrap->client->on_topic_message(topic_str, [wrap, cb, user_data](const std::string& peer_id, const std::string& topic, const std::string& message) {
|
|
1051
|
-
if (cb) {
|
|
1052
|
-
cb(user_data, peer_id.c_str(), topic.c_str(), message.c_str());
|
|
1053
|
-
}
|
|
1054
|
-
});
|
|
1055
|
-
} else {
|
|
1056
|
-
wrap->topic_message_handlers.erase(topic_str);
|
|
1057
|
-
}
|
|
1058
|
-
}
|
|
1059
|
-
|
|
1060
|
-
void rats_set_topic_json_message_callback(rats_client_t handle, const char* topic, rats_topic_json_message_cb cb, void* user_data) {
|
|
1061
|
-
if (!handle || !topic) return;
|
|
1062
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
1063
|
-
|
|
1064
|
-
std::string topic_str(topic);
|
|
1065
|
-
if (cb) {
|
|
1066
|
-
wrap->topic_json_message_handlers[topic_str] = std::make_pair(cb, user_data);
|
|
1067
|
-
wrap->client->on_topic_json_message(topic_str, [wrap, cb, user_data](const std::string& peer_id, const std::string& topic, const nlohmann::json& message) {
|
|
1068
|
-
if (cb) {
|
|
1069
|
-
std::string json_str = message.dump();
|
|
1070
|
-
cb(user_data, peer_id.c_str(), topic.c_str(), json_str.c_str());
|
|
1071
|
-
}
|
|
1072
|
-
});
|
|
1073
|
-
} else {
|
|
1074
|
-
wrap->topic_json_message_handlers.erase(topic_str);
|
|
1075
|
-
}
|
|
1076
|
-
}
|
|
1077
|
-
|
|
1078
|
-
void rats_set_topic_peer_joined_callback(rats_client_t handle, const char* topic, rats_topic_peer_joined_cb cb, void* user_data) {
|
|
1079
|
-
if (!handle || !topic) return;
|
|
1080
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
1081
|
-
|
|
1082
|
-
std::string topic_str(topic);
|
|
1083
|
-
if (cb) {
|
|
1084
|
-
wrap->topic_peer_joined_handlers[topic_str] = std::make_pair(cb, user_data);
|
|
1085
|
-
wrap->client->on_topic_peer_joined(topic_str, [wrap, cb, user_data](const std::string& peer_id, const std::string& topic) {
|
|
1086
|
-
if (cb) {
|
|
1087
|
-
cb(user_data, peer_id.c_str(), topic.c_str());
|
|
1088
|
-
}
|
|
1089
|
-
});
|
|
1090
|
-
} else {
|
|
1091
|
-
wrap->topic_peer_joined_handlers.erase(topic_str);
|
|
1092
|
-
}
|
|
1093
|
-
}
|
|
1094
|
-
|
|
1095
|
-
void rats_set_topic_peer_left_callback(rats_client_t handle, const char* topic, rats_topic_peer_left_cb cb, void* user_data) {
|
|
1096
|
-
if (!handle || !topic) return;
|
|
1097
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
1098
|
-
|
|
1099
|
-
std::string topic_str(topic);
|
|
1100
|
-
if (cb) {
|
|
1101
|
-
wrap->topic_peer_left_handlers[topic_str] = std::make_pair(cb, user_data);
|
|
1102
|
-
wrap->client->on_topic_peer_left(topic_str, [wrap, cb, user_data](const std::string& peer_id, const std::string& topic) {
|
|
1103
|
-
if (cb) {
|
|
1104
|
-
cb(user_data, peer_id.c_str(), topic.c_str());
|
|
1105
|
-
}
|
|
1106
|
-
});
|
|
1107
|
-
} else {
|
|
1108
|
-
wrap->topic_peer_left_handlers.erase(topic_str);
|
|
1109
|
-
}
|
|
1110
|
-
}
|
|
1111
|
-
|
|
1112
|
-
void rats_clear_topic_callbacks(rats_client_t handle, const char* topic) {
|
|
1113
|
-
if (!handle || !topic) return;
|
|
1114
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
1115
|
-
|
|
1116
|
-
std::string topic_str(topic);
|
|
1117
|
-
wrap->topic_message_handlers.erase(topic_str);
|
|
1118
|
-
wrap->topic_json_message_handlers.erase(topic_str);
|
|
1119
|
-
wrap->topic_peer_joined_handlers.erase(topic_str);
|
|
1120
|
-
wrap->topic_peer_left_handlers.erase(topic_str);
|
|
1121
|
-
|
|
1122
|
-
wrap->client->off_topic(topic_str);
|
|
1123
|
-
}
|
|
1124
|
-
|
|
1125
|
-
// ===================== ADDRESS BLOCKING =====================
|
|
1126
|
-
|
|
1127
|
-
void rats_add_ignored_address(rats_client_t handle, const char* ip_address) {
|
|
1128
|
-
if (!handle || !ip_address) return;
|
|
1129
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
1130
|
-
wrap->client->add_ignored_address(std::string(ip_address));
|
|
1131
|
-
}
|
|
1132
|
-
|
|
1133
|
-
// ===================== CONFIGURATION PERSISTENCE =====================
|
|
1134
|
-
|
|
1135
|
-
rats_error_t rats_load_configuration(rats_client_t handle) {
|
|
1136
|
-
if (!handle) return RATS_ERROR_INVALID_HANDLE;
|
|
1137
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
1138
|
-
return wrap->client->load_configuration() ? RATS_SUCCESS : RATS_ERROR_OPERATION_FAILED;
|
|
1139
|
-
}
|
|
1140
|
-
|
|
1141
|
-
rats_error_t rats_save_configuration(rats_client_t handle) {
|
|
1142
|
-
if (!handle) return RATS_ERROR_INVALID_HANDLE;
|
|
1143
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
1144
|
-
return wrap->client->save_configuration() ? RATS_SUCCESS : RATS_ERROR_OPERATION_FAILED;
|
|
1145
|
-
}
|
|
1146
|
-
|
|
1147
|
-
rats_error_t rats_set_data_directory(rats_client_t handle, const char* directory_path) {
|
|
1148
|
-
if (!handle || !directory_path) return RATS_ERROR_INVALID_PARAMETER;
|
|
1149
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
1150
|
-
return wrap->client->set_data_directory(std::string(directory_path)) ? RATS_SUCCESS : RATS_ERROR_OPERATION_FAILED;
|
|
1151
|
-
}
|
|
1152
|
-
|
|
1153
|
-
char* rats_get_data_directory(rats_client_t handle) {
|
|
1154
|
-
if (!handle) return nullptr;
|
|
1155
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
1156
|
-
return rats_strdup_owned(wrap->client->get_data_directory());
|
|
1157
|
-
}
|
|
1158
|
-
|
|
1159
|
-
int rats_load_and_reconnect_peers(rats_client_t handle) {
|
|
1160
|
-
if (!handle) return 0;
|
|
1161
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
1162
|
-
return wrap->client->load_and_reconnect_peers();
|
|
1163
|
-
}
|
|
1164
|
-
|
|
1165
|
-
int rats_load_historical_peers(rats_client_t handle) {
|
|
1166
|
-
if (!handle) return 0;
|
|
1167
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
1168
|
-
return wrap->client->load_historical_peers() ? 1 : 0;
|
|
1169
|
-
}
|
|
1170
|
-
|
|
1171
|
-
int rats_save_historical_peers(rats_client_t handle) {
|
|
1172
|
-
if (!handle) return 0;
|
|
1173
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
1174
|
-
return wrap->client->save_historical_peers() ? 1 : 0;
|
|
1175
|
-
}
|
|
1176
|
-
|
|
1177
|
-
void rats_clear_historical_peers(rats_client_t handle) {
|
|
1178
|
-
if (!handle) return;
|
|
1179
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
1180
|
-
wrap->client->clear_historical_peers();
|
|
1181
|
-
}
|
|
1182
|
-
|
|
1183
|
-
char** rats_get_historical_peer_ids(rats_client_t handle, int* count) {
|
|
1184
|
-
if (!handle || !count) {
|
|
1185
|
-
if (count) *count = 0;
|
|
1186
|
-
return nullptr;
|
|
1187
|
-
}
|
|
1188
|
-
|
|
1189
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
1190
|
-
auto historical_peers = wrap->client->get_historical_peers();
|
|
1191
|
-
|
|
1192
|
-
*count = static_cast<int>(historical_peers.size());
|
|
1193
|
-
if (*count == 0) return nullptr;
|
|
1194
|
-
|
|
1195
|
-
char** peer_ids = static_cast<char**>(malloc(*count * sizeof(char*)));
|
|
1196
|
-
if (!peer_ids) {
|
|
1197
|
-
*count = 0;
|
|
1198
|
-
return nullptr;
|
|
1199
|
-
}
|
|
1200
|
-
|
|
1201
|
-
for (int i = 0; i < *count; ++i) {
|
|
1202
|
-
peer_ids[i] = rats_strdup_owned(historical_peers[i].peer_id);
|
|
1203
|
-
if (!peer_ids[i]) {
|
|
1204
|
-
// Clean up on allocation failure
|
|
1205
|
-
for (int j = 0; j < i; ++j) {
|
|
1206
|
-
free(peer_ids[j]);
|
|
1207
|
-
}
|
|
1208
|
-
free(peer_ids);
|
|
1209
|
-
*count = 0;
|
|
1210
|
-
return nullptr;
|
|
1211
|
-
}
|
|
1212
|
-
}
|
|
1213
|
-
|
|
1214
|
-
return peer_ids;
|
|
1215
|
-
}
|
|
1216
|
-
|
|
1217
|
-
// ===================== ENHANCED ENCRYPTION API =====================
|
|
1218
|
-
|
|
1219
|
-
rats_error_t rats_initialize_encryption(rats_client_t handle, int enable) {
|
|
1220
|
-
if (!handle) return RATS_ERROR_INVALID_HANDLE;
|
|
1221
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
1222
|
-
return wrap->client->initialize_encryption(enable != 0) ? RATS_SUCCESS : RATS_ERROR_OPERATION_FAILED;
|
|
1223
|
-
}
|
|
1224
|
-
|
|
1225
|
-
int rats_is_peer_encrypted(rats_client_t handle, const char* peer_id) {
|
|
1226
|
-
if (!handle || !peer_id) return 0;
|
|
1227
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
1228
|
-
return wrap->client->is_peer_encrypted(std::string(peer_id)) ? 1 : 0;
|
|
1229
|
-
}
|
|
1230
|
-
|
|
1231
|
-
rats_error_t rats_set_noise_static_keypair(rats_client_t handle, const char* private_key_hex) {
|
|
1232
|
-
if (!handle || !private_key_hex) return RATS_ERROR_INVALID_PARAMETER;
|
|
1233
|
-
if (strlen(private_key_hex) != 64) return RATS_ERROR_INVALID_PARAMETER; // 32 bytes = 64 hex chars
|
|
1234
|
-
|
|
1235
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
1236
|
-
|
|
1237
|
-
// Convert hex string to bytes
|
|
1238
|
-
uint8_t private_key[32];
|
|
1239
|
-
for (int i = 0; i < 32; i++) {
|
|
1240
|
-
unsigned int byte;
|
|
1241
|
-
if (sscanf(private_key_hex + i * 2, "%02x", &byte) != 1) {
|
|
1242
|
-
return RATS_ERROR_INVALID_PARAMETER;
|
|
1243
|
-
}
|
|
1244
|
-
private_key[i] = static_cast<uint8_t>(byte);
|
|
1245
|
-
}
|
|
1246
|
-
|
|
1247
|
-
return wrap->client->set_noise_static_keypair(private_key) ? RATS_SUCCESS : RATS_ERROR_OPERATION_FAILED;
|
|
1248
|
-
}
|
|
1249
|
-
|
|
1250
|
-
static std::string bytes_to_hex(const std::vector<uint8_t>& bytes) {
|
|
1251
|
-
std::string hex;
|
|
1252
|
-
hex.reserve(bytes.size() * 2);
|
|
1253
|
-
for (uint8_t b : bytes) {
|
|
1254
|
-
char buf[3];
|
|
1255
|
-
snprintf(buf, sizeof(buf), "%02x", b);
|
|
1256
|
-
hex += buf;
|
|
1257
|
-
}
|
|
1258
|
-
return hex;
|
|
1259
|
-
}
|
|
1260
|
-
|
|
1261
|
-
char* rats_get_noise_static_public_key(rats_client_t handle) {
|
|
1262
|
-
if (!handle) return nullptr;
|
|
1263
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
1264
|
-
auto key = wrap->client->get_noise_static_public_key();
|
|
1265
|
-
if (key.empty()) return nullptr;
|
|
1266
|
-
return rats_strdup_owned(bytes_to_hex(key));
|
|
1267
|
-
}
|
|
1268
|
-
|
|
1269
|
-
char* rats_get_peer_noise_public_key(rats_client_t handle, const char* peer_id) {
|
|
1270
|
-
if (!handle || !peer_id) return nullptr;
|
|
1271
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
1272
|
-
auto key = wrap->client->get_peer_noise_public_key(std::string(peer_id));
|
|
1273
|
-
if (key.empty()) return nullptr;
|
|
1274
|
-
return rats_strdup_owned(bytes_to_hex(key));
|
|
1275
|
-
}
|
|
1276
|
-
|
|
1277
|
-
char* rats_get_peer_handshake_hash(rats_client_t handle, const char* peer_id) {
|
|
1278
|
-
if (!handle || !peer_id) return nullptr;
|
|
1279
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
1280
|
-
auto hash = wrap->client->get_peer_handshake_hash(std::string(peer_id));
|
|
1281
|
-
if (hash.empty()) return nullptr;
|
|
1282
|
-
return rats_strdup_owned(bytes_to_hex(hash));
|
|
1283
|
-
}
|
|
1284
|
-
|
|
1285
|
-
// ===================== ICE (NAT TRAVERSAL) API =====================
|
|
1286
|
-
|
|
1287
|
-
int rats_is_ice_available(rats_client_t handle) {
|
|
1288
|
-
if (!handle) return 0;
|
|
1289
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
1290
|
-
return wrap->client->is_ice_available() ? 1 : 0;
|
|
1291
|
-
}
|
|
1292
|
-
|
|
1293
|
-
void rats_add_stun_server(rats_client_t handle, const char* host, uint16_t port) {
|
|
1294
|
-
if (!handle || !host) return;
|
|
1295
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
1296
|
-
wrap->client->add_stun_server(std::string(host), port);
|
|
1297
|
-
}
|
|
1298
|
-
|
|
1299
|
-
void rats_add_turn_server(rats_client_t handle, const char* host, uint16_t port,
|
|
1300
|
-
const char* username, const char* password) {
|
|
1301
|
-
if (!handle || !host || !username || !password) return;
|
|
1302
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
1303
|
-
wrap->client->add_turn_server(std::string(host), port,
|
|
1304
|
-
std::string(username), std::string(password));
|
|
1305
|
-
}
|
|
1306
|
-
|
|
1307
|
-
void rats_clear_ice_servers(rats_client_t handle) {
|
|
1308
|
-
if (!handle) return;
|
|
1309
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
1310
|
-
wrap->client->clear_ice_servers();
|
|
1311
|
-
}
|
|
1312
|
-
|
|
1313
|
-
int rats_gather_ice_candidates(rats_client_t handle) {
|
|
1314
|
-
if (!handle) return 0;
|
|
1315
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
1316
|
-
return wrap->client->gather_ice_candidates() ? 1 : 0;
|
|
1317
|
-
}
|
|
1318
|
-
|
|
1319
|
-
char* rats_get_ice_candidates_json(rats_client_t handle) {
|
|
1320
|
-
if (!handle) return nullptr;
|
|
1321
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
1322
|
-
|
|
1323
|
-
auto candidates = wrap->client->get_ice_candidates();
|
|
1324
|
-
nlohmann::json candidates_json = nlohmann::json::array();
|
|
1325
|
-
|
|
1326
|
-
for (const auto& c : candidates) {
|
|
1327
|
-
nlohmann::json cj;
|
|
1328
|
-
cj["type"] = static_cast<int>(c.type);
|
|
1329
|
-
cj["foundation"] = c.foundation;
|
|
1330
|
-
cj["component_id"] = c.component_id;
|
|
1331
|
-
cj["transport"] = static_cast<int>(c.transport);
|
|
1332
|
-
cj["priority"] = c.priority;
|
|
1333
|
-
cj["address"] = c.address;
|
|
1334
|
-
cj["port"] = c.port;
|
|
1335
|
-
cj["related_address"] = c.related_address;
|
|
1336
|
-
cj["related_port"] = c.related_port;
|
|
1337
|
-
cj["sdp"] = c.to_sdp_attribute();
|
|
1338
|
-
candidates_json.push_back(cj);
|
|
1339
|
-
}
|
|
1340
|
-
|
|
1341
|
-
return rats_strdup_owned(candidates_json.dump());
|
|
1342
|
-
}
|
|
1343
|
-
|
|
1344
|
-
int rats_is_ice_gathering_complete(rats_client_t handle) {
|
|
1345
|
-
if (!handle) return 0;
|
|
1346
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
1347
|
-
return wrap->client->is_ice_gathering_complete() ? 1 : 0;
|
|
1348
|
-
}
|
|
1349
|
-
|
|
1350
|
-
char* rats_get_public_address(rats_client_t handle) {
|
|
1351
|
-
if (!handle) return nullptr;
|
|
1352
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
1353
|
-
|
|
1354
|
-
auto addr = wrap->client->get_public_address();
|
|
1355
|
-
if (!addr.has_value()) return nullptr;
|
|
1356
|
-
|
|
1357
|
-
std::string result = addr->first + ":" + std::to_string(addr->second);
|
|
1358
|
-
return rats_strdup_owned(result);
|
|
1359
|
-
}
|
|
1360
|
-
|
|
1361
|
-
char* rats_discover_public_address(rats_client_t handle, const char* stun_server,
|
|
1362
|
-
uint16_t port, int timeout_ms) {
|
|
1363
|
-
if (!handle) return nullptr;
|
|
1364
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
1365
|
-
|
|
1366
|
-
std::string server = stun_server ? std::string(stun_server) : "stun.l.google.com";
|
|
1367
|
-
uint16_t server_port = (port > 0) ? port : 19302;
|
|
1368
|
-
int timeout = (timeout_ms > 0) ? timeout_ms : 5000;
|
|
1369
|
-
|
|
1370
|
-
auto addr = wrap->client->discover_public_address(server, server_port, timeout);
|
|
1371
|
-
if (!addr.has_value()) return nullptr;
|
|
1372
|
-
|
|
1373
|
-
std::string result = addr->address + ":" + std::to_string(addr->port);
|
|
1374
|
-
return rats_strdup_owned(result);
|
|
1375
|
-
}
|
|
1376
|
-
|
|
1377
|
-
void rats_add_remote_ice_candidate(rats_client_t handle, const char* candidate_sdp) {
|
|
1378
|
-
if (!handle || !candidate_sdp) return;
|
|
1379
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
1380
|
-
|
|
1381
|
-
auto candidate = IceCandidate::from_sdp_attribute(std::string(candidate_sdp));
|
|
1382
|
-
if (candidate.has_value()) {
|
|
1383
|
-
wrap->client->add_remote_ice_candidate(candidate.value());
|
|
1384
|
-
}
|
|
1385
|
-
}
|
|
1386
|
-
|
|
1387
|
-
void rats_add_remote_ice_candidates_from_sdp(rats_client_t handle,
|
|
1388
|
-
const char** sdp_lines, int count) {
|
|
1389
|
-
if (!handle || !sdp_lines || count <= 0) return;
|
|
1390
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
1391
|
-
|
|
1392
|
-
std::vector<std::string> lines;
|
|
1393
|
-
for (int i = 0; i < count; i++) {
|
|
1394
|
-
if (sdp_lines[i]) {
|
|
1395
|
-
lines.push_back(std::string(sdp_lines[i]));
|
|
1396
|
-
}
|
|
1397
|
-
}
|
|
1398
|
-
|
|
1399
|
-
wrap->client->add_remote_ice_candidates_from_sdp(lines);
|
|
1400
|
-
}
|
|
1401
|
-
|
|
1402
|
-
void rats_end_of_remote_ice_candidates(rats_client_t handle) {
|
|
1403
|
-
if (!handle) return;
|
|
1404
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
1405
|
-
wrap->client->end_of_remote_ice_candidates();
|
|
1406
|
-
}
|
|
1407
|
-
|
|
1408
|
-
void rats_start_ice_checks(rats_client_t handle) {
|
|
1409
|
-
if (!handle) return;
|
|
1410
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
1411
|
-
wrap->client->start_ice_checks();
|
|
1412
|
-
}
|
|
1413
|
-
|
|
1414
|
-
rats_ice_connection_state_t rats_get_ice_connection_state(rats_client_t handle) {
|
|
1415
|
-
if (!handle) return RATS_ICE_STATE_CLOSED;
|
|
1416
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
1417
|
-
return static_cast<rats_ice_connection_state_t>(wrap->client->get_ice_connection_state());
|
|
1418
|
-
}
|
|
1419
|
-
|
|
1420
|
-
rats_ice_gathering_state_t rats_get_ice_gathering_state(rats_client_t handle) {
|
|
1421
|
-
if (!handle) return RATS_ICE_GATHERING_NEW;
|
|
1422
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
1423
|
-
return static_cast<rats_ice_gathering_state_t>(wrap->client->get_ice_gathering_state());
|
|
1424
|
-
}
|
|
1425
|
-
|
|
1426
|
-
int rats_is_ice_connected(rats_client_t handle) {
|
|
1427
|
-
if (!handle) return 0;
|
|
1428
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
1429
|
-
return wrap->client->is_ice_connected() ? 1 : 0;
|
|
1430
|
-
}
|
|
1431
|
-
|
|
1432
|
-
char* rats_get_ice_selected_pair_json(rats_client_t handle) {
|
|
1433
|
-
if (!handle) return nullptr;
|
|
1434
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
1435
|
-
|
|
1436
|
-
auto pair = wrap->client->get_ice_selected_pair();
|
|
1437
|
-
if (!pair.has_value()) return nullptr;
|
|
1438
|
-
|
|
1439
|
-
nlohmann::json pair_json;
|
|
1440
|
-
|
|
1441
|
-
nlohmann::json local_json;
|
|
1442
|
-
local_json["type"] = static_cast<int>(pair->local.type);
|
|
1443
|
-
local_json["address"] = pair->local.address;
|
|
1444
|
-
local_json["port"] = pair->local.port;
|
|
1445
|
-
local_json["priority"] = pair->local.priority;
|
|
1446
|
-
local_json["sdp"] = pair->local.to_sdp_attribute();
|
|
1447
|
-
|
|
1448
|
-
nlohmann::json remote_json;
|
|
1449
|
-
remote_json["type"] = static_cast<int>(pair->remote.type);
|
|
1450
|
-
remote_json["address"] = pair->remote.address;
|
|
1451
|
-
remote_json["port"] = pair->remote.port;
|
|
1452
|
-
remote_json["priority"] = pair->remote.priority;
|
|
1453
|
-
remote_json["sdp"] = pair->remote.to_sdp_attribute();
|
|
1454
|
-
|
|
1455
|
-
pair_json["local"] = local_json;
|
|
1456
|
-
pair_json["remote"] = remote_json;
|
|
1457
|
-
pair_json["state"] = static_cast<int>(pair->state);
|
|
1458
|
-
pair_json["priority"] = pair->priority;
|
|
1459
|
-
pair_json["nominated"] = pair->nominated;
|
|
1460
|
-
|
|
1461
|
-
return rats_strdup_owned(pair_json.dump());
|
|
1462
|
-
}
|
|
1463
|
-
|
|
1464
|
-
void rats_set_ice_candidates_gathered_callback(rats_client_t handle,
|
|
1465
|
-
rats_ice_candidates_cb cb, void* user_data) {
|
|
1466
|
-
if (!handle) return;
|
|
1467
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
1468
|
-
|
|
1469
|
-
if (cb) {
|
|
1470
|
-
wrap->client->on_ice_candidates_gathered([cb, user_data](const std::vector<IceCandidate>& candidates) {
|
|
1471
|
-
nlohmann::json candidates_json = nlohmann::json::array();
|
|
1472
|
-
for (const auto& c : candidates) {
|
|
1473
|
-
nlohmann::json cj;
|
|
1474
|
-
cj["sdp"] = c.to_sdp_attribute();
|
|
1475
|
-
cj["address"] = c.address;
|
|
1476
|
-
cj["port"] = c.port;
|
|
1477
|
-
cj["type"] = static_cast<int>(c.type);
|
|
1478
|
-
candidates_json.push_back(cj);
|
|
1479
|
-
}
|
|
1480
|
-
cb(user_data, candidates_json.dump().c_str());
|
|
1481
|
-
});
|
|
1482
|
-
}
|
|
1483
|
-
}
|
|
1484
|
-
|
|
1485
|
-
void rats_set_ice_new_candidate_callback(rats_client_t handle,
|
|
1486
|
-
rats_ice_new_candidate_cb cb, void* user_data) {
|
|
1487
|
-
if (!handle) return;
|
|
1488
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
1489
|
-
|
|
1490
|
-
if (cb) {
|
|
1491
|
-
wrap->client->on_ice_new_candidate([cb, user_data](const IceCandidate& candidate) {
|
|
1492
|
-
cb(user_data, candidate.to_sdp_attribute().c_str());
|
|
1493
|
-
});
|
|
1494
|
-
}
|
|
1495
|
-
}
|
|
1496
|
-
|
|
1497
|
-
void rats_set_ice_gathering_state_callback(rats_client_t handle,
|
|
1498
|
-
rats_ice_gathering_state_cb cb, void* user_data) {
|
|
1499
|
-
if (!handle) return;
|
|
1500
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
1501
|
-
|
|
1502
|
-
if (cb) {
|
|
1503
|
-
wrap->client->on_ice_gathering_state_changed([cb, user_data](IceGatheringState state) {
|
|
1504
|
-
cb(user_data, static_cast<rats_ice_gathering_state_t>(state));
|
|
1505
|
-
});
|
|
1506
|
-
}
|
|
1507
|
-
}
|
|
1508
|
-
|
|
1509
|
-
void rats_set_ice_connection_state_callback(rats_client_t handle,
|
|
1510
|
-
rats_ice_connection_state_cb cb, void* user_data) {
|
|
1511
|
-
if (!handle) return;
|
|
1512
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
1513
|
-
|
|
1514
|
-
if (cb) {
|
|
1515
|
-
wrap->client->on_ice_connection_state_changed([cb, user_data](IceConnectionState state) {
|
|
1516
|
-
cb(user_data, static_cast<rats_ice_connection_state_t>(state));
|
|
1517
|
-
});
|
|
1518
|
-
}
|
|
1519
|
-
}
|
|
1520
|
-
|
|
1521
|
-
void rats_set_ice_selected_pair_callback(rats_client_t handle,
|
|
1522
|
-
rats_ice_selected_pair_cb cb, void* user_data) {
|
|
1523
|
-
if (!handle) return;
|
|
1524
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
1525
|
-
|
|
1526
|
-
if (cb) {
|
|
1527
|
-
wrap->client->on_ice_selected_pair([cb, user_data](const IceCandidatePair& pair) {
|
|
1528
|
-
nlohmann::json local_json;
|
|
1529
|
-
local_json["sdp"] = pair.local.to_sdp_attribute();
|
|
1530
|
-
local_json["address"] = pair.local.address;
|
|
1531
|
-
local_json["port"] = pair.local.port;
|
|
1532
|
-
|
|
1533
|
-
nlohmann::json remote_json;
|
|
1534
|
-
remote_json["sdp"] = pair.remote.to_sdp_attribute();
|
|
1535
|
-
remote_json["address"] = pair.remote.address;
|
|
1536
|
-
remote_json["port"] = pair.remote.port;
|
|
1537
|
-
|
|
1538
|
-
cb(user_data, local_json.dump().c_str(), remote_json.dump().c_str());
|
|
1539
|
-
});
|
|
1540
|
-
}
|
|
1541
|
-
}
|
|
1542
|
-
|
|
1543
|
-
void rats_close_ice(rats_client_t handle) {
|
|
1544
|
-
if (!handle) return;
|
|
1545
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
1546
|
-
wrap->client->close_ice();
|
|
1547
|
-
}
|
|
1548
|
-
|
|
1549
|
-
void rats_restart_ice(rats_client_t handle) {
|
|
1550
|
-
if (!handle) return;
|
|
1551
|
-
rats_client_wrapper* wrap = static_cast<rats_client_wrapper*>(handle);
|
|
1552
|
-
wrap->client->restart_ice();
|
|
1553
|
-
}
|
|
1554
|
-
|
|
1555
|
-
} // extern "C"
|
|
1556
|
-
|
|
1557
|
-
|