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
|
@@ -0,0 +1,444 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @file json.h
|
|
5
|
+
* @brief A small, self-contained JSON value type for librats.
|
|
6
|
+
*
|
|
7
|
+
* `librats::Json` is a dynamically-typed JSON value with a deliberately
|
|
8
|
+
* nlohmann-flavoured surface so existing call sites read naturally:
|
|
9
|
+
*
|
|
10
|
+
* Json j; // null
|
|
11
|
+
* j["name"] = "rats"; // becomes an object
|
|
12
|
+
* j["count"] = 42; // signed integer
|
|
13
|
+
* j["tags"] = Json::array(); // empty array
|
|
14
|
+
* j["tags"].push_back("p2p");
|
|
15
|
+
*
|
|
16
|
+
* Json cfg = { // initializer-list "object" detection,
|
|
17
|
+
* {"version", 1}, // exactly like nlohmann: a list whose
|
|
18
|
+
* {"nodes", {{"id", "ab"}}}, // every element is a [string, value] pair
|
|
19
|
+
* }; // is treated as an object.
|
|
20
|
+
*
|
|
21
|
+
* std::string text = j.dump(); // compact
|
|
22
|
+
* std::string nice = j.dump(2); // pretty, 2-space indent
|
|
23
|
+
* Json back = Json::parse(text); // throws on malformed input
|
|
24
|
+
* Json safe = Json::parse(text, nullptr, false); // never throws; see is_discarded()
|
|
25
|
+
*
|
|
26
|
+
* Design notes:
|
|
27
|
+
* - Numbers keep their kind (signed / unsigned / floating) so integers
|
|
28
|
+
* round-trip exactly and large 64-bit values are not silently truncated.
|
|
29
|
+
* - Objects preserve insertion order while offering O(1) average key lookup.
|
|
30
|
+
* - Heavy payloads (string / array / object) live behind a pointer, so a Json
|
|
31
|
+
* value is small (a tag plus one word) and cheap to move.
|
|
32
|
+
* - The parser is iterative-friendly recursive descent with a depth guard, so
|
|
33
|
+
* adversarial deeply-nested input fails cleanly instead of smashing the stack.
|
|
34
|
+
*/
|
|
35
|
+
|
|
36
|
+
#include "librats/util/rats_export.h"
|
|
37
|
+
#include <cstdint>
|
|
38
|
+
#include <initializer_list>
|
|
39
|
+
#include <iosfwd>
|
|
40
|
+
#include <stdexcept>
|
|
41
|
+
#include <string>
|
|
42
|
+
#include <type_traits>
|
|
43
|
+
#include <utility>
|
|
44
|
+
#include <vector>
|
|
45
|
+
|
|
46
|
+
namespace librats {
|
|
47
|
+
|
|
48
|
+
/// Thrown by the throwing parse path and by type-mismatched accessors.
|
|
49
|
+
/// Derives from std::runtime_error so existing catch(const std::exception&)
|
|
50
|
+
/// blocks keep working unchanged.
|
|
51
|
+
class JsonError : public std::runtime_error {
|
|
52
|
+
public:
|
|
53
|
+
explicit JsonError(const std::string& what) : std::runtime_error(what) {}
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
class RATS_API Json {
|
|
57
|
+
public:
|
|
58
|
+
enum class Type : uint8_t {
|
|
59
|
+
Null,
|
|
60
|
+
Boolean,
|
|
61
|
+
Integer, // signed, stored as int64_t
|
|
62
|
+
Unsigned, // unsigned, stored as uint64_t
|
|
63
|
+
Float, // stored as double
|
|
64
|
+
String,
|
|
65
|
+
Array,
|
|
66
|
+
Object,
|
|
67
|
+
Discarded, // result of a non-throwing parse failure
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
using Array = std::vector<Json>;
|
|
71
|
+
|
|
72
|
+
/// Insertion-ordered string->Json map with O(1) average lookup.
|
|
73
|
+
class Object {
|
|
74
|
+
public:
|
|
75
|
+
using value_type = std::pair<std::string, Json>;
|
|
76
|
+
using storage = std::vector<value_type>;
|
|
77
|
+
|
|
78
|
+
Object() = default;
|
|
79
|
+
Object(const Object&) = default;
|
|
80
|
+
Object(Object&&) noexcept = default;
|
|
81
|
+
Object& operator=(const Object&) = default;
|
|
82
|
+
Object& operator=(Object&&) noexcept = default;
|
|
83
|
+
|
|
84
|
+
Json& operator[](const std::string& key); // inserts null if absent
|
|
85
|
+
Json& operator[](std::string&& key); // ditto, moves key on insert
|
|
86
|
+
const Json* find(const std::string& key) const; // nullptr if absent
|
|
87
|
+
Json* find(const std::string& key); // nullptr if absent
|
|
88
|
+
bool contains(const std::string& key) const { return find(key) != nullptr; }
|
|
89
|
+
bool erase(const std::string& key);
|
|
90
|
+
|
|
91
|
+
std::size_t size() const { return items_.size(); }
|
|
92
|
+
bool empty() const { return items_.empty(); }
|
|
93
|
+
void clear() { items_.clear(); index_ = {}; }
|
|
94
|
+
|
|
95
|
+
storage::iterator begin() { return items_.begin(); }
|
|
96
|
+
storage::iterator end() { return items_.end(); }
|
|
97
|
+
storage::const_iterator begin() const { return items_.begin(); }
|
|
98
|
+
storage::const_iterator end() const { return items_.end(); }
|
|
99
|
+
|
|
100
|
+
bool operator==(const Object& other) const; // order-independent
|
|
101
|
+
|
|
102
|
+
private:
|
|
103
|
+
// Small objects (the common case — a peer record, a config node) keep
|
|
104
|
+
// only the insertion-ordered vector and find keys with a linear scan,
|
|
105
|
+
// which beats hashing for a handful of entries and costs no allocation.
|
|
106
|
+
// Past the threshold we build an open-addressing index that stores *only*
|
|
107
|
+
// 1-based positions into items_ (a 0 slot means empty) — so it copies no
|
|
108
|
+
// keys and is one small vector instead of a node-per-key hash map. items_
|
|
109
|
+
// stays the single source of truth; every probe reads the key back from
|
|
110
|
+
// it. The index is non-empty exactly while the object is indexed.
|
|
111
|
+
static constexpr std::size_t kIndexThreshold = 16;
|
|
112
|
+
|
|
113
|
+
static std::size_t hash_key(const std::string& key);
|
|
114
|
+
void rebuild_index(); // size the table for items_ and fill it from scratch
|
|
115
|
+
void reindex(); // after erase: rebuild while large, else drop the index
|
|
116
|
+
bool indexed() const { return !index_.empty(); }
|
|
117
|
+
|
|
118
|
+
// Shared find-or-insert for both operator[] overloads. K is deduced as
|
|
119
|
+
// `const std::string&` or `std::string&&`, so the key is copied or moved
|
|
120
|
+
// into storage to match how the caller supplied it.
|
|
121
|
+
template <typename K>
|
|
122
|
+
Json& emplace_key(K&& key);
|
|
123
|
+
|
|
124
|
+
storage items_;
|
|
125
|
+
// Open-addressing slots: value 0 is an empty slot, otherwise it is
|
|
126
|
+
// (items_ index + 1). uint32_t positions cap an object at ~4 billion
|
|
127
|
+
// keys — far beyond any real JSON document.
|
|
128
|
+
std::vector<std::uint32_t> index_;
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
// ── Construction ────────────────────────────────────────────────────────
|
|
132
|
+
|
|
133
|
+
Json() noexcept : type_(Type::Null) {}
|
|
134
|
+
Json(std::nullptr_t) noexcept : type_(Type::Null) {}
|
|
135
|
+
Json(bool b) noexcept : type_(Type::Boolean) { bool_ = b; }
|
|
136
|
+
|
|
137
|
+
template <typename T,
|
|
138
|
+
typename std::enable_if<std::is_integral<T>::value &&
|
|
139
|
+
!std::is_same<T, bool>::value,
|
|
140
|
+
int>::type = 0>
|
|
141
|
+
Json(T v) noexcept {
|
|
142
|
+
if (std::is_signed<T>::value) {
|
|
143
|
+
type_ = Type::Integer;
|
|
144
|
+
int_ = static_cast<int64_t>(v);
|
|
145
|
+
} else {
|
|
146
|
+
type_ = Type::Unsigned;
|
|
147
|
+
uint_ = static_cast<uint64_t>(v);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
template <typename T,
|
|
152
|
+
typename std::enable_if<std::is_floating_point<T>::value, int>::type = 0>
|
|
153
|
+
Json(T v) noexcept : type_(Type::Float) { float_ = static_cast<double>(v); }
|
|
154
|
+
|
|
155
|
+
Json(const char* s) : type_(Type::String) { str_ = new std::string(s ? s : ""); }
|
|
156
|
+
Json(const std::string& s) : type_(Type::String) { str_ = new std::string(s); }
|
|
157
|
+
Json(std::string&& s) : type_(Type::String) { str_ = new std::string(std::move(s)); }
|
|
158
|
+
|
|
159
|
+
/// nlohmann-style brace initialisation. A list whose every element is a
|
|
160
|
+
/// two-element array with a string first element is read as an object;
|
|
161
|
+
/// otherwise it is an array.
|
|
162
|
+
Json(std::initializer_list<Json> init);
|
|
163
|
+
|
|
164
|
+
Json(const Json& other) { copy_from(other); }
|
|
165
|
+
Json(Json&& other) noexcept { move_from(other); }
|
|
166
|
+
|
|
167
|
+
Json& operator=(const Json& other);
|
|
168
|
+
Json& operator=(Json&& other) noexcept;
|
|
169
|
+
|
|
170
|
+
~Json() { destroy(); }
|
|
171
|
+
|
|
172
|
+
/// Explicit empties (also handy to force kind on an otherwise-null value).
|
|
173
|
+
static Json array() { Json j; j.type_ = Type::Array; j.arr_ = new Array(); return j; }
|
|
174
|
+
static Json object() { Json j; j.type_ = Type::Object; j.obj_ = new Object(); return j; }
|
|
175
|
+
|
|
176
|
+
// ── Parsing ─────────────────────────────────────────────────────────────
|
|
177
|
+
//
|
|
178
|
+
// The second argument exists only for nlohmann call-site compatibility
|
|
179
|
+
// (a parser callback, which this implementation ignores). When
|
|
180
|
+
// allow_exceptions is false a malformed document yields a Discarded value
|
|
181
|
+
// (see is_discarded()) instead of throwing.
|
|
182
|
+
|
|
183
|
+
static Json parse(const std::string& text, std::nullptr_t = nullptr,
|
|
184
|
+
bool allow_exceptions = true);
|
|
185
|
+
static Json parse(const char* text, std::nullptr_t = nullptr,
|
|
186
|
+
bool allow_exceptions = true);
|
|
187
|
+
|
|
188
|
+
template <typename InputIt>
|
|
189
|
+
static Json parse(InputIt first, InputIt last, std::nullptr_t = nullptr,
|
|
190
|
+
bool allow_exceptions = true) {
|
|
191
|
+
// std::string's range constructor copies [first, last), converting each
|
|
192
|
+
// element to char — this handles const char*, const uint8_t*, etc.
|
|
193
|
+
std::string buf(first, last);
|
|
194
|
+
return parse(buf, nullptr, allow_exceptions);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// ── Serialisation ───────────────────────────────────────────────────────
|
|
198
|
+
//
|
|
199
|
+
// indent < 0 (the default) produces the most compact form. indent >= 0
|
|
200
|
+
// pretty-prints with that many spaces per level.
|
|
201
|
+
std::string dump(int indent = -1) const;
|
|
202
|
+
|
|
203
|
+
// ── Type inspection ─────────────────────────────────────────────────────
|
|
204
|
+
|
|
205
|
+
Type type() const noexcept { return type_; }
|
|
206
|
+
bool is_null() const noexcept { return type_ == Type::Null; }
|
|
207
|
+
bool is_boolean() const noexcept { return type_ == Type::Boolean; }
|
|
208
|
+
bool is_number() const noexcept {
|
|
209
|
+
return type_ == Type::Integer || type_ == Type::Unsigned || type_ == Type::Float;
|
|
210
|
+
}
|
|
211
|
+
bool is_number_integer() const noexcept {
|
|
212
|
+
return type_ == Type::Integer || type_ == Type::Unsigned;
|
|
213
|
+
}
|
|
214
|
+
bool is_number_unsigned() const noexcept { return type_ == Type::Unsigned; }
|
|
215
|
+
bool is_number_float() const noexcept { return type_ == Type::Float; }
|
|
216
|
+
bool is_string() const noexcept { return type_ == Type::String; }
|
|
217
|
+
bool is_array() const noexcept { return type_ == Type::Array; }
|
|
218
|
+
bool is_object() const noexcept { return type_ == Type::Object; }
|
|
219
|
+
bool is_discarded() const noexcept { return type_ == Type::Discarded; }
|
|
220
|
+
bool is_primitive() const noexcept {
|
|
221
|
+
return is_null() || is_boolean() || is_number() || is_string();
|
|
222
|
+
}
|
|
223
|
+
bool is_structured() const noexcept { return is_array() || is_object(); }
|
|
224
|
+
|
|
225
|
+
/// Number of elements (array/object), or 0 for null, 1 for any scalar.
|
|
226
|
+
std::size_t size() const noexcept;
|
|
227
|
+
/// True for null, an empty array, or an empty object.
|
|
228
|
+
bool empty() const noexcept;
|
|
229
|
+
|
|
230
|
+
// ── Object / array access ───────────────────────────────────────────────
|
|
231
|
+
|
|
232
|
+
Json& operator[](const std::string& key);
|
|
233
|
+
Json& operator[](const char* key) { return operator[](std::string(key)); }
|
|
234
|
+
const Json& operator[](const std::string& key) const;
|
|
235
|
+
const Json& operator[](const char* key) const { return operator[](std::string(key)); }
|
|
236
|
+
|
|
237
|
+
Json& operator[](int index) { return operator[](static_cast<std::size_t>(index)); }
|
|
238
|
+
Json& operator[](std::size_t index);
|
|
239
|
+
const Json& operator[](int index) const {
|
|
240
|
+
return operator[](static_cast<std::size_t>(index));
|
|
241
|
+
}
|
|
242
|
+
const Json& operator[](std::size_t index) const;
|
|
243
|
+
|
|
244
|
+
/// Bounds/existence-checked access; throws JsonError when missing.
|
|
245
|
+
Json& at(const std::string& key);
|
|
246
|
+
const Json& at(const std::string& key) const;
|
|
247
|
+
Json& at(std::size_t index);
|
|
248
|
+
const Json& at(std::size_t index) const;
|
|
249
|
+
|
|
250
|
+
bool contains(const std::string& key) const {
|
|
251
|
+
return is_object() && obj_->contains(key);
|
|
252
|
+
}
|
|
253
|
+
bool erase(const std::string& key);
|
|
254
|
+
void erase(std::size_t index);
|
|
255
|
+
|
|
256
|
+
Json& front();
|
|
257
|
+
const Json& front() const;
|
|
258
|
+
Json& back();
|
|
259
|
+
const Json& back() const;
|
|
260
|
+
|
|
261
|
+
void push_back(const Json& value);
|
|
262
|
+
void push_back(Json&& value);
|
|
263
|
+
template <typename... Args>
|
|
264
|
+
Json& emplace_back(Args&&... args) {
|
|
265
|
+
push_back(Json(std::forward<Args>(args)...));
|
|
266
|
+
return back();
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
void clear();
|
|
270
|
+
|
|
271
|
+
// ── Typed extraction ────────────────────────────────────────────────────
|
|
272
|
+
|
|
273
|
+
template <typename T>
|
|
274
|
+
T get() const {
|
|
275
|
+
if constexpr (std::is_same<T, bool>::value) {
|
|
276
|
+
return static_cast<T>(as_bool());
|
|
277
|
+
} else if constexpr (std::is_integral<T>::value) {
|
|
278
|
+
if constexpr (std::is_unsigned<T>::value) return static_cast<T>(as_uint64());
|
|
279
|
+
else return static_cast<T>(as_int64());
|
|
280
|
+
} else if constexpr (std::is_floating_point<T>::value) {
|
|
281
|
+
return static_cast<T>(as_double());
|
|
282
|
+
} else {
|
|
283
|
+
return get_impl(static_cast<T*>(nullptr));
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
/// Implicit conversion to arithmetic types and std::string, so call sites
|
|
288
|
+
/// like `int v = j["x"];` and `std::string s = j["y"];` read naturally.
|
|
289
|
+
template <typename T,
|
|
290
|
+
typename std::enable_if<(std::is_arithmetic<T>::value ||
|
|
291
|
+
std::is_same<T, std::string>::value) &&
|
|
292
|
+
!std::is_same<T, Json>::value,
|
|
293
|
+
int>::type = 0>
|
|
294
|
+
operator T() const { return get<T>(); }
|
|
295
|
+
|
|
296
|
+
/// value(key, default): typed object lookup with a fallback. Returns the
|
|
297
|
+
/// default when this is not an object or the key is absent.
|
|
298
|
+
template <typename T>
|
|
299
|
+
T value(const std::string& key, const T& default_value) const {
|
|
300
|
+
if (is_object()) {
|
|
301
|
+
if (const Json* v = obj_->find(key)) return v->get<T>();
|
|
302
|
+
}
|
|
303
|
+
return default_value;
|
|
304
|
+
}
|
|
305
|
+
/// const char* default resolves to a std::string result (nlohmann parity).
|
|
306
|
+
std::string value(const std::string& key, const char* default_value) const {
|
|
307
|
+
if (is_object()) {
|
|
308
|
+
if (const Json* v = obj_->find(key)) return v->get<std::string>();
|
|
309
|
+
}
|
|
310
|
+
return std::string(default_value);
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
// ── Iteration ───────────────────────────────────────────────────────────
|
|
314
|
+
//
|
|
315
|
+
// Range-for visits array elements, or object values in insertion order.
|
|
316
|
+
// The iterator exposes .key()/.value() (nlohmann-style). For key/value
|
|
317
|
+
// structured bindings, use items(): `for (auto e : j.items()) ...`.
|
|
318
|
+
|
|
319
|
+
template <bool Const>
|
|
320
|
+
class Iterator {
|
|
321
|
+
public:
|
|
322
|
+
using JsonRef = typename std::conditional<Const, const Json&, Json&>::type;
|
|
323
|
+
using JsonPtr = typename std::conditional<Const, const Json*, Json*>::type;
|
|
324
|
+
|
|
325
|
+
Iterator(JsonPtr owner, std::size_t idx) : owner_(owner), idx_(idx) {}
|
|
326
|
+
|
|
327
|
+
JsonRef operator*() const { return value(); }
|
|
328
|
+
JsonPtr operator->() const { return &value(); }
|
|
329
|
+
Iterator& operator++() { ++idx_; return *this; }
|
|
330
|
+
Iterator operator++(int) { Iterator tmp = *this; ++idx_; return tmp; }
|
|
331
|
+
bool operator==(const Iterator& o) const { return owner_ == o.owner_ && idx_ == o.idx_; }
|
|
332
|
+
bool operator!=(const Iterator& o) const { return !(*this == o); }
|
|
333
|
+
|
|
334
|
+
const std::string& key() const;
|
|
335
|
+
JsonRef value() const;
|
|
336
|
+
|
|
337
|
+
private:
|
|
338
|
+
JsonPtr owner_;
|
|
339
|
+
std::size_t idx_;
|
|
340
|
+
};
|
|
341
|
+
|
|
342
|
+
using iterator = Iterator<false>;
|
|
343
|
+
using const_iterator = Iterator<true>;
|
|
344
|
+
|
|
345
|
+
iterator begin() { return iterator(this, 0); }
|
|
346
|
+
iterator end() { return iterator(this, size()); }
|
|
347
|
+
const_iterator begin() const { return const_iterator(this, 0); }
|
|
348
|
+
const_iterator end() const { return const_iterator(this, size()); }
|
|
349
|
+
const_iterator cbegin() const { return const_iterator(this, 0); }
|
|
350
|
+
const_iterator cend() const { return const_iterator(this, size()); }
|
|
351
|
+
|
|
352
|
+
/// A key/value view supporting structured bindings:
|
|
353
|
+
/// for (auto&& [key, val] : obj.items()) { ... }
|
|
354
|
+
/// For arrays, key() is the decimal index.
|
|
355
|
+
template <bool Const>
|
|
356
|
+
class ItemsProxy {
|
|
357
|
+
public:
|
|
358
|
+
using JsonPtr = typename std::conditional<Const, const Json*, Json*>::type;
|
|
359
|
+
explicit ItemsProxy(JsonPtr owner) : owner_(owner) {}
|
|
360
|
+
Iterator<Const> begin() const { return Iterator<Const>(owner_, 0); }
|
|
361
|
+
Iterator<Const> end() const { return Iterator<Const>(owner_, owner_->size()); }
|
|
362
|
+
private:
|
|
363
|
+
JsonPtr owner_;
|
|
364
|
+
};
|
|
365
|
+
|
|
366
|
+
ItemsProxy<false> items() { return ItemsProxy<false>(this); }
|
|
367
|
+
ItemsProxy<true> items() const { return ItemsProxy<true>(this); }
|
|
368
|
+
|
|
369
|
+
// ── Equality ────────────────────────────────────────────────────────────
|
|
370
|
+
|
|
371
|
+
bool operator==(const Json& other) const;
|
|
372
|
+
bool operator!=(const Json& other) const { return !(*this == other); }
|
|
373
|
+
|
|
374
|
+
// ── Direct container access (advanced) ──────────────────────────────────
|
|
375
|
+
|
|
376
|
+
Array& as_array();
|
|
377
|
+
const Array& as_array() const;
|
|
378
|
+
Object& as_object();
|
|
379
|
+
const Object& as_object() const;
|
|
380
|
+
|
|
381
|
+
private:
|
|
382
|
+
// value storage: scalars live inline, heavy payloads behind a pointer.
|
|
383
|
+
Type type_ = Type::Null;
|
|
384
|
+
union {
|
|
385
|
+
bool bool_;
|
|
386
|
+
int64_t int_;
|
|
387
|
+
uint64_t uint_;
|
|
388
|
+
double float_;
|
|
389
|
+
std::string* str_;
|
|
390
|
+
Array* arr_;
|
|
391
|
+
Object* obj_;
|
|
392
|
+
};
|
|
393
|
+
|
|
394
|
+
void destroy() noexcept;
|
|
395
|
+
void copy_from(const Json& other);
|
|
396
|
+
void move_from(Json& other) noexcept;
|
|
397
|
+
|
|
398
|
+
bool as_bool() const;
|
|
399
|
+
int64_t as_int64() const;
|
|
400
|
+
uint64_t as_uint64() const;
|
|
401
|
+
double as_double() const;
|
|
402
|
+
const std::string& as_string() const;
|
|
403
|
+
|
|
404
|
+
// get_impl tag overloads — only std::string is supported as a class type.
|
|
405
|
+
std::string get_impl(std::string*) const { return as_string(); }
|
|
406
|
+
|
|
407
|
+
void dump_to(std::string& out, int indent, int depth) const;
|
|
408
|
+
|
|
409
|
+
static Json make_discarded() { Json j; j.type_ = Type::Discarded; return j; }
|
|
410
|
+
|
|
411
|
+
// The parser is implemented in json.cpp.
|
|
412
|
+
friend class JsonParser;
|
|
413
|
+
};
|
|
414
|
+
|
|
415
|
+
// Stream helpers: `is >> j` parses the whole stream; `os << j` writes dump().
|
|
416
|
+
std::istream& operator>>(std::istream& is, Json& j);
|
|
417
|
+
std::ostream& operator<<(std::ostream& os, const Json& j);
|
|
418
|
+
|
|
419
|
+
// ── Iterator member definitions (need the complete Json type) ───────────────
|
|
420
|
+
|
|
421
|
+
template <bool Const>
|
|
422
|
+
inline const std::string& Json::Iterator<Const>::key() const {
|
|
423
|
+
if (owner_->type_ == Type::Object) {
|
|
424
|
+
return (owner_->obj_->begin() + idx_)->first;
|
|
425
|
+
}
|
|
426
|
+
// Arrays: synthesise a decimal index string on demand (thread-local cache).
|
|
427
|
+
static thread_local std::string idx_str;
|
|
428
|
+
idx_str = std::to_string(idx_);
|
|
429
|
+
return idx_str;
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
template <bool Const>
|
|
433
|
+
inline typename Json::Iterator<Const>::JsonRef Json::Iterator<Const>::value() const {
|
|
434
|
+
if (owner_->type_ == Type::Object) {
|
|
435
|
+
return (owner_->obj_->begin() + idx_)->second;
|
|
436
|
+
}
|
|
437
|
+
if (owner_->type_ == Type::Array) {
|
|
438
|
+
return (*owner_->arr_)[idx_];
|
|
439
|
+
}
|
|
440
|
+
// Scalars iterate as a single element.
|
|
441
|
+
return *owner_;
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
} // namespace librats
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
#pragma once
|
|
2
2
|
|
|
3
|
+
#include "librats/util/rats_export.h"
|
|
3
4
|
#include <string>
|
|
4
5
|
#include <iostream>
|
|
5
6
|
#include <mutex>
|
|
@@ -8,9 +9,16 @@
|
|
|
8
9
|
#include <iomanip>
|
|
9
10
|
#include <cstdint>
|
|
10
11
|
#include <fstream>
|
|
11
|
-
#include
|
|
12
|
+
#include <atomic>
|
|
13
|
+
#include "librats/util/fs.h"
|
|
12
14
|
|
|
13
15
|
#ifdef _WIN32
|
|
16
|
+
// Include winsock2.h before windows.h: winsock2 defines _WINSOCKAPI_, which
|
|
17
|
+
// stops windows.h from pulling in the legacy winsock.h. Without this a TU that
|
|
18
|
+
// includes this header before a socket header (e.g. core/socket.h) gets
|
|
19
|
+
// winsock.h first and then a wall of winsock.h/winsock2.h redefinition errors
|
|
20
|
+
// under MSVC.
|
|
21
|
+
#include <winsock2.h>
|
|
14
22
|
#include <windows.h>
|
|
15
23
|
#include <io.h>
|
|
16
24
|
#define isatty _isatty
|
|
@@ -32,7 +40,7 @@ enum class LogLevel {
|
|
|
32
40
|
ERROR = 3
|
|
33
41
|
};
|
|
34
42
|
|
|
35
|
-
class Logger {
|
|
43
|
+
class RATS_API Logger {
|
|
36
44
|
public:
|
|
37
45
|
// Singleton pattern - implementation in logger.cpp to ensure single instance across TUs
|
|
38
46
|
static Logger& getInstance();
|
|
@@ -44,7 +52,19 @@ public:
|
|
|
44
52
|
// Set the minimum log level
|
|
45
53
|
void set_log_level(LogLevel level) {
|
|
46
54
|
std::lock_guard<std::mutex> lock(mutex_);
|
|
47
|
-
min_level_
|
|
55
|
+
min_level_.store(level, std::memory_order_relaxed);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// Current minimum level (lock-free).
|
|
59
|
+
LogLevel get_log_level() const {
|
|
60
|
+
return min_level_.load(std::memory_order_relaxed);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// True if a message at `level` would be emitted. Cheap and lock-free, so the LOG_*
|
|
64
|
+
// macros can gate message construction on it and skip formatting work — string
|
|
65
|
+
// building, id-to-hex conversions — that would otherwise be built and thrown away.
|
|
66
|
+
bool is_enabled(LogLevel level) const {
|
|
67
|
+
return level >= min_level_.load(std::memory_order_relaxed);
|
|
48
68
|
}
|
|
49
69
|
|
|
50
70
|
// Enable/disable colors
|
|
@@ -125,8 +145,8 @@ public:
|
|
|
125
145
|
// Main logging function
|
|
126
146
|
void log(LogLevel level, const std::string& module, const std::string& message) {
|
|
127
147
|
std::lock_guard<std::mutex> lock(mutex_);
|
|
128
|
-
|
|
129
|
-
if (level < min_level_) {
|
|
148
|
+
|
|
149
|
+
if (level < min_level_.load(std::memory_order_relaxed)) {
|
|
130
150
|
return;
|
|
131
151
|
}
|
|
132
152
|
|
|
@@ -406,7 +426,7 @@ private:
|
|
|
406
426
|
}
|
|
407
427
|
|
|
408
428
|
mutable std::mutex mutex_;
|
|
409
|
-
LogLevel min_level_;
|
|
429
|
+
std::atomic<LogLevel> min_level_;
|
|
410
430
|
bool colors_enabled_;
|
|
411
431
|
bool timestamps_enabled_;
|
|
412
432
|
bool is_terminal_;
|
|
@@ -429,33 +449,25 @@ private:
|
|
|
429
449
|
|
|
430
450
|
} // namespace librats
|
|
431
451
|
|
|
432
|
-
// Convenience macros for easy logging
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
#define LOG_INFO(module, message) \
|
|
452
|
+
// Convenience macros for easy logging.
|
|
453
|
+
//
|
|
454
|
+
// Each macro first checks is_enabled() — a lock-free level read — and only builds the
|
|
455
|
+
// message string when it would actually be emitted. This keeps a filtered-out log
|
|
456
|
+
// (e.g. a DEBUG line while running at INFO) down to a single atomic load, so hot-path
|
|
457
|
+
// logging costs nothing until the level is turned up. `message` is only evaluated when
|
|
458
|
+
// the level is enabled; keep it side-effect free.
|
|
459
|
+
#define RATS_LOG_AT(level_enum, module, message) \
|
|
441
460
|
do { \
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
461
|
+
if (librats::Logger::getInstance().is_enabled(level_enum)) { \
|
|
462
|
+
std::ostringstream oss; \
|
|
463
|
+
oss << message; \
|
|
464
|
+
librats::Logger::getInstance().log(level_enum, module, oss.str()); \
|
|
465
|
+
} \
|
|
445
466
|
} while(0)
|
|
446
467
|
|
|
447
|
-
#define
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
librats::Logger::getInstance().log(librats::LogLevel::WARN, module, oss.str()); \
|
|
452
|
-
} while(0)
|
|
453
|
-
|
|
454
|
-
#define LOG_ERROR(module, message) \
|
|
455
|
-
do { \
|
|
456
|
-
std::ostringstream oss; \
|
|
457
|
-
oss << message; \
|
|
458
|
-
librats::Logger::getInstance().log(librats::LogLevel::ERROR, module, oss.str()); \
|
|
459
|
-
} while(0)
|
|
468
|
+
#define LOG_DEBUG(module, message) RATS_LOG_AT(librats::LogLevel::DEBUG, module, message)
|
|
469
|
+
#define LOG_INFO(module, message) RATS_LOG_AT(librats::LogLevel::INFO, module, message)
|
|
470
|
+
#define LOG_WARN(module, message) RATS_LOG_AT(librats::LogLevel::WARN, module, message)
|
|
471
|
+
#define LOG_ERROR(module, message) RATS_LOG_AT(librats::LogLevel::ERROR, module, message)
|
|
460
472
|
|
|
461
473
|
|
|
@@ -5,10 +5,10 @@
|
|
|
5
5
|
|
|
6
6
|
// socket.h pulls in winsock2.h/ws2tcpip.h first on Windows (must precede the
|
|
7
7
|
// iphlpapi / windows headers below to avoid the classic winsock2/windows.h clash).
|
|
8
|
-
#include "socket.h"
|
|
9
|
-
#include "network_monitor.h"
|
|
10
|
-
#include "network_utils.h"
|
|
11
|
-
#include "logger.h"
|
|
8
|
+
#include "librats/core/socket.h"
|
|
9
|
+
#include "librats/util/network_monitor.h"
|
|
10
|
+
#include "librats/util/network_utils.h"
|
|
11
|
+
#include "librats/util/logger.h"
|
|
12
12
|
|
|
13
13
|
#include <algorithm>
|
|
14
14
|
|
|
@@ -110,6 +110,14 @@ void NetworkMonitor::stop() {
|
|
|
110
110
|
if (!running_.exchange(false)) {
|
|
111
111
|
return;
|
|
112
112
|
}
|
|
113
|
+
// Signal under mutex_ so this synchronizes with the worker's wait: without
|
|
114
|
+
// holding the lock, a notify_all() that lands between the worker's predicate
|
|
115
|
+
// check and its enrollment in the CV wait queue is lost, and the worker then
|
|
116
|
+
// sleeps the full poll_interval (30 s with an event backend) before join()
|
|
117
|
+
// returns. Taking the lock (as check_now() does) closes that window.
|
|
118
|
+
{
|
|
119
|
+
std::lock_guard<std::mutex> lock(mutex_);
|
|
120
|
+
}
|
|
113
121
|
cv_.notify_all(); // wake the worker out of its wait
|
|
114
122
|
backend_stop(); // stop OS notifications / join the reader thread
|
|
115
123
|
if (worker_.joinable()) {
|
|
@@ -29,6 +29,7 @@
|
|
|
29
29
|
* long; offload slow recovery work (STUN, port mapping) to another thread.
|
|
30
30
|
*/
|
|
31
31
|
|
|
32
|
+
#include "librats/util/rats_export.h"
|
|
32
33
|
#include <atomic>
|
|
33
34
|
#include <chrono>
|
|
34
35
|
#include <condition_variable>
|
|
@@ -41,7 +42,7 @@
|
|
|
41
42
|
|
|
42
43
|
namespace librats {
|
|
43
44
|
|
|
44
|
-
class NetworkMonitor {
|
|
45
|
+
class RATS_API NetworkMonitor {
|
|
45
46
|
public:
|
|
46
47
|
/// Invoked (debounced) whenever the set of local interface addresses changes.
|
|
47
48
|
/// @param current_addresses the new, full list of local interface addresses.
|